mirror of
https://github.com/rust-lang/rust.git
synced 2025-05-14 02:49:40 +00:00
Auto merge of #135789 - matthiaskrgr:rollup-4cvw8s4, r=matthiaskrgr
Rollup of 7 pull requests Successful merges: - #133695 (Reexport likely/unlikely in std::hint) - #135330 (Respect --sysroot for rustc -vV and -Cpasses=list) - #135333 (Partial progress on #132735: Replace extern "rust-intrinsic" with #[rustc_intrinsic] across the codebase) - #135741 (Recognise new IPv6 documentation range from IETF RFC 9637) - #135770 (Update contributing docs for submodule/subtree changes) - #135775 (Subtree update of `rust-analyzer`) - #135776 (Subtree sync for rustc_codegen_cranelift) r? `@ghost` `@rustbot` modify labels: rollup
This commit is contained in:
commit
f3d1d47fd8
@ -12,6 +12,15 @@ Documentation for contributing to the compiler or tooling is located in the [Gui
|
|||||||
Development][rustc-dev-guide], commonly known as the [rustc-dev-guide]. Documentation for the
|
Development][rustc-dev-guide], commonly known as the [rustc-dev-guide]. Documentation for the
|
||||||
standard library in the [Standard library developers Guide][std-dev-guide], commonly known as the [std-dev-guide].
|
standard library in the [Standard library developers Guide][std-dev-guide], commonly known as the [std-dev-guide].
|
||||||
|
|
||||||
|
## Making changes to subtrees and submodules
|
||||||
|
|
||||||
|
For submodules, changes need to be made against the repository corresponding the
|
||||||
|
submodule, and not the main `rust-lang/rust` repository.
|
||||||
|
|
||||||
|
For subtrees, prefer sending a PR against the subtree's repository if it does
|
||||||
|
not need to be made against the main `rust-lang/rust` repostory (e.g. a
|
||||||
|
rustc-dev-guide change that does not accompany a compiler change).
|
||||||
|
|
||||||
## About the [rustc-dev-guide]
|
## About the [rustc-dev-guide]
|
||||||
|
|
||||||
The [rustc-dev-guide] is meant to help document how rustc –the Rust compiler– works,
|
The [rustc-dev-guide] is meant to help document how rustc –the Rust compiler– works,
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
[toolchain]
|
[toolchain]
|
||||||
channel = "nightly-2025-01-10"
|
channel = "nightly-2025-01-20"
|
||||||
components = ["rust-src", "rustc-dev", "llvm-tools"]
|
components = ["rust-src", "rustc-dev", "llvm-tools"]
|
||||||
profile = "minimal"
|
profile = "minimal"
|
||||||
|
@ -176,12 +176,11 @@ diff --git a/src/tools/run-make-support/src/rustdoc.rs b/src/tools/run-make-supp
|
|||||||
index 9607ff02f96..b7d97caf9a2 100644
|
index 9607ff02f96..b7d97caf9a2 100644
|
||||||
--- a/src/tools/run-make-support/src/external_deps/rustdoc.rs
|
--- a/src/tools/run-make-support/src/external_deps/rustdoc.rs
|
||||||
+++ b/src/tools/run-make-support/src/external_deps/rustdoc.rs
|
+++ b/src/tools/run-make-support/src/external_deps/rustdoc.rs
|
||||||
@@ -34,8 +34,6 @@ pub fn bare() -> Self {
|
@@ -34,7 +34,6 @@ pub fn bare() -> Self {
|
||||||
#[track_caller]
|
#[track_caller]
|
||||||
pub fn new() -> Self {
|
pub fn new() -> Self {
|
||||||
let mut cmd = setup_common();
|
let mut cmd = setup_common();
|
||||||
- let target_rpath_dir = env_var_os("TARGET_RPATH_DIR");
|
- cmd.arg("-L").arg(env_var_os("TARGET_RPATH_DIR"));
|
||||||
- cmd.arg(format!("-L{}", target_rpath_dir.to_string_lossy()));
|
|
||||||
Self { cmd }
|
Self { cmd }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -333,9 +333,17 @@ fn make_module(sess: &Session, name: String) -> UnwindModule<ObjectModule> {
|
|||||||
|
|
||||||
let mut builder =
|
let mut builder =
|
||||||
ObjectBuilder::new(isa, name + ".o", cranelift_module::default_libcall_names()).unwrap();
|
ObjectBuilder::new(isa, name + ".o", cranelift_module::default_libcall_names()).unwrap();
|
||||||
|
|
||||||
|
// Disable function sections by default on MSVC as it causes significant slowdowns with link.exe.
|
||||||
|
// Maybe link.exe has exponential behavior when there are many sections with the same name? Also
|
||||||
|
// explicitly disable it on MinGW as rustc already disables it by default on MinGW and as such
|
||||||
|
// isn't tested. If rustc enables it in the future on MinGW, we can re-enable it too once it has
|
||||||
|
// been on MinGW.
|
||||||
|
let default_function_sections = sess.target.function_sections && !sess.target.is_like_windows;
|
||||||
builder.per_function_section(
|
builder.per_function_section(
|
||||||
sess.opts.unstable_opts.function_sections.unwrap_or(sess.target.function_sections),
|
sess.opts.unstable_opts.function_sections.unwrap_or(default_function_sections),
|
||||||
);
|
);
|
||||||
|
|
||||||
UnwindModule::new(ObjectModule::new(builder), true)
|
UnwindModule::new(ObjectModule::new(builder), true)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
//! Codegen of intrinsics. This includes `extern "rust-intrinsic"`,
|
//! Codegen of intrinsics. This includes `extern "rust-intrinsic"`,
|
||||||
|
//! functions marked with the `#[rustc_intrinsic]` attribute
|
||||||
//! and LLVM intrinsics that have symbol names starting with `llvm.`.
|
//! and LLVM intrinsics that have symbol names starting with `llvm.`.
|
||||||
|
|
||||||
macro_rules! intrinsic_args {
|
macro_rules! intrinsic_args {
|
||||||
|
@ -53,7 +53,7 @@ use rustc_middle::ty::TyCtxt;
|
|||||||
use rustc_parse::{new_parser_from_file, new_parser_from_source_str, unwrap_or_emit_fatal};
|
use rustc_parse::{new_parser_from_file, new_parser_from_source_str, unwrap_or_emit_fatal};
|
||||||
use rustc_session::config::{
|
use rustc_session::config::{
|
||||||
CG_OPTIONS, ErrorOutputType, Input, OptionDesc, OutFileName, OutputType, UnstableOptions,
|
CG_OPTIONS, ErrorOutputType, Input, OptionDesc, OutFileName, OutputType, UnstableOptions,
|
||||||
Z_OPTIONS, nightly_options,
|
Z_OPTIONS, nightly_options, parse_target_triple,
|
||||||
};
|
};
|
||||||
use rustc_session::getopts::{self, Matches};
|
use rustc_session::getopts::{self, Matches};
|
||||||
use rustc_session::lint::{Lint, LintId};
|
use rustc_session::lint::{Lint, LintId};
|
||||||
@ -916,13 +916,7 @@ pub fn version_at_macro_invocation(
|
|||||||
safe_println!("host: {}", config::host_tuple());
|
safe_println!("host: {}", config::host_tuple());
|
||||||
safe_println!("release: {release}");
|
safe_println!("release: {release}");
|
||||||
|
|
||||||
let debug_flags = matches.opt_strs("Z");
|
get_backend_from_raw_matches(early_dcx, matches).print_version();
|
||||||
let backend_name = debug_flags.iter().find_map(|x| x.strip_prefix("codegen-backend="));
|
|
||||||
let opts = config::Options::default();
|
|
||||||
let sysroot = filesearch::materialize_sysroot(opts.maybe_sysroot.clone());
|
|
||||||
let target = config::build_target_config(early_dcx, &opts, &sysroot);
|
|
||||||
|
|
||||||
get_codegen_backend(early_dcx, &sysroot, backend_name, &target).print_version();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1125,19 +1119,32 @@ pub fn describe_flag_categories(early_dcx: &EarlyDiagCtxt, matches: &Matches) ->
|
|||||||
}
|
}
|
||||||
|
|
||||||
if cg_flags.iter().any(|x| *x == "passes=list") {
|
if cg_flags.iter().any(|x| *x == "passes=list") {
|
||||||
let backend_name = debug_flags.iter().find_map(|x| x.strip_prefix("codegen-backend="));
|
get_backend_from_raw_matches(early_dcx, matches).print_passes();
|
||||||
|
|
||||||
let opts = config::Options::default();
|
|
||||||
let sysroot = filesearch::materialize_sysroot(opts.maybe_sysroot.clone());
|
|
||||||
let target = config::build_target_config(early_dcx, &opts, &sysroot);
|
|
||||||
|
|
||||||
get_codegen_backend(early_dcx, &sysroot, backend_name, &target).print_passes();
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
false
|
false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Get the codegen backend based on the raw [`Matches`].
|
||||||
|
///
|
||||||
|
/// `rustc -vV` and `rustc -Cpasses=list` need to get the codegen backend before we have parsed all
|
||||||
|
/// arguments and created a [`Session`]. This function reads `-Zcodegen-backend`, `--target` and
|
||||||
|
/// `--sysroot` without validating any other arguments and loads the codegen backend based on these
|
||||||
|
/// arguments.
|
||||||
|
fn get_backend_from_raw_matches(
|
||||||
|
early_dcx: &EarlyDiagCtxt,
|
||||||
|
matches: &Matches,
|
||||||
|
) -> Box<dyn CodegenBackend> {
|
||||||
|
let debug_flags = matches.opt_strs("Z");
|
||||||
|
let backend_name = debug_flags.iter().find_map(|x| x.strip_prefix("codegen-backend="));
|
||||||
|
let target = parse_target_triple(early_dcx, matches);
|
||||||
|
let sysroot = filesearch::materialize_sysroot(matches.opt_str("sysroot").map(PathBuf::from));
|
||||||
|
let target = config::build_target_config(early_dcx, &target, &sysroot);
|
||||||
|
|
||||||
|
get_codegen_backend(early_dcx, &sysroot, backend_name, &target)
|
||||||
|
}
|
||||||
|
|
||||||
fn describe_debug_flags() {
|
fn describe_debug_flags() {
|
||||||
safe_println!("\nAvailable options:\n");
|
safe_println!("\nAvailable options:\n");
|
||||||
print_flag_list("-Z", config::Z_OPTIONS);
|
print_flag_list("-Z", config::Z_OPTIONS);
|
||||||
|
@ -383,7 +383,7 @@ pub fn run_compiler<R: Send>(config: Config, f: impl FnOnce(&Compiler) -> R + Se
|
|||||||
crate::callbacks::setup_callbacks();
|
crate::callbacks::setup_callbacks();
|
||||||
|
|
||||||
let sysroot = filesearch::materialize_sysroot(config.opts.maybe_sysroot.clone());
|
let sysroot = filesearch::materialize_sysroot(config.opts.maybe_sysroot.clone());
|
||||||
let target = config::build_target_config(&early_dcx, &config.opts, &sysroot);
|
let target = config::build_target_config(&early_dcx, &config.opts.target_triple, &sysroot);
|
||||||
let file_loader = config.file_loader.unwrap_or_else(|| Box::new(RealFileLoader));
|
let file_loader = config.file_loader.unwrap_or_else(|| Box::new(RealFileLoader));
|
||||||
let path_mapping = config.opts.file_path_mapping();
|
let path_mapping = config.opts.file_path_mapping();
|
||||||
let hash_kind = config.opts.unstable_opts.src_hash_algorithm(&target);
|
let hash_kind = config.opts.unstable_opts.src_hash_algorithm(&target);
|
||||||
|
@ -42,7 +42,8 @@ where
|
|||||||
let matches = optgroups().parse(args).unwrap();
|
let matches = optgroups().parse(args).unwrap();
|
||||||
let sessopts = build_session_options(&mut early_dcx, &matches);
|
let sessopts = build_session_options(&mut early_dcx, &matches);
|
||||||
let sysroot = filesearch::materialize_sysroot(sessopts.maybe_sysroot.clone());
|
let sysroot = filesearch::materialize_sysroot(sessopts.maybe_sysroot.clone());
|
||||||
let target = rustc_session::config::build_target_config(&early_dcx, &sessopts, &sysroot);
|
let target =
|
||||||
|
rustc_session::config::build_target_config(&early_dcx, &sessopts.target_triple, &sysroot);
|
||||||
let hash_kind = sessopts.unstable_opts.src_hash_algorithm(&target);
|
let hash_kind = sessopts.unstable_opts.src_hash_algorithm(&target);
|
||||||
let checksum_hash_kind = sessopts.unstable_opts.checksum_hash_algorithm();
|
let checksum_hash_kind = sessopts.unstable_opts.checksum_hash_algorithm();
|
||||||
let sm_inputs = Some(SourceMapInputs {
|
let sm_inputs = Some(SourceMapInputs {
|
||||||
|
@ -1346,8 +1346,12 @@ pub fn build_configuration(sess: &Session, mut user_cfg: Cfg) -> Cfg {
|
|||||||
user_cfg
|
user_cfg
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn build_target_config(early_dcx: &EarlyDiagCtxt, opts: &Options, sysroot: &Path) -> Target {
|
pub fn build_target_config(
|
||||||
match Target::search(&opts.target_triple, sysroot) {
|
early_dcx: &EarlyDiagCtxt,
|
||||||
|
target: &TargetTuple,
|
||||||
|
sysroot: &Path,
|
||||||
|
) -> Target {
|
||||||
|
match Target::search(target, sysroot) {
|
||||||
Ok((target, warnings)) => {
|
Ok((target, warnings)) => {
|
||||||
for warning in warnings.warning_messages() {
|
for warning in warnings.warning_messages() {
|
||||||
early_dcx.early_warn(warning)
|
early_dcx.early_warn(warning)
|
||||||
|
@ -597,3 +597,138 @@ pub const fn black_box<T>(dummy: T) -> T {
|
|||||||
pub const fn must_use<T>(value: T) -> T {
|
pub const fn must_use<T>(value: T) -> T {
|
||||||
value
|
value
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Hints to the compiler that a branch condition is likely to be true.
|
||||||
|
/// Returns the value passed to it.
|
||||||
|
///
|
||||||
|
/// It can be used with `if` or boolean `match` expressions.
|
||||||
|
///
|
||||||
|
/// When used outside of a branch condition, it may still influence a nearby branch, but
|
||||||
|
/// probably will not have any effect.
|
||||||
|
///
|
||||||
|
/// It can also be applied to parts of expressions, such as `likely(a) && unlikely(b)`, or to
|
||||||
|
/// compound expressions, such as `likely(a && b)`. When applied to compound expressions, it has
|
||||||
|
/// the following effect:
|
||||||
|
/// ```text
|
||||||
|
/// likely(!a) => !unlikely(a)
|
||||||
|
/// likely(a && b) => likely(a) && likely(b)
|
||||||
|
/// likely(a || b) => a || likely(b)
|
||||||
|
/// ```
|
||||||
|
///
|
||||||
|
/// See also the function [`cold_path()`] which may be more appropriate for idiomatic Rust code.
|
||||||
|
///
|
||||||
|
/// # Examples
|
||||||
|
///
|
||||||
|
/// ```
|
||||||
|
/// #![feature(likely_unlikely)]
|
||||||
|
/// use core::hint::likely;
|
||||||
|
///
|
||||||
|
/// fn foo(x: i32) {
|
||||||
|
/// if likely(x > 0) {
|
||||||
|
/// println!("this branch is likely to be taken");
|
||||||
|
/// } else {
|
||||||
|
/// println!("this branch is unlikely to be taken");
|
||||||
|
/// }
|
||||||
|
///
|
||||||
|
/// match likely(x > 0) {
|
||||||
|
/// true => println!("this branch is likely to be taken"),
|
||||||
|
/// false => println!("this branch is unlikely to be taken"),
|
||||||
|
/// }
|
||||||
|
///
|
||||||
|
/// // Use outside of a branch condition may still influence a nearby branch
|
||||||
|
/// let cond = likely(x != 0);
|
||||||
|
/// if cond {
|
||||||
|
/// println!("this branch is likely to be taken");
|
||||||
|
/// }
|
||||||
|
/// }
|
||||||
|
/// ```
|
||||||
|
///
|
||||||
|
///
|
||||||
|
#[unstable(feature = "likely_unlikely", issue = "26179")]
|
||||||
|
#[inline(always)]
|
||||||
|
pub const fn likely(b: bool) -> bool {
|
||||||
|
crate::intrinsics::likely(b)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Hints to the compiler that a branch condition is unlikely to be true.
|
||||||
|
/// Returns the value passed to it.
|
||||||
|
///
|
||||||
|
/// It can be used with `if` or boolean `match` expressions.
|
||||||
|
///
|
||||||
|
/// When used outside of a branch condition, it may still influence a nearby branch, but
|
||||||
|
/// probably will not have any effect.
|
||||||
|
///
|
||||||
|
/// It can also be applied to parts of expressions, such as `likely(a) && unlikely(b)`, or to
|
||||||
|
/// compound expressions, such as `unlikely(a && b)`. When applied to compound expressions, it has
|
||||||
|
/// the following effect:
|
||||||
|
/// ```text
|
||||||
|
/// unlikely(!a) => !likely(a)
|
||||||
|
/// unlikely(a && b) => a && unlikely(b)
|
||||||
|
/// unlikely(a || b) => unlikely(a) || unlikely(b)
|
||||||
|
/// ```
|
||||||
|
///
|
||||||
|
/// See also the function [`cold_path()`] which may be more appropriate for idiomatic Rust code.
|
||||||
|
///
|
||||||
|
/// # Examples
|
||||||
|
///
|
||||||
|
/// ```
|
||||||
|
/// #![feature(likely_unlikely)]
|
||||||
|
/// use core::hint::unlikely;
|
||||||
|
///
|
||||||
|
/// fn foo(x: i32) {
|
||||||
|
/// if unlikely(x > 0) {
|
||||||
|
/// println!("this branch is unlikely to be taken");
|
||||||
|
/// } else {
|
||||||
|
/// println!("this branch is likely to be taken");
|
||||||
|
/// }
|
||||||
|
///
|
||||||
|
/// match unlikely(x > 0) {
|
||||||
|
/// true => println!("this branch is unlikely to be taken"),
|
||||||
|
/// false => println!("this branch is likely to be taken"),
|
||||||
|
/// }
|
||||||
|
///
|
||||||
|
/// // Use outside of a branch condition may still influence a nearby branch
|
||||||
|
/// let cond = unlikely(x != 0);
|
||||||
|
/// if cond {
|
||||||
|
/// println!("this branch is likely to be taken");
|
||||||
|
/// }
|
||||||
|
/// }
|
||||||
|
/// ```
|
||||||
|
#[unstable(feature = "likely_unlikely", issue = "26179")]
|
||||||
|
#[inline(always)]
|
||||||
|
pub const fn unlikely(b: bool) -> bool {
|
||||||
|
crate::intrinsics::unlikely(b)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Hints to the compiler that given path is cold, i.e., unlikely to be taken. The compiler may
|
||||||
|
/// choose to optimize paths that are not cold at the expense of paths that are cold.
|
||||||
|
///
|
||||||
|
/// # Examples
|
||||||
|
///
|
||||||
|
/// ```
|
||||||
|
/// #![feature(cold_path)]
|
||||||
|
/// use core::hint::cold_path;
|
||||||
|
///
|
||||||
|
/// fn foo(x: &[i32]) {
|
||||||
|
/// if let Some(first) = x.get(0) {
|
||||||
|
/// // this is the fast path
|
||||||
|
/// } else {
|
||||||
|
/// // this path is unlikely
|
||||||
|
/// cold_path();
|
||||||
|
/// }
|
||||||
|
/// }
|
||||||
|
///
|
||||||
|
/// fn bar(x: i32) -> i32 {
|
||||||
|
/// match x {
|
||||||
|
/// 1 => 10,
|
||||||
|
/// 2 => 100,
|
||||||
|
/// 3 => { cold_path(); 1000 }, // this branch is unlikely
|
||||||
|
/// _ => { cold_path(); 10000 }, // this is also unlikely
|
||||||
|
/// }
|
||||||
|
/// }
|
||||||
|
/// ```
|
||||||
|
#[unstable(feature = "cold_path", issue = "26179")]
|
||||||
|
#[inline(always)]
|
||||||
|
pub const fn cold_path() {
|
||||||
|
crate::intrinsics::cold_path()
|
||||||
|
}
|
||||||
|
@ -1539,8 +1539,9 @@ impl Ipv6Addr {
|
|||||||
/// // Addresses reserved for benchmarking (`2001:2::/48`)
|
/// // Addresses reserved for benchmarking (`2001:2::/48`)
|
||||||
/// assert_eq!(Ipv6Addr::new(0x2001, 2, 0, 0, 0, 0, 0, 1,).is_global(), false);
|
/// assert_eq!(Ipv6Addr::new(0x2001, 2, 0, 0, 0, 0, 0, 1,).is_global(), false);
|
||||||
///
|
///
|
||||||
/// // Addresses reserved for documentation (`2001:db8::/32`)
|
/// // Addresses reserved for documentation (`2001:db8::/32` and `3fff::/20`)
|
||||||
/// assert_eq!(Ipv6Addr::new(0x2001, 0xdb8, 0, 0, 0, 0, 0, 1).is_global(), false);
|
/// assert_eq!(Ipv6Addr::new(0x2001, 0xdb8, 0, 0, 0, 0, 0, 1).is_global(), false);
|
||||||
|
/// assert_eq!(Ipv6Addr::new(0x3fff, 0, 0, 0, 0, 0, 0, 0).is_global(), false);
|
||||||
///
|
///
|
||||||
/// // Unique local addresses (`fc00::/7`)
|
/// // Unique local addresses (`fc00::/7`)
|
||||||
/// assert_eq!(Ipv6Addr::new(0xfc02, 0, 0, 0, 0, 0, 0, 1).is_global(), false);
|
/// assert_eq!(Ipv6Addr::new(0xfc02, 0, 0, 0, 0, 0, 0, 1).is_global(), false);
|
||||||
@ -1686,11 +1687,12 @@ impl Ipv6Addr {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Returns [`true`] if this is an address reserved for documentation
|
/// Returns [`true`] if this is an address reserved for documentation
|
||||||
/// (`2001:db8::/32`).
|
/// (`2001:db8::/32` and `3fff::/20`).
|
||||||
///
|
///
|
||||||
/// This property is defined in [IETF RFC 3849].
|
/// This property is defined by [IETF RFC 3849] and [IETF RFC 9637].
|
||||||
///
|
///
|
||||||
/// [IETF RFC 3849]: https://tools.ietf.org/html/rfc3849
|
/// [IETF RFC 3849]: https://tools.ietf.org/html/rfc3849
|
||||||
|
/// [IETF RFC 9637]: https://tools.ietf.org/html/rfc9637
|
||||||
///
|
///
|
||||||
/// # Examples
|
/// # Examples
|
||||||
///
|
///
|
||||||
@ -1701,12 +1703,13 @@ impl Ipv6Addr {
|
|||||||
///
|
///
|
||||||
/// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0xc00a, 0x2ff).is_documentation(), false);
|
/// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0xc00a, 0x2ff).is_documentation(), false);
|
||||||
/// assert_eq!(Ipv6Addr::new(0x2001, 0xdb8, 0, 0, 0, 0, 0, 0).is_documentation(), true);
|
/// assert_eq!(Ipv6Addr::new(0x2001, 0xdb8, 0, 0, 0, 0, 0, 0).is_documentation(), true);
|
||||||
|
/// assert_eq!(Ipv6Addr::new(0x3fff, 0, 0, 0, 0, 0, 0, 0).is_documentation(), true);
|
||||||
/// ```
|
/// ```
|
||||||
#[unstable(feature = "ip", issue = "27709")]
|
#[unstable(feature = "ip", issue = "27709")]
|
||||||
#[must_use]
|
#[must_use]
|
||||||
#[inline]
|
#[inline]
|
||||||
pub const fn is_documentation(&self) -> bool {
|
pub const fn is_documentation(&self) -> bool {
|
||||||
(self.segments()[0] == 0x2001) && (self.segments()[1] == 0xdb8)
|
matches!(self.segments(), [0x2001, 0xdb8, ..] | [0x3fff, 0..=0x0fff, ..])
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns [`true`] if this is an address reserved for benchmarking (`2001:2::/48`).
|
/// Returns [`true`] if this is an address reserved for benchmarking (`2001:2::/48`).
|
||||||
|
@ -332,6 +332,7 @@ fn ip_properties() {
|
|||||||
check!("ff08::", global | multicast);
|
check!("ff08::", global | multicast);
|
||||||
check!("ff0e::", global | multicast);
|
check!("ff0e::", global | multicast);
|
||||||
check!("2001:db8:85a3::8a2e:370:7334", doc);
|
check!("2001:db8:85a3::8a2e:370:7334", doc);
|
||||||
|
check!("3fff:fff:ffff:ffff:ffff:ffff:ffff:ffff", doc);
|
||||||
check!("2001:2::ac32:23ff:21", benchmarking);
|
check!("2001:2::ac32:23ff:21", benchmarking);
|
||||||
check!("102:304:506:708:90a:b0c:d0e:f10", global);
|
check!("102:304:506:708:90a:b0c:d0e:f10", global);
|
||||||
}
|
}
|
||||||
@ -790,6 +791,15 @@ fn ipv6_properties() {
|
|||||||
documentation
|
documentation
|
||||||
);
|
);
|
||||||
|
|
||||||
|
check!(
|
||||||
|
"3fff:fff:ffff:ffff:ffff:ffff:ffff:ffff",
|
||||||
|
&[
|
||||||
|
0x3f, 0xff, 0x0f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||||
|
0xff, 0xff
|
||||||
|
],
|
||||||
|
documentation
|
||||||
|
);
|
||||||
|
|
||||||
check!(
|
check!(
|
||||||
"2001:2::ac32:23ff:21",
|
"2001:2::ac32:23ff:21",
|
||||||
&[0x20, 1, 0, 2, 0, 0, 0, 0, 0, 0, 0xac, 0x32, 0x23, 0xff, 0, 0x21],
|
&[0x20, 1, 0, 2, 0, 0, 0, 0, 0, 0, 0xac, 0x32, 0x23, 0xff, 0, 0x21],
|
||||||
|
@ -1,9 +1,8 @@
|
|||||||
#![feature(intrinsics)]
|
#![feature(intrinsics)]
|
||||||
|
|
||||||
// Directly call intrinsic to avoid debug assertions in libstd
|
// Directly call intrinsic to avoid debug assertions in libstd
|
||||||
extern "rust-intrinsic" {
|
#[rustc_intrinsic]
|
||||||
fn copy_nonoverlapping<T>(src: *const T, dst: *mut T, count: usize);
|
unsafe fn copy_nonoverlapping<T>(_src: *const T, _dst: *mut T, _count: usize);
|
||||||
}
|
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
let mut data = [0u8; 16];
|
let mut data = [0u8; 16];
|
||||||
|
@ -1,9 +1,8 @@
|
|||||||
#![feature(intrinsics)]
|
#![feature(intrinsics)]
|
||||||
|
|
||||||
// Directly call intrinsic to avoid debug assertions in libstd
|
// Directly call intrinsic to avoid debug assertions in libstd
|
||||||
extern "rust-intrinsic" {
|
#[rustc_intrinsic]
|
||||||
fn copy_nonoverlapping<T>(src: *const T, dst: *mut T, count: usize);
|
unsafe fn copy_nonoverlapping<T>(_src: *const T, _dst: *mut T, _count: usize);
|
||||||
}
|
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
let mut data = [0u16; 8];
|
let mut data = [0u16; 8];
|
||||||
|
@ -1,9 +1,8 @@
|
|||||||
#![feature(intrinsics)]
|
#![feature(intrinsics)]
|
||||||
|
|
||||||
mod rusti {
|
mod rusti {
|
||||||
extern "rust-intrinsic" {
|
#[rustc_intrinsic]
|
||||||
pub fn ctlz_nonzero<T>(x: T) -> u32;
|
pub unsafe fn ctlz_nonzero<T>(_x: T) -> u32;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn main() {
|
pub fn main() {
|
||||||
|
@ -1,9 +1,9 @@
|
|||||||
|
|
||||||
#![feature(intrinsics)]
|
#![feature(intrinsics)]
|
||||||
|
|
||||||
mod rusti {
|
mod rusti {
|
||||||
extern "rust-intrinsic" {
|
#[rustc_intrinsic]
|
||||||
pub fn cttz_nonzero<T>(x: T) -> u32;
|
pub unsafe fn cttz_nonzero<T>(_x: T) -> u32;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn main() {
|
pub fn main() {
|
||||||
|
@ -1,9 +1,8 @@
|
|||||||
#![feature(intrinsics)]
|
#![feature(intrinsics)]
|
||||||
|
|
||||||
// Directly call intrinsic to avoid debug assertions in libstd
|
// Directly call intrinsic to avoid debug assertions in libstd
|
||||||
extern "rust-intrinsic" {
|
#[rustc_intrinsic]
|
||||||
fn float_to_int_unchecked<Float: Copy, Int: Copy>(value: Float) -> Int;
|
unsafe fn float_to_int_unchecked<Float: Copy, Int: Copy>(_value: Float) -> Int;
|
||||||
}
|
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
unsafe {
|
unsafe {
|
||||||
|
@ -1,9 +1,8 @@
|
|||||||
#![feature(intrinsics)]
|
#![feature(intrinsics)]
|
||||||
|
|
||||||
// Directly call intrinsic to avoid debug assertions in libstd
|
// Directly call intrinsic to avoid debug assertions in libstd
|
||||||
extern "rust-intrinsic" {
|
#[rustc_intrinsic]
|
||||||
fn float_to_int_unchecked<Float: Copy, Int: Copy>(value: Float) -> Int;
|
unsafe fn float_to_int_unchecked<Float: Copy, Int: Copy>(_value: Float) -> Int;
|
||||||
}
|
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
unsafe {
|
unsafe {
|
||||||
|
@ -1,9 +1,8 @@
|
|||||||
#![feature(intrinsics)]
|
#![feature(intrinsics)]
|
||||||
|
|
||||||
// Directly call intrinsic to avoid debug assertions in libstd
|
// Directly call intrinsic to avoid debug assertions in libstd
|
||||||
extern "rust-intrinsic" {
|
#[rustc_intrinsic]
|
||||||
fn float_to_int_unchecked<Float: Copy, Int: Copy>(value: Float) -> Int;
|
unsafe fn float_to_int_unchecked<Float: Copy, Int: Copy>(_value: Float) -> Int;
|
||||||
}
|
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
unsafe {
|
unsafe {
|
||||||
|
@ -1,9 +1,9 @@
|
|||||||
#![feature(intrinsics)]
|
#![feature(intrinsics)]
|
||||||
|
|
||||||
// Directly call intrinsic to avoid debug assertions in libstd
|
// Directly call intrinsic to avoid debug assertions in libstd
|
||||||
extern "rust-intrinsic" {
|
#[rustc_intrinsic]
|
||||||
fn float_to_int_unchecked<Float: Copy, Int: Copy>(value: Float) -> Int;
|
unsafe fn float_to_int_unchecked<Float: Copy, Int: Copy>(_value: Float) -> Int;
|
||||||
}
|
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
unsafe {
|
unsafe {
|
||||||
|
@ -1,9 +1,8 @@
|
|||||||
#![feature(intrinsics)]
|
#![feature(intrinsics)]
|
||||||
|
|
||||||
// Directly call intrinsic to avoid debug assertions in libstd
|
// Directly call intrinsic to avoid debug assertions in libstd
|
||||||
extern "rust-intrinsic" {
|
#[rustc_intrinsic]
|
||||||
fn float_to_int_unchecked<Float: Copy, Int: Copy>(value: Float) -> Int;
|
unsafe fn float_to_int_unchecked<Float: Copy, Int: Copy>(_value: Float) -> Int;
|
||||||
}
|
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
unsafe {
|
unsafe {
|
||||||
|
@ -1,9 +1,8 @@
|
|||||||
#![feature(intrinsics)]
|
#![feature(intrinsics)]
|
||||||
|
|
||||||
// Directly call intrinsic to avoid debug assertions in libstd
|
// Directly call intrinsic to avoid debug assertions in libstd
|
||||||
extern "rust-intrinsic" {
|
#[rustc_intrinsic]
|
||||||
fn float_to_int_unchecked<Float: Copy, Int: Copy>(value: Float) -> Int;
|
unsafe fn float_to_int_unchecked<Float: Copy, Int: Copy>(_value: Float) -> Int;
|
||||||
}
|
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
unsafe {
|
unsafe {
|
||||||
|
@ -1,9 +1,8 @@
|
|||||||
#![feature(intrinsics)]
|
#![feature(intrinsics)]
|
||||||
|
|
||||||
// Directly call intrinsic to avoid debug assertions in libstd
|
// Directly call intrinsic to avoid debug assertions in libstd
|
||||||
extern "rust-intrinsic" {
|
#[rustc_intrinsic]
|
||||||
fn float_to_int_unchecked<Float: Copy, Int: Copy>(value: Float) -> Int;
|
unsafe fn float_to_int_unchecked<Float: Copy, Int: Copy>(_value: Float) -> Int;
|
||||||
}
|
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
unsafe {
|
unsafe {
|
||||||
|
@ -1,9 +1,8 @@
|
|||||||
#![feature(intrinsics)]
|
#![feature(intrinsics)]
|
||||||
|
|
||||||
// Directly call intrinsic to avoid debug assertions in libstd
|
// Directly call intrinsic to avoid debug assertions in libstd
|
||||||
extern "rust-intrinsic" {
|
#[rustc_intrinsic]
|
||||||
fn float_to_int_unchecked<Float: Copy, Int: Copy>(value: Float) -> Int;
|
unsafe fn float_to_int_unchecked<Float: Copy, Int: Copy>(_value: Float) -> Int;
|
||||||
}
|
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
unsafe {
|
unsafe {
|
||||||
|
@ -1,9 +1,8 @@
|
|||||||
#![feature(intrinsics)]
|
#![feature(intrinsics)]
|
||||||
|
|
||||||
// Directly call intrinsic to avoid debug assertions in libstd
|
// Directly call intrinsic to avoid debug assertions in libstd
|
||||||
extern "rust-intrinsic" {
|
#[rustc_intrinsic]
|
||||||
fn float_to_int_unchecked<Float: Copy, Int: Copy>(value: Float) -> Int;
|
unsafe fn float_to_int_unchecked<Float: Copy, Int: Copy>(_value: Float) -> Int;
|
||||||
}
|
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
unsafe {
|
unsafe {
|
||||||
|
@ -1,9 +1,9 @@
|
|||||||
#![feature(intrinsics)]
|
#![feature(intrinsics)]
|
||||||
|
|
||||||
// Directly call intrinsic to avoid debug assertions in libstd
|
// Directly call intrinsic to avoid debug assertions in libstd
|
||||||
extern "rust-intrinsic" {
|
#[rustc_intrinsic]
|
||||||
fn float_to_int_unchecked<Float: Copy, Int: Copy>(value: Float) -> Int;
|
unsafe fn float_to_int_unchecked<Float: Copy, Int: Copy>(_value: Float) -> Int;
|
||||||
}
|
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
unsafe {
|
unsafe {
|
||||||
|
@ -1,9 +1,8 @@
|
|||||||
#![feature(intrinsics)]
|
#![feature(intrinsics)]
|
||||||
|
|
||||||
// Directly call intrinsic to avoid debug assertions in libstd
|
// Directly call intrinsic to avoid debug assertions in libstd
|
||||||
extern "rust-intrinsic" {
|
#[rustc_intrinsic]
|
||||||
fn float_to_int_unchecked<Float: Copy, Int: Copy>(value: Float) -> Int;
|
unsafe fn float_to_int_unchecked<Float: Copy, Int: Copy>(_value: Float) -> Int;
|
||||||
}
|
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
unsafe {
|
unsafe {
|
||||||
|
@ -1,9 +1,8 @@
|
|||||||
#![feature(intrinsics)]
|
#![feature(intrinsics)]
|
||||||
|
|
||||||
// Directly call intrinsic to avoid debug assertions in libstd
|
// Directly call intrinsic to avoid debug assertions in libstd
|
||||||
extern "rust-intrinsic" {
|
#[rustc_intrinsic]
|
||||||
fn float_to_int_unchecked<Float: Copy, Int: Copy>(value: Float) -> Int;
|
unsafe fn float_to_int_unchecked<Float: Copy, Int: Copy>(_value: Float) -> Int;
|
||||||
}
|
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
unsafe {
|
unsafe {
|
||||||
|
@ -1,9 +1,8 @@
|
|||||||
#![feature(intrinsics)]
|
#![feature(intrinsics)]
|
||||||
|
|
||||||
// Directly call intrinsic to avoid debug assertions in libstd
|
// Directly call intrinsic to avoid debug assertions in libstd
|
||||||
extern "rust-intrinsic" {
|
#[rustc_intrinsic]
|
||||||
fn float_to_int_unchecked<Float: Copy, Int: Copy>(value: Float) -> Int;
|
unsafe fn float_to_int_unchecked<Float: Copy, Int: Copy>(_value: Float) -> Int;
|
||||||
}
|
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
unsafe {
|
unsafe {
|
||||||
|
@ -1,9 +1,8 @@
|
|||||||
#![feature(intrinsics)]
|
#![feature(intrinsics)]
|
||||||
|
|
||||||
// Directly call intrinsic to avoid debug assertions in libstd
|
// Directly call intrinsic to avoid debug assertions in libstd
|
||||||
extern "rust-intrinsic" {
|
#[rustc_intrinsic]
|
||||||
fn float_to_int_unchecked<Float: Copy, Int: Copy>(value: Float) -> Int;
|
unsafe fn float_to_int_unchecked<Float: Copy, Int: Copy>(_value: Float) -> Int;
|
||||||
}
|
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
unsafe {
|
unsafe {
|
||||||
|
@ -1,9 +1,8 @@
|
|||||||
#![feature(intrinsics)]
|
#![feature(intrinsics)]
|
||||||
|
|
||||||
// Directly call intrinsic to avoid debug assertions in libstd
|
// Directly call intrinsic to avoid debug assertions in libstd
|
||||||
extern "rust-intrinsic" {
|
#[rustc_intrinsic]
|
||||||
fn float_to_int_unchecked<Float: Copy, Int: Copy>(value: Float) -> Int;
|
unsafe fn float_to_int_unchecked<Float: Copy, Int: Copy>(_value: Float) -> Int;
|
||||||
}
|
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
unsafe {
|
unsafe {
|
||||||
|
@ -1,9 +1,8 @@
|
|||||||
#![feature(intrinsics)]
|
#![feature(intrinsics)]
|
||||||
|
|
||||||
// Directly call intrinsic to avoid debug assertions in libstd
|
// Directly call intrinsic to avoid debug assertions in libstd
|
||||||
extern "rust-intrinsic" {
|
#[rustc_intrinsic]
|
||||||
fn float_to_int_unchecked<Float: Copy, Int: Copy>(value: Float) -> Int;
|
unsafe fn float_to_int_unchecked<Float: Copy, Int: Copy>(_value: Float) -> Int;
|
||||||
}
|
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
unsafe {
|
unsafe {
|
||||||
|
@ -1,9 +1,8 @@
|
|||||||
#![feature(intrinsics)]
|
#![feature(intrinsics)]
|
||||||
|
|
||||||
// Directly call intrinsic to avoid debug assertions in libstd
|
// Directly call intrinsic to avoid debug assertions in libstd
|
||||||
extern "rust-intrinsic" {
|
#[rustc_intrinsic]
|
||||||
fn float_to_int_unchecked<Float: Copy, Int: Copy>(value: Float) -> Int;
|
unsafe fn float_to_int_unchecked<Float: Copy, Int: Copy>(_value: Float) -> Int;
|
||||||
}
|
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
unsafe {
|
unsafe {
|
||||||
|
@ -1,9 +1,8 @@
|
|||||||
#![feature(intrinsics)]
|
#![feature(intrinsics)]
|
||||||
|
|
||||||
// Directly call intrinsic to avoid debug assertions in libstd
|
// Directly call intrinsic to avoid debug assertions in libstd
|
||||||
extern "rust-intrinsic" {
|
#[rustc_intrinsic]
|
||||||
fn float_to_int_unchecked<Float: Copy, Int: Copy>(value: Float) -> Int;
|
unsafe fn float_to_int_unchecked<Float: Copy, Int: Copy>(_value: Float) -> Int;
|
||||||
}
|
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
unsafe {
|
unsafe {
|
||||||
|
@ -1,9 +1,8 @@
|
|||||||
#![feature(intrinsics)]
|
#![feature(intrinsics)]
|
||||||
|
|
||||||
// Directly call intrinsic to avoid debug assertions in libstd
|
// Directly call intrinsic to avoid debug assertions in libstd
|
||||||
extern "rust-intrinsic" {
|
#[rustc_intrinsic]
|
||||||
fn float_to_int_unchecked<Float: Copy, Int: Copy>(value: Float) -> Int;
|
unsafe fn float_to_int_unchecked<Float: Copy, Int: Copy>(_value: Float) -> Int;
|
||||||
}
|
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
unsafe {
|
unsafe {
|
||||||
|
@ -1,9 +1,8 @@
|
|||||||
#![feature(intrinsics)]
|
#![feature(intrinsics)]
|
||||||
|
|
||||||
// Directly call intrinsic to avoid debug assertions in libstd
|
// Directly call intrinsic to avoid debug assertions in libstd
|
||||||
extern "rust-intrinsic" {
|
#[rustc_intrinsic]
|
||||||
fn float_to_int_unchecked<Float: Copy, Int: Copy>(value: Float) -> Int;
|
unsafe fn float_to_int_unchecked<Float: Copy, Int: Copy>(_value: Float) -> Int;
|
||||||
}
|
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
unsafe {
|
unsafe {
|
||||||
|
@ -1,9 +1,8 @@
|
|||||||
#![feature(intrinsics)]
|
#![feature(intrinsics)]
|
||||||
|
|
||||||
// Directly call intrinsic to avoid debug assertions in libstd
|
// Directly call intrinsic to avoid debug assertions in libstd
|
||||||
extern "rust-intrinsic" {
|
#[rustc_intrinsic]
|
||||||
fn float_to_int_unchecked<Float: Copy, Int: Copy>(value: Float) -> Int;
|
unsafe fn float_to_int_unchecked<Float: Copy, Int: Copy>(_value: Float) -> Int;
|
||||||
}
|
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
unsafe {
|
unsafe {
|
||||||
|
@ -1,9 +1,8 @@
|
|||||||
#![feature(intrinsics)]
|
#![feature(intrinsics)]
|
||||||
|
|
||||||
// Directly call intrinsic to avoid debug assertions in libstd
|
// Directly call intrinsic to avoid debug assertions in libstd
|
||||||
extern "rust-intrinsic" {
|
#[rustc_intrinsic]
|
||||||
fn float_to_int_unchecked<Float: Copy, Int: Copy>(value: Float) -> Int;
|
unsafe fn float_to_int_unchecked<Float: Copy, Int: Copy>(_value: Float) -> Int;
|
||||||
}
|
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
unsafe {
|
unsafe {
|
||||||
|
@ -1,9 +1,8 @@
|
|||||||
#![feature(intrinsics)]
|
#![feature(intrinsics)]
|
||||||
|
|
||||||
// Directly call intrinsic to avoid debug assertions in libstd
|
// Directly call intrinsic to avoid debug assertions in libstd
|
||||||
extern "rust-intrinsic" {
|
#[rustc_intrinsic]
|
||||||
fn float_to_int_unchecked<Float: Copy, Int: Copy>(value: Float) -> Int;
|
unsafe fn float_to_int_unchecked<Float: Copy, Int: Copy>(_value: Float) -> Int;
|
||||||
}
|
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
unsafe {
|
unsafe {
|
||||||
|
@ -14,10 +14,9 @@ use std::ptr;
|
|||||||
use std::simd::StdFloat;
|
use std::simd::StdFloat;
|
||||||
use std::simd::prelude::*;
|
use std::simd::prelude::*;
|
||||||
|
|
||||||
extern "rust-intrinsic" {
|
#[rustc_intrinsic]
|
||||||
#[rustc_nounwind]
|
#[rustc_nounwind]
|
||||||
pub fn simd_shuffle_generic<T, U, const IDX: &'static [u32]>(x: T, y: T) -> U;
|
pub unsafe fn simd_shuffle_generic<T, U, const IDX: &'static [u32]>(_x: T, _y: T) -> U;
|
||||||
}
|
|
||||||
|
|
||||||
fn simd_ops_f32() {
|
fn simd_ops_f32() {
|
||||||
let a = f32x4::splat(10.0);
|
let a = f32x4::splat(10.0);
|
||||||
|
@ -98,9 +98,9 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "bitflags"
|
name = "bitflags"
|
||||||
version = "2.6.0"
|
version = "2.7.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "b048fb63fd8b5923fc5aa7b340d8e156aec7ec02f0c78fa8a6ddc2613f6f71de"
|
checksum = "1be3f42a67d6d345ecd59f675f3f012d6974981560836e938c22b424b85ce1be"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "borsh"
|
name = "borsh"
|
||||||
@ -194,9 +194,9 @@ checksum = "613afe47fcd5fac7ccf1db93babcb082c5994d996f20b8b159f2ad1658eb5724"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "chalk-derive"
|
name = "chalk-derive"
|
||||||
version = "0.98.0"
|
version = "0.99.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "9426c8fd0fe61c3da880b801d3b510524df17843a8f9ec1f5b9cec24fb7412df"
|
checksum = "572583d9b97f9d277e5c7607f8239a30e2e04d3ed3b47c87d1cb2152ae724073"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
@ -206,19 +206,19 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "chalk-ir"
|
name = "chalk-ir"
|
||||||
version = "0.98.0"
|
version = "0.99.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "d5f2eb1cd6054da221bd1ac0197fb2fe5e2caf3dcb93619398fc1433f8f09093"
|
checksum = "e60e0ef9c81dce1336a9ed3c76f08775f5b623151d96d85ba45f7b10de76d1c7"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bitflags 2.6.0",
|
"bitflags 2.7.0",
|
||||||
"chalk-derive",
|
"chalk-derive",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "chalk-recursive"
|
name = "chalk-recursive"
|
||||||
version = "0.98.0"
|
version = "0.99.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "129dc03458f71cfb9c3cd621c9c68166a94e87b85b16ccd29af015d7ff9a1c61"
|
checksum = "5a06350d614e22b03a69b8105e3541614450a7ea48bc58ecc6c6bd92731a3995"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"chalk-derive",
|
"chalk-derive",
|
||||||
"chalk-ir",
|
"chalk-ir",
|
||||||
@ -229,9 +229,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "chalk-solve"
|
name = "chalk-solve"
|
||||||
version = "0.98.0"
|
version = "0.99.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "d7e8a8c1e928f98cdf227b868416ef21dcd8cc3c61b347576d783713444d41c8"
|
checksum = "0e428761e9b55bee516bfe2457caed8b6d1b86353f92ae825bbe438a36ce91e8"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"chalk-derive",
|
"chalk-derive",
|
||||||
"chalk-ir",
|
"chalk-ir",
|
||||||
@ -523,6 +523,7 @@ dependencies = [
|
|||||||
"hir-def",
|
"hir-def",
|
||||||
"hir-expand",
|
"hir-expand",
|
||||||
"hir-ty",
|
"hir-ty",
|
||||||
|
"indexmap",
|
||||||
"intern",
|
"intern",
|
||||||
"itertools",
|
"itertools",
|
||||||
"rustc-hash 2.0.0",
|
"rustc-hash 2.0.0",
|
||||||
@ -544,7 +545,7 @@ version = "0.0.0"
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"arrayvec",
|
"arrayvec",
|
||||||
"base-db",
|
"base-db",
|
||||||
"bitflags 2.6.0",
|
"bitflags 2.7.0",
|
||||||
"cfg",
|
"cfg",
|
||||||
"cov-mark",
|
"cov-mark",
|
||||||
"dashmap",
|
"dashmap",
|
||||||
@ -610,7 +611,7 @@ version = "0.0.0"
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"arrayvec",
|
"arrayvec",
|
||||||
"base-db",
|
"base-db",
|
||||||
"bitflags 2.6.0",
|
"bitflags 2.7.0",
|
||||||
"chalk-derive",
|
"chalk-derive",
|
||||||
"chalk-ir",
|
"chalk-ir",
|
||||||
"chalk-recursive",
|
"chalk-recursive",
|
||||||
@ -734,7 +735,7 @@ version = "0.0.0"
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"arrayvec",
|
"arrayvec",
|
||||||
"base-db",
|
"base-db",
|
||||||
"bitflags 2.6.0",
|
"bitflags 2.7.0",
|
||||||
"cov-mark",
|
"cov-mark",
|
||||||
"crossbeam-channel",
|
"crossbeam-channel",
|
||||||
"either",
|
"either",
|
||||||
@ -820,11 +821,11 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "inotify"
|
name = "inotify"
|
||||||
version = "0.9.6"
|
version = "0.11.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "f8069d3ec154eb856955c1c0fbffefbf5f3c40a104ec912d4797314c1801abff"
|
checksum = "f37dccff2791ab604f9babef0ba14fbe0be30bd368dc541e2b08d07c8aa908f3"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bitflags 1.3.2",
|
"bitflags 2.7.0",
|
||||||
"inotify-sys",
|
"inotify-sys",
|
||||||
"libc",
|
"libc",
|
||||||
]
|
]
|
||||||
@ -908,9 +909,9 @@ checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "libc"
|
name = "libc"
|
||||||
version = "0.2.155"
|
version = "0.2.169"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "97b3888a4aecf77e811145cadf6eef5901f4782c53886191b2f693f24761847c"
|
checksum = "b5aba8db14291edd000dfcc4d620c7ebfb122c613afb886ca8803fa4e128a20a"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "libloading"
|
name = "libloading"
|
||||||
@ -938,7 +939,7 @@ version = "0.1.3"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "c0ff37bd590ca25063e35af745c343cb7a0271906fb7b37e4813e8f79f00268d"
|
checksum = "c0ff37bd590ca25063e35af745c343cb7a0271906fb7b37e4813e8f79f00268d"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bitflags 2.6.0",
|
"bitflags 2.7.0",
|
||||||
"libc",
|
"libc",
|
||||||
"redox_syscall",
|
"redox_syscall",
|
||||||
]
|
]
|
||||||
@ -1117,14 +1118,14 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "mio"
|
name = "mio"
|
||||||
version = "0.8.11"
|
version = "1.0.3"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "a4a650543ca06a924e8b371db273b2756685faae30f8487da1b56505a8f78b0c"
|
checksum = "2886843bf800fba2e3377cff24abf6379b4c4d5c6681eaf9ea5b0d15090450bd"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"libc",
|
"libc",
|
||||||
"log",
|
"log",
|
||||||
"wasi",
|
"wasi",
|
||||||
"windows-sys 0.48.0",
|
"windows-sys 0.52.0",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@ -1142,7 +1143,7 @@ version = "0.28.0"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "ab2156c4fce2f8df6c499cc1c763e4394b7482525bf2a9701c9d79d215f519e4"
|
checksum = "ab2156c4fce2f8df6c499cc1c763e4394b7482525bf2a9701c9d79d215f519e4"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bitflags 2.6.0",
|
"bitflags 2.7.0",
|
||||||
"cfg-if",
|
"cfg-if",
|
||||||
"cfg_aliases 0.1.1",
|
"cfg_aliases 0.1.1",
|
||||||
"libc",
|
"libc",
|
||||||
@ -1156,12 +1157,11 @@ checksum = "2bf50223579dc7cdcfb3bfcacf7069ff68243f8c363f62ffa99cf000a6b9c451"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "notify"
|
name = "notify"
|
||||||
version = "6.1.1"
|
version = "8.0.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "6205bd8bb1e454ad2e27422015fb5e4f2bcc7e08fa8f27058670d208324a4d2d"
|
checksum = "2fee8403b3d66ac7b26aee6e40a897d85dc5ce26f44da36b8b73e987cc52e943"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bitflags 2.6.0",
|
"bitflags 2.7.0",
|
||||||
"crossbeam-channel",
|
|
||||||
"filetime",
|
"filetime",
|
||||||
"fsevent-sys",
|
"fsevent-sys",
|
||||||
"inotify",
|
"inotify",
|
||||||
@ -1169,10 +1169,17 @@ dependencies = [
|
|||||||
"libc",
|
"libc",
|
||||||
"log",
|
"log",
|
||||||
"mio",
|
"mio",
|
||||||
|
"notify-types",
|
||||||
"walkdir",
|
"walkdir",
|
||||||
"windows-sys 0.48.0",
|
"windows-sys 0.59.0",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "notify-types"
|
||||||
|
version = "2.0.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "5e0826a989adedc2a244799e823aece04662b66609d96af8dff7ac6df9a8925d"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "nu-ansi-term"
|
name = "nu-ansi-term"
|
||||||
version = "0.50.1"
|
version = "0.50.1"
|
||||||
@ -1371,6 +1378,7 @@ version = "0.0.0"
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"expect-test",
|
"expect-test",
|
||||||
"intern",
|
"intern",
|
||||||
|
"libc",
|
||||||
"libloading",
|
"libloading",
|
||||||
"memmap2",
|
"memmap2",
|
||||||
"object 0.33.0",
|
"object 0.33.0",
|
||||||
@ -1428,7 +1436,7 @@ dependencies = [
|
|||||||
"libc",
|
"libc",
|
||||||
"perf-event",
|
"perf-event",
|
||||||
"tikv-jemalloc-ctl",
|
"tikv-jemalloc-ctl",
|
||||||
"windows-sys 0.52.0",
|
"windows-sys 0.59.0",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@ -1482,7 +1490,7 @@ version = "0.9.6"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "57206b407293d2bcd3af849ce869d52068623f19e1b5ff8e8778e3309439682b"
|
checksum = "57206b407293d2bcd3af849ce869d52068623f19e1b5ff8e8778e3309439682b"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bitflags 2.6.0",
|
"bitflags 2.7.0",
|
||||||
"memchr",
|
"memchr",
|
||||||
"unicase",
|
"unicase",
|
||||||
]
|
]
|
||||||
@ -1507,20 +1515,20 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "ra-ap-rustc_abi"
|
name = "ra-ap-rustc_abi"
|
||||||
version = "0.87.0"
|
version = "0.91.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "28b782af0a7a8df16ddf43cd70da9f17bc3b1ce712c9e4992b6edb16f5f53632"
|
checksum = "d5246e9e1f450333a990877eabbc36fe0567e7cedd56d5365db319e14079cf2a"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bitflags 2.6.0",
|
"bitflags 2.7.0",
|
||||||
"ra-ap-rustc_index",
|
"ra-ap-rustc_index",
|
||||||
"tracing",
|
"tracing",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "ra-ap-rustc_index"
|
name = "ra-ap-rustc_index"
|
||||||
version = "0.87.0"
|
version = "0.91.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "ce5742f134960482f543b35ecebec3cacc6d79a9a685713518b4d8d70c5f9aa8"
|
checksum = "59fd8e4f5b34c434ec111efb0e0614954db048b9307d3b2e4cc3c915da9d2160"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"ra-ap-rustc_index_macros",
|
"ra-ap-rustc_index_macros",
|
||||||
"smallvec",
|
"smallvec",
|
||||||
@ -1528,9 +1536,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "ra-ap-rustc_index_macros"
|
name = "ra-ap-rustc_index_macros"
|
||||||
version = "0.87.0"
|
version = "0.91.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "d7ea011fcf68309a8835ad01d91c032cb18444617b00e2cab21d45b208164441"
|
checksum = "2d34973fe081392bd1edb022e865e9952fcaa093f9cdae183edce64472e5e889"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
@ -1539,9 +1547,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "ra-ap-rustc_lexer"
|
name = "ra-ap-rustc_lexer"
|
||||||
version = "0.87.0"
|
version = "0.91.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "eb76f0a4d4c20859e41f0a23bff0f37ab9ca9171c214a6c7dd72ea69434865dc"
|
checksum = "52fa42c582e21b35e8f61a5afe3c63a9c722d995826762eb19b18beeccf5157f"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"unicode-properties",
|
"unicode-properties",
|
||||||
"unicode-xid",
|
"unicode-xid",
|
||||||
@ -1549,9 +1557,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "ra-ap-rustc_parse_format"
|
name = "ra-ap-rustc_parse_format"
|
||||||
version = "0.87.0"
|
version = "0.91.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "06080bd35078305421a62da77f3c128482d8d44441b6da8ce9d146d1cd9cdb5b"
|
checksum = "740383328d7033393e5385f4a6073b880d5811b0fc0fd2559e481f905940f2f8"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"ra-ap-rustc_index",
|
"ra-ap-rustc_index",
|
||||||
"ra-ap-rustc_lexer",
|
"ra-ap-rustc_lexer",
|
||||||
@ -1559,9 +1567,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "ra-ap-rustc_pattern_analysis"
|
name = "ra-ap-rustc_pattern_analysis"
|
||||||
version = "0.87.0"
|
version = "0.91.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "68a3154fe4c20c177d7b3c678a2d3a97aba0cca156ddef88959915041889daf0"
|
checksum = "c39f544728f32cebffb1a8b92ba3c1f3dcb4144081438d192137ed197d479a9d"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"ra-ap-rustc_index",
|
"ra-ap-rustc_index",
|
||||||
"rustc-hash 2.0.0",
|
"rustc-hash 2.0.0",
|
||||||
@ -1626,7 +1634,7 @@ version = "0.5.3"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "2a908a6e00f1fdd0dfd9c0eb08ce85126f6d8bbda50017e74bc4a4b7d4a926a4"
|
checksum = "2a908a6e00f1fdd0dfd9c0eb08ce85126f6d8bbda50017e74bc4a4b7d4a926a4"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bitflags 2.6.0",
|
"bitflags 2.7.0",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@ -1713,7 +1721,7 @@ dependencies = [
|
|||||||
"vfs",
|
"vfs",
|
||||||
"vfs-notify",
|
"vfs-notify",
|
||||||
"walkdir",
|
"walkdir",
|
||||||
"windows-sys 0.52.0",
|
"windows-sys 0.59.0",
|
||||||
"xflags",
|
"xflags",
|
||||||
"xshell",
|
"xshell",
|
||||||
]
|
]
|
||||||
@ -1936,7 +1944,7 @@ dependencies = [
|
|||||||
"jod-thread",
|
"jod-thread",
|
||||||
"libc",
|
"libc",
|
||||||
"miow",
|
"miow",
|
||||||
"windows-sys 0.52.0",
|
"windows-sys 0.59.0",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
@ -4,7 +4,7 @@ exclude = ["crates/proc-macro-srv/proc-macro-test/imp"]
|
|||||||
resolver = "2"
|
resolver = "2"
|
||||||
|
|
||||||
[workspace.package]
|
[workspace.package]
|
||||||
rust-version = "1.82"
|
rust-version = "1.83"
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
license = "MIT OR Apache-2.0"
|
license = "MIT OR Apache-2.0"
|
||||||
authors = ["rust-analyzer team"]
|
authors = ["rust-analyzer team"]
|
||||||
@ -79,6 +79,7 @@ span = { path = "./crates/span", version = "0.0.0" }
|
|||||||
stdx = { path = "./crates/stdx", version = "0.0.0" }
|
stdx = { path = "./crates/stdx", version = "0.0.0" }
|
||||||
syntax = { path = "./crates/syntax", version = "0.0.0" }
|
syntax = { path = "./crates/syntax", version = "0.0.0" }
|
||||||
syntax-bridge = { path = "./crates/syntax-bridge", version = "0.0.0" }
|
syntax-bridge = { path = "./crates/syntax-bridge", version = "0.0.0" }
|
||||||
|
test-fixture = { path = "./crates/test-fixture", version = "0.0.0" }
|
||||||
test-utils = { path = "./crates/test-utils", version = "0.0.0" }
|
test-utils = { path = "./crates/test-utils", version = "0.0.0" }
|
||||||
toolchain = { path = "./crates/toolchain", version = "0.0.0" }
|
toolchain = { path = "./crates/toolchain", version = "0.0.0" }
|
||||||
tt = { path = "./crates/tt", version = "0.0.0" }
|
tt = { path = "./crates/tt", version = "0.0.0" }
|
||||||
@ -86,16 +87,15 @@ vfs-notify = { path = "./crates/vfs-notify", version = "0.0.0" }
|
|||||||
vfs = { path = "./crates/vfs", version = "0.0.0" }
|
vfs = { path = "./crates/vfs", version = "0.0.0" }
|
||||||
edition = { path = "./crates/edition", version = "0.0.0" }
|
edition = { path = "./crates/edition", version = "0.0.0" }
|
||||||
|
|
||||||
ra-ap-rustc_lexer = { version = "0.87", default-features = false }
|
ra-ap-rustc_lexer = { version = "0.91", default-features = false }
|
||||||
ra-ap-rustc_parse_format = { version = "0.87", default-features = false }
|
ra-ap-rustc_parse_format = { version = "0.91", default-features = false }
|
||||||
ra-ap-rustc_index = { version = "0.87", default-features = false }
|
ra-ap-rustc_index = { version = "0.91", default-features = false }
|
||||||
ra-ap-rustc_abi = { version = "0.87", default-features = false }
|
ra-ap-rustc_abi = { version = "0.91", default-features = false }
|
||||||
ra-ap-rustc_pattern_analysis = { version = "0.87", default-features = false }
|
ra-ap-rustc_pattern_analysis = { version = "0.91", default-features = false }
|
||||||
|
|
||||||
# local crates that aren't published to crates.io. These should not have versions.
|
# local crates that aren't published to crates.io. These should not have versions.
|
||||||
test-fixture = { path = "./crates/test-fixture" }
|
|
||||||
|
|
||||||
# In-tree crates that are published separately and follow semver. See lib/README.md
|
# in-tree crates that are published separately and follow semver. See lib/README.md
|
||||||
line-index = { version = "0.1.2" }
|
line-index = { version = "0.1.2" }
|
||||||
la-arena = { version = "0.3.1" }
|
la-arena = { version = "0.3.1" }
|
||||||
lsp-server = { version = "0.7.6" }
|
lsp-server = { version = "0.7.6" }
|
||||||
@ -106,10 +106,10 @@ arrayvec = "0.7.4"
|
|||||||
bitflags = "2.4.1"
|
bitflags = "2.4.1"
|
||||||
cargo_metadata = "0.18.1"
|
cargo_metadata = "0.18.1"
|
||||||
camino = "1.1.6"
|
camino = "1.1.6"
|
||||||
chalk-solve = { version = "0.98.0", default-features = false }
|
chalk-solve = { version = "0.99.0", default-features = false }
|
||||||
chalk-ir = "0.98.0"
|
chalk-ir = "0.99.0"
|
||||||
chalk-recursive = { version = "0.98.0", default-features = false }
|
chalk-recursive = { version = "0.99.0", default-features = false }
|
||||||
chalk-derive = "0.98.0"
|
chalk-derive = "0.99.0"
|
||||||
crossbeam-channel = "0.5.8"
|
crossbeam-channel = "0.5.8"
|
||||||
dissimilar = "1.0.7"
|
dissimilar = "1.0.7"
|
||||||
dot = "0.1.4"
|
dot = "0.1.4"
|
||||||
|
@ -136,7 +136,7 @@ pub trait SourceRootDatabase: SourceDatabase {
|
|||||||
#[ra_salsa::input]
|
#[ra_salsa::input]
|
||||||
fn source_root(&self, id: SourceRootId) -> Arc<SourceRoot>;
|
fn source_root(&self, id: SourceRootId) -> Arc<SourceRoot>;
|
||||||
|
|
||||||
/// Crates whose root fool is in `id`.
|
/// Crates whose root file is in `id`.
|
||||||
fn source_root_crates(&self, id: SourceRootId) -> Arc<[CrateId]>;
|
fn source_root_crates(&self, id: SourceRootId) -> Arc<[CrateId]>;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -5,7 +5,8 @@ use std::fmt;
|
|||||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
||||||
#[repr(u8)]
|
#[repr(u8)]
|
||||||
pub enum Edition {
|
pub enum Edition {
|
||||||
Edition2015,
|
// The syntax context stuff needs the discriminants to start from 0 and be consecutive.
|
||||||
|
Edition2015 = 0,
|
||||||
Edition2018,
|
Edition2018,
|
||||||
Edition2021,
|
Edition2021,
|
||||||
Edition2024,
|
Edition2024,
|
||||||
|
@ -122,6 +122,11 @@ impl Attrs {
|
|||||||
AttrQuery { attrs: self, key }
|
AttrQuery { attrs: self, key }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn rust_analyzer_tool(&self) -> impl Iterator<Item = &Attr> {
|
||||||
|
self.iter()
|
||||||
|
.filter(|&attr| attr.path.segments().first().is_some_and(|s| *s == sym::rust_analyzer))
|
||||||
|
}
|
||||||
|
|
||||||
pub fn cfg(&self) -> Option<CfgExpr> {
|
pub fn cfg(&self) -> Option<CfgExpr> {
|
||||||
let mut cfgs = self.by_key(&sym::cfg).tt_values().map(CfgExpr::parse);
|
let mut cfgs = self.by_key(&sym::cfg).tt_values().map(CfgExpr::parse);
|
||||||
let first = cfgs.next()?;
|
let first = cfgs.next()?;
|
||||||
|
@ -15,7 +15,7 @@ use hir_expand::{name::Name, ExpandError, InFile};
|
|||||||
use la_arena::{Arena, ArenaMap, Idx, RawIdx};
|
use la_arena::{Arena, ArenaMap, Idx, RawIdx};
|
||||||
use rustc_hash::FxHashMap;
|
use rustc_hash::FxHashMap;
|
||||||
use smallvec::SmallVec;
|
use smallvec::SmallVec;
|
||||||
use span::{Edition, MacroFileId};
|
use span::{Edition, MacroFileId, SyntaxContextData};
|
||||||
use syntax::{ast, AstPtr, SyntaxNodePtr};
|
use syntax::{ast, AstPtr, SyntaxNodePtr};
|
||||||
use triomphe::Arc;
|
use triomphe::Arc;
|
||||||
use tt::TextRange;
|
use tt::TextRange;
|
||||||
@ -37,15 +37,22 @@ use crate::{
|
|||||||
|
|
||||||
/// A wrapper around [`span::SyntaxContextId`] that is intended only for comparisons.
|
/// A wrapper around [`span::SyntaxContextId`] that is intended only for comparisons.
|
||||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
|
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
|
||||||
pub struct HygieneId(pub(crate) span::SyntaxContextId);
|
pub struct HygieneId(span::SyntaxContextId);
|
||||||
|
|
||||||
impl HygieneId {
|
impl HygieneId {
|
||||||
pub const ROOT: Self = Self(span::SyntaxContextId::ROOT);
|
// The edition doesn't matter here, we only use this for comparisons and to lookup the macro.
|
||||||
|
pub const ROOT: Self = Self(span::SyntaxContextId::root(Edition::Edition2015));
|
||||||
|
|
||||||
pub fn new(ctx: span::SyntaxContextId) -> Self {
|
pub fn new(mut ctx: span::SyntaxContextId) -> Self {
|
||||||
|
// See `Name` for why we're doing that.
|
||||||
|
ctx.remove_root_edition();
|
||||||
Self(ctx)
|
Self(ctx)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub(crate) fn lookup(self, db: &dyn DefDatabase) -> SyntaxContextData {
|
||||||
|
db.lookup_intern_syntax_context(self.0)
|
||||||
|
}
|
||||||
|
|
||||||
pub(crate) fn is_root(self) -> bool {
|
pub(crate) fn is_root(self) -> bool {
|
||||||
self.0.is_root()
|
self.0.is_root()
|
||||||
}
|
}
|
||||||
|
@ -8,6 +8,7 @@ use std::mem;
|
|||||||
use base_db::CrateId;
|
use base_db::CrateId;
|
||||||
use either::Either;
|
use either::Either;
|
||||||
use hir_expand::{
|
use hir_expand::{
|
||||||
|
mod_path::tool_path,
|
||||||
name::{AsName, Name},
|
name::{AsName, Name},
|
||||||
span_map::{ExpansionSpanMap, SpanMap},
|
span_map::{ExpansionSpanMap, SpanMap},
|
||||||
InFile, MacroDefId,
|
InFile, MacroDefId,
|
||||||
@ -27,6 +28,7 @@ use text_size::TextSize;
|
|||||||
use triomphe::Arc;
|
use triomphe::Arc;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
|
attr::Attrs,
|
||||||
body::{Body, BodyDiagnostic, BodySourceMap, ExprPtr, HygieneId, LabelPtr, PatPtr},
|
body::{Body, BodyDiagnostic, BodySourceMap, ExprPtr, HygieneId, LabelPtr, PatPtr},
|
||||||
builtin_type::BuiltinUint,
|
builtin_type::BuiltinUint,
|
||||||
data::adt::StructKind,
|
data::adt::StructKind,
|
||||||
@ -212,6 +214,43 @@ impl ExprCollector<'_> {
|
|||||||
body: Option<ast::Expr>,
|
body: Option<ast::Expr>,
|
||||||
is_async_fn: bool,
|
is_async_fn: bool,
|
||||||
) -> (Body, BodySourceMap) {
|
) -> (Body, BodySourceMap) {
|
||||||
|
let skip_body = match self.owner {
|
||||||
|
DefWithBodyId::FunctionId(it) => self.db.attrs(it.into()),
|
||||||
|
DefWithBodyId::StaticId(it) => self.db.attrs(it.into()),
|
||||||
|
DefWithBodyId::ConstId(it) => self.db.attrs(it.into()),
|
||||||
|
DefWithBodyId::InTypeConstId(_) => Attrs::EMPTY,
|
||||||
|
DefWithBodyId::VariantId(it) => self.db.attrs(it.into()),
|
||||||
|
}
|
||||||
|
.rust_analyzer_tool()
|
||||||
|
.any(|attr| *attr.path() == tool_path![skip]);
|
||||||
|
// If #[rust_analyzer::skip] annotated, only construct enough information for the signature
|
||||||
|
// and skip the body.
|
||||||
|
if skip_body {
|
||||||
|
self.body.body_expr = self.missing_expr();
|
||||||
|
if let Some((param_list, mut attr_enabled)) = param_list {
|
||||||
|
if let Some(self_param) =
|
||||||
|
param_list.self_param().filter(|_| attr_enabled.next().unwrap_or(false))
|
||||||
|
{
|
||||||
|
let is_mutable =
|
||||||
|
self_param.mut_token().is_some() && self_param.amp_token().is_none();
|
||||||
|
let binding_id: la_arena::Idx<Binding> = self.alloc_binding(
|
||||||
|
Name::new_symbol_root(sym::self_.clone()),
|
||||||
|
BindingAnnotation::new(is_mutable, false),
|
||||||
|
);
|
||||||
|
self.body.self_param = Some(binding_id);
|
||||||
|
self.source_map.self_param =
|
||||||
|
Some(self.expander.in_file(AstPtr::new(&self_param)));
|
||||||
|
}
|
||||||
|
self.body.params = param_list
|
||||||
|
.params()
|
||||||
|
.zip(attr_enabled)
|
||||||
|
.filter(|(_, enabled)| *enabled)
|
||||||
|
.map(|_| self.missing_pat())
|
||||||
|
.collect();
|
||||||
|
};
|
||||||
|
return (self.body, self.source_map);
|
||||||
|
}
|
||||||
|
|
||||||
self.awaitable_context.replace(if is_async_fn {
|
self.awaitable_context.replace(if is_async_fn {
|
||||||
Awaitable::Yes
|
Awaitable::Yes
|
||||||
} else {
|
} else {
|
||||||
@ -542,10 +581,7 @@ impl ExprCollector<'_> {
|
|||||||
let mutability = if raw_tok {
|
let mutability = if raw_tok {
|
||||||
if e.mut_token().is_some() {
|
if e.mut_token().is_some() {
|
||||||
Mutability::Mut
|
Mutability::Mut
|
||||||
} else if e.const_token().is_some() {
|
|
||||||
Mutability::Shared
|
|
||||||
} else {
|
} else {
|
||||||
never!("parser only remaps to raw_token() if matching mutability token follows");
|
|
||||||
Mutability::Shared
|
Mutability::Shared
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@ -2460,7 +2496,7 @@ impl ExprCollector<'_> {
|
|||||||
None => HygieneId::ROOT,
|
None => HygieneId::ROOT,
|
||||||
Some(span_map) => {
|
Some(span_map) => {
|
||||||
let ctx = span_map.span_at(span_start).ctx;
|
let ctx = span_map.span_at(span_start).ctx;
|
||||||
HygieneId(self.db.lookup_intern_syntax_context(ctx).opaque_and_semitransparent)
|
HygieneId::new(self.db.lookup_intern_syntax_context(ctx).opaque_and_semitransparent)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -345,7 +345,7 @@ mod tests {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn do_check(ra_fixture: &str, expected: &[&str]) {
|
fn do_check(#[rust_analyzer::rust_fixture] ra_fixture: &str, expected: &[&str]) {
|
||||||
let (offset, code) = extract_offset(ra_fixture);
|
let (offset, code) = extract_offset(ra_fixture);
|
||||||
let code = {
|
let code = {
|
||||||
let mut buf = String::new();
|
let mut buf = String::new();
|
||||||
@ -509,7 +509,7 @@ fn foo() {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn do_check_local_name(ra_fixture: &str, expected_offset: u32) {
|
fn do_check_local_name(#[rust_analyzer::rust_fixture] ra_fixture: &str, expected_offset: u32) {
|
||||||
let (db, position) = TestDB::with_position(ra_fixture);
|
let (db, position) = TestDB::with_position(ra_fixture);
|
||||||
let file_id = position.file_id;
|
let file_id = position.file_id;
|
||||||
let offset = position.offset;
|
let offset = position.offset;
|
||||||
|
@ -7,7 +7,7 @@ use crate::{test_db::TestDB, ModuleDefId};
|
|||||||
|
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
||||||
fn lower(ra_fixture: &str) -> (TestDB, Arc<Body>, DefWithBodyId) {
|
fn lower(#[rust_analyzer::rust_fixture] ra_fixture: &str) -> (TestDB, Arc<Body>, DefWithBodyId) {
|
||||||
let db = TestDB::with_files(ra_fixture);
|
let db = TestDB::with_files(ra_fixture);
|
||||||
|
|
||||||
let krate = db.fetch_test_crate();
|
let krate = db.fetch_test_crate();
|
||||||
@ -27,14 +27,14 @@ fn lower(ra_fixture: &str) -> (TestDB, Arc<Body>, DefWithBodyId) {
|
|||||||
(db, body, fn_def)
|
(db, body, fn_def)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn def_map_at(ra_fixture: &str) -> String {
|
fn def_map_at(#[rust_analyzer::rust_fixture] ra_fixture: &str) -> String {
|
||||||
let (db, position) = TestDB::with_position(ra_fixture);
|
let (db, position) = TestDB::with_position(ra_fixture);
|
||||||
|
|
||||||
let module = db.module_at_position(position);
|
let module = db.module_at_position(position);
|
||||||
module.def_map(&db).dump(&db)
|
module.def_map(&db).dump(&db)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn check_block_scopes_at(ra_fixture: &str, expect: Expect) {
|
fn check_block_scopes_at(#[rust_analyzer::rust_fixture] ra_fixture: &str, expect: Expect) {
|
||||||
let (db, position) = TestDB::with_position(ra_fixture);
|
let (db, position) = TestDB::with_position(ra_fixture);
|
||||||
|
|
||||||
let module = db.module_at_position(position);
|
let module = db.module_at_position(position);
|
||||||
@ -42,7 +42,7 @@ fn check_block_scopes_at(ra_fixture: &str, expect: Expect) {
|
|||||||
expect.assert_eq(&actual);
|
expect.assert_eq(&actual);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn check_at(ra_fixture: &str, expect: Expect) {
|
fn check_at(#[rust_analyzer::rust_fixture] ra_fixture: &str, expect: Expect) {
|
||||||
let actual = def_map_at(ra_fixture);
|
let actual = def_map_at(ra_fixture);
|
||||||
expect.assert_eq(&actual);
|
expect.assert_eq(&actual);
|
||||||
}
|
}
|
||||||
@ -444,3 +444,18 @@ fn foo() {
|
|||||||
}"#
|
}"#
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn skip_skips_body() {
|
||||||
|
let (db, body, owner) = lower(
|
||||||
|
r#"
|
||||||
|
#[rust_analyzer::skip]
|
||||||
|
async fn foo(a: (), b: i32) -> u32 {
|
||||||
|
0 + 1 + b()
|
||||||
|
}
|
||||||
|
"#,
|
||||||
|
);
|
||||||
|
let printed = body.pretty_print(&db, owner, Edition::CURRENT);
|
||||||
|
expect!["fn foo(<28>: (), <20>: i32) -> impl ::core::future::Future::<Output = u32> <20>"]
|
||||||
|
.assert_eq(&printed);
|
||||||
|
}
|
||||||
|
@ -244,7 +244,7 @@ bitflags::bitflags! {
|
|||||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||||
pub struct TraitData {
|
pub struct TraitData {
|
||||||
pub name: Name,
|
pub name: Name,
|
||||||
pub items: Vec<(Name, AssocItemId)>,
|
pub items: Box<[(Name, AssocItemId)]>,
|
||||||
pub flags: TraitFlags,
|
pub flags: TraitFlags,
|
||||||
pub visibility: RawVisibility,
|
pub visibility: RawVisibility,
|
||||||
// box it as the vec is usually empty anyways
|
// box it as the vec is usually empty anyways
|
||||||
@ -360,7 +360,7 @@ impl TraitAliasData {
|
|||||||
pub struct ImplData {
|
pub struct ImplData {
|
||||||
pub target_trait: Option<TraitRef>,
|
pub target_trait: Option<TraitRef>,
|
||||||
pub self_ty: TypeRefId,
|
pub self_ty: TypeRefId,
|
||||||
pub items: Box<[AssocItemId]>,
|
pub items: Box<[(Name, AssocItemId)]>,
|
||||||
pub is_negative: bool,
|
pub is_negative: bool,
|
||||||
pub is_unsafe: bool,
|
pub is_unsafe: bool,
|
||||||
// box it as the vec is usually empty anyways
|
// box it as the vec is usually empty anyways
|
||||||
@ -393,7 +393,6 @@ impl ImplData {
|
|||||||
collector.collect(&item_tree, tree_id.tree_id(), &impl_def.items);
|
collector.collect(&item_tree, tree_id.tree_id(), &impl_def.items);
|
||||||
|
|
||||||
let (items, macro_calls, diagnostics) = collector.finish();
|
let (items, macro_calls, diagnostics) = collector.finish();
|
||||||
let items = items.into_iter().map(|(_, item)| item).collect();
|
|
||||||
|
|
||||||
(
|
(
|
||||||
Arc::new(ImplData {
|
Arc::new(ImplData {
|
||||||
@ -648,12 +647,12 @@ impl<'a> AssocItemCollector<'a> {
|
|||||||
fn finish(
|
fn finish(
|
||||||
self,
|
self,
|
||||||
) -> (
|
) -> (
|
||||||
Vec<(Name, AssocItemId)>,
|
Box<[(Name, AssocItemId)]>,
|
||||||
Option<Box<Vec<(AstId<ast::Item>, MacroCallId)>>>,
|
Option<Box<Vec<(AstId<ast::Item>, MacroCallId)>>>,
|
||||||
Vec<DefDiagnostic>,
|
Vec<DefDiagnostic>,
|
||||||
) {
|
) {
|
||||||
(
|
(
|
||||||
self.items,
|
self.items.into_boxed_slice(),
|
||||||
if self.macro_calls.is_empty() { None } else { Some(Box::new(self.macro_calls)) },
|
if self.macro_calls.is_empty() { None } else { Some(Box::new(self.macro_calls)) },
|
||||||
self.diagnostics,
|
self.diagnostics,
|
||||||
)
|
)
|
||||||
|
@ -10,7 +10,7 @@ use hir_expand::{
|
|||||||
ExpandResult, HirFileId, InFile, Lookup, MacroCallId,
|
ExpandResult, HirFileId, InFile, Lookup, MacroCallId,
|
||||||
};
|
};
|
||||||
use limit::Limit;
|
use limit::Limit;
|
||||||
use span::SyntaxContextId;
|
use span::{Edition, SyntaxContextId};
|
||||||
use syntax::{ast, Parse};
|
use syntax::{ast, Parse};
|
||||||
use triomphe::Arc;
|
use triomphe::Arc;
|
||||||
|
|
||||||
@ -60,7 +60,7 @@ impl Expander {
|
|||||||
|
|
||||||
pub fn syntax_context(&self) -> SyntaxContextId {
|
pub fn syntax_context(&self) -> SyntaxContextId {
|
||||||
// FIXME:
|
// FIXME:
|
||||||
SyntaxContextId::ROOT
|
SyntaxContextId::root(Edition::CURRENT)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn enter_expand<T: ast::AstNode>(
|
pub fn enter_expand<T: ast::AstNode>(
|
||||||
|
@ -665,7 +665,7 @@ mod tests {
|
|||||||
/// module the cursor is in.
|
/// module the cursor is in.
|
||||||
#[track_caller]
|
#[track_caller]
|
||||||
fn check_found_path_(
|
fn check_found_path_(
|
||||||
ra_fixture: &str,
|
#[rust_analyzer::rust_fixture] ra_fixture: &str,
|
||||||
path: &str,
|
path: &str,
|
||||||
prefer_prelude: bool,
|
prefer_prelude: bool,
|
||||||
prefer_absolute: bool,
|
prefer_absolute: bool,
|
||||||
@ -727,19 +727,35 @@ mod tests {
|
|||||||
expect.assert_eq(&res);
|
expect.assert_eq(&res);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn check_found_path(ra_fixture: &str, path: &str, expect: Expect) {
|
fn check_found_path(
|
||||||
|
#[rust_analyzer::rust_fixture] ra_fixture: &str,
|
||||||
|
path: &str,
|
||||||
|
expect: Expect,
|
||||||
|
) {
|
||||||
check_found_path_(ra_fixture, path, false, false, false, expect);
|
check_found_path_(ra_fixture, path, false, false, false, expect);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn check_found_path_prelude(ra_fixture: &str, path: &str, expect: Expect) {
|
fn check_found_path_prelude(
|
||||||
|
#[rust_analyzer::rust_fixture] ra_fixture: &str,
|
||||||
|
path: &str,
|
||||||
|
expect: Expect,
|
||||||
|
) {
|
||||||
check_found_path_(ra_fixture, path, true, false, false, expect);
|
check_found_path_(ra_fixture, path, true, false, false, expect);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn check_found_path_absolute(ra_fixture: &str, path: &str, expect: Expect) {
|
fn check_found_path_absolute(
|
||||||
|
#[rust_analyzer::rust_fixture] ra_fixture: &str,
|
||||||
|
path: &str,
|
||||||
|
expect: Expect,
|
||||||
|
) {
|
||||||
check_found_path_(ra_fixture, path, false, true, false, expect);
|
check_found_path_(ra_fixture, path, false, true, false, expect);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn check_found_path_prefer_no_std(ra_fixture: &str, path: &str, expect: Expect) {
|
fn check_found_path_prefer_no_std(
|
||||||
|
#[rust_analyzer::rust_fixture] ra_fixture: &str,
|
||||||
|
path: &str,
|
||||||
|
expect: Expect,
|
||||||
|
) {
|
||||||
check_found_path_(ra_fixture, path, false, false, true, expect);
|
check_found_path_(ra_fixture, path, false, false, true, expect);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -509,7 +509,12 @@ mod tests {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn check_search(ra_fixture: &str, crate_name: &str, query: Query, expect: Expect) {
|
fn check_search(
|
||||||
|
#[rust_analyzer::rust_fixture] ra_fixture: &str,
|
||||||
|
crate_name: &str,
|
||||||
|
query: Query,
|
||||||
|
expect: Expect,
|
||||||
|
) {
|
||||||
let db = TestDB::with_files(ra_fixture);
|
let db = TestDB::with_files(ra_fixture);
|
||||||
let crate_graph = db.crate_graph();
|
let crate_graph = db.crate_graph();
|
||||||
let krate = crate_graph
|
let krate = crate_graph
|
||||||
@ -587,7 +592,7 @@ mod tests {
|
|||||||
))
|
))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn check(ra_fixture: &str, expect: Expect) {
|
fn check(#[rust_analyzer::rust_fixture] ra_fixture: &str, expect: Expect) {
|
||||||
let db = TestDB::with_files(ra_fixture);
|
let db = TestDB::with_files(ra_fixture);
|
||||||
let crate_graph = db.crate_graph();
|
let crate_graph = db.crate_graph();
|
||||||
|
|
||||||
|
@ -162,6 +162,20 @@ impl ItemScope {
|
|||||||
.map(move |name| (name, self.get(name)))
|
.map(move |name| (name, self.get(name)))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn values(&self) -> impl Iterator<Item = (&Name, Item<ModuleDefId, ImportId>)> + '_ {
|
||||||
|
self.values.iter().map(|(n, &i)| (n, i))
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn types(
|
||||||
|
&self,
|
||||||
|
) -> impl Iterator<Item = (&Name, Item<ModuleDefId, ImportOrExternCrate>)> + '_ {
|
||||||
|
self.types.iter().map(|(n, &i)| (n, i))
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn macros(&self) -> impl Iterator<Item = (&Name, Item<MacroId, ImportId>)> + '_ {
|
||||||
|
self.macros.iter().map(|(n, &i)| (n, i))
|
||||||
|
}
|
||||||
|
|
||||||
pub fn imports(&self) -> impl Iterator<Item = ImportId> + '_ {
|
pub fn imports(&self) -> impl Iterator<Item = ImportId> + '_ {
|
||||||
self.use_imports_types
|
self.use_imports_types
|
||||||
.keys()
|
.keys()
|
||||||
@ -263,11 +277,6 @@ impl ItemScope {
|
|||||||
self.unnamed_consts.iter().copied()
|
self.unnamed_consts.iter().copied()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Iterate over all module scoped macros
|
|
||||||
pub(crate) fn macros(&self) -> impl Iterator<Item = (&Name, MacroId)> + '_ {
|
|
||||||
self.entries().filter_map(|(name, def)| def.take_macros().map(|macro_| (name, macro_)))
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Iterate over all legacy textual scoped macros visible at the end of the module
|
/// Iterate over all legacy textual scoped macros visible at the end of the module
|
||||||
pub fn legacy_macros(&self) -> impl Iterator<Item = (&Name, &[MacroId])> + '_ {
|
pub fn legacy_macros(&self) -> impl Iterator<Item = (&Name, &[MacroId])> + '_ {
|
||||||
self.legacy_macros.iter().map(|(name, def)| (name, &**def))
|
self.legacy_macros.iter().map(|(name, def)| (name, &**def))
|
||||||
|
@ -4,7 +4,7 @@ use test_fixture::WithFixture;
|
|||||||
|
|
||||||
use crate::{db::DefDatabase, test_db::TestDB};
|
use crate::{db::DefDatabase, test_db::TestDB};
|
||||||
|
|
||||||
fn check(ra_fixture: &str, expect: Expect) {
|
fn check(#[rust_analyzer::rust_fixture] ra_fixture: &str, expect: Expect) {
|
||||||
let (db, file_id) = TestDB::with_single_file(ra_fixture);
|
let (db, file_id) = TestDB::with_single_file(ra_fixture);
|
||||||
let item_tree = db.file_item_tree(file_id.into());
|
let item_tree = db.file_item_tree(file_id.into());
|
||||||
let pretty = item_tree.pretty_print(&db, Edition::CURRENT);
|
let pretty = item_tree.pretty_print(&db, Edition::CURRENT);
|
||||||
@ -270,7 +270,7 @@ m!();
|
|||||||
// AstId: 2
|
// AstId: 2
|
||||||
pub macro m2 { ... }
|
pub macro m2 { ... }
|
||||||
|
|
||||||
// AstId: 3, SyntaxContext: 0, ExpandTo: Items
|
// AstId: 3, SyntaxContext: 2, ExpandTo: Items
|
||||||
m!(...);
|
m!(...);
|
||||||
"#]],
|
"#]],
|
||||||
);
|
);
|
||||||
|
@ -107,7 +107,7 @@ impl LangItems {
|
|||||||
for (_, module_data) in crate_def_map.modules() {
|
for (_, module_data) in crate_def_map.modules() {
|
||||||
for impl_def in module_data.scope.impls() {
|
for impl_def in module_data.scope.impls() {
|
||||||
lang_items.collect_lang_item(db, impl_def, LangItemTarget::ImplDef);
|
lang_items.collect_lang_item(db, impl_def, LangItemTarget::ImplDef);
|
||||||
for assoc in db.impl_data(impl_def).items.iter().copied() {
|
for &(_, assoc) in db.impl_data(impl_def).items.iter() {
|
||||||
match assoc {
|
match assoc {
|
||||||
AssocItemId::FunctionId(f) => {
|
AssocItemId::FunctionId(f) => {
|
||||||
lang_items.collect_lang_item(db, f, LangItemTarget::Function)
|
lang_items.collect_lang_item(db, f, LangItemTarget::Function)
|
||||||
|
@ -502,7 +502,7 @@ impl ModuleId {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Whether this module represents the crate root module
|
/// Whether this module represents the crate root module
|
||||||
fn is_crate_root(&self) -> bool {
|
pub fn is_crate_root(&self) -> bool {
|
||||||
self.local_id == DefMap::ROOT && self.block.is_none()
|
self.local_id == DefMap::ROOT && self.block.is_none()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -35,9 +35,9 @@ macro_rules! f {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
struct#0:1@58..64#1# MyTraitMap2#0:2@31..42#0# {#0:1@72..73#1#
|
struct#0:1@58..64#4# MyTraitMap2#0:2@31..42#2# {#0:1@72..73#4#
|
||||||
map#0:1@86..89#1#:#0:1@89..90#1# #0:1@89..90#1#::#0:1@91..93#1#std#0:1@93..96#1#::#0:1@96..98#1#collections#0:1@98..109#1#::#0:1@109..111#1#HashSet#0:1@111..118#1#<#0:1@118..119#1#(#0:1@119..120#1#)#0:1@120..121#1#>#0:1@121..122#1#,#0:1@122..123#1#
|
map#0:1@86..89#4#:#0:1@89..90#4# #0:1@89..90#4#::#0:1@91..93#4#std#0:1@93..96#4#::#0:1@96..98#4#collections#0:1@98..109#4#::#0:1@109..111#4#HashSet#0:1@111..118#4#<#0:1@118..119#4#(#0:1@119..120#4#)#0:1@120..121#4#>#0:1@121..122#4#,#0:1@122..123#4#
|
||||||
}#0:1@132..133#1#
|
}#0:1@132..133#4#
|
||||||
"#]],
|
"#]],
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -75,12 +75,12 @@ macro_rules! f {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
fn#0:2@30..32#0# main#0:2@33..37#0#(#0:2@37..38#0#)#0:2@38..39#0# {#0:2@40..41#0#
|
fn#0:2@30..32#2# main#0:2@33..37#2#(#0:2@37..38#2#)#0:2@38..39#2# {#0:2@40..41#2#
|
||||||
1#0:2@50..51#0#;#0:2@51..52#0#
|
1#0:2@50..51#2#;#0:2@51..52#2#
|
||||||
1.0#0:2@61..64#0#;#0:2@64..65#0#
|
1.0#0:2@61..64#2#;#0:2@64..65#2#
|
||||||
(#0:2@74..75#0#(#0:2@75..76#0#1#0:2@76..77#0#,#0:2@77..78#0# )#0:2@78..79#0#,#0:2@79..80#0# )#0:2@80..81#0#.#0:2@81..82#0#0#0:2@82..85#0#.#0:2@82..85#0#0#0:2@82..85#0#;#0:2@85..86#0#
|
(#0:2@74..75#2#(#0:2@75..76#2#1#0:2@76..77#2#,#0:2@77..78#2# )#0:2@78..79#2#,#0:2@79..80#2# )#0:2@80..81#2#.#0:2@81..82#2#0#0:2@82..85#2#.#0:2@82..85#2#0#0:2@82..85#2#;#0:2@85..86#2#
|
||||||
let#0:2@95..98#0# x#0:2@99..100#0# =#0:2@101..102#0# 1#0:2@103..104#0#;#0:2@104..105#0#
|
let#0:2@95..98#2# x#0:2@99..100#2# =#0:2@101..102#2# 1#0:2@103..104#2#;#0:2@104..105#2#
|
||||||
}#0:2@110..111#0#
|
}#0:2@110..111#2#
|
||||||
|
|
||||||
|
|
||||||
"#]],
|
"#]],
|
||||||
@ -171,7 +171,7 @@ fn main(foo: ()) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn main(foo: ()) {
|
fn main(foo: ()) {
|
||||||
/* error: unresolved macro unresolved */"helloworld!"#0:3@236..321#0#;
|
/* error: unresolved macro unresolved */"helloworld!"#0:3@236..321#2#;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -197,7 +197,7 @@ macro_rules! mk_struct {
|
|||||||
#[macro_use]
|
#[macro_use]
|
||||||
mod foo;
|
mod foo;
|
||||||
|
|
||||||
struct#1:1@59..65#1# Foo#0:2@32..35#0#(#1:1@70..71#1#u32#0:2@41..44#0#)#1:1@74..75#1#;#1:1@75..76#1#
|
struct#1:1@59..65#4# Foo#0:2@32..35#2#(#1:1@70..71#4#u32#0:2@41..44#2#)#1:1@74..75#4#;#1:1@75..76#4#
|
||||||
"#]],
|
"#]],
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -423,10 +423,10 @@ m! { foo, bar }
|
|||||||
macro_rules! m {
|
macro_rules! m {
|
||||||
($($i:ident),*) => ( impl Bar { $(fn $i() {})* } );
|
($($i:ident),*) => ( impl Bar { $(fn $i() {})* } );
|
||||||
}
|
}
|
||||||
impl#\1# Bar#\1# {#\1#
|
impl#\4# Bar#\4# {#\4#
|
||||||
fn#\1# foo#\0#(#\1#)#\1# {#\1#}#\1#
|
fn#\4# foo#\2#(#\4#)#\4# {#\4#}#\4#
|
||||||
fn#\1# bar#\0#(#\1#)#\1# {#\1#}#\1#
|
fn#\4# bar#\2#(#\4#)#\4# {#\4#}#\4#
|
||||||
}#\1#
|
}#\4#
|
||||||
"#]],
|
"#]],
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -47,7 +47,7 @@ use crate::{
|
|||||||
};
|
};
|
||||||
|
|
||||||
#[track_caller]
|
#[track_caller]
|
||||||
fn check_errors(ra_fixture: &str, expect: Expect) {
|
fn check_errors(#[rust_analyzer::rust_fixture] ra_fixture: &str, expect: Expect) {
|
||||||
let db = TestDB::with_files(ra_fixture);
|
let db = TestDB::with_files(ra_fixture);
|
||||||
let krate = db.fetch_test_crate();
|
let krate = db.fetch_test_crate();
|
||||||
let def_map = db.crate_def_map(krate);
|
let def_map = db.crate_def_map(krate);
|
||||||
@ -77,7 +77,7 @@ fn check_errors(ra_fixture: &str, expect: Expect) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[track_caller]
|
#[track_caller]
|
||||||
fn check(ra_fixture: &str, mut expect: Expect) {
|
fn check(#[rust_analyzer::rust_fixture] ra_fixture: &str, mut expect: Expect) {
|
||||||
let extra_proc_macros = vec![(
|
let extra_proc_macros = vec![(
|
||||||
r#"
|
r#"
|
||||||
#[proc_macro_attribute]
|
#[proc_macro_attribute]
|
||||||
@ -358,6 +358,7 @@ impl ProcMacroExpander for IdentityWhenValidProcMacroExpander {
|
|||||||
let (parse, _) = syntax_bridge::token_tree_to_syntax_node(
|
let (parse, _) = syntax_bridge::token_tree_to_syntax_node(
|
||||||
subtree,
|
subtree,
|
||||||
syntax_bridge::TopEntryPoint::MacroItems,
|
syntax_bridge::TopEntryPoint::MacroItems,
|
||||||
|
&mut |_| span::Edition::CURRENT,
|
||||||
span::Edition::CURRENT,
|
span::Edition::CURRENT,
|
||||||
);
|
);
|
||||||
if parse.errors().is_empty() {
|
if parse.errors().is_empty() {
|
||||||
|
@ -181,9 +181,9 @@ fn foo(&self) {
|
|||||||
self.0. 1;
|
self.0. 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn#0:1@45..47#0# foo#0:1@48..51#0#(#0:1@51..52#0#�:1@52..53#0#self#0:1@53..57#0# )#0:1@57..58#0# {#0:1@59..60#0#
|
fn#0:1@45..47#2# foo#0:1@48..51#2#(#0:1@51..52#2#�:1@52..53#2#self#0:1@53..57#2# )#0:1@57..58#2# {#0:1@59..60#2#
|
||||||
self#0:1@65..69#0# .#0:1@69..70#0#0#0:1@70..71#0#.#0:1@71..72#0#1#0:1@73..74#0#;#0:1@74..75#0#
|
self#0:1@65..69#2# .#0:1@69..70#2#0#0:1@70..71#2#.#0:1@71..72#2#1#0:1@73..74#2#;#0:1@74..75#2#
|
||||||
}#0:1@76..77#0#"#]],
|
}#0:1@76..77#2#"#]],
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -74,7 +74,7 @@ pub(super) fn collect_defs(db: &dyn DefDatabase, def_map: DefMap, tree_id: TreeI
|
|||||||
|
|
||||||
let proc_macros = if krate.is_proc_macro {
|
let proc_macros = if krate.is_proc_macro {
|
||||||
db.proc_macros()
|
db.proc_macros()
|
||||||
.for_crate(def_map.krate, db.syntax_context(tree_id.file_id()))
|
.for_crate(def_map.krate, db.syntax_context(tree_id.file_id(), krate.edition))
|
||||||
.unwrap_or_default()
|
.unwrap_or_default()
|
||||||
} else {
|
} else {
|
||||||
Default::default()
|
Default::default()
|
||||||
@ -717,8 +717,8 @@ impl DefCollector<'_> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
None => {
|
None => {
|
||||||
for (name, def) in root_scope.macros() {
|
for (name, it) in root_scope.macros() {
|
||||||
self.def_map.macro_use_prelude.insert(name.clone(), (def, extern_crate));
|
self.def_map.macro_use_prelude.insert(name.clone(), (it.def, extern_crate));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -11,19 +11,19 @@ use triomphe::Arc;
|
|||||||
|
|
||||||
use crate::{db::DefDatabase, nameres::DefMap, test_db::TestDB};
|
use crate::{db::DefDatabase, nameres::DefMap, test_db::TestDB};
|
||||||
|
|
||||||
fn compute_crate_def_map(ra_fixture: &str) -> Arc<DefMap> {
|
fn compute_crate_def_map(#[rust_analyzer::rust_fixture] ra_fixture: &str) -> Arc<DefMap> {
|
||||||
let db = TestDB::with_files(ra_fixture);
|
let db = TestDB::with_files(ra_fixture);
|
||||||
let krate = db.fetch_test_crate();
|
let krate = db.fetch_test_crate();
|
||||||
db.crate_def_map(krate)
|
db.crate_def_map(krate)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn render_crate_def_map(ra_fixture: &str) -> String {
|
fn render_crate_def_map(#[rust_analyzer::rust_fixture] ra_fixture: &str) -> String {
|
||||||
let db = TestDB::with_files(ra_fixture);
|
let db = TestDB::with_files(ra_fixture);
|
||||||
let krate = db.fetch_test_crate();
|
let krate = db.fetch_test_crate();
|
||||||
db.crate_def_map(krate).dump(&db)
|
db.crate_def_map(krate).dump(&db)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn check(ra_fixture: &str, expect: Expect) {
|
fn check(#[rust_analyzer::rust_fixture] ra_fixture: &str, expect: Expect) {
|
||||||
let actual = render_crate_def_map(ra_fixture);
|
let actual = render_crate_def_map(ra_fixture);
|
||||||
expect.assert_eq(&actual);
|
expect.assert_eq(&actual);
|
||||||
}
|
}
|
||||||
|
@ -166,6 +166,17 @@ impl Resolver {
|
|||||||
db: &dyn DefDatabase,
|
db: &dyn DefDatabase,
|
||||||
path: &Path,
|
path: &Path,
|
||||||
) -> Option<(TypeNs, Option<usize>, Option<ImportOrExternCrate>)> {
|
) -> Option<(TypeNs, Option<usize>, Option<ImportOrExternCrate>)> {
|
||||||
|
self.resolve_path_in_type_ns_with_prefix_info(db, path).map(
|
||||||
|
|(resolution, remaining_segments, import, _)| (resolution, remaining_segments, import),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn resolve_path_in_type_ns_with_prefix_info(
|
||||||
|
&self,
|
||||||
|
db: &dyn DefDatabase,
|
||||||
|
path: &Path,
|
||||||
|
) -> Option<(TypeNs, Option<usize>, Option<ImportOrExternCrate>, ResolvePathResultPrefixInfo)>
|
||||||
|
{
|
||||||
let path = match path {
|
let path = match path {
|
||||||
Path::BarePath(mod_path) => mod_path,
|
Path::BarePath(mod_path) => mod_path,
|
||||||
Path::Normal(it) => it.mod_path(),
|
Path::Normal(it) => it.mod_path(),
|
||||||
@ -181,7 +192,12 @@ impl Resolver {
|
|||||||
| LangItemTarget::ImplDef(_)
|
| LangItemTarget::ImplDef(_)
|
||||||
| LangItemTarget::Static(_) => return None,
|
| LangItemTarget::Static(_) => return None,
|
||||||
};
|
};
|
||||||
return Some((type_ns, seg.as_ref().map(|_| 1), None));
|
return Some((
|
||||||
|
type_ns,
|
||||||
|
seg.as_ref().map(|_| 1),
|
||||||
|
None,
|
||||||
|
ResolvePathResultPrefixInfo::default(),
|
||||||
|
));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
let first_name = path.segments().first()?;
|
let first_name = path.segments().first()?;
|
||||||
@ -197,17 +213,32 @@ impl Resolver {
|
|||||||
Scope::ExprScope(_) | Scope::MacroDefScope(_) => continue,
|
Scope::ExprScope(_) | Scope::MacroDefScope(_) => continue,
|
||||||
Scope::GenericParams { params, def } => {
|
Scope::GenericParams { params, def } => {
|
||||||
if let Some(id) = params.find_type_by_name(first_name, *def) {
|
if let Some(id) = params.find_type_by_name(first_name, *def) {
|
||||||
return Some((TypeNs::GenericParam(id), remaining_idx(), None));
|
return Some((
|
||||||
|
TypeNs::GenericParam(id),
|
||||||
|
remaining_idx(),
|
||||||
|
None,
|
||||||
|
ResolvePathResultPrefixInfo::default(),
|
||||||
|
));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
&Scope::ImplDefScope(impl_) => {
|
&Scope::ImplDefScope(impl_) => {
|
||||||
if *first_name == sym::Self_.clone() {
|
if *first_name == sym::Self_.clone() {
|
||||||
return Some((TypeNs::SelfType(impl_), remaining_idx(), None));
|
return Some((
|
||||||
|
TypeNs::SelfType(impl_),
|
||||||
|
remaining_idx(),
|
||||||
|
None,
|
||||||
|
ResolvePathResultPrefixInfo::default(),
|
||||||
|
));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
&Scope::AdtScope(adt) => {
|
&Scope::AdtScope(adt) => {
|
||||||
if *first_name == sym::Self_.clone() {
|
if *first_name == sym::Self_.clone() {
|
||||||
return Some((TypeNs::AdtSelfType(adt), remaining_idx(), None));
|
return Some((
|
||||||
|
TypeNs::AdtSelfType(adt),
|
||||||
|
remaining_idx(),
|
||||||
|
None,
|
||||||
|
ResolvePathResultPrefixInfo::default(),
|
||||||
|
));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Scope::BlockScope(m) => {
|
Scope::BlockScope(m) => {
|
||||||
@ -220,18 +251,6 @@ impl Resolver {
|
|||||||
self.module_scope.resolve_path_in_type_ns(db, path)
|
self.module_scope.resolve_path_in_type_ns(db, path)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn resolve_path_in_type_ns_fully_with_imports(
|
|
||||||
&self,
|
|
||||||
db: &dyn DefDatabase,
|
|
||||||
path: &Path,
|
|
||||||
) -> Option<(TypeNs, Option<ImportOrExternCrate>)> {
|
|
||||||
let (res, unresolved, imp) = self.resolve_path_in_type_ns(db, path)?;
|
|
||||||
if unresolved.is_some() {
|
|
||||||
return None;
|
|
||||||
}
|
|
||||||
Some((res, imp))
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn resolve_path_in_type_ns_fully(
|
pub fn resolve_path_in_type_ns_fully(
|
||||||
&self,
|
&self,
|
||||||
db: &dyn DefDatabase,
|
db: &dyn DefDatabase,
|
||||||
@ -324,7 +343,7 @@ impl Resolver {
|
|||||||
|
|
||||||
if n_segments <= 1 {
|
if n_segments <= 1 {
|
||||||
let mut hygiene_info = if !hygiene_id.is_root() {
|
let mut hygiene_info = if !hygiene_id.is_root() {
|
||||||
let ctx = db.lookup_intern_syntax_context(hygiene_id.0);
|
let ctx = hygiene_id.lookup(db);
|
||||||
ctx.outer_expn.map(|expansion| {
|
ctx.outer_expn.map(|expansion| {
|
||||||
let expansion = db.lookup_intern_macro_call(expansion);
|
let expansion = db.lookup_intern_macro_call(expansion);
|
||||||
(ctx.parent, expansion.def)
|
(ctx.parent, expansion.def)
|
||||||
@ -986,11 +1005,12 @@ impl ModuleItemMap {
|
|||||||
&self,
|
&self,
|
||||||
db: &dyn DefDatabase,
|
db: &dyn DefDatabase,
|
||||||
path: &ModPath,
|
path: &ModPath,
|
||||||
) -> Option<(TypeNs, Option<usize>, Option<ImportOrExternCrate>)> {
|
) -> Option<(TypeNs, Option<usize>, Option<ImportOrExternCrate>, ResolvePathResultPrefixInfo)>
|
||||||
let (module_def, idx, _) =
|
{
|
||||||
|
let (module_def, idx, prefix_info) =
|
||||||
self.def_map.resolve_path_locally(db, self.module_id, path, BuiltinShadowMode::Other);
|
self.def_map.resolve_path_locally(db, self.module_id, path, BuiltinShadowMode::Other);
|
||||||
let (res, import) = to_type_ns(module_def)?;
|
let (res, import) = to_type_ns(module_def)?;
|
||||||
Some((res, idx, import))
|
Some((res, idx, import, prefix_info))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -240,12 +240,12 @@ impl Visibility {
|
|||||||
|
|
||||||
if a_ancestors.any(|m| m == mod_b.local_id) {
|
if a_ancestors.any(|m| m == mod_b.local_id) {
|
||||||
// B is above A
|
// B is above A
|
||||||
return Some(Visibility::Module(mod_a, expl_b));
|
return Some(Visibility::Module(mod_a, expl_a));
|
||||||
}
|
}
|
||||||
|
|
||||||
if b_ancestors.any(|m| m == mod_a.local_id) {
|
if b_ancestors.any(|m| m == mod_a.local_id) {
|
||||||
// A is above B
|
// A is above B
|
||||||
return Some(Visibility::Module(mod_b, expl_a));
|
return Some(Visibility::Module(mod_b, expl_b));
|
||||||
}
|
}
|
||||||
|
|
||||||
None
|
None
|
||||||
|
@ -4,7 +4,7 @@ use intern::sym;
|
|||||||
use itertools::{izip, Itertools};
|
use itertools::{izip, Itertools};
|
||||||
use parser::SyntaxKind;
|
use parser::SyntaxKind;
|
||||||
use rustc_hash::FxHashSet;
|
use rustc_hash::FxHashSet;
|
||||||
use span::{MacroCallId, Span, SyntaxContextId};
|
use span::{Edition, MacroCallId, Span, SyntaxContextId};
|
||||||
use stdx::never;
|
use stdx::never;
|
||||||
use syntax_bridge::DocCommentDesugarMode;
|
use syntax_bridge::DocCommentDesugarMode;
|
||||||
use tracing::debug;
|
use tracing::debug;
|
||||||
@ -33,7 +33,7 @@ macro_rules! register_builtin {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl BuiltinDeriveExpander {
|
impl BuiltinDeriveExpander {
|
||||||
pub fn expander(&self) -> fn(Span, &tt::TopSubtree) -> ExpandResult<tt::TopSubtree> {
|
pub fn expander(&self) -> fn(&dyn ExpandDatabase, Span, &tt::TopSubtree) -> ExpandResult<tt::TopSubtree> {
|
||||||
match *self {
|
match *self {
|
||||||
$( BuiltinDeriveExpander::$trait => $expand, )*
|
$( BuiltinDeriveExpander::$trait => $expand, )*
|
||||||
}
|
}
|
||||||
@ -58,8 +58,8 @@ impl BuiltinDeriveExpander {
|
|||||||
tt: &tt::TopSubtree,
|
tt: &tt::TopSubtree,
|
||||||
span: Span,
|
span: Span,
|
||||||
) -> ExpandResult<tt::TopSubtree> {
|
) -> ExpandResult<tt::TopSubtree> {
|
||||||
let span = span_with_def_site_ctxt(db, span, id);
|
let span = span_with_def_site_ctxt(db, span, id, Edition::CURRENT);
|
||||||
self.expander()(span, tt)
|
self.expander()(db, span, tt)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -226,8 +226,12 @@ struct AdtParam {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// FIXME: This whole thing needs a refactor. Each derive requires its special values, and the result is a mess.
|
// FIXME: This whole thing needs a refactor. Each derive requires its special values, and the result is a mess.
|
||||||
fn parse_adt(tt: &tt::TopSubtree, call_site: Span) -> Result<BasicAdtInfo, ExpandError> {
|
fn parse_adt(
|
||||||
let (adt, tm) = to_adt_syntax(tt, call_site)?;
|
db: &dyn ExpandDatabase,
|
||||||
|
tt: &tt::TopSubtree,
|
||||||
|
call_site: Span,
|
||||||
|
) -> Result<BasicAdtInfo, ExpandError> {
|
||||||
|
let (adt, tm) = to_adt_syntax(db, tt, call_site)?;
|
||||||
parse_adt_from_syntax(&adt, &tm, call_site)
|
parse_adt_from_syntax(&adt, &tm, call_site)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -382,12 +386,14 @@ fn parse_adt_from_syntax(
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn to_adt_syntax(
|
fn to_adt_syntax(
|
||||||
|
db: &dyn ExpandDatabase,
|
||||||
tt: &tt::TopSubtree,
|
tt: &tt::TopSubtree,
|
||||||
call_site: Span,
|
call_site: Span,
|
||||||
) -> Result<(ast::Adt, span::SpanMap<SyntaxContextId>), ExpandError> {
|
) -> Result<(ast::Adt, span::SpanMap<SyntaxContextId>), ExpandError> {
|
||||||
let (parsed, tm) = syntax_bridge::token_tree_to_syntax_node(
|
let (parsed, tm) = crate::db::token_tree_to_syntax_node(
|
||||||
|
db,
|
||||||
tt,
|
tt,
|
||||||
syntax_bridge::TopEntryPoint::MacroItems,
|
crate::ExpandTo::Items,
|
||||||
parser::Edition::CURRENT_FIXME,
|
parser::Edition::CURRENT_FIXME,
|
||||||
);
|
);
|
||||||
let macro_items = ast::MacroItems::cast(parsed.syntax_node())
|
let macro_items = ast::MacroItems::cast(parsed.syntax_node())
|
||||||
@ -446,12 +452,13 @@ fn name_to_token(
|
|||||||
/// where B1, ..., BN are the bounds given by `bounds_paths`. Z is a phantom type, and
|
/// where B1, ..., BN are the bounds given by `bounds_paths`. Z is a phantom type, and
|
||||||
/// therefore does not get bound by the derived trait.
|
/// therefore does not get bound by the derived trait.
|
||||||
fn expand_simple_derive(
|
fn expand_simple_derive(
|
||||||
|
db: &dyn ExpandDatabase,
|
||||||
invoc_span: Span,
|
invoc_span: Span,
|
||||||
tt: &tt::TopSubtree,
|
tt: &tt::TopSubtree,
|
||||||
trait_path: tt::TopSubtree,
|
trait_path: tt::TopSubtree,
|
||||||
make_trait_body: impl FnOnce(&BasicAdtInfo) -> tt::TopSubtree,
|
make_trait_body: impl FnOnce(&BasicAdtInfo) -> tt::TopSubtree,
|
||||||
) -> ExpandResult<tt::TopSubtree> {
|
) -> ExpandResult<tt::TopSubtree> {
|
||||||
let info = match parse_adt(tt, invoc_span) {
|
let info = match parse_adt(db, tt, invoc_span) {
|
||||||
Ok(info) => info,
|
Ok(info) => info,
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
return ExpandResult::new(
|
return ExpandResult::new(
|
||||||
@ -520,14 +527,22 @@ fn expand_simple_derive_with_parsed(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn copy_expand(span: Span, tt: &tt::TopSubtree) -> ExpandResult<tt::TopSubtree> {
|
fn copy_expand(
|
||||||
|
db: &dyn ExpandDatabase,
|
||||||
|
span: Span,
|
||||||
|
tt: &tt::TopSubtree,
|
||||||
|
) -> ExpandResult<tt::TopSubtree> {
|
||||||
let krate = dollar_crate(span);
|
let krate = dollar_crate(span);
|
||||||
expand_simple_derive(span, tt, quote! {span => #krate::marker::Copy }, |_| quote! {span =>})
|
expand_simple_derive(db, span, tt, quote! {span => #krate::marker::Copy }, |_| quote! {span =>})
|
||||||
}
|
}
|
||||||
|
|
||||||
fn clone_expand(span: Span, tt: &tt::TopSubtree) -> ExpandResult<tt::TopSubtree> {
|
fn clone_expand(
|
||||||
|
db: &dyn ExpandDatabase,
|
||||||
|
span: Span,
|
||||||
|
tt: &tt::TopSubtree,
|
||||||
|
) -> ExpandResult<tt::TopSubtree> {
|
||||||
let krate = dollar_crate(span);
|
let krate = dollar_crate(span);
|
||||||
expand_simple_derive(span, tt, quote! {span => #krate::clone::Clone }, |adt| {
|
expand_simple_derive(db, span, tt, quote! {span => #krate::clone::Clone }, |adt| {
|
||||||
if matches!(adt.shape, AdtShape::Union) {
|
if matches!(adt.shape, AdtShape::Union) {
|
||||||
let star = tt::Punct { char: '*', spacing: ::tt::Spacing::Alone, span };
|
let star = tt::Punct { char: '*', spacing: ::tt::Spacing::Alone, span };
|
||||||
return quote! {span =>
|
return quote! {span =>
|
||||||
@ -576,9 +591,13 @@ fn and_and(span: Span) -> tt::TopSubtree {
|
|||||||
quote! {span => #and& }
|
quote! {span => #and& }
|
||||||
}
|
}
|
||||||
|
|
||||||
fn default_expand(span: Span, tt: &tt::TopSubtree) -> ExpandResult<tt::TopSubtree> {
|
fn default_expand(
|
||||||
|
db: &dyn ExpandDatabase,
|
||||||
|
span: Span,
|
||||||
|
tt: &tt::TopSubtree,
|
||||||
|
) -> ExpandResult<tt::TopSubtree> {
|
||||||
let krate = &dollar_crate(span);
|
let krate = &dollar_crate(span);
|
||||||
expand_simple_derive(span, tt, quote! {span => #krate::default::Default }, |adt| {
|
expand_simple_derive(db, span, tt, quote! {span => #krate::default::Default }, |adt| {
|
||||||
let body = match &adt.shape {
|
let body = match &adt.shape {
|
||||||
AdtShape::Struct(fields) => {
|
AdtShape::Struct(fields) => {
|
||||||
let name = &adt.name;
|
let name = &adt.name;
|
||||||
@ -615,9 +634,13 @@ fn default_expand(span: Span, tt: &tt::TopSubtree) -> ExpandResult<tt::TopSubtre
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
fn debug_expand(span: Span, tt: &tt::TopSubtree) -> ExpandResult<tt::TopSubtree> {
|
fn debug_expand(
|
||||||
|
db: &dyn ExpandDatabase,
|
||||||
|
span: Span,
|
||||||
|
tt: &tt::TopSubtree,
|
||||||
|
) -> ExpandResult<tt::TopSubtree> {
|
||||||
let krate = &dollar_crate(span);
|
let krate = &dollar_crate(span);
|
||||||
expand_simple_derive(span, tt, quote! {span => #krate::fmt::Debug }, |adt| {
|
expand_simple_derive(db, span, tt, quote! {span => #krate::fmt::Debug }, |adt| {
|
||||||
let for_variant = |name: String, v: &VariantShape| match v {
|
let for_variant = |name: String, v: &VariantShape| match v {
|
||||||
VariantShape::Struct(fields) => {
|
VariantShape::Struct(fields) => {
|
||||||
let for_fields = fields.iter().map(|it| {
|
let for_fields = fields.iter().map(|it| {
|
||||||
@ -687,9 +710,13 @@ fn debug_expand(span: Span, tt: &tt::TopSubtree) -> ExpandResult<tt::TopSubtree>
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
fn hash_expand(span: Span, tt: &tt::TopSubtree) -> ExpandResult<tt::TopSubtree> {
|
fn hash_expand(
|
||||||
|
db: &dyn ExpandDatabase,
|
||||||
|
span: Span,
|
||||||
|
tt: &tt::TopSubtree,
|
||||||
|
) -> ExpandResult<tt::TopSubtree> {
|
||||||
let krate = &dollar_crate(span);
|
let krate = &dollar_crate(span);
|
||||||
expand_simple_derive(span, tt, quote! {span => #krate::hash::Hash }, |adt| {
|
expand_simple_derive(db, span, tt, quote! {span => #krate::hash::Hash }, |adt| {
|
||||||
if matches!(adt.shape, AdtShape::Union) {
|
if matches!(adt.shape, AdtShape::Union) {
|
||||||
// FIXME: Return expand error here
|
// FIXME: Return expand error here
|
||||||
return quote! {span =>};
|
return quote! {span =>};
|
||||||
@ -734,14 +761,22 @@ fn hash_expand(span: Span, tt: &tt::TopSubtree) -> ExpandResult<tt::TopSubtree>
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
fn eq_expand(span: Span, tt: &tt::TopSubtree) -> ExpandResult<tt::TopSubtree> {
|
fn eq_expand(
|
||||||
|
db: &dyn ExpandDatabase,
|
||||||
|
span: Span,
|
||||||
|
tt: &tt::TopSubtree,
|
||||||
|
) -> ExpandResult<tt::TopSubtree> {
|
||||||
let krate = dollar_crate(span);
|
let krate = dollar_crate(span);
|
||||||
expand_simple_derive(span, tt, quote! {span => #krate::cmp::Eq }, |_| quote! {span =>})
|
expand_simple_derive(db, span, tt, quote! {span => #krate::cmp::Eq }, |_| quote! {span =>})
|
||||||
}
|
}
|
||||||
|
|
||||||
fn partial_eq_expand(span: Span, tt: &tt::TopSubtree) -> ExpandResult<tt::TopSubtree> {
|
fn partial_eq_expand(
|
||||||
|
db: &dyn ExpandDatabase,
|
||||||
|
span: Span,
|
||||||
|
tt: &tt::TopSubtree,
|
||||||
|
) -> ExpandResult<tt::TopSubtree> {
|
||||||
let krate = dollar_crate(span);
|
let krate = dollar_crate(span);
|
||||||
expand_simple_derive(span, tt, quote! {span => #krate::cmp::PartialEq }, |adt| {
|
expand_simple_derive(db, span, tt, quote! {span => #krate::cmp::PartialEq }, |adt| {
|
||||||
if matches!(adt.shape, AdtShape::Union) {
|
if matches!(adt.shape, AdtShape::Union) {
|
||||||
// FIXME: Return expand error here
|
// FIXME: Return expand error here
|
||||||
return quote! {span =>};
|
return quote! {span =>};
|
||||||
@ -811,9 +846,13 @@ fn self_and_other_patterns(
|
|||||||
(self_patterns, other_patterns)
|
(self_patterns, other_patterns)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn ord_expand(span: Span, tt: &tt::TopSubtree) -> ExpandResult<tt::TopSubtree> {
|
fn ord_expand(
|
||||||
|
db: &dyn ExpandDatabase,
|
||||||
|
span: Span,
|
||||||
|
tt: &tt::TopSubtree,
|
||||||
|
) -> ExpandResult<tt::TopSubtree> {
|
||||||
let krate = &dollar_crate(span);
|
let krate = &dollar_crate(span);
|
||||||
expand_simple_derive(span, tt, quote! {span => #krate::cmp::Ord }, |adt| {
|
expand_simple_derive(db, span, tt, quote! {span => #krate::cmp::Ord }, |adt| {
|
||||||
fn compare(
|
fn compare(
|
||||||
krate: &tt::Ident,
|
krate: &tt::Ident,
|
||||||
left: tt::TopSubtree,
|
left: tt::TopSubtree,
|
||||||
@ -869,9 +908,13 @@ fn ord_expand(span: Span, tt: &tt::TopSubtree) -> ExpandResult<tt::TopSubtree> {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
fn partial_ord_expand(span: Span, tt: &tt::TopSubtree) -> ExpandResult<tt::TopSubtree> {
|
fn partial_ord_expand(
|
||||||
|
db: &dyn ExpandDatabase,
|
||||||
|
span: Span,
|
||||||
|
tt: &tt::TopSubtree,
|
||||||
|
) -> ExpandResult<tt::TopSubtree> {
|
||||||
let krate = &dollar_crate(span);
|
let krate = &dollar_crate(span);
|
||||||
expand_simple_derive(span, tt, quote! {span => #krate::cmp::PartialOrd }, |adt| {
|
expand_simple_derive(db, span, tt, quote! {span => #krate::cmp::PartialOrd }, |adt| {
|
||||||
fn compare(
|
fn compare(
|
||||||
krate: &tt::Ident,
|
krate: &tt::Ident,
|
||||||
left: tt::TopSubtree,
|
left: tt::TopSubtree,
|
||||||
@ -932,8 +975,12 @@ fn partial_ord_expand(span: Span, tt: &tt::TopSubtree) -> ExpandResult<tt::TopSu
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
fn coerce_pointee_expand(span: Span, tt: &tt::TopSubtree) -> ExpandResult<tt::TopSubtree> {
|
fn coerce_pointee_expand(
|
||||||
let (adt, _span_map) = match to_adt_syntax(tt, span) {
|
db: &dyn ExpandDatabase,
|
||||||
|
span: Span,
|
||||||
|
tt: &tt::TopSubtree,
|
||||||
|
) -> ExpandResult<tt::TopSubtree> {
|
||||||
|
let (adt, _span_map) = match to_adt_syntax(db, tt, span) {
|
||||||
Ok(it) => it,
|
Ok(it) => it,
|
||||||
Err(err) => {
|
Err(err) => {
|
||||||
return ExpandResult::new(tt::TopSubtree::empty(tt::DelimSpan::from_single(span)), err);
|
return ExpandResult::new(tt::TopSubtree::empty(tt::DelimSpan::from_single(span)), err);
|
||||||
|
@ -69,7 +69,7 @@ impl BuiltinFnLikeExpander {
|
|||||||
tt: &tt::TopSubtree,
|
tt: &tt::TopSubtree,
|
||||||
span: Span,
|
span: Span,
|
||||||
) -> ExpandResult<tt::TopSubtree> {
|
) -> ExpandResult<tt::TopSubtree> {
|
||||||
let span = span_with_def_site_ctxt(db, span, id);
|
let span = span_with_def_site_ctxt(db, span, id, Edition::CURRENT);
|
||||||
self.expander()(db, id, tt, span)
|
self.expander()(db, id, tt, span)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -86,7 +86,7 @@ impl EagerExpander {
|
|||||||
tt: &tt::TopSubtree,
|
tt: &tt::TopSubtree,
|
||||||
span: Span,
|
span: Span,
|
||||||
) -> ExpandResult<tt::TopSubtree> {
|
) -> ExpandResult<tt::TopSubtree> {
|
||||||
let span = span_with_def_site_ctxt(db, span, id);
|
let span = span_with_def_site_ctxt(db, span, id, Edition::CURRENT);
|
||||||
self.expander()(db, id, tt, span)
|
self.expander()(db, id, tt, span)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -221,7 +221,7 @@ fn assert_expand(
|
|||||||
tt: &tt::TopSubtree,
|
tt: &tt::TopSubtree,
|
||||||
span: Span,
|
span: Span,
|
||||||
) -> ExpandResult<tt::TopSubtree> {
|
) -> ExpandResult<tt::TopSubtree> {
|
||||||
let call_site_span = span_with_call_site_ctxt(db, span, id);
|
let call_site_span = span_with_call_site_ctxt(db, span, id, Edition::CURRENT);
|
||||||
|
|
||||||
let mut iter = tt.iter();
|
let mut iter = tt.iter();
|
||||||
|
|
||||||
@ -342,7 +342,7 @@ fn panic_expand(
|
|||||||
span: Span,
|
span: Span,
|
||||||
) -> ExpandResult<tt::TopSubtree> {
|
) -> ExpandResult<tt::TopSubtree> {
|
||||||
let dollar_crate = dollar_crate(span);
|
let dollar_crate = dollar_crate(span);
|
||||||
let call_site_span = span_with_call_site_ctxt(db, span, id);
|
let call_site_span = span_with_call_site_ctxt(db, span, id, Edition::CURRENT);
|
||||||
|
|
||||||
let mac = if use_panic_2021(db, call_site_span) {
|
let mac = if use_panic_2021(db, call_site_span) {
|
||||||
sym::panic_2021.clone()
|
sym::panic_2021.clone()
|
||||||
@ -373,7 +373,7 @@ fn unreachable_expand(
|
|||||||
span: Span,
|
span: Span,
|
||||||
) -> ExpandResult<tt::TopSubtree> {
|
) -> ExpandResult<tt::TopSubtree> {
|
||||||
let dollar_crate = dollar_crate(span);
|
let dollar_crate = dollar_crate(span);
|
||||||
let call_site_span = span_with_call_site_ctxt(db, span, id);
|
let call_site_span = span_with_call_site_ctxt(db, span, id, Edition::CURRENT);
|
||||||
|
|
||||||
let mac = if use_panic_2021(db, call_site_span) {
|
let mac = if use_panic_2021(db, call_site_span) {
|
||||||
sym::unreachable_2021.clone()
|
sym::unreachable_2021.clone()
|
||||||
|
@ -102,6 +102,7 @@ macro_rules! quote_impl__ {
|
|||||||
($span:ident $builder:ident # ) => {$crate::builtin::quote::__quote!(@PUNCT($span $builder) '#')};
|
($span:ident $builder:ident # ) => {$crate::builtin::quote::__quote!(@PUNCT($span $builder) '#')};
|
||||||
($span:ident $builder:ident $ ) => {$crate::builtin::quote::__quote!(@PUNCT($span $builder) '$')};
|
($span:ident $builder:ident $ ) => {$crate::builtin::quote::__quote!(@PUNCT($span $builder) '$')};
|
||||||
($span:ident $builder:ident * ) => {$crate::builtin::quote::__quote!(@PUNCT($span $builder) '*')};
|
($span:ident $builder:ident * ) => {$crate::builtin::quote::__quote!(@PUNCT($span $builder) '*')};
|
||||||
|
($span:ident $builder:ident = ) => {$crate::builtin::quote::__quote!(@PUNCT($span $builder) '=')};
|
||||||
|
|
||||||
($span:ident $builder:ident $first:tt $($tail:tt)+ ) => {{
|
($span:ident $builder:ident $first:tt $($tail:tt)+ ) => {{
|
||||||
$crate::builtin::quote::__quote!($span $builder $first);
|
$crate::builtin::quote::__quote!($span $builder $first);
|
||||||
@ -225,7 +226,7 @@ mod tests {
|
|||||||
use ::tt::IdentIsRaw;
|
use ::tt::IdentIsRaw;
|
||||||
use expect_test::expect;
|
use expect_test::expect;
|
||||||
use intern::Symbol;
|
use intern::Symbol;
|
||||||
use span::{SpanAnchor, SyntaxContextId, ROOT_ERASED_FILE_AST_ID};
|
use span::{Edition, SpanAnchor, SyntaxContextId, ROOT_ERASED_FILE_AST_ID};
|
||||||
use syntax::{TextRange, TextSize};
|
use syntax::{TextRange, TextSize};
|
||||||
|
|
||||||
use super::quote;
|
use super::quote;
|
||||||
@ -239,7 +240,7 @@ mod tests {
|
|||||||
),
|
),
|
||||||
ast_id: ROOT_ERASED_FILE_AST_ID,
|
ast_id: ROOT_ERASED_FILE_AST_ID,
|
||||||
},
|
},
|
||||||
ctx: SyntaxContextId::ROOT,
|
ctx: SyntaxContextId::root(Edition::CURRENT),
|
||||||
};
|
};
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
@ -276,8 +277,8 @@ mod tests {
|
|||||||
assert_eq!(quoted.to_string(), "hello");
|
assert_eq!(quoted.to_string(), "hello");
|
||||||
let t = format!("{quoted:#?}");
|
let t = format!("{quoted:#?}");
|
||||||
expect![[r#"
|
expect![[r#"
|
||||||
SUBTREE $$ 937550:0@0..0#0 937550:0@0..0#0
|
SUBTREE $$ 937550:0@0..0#2 937550:0@0..0#2
|
||||||
IDENT hello 937550:0@0..0#0"#]]
|
IDENT hello 937550:0@0..0#2"#]]
|
||||||
.assert_eq(&t);
|
.assert_eq(&t);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -5,7 +5,7 @@ use either::Either;
|
|||||||
use limit::Limit;
|
use limit::Limit;
|
||||||
use mbe::MatchedArmIndex;
|
use mbe::MatchedArmIndex;
|
||||||
use rustc_hash::FxHashSet;
|
use rustc_hash::FxHashSet;
|
||||||
use span::{AstIdMap, EditionedFileId, Span, SyntaxContextData, SyntaxContextId};
|
use span::{AstIdMap, Edition, EditionedFileId, Span, SyntaxContextData, SyntaxContextId};
|
||||||
use syntax::{ast, AstNode, Parse, SyntaxElement, SyntaxError, SyntaxNode, SyntaxToken, T};
|
use syntax::{ast, AstNode, Parse, SyntaxElement, SyntaxError, SyntaxNode, SyntaxToken, T};
|
||||||
use syntax_bridge::{syntax_node_to_token_tree, DocCommentDesugarMode};
|
use syntax_bridge::{syntax_node_to_token_tree, DocCommentDesugarMode};
|
||||||
use triomphe::Arc;
|
use triomphe::Arc;
|
||||||
@ -136,12 +136,12 @@ pub trait ExpandDatabase: SourceDatabase {
|
|||||||
macro_call: MacroCallId,
|
macro_call: MacroCallId,
|
||||||
) -> Option<Arc<ExpandResult<Arc<[SyntaxError]>>>>;
|
) -> Option<Arc<ExpandResult<Arc<[SyntaxError]>>>>;
|
||||||
#[ra_salsa::transparent]
|
#[ra_salsa::transparent]
|
||||||
fn syntax_context(&self, file: HirFileId) -> SyntaxContextId;
|
fn syntax_context(&self, file: HirFileId, edition: Edition) -> SyntaxContextId;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn syntax_context(db: &dyn ExpandDatabase, file: HirFileId) -> SyntaxContextId {
|
fn syntax_context(db: &dyn ExpandDatabase, file: HirFileId, edition: Edition) -> SyntaxContextId {
|
||||||
match file.repr() {
|
match file.repr() {
|
||||||
HirFileIdRepr::FileId(_) => SyntaxContextId::ROOT,
|
HirFileIdRepr::FileId(_) => SyntaxContextId::root(edition),
|
||||||
HirFileIdRepr::MacroFile(m) => {
|
HirFileIdRepr::MacroFile(m) => {
|
||||||
db.macro_arg_considering_derives(m.macro_call_id, &m.macro_call_id.lookup(db).kind)
|
db.macro_arg_considering_derives(m.macro_call_id, &m.macro_call_id.lookup(db).kind)
|
||||||
.2
|
.2
|
||||||
@ -273,9 +273,9 @@ pub fn expand_speculative(
|
|||||||
loc.krate,
|
loc.krate,
|
||||||
&tt,
|
&tt,
|
||||||
attr_arg.as_ref(),
|
attr_arg.as_ref(),
|
||||||
span_with_def_site_ctxt(db, span, actual_macro_call),
|
span_with_def_site_ctxt(db, span, actual_macro_call, loc.def.edition),
|
||||||
span_with_call_site_ctxt(db, span, actual_macro_call),
|
span_with_call_site_ctxt(db, span, actual_macro_call, loc.def.edition),
|
||||||
span_with_mixed_site_ctxt(db, span, actual_macro_call),
|
span_with_mixed_site_ctxt(db, span, actual_macro_call, loc.def.edition),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
MacroDefKind::BuiltInAttr(_, it) if it.is_derive() => {
|
MacroDefKind::BuiltInAttr(_, it) if it.is_derive() => {
|
||||||
@ -300,7 +300,7 @@ pub fn expand_speculative(
|
|||||||
|
|
||||||
fixup::reverse_fixups(&mut speculative_expansion.value, &undo_info);
|
fixup::reverse_fixups(&mut speculative_expansion.value, &undo_info);
|
||||||
let (node, rev_tmap) =
|
let (node, rev_tmap) =
|
||||||
token_tree_to_syntax_node(&speculative_expansion.value, expand_to, loc.def.edition);
|
token_tree_to_syntax_node(db, &speculative_expansion.value, expand_to, loc.def.edition);
|
||||||
|
|
||||||
let syntax_node = node.syntax_node();
|
let syntax_node = node.syntax_node();
|
||||||
let token = rev_tmap
|
let token = rev_tmap
|
||||||
@ -346,6 +346,7 @@ fn parse_macro_expansion(
|
|||||||
macro_expand(db, macro_file.macro_call_id, loc);
|
macro_expand(db, macro_file.macro_call_id, loc);
|
||||||
|
|
||||||
let (parse, mut rev_token_map) = token_tree_to_syntax_node(
|
let (parse, mut rev_token_map) = token_tree_to_syntax_node(
|
||||||
|
db,
|
||||||
match &tt {
|
match &tt {
|
||||||
CowArc::Arc(it) => it,
|
CowArc::Arc(it) => it,
|
||||||
CowArc::Owned(it) => it,
|
CowArc::Owned(it) => it,
|
||||||
@ -699,9 +700,9 @@ fn expand_proc_macro(
|
|||||||
loc.krate,
|
loc.krate,
|
||||||
¯o_arg,
|
¯o_arg,
|
||||||
attr_arg,
|
attr_arg,
|
||||||
span_with_def_site_ctxt(db, span, id),
|
span_with_def_site_ctxt(db, span, id, loc.def.edition),
|
||||||
span_with_call_site_ctxt(db, span, id),
|
span_with_call_site_ctxt(db, span, id, loc.def.edition),
|
||||||
span_with_mixed_site_ctxt(db, span, id),
|
span_with_mixed_site_ctxt(db, span, id, loc.def.edition),
|
||||||
)
|
)
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -715,7 +716,8 @@ fn expand_proc_macro(
|
|||||||
ExpandResult { value: Arc::new(tt), err }
|
ExpandResult { value: Arc::new(tt), err }
|
||||||
}
|
}
|
||||||
|
|
||||||
fn token_tree_to_syntax_node(
|
pub(crate) fn token_tree_to_syntax_node(
|
||||||
|
db: &dyn ExpandDatabase,
|
||||||
tt: &tt::TopSubtree,
|
tt: &tt::TopSubtree,
|
||||||
expand_to: ExpandTo,
|
expand_to: ExpandTo,
|
||||||
edition: parser::Edition,
|
edition: parser::Edition,
|
||||||
@ -727,7 +729,12 @@ fn token_tree_to_syntax_node(
|
|||||||
ExpandTo::Type => syntax_bridge::TopEntryPoint::Type,
|
ExpandTo::Type => syntax_bridge::TopEntryPoint::Type,
|
||||||
ExpandTo::Expr => syntax_bridge::TopEntryPoint::Expr,
|
ExpandTo::Expr => syntax_bridge::TopEntryPoint::Expr,
|
||||||
};
|
};
|
||||||
syntax_bridge::token_tree_to_syntax_node(tt, entry_point, edition)
|
syntax_bridge::token_tree_to_syntax_node(
|
||||||
|
tt,
|
||||||
|
entry_point,
|
||||||
|
&mut |ctx| ctx.lookup(db).edition,
|
||||||
|
edition,
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn check_tt_count(tt: &tt::TopSubtree) -> Result<(), ExpandResult<()>> {
|
fn check_tt_count(tt: &tt::TopSubtree) -> Result<(), ExpandResult<()>> {
|
||||||
@ -751,5 +758,7 @@ fn check_tt_count(tt: &tt::TopSubtree) -> Result<(), ExpandResult<()>> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn setup_syntax_context_root(db: &dyn ExpandDatabase) {
|
fn setup_syntax_context_root(db: &dyn ExpandDatabase) {
|
||||||
db.intern_syntax_context(SyntaxContextData::root());
|
for edition in Edition::iter() {
|
||||||
|
db.intern_syntax_context(SyntaxContextData::root(edition));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
use base_db::CrateId;
|
use base_db::CrateId;
|
||||||
use intern::sym;
|
use intern::sym;
|
||||||
use span::{Edition, MacroCallId, Span, SyntaxContextId};
|
use span::{Edition, HirFileIdRepr, MacroCallId, Span, SyntaxContextId};
|
||||||
use stdx::TupleExt;
|
use stdx::TupleExt;
|
||||||
use syntax::{ast, AstNode};
|
use syntax::{ast, AstNode};
|
||||||
use syntax_bridge::DocCommentDesugarMode;
|
use syntax_bridge::DocCommentDesugarMode;
|
||||||
@ -20,6 +20,7 @@ use crate::{
|
|||||||
pub struct DeclarativeMacroExpander {
|
pub struct DeclarativeMacroExpander {
|
||||||
pub mac: mbe::DeclarativeMacro,
|
pub mac: mbe::DeclarativeMacro,
|
||||||
pub transparency: Transparency,
|
pub transparency: Transparency,
|
||||||
|
edition: Edition,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl DeclarativeMacroExpander {
|
impl DeclarativeMacroExpander {
|
||||||
@ -40,7 +41,7 @@ impl DeclarativeMacroExpander {
|
|||||||
.mac
|
.mac
|
||||||
.expand(
|
.expand(
|
||||||
&tt,
|
&tt,
|
||||||
|s| s.ctx = apply_mark(db, s.ctx, call_id, self.transparency),
|
|s| s.ctx = apply_mark(db, s.ctx, call_id, self.transparency, self.edition),
|
||||||
span,
|
span,
|
||||||
loc.def.edition,
|
loc.def.edition,
|
||||||
)
|
)
|
||||||
@ -159,6 +160,10 @@ impl DeclarativeMacroExpander {
|
|||||||
transparency(¯o_def).unwrap_or(Transparency::Opaque),
|
transparency(¯o_def).unwrap_or(Transparency::Opaque),
|
||||||
),
|
),
|
||||||
};
|
};
|
||||||
Arc::new(DeclarativeMacroExpander { mac, transparency })
|
let edition = ctx_edition(match id.file_id.repr() {
|
||||||
|
HirFileIdRepr::MacroFile(macro_file) => macro_file.macro_call_id.lookup(db).ctxt,
|
||||||
|
HirFileIdRepr::FileId(file) => SyntaxContextId::root(file.edition()),
|
||||||
|
});
|
||||||
|
Arc::new(DeclarativeMacroExpander { mac, transparency, edition })
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -380,14 +380,14 @@ impl InFile<TextRange> {
|
|||||||
) -> (FileRange, SyntaxContextId) {
|
) -> (FileRange, SyntaxContextId) {
|
||||||
match self.file_id.repr() {
|
match self.file_id.repr() {
|
||||||
HirFileIdRepr::FileId(file_id) => {
|
HirFileIdRepr::FileId(file_id) => {
|
||||||
(FileRange { file_id, range: self.value }, SyntaxContextId::ROOT)
|
(FileRange { file_id, range: self.value }, SyntaxContextId::root(file_id.edition()))
|
||||||
}
|
}
|
||||||
HirFileIdRepr::MacroFile(mac_file) => {
|
HirFileIdRepr::MacroFile(mac_file) => {
|
||||||
match map_node_range_up(db, &db.expansion_span_map(mac_file), self.value) {
|
match map_node_range_up(db, &db.expansion_span_map(mac_file), self.value) {
|
||||||
Some(it) => it,
|
Some(it) => it,
|
||||||
None => {
|
None => {
|
||||||
let loc = db.lookup_intern_macro_call(mac_file.macro_call_id);
|
let loc = db.lookup_intern_macro_call(mac_file.macro_call_id);
|
||||||
(loc.kind.original_call_range(db), SyntaxContextId::ROOT)
|
(loc.kind.original_call_range(db), SyntaxContextId::root(loc.def.edition))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -432,9 +432,10 @@ impl InFile<TextRange> {
|
|||||||
db: &dyn db::ExpandDatabase,
|
db: &dyn db::ExpandDatabase,
|
||||||
) -> Option<(FileRange, SyntaxContextId)> {
|
) -> Option<(FileRange, SyntaxContextId)> {
|
||||||
match self.file_id.repr() {
|
match self.file_id.repr() {
|
||||||
HirFileIdRepr::FileId(file_id) => {
|
HirFileIdRepr::FileId(file_id) => Some((
|
||||||
Some((FileRange { file_id, range: self.value }, SyntaxContextId::ROOT))
|
FileRange { file_id, range: self.value },
|
||||||
}
|
SyntaxContextId::root(file_id.edition()),
|
||||||
|
)),
|
||||||
HirFileIdRepr::MacroFile(mac_file) => {
|
HirFileIdRepr::MacroFile(mac_file) => {
|
||||||
map_node_range_up(db, &db.expansion_span_map(mac_file), self.value)
|
map_node_range_up(db, &db.expansion_span_map(mac_file), self.value)
|
||||||
}
|
}
|
||||||
|
@ -380,7 +380,7 @@ pub(crate) fn reverse_fixups(tt: &mut TopSubtree, undo_info: &SyntaxFixupUndoInf
|
|||||||
let span = |file_id| Span {
|
let span = |file_id| Span {
|
||||||
range: TextRange::empty(TextSize::new(0)),
|
range: TextRange::empty(TextSize::new(0)),
|
||||||
anchor: SpanAnchor { file_id, ast_id: ROOT_ERASED_FILE_AST_ID },
|
anchor: SpanAnchor { file_id, ast_id: ROOT_ERASED_FILE_AST_ID },
|
||||||
ctx: SyntaxContextId::ROOT,
|
ctx: SyntaxContextId::root(span::Edition::Edition2015),
|
||||||
};
|
};
|
||||||
delimiter.open = span(delimiter.open.anchor.file_id);
|
delimiter.open = span(delimiter.open.anchor.file_id);
|
||||||
delimiter.close = span(delimiter.close.anchor.file_id);
|
delimiter.close = span(delimiter.close.anchor.file_id);
|
||||||
@ -441,8 +441,8 @@ fn transform_tt<'a, 'b>(
|
|||||||
};
|
};
|
||||||
let len_diff = replacement.len() as i64 - old_len as i64;
|
let len_diff = replacement.len() as i64 - old_len as i64;
|
||||||
tt.splice(i..i + old_len, replacement.flat_tokens().iter().cloned());
|
tt.splice(i..i + old_len, replacement.flat_tokens().iter().cloned());
|
||||||
// `+1` for the loop.
|
// Skip the newly inserted replacement, we don't want to visit it.
|
||||||
i = i.checked_add_signed(len_diff as isize + 1).unwrap();
|
i += replacement.len();
|
||||||
|
|
||||||
for &subtree_idx in &subtrees_stack {
|
for &subtree_idx in &subtrees_stack {
|
||||||
let tt::TokenTree::Subtree(subtree) = &mut tt[subtree_idx] else {
|
let tt::TokenTree::Subtree(subtree) = &mut tt[subtree_idx] else {
|
||||||
@ -532,7 +532,7 @@ mod tests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[track_caller]
|
#[track_caller]
|
||||||
fn check(ra_fixture: &str, mut expect: Expect) {
|
fn check(#[rust_analyzer::rust_fixture] ra_fixture: &str, mut expect: Expect) {
|
||||||
let parsed = syntax::SourceFile::parse(ra_fixture, span::Edition::CURRENT);
|
let parsed = syntax::SourceFile::parse(ra_fixture, span::Edition::CURRENT);
|
||||||
let span_map = SpanMap::RealSpanMap(Arc::new(RealSpanMap::absolute(EditionedFileId::new(
|
let span_map = SpanMap::RealSpanMap(Arc::new(RealSpanMap::absolute(EditionedFileId::new(
|
||||||
FileId::from_raw(0),
|
FileId::from_raw(0),
|
||||||
@ -562,6 +562,7 @@ mod tests {
|
|||||||
let (parse, _) = syntax_bridge::token_tree_to_syntax_node(
|
let (parse, _) = syntax_bridge::token_tree_to_syntax_node(
|
||||||
&tt,
|
&tt,
|
||||||
syntax_bridge::TopEntryPoint::MacroItems,
|
syntax_bridge::TopEntryPoint::MacroItems,
|
||||||
|
&mut |_| parser::Edition::CURRENT,
|
||||||
parser::Edition::CURRENT,
|
parser::Edition::CURRENT,
|
||||||
);
|
);
|
||||||
assert!(
|
assert!(
|
||||||
|
@ -24,26 +24,37 @@
|
|||||||
|
|
||||||
use std::iter;
|
use std::iter;
|
||||||
|
|
||||||
use span::{MacroCallId, Span, SyntaxContextData, SyntaxContextId};
|
use span::{Edition, MacroCallId, Span, SyntaxContextData, SyntaxContextId};
|
||||||
|
|
||||||
use crate::db::{ExpandDatabase, InternSyntaxContextQuery};
|
use crate::db::{ExpandDatabase, InternSyntaxContextQuery};
|
||||||
|
|
||||||
pub use span::Transparency;
|
pub use span::Transparency;
|
||||||
|
|
||||||
pub fn span_with_def_site_ctxt(db: &dyn ExpandDatabase, span: Span, expn_id: MacroCallId) -> Span {
|
pub fn span_with_def_site_ctxt(
|
||||||
span_with_ctxt_from_mark(db, span, expn_id, Transparency::Opaque)
|
db: &dyn ExpandDatabase,
|
||||||
|
span: Span,
|
||||||
|
expn_id: MacroCallId,
|
||||||
|
edition: Edition,
|
||||||
|
) -> Span {
|
||||||
|
span_with_ctxt_from_mark(db, span, expn_id, Transparency::Opaque, edition)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn span_with_call_site_ctxt(db: &dyn ExpandDatabase, span: Span, expn_id: MacroCallId) -> Span {
|
pub fn span_with_call_site_ctxt(
|
||||||
span_with_ctxt_from_mark(db, span, expn_id, Transparency::Transparent)
|
db: &dyn ExpandDatabase,
|
||||||
|
span: Span,
|
||||||
|
expn_id: MacroCallId,
|
||||||
|
edition: Edition,
|
||||||
|
) -> Span {
|
||||||
|
span_with_ctxt_from_mark(db, span, expn_id, Transparency::Transparent, edition)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn span_with_mixed_site_ctxt(
|
pub fn span_with_mixed_site_ctxt(
|
||||||
db: &dyn ExpandDatabase,
|
db: &dyn ExpandDatabase,
|
||||||
span: Span,
|
span: Span,
|
||||||
expn_id: MacroCallId,
|
expn_id: MacroCallId,
|
||||||
|
edition: Edition,
|
||||||
) -> Span {
|
) -> Span {
|
||||||
span_with_ctxt_from_mark(db, span, expn_id, Transparency::SemiTransparent)
|
span_with_ctxt_from_mark(db, span, expn_id, Transparency::SemiTransparent, edition)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn span_with_ctxt_from_mark(
|
fn span_with_ctxt_from_mark(
|
||||||
@ -51,8 +62,12 @@ fn span_with_ctxt_from_mark(
|
|||||||
span: Span,
|
span: Span,
|
||||||
expn_id: MacroCallId,
|
expn_id: MacroCallId,
|
||||||
transparency: Transparency,
|
transparency: Transparency,
|
||||||
|
edition: Edition,
|
||||||
) -> Span {
|
) -> Span {
|
||||||
Span { ctx: apply_mark(db, SyntaxContextId::ROOT, expn_id, transparency), ..span }
|
Span {
|
||||||
|
ctx: apply_mark(db, SyntaxContextId::root(edition), expn_id, transparency, edition),
|
||||||
|
..span
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(super) fn apply_mark(
|
pub(super) fn apply_mark(
|
||||||
@ -60,9 +75,10 @@ pub(super) fn apply_mark(
|
|||||||
ctxt: SyntaxContextId,
|
ctxt: SyntaxContextId,
|
||||||
call_id: MacroCallId,
|
call_id: MacroCallId,
|
||||||
transparency: Transparency,
|
transparency: Transparency,
|
||||||
|
edition: Edition,
|
||||||
) -> SyntaxContextId {
|
) -> SyntaxContextId {
|
||||||
if transparency == Transparency::Opaque {
|
if transparency == Transparency::Opaque {
|
||||||
return apply_mark_internal(db, ctxt, call_id, transparency);
|
return apply_mark_internal(db, ctxt, call_id, transparency, edition);
|
||||||
}
|
}
|
||||||
|
|
||||||
let call_site_ctxt = db.lookup_intern_macro_call(call_id).ctxt;
|
let call_site_ctxt = db.lookup_intern_macro_call(call_id).ctxt;
|
||||||
@ -73,7 +89,7 @@ pub(super) fn apply_mark(
|
|||||||
};
|
};
|
||||||
|
|
||||||
if call_site_ctxt.is_root() {
|
if call_site_ctxt.is_root() {
|
||||||
return apply_mark_internal(db, ctxt, call_id, transparency);
|
return apply_mark_internal(db, ctxt, call_id, transparency, edition);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Otherwise, `expn_id` is a macros 1.0 definition and the call site is in a
|
// Otherwise, `expn_id` is a macros 1.0 definition and the call site is in a
|
||||||
@ -86,9 +102,9 @@ pub(super) fn apply_mark(
|
|||||||
//
|
//
|
||||||
// See the example at `test/ui/hygiene/legacy_interaction.rs`.
|
// See the example at `test/ui/hygiene/legacy_interaction.rs`.
|
||||||
for (call_id, transparency) in ctxt.marks(db) {
|
for (call_id, transparency) in ctxt.marks(db) {
|
||||||
call_site_ctxt = apply_mark_internal(db, call_site_ctxt, call_id, transparency);
|
call_site_ctxt = apply_mark_internal(db, call_site_ctxt, call_id, transparency, edition);
|
||||||
}
|
}
|
||||||
apply_mark_internal(db, call_site_ctxt, call_id, transparency)
|
apply_mark_internal(db, call_site_ctxt, call_id, transparency, edition)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn apply_mark_internal(
|
fn apply_mark_internal(
|
||||||
@ -96,6 +112,7 @@ fn apply_mark_internal(
|
|||||||
ctxt: SyntaxContextId,
|
ctxt: SyntaxContextId,
|
||||||
call_id: MacroCallId,
|
call_id: MacroCallId,
|
||||||
transparency: Transparency,
|
transparency: Transparency,
|
||||||
|
edition: Edition,
|
||||||
) -> SyntaxContextId {
|
) -> SyntaxContextId {
|
||||||
use base_db::ra_salsa;
|
use base_db::ra_salsa;
|
||||||
|
|
||||||
@ -108,13 +125,14 @@ fn apply_mark_internal(
|
|||||||
if transparency >= Transparency::Opaque {
|
if transparency >= Transparency::Opaque {
|
||||||
let parent = opaque;
|
let parent = opaque;
|
||||||
opaque = ra_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),
|
(parent, call_id, transparency, edition),
|
||||||
|new_opaque| SyntaxContextData {
|
|new_opaque| SyntaxContextData {
|
||||||
outer_expn: call_id,
|
outer_expn: call_id,
|
||||||
outer_transparency: transparency,
|
outer_transparency: transparency,
|
||||||
parent,
|
parent,
|
||||||
opaque: new_opaque,
|
opaque: new_opaque,
|
||||||
opaque_and_semitransparent: new_opaque,
|
opaque_and_semitransparent: new_opaque,
|
||||||
|
edition,
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -123,13 +141,14 @@ fn apply_mark_internal(
|
|||||||
let parent = opaque_and_semitransparent;
|
let parent = opaque_and_semitransparent;
|
||||||
opaque_and_semitransparent =
|
opaque_and_semitransparent =
|
||||||
ra_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),
|
(parent, call_id, transparency, edition),
|
||||||
|new_opaque_and_semitransparent| SyntaxContextData {
|
|new_opaque_and_semitransparent| SyntaxContextData {
|
||||||
outer_expn: call_id,
|
outer_expn: call_id,
|
||||||
outer_transparency: transparency,
|
outer_transparency: transparency,
|
||||||
parent,
|
parent,
|
||||||
opaque,
|
opaque,
|
||||||
opaque_and_semitransparent: new_opaque_and_semitransparent,
|
opaque_and_semitransparent: new_opaque_and_semitransparent,
|
||||||
|
edition,
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -141,6 +160,7 @@ fn apply_mark_internal(
|
|||||||
parent,
|
parent,
|
||||||
opaque,
|
opaque,
|
||||||
opaque_and_semitransparent,
|
opaque_and_semitransparent,
|
||||||
|
edition,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -188,6 +188,8 @@ impl fmt::Display for RenderedExpandError {
|
|||||||
|
|
||||||
impl RenderedExpandError {
|
impl RenderedExpandError {
|
||||||
const GENERAL_KIND: &str = "macro-error";
|
const GENERAL_KIND: &str = "macro-error";
|
||||||
|
const DISABLED: &str = "proc-macro-disabled";
|
||||||
|
const ATTR_EXP_DISABLED: &str = "attribute-expansion-disabled";
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ExpandErrorKind {
|
impl ExpandErrorKind {
|
||||||
@ -196,12 +198,12 @@ impl ExpandErrorKind {
|
|||||||
ExpandErrorKind::ProcMacroAttrExpansionDisabled => RenderedExpandError {
|
ExpandErrorKind::ProcMacroAttrExpansionDisabled => RenderedExpandError {
|
||||||
message: "procedural attribute macro expansion is disabled".to_owned(),
|
message: "procedural attribute macro expansion is disabled".to_owned(),
|
||||||
error: false,
|
error: false,
|
||||||
kind: "proc-macros-disabled",
|
kind: RenderedExpandError::ATTR_EXP_DISABLED,
|
||||||
},
|
},
|
||||||
ExpandErrorKind::MacroDisabled => RenderedExpandError {
|
ExpandErrorKind::MacroDisabled => RenderedExpandError {
|
||||||
message: "proc-macro is explicitly disabled".to_owned(),
|
message: "proc-macro is explicitly disabled".to_owned(),
|
||||||
error: false,
|
error: false,
|
||||||
kind: "proc-macro-disabled",
|
kind: RenderedExpandError::DISABLED,
|
||||||
},
|
},
|
||||||
&ExpandErrorKind::MissingProcMacroExpander(def_crate) => {
|
&ExpandErrorKind::MissingProcMacroExpander(def_crate) => {
|
||||||
match db.proc_macros().get_error_for_crate(def_crate) {
|
match db.proc_macros().get_error_for_crate(def_crate) {
|
||||||
|
@ -273,10 +273,9 @@ fn convert_path(
|
|||||||
res
|
res
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ast::PathSegmentKind::SelfTypeKw => ModPath::from_segments(
|
ast::PathSegmentKind::SelfTypeKw => {
|
||||||
PathKind::Plain,
|
ModPath::from_segments(PathKind::Plain, Some(Name::new_symbol_root(sym::Self_.clone())))
|
||||||
Some(Name::new_symbol(sym::Self_.clone(), SyntaxContextId::ROOT)),
|
}
|
||||||
),
|
|
||||||
ast::PathSegmentKind::CrateKw => ModPath::from_segments(PathKind::Crate, iter::empty()),
|
ast::PathSegmentKind::CrateKw => ModPath::from_segments(PathKind::Crate, iter::empty()),
|
||||||
ast::PathSegmentKind::SelfKw => handle_super_kw(0)?,
|
ast::PathSegmentKind::SelfKw => handle_super_kw(0)?,
|
||||||
ast::PathSegmentKind::SuperKw => handle_super_kw(1)?,
|
ast::PathSegmentKind::SuperKw => handle_super_kw(1)?,
|
||||||
@ -399,6 +398,9 @@ macro_rules! __known_path {
|
|||||||
(core::fmt::Debug) => {};
|
(core::fmt::Debug) => {};
|
||||||
(std::fmt::format) => {};
|
(std::fmt::format) => {};
|
||||||
(core::ops::Try) => {};
|
(core::ops::Try) => {};
|
||||||
|
(core::convert::From) => {};
|
||||||
|
(core::convert::TryFrom) => {};
|
||||||
|
(core::str::FromStr) => {};
|
||||||
($path:path) => {
|
($path:path) => {
|
||||||
compile_error!("Please register your known path in the path module")
|
compile_error!("Please register your known path in the path module")
|
||||||
};
|
};
|
||||||
@ -415,3 +417,14 @@ macro_rules! __path {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub use crate::__path as path;
|
pub use crate::__path as path;
|
||||||
|
|
||||||
|
#[macro_export]
|
||||||
|
macro_rules! __tool_path {
|
||||||
|
($start:ident $(:: $seg:ident)*) => ({
|
||||||
|
$crate::mod_path::ModPath::from_segments($crate::mod_path::PathKind::Plain, vec![
|
||||||
|
$crate::name::Name::new_symbol_root(intern::sym::rust_analyzer.clone()), $crate::name::Name::new_symbol_root(intern::sym::$start.clone()), $($crate::name::Name::new_symbol_root(intern::sym::$seg.clone()),)*
|
||||||
|
])
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
pub use crate::__tool_path as tool_path;
|
||||||
|
@ -11,7 +11,7 @@ use syntax::utils::is_raw_identifier;
|
|||||||
/// and declarations. In theory, names should also carry hygiene info, but we are
|
/// and declarations. In theory, names should also carry hygiene info, but we are
|
||||||
/// not there yet!
|
/// not there yet!
|
||||||
///
|
///
|
||||||
/// Note that the rawness (`r#`) of names does not depend on whether they are written raw.
|
/// Note that the rawness (`r#`) of names is not preserved. Names are always stored without a `r#` prefix.
|
||||||
/// This is because we want to show (in completions etc.) names as raw depending on the needs
|
/// This is because we want to show (in completions etc.) names as raw depending on the needs
|
||||||
/// of the current crate, for example if it is edition 2021 complete `gen` even if the defining
|
/// of the current crate, for example if it is edition 2021 complete `gen` even if the defining
|
||||||
/// crate is in edition 2024 and wrote `r#gen`, and the opposite holds as well.
|
/// crate is in edition 2024 and wrote `r#gen`, and the opposite holds as well.
|
||||||
@ -77,20 +77,49 @@ impl Name {
|
|||||||
/// Hopefully, this should allow us to integrate hygiene cleaner in the
|
/// Hopefully, this should allow us to integrate hygiene cleaner in the
|
||||||
/// future, and to switch to interned representation of names.
|
/// future, and to switch to interned representation of names.
|
||||||
fn new_text(text: &str) -> Name {
|
fn new_text(text: &str) -> Name {
|
||||||
|
debug_assert!(!text.starts_with("r#"));
|
||||||
Name { symbol: Symbol::intern(text), ctx: () }
|
Name { symbol: Symbol::intern(text), ctx: () }
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn new(text: &str, ctx: SyntaxContextId) -> Name {
|
pub fn new(text: &str, mut ctx: SyntaxContextId) -> Name {
|
||||||
|
// For comparisons etc. we remove the edition, because sometimes we search for some `Name`
|
||||||
|
// and we don't know which edition it came from.
|
||||||
|
// Can't do that for all `SyntaxContextId`s because it breaks Salsa.
|
||||||
|
ctx.remove_root_edition();
|
||||||
_ = ctx;
|
_ = ctx;
|
||||||
Self::new_text(text)
|
Self::new_text(text)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn new_root(text: &str) -> Name {
|
||||||
|
// The edition doesn't matter for hygiene.
|
||||||
|
Self::new(text.trim_start_matches("r#"), SyntaxContextId::root(Edition::Edition2015))
|
||||||
|
}
|
||||||
|
|
||||||
pub fn new_tuple_field(idx: usize) -> Name {
|
pub fn new_tuple_field(idx: usize) -> Name {
|
||||||
Name { symbol: Symbol::intern(&idx.to_string()), ctx: () }
|
let symbol = match idx {
|
||||||
|
0 => sym::INTEGER_0.clone(),
|
||||||
|
1 => sym::INTEGER_1.clone(),
|
||||||
|
2 => sym::INTEGER_2.clone(),
|
||||||
|
3 => sym::INTEGER_3.clone(),
|
||||||
|
4 => sym::INTEGER_4.clone(),
|
||||||
|
5 => sym::INTEGER_5.clone(),
|
||||||
|
6 => sym::INTEGER_6.clone(),
|
||||||
|
7 => sym::INTEGER_7.clone(),
|
||||||
|
8 => sym::INTEGER_8.clone(),
|
||||||
|
9 => sym::INTEGER_9.clone(),
|
||||||
|
10 => sym::INTEGER_10.clone(),
|
||||||
|
11 => sym::INTEGER_11.clone(),
|
||||||
|
12 => sym::INTEGER_12.clone(),
|
||||||
|
13 => sym::INTEGER_13.clone(),
|
||||||
|
14 => sym::INTEGER_14.clone(),
|
||||||
|
15 => sym::INTEGER_15.clone(),
|
||||||
|
_ => Symbol::intern(&idx.to_string()),
|
||||||
|
};
|
||||||
|
Name { symbol, ctx: () }
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn new_lifetime(lt: &ast::Lifetime) -> Name {
|
pub fn new_lifetime(lt: &ast::Lifetime) -> Name {
|
||||||
Name { symbol: Symbol::intern(lt.text().as_str()), ctx: () }
|
Self::new_text(lt.text().as_str().trim_start_matches("r#"))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Resolve a name from the text of token.
|
/// Resolve a name from the text of token.
|
||||||
@ -133,15 +162,18 @@ impl Name {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Returns the text this name represents if it isn't a tuple field.
|
/// Returns the text this name represents if it isn't a tuple field.
|
||||||
|
///
|
||||||
|
/// Do not use this for user-facing text, use `display` instead to handle editions properly.
|
||||||
pub fn as_str(&self) -> &str {
|
pub fn as_str(&self) -> &str {
|
||||||
self.symbol.as_str()
|
self.symbol.as_str()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// FIXME: Remove this
|
||||||
pub fn unescaped(&self) -> UnescapedName<'_> {
|
pub fn unescaped(&self) -> UnescapedName<'_> {
|
||||||
UnescapedName(self)
|
UnescapedName(self)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn is_escaped(&self, edition: Edition) -> bool {
|
pub fn needs_escape(&self, edition: Edition) -> bool {
|
||||||
is_raw_identifier(self.symbol.as_str(), edition)
|
is_raw_identifier(self.symbol.as_str(), edition)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -164,16 +196,19 @@ impl Name {
|
|||||||
&self.symbol
|
&self.symbol
|
||||||
}
|
}
|
||||||
|
|
||||||
pub const fn new_symbol(symbol: Symbol, ctx: SyntaxContextId) -> Self {
|
pub fn new_symbol(symbol: Symbol, ctx: SyntaxContextId) -> Self {
|
||||||
|
debug_assert!(!symbol.as_str().starts_with("r#"));
|
||||||
_ = ctx;
|
_ = ctx;
|
||||||
Self { symbol, ctx: () }
|
Self { symbol, ctx: () }
|
||||||
}
|
}
|
||||||
|
|
||||||
// FIXME: This needs to go once we have hygiene
|
// FIXME: This needs to go once we have hygiene
|
||||||
pub const fn new_symbol_root(sym: Symbol) -> Self {
|
pub fn new_symbol_root(sym: Symbol) -> Self {
|
||||||
|
debug_assert!(!sym.as_str().starts_with("r#"));
|
||||||
Self { symbol: sym, ctx: () }
|
Self { symbol: sym, ctx: () }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// FIXME: Remove this
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn eq_ident(&self, ident: &str) -> bool {
|
pub fn eq_ident(&self, ident: &str) -> bool {
|
||||||
self.as_str() == ident.trim_start_matches("r#")
|
self.as_str() == ident.trim_start_matches("r#")
|
||||||
|
@ -856,7 +856,7 @@ fn impl_def_datum(
|
|||||||
let associated_ty_value_ids = impl_data
|
let associated_ty_value_ids = impl_data
|
||||||
.items
|
.items
|
||||||
.iter()
|
.iter()
|
||||||
.filter_map(|item| match item {
|
.filter_map(|(_, item)| match item {
|
||||||
AssocItemId::TypeAliasId(type_alias) => Some(*type_alias),
|
AssocItemId::TypeAliasId(type_alias) => Some(*type_alias),
|
||||||
_ => None,
|
_ => None,
|
||||||
})
|
})
|
||||||
|
@ -31,7 +31,10 @@ fn simplify(e: ConstEvalError) -> ConstEvalError {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[track_caller]
|
#[track_caller]
|
||||||
fn check_fail(ra_fixture: &str, error: impl FnOnce(ConstEvalError) -> bool) {
|
fn check_fail(
|
||||||
|
#[rust_analyzer::rust_fixture] ra_fixture: &str,
|
||||||
|
error: impl FnOnce(ConstEvalError) -> bool,
|
||||||
|
) {
|
||||||
let (db, file_id) = TestDB::with_single_file(ra_fixture);
|
let (db, file_id) = TestDB::with_single_file(ra_fixture);
|
||||||
match eval_goal(&db, file_id) {
|
match eval_goal(&db, file_id) {
|
||||||
Ok(_) => panic!("Expected fail, but it succeeded"),
|
Ok(_) => panic!("Expected fail, but it succeeded"),
|
||||||
@ -42,7 +45,7 @@ fn check_fail(ra_fixture: &str, error: impl FnOnce(ConstEvalError) -> bool) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[track_caller]
|
#[track_caller]
|
||||||
fn check_number(ra_fixture: &str, answer: i128) {
|
fn check_number(#[rust_analyzer::rust_fixture] ra_fixture: &str, answer: i128) {
|
||||||
check_answer(ra_fixture, |b, _| {
|
check_answer(ra_fixture, |b, _| {
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
b,
|
b,
|
||||||
@ -54,7 +57,7 @@ fn check_number(ra_fixture: &str, answer: i128) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[track_caller]
|
#[track_caller]
|
||||||
fn check_str(ra_fixture: &str, answer: &str) {
|
fn check_str(#[rust_analyzer::rust_fixture] ra_fixture: &str, answer: &str) {
|
||||||
check_answer(ra_fixture, |b, mm| {
|
check_answer(ra_fixture, |b, mm| {
|
||||||
let addr = usize::from_le_bytes(b[0..b.len() / 2].try_into().unwrap());
|
let addr = usize::from_le_bytes(b[0..b.len() / 2].try_into().unwrap());
|
||||||
let size = usize::from_le_bytes(b[b.len() / 2..].try_into().unwrap());
|
let size = usize::from_le_bytes(b[b.len() / 2..].try_into().unwrap());
|
||||||
@ -71,7 +74,10 @@ fn check_str(ra_fixture: &str, answer: &str) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[track_caller]
|
#[track_caller]
|
||||||
fn check_answer(ra_fixture: &str, check: impl FnOnce(&[u8], &MemoryMap)) {
|
fn check_answer(
|
||||||
|
#[rust_analyzer::rust_fixture] ra_fixture: &str,
|
||||||
|
check: impl FnOnce(&[u8], &MemoryMap),
|
||||||
|
) {
|
||||||
let (db, file_ids) = TestDB::with_many_files(ra_fixture);
|
let (db, file_ids) = TestDB::with_many_files(ra_fixture);
|
||||||
let file_id = *file_ids.last().unwrap();
|
let file_id = *file_ids.last().unwrap();
|
||||||
let r = match eval_goal(&db, file_id) {
|
let r = match eval_goal(&db, file_id) {
|
||||||
|
@ -471,10 +471,55 @@ impl HirDisplay for ProjectionTy {
|
|||||||
if f.should_truncate() {
|
if f.should_truncate() {
|
||||||
return write!(f, "{TYPE_HINT_TRUNCATION}");
|
return write!(f, "{TYPE_HINT_TRUNCATION}");
|
||||||
}
|
}
|
||||||
|
|
||||||
let trait_ref = self.trait_ref(f.db);
|
let trait_ref = self.trait_ref(f.db);
|
||||||
|
let self_ty = trait_ref.self_type_parameter(Interner);
|
||||||
|
|
||||||
|
// if we are projection on a type parameter, check if the projection target has bounds
|
||||||
|
// itself, if so, we render them directly as `impl Bound` instead of the less useful
|
||||||
|
// `<Param as Trait>::Assoc`
|
||||||
|
if !f.display_target.is_source_code() {
|
||||||
|
if let TyKind::Placeholder(idx) = self_ty.kind(Interner) {
|
||||||
|
let db = f.db;
|
||||||
|
let id = from_placeholder_idx(db, *idx);
|
||||||
|
let generics = generics(db.upcast(), id.parent);
|
||||||
|
|
||||||
|
let substs = generics.placeholder_subst(db);
|
||||||
|
let bounds = db
|
||||||
|
.generic_predicates(id.parent)
|
||||||
|
.iter()
|
||||||
|
.map(|pred| pred.clone().substitute(Interner, &substs))
|
||||||
|
.filter(|wc| match wc.skip_binders() {
|
||||||
|
WhereClause::Implemented(tr) => {
|
||||||
|
match tr.self_type_parameter(Interner).kind(Interner) {
|
||||||
|
TyKind::Alias(AliasTy::Projection(proj)) => proj == self,
|
||||||
|
_ => false,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
WhereClause::TypeOutlives(t) => match t.ty.kind(Interner) {
|
||||||
|
TyKind::Alias(AliasTy::Projection(proj)) => proj == self,
|
||||||
|
_ => false,
|
||||||
|
},
|
||||||
|
// We shouldn't be here if these exist
|
||||||
|
WhereClause::AliasEq(_) => false,
|
||||||
|
WhereClause::LifetimeOutlives(_) => false,
|
||||||
|
})
|
||||||
|
.collect::<Vec<_>>();
|
||||||
|
if !bounds.is_empty() {
|
||||||
|
return write_bounds_like_dyn_trait_with_prefix(
|
||||||
|
f,
|
||||||
|
"impl",
|
||||||
|
Either::Left(
|
||||||
|
&TyKind::Alias(AliasTy::Projection(self.clone())).intern(Interner),
|
||||||
|
),
|
||||||
|
&bounds,
|
||||||
|
SizedByDefault::NotSized,
|
||||||
|
);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
write!(f, "<")?;
|
write!(f, "<")?;
|
||||||
trait_ref.self_type_parameter(Interner).hir_fmt(f)?;
|
self_ty.hir_fmt(f)?;
|
||||||
write!(f, " as ")?;
|
write!(f, " as ")?;
|
||||||
trait_ref.hir_fmt(f)?;
|
trait_ref.hir_fmt(f)?;
|
||||||
write!(
|
write!(
|
||||||
|
@ -26,7 +26,7 @@ enum DynCompatibilityViolationKind {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn check_dyn_compatibility<'a>(
|
fn check_dyn_compatibility<'a>(
|
||||||
ra_fixture: &str,
|
#[rust_analyzer::rust_fixture] ra_fixture: &str,
|
||||||
expected: impl IntoIterator<Item = (&'a str, Vec<DynCompatibilityViolationKind>)>,
|
expected: impl IntoIterator<Item = (&'a str, Vec<DynCompatibilityViolationKind>)>,
|
||||||
) {
|
) {
|
||||||
let mut expected: FxHashMap<_, _> =
|
let mut expected: FxHashMap<_, _> =
|
||||||
|
@ -25,7 +25,10 @@ fn current_machine_data_layout() -> String {
|
|||||||
.unwrap()
|
.unwrap()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn eval_goal(ra_fixture: &str, minicore: &str) -> Result<Arc<Layout>, LayoutError> {
|
fn eval_goal(
|
||||||
|
#[rust_analyzer::rust_fixture] ra_fixture: &str,
|
||||||
|
minicore: &str,
|
||||||
|
) -> Result<Arc<Layout>, LayoutError> {
|
||||||
let target_data_layout = current_machine_data_layout();
|
let target_data_layout = current_machine_data_layout();
|
||||||
let ra_fixture = format!(
|
let ra_fixture = format!(
|
||||||
"//- target_data_layout: {target_data_layout}\n{minicore}//- /main.rs crate:test\n{ra_fixture}",
|
"//- target_data_layout: {target_data_layout}\n{minicore}//- /main.rs crate:test\n{ra_fixture}",
|
||||||
@ -81,7 +84,10 @@ fn eval_goal(ra_fixture: &str, minicore: &str) -> Result<Arc<Layout>, LayoutErro
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// A version of `eval_goal` for types that can not be expressed in ADTs, like closures and `impl Trait`
|
/// A version of `eval_goal` for types that can not be expressed in ADTs, like closures and `impl Trait`
|
||||||
fn eval_expr(ra_fixture: &str, minicore: &str) -> Result<Arc<Layout>, LayoutError> {
|
fn eval_expr(
|
||||||
|
#[rust_analyzer::rust_fixture] ra_fixture: &str,
|
||||||
|
minicore: &str,
|
||||||
|
) -> Result<Arc<Layout>, LayoutError> {
|
||||||
let target_data_layout = current_machine_data_layout();
|
let target_data_layout = current_machine_data_layout();
|
||||||
let ra_fixture = format!(
|
let ra_fixture = format!(
|
||||||
"//- target_data_layout: {target_data_layout}\n{minicore}//- /main.rs crate:test\nfn main(){{let goal = {{{ra_fixture}}};}}",
|
"//- target_data_layout: {target_data_layout}\n{minicore}//- /main.rs crate:test\nfn main(){{let goal = {{{ra_fixture}}};}}",
|
||||||
@ -114,21 +120,31 @@ fn eval_expr(ra_fixture: &str, minicore: &str) -> Result<Arc<Layout>, LayoutErro
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[track_caller]
|
#[track_caller]
|
||||||
fn check_size_and_align(ra_fixture: &str, minicore: &str, size: u64, align: u64) {
|
fn check_size_and_align(
|
||||||
|
#[rust_analyzer::rust_fixture] ra_fixture: &str,
|
||||||
|
minicore: &str,
|
||||||
|
size: u64,
|
||||||
|
align: u64,
|
||||||
|
) {
|
||||||
let l = eval_goal(ra_fixture, minicore).unwrap();
|
let l = eval_goal(ra_fixture, minicore).unwrap();
|
||||||
assert_eq!(l.size.bytes(), size, "size mismatch");
|
assert_eq!(l.size.bytes(), size, "size mismatch");
|
||||||
assert_eq!(l.align.abi.bytes(), align, "align mismatch");
|
assert_eq!(l.align.abi.bytes(), align, "align mismatch");
|
||||||
}
|
}
|
||||||
|
|
||||||
#[track_caller]
|
#[track_caller]
|
||||||
fn check_size_and_align_expr(ra_fixture: &str, minicore: &str, size: u64, align: u64) {
|
fn check_size_and_align_expr(
|
||||||
|
#[rust_analyzer::rust_fixture] ra_fixture: &str,
|
||||||
|
minicore: &str,
|
||||||
|
size: u64,
|
||||||
|
align: u64,
|
||||||
|
) {
|
||||||
let l = eval_expr(ra_fixture, minicore).unwrap();
|
let l = eval_expr(ra_fixture, minicore).unwrap();
|
||||||
assert_eq!(l.size.bytes(), size, "size mismatch");
|
assert_eq!(l.size.bytes(), size, "size mismatch");
|
||||||
assert_eq!(l.align.abi.bytes(), align, "align mismatch");
|
assert_eq!(l.align.abi.bytes(), align, "align mismatch");
|
||||||
}
|
}
|
||||||
|
|
||||||
#[track_caller]
|
#[track_caller]
|
||||||
fn check_fail(ra_fixture: &str, e: LayoutError) {
|
fn check_fail(#[rust_analyzer::rust_fixture] ra_fixture: &str, e: LayoutError) {
|
||||||
let r = eval_goal(ra_fixture, "");
|
let r = eval_goal(ra_fixture, "");
|
||||||
assert_eq!(r, Err(e));
|
assert_eq!(r, Err(e));
|
||||||
}
|
}
|
||||||
|
@ -761,8 +761,8 @@ impl<'a> TyLoweringContext<'a> {
|
|||||||
path: &Path,
|
path: &Path,
|
||||||
on_diagnostic: &mut dyn FnMut(&mut Self, PathLoweringDiagnostic),
|
on_diagnostic: &mut dyn FnMut(&mut Self, PathLoweringDiagnostic),
|
||||||
) -> Option<(TypeNs, Option<usize>)> {
|
) -> Option<(TypeNs, Option<usize>)> {
|
||||||
let (resolution, remaining_index, _) =
|
let (resolution, remaining_index, _, prefix_info) =
|
||||||
self.resolver.resolve_path_in_type_ns(self.db.upcast(), path)?;
|
self.resolver.resolve_path_in_type_ns_with_prefix_info(self.db.upcast(), path)?;
|
||||||
let segments = path.segments();
|
let segments = path.segments();
|
||||||
|
|
||||||
match path {
|
match path {
|
||||||
@ -771,13 +771,12 @@ impl<'a> TyLoweringContext<'a> {
|
|||||||
_ => return Some((resolution, remaining_index)),
|
_ => return Some((resolution, remaining_index)),
|
||||||
};
|
};
|
||||||
|
|
||||||
let (module_segments, resolved_segment_idx, resolved_segment) = match remaining_index {
|
let (module_segments, resolved_segment_idx, enum_segment) = match remaining_index {
|
||||||
None => (
|
None if prefix_info.enum_variant => {
|
||||||
segments.strip_last(),
|
(segments.strip_last_two(), segments.len() - 1, Some(segments.len() - 2))
|
||||||
segments.len() - 1,
|
}
|
||||||
segments.last().expect("resolved path has at least one element"),
|
None => (segments.strip_last(), segments.len() - 1, None),
|
||||||
),
|
Some(i) => (segments.take(i - 1), i - 1, None),
|
||||||
Some(i) => (segments.take(i - 1), i - 1, segments.get(i - 1).unwrap()),
|
|
||||||
};
|
};
|
||||||
|
|
||||||
for (i, mod_segment) in module_segments.iter().enumerate() {
|
for (i, mod_segment) in module_segments.iter().enumerate() {
|
||||||
@ -792,9 +791,23 @@ impl<'a> TyLoweringContext<'a> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if let Some(enum_segment) = enum_segment {
|
||||||
|
if segments.get(enum_segment).is_some_and(|it| it.args_and_bindings.is_some())
|
||||||
|
&& segments.get(enum_segment + 1).is_some_and(|it| it.args_and_bindings.is_some())
|
||||||
|
{
|
||||||
|
on_diagnostic(
|
||||||
|
self,
|
||||||
|
PathLoweringDiagnostic::GenericArgsProhibited {
|
||||||
|
segment: (enum_segment + 1) as u32,
|
||||||
|
reason: GenericArgsProhibitedReason::EnumVariant,
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
self.handle_type_ns_resolution(
|
self.handle_type_ns_resolution(
|
||||||
&resolution,
|
&resolution,
|
||||||
resolved_segment,
|
segments.get(resolved_segment_idx).expect("should have resolved segment"),
|
||||||
resolved_segment_idx,
|
resolved_segment_idx,
|
||||||
on_diagnostic,
|
on_diagnostic,
|
||||||
);
|
);
|
||||||
|
@ -746,16 +746,9 @@ fn lookup_impl_assoc_item_for_trait_ref(
|
|||||||
let table = InferenceTable::new(db, env);
|
let table = InferenceTable::new(db, env);
|
||||||
|
|
||||||
let (impl_data, impl_subst) = find_matching_impl(impls, table, trait_ref)?;
|
let (impl_data, impl_subst) = find_matching_impl(impls, table, trait_ref)?;
|
||||||
let item = impl_data.items.iter().find_map(|&it| match it {
|
let item = impl_data.items.iter().find_map(|(n, it)| match *it {
|
||||||
AssocItemId::FunctionId(f) => {
|
AssocItemId::FunctionId(f) => (n == name).then_some(AssocItemId::FunctionId(f)),
|
||||||
(db.function_data(f).name == *name).then_some(AssocItemId::FunctionId(f))
|
AssocItemId::ConstId(c) => (n == name).then_some(AssocItemId::ConstId(c)),
|
||||||
}
|
|
||||||
AssocItemId::ConstId(c) => db
|
|
||||||
.const_data(c)
|
|
||||||
.name
|
|
||||||
.as_ref()
|
|
||||||
.map(|n| n == name)
|
|
||||||
.and_then(|result| if result { Some(AssocItemId::ConstId(c)) } else { None }),
|
|
||||||
AssocItemId::TypeAliasId(_) => None,
|
AssocItemId::TypeAliasId(_) => None,
|
||||||
})?;
|
})?;
|
||||||
Some((item, impl_subst))
|
Some((item, impl_subst))
|
||||||
@ -850,7 +843,7 @@ fn is_inherent_impl_coherent(
|
|||||||
};
|
};
|
||||||
rustc_has_incoherent_inherent_impls
|
rustc_has_incoherent_inherent_impls
|
||||||
&& !impl_data.items.is_empty()
|
&& !impl_data.items.is_empty()
|
||||||
&& impl_data.items.iter().copied().all(|assoc| match assoc {
|
&& impl_data.items.iter().all(|&(_, assoc)| match assoc {
|
||||||
AssocItemId::FunctionId(it) => db.function_data(it).rustc_allow_incoherent_impl,
|
AssocItemId::FunctionId(it) => db.function_data(it).rustc_allow_incoherent_impl,
|
||||||
AssocItemId::ConstId(it) => db.const_data(it).rustc_allow_incoherent_impl,
|
AssocItemId::ConstId(it) => db.const_data(it).rustc_allow_incoherent_impl,
|
||||||
AssocItemId::TypeAliasId(it) => db.type_alias_data(it).rustc_allow_incoherent_impl,
|
AssocItemId::TypeAliasId(it) => db.type_alias_data(it).rustc_allow_incoherent_impl,
|
||||||
@ -1399,7 +1392,7 @@ fn iterate_inherent_methods(
|
|||||||
callback: &mut dyn FnMut(ReceiverAdjustments, AssocItemId, bool) -> ControlFlow<()>,
|
callback: &mut dyn FnMut(ReceiverAdjustments, AssocItemId, bool) -> ControlFlow<()>,
|
||||||
) -> ControlFlow<()> {
|
) -> ControlFlow<()> {
|
||||||
for &impl_id in impls.for_self_ty(self_ty) {
|
for &impl_id in impls.for_self_ty(self_ty) {
|
||||||
for &item in table.db.impl_data(impl_id).items.iter() {
|
for &(ref item_name, item) in table.db.impl_data(impl_id).items.iter() {
|
||||||
let visible = match is_valid_impl_method_candidate(
|
let visible = match is_valid_impl_method_candidate(
|
||||||
table,
|
table,
|
||||||
self_ty,
|
self_ty,
|
||||||
@ -1408,6 +1401,7 @@ fn iterate_inherent_methods(
|
|||||||
name,
|
name,
|
||||||
impl_id,
|
impl_id,
|
||||||
item,
|
item,
|
||||||
|
item_name,
|
||||||
) {
|
) {
|
||||||
IsValidCandidate::Yes => true,
|
IsValidCandidate::Yes => true,
|
||||||
IsValidCandidate::NotVisible => false,
|
IsValidCandidate::NotVisible => false,
|
||||||
@ -1467,6 +1461,7 @@ fn is_valid_impl_method_candidate(
|
|||||||
name: Option<&Name>,
|
name: Option<&Name>,
|
||||||
impl_id: ImplId,
|
impl_id: ImplId,
|
||||||
item: AssocItemId,
|
item: AssocItemId,
|
||||||
|
item_name: &Name,
|
||||||
) -> IsValidCandidate {
|
) -> IsValidCandidate {
|
||||||
match item {
|
match item {
|
||||||
AssocItemId::FunctionId(f) => is_valid_impl_fn_candidate(
|
AssocItemId::FunctionId(f) => is_valid_impl_fn_candidate(
|
||||||
@ -1477,11 +1472,12 @@ fn is_valid_impl_method_candidate(
|
|||||||
receiver_ty,
|
receiver_ty,
|
||||||
self_ty,
|
self_ty,
|
||||||
visible_from_module,
|
visible_from_module,
|
||||||
|
item_name,
|
||||||
),
|
),
|
||||||
AssocItemId::ConstId(c) => {
|
AssocItemId::ConstId(c) => {
|
||||||
let db = table.db;
|
let db = table.db;
|
||||||
check_that!(receiver_ty.is_none());
|
check_that!(receiver_ty.is_none());
|
||||||
check_that!(name.is_none_or(|n| db.const_data(c).name.as_ref() == Some(n)));
|
check_that!(name.is_none_or(|n| n == item_name));
|
||||||
|
|
||||||
if let Some(from_module) = visible_from_module {
|
if let Some(from_module) = visible_from_module {
|
||||||
if !db.const_visibility(c).is_visible_from(db.upcast(), from_module) {
|
if !db.const_visibility(c).is_visible_from(db.upcast(), from_module) {
|
||||||
@ -1565,11 +1561,13 @@ fn is_valid_impl_fn_candidate(
|
|||||||
receiver_ty: Option<&Ty>,
|
receiver_ty: Option<&Ty>,
|
||||||
self_ty: &Ty,
|
self_ty: &Ty,
|
||||||
visible_from_module: Option<ModuleId>,
|
visible_from_module: Option<ModuleId>,
|
||||||
|
item_name: &Name,
|
||||||
) -> IsValidCandidate {
|
) -> IsValidCandidate {
|
||||||
|
check_that!(name.is_none_or(|n| n == item_name));
|
||||||
|
|
||||||
let db = table.db;
|
let db = table.db;
|
||||||
let data = db.function_data(fn_id);
|
let data = db.function_data(fn_id);
|
||||||
|
|
||||||
check_that!(name.is_none_or(|n| n == &data.name));
|
|
||||||
if let Some(from_module) = visible_from_module {
|
if let Some(from_module) = visible_from_module {
|
||||||
if !db.function_visibility(fn_id).is_visible_from(db.upcast(), from_module) {
|
if !db.function_visibility(fn_id).is_visible_from(db.upcast(), from_module) {
|
||||||
cov_mark::hit!(autoderef_candidate_not_visible);
|
cov_mark::hit!(autoderef_candidate_not_visible);
|
||||||
|
@ -37,11 +37,15 @@ fn eval_main(db: &TestDB, file_id: EditionedFileId) -> Result<(String, String),
|
|||||||
Ok((output.stdout().into_owned(), output.stderr().into_owned()))
|
Ok((output.stdout().into_owned(), output.stderr().into_owned()))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn check_pass(ra_fixture: &str) {
|
fn check_pass(#[rust_analyzer::rust_fixture] ra_fixture: &str) {
|
||||||
check_pass_and_stdio(ra_fixture, "", "");
|
check_pass_and_stdio(ra_fixture, "", "");
|
||||||
}
|
}
|
||||||
|
|
||||||
fn check_pass_and_stdio(ra_fixture: &str, expected_stdout: &str, expected_stderr: &str) {
|
fn check_pass_and_stdio(
|
||||||
|
#[rust_analyzer::rust_fixture] ra_fixture: &str,
|
||||||
|
expected_stdout: &str,
|
||||||
|
expected_stderr: &str,
|
||||||
|
) {
|
||||||
let (db, file_ids) = TestDB::with_many_files(ra_fixture);
|
let (db, file_ids) = TestDB::with_many_files(ra_fixture);
|
||||||
let file_id = *file_ids.last().unwrap();
|
let file_id = *file_ids.last().unwrap();
|
||||||
let x = eval_main(&db, file_id);
|
let x = eval_main(&db, file_id);
|
||||||
@ -73,7 +77,7 @@ fn check_pass_and_stdio(ra_fixture: &str, expected_stdout: &str, expected_stderr
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn check_panic(ra_fixture: &str, expected_panic: &str) {
|
fn check_panic(#[rust_analyzer::rust_fixture] ra_fixture: &str, expected_panic: &str) {
|
||||||
let (db, file_ids) = TestDB::with_many_files(ra_fixture);
|
let (db, file_ids) = TestDB::with_many_files(ra_fixture);
|
||||||
let file_id = *file_ids.last().unwrap();
|
let file_id = *file_ids.last().unwrap();
|
||||||
let e = eval_main(&db, file_id).unwrap_err();
|
let e = eval_main(&db, file_id).unwrap_err();
|
||||||
|
@ -69,27 +69,32 @@ fn setup_tracing() -> Option<tracing::subscriber::DefaultGuard> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[track_caller]
|
#[track_caller]
|
||||||
fn check_types(ra_fixture: &str) {
|
fn check_types(#[rust_analyzer::rust_fixture] ra_fixture: &str) {
|
||||||
check_impl(ra_fixture, false, true, false)
|
check_impl(ra_fixture, false, true, false)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[track_caller]
|
#[track_caller]
|
||||||
fn check_types_source_code(ra_fixture: &str) {
|
fn check_types_source_code(#[rust_analyzer::rust_fixture] ra_fixture: &str) {
|
||||||
check_impl(ra_fixture, false, true, true)
|
check_impl(ra_fixture, false, true, true)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[track_caller]
|
#[track_caller]
|
||||||
fn check_no_mismatches(ra_fixture: &str) {
|
fn check_no_mismatches(#[rust_analyzer::rust_fixture] ra_fixture: &str) {
|
||||||
check_impl(ra_fixture, true, false, false)
|
check_impl(ra_fixture, true, false, false)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[track_caller]
|
#[track_caller]
|
||||||
fn check(ra_fixture: &str) {
|
fn check(#[rust_analyzer::rust_fixture] ra_fixture: &str) {
|
||||||
check_impl(ra_fixture, false, false, false)
|
check_impl(ra_fixture, false, false, false)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[track_caller]
|
#[track_caller]
|
||||||
fn check_impl(ra_fixture: &str, allow_none: bool, only_types: bool, display_source: bool) {
|
fn check_impl(
|
||||||
|
#[rust_analyzer::rust_fixture] ra_fixture: &str,
|
||||||
|
allow_none: bool,
|
||||||
|
only_types: bool,
|
||||||
|
display_source: bool,
|
||||||
|
) {
|
||||||
let _tracing = setup_tracing();
|
let _tracing = setup_tracing();
|
||||||
let (db, files) = TestDB::with_many_files(ra_fixture);
|
let (db, files) = TestDB::with_many_files(ra_fixture);
|
||||||
|
|
||||||
@ -282,7 +287,7 @@ fn pat_node(
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
fn infer(ra_fixture: &str) -> String {
|
fn infer(#[rust_analyzer::rust_fixture] ra_fixture: &str) -> String {
|
||||||
infer_with_mismatches(ra_fixture, false)
|
infer_with_mismatches(ra_fixture, false)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -430,7 +435,7 @@ pub(crate) fn visit_module(
|
|||||||
visit_scope(db, crate_def_map, &crate_def_map[module_id].scope, cb);
|
visit_scope(db, crate_def_map, &crate_def_map[module_id].scope, cb);
|
||||||
for impl_id in crate_def_map[module_id].scope.impls() {
|
for impl_id in crate_def_map[module_id].scope.impls() {
|
||||||
let impl_data = db.impl_data(impl_id);
|
let impl_data = db.impl_data(impl_id);
|
||||||
for &item in impl_data.items.iter() {
|
for &(_, item) in impl_data.items.iter() {
|
||||||
match item {
|
match item {
|
||||||
AssocItemId::FunctionId(it) => {
|
AssocItemId::FunctionId(it) => {
|
||||||
let body = db.body(it.into());
|
let body = db.body(it.into());
|
||||||
@ -520,13 +525,13 @@ fn ellipsize(mut text: String, max_len: usize) -> String {
|
|||||||
text
|
text
|
||||||
}
|
}
|
||||||
|
|
||||||
fn check_infer(ra_fixture: &str, expect: Expect) {
|
fn check_infer(#[rust_analyzer::rust_fixture] ra_fixture: &str, expect: Expect) {
|
||||||
let mut actual = infer(ra_fixture);
|
let mut actual = infer(ra_fixture);
|
||||||
actual.push('\n');
|
actual.push('\n');
|
||||||
expect.assert_eq(&actual);
|
expect.assert_eq(&actual);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn check_infer_with_mismatches(ra_fixture: &str, expect: Expect) {
|
fn check_infer_with_mismatches(#[rust_analyzer::rust_fixture] ra_fixture: &str, expect: Expect) {
|
||||||
let mut actual = infer_with_mismatches(ra_fixture, true);
|
let mut actual = infer_with_mismatches(ra_fixture, true);
|
||||||
actual.push('\n');
|
actual.push('\n');
|
||||||
expect.assert_eq(&actual);
|
expect.assert_eq(&actual);
|
||||||
|
@ -14,7 +14,7 @@ use crate::test_db::TestDB;
|
|||||||
|
|
||||||
use super::visit_module;
|
use super::visit_module;
|
||||||
|
|
||||||
fn check_closure_captures(ra_fixture: &str, expect: Expect) {
|
fn check_closure_captures(#[rust_analyzer::rust_fixture] ra_fixture: &str, expect: Expect) {
|
||||||
let (db, file_id) = TestDB::with_single_file(ra_fixture);
|
let (db, file_id) = TestDB::with_single_file(ra_fixture);
|
||||||
let module = db.module_for_file(file_id);
|
let module = db.module_for_file(file_id);
|
||||||
let def_map = module.def_map(&db);
|
let def_map = module.def_map(&db);
|
||||||
|
@ -3802,3 +3802,15 @@ fn foo() {
|
|||||||
"#,
|
"#,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn tool_attr_skip() {
|
||||||
|
check_no_mismatches(
|
||||||
|
r#"
|
||||||
|
#[rust_analyzer::skip]
|
||||||
|
async fn foo(a: (), b: i32) -> u32 {
|
||||||
|
0 + 1 + b()
|
||||||
|
}
|
||||||
|
"#,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
@ -968,7 +968,7 @@ struct FixedPoint<T, U, V>(&'static FixedPoint<(), T, U>, V);
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[track_caller]
|
#[track_caller]
|
||||||
fn check(ra_fixture: &str, expected: Expect) {
|
fn check(#[rust_analyzer::rust_fixture] ra_fixture: &str, expected: Expect) {
|
||||||
// use tracing_subscriber::{layer::SubscriberExt, Layer};
|
// use tracing_subscriber::{layer::SubscriberExt, Layer};
|
||||||
// let my_layer = tracing_subscriber::fmt::layer();
|
// let my_layer = tracing_subscriber::fmt::layer();
|
||||||
// let _g = tracing::subscriber::set_default(tracing_subscriber::registry().with(
|
// let _g = tracing::subscriber::set_default(tracing_subscriber::registry().with(
|
||||||
|
@ -20,6 +20,7 @@ itertools.workspace = true
|
|||||||
smallvec.workspace = true
|
smallvec.workspace = true
|
||||||
tracing.workspace = true
|
tracing.workspace = true
|
||||||
triomphe.workspace = true
|
triomphe.workspace = true
|
||||||
|
indexmap.workspace = true
|
||||||
|
|
||||||
# local deps
|
# local deps
|
||||||
base-db.workspace = true
|
base-db.workspace = true
|
||||||
|
@ -12,7 +12,6 @@ use hir_def::{
|
|||||||
};
|
};
|
||||||
use hir_expand::{mod_path::PathKind, name::Name};
|
use hir_expand::{mod_path::PathKind, name::Name};
|
||||||
use hir_ty::{db::HirDatabase, method_resolution};
|
use hir_ty::{db::HirDatabase, method_resolution};
|
||||||
use span::SyntaxContextId;
|
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
Adt, AsAssocItem, AssocItem, BuiltinType, Const, ConstParam, DocLinkDef, Enum, ExternCrateDecl,
|
Adt, AsAssocItem, AssocItem, BuiltinType, Const, ConstParam, DocLinkDef, Enum, ExternCrateDecl,
|
||||||
@ -90,6 +89,16 @@ impl HasAttrs for AssocItem {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl HasAttrs for crate::Crate {
|
||||||
|
fn attrs(self, db: &dyn HirDatabase) -> AttrsWithOwner {
|
||||||
|
let def = AttrDefId::ModuleId(self.root_module().id);
|
||||||
|
AttrsWithOwner::new(db.upcast(), def)
|
||||||
|
}
|
||||||
|
fn attr_id(self) -> AttrDefId {
|
||||||
|
AttrDefId::ModuleId(self.root_module().id)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Resolves the item `link` points to in the scope of `def`.
|
/// Resolves the item `link` points to in the scope of `def`.
|
||||||
pub fn resolve_doc_path_on(
|
pub fn resolve_doc_path_on(
|
||||||
db: &dyn HirDatabase,
|
db: &dyn HirDatabase,
|
||||||
@ -328,9 +337,7 @@ fn doc_modpath_from_str(link: &str) -> Option<ModPath> {
|
|||||||
};
|
};
|
||||||
let parts = first_segment.into_iter().chain(parts).map(|segment| match segment.parse() {
|
let parts = first_segment.into_iter().chain(parts).map(|segment| match segment.parse() {
|
||||||
Ok(idx) => Name::new_tuple_field(idx),
|
Ok(idx) => Name::new_tuple_field(idx),
|
||||||
Err(_) => {
|
Err(_) => Name::new_root(segment.split_once('<').map_or(segment, |it| it.0)),
|
||||||
Name::new(segment.split_once('<').map_or(segment, |it| it.0), SyntaxContextId::ROOT)
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
Some(ModPath::from_segments(kind, parts))
|
Some(ModPath::from_segments(kind, parts))
|
||||||
};
|
};
|
||||||
|
@ -23,10 +23,10 @@ use hir_ty::{
|
|||||||
use itertools::Itertools;
|
use itertools::Itertools;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
Adt, AsAssocItem, AssocItem, AssocItemContainer, Const, ConstParam, Enum, ExternCrateDecl,
|
Adt, AsAssocItem, AssocItem, AssocItemContainer, Const, ConstParam, Crate, Enum,
|
||||||
Field, Function, GenericParam, HasCrate, HasVisibility, Impl, LifetimeParam, Macro, Module,
|
ExternCrateDecl, Field, Function, GenericParam, HasCrate, HasVisibility, Impl, LifetimeParam,
|
||||||
SelfParam, Static, Struct, Trait, TraitAlias, TraitRef, TupleField, TyBuilder, Type, TypeAlias,
|
Macro, Module, SelfParam, Static, Struct, Trait, TraitAlias, TraitRef, TupleField, TyBuilder,
|
||||||
TypeOrConstParam, TypeParam, Union, Variant,
|
Type, TypeAlias, TypeOrConstParam, TypeParam, Union, Variant,
|
||||||
};
|
};
|
||||||
|
|
||||||
impl HirDisplay for Function {
|
impl HirDisplay for Function {
|
||||||
@ -846,14 +846,27 @@ impl HirDisplay for TypeAlias {
|
|||||||
|
|
||||||
impl HirDisplay for Module {
|
impl HirDisplay for Module {
|
||||||
fn hir_fmt(&self, f: &mut HirFormatter<'_>) -> Result<(), HirDisplayError> {
|
fn hir_fmt(&self, f: &mut HirFormatter<'_>) -> Result<(), HirDisplayError> {
|
||||||
// FIXME: Module doesn't have visibility saved in data.
|
match self.parent(f.db) {
|
||||||
match self.name(f.db) {
|
Some(m) => write_visibility(m.id, self.visibility(f.db), f)?,
|
||||||
Some(name) => write!(f, "mod {}", name.display(f.db.upcast(), f.edition())),
|
None => {
|
||||||
None if self.is_crate_root() => match self.krate(f.db).display_name(f.db) {
|
return match self.krate(f.db).display_name(f.db) {
|
||||||
|
Some(name) => write!(f, "extern crate {name}"),
|
||||||
|
None => f.write_str("extern crate {unknown}"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
match self.name(f.db) {
|
||||||
|
Some(name) => write!(f, "mod {}", name.display(f.db.upcast(), f.edition())),
|
||||||
|
None => f.write_str("mod {unknown}"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl HirDisplay for Crate {
|
||||||
|
fn hir_fmt(&self, f: &mut HirFormatter<'_>) -> Result<(), HirDisplayError> {
|
||||||
|
match self.display_name(f.db) {
|
||||||
Some(name) => write!(f, "extern crate {name}"),
|
Some(name) => write!(f, "extern crate {name}"),
|
||||||
None => f.write_str("extern crate {unknown}"),
|
None => f.write_str("extern crate {unknown}"),
|
||||||
},
|
|
||||||
None => f.write_str("mod {unnamed}"),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -54,11 +54,11 @@ use hir_def::{
|
|||||||
per_ns::PerNs,
|
per_ns::PerNs,
|
||||||
resolver::{HasResolver, Resolver},
|
resolver::{HasResolver, Resolver},
|
||||||
type_ref::TypesSourceMap,
|
type_ref::TypesSourceMap,
|
||||||
AssocItemId, AssocItemLoc, AttrDefId, CallableDefId, ConstId, ConstParamId, CrateRootModuleId,
|
AdtId, AssocItemId, AssocItemLoc, AttrDefId, CallableDefId, ConstId, ConstParamId,
|
||||||
DefWithBodyId, EnumId, EnumVariantId, ExternCrateId, FunctionId, GenericDefId, GenericParamId,
|
CrateRootModuleId, DefWithBodyId, EnumId, EnumVariantId, ExternCrateId, FunctionId,
|
||||||
HasModule, ImplId, InTypeConstId, ItemContainerId, LifetimeParamId, LocalFieldId, Lookup,
|
GenericDefId, GenericParamId, HasModule, ImplId, InTypeConstId, ItemContainerId,
|
||||||
MacroExpander, ModuleId, StaticId, StructId, SyntheticSyntax, TraitAliasId, TraitId, TupleId,
|
LifetimeParamId, LocalFieldId, Lookup, MacroExpander, MacroId, ModuleId, StaticId, StructId,
|
||||||
TypeAliasId, TypeOrConstParamId, TypeParamId, UnionId,
|
SyntheticSyntax, TraitAliasId, TupleId, TypeAliasId, TypeOrConstParamId, TypeParamId, UnionId,
|
||||||
};
|
};
|
||||||
use hir_expand::{
|
use hir_expand::{
|
||||||
attrs::collect_attrs, proc_macro::ProcMacroKind, AstId, MacroCallKind, RenderedExpandError,
|
attrs::collect_attrs, proc_macro::ProcMacroKind, AstId, MacroCallKind, RenderedExpandError,
|
||||||
@ -83,7 +83,7 @@ use itertools::Itertools;
|
|||||||
use nameres::diagnostics::DefDiagnosticKind;
|
use nameres::diagnostics::DefDiagnosticKind;
|
||||||
use rustc_hash::FxHashSet;
|
use rustc_hash::FxHashSet;
|
||||||
use smallvec::SmallVec;
|
use smallvec::SmallVec;
|
||||||
use span::{Edition, EditionedFileId, FileId, MacroCallId, SyntaxContextId};
|
use span::{Edition, EditionedFileId, FileId, MacroCallId};
|
||||||
use stdx::{format_to, impl_from, never};
|
use stdx::{format_to, impl_from, never};
|
||||||
use syntax::{
|
use syntax::{
|
||||||
ast::{self, HasAttrs as _, HasGenericParams, HasName},
|
ast::{self, HasAttrs as _, HasGenericParams, HasName},
|
||||||
@ -127,7 +127,7 @@ pub use {
|
|||||||
ImportPathConfig,
|
ImportPathConfig,
|
||||||
// FIXME: This is here since some queries take it as input that are used
|
// FIXME: This is here since some queries take it as input that are used
|
||||||
// outside of hir.
|
// outside of hir.
|
||||||
{AdtId, MacroId, ModuleDefId},
|
{ModuleDefId, TraitId},
|
||||||
},
|
},
|
||||||
hir_expand::{
|
hir_expand::{
|
||||||
attrs::{Attr, AttrId},
|
attrs::{Attr, AttrId},
|
||||||
@ -775,29 +775,16 @@ impl Module {
|
|||||||
AssocItemId::ConstId(id) => !db.const_data(id).has_body,
|
AssocItemId::ConstId(id) => !db.const_data(id).has_body,
|
||||||
AssocItemId::TypeAliasId(it) => db.type_alias_data(it).type_ref.is_none(),
|
AssocItemId::TypeAliasId(it) => db.type_alias_data(it).type_ref.is_none(),
|
||||||
});
|
});
|
||||||
impl_assoc_items_scratch.extend(db.impl_data(impl_def.id).items.iter().filter_map(
|
impl_assoc_items_scratch.extend(db.impl_data(impl_def.id).items.iter().cloned());
|
||||||
|&item| {
|
|
||||||
Some((
|
|
||||||
item,
|
|
||||||
match item {
|
|
||||||
AssocItemId::FunctionId(it) => db.function_data(it).name.clone(),
|
|
||||||
AssocItemId::ConstId(it) => {
|
|
||||||
db.const_data(it).name.as_ref()?.clone()
|
|
||||||
}
|
|
||||||
AssocItemId::TypeAliasId(it) => db.type_alias_data(it).name.clone(),
|
|
||||||
},
|
|
||||||
))
|
|
||||||
},
|
|
||||||
));
|
|
||||||
|
|
||||||
let redundant = impl_assoc_items_scratch
|
let redundant = impl_assoc_items_scratch
|
||||||
.iter()
|
.iter()
|
||||||
.filter(|(id, name)| {
|
.filter(|(name, id)| {
|
||||||
!items.iter().any(|(impl_name, impl_item)| {
|
!items.iter().any(|(impl_name, impl_item)| {
|
||||||
discriminant(impl_item) == discriminant(id) && impl_name == name
|
discriminant(impl_item) == discriminant(id) && impl_name == name
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
.map(|(item, name)| (name.clone(), AssocItem::from(*item)));
|
.map(|(name, item)| (name.clone(), AssocItem::from(*item)));
|
||||||
for (name, assoc_item) in redundant {
|
for (name, assoc_item) in redundant {
|
||||||
acc.push(
|
acc.push(
|
||||||
TraitImplRedundantAssocItems {
|
TraitImplRedundantAssocItems {
|
||||||
@ -812,7 +799,7 @@ impl Module {
|
|||||||
|
|
||||||
let missing: Vec<_> = required_items
|
let missing: Vec<_> = required_items
|
||||||
.filter(|(name, id)| {
|
.filter(|(name, id)| {
|
||||||
!impl_assoc_items_scratch.iter().any(|(impl_item, impl_name)| {
|
!impl_assoc_items_scratch.iter().any(|(impl_name, impl_item)| {
|
||||||
discriminant(impl_item) == discriminant(id) && impl_name == name
|
discriminant(impl_item) == discriminant(id) && impl_name == name
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
@ -844,7 +831,7 @@ impl Module {
|
|||||||
source_map,
|
source_map,
|
||||||
);
|
);
|
||||||
|
|
||||||
for &item in db.impl_data(impl_def.id).items.iter() {
|
for &(_, item) in db.impl_data(impl_def.id).items.iter() {
|
||||||
AssocItem::from(item).diagnostics(db, acc, style_lints);
|
AssocItem::from(item).diagnostics(db, acc, style_lints);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -3000,6 +2987,10 @@ impl Macro {
|
|||||||
matches!(self.id, MacroId::MacroRulesId(id) if db.macro_rules_data(id).macro_export)
|
matches!(self.id, MacroId::MacroRulesId(id) if db.macro_rules_data(id).macro_export)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn is_proc_macro(self) -> bool {
|
||||||
|
matches!(self.id, MacroId::ProcMacroId(_))
|
||||||
|
}
|
||||||
|
|
||||||
pub fn kind(&self, db: &dyn HirDatabase) -> MacroKind {
|
pub fn kind(&self, db: &dyn HirDatabase) -> MacroKind {
|
||||||
match self.id {
|
match self.id {
|
||||||
MacroId::Macro2Id(it) => match it.lookup(db.upcast()).expander {
|
MacroId::Macro2Id(it) => match it.lookup(db.upcast()).expander {
|
||||||
@ -3046,14 +3037,23 @@ impl Macro {
|
|||||||
MacroId::Macro2Id(it) => {
|
MacroId::Macro2Id(it) => {
|
||||||
matches!(it.lookup(db.upcast()).expander, MacroExpander::BuiltInEager(eager) if eager.is_env_or_option_env())
|
matches!(it.lookup(db.upcast()).expander, MacroExpander::BuiltInEager(eager) if eager.is_env_or_option_env())
|
||||||
}
|
}
|
||||||
MacroId::MacroRulesId(_) | MacroId::ProcMacroId(_) => false,
|
MacroId::MacroRulesId(it) => {
|
||||||
|
matches!(it.lookup(db.upcast()).expander, MacroExpander::BuiltInEager(eager) if eager.is_env_or_option_env())
|
||||||
|
}
|
||||||
|
MacroId::ProcMacroId(_) => false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn is_asm_or_global_asm(&self, db: &dyn HirDatabase) -> bool {
|
pub fn is_asm_or_global_asm(&self, db: &dyn HirDatabase) -> bool {
|
||||||
matches!(self.id, MacroId::Macro2Id(it) if {
|
match self.id {
|
||||||
|
MacroId::Macro2Id(it) => {
|
||||||
matches!(it.lookup(db.upcast()).expander, MacroExpander::BuiltIn(m) if m.is_asm())
|
matches!(it.lookup(db.upcast()).expander, MacroExpander::BuiltIn(m) if m.is_asm())
|
||||||
})
|
}
|
||||||
|
MacroId::MacroRulesId(it) => {
|
||||||
|
matches!(it.lookup(db.upcast()).expander, MacroExpander::BuiltIn(m) if m.is_asm())
|
||||||
|
}
|
||||||
|
MacroId::ProcMacroId(_) => false,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn is_attr(&self, db: &dyn HirDatabase) -> bool {
|
pub fn is_attr(&self, db: &dyn HirDatabase) -> bool {
|
||||||
@ -3902,6 +3902,10 @@ impl ToolModule {
|
|||||||
db.crate_def_map(self.krate).registered_tools()[self.idx as usize].clone(),
|
db.crate_def_map(self.krate).registered_tools()[self.idx as usize].clone(),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn krate(&self) -> Crate {
|
||||||
|
Crate { id: self.krate }
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
|
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
|
||||||
@ -4290,7 +4294,7 @@ impl Impl {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn items(self, db: &dyn HirDatabase) -> Vec<AssocItem> {
|
pub fn items(self, db: &dyn HirDatabase) -> Vec<AssocItem> {
|
||||||
db.impl_data(self.id).items.iter().map(|&it| it.into()).collect()
|
db.impl_data(self.id).items.iter().map(|&(_, it)| it.into()).collect()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn is_negative(self, db: &dyn HirDatabase) -> bool {
|
pub fn is_negative(self, db: &dyn HirDatabase) -> bool {
|
||||||
@ -4731,6 +4735,14 @@ impl Type {
|
|||||||
Some((self.derived(ty.clone()), m))
|
Some((self.derived(ty.clone()), m))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn add_reference(&self, mutability: Mutability) -> Type {
|
||||||
|
let ty_mutability = match mutability {
|
||||||
|
Mutability::Shared => hir_ty::Mutability::Not,
|
||||||
|
Mutability::Mut => hir_ty::Mutability::Mut,
|
||||||
|
};
|
||||||
|
self.derived(TyKind::Ref(ty_mutability, error_lifetime(), self.ty.clone()).intern(Interner))
|
||||||
|
}
|
||||||
|
|
||||||
pub fn is_slice(&self) -> bool {
|
pub fn is_slice(&self) -> bool {
|
||||||
matches!(self.ty.kind(Interner), TyKind::Slice(..))
|
matches!(self.ty.kind(Interner), TyKind::Slice(..))
|
||||||
}
|
}
|
||||||
@ -4786,9 +4798,9 @@ impl Type {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Checks that particular type `ty` implements `std::future::IntoFuture` or
|
/// Checks that particular type `ty` implements `std::future::IntoFuture` or
|
||||||
/// `std::future::Future`.
|
/// `std::future::Future` and returns the `Output` associated type.
|
||||||
/// This function is used in `.await` syntax completion.
|
/// This function is used in `.await` syntax completion.
|
||||||
pub fn impls_into_future(&self, db: &dyn HirDatabase) -> bool {
|
pub fn into_future_output(&self, db: &dyn HirDatabase) -> Option<Type> {
|
||||||
let trait_ = db
|
let trait_ = db
|
||||||
.lang_item(self.env.krate, LangItem::IntoFutureIntoFuture)
|
.lang_item(self.env.krate, LangItem::IntoFutureIntoFuture)
|
||||||
.and_then(|it| {
|
.and_then(|it| {
|
||||||
@ -4800,16 +4812,18 @@ impl Type {
|
|||||||
.or_else(|| {
|
.or_else(|| {
|
||||||
let future_trait = db.lang_item(self.env.krate, LangItem::Future)?;
|
let future_trait = db.lang_item(self.env.krate, LangItem::Future)?;
|
||||||
future_trait.as_trait()
|
future_trait.as_trait()
|
||||||
});
|
})?;
|
||||||
|
|
||||||
let trait_ = match trait_ {
|
|
||||||
Some(it) => it,
|
|
||||||
None => return false,
|
|
||||||
};
|
|
||||||
|
|
||||||
let canonical_ty =
|
let canonical_ty =
|
||||||
Canonical { value: self.ty.clone(), binders: CanonicalVarKinds::empty(Interner) };
|
Canonical { value: self.ty.clone(), binders: CanonicalVarKinds::empty(Interner) };
|
||||||
method_resolution::implements_trait(&canonical_ty, db, &self.env, trait_)
|
if !method_resolution::implements_trait_unique(&canonical_ty, db, &self.env, trait_) {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
|
||||||
|
let output_assoc_type = db
|
||||||
|
.trait_data(trait_)
|
||||||
|
.associated_type_by_name(&Name::new_symbol_root(sym::Output.clone()))?;
|
||||||
|
self.normalize_trait_assoc_type(db, &[], output_assoc_type.into())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// This does **not** resolve `IntoFuture`, only `Future`.
|
/// This does **not** resolve `IntoFuture`, only `Future`.
|
||||||
@ -4824,10 +4838,31 @@ impl Type {
|
|||||||
let iterator_trait = db.lang_item(self.env.krate, LangItem::Iterator)?.as_trait()?;
|
let iterator_trait = db.lang_item(self.env.krate, LangItem::Iterator)?.as_trait()?;
|
||||||
let iterator_item = db
|
let iterator_item = db
|
||||||
.trait_data(iterator_trait)
|
.trait_data(iterator_trait)
|
||||||
.associated_type_by_name(&Name::new_symbol(sym::Item.clone(), SyntaxContextId::ROOT))?;
|
.associated_type_by_name(&Name::new_symbol_root(sym::Item.clone()))?;
|
||||||
self.normalize_trait_assoc_type(db, &[], iterator_item.into())
|
self.normalize_trait_assoc_type(db, &[], iterator_item.into())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Resolves the projection `<Self as IntoIterator>::IntoIter` and returns the resulting type
|
||||||
|
pub fn into_iterator_iter(self, db: &dyn HirDatabase) -> Option<Type> {
|
||||||
|
let trait_ = db.lang_item(self.env.krate, LangItem::IntoIterIntoIter).and_then(|it| {
|
||||||
|
let into_iter_fn = it.as_function()?;
|
||||||
|
let assoc_item = as_assoc_item(db, AssocItem::Function, into_iter_fn)?;
|
||||||
|
let into_iter_trait = assoc_item.container_or_implemented_trait(db)?;
|
||||||
|
Some(into_iter_trait.id)
|
||||||
|
})?;
|
||||||
|
|
||||||
|
let canonical_ty =
|
||||||
|
Canonical { value: self.ty.clone(), binders: CanonicalVarKinds::empty(Interner) };
|
||||||
|
if !method_resolution::implements_trait_unique(&canonical_ty, db, &self.env, trait_) {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
|
||||||
|
let into_iter_assoc_type = db
|
||||||
|
.trait_data(trait_)
|
||||||
|
.associated_type_by_name(&Name::new_symbol_root(sym::IntoIter.clone()))?;
|
||||||
|
self.normalize_trait_assoc_type(db, &[], into_iter_assoc_type.into())
|
||||||
|
}
|
||||||
|
|
||||||
/// Checks that particular type `ty` implements `std::ops::FnOnce`.
|
/// Checks that particular type `ty` implements `std::ops::FnOnce`.
|
||||||
///
|
///
|
||||||
/// This function can be used to check if a particular type is callable, since FnOnce is a
|
/// This function can be used to check if a particular type is callable, since FnOnce is a
|
||||||
@ -5117,7 +5152,7 @@ impl Type {
|
|||||||
let impls = db.inherent_impls_in_crate(krate);
|
let impls = db.inherent_impls_in_crate(krate);
|
||||||
|
|
||||||
for impl_def in impls.for_self_ty(&self.ty) {
|
for impl_def in impls.for_self_ty(&self.ty) {
|
||||||
for &item in db.impl_data(*impl_def).items.iter() {
|
for &(_, item) in db.impl_data(*impl_def).items.iter() {
|
||||||
if callback(item) {
|
if callback(item) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -5535,6 +5570,7 @@ impl Type {
|
|||||||
walk_substs(db, type_, &opaque_ty.substitution, cb);
|
walk_substs(db, type_, &opaque_ty.substitution, cb);
|
||||||
}
|
}
|
||||||
TyKind::Placeholder(_) => {
|
TyKind::Placeholder(_) => {
|
||||||
|
cb(type_.derived(ty.clone()));
|
||||||
if let Some(bounds) = ty.impl_trait_bounds(db) {
|
if let Some(bounds) = ty.impl_trait_bounds(db) {
|
||||||
walk_bounds(db, &type_.derived(ty.clone()), &bounds, cb);
|
walk_bounds(db, &type_.derived(ty.clone()), &bounds, cb);
|
||||||
}
|
}
|
||||||
|
@ -39,8 +39,8 @@ use stdx::TupleExt;
|
|||||||
use syntax::{
|
use syntax::{
|
||||||
algo::skip_trivia_token,
|
algo::skip_trivia_token,
|
||||||
ast::{self, HasAttrs as _, HasGenericParams},
|
ast::{self, HasAttrs as _, HasGenericParams},
|
||||||
AstNode, AstToken, Direction, SmolStr, SyntaxKind, SyntaxNode, SyntaxNodePtr, SyntaxToken,
|
AstNode, AstToken, Direction, SyntaxKind, SyntaxNode, SyntaxNodePtr, SyntaxToken, TextRange,
|
||||||
TextRange, TextSize,
|
TextSize,
|
||||||
};
|
};
|
||||||
use triomphe::Arc;
|
use triomphe::Arc;
|
||||||
|
|
||||||
@ -136,8 +136,6 @@ pub struct Semantics<'db, DB> {
|
|||||||
pub struct SemanticsImpl<'db> {
|
pub struct SemanticsImpl<'db> {
|
||||||
pub db: &'db dyn HirDatabase,
|
pub db: &'db dyn HirDatabase,
|
||||||
s2d_cache: RefCell<SourceToDefCache>,
|
s2d_cache: RefCell<SourceToDefCache>,
|
||||||
/// Rootnode to HirFileId cache
|
|
||||||
root_to_file_cache: RefCell<FxHashMap<SyntaxNode, HirFileId>>,
|
|
||||||
/// MacroCall to its expansion's MacroFileId cache
|
/// MacroCall to its expansion's MacroFileId cache
|
||||||
macro_call_cache: RefCell<FxHashMap<InFile<ast::MacroCall>, MacroFileId>>,
|
macro_call_cache: RefCell<FxHashMap<InFile<ast::MacroCall>, MacroFileId>>,
|
||||||
}
|
}
|
||||||
@ -304,12 +302,7 @@ impl<DB: HirDatabase> Semantics<'_, DB> {
|
|||||||
|
|
||||||
impl<'db> SemanticsImpl<'db> {
|
impl<'db> SemanticsImpl<'db> {
|
||||||
fn new(db: &'db dyn HirDatabase) -> Self {
|
fn new(db: &'db dyn HirDatabase) -> Self {
|
||||||
SemanticsImpl {
|
SemanticsImpl { db, s2d_cache: Default::default(), macro_call_cache: Default::default() }
|
||||||
db,
|
|
||||||
s2d_cache: Default::default(),
|
|
||||||
root_to_file_cache: Default::default(),
|
|
||||||
macro_call_cache: Default::default(),
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn parse(&self, file_id: EditionedFileId) -> ast::SourceFile {
|
pub fn parse(&self, file_id: EditionedFileId) -> ast::SourceFile {
|
||||||
@ -483,7 +476,7 @@ impl<'db> SemanticsImpl<'db> {
|
|||||||
Some(
|
Some(
|
||||||
calls
|
calls
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.map(|call| macro_call_to_macro_id(self, ctx, call?).map(|id| Macro { id }))
|
.map(|call| macro_call_to_macro_id(ctx, call?).map(|id| Macro { id }))
|
||||||
.collect(),
|
.collect(),
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
@ -962,7 +955,7 @@ impl<'db> SemanticsImpl<'db> {
|
|||||||
let InMacroFile { file_id, value: mapped_tokens } = self.with_ctx(|ctx| {
|
let InMacroFile { file_id, value: mapped_tokens } = self.with_ctx(|ctx| {
|
||||||
Some(
|
Some(
|
||||||
ctx.cache
|
ctx.cache
|
||||||
.get_or_insert_expansion(self, macro_file)
|
.get_or_insert_expansion(ctx.db, macro_file)
|
||||||
.map_range_down(span)?
|
.map_range_down(span)?
|
||||||
.map(SmallVec::<[_; 2]>::from_iter),
|
.map(SmallVec::<[_; 2]>::from_iter),
|
||||||
)
|
)
|
||||||
@ -986,7 +979,10 @@ impl<'db> SemanticsImpl<'db> {
|
|||||||
process_expansion_for_token(&mut stack, include)?;
|
process_expansion_for_token(&mut stack, include)?;
|
||||||
}
|
}
|
||||||
None => {
|
None => {
|
||||||
stack.push((file_id.into(), smallvec![(token, SyntaxContextId::ROOT)]));
|
stack.push((
|
||||||
|
file_id.into(),
|
||||||
|
smallvec![(token, SyntaxContextId::root(file_id.edition()))],
|
||||||
|
));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1284,7 +1280,7 @@ impl<'db> SemanticsImpl<'db> {
|
|||||||
let macro_file = file_id.macro_file()?;
|
let macro_file = file_id.macro_file()?;
|
||||||
|
|
||||||
self.with_ctx(|ctx| {
|
self.with_ctx(|ctx| {
|
||||||
let expansion_info = ctx.cache.get_or_insert_expansion(self, macro_file);
|
let expansion_info = ctx.cache.get_or_insert_expansion(ctx.db, macro_file);
|
||||||
expansion_info.arg().map(|node| node?.parent()).transpose()
|
expansion_info.arg().map(|node| node?.parent()).transpose()
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@ -1315,8 +1311,8 @@ impl<'db> SemanticsImpl<'db> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn resolve_label(&self, label: &ast::Lifetime) -> Option<Label> {
|
pub fn resolve_label(&self, label: &ast::Lifetime) -> Option<Label> {
|
||||||
let (parent, label_id) = self
|
let src = self.wrap_node_infile(label.clone());
|
||||||
.with_ctx(|ctx| ctx.label_ref_to_def(self.wrap_node_infile(label.clone()).as_ref()))?;
|
let (parent, label_id) = self.with_ctx(|ctx| ctx.label_ref_to_def(src.as_ref()))?;
|
||||||
Some(Label { parent, label_id })
|
Some(Label { parent, label_id })
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1443,6 +1439,10 @@ impl<'db> SemanticsImpl<'db> {
|
|||||||
self.analyze(call.syntax())?.resolve_method_call_fallback(self.db, call)
|
self.analyze(call.syntax())?.resolve_method_call_fallback(self.db, call)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn resolve_known_blanket_dual_impls(&self, call: &ast::MethodCallExpr) -> Option<Function> {
|
||||||
|
self.analyze(call.syntax())?.resolve_known_blanket_dual_impls(self.db, call)
|
||||||
|
}
|
||||||
|
|
||||||
fn resolve_range_pat(&self, range_pat: &ast::RangePat) -> Option<StructId> {
|
fn resolve_range_pat(&self, range_pat: &ast::RangePat) -> Option<StructId> {
|
||||||
self.analyze(range_pat.syntax())?.resolve_range_pat(self.db, range_pat)
|
self.analyze(range_pat.syntax())?.resolve_range_pat(self.db, range_pat)
|
||||||
}
|
}
|
||||||
@ -1516,7 +1516,7 @@ impl<'db> SemanticsImpl<'db> {
|
|||||||
let macro_call = self.find_file(macro_call.syntax()).with_value(macro_call);
|
let macro_call = self.find_file(macro_call.syntax()).with_value(macro_call);
|
||||||
self.with_ctx(|ctx| {
|
self.with_ctx(|ctx| {
|
||||||
ctx.macro_call_to_macro_call(macro_call)
|
ctx.macro_call_to_macro_call(macro_call)
|
||||||
.and_then(|call| macro_call_to_macro_id(self, ctx, call))
|
.and_then(|call| macro_call_to_macro_id(ctx, call))
|
||||||
.map(Into::into)
|
.map(Into::into)
|
||||||
})
|
})
|
||||||
.or_else(|| {
|
.or_else(|| {
|
||||||
@ -1558,7 +1558,7 @@ impl<'db> SemanticsImpl<'db> {
|
|||||||
let item_in_file = self.wrap_node_infile(item.clone());
|
let item_in_file = self.wrap_node_infile(item.clone());
|
||||||
let id = self.with_ctx(|ctx| {
|
let id = self.with_ctx(|ctx| {
|
||||||
let macro_call_id = ctx.item_to_macro_call(item_in_file.as_ref())?;
|
let macro_call_id = ctx.item_to_macro_call(item_in_file.as_ref())?;
|
||||||
macro_call_to_macro_id(self, ctx, macro_call_id)
|
macro_call_to_macro_id(ctx, macro_call_id)
|
||||||
})?;
|
})?;
|
||||||
Some(Macro { id })
|
Some(Macro { id })
|
||||||
}
|
}
|
||||||
@ -1591,14 +1591,11 @@ impl<'db> SemanticsImpl<'db> {
|
|||||||
pub fn resolve_mod_path_relative(
|
pub fn resolve_mod_path_relative(
|
||||||
&self,
|
&self,
|
||||||
to: Module,
|
to: Module,
|
||||||
segments: impl IntoIterator<Item = SmolStr>,
|
segments: impl IntoIterator<Item = Name>,
|
||||||
) -> Option<impl Iterator<Item = ItemInNs>> {
|
) -> Option<impl Iterator<Item = ItemInNs>> {
|
||||||
let items = to.id.resolver(self.db.upcast()).resolve_module_path_in_items(
|
let items = to.id.resolver(self.db.upcast()).resolve_module_path_in_items(
|
||||||
self.db.upcast(),
|
self.db.upcast(),
|
||||||
&ModPath::from_segments(
|
&ModPath::from_segments(hir_def::path::PathKind::Plain, segments),
|
||||||
hir_def::path::PathKind::Plain,
|
|
||||||
segments.into_iter().map(|it| Name::new(&it, SyntaxContextId::ROOT)),
|
|
||||||
),
|
|
||||||
);
|
);
|
||||||
Some(items.iter_items().map(|(item, _)| item.into()))
|
Some(items.iter_items().map(|(item, _)| item.into()))
|
||||||
}
|
}
|
||||||
@ -1722,10 +1719,11 @@ impl<'db> SemanticsImpl<'db> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn cache(&self, root_node: SyntaxNode, file_id: HirFileId) {
|
fn cache(&self, root_node: SyntaxNode, file_id: HirFileId) {
|
||||||
assert!(root_node.parent().is_none());
|
SourceToDefCache::cache(
|
||||||
let mut cache = self.root_to_file_cache.borrow_mut();
|
&mut self.s2d_cache.borrow_mut().root_to_file_cache,
|
||||||
let prev = cache.insert(root_node, file_id);
|
root_node,
|
||||||
assert!(prev.is_none() || prev == Some(file_id));
|
file_id,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn assert_contains_node(&self, node: &SyntaxNode) {
|
pub fn assert_contains_node(&self, node: &SyntaxNode) {
|
||||||
@ -1733,8 +1731,8 @@ impl<'db> SemanticsImpl<'db> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn lookup(&self, root_node: &SyntaxNode) -> Option<HirFileId> {
|
fn lookup(&self, root_node: &SyntaxNode) -> Option<HirFileId> {
|
||||||
let cache = self.root_to_file_cache.borrow();
|
let cache = self.s2d_cache.borrow();
|
||||||
cache.get(root_node).copied()
|
cache.root_to_file_cache.get(root_node).copied()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn wrap_node_infile<N: AstNode>(&self, node: N) -> InFile<N> {
|
fn wrap_node_infile<N: AstNode>(&self, node: N) -> InFile<N> {
|
||||||
@ -1753,13 +1751,14 @@ impl<'db> SemanticsImpl<'db> {
|
|||||||
let file_id = self.lookup(&root_node).unwrap_or_else(|| {
|
let file_id = self.lookup(&root_node).unwrap_or_else(|| {
|
||||||
panic!(
|
panic!(
|
||||||
"\n\nFailed to lookup {:?} in this Semantics.\n\
|
"\n\nFailed to lookup {:?} in this Semantics.\n\
|
||||||
Make sure to use only query nodes, derived from this instance of Semantics.\n\
|
Make sure to only query nodes derived from this instance of Semantics.\n\
|
||||||
root node: {:?}\n\
|
root node: {:?}\n\
|
||||||
known nodes: {}\n\n",
|
known nodes: {}\n\n",
|
||||||
node,
|
node,
|
||||||
root_node,
|
root_node,
|
||||||
self.root_to_file_cache
|
self.s2d_cache
|
||||||
.borrow()
|
.borrow()
|
||||||
|
.root_to_file_cache
|
||||||
.keys()
|
.keys()
|
||||||
.map(|it| format!("{it:?}"))
|
.map(|it| format!("{it:?}"))
|
||||||
.collect::<Vec<_>>()
|
.collect::<Vec<_>>()
|
||||||
@ -1906,7 +1905,6 @@ impl<'db> SemanticsImpl<'db> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn macro_call_to_macro_id(
|
fn macro_call_to_macro_id(
|
||||||
sema: &SemanticsImpl<'_>,
|
|
||||||
ctx: &mut SourceToDefCtx<'_, '_>,
|
ctx: &mut SourceToDefCtx<'_, '_>,
|
||||||
macro_call_id: MacroCallId,
|
macro_call_id: MacroCallId,
|
||||||
) -> Option<MacroId> {
|
) -> Option<MacroId> {
|
||||||
@ -1922,7 +1920,7 @@ fn macro_call_to_macro_id(
|
|||||||
it.to_ptr(db).to_node(&db.parse(file_id).syntax_node())
|
it.to_ptr(db).to_node(&db.parse(file_id).syntax_node())
|
||||||
}
|
}
|
||||||
HirFileIdRepr::MacroFile(macro_file) => {
|
HirFileIdRepr::MacroFile(macro_file) => {
|
||||||
let expansion_info = ctx.cache.get_or_insert_expansion(sema, macro_file);
|
let expansion_info = ctx.cache.get_or_insert_expansion(ctx.db, macro_file);
|
||||||
it.to_ptr(db).to_node(&expansion_info.expanded().value)
|
it.to_ptr(db).to_node(&expansion_info.expanded().value)
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@ -1934,7 +1932,7 @@ fn macro_call_to_macro_id(
|
|||||||
it.to_ptr(db).to_node(&db.parse(file_id).syntax_node())
|
it.to_ptr(db).to_node(&db.parse(file_id).syntax_node())
|
||||||
}
|
}
|
||||||
HirFileIdRepr::MacroFile(macro_file) => {
|
HirFileIdRepr::MacroFile(macro_file) => {
|
||||||
let expansion_info = ctx.cache.get_or_insert_expansion(sema, macro_file);
|
let expansion_info = ctx.cache.get_or_insert_expansion(ctx.db, macro_file);
|
||||||
it.to_ptr(db).to_node(&expansion_info.expanded().value)
|
it.to_ptr(db).to_node(&expansion_info.expanded().value)
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -56,7 +56,7 @@ impl ChildBySource for ImplId {
|
|||||||
res[keys::ATTR_MACRO_CALL].insert(ast_id.to_ptr(db.upcast()), call_id);
|
res[keys::ATTR_MACRO_CALL].insert(ast_id.to_ptr(db.upcast()), call_id);
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
data.items.iter().for_each(|&item| {
|
data.items.iter().for_each(|&(_, item)| {
|
||||||
add_assoc_item(db, res, file_id, item);
|
add_assoc_item(db, res, file_id, item);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -110,10 +110,7 @@ use syntax::{
|
|||||||
AstNode, AstPtr, SyntaxNode,
|
AstNode, AstPtr, SyntaxNode,
|
||||||
};
|
};
|
||||||
|
|
||||||
use crate::{
|
use crate::{db::HirDatabase, semantics::child_by_source::ChildBySource, InFile, InlineAsmOperand};
|
||||||
db::HirDatabase, semantics::child_by_source::ChildBySource, InFile, InlineAsmOperand,
|
|
||||||
SemanticsImpl,
|
|
||||||
};
|
|
||||||
|
|
||||||
#[derive(Default)]
|
#[derive(Default)]
|
||||||
pub(super) struct SourceToDefCache {
|
pub(super) struct SourceToDefCache {
|
||||||
@ -121,9 +118,21 @@ pub(super) struct SourceToDefCache {
|
|||||||
expansion_info_cache: FxHashMap<MacroFileId, ExpansionInfo>,
|
expansion_info_cache: FxHashMap<MacroFileId, ExpansionInfo>,
|
||||||
pub(super) file_to_def_cache: FxHashMap<FileId, SmallVec<[ModuleId; 1]>>,
|
pub(super) file_to_def_cache: FxHashMap<FileId, SmallVec<[ModuleId; 1]>>,
|
||||||
pub(super) included_file_cache: FxHashMap<EditionedFileId, Option<MacroFileId>>,
|
pub(super) included_file_cache: FxHashMap<EditionedFileId, Option<MacroFileId>>,
|
||||||
|
/// Rootnode to HirFileId cache
|
||||||
|
pub(super) root_to_file_cache: FxHashMap<SyntaxNode, HirFileId>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl SourceToDefCache {
|
impl SourceToDefCache {
|
||||||
|
pub(super) fn cache(
|
||||||
|
root_to_file_cache: &mut FxHashMap<SyntaxNode, HirFileId>,
|
||||||
|
root_node: SyntaxNode,
|
||||||
|
file_id: HirFileId,
|
||||||
|
) {
|
||||||
|
assert!(root_node.parent().is_none());
|
||||||
|
let prev = root_to_file_cache.insert(root_node, file_id);
|
||||||
|
assert!(prev.is_none() || prev == Some(file_id));
|
||||||
|
}
|
||||||
|
|
||||||
pub(super) fn get_or_insert_include_for(
|
pub(super) fn get_or_insert_include_for(
|
||||||
&mut self,
|
&mut self,
|
||||||
db: &dyn HirDatabase,
|
db: &dyn HirDatabase,
|
||||||
@ -143,14 +152,14 @@ impl SourceToDefCache {
|
|||||||
|
|
||||||
pub(super) fn get_or_insert_expansion(
|
pub(super) fn get_or_insert_expansion(
|
||||||
&mut self,
|
&mut self,
|
||||||
sema: &SemanticsImpl<'_>,
|
db: &dyn HirDatabase,
|
||||||
macro_file: MacroFileId,
|
macro_file: MacroFileId,
|
||||||
) -> &ExpansionInfo {
|
) -> &ExpansionInfo {
|
||||||
self.expansion_info_cache.entry(macro_file).or_insert_with(|| {
|
self.expansion_info_cache.entry(macro_file).or_insert_with(|| {
|
||||||
let exp_info = macro_file.expansion_info(sema.db.upcast());
|
let exp_info = macro_file.expansion_info(db.upcast());
|
||||||
|
|
||||||
let InMacroFile { file_id, value } = exp_info.expanded();
|
let InMacroFile { file_id, value } = exp_info.expanded();
|
||||||
sema.cache(value, file_id.into());
|
Self::cache(&mut self.root_to_file_cache, value, file_id.into());
|
||||||
|
|
||||||
exp_info
|
exp_info
|
||||||
})
|
})
|
||||||
@ -520,18 +529,11 @@ impl SourceToDefCtx<'_, '_> {
|
|||||||
node: InFile<&SyntaxNode>,
|
node: InFile<&SyntaxNode>,
|
||||||
mut cb: impl FnMut(&mut Self, InFile<SyntaxNode>) -> Option<T>,
|
mut cb: impl FnMut(&mut Self, InFile<SyntaxNode>) -> Option<T>,
|
||||||
) -> Option<T> {
|
) -> Option<T> {
|
||||||
use hir_expand::MacroFileIdExt;
|
|
||||||
let parent = |this: &mut Self, node: InFile<&SyntaxNode>| match node.value.parent() {
|
let parent = |this: &mut Self, node: InFile<&SyntaxNode>| match node.value.parent() {
|
||||||
Some(parent) => Some(node.with_value(parent)),
|
Some(parent) => Some(node.with_value(parent)),
|
||||||
None => {
|
None => {
|
||||||
let macro_file = node.file_id.macro_file()?;
|
let macro_file = node.file_id.macro_file()?;
|
||||||
|
let expansion_info = this.cache.get_or_insert_expansion(this.db, macro_file);
|
||||||
let expansion_info = this
|
|
||||||
.cache
|
|
||||||
.expansion_info_cache
|
|
||||||
.entry(macro_file)
|
|
||||||
.or_insert_with(|| macro_file.expansion_info(this.db.upcast()));
|
|
||||||
|
|
||||||
expansion_info.arg().map(|node| node?.parent()).transpose()
|
expansion_info.arg().map(|node| node?.parent()).transpose()
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -322,6 +322,68 @@ impl SourceAnalyzer {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// If the method is into(), try_into(), parse(), resolve it to from, try_from, from_str.
|
||||||
|
pub(crate) fn resolve_known_blanket_dual_impls(
|
||||||
|
&self,
|
||||||
|
db: &dyn HirDatabase,
|
||||||
|
call: &ast::MethodCallExpr,
|
||||||
|
) -> Option<Function> {
|
||||||
|
// e.g. if the method call is let b = a.into(),
|
||||||
|
// - receiver_type is A (type of a)
|
||||||
|
// - return_type is B (type of b)
|
||||||
|
// We will find the definition of B::from(a: A).
|
||||||
|
let callable = self.resolve_method_call_as_callable(db, call)?;
|
||||||
|
let (_, receiver_type) = callable.receiver_param(db)?;
|
||||||
|
let return_type = callable.return_type();
|
||||||
|
let (search_method, substs) = match call.name_ref()?.text().as_str() {
|
||||||
|
"into" => {
|
||||||
|
let trait_ =
|
||||||
|
self.resolver.resolve_known_trait(db.upcast(), &path![core::convert::From])?;
|
||||||
|
(
|
||||||
|
self.trait_fn(db, trait_, "from")?,
|
||||||
|
hir_ty::TyBuilder::subst_for_def(db, trait_, None)
|
||||||
|
.push(return_type.ty)
|
||||||
|
.push(receiver_type.ty)
|
||||||
|
.build(),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
"try_into" => {
|
||||||
|
let trait_ = self
|
||||||
|
.resolver
|
||||||
|
.resolve_known_trait(db.upcast(), &path![core::convert::TryFrom])?;
|
||||||
|
(
|
||||||
|
self.trait_fn(db, trait_, "try_from")?,
|
||||||
|
hir_ty::TyBuilder::subst_for_def(db, trait_, None)
|
||||||
|
// If the method is try_into() or parse(), return_type is Result<T, Error>.
|
||||||
|
// Get T from type arguments of Result<T, Error>.
|
||||||
|
.push(return_type.type_arguments().next()?.ty)
|
||||||
|
.push(receiver_type.ty)
|
||||||
|
.build(),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
"parse" => {
|
||||||
|
let trait_ =
|
||||||
|
self.resolver.resolve_known_trait(db.upcast(), &path![core::str::FromStr])?;
|
||||||
|
(
|
||||||
|
self.trait_fn(db, trait_, "from_str")?,
|
||||||
|
hir_ty::TyBuilder::subst_for_def(db, trait_, None)
|
||||||
|
.push(return_type.type_arguments().next()?.ty)
|
||||||
|
.build(),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
_ => return None,
|
||||||
|
};
|
||||||
|
|
||||||
|
let found_method = self.resolve_impl_method_or_trait_def(db, search_method, substs);
|
||||||
|
// If found_method == search_method, the method in trait itself is resolved.
|
||||||
|
// It means the blanket dual impl is not found.
|
||||||
|
if found_method == search_method {
|
||||||
|
None
|
||||||
|
} else {
|
||||||
|
Some(found_method.into())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub(crate) fn resolve_expr_as_callable(
|
pub(crate) fn resolve_expr_as_callable(
|
||||||
&self,
|
&self,
|
||||||
db: &dyn HirDatabase,
|
db: &dyn HirDatabase,
|
||||||
@ -1247,6 +1309,18 @@ impl SourceAnalyzer {
|
|||||||
Some((trait_id, fn_id))
|
Some((trait_id, fn_id))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn trait_fn(
|
||||||
|
&self,
|
||||||
|
db: &dyn HirDatabase,
|
||||||
|
trait_id: TraitId,
|
||||||
|
method_name: &str,
|
||||||
|
) -> Option<FunctionId> {
|
||||||
|
db.trait_data(trait_id).items.iter().find_map(|(item_name, item)| match item {
|
||||||
|
AssocItemId::FunctionId(t) if item_name.as_str() == method_name => Some(*t),
|
||||||
|
_ => None,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
fn ty_of_expr(&self, db: &dyn HirDatabase, expr: &ast::Expr) -> Option<&Ty> {
|
fn ty_of_expr(&self, db: &dyn HirDatabase, expr: &ast::Expr) -> Option<&Ty> {
|
||||||
self.infer.as_ref()?.type_of_expr_or_pat(self.expr_id(db, expr)?)
|
self.infer.as_ref()?.type_of_expr_or_pat(self.expr_id(db, expr)?)
|
||||||
}
|
}
|
||||||
|
@ -1,27 +1,34 @@
|
|||||||
//! File symbol extraction.
|
//! File symbol extraction.
|
||||||
|
|
||||||
|
use either::Either;
|
||||||
use hir_def::{
|
use hir_def::{
|
||||||
db::DefDatabase,
|
db::DefDatabase,
|
||||||
item_scope::ItemInNs,
|
item_scope::{ImportId, ImportOrExternCrate},
|
||||||
|
per_ns::Item,
|
||||||
src::{HasChildSource, HasSource},
|
src::{HasChildSource, HasSource},
|
||||||
AdtId, AssocItemId, DefWithBodyId, HasModule, ImplId, Lookup, MacroId, ModuleDefId, ModuleId,
|
visibility::{Visibility, VisibilityExplicitness},
|
||||||
TraitId,
|
AdtId, AssocItemId, DefWithBodyId, ExternCrateId, HasModule, ImplId, Lookup, MacroId,
|
||||||
|
ModuleDefId, ModuleId, TraitId,
|
||||||
};
|
};
|
||||||
use hir_expand::HirFileId;
|
use hir_expand::{name::Name, HirFileId};
|
||||||
use hir_ty::{
|
use hir_ty::{
|
||||||
db::HirDatabase,
|
db::HirDatabase,
|
||||||
display::{hir_display_with_types_map, HirDisplay},
|
display::{hir_display_with_types_map, HirDisplay},
|
||||||
};
|
};
|
||||||
|
use intern::Symbol;
|
||||||
|
use rustc_hash::FxHashMap;
|
||||||
use span::Edition;
|
use span::Edition;
|
||||||
use syntax::{ast::HasName, AstNode, AstPtr, SmolStr, SyntaxNode, SyntaxNodePtr, ToSmolStr};
|
use syntax::{ast::HasName, AstNode, AstPtr, SmolStr, SyntaxNode, SyntaxNodePtr, ToSmolStr};
|
||||||
|
|
||||||
use crate::{Module, ModuleDef, Semantics};
|
use crate::{Module, ModuleDef, Semantics};
|
||||||
|
|
||||||
|
pub type FxIndexSet<T> = indexmap::IndexSet<T, std::hash::BuildHasherDefault<rustc_hash::FxHasher>>;
|
||||||
|
|
||||||
/// The actual data that is stored in the index. It should be as compact as
|
/// The actual data that is stored in the index. It should be as compact as
|
||||||
/// possible.
|
/// possible.
|
||||||
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
|
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
|
||||||
pub struct FileSymbol {
|
pub struct FileSymbol {
|
||||||
pub name: SmolStr,
|
pub name: Symbol,
|
||||||
pub def: ModuleDef,
|
pub def: ModuleDef,
|
||||||
pub loc: DeclarationLocation,
|
pub loc: DeclarationLocation,
|
||||||
pub container_name: Option<SmolStr>,
|
pub container_name: Option<SmolStr>,
|
||||||
@ -37,7 +44,7 @@ pub struct DeclarationLocation {
|
|||||||
/// This points to the whole syntax node of the declaration.
|
/// This points to the whole syntax node of the declaration.
|
||||||
pub ptr: SyntaxNodePtr,
|
pub ptr: SyntaxNodePtr,
|
||||||
/// This points to the [`syntax::ast::Name`] identifier of the declaration.
|
/// This points to the [`syntax::ast::Name`] identifier of the declaration.
|
||||||
pub name_ptr: AstPtr<syntax::ast::Name>,
|
pub name_ptr: AstPtr<Either<syntax::ast::Name, syntax::ast::NameRef>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl DeclarationLocation {
|
impl DeclarationLocation {
|
||||||
@ -55,7 +62,7 @@ struct SymbolCollectorWork {
|
|||||||
|
|
||||||
pub struct SymbolCollector<'a> {
|
pub struct SymbolCollector<'a> {
|
||||||
db: &'a dyn HirDatabase,
|
db: &'a dyn HirDatabase,
|
||||||
symbols: Vec<FileSymbol>,
|
symbols: FxIndexSet<FileSymbol>,
|
||||||
work: Vec<SymbolCollectorWork>,
|
work: Vec<SymbolCollectorWork>,
|
||||||
current_container_name: Option<SmolStr>,
|
current_container_name: Option<SmolStr>,
|
||||||
edition: Edition,
|
edition: Edition,
|
||||||
@ -86,11 +93,11 @@ impl<'a> SymbolCollector<'a> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn finish(self) -> Vec<FileSymbol> {
|
pub fn finish(self) -> Box<[FileSymbol]> {
|
||||||
self.symbols
|
self.symbols.into_iter().collect()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn collect_module(db: &dyn HirDatabase, module: Module) -> Vec<FileSymbol> {
|
pub fn collect_module(db: &dyn HirDatabase, module: Module) -> Box<[FileSymbol]> {
|
||||||
let mut symbol_collector = SymbolCollector::new(db);
|
let mut symbol_collector = SymbolCollector::new(db);
|
||||||
symbol_collector.collect(module);
|
symbol_collector.collect(module);
|
||||||
symbol_collector.finish()
|
symbol_collector.finish()
|
||||||
@ -104,96 +111,174 @@ impl<'a> SymbolCollector<'a> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn collect_from_module(&mut self, module_id: ModuleId) {
|
fn collect_from_module(&mut self, module_id: ModuleId) {
|
||||||
let def_map = module_id.def_map(self.db.upcast());
|
let push_decl = |this: &mut Self, def, name| {
|
||||||
let scope = &def_map[module_id.local_id].scope;
|
match def {
|
||||||
|
ModuleDefId::ModuleId(id) => this.push_module(id, name),
|
||||||
for module_def_id in scope.declarations() {
|
|
||||||
match module_def_id {
|
|
||||||
ModuleDefId::ModuleId(id) => self.push_module(id),
|
|
||||||
ModuleDefId::FunctionId(id) => {
|
ModuleDefId::FunctionId(id) => {
|
||||||
self.push_decl(id, false);
|
this.push_decl(id, name, false);
|
||||||
self.collect_from_body(id);
|
this.collect_from_body(id);
|
||||||
}
|
}
|
||||||
ModuleDefId::AdtId(AdtId::StructId(id)) => self.push_decl(id, false),
|
ModuleDefId::AdtId(AdtId::StructId(id)) => this.push_decl(id, name, false),
|
||||||
ModuleDefId::AdtId(AdtId::EnumId(id)) => self.push_decl(id, false),
|
ModuleDefId::AdtId(AdtId::EnumId(id)) => this.push_decl(id, name, false),
|
||||||
ModuleDefId::AdtId(AdtId::UnionId(id)) => self.push_decl(id, false),
|
ModuleDefId::AdtId(AdtId::UnionId(id)) => this.push_decl(id, name, false),
|
||||||
ModuleDefId::ConstId(id) => {
|
ModuleDefId::ConstId(id) => {
|
||||||
self.push_decl(id, false);
|
this.push_decl(id, name, false);
|
||||||
self.collect_from_body(id);
|
this.collect_from_body(id);
|
||||||
}
|
}
|
||||||
ModuleDefId::StaticId(id) => {
|
ModuleDefId::StaticId(id) => {
|
||||||
self.push_decl(id, false);
|
this.push_decl(id, name, false);
|
||||||
self.collect_from_body(id);
|
this.collect_from_body(id);
|
||||||
}
|
}
|
||||||
ModuleDefId::TraitId(id) => {
|
ModuleDefId::TraitId(id) => {
|
||||||
self.push_decl(id, false);
|
this.push_decl(id, name, false);
|
||||||
self.collect_from_trait(id);
|
this.collect_from_trait(id);
|
||||||
}
|
}
|
||||||
ModuleDefId::TraitAliasId(id) => {
|
ModuleDefId::TraitAliasId(id) => {
|
||||||
self.push_decl(id, false);
|
this.push_decl(id, name, false);
|
||||||
}
|
}
|
||||||
ModuleDefId::TypeAliasId(id) => {
|
ModuleDefId::TypeAliasId(id) => {
|
||||||
self.push_decl(id, false);
|
this.push_decl(id, name, false);
|
||||||
}
|
}
|
||||||
ModuleDefId::MacroId(id) => match id {
|
ModuleDefId::MacroId(id) => match id {
|
||||||
MacroId::Macro2Id(id) => self.push_decl(id, false),
|
MacroId::Macro2Id(id) => this.push_decl(id, name, false),
|
||||||
MacroId::MacroRulesId(id) => self.push_decl(id, false),
|
MacroId::MacroRulesId(id) => this.push_decl(id, name, false),
|
||||||
MacroId::ProcMacroId(id) => self.push_decl(id, false),
|
MacroId::ProcMacroId(id) => this.push_decl(id, name, false),
|
||||||
},
|
},
|
||||||
// Don't index these.
|
// Don't index these.
|
||||||
ModuleDefId::BuiltinType(_) => {}
|
ModuleDefId::BuiltinType(_) => {}
|
||||||
ModuleDefId::EnumVariantId(_) => {}
|
ModuleDefId::EnumVariantId(_) => {}
|
||||||
}
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// Nested trees are very common, so a cache here will hit a lot.
|
||||||
|
let import_child_source_cache = &mut FxHashMap::default();
|
||||||
|
|
||||||
|
let mut push_import = |this: &mut Self, i: ImportId, name: &Name, def: ModuleDefId| {
|
||||||
|
let source = import_child_source_cache
|
||||||
|
.entry(i.import)
|
||||||
|
.or_insert_with(|| i.import.child_source(this.db.upcast()));
|
||||||
|
let Some(use_tree_src) = source.value.get(i.idx) else { return };
|
||||||
|
let Some(name_ptr) = use_tree_src
|
||||||
|
.rename()
|
||||||
|
.and_then(|rename| rename.name())
|
||||||
|
.map(Either::Left)
|
||||||
|
.or_else(|| use_tree_src.path()?.segment()?.name_ref().map(Either::Right))
|
||||||
|
.map(|it| AstPtr::new(&it))
|
||||||
|
else {
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
let dec_loc = DeclarationLocation {
|
||||||
|
hir_file_id: source.file_id,
|
||||||
|
ptr: SyntaxNodePtr::new(use_tree_src.syntax()),
|
||||||
|
name_ptr,
|
||||||
|
};
|
||||||
|
this.symbols.insert(FileSymbol {
|
||||||
|
name: name.symbol().clone(),
|
||||||
|
def: def.into(),
|
||||||
|
container_name: this.current_container_name.clone(),
|
||||||
|
loc: dec_loc,
|
||||||
|
is_alias: false,
|
||||||
|
is_assoc: false,
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
let push_extern_crate =
|
||||||
|
|this: &mut Self, i: ExternCrateId, name: &Name, def: ModuleDefId| {
|
||||||
|
let loc = i.lookup(this.db.upcast());
|
||||||
|
let source = loc.source(this.db.upcast());
|
||||||
|
let Some(name_ptr) = source
|
||||||
|
.value
|
||||||
|
.rename()
|
||||||
|
.and_then(|rename| rename.name())
|
||||||
|
.map(Either::Left)
|
||||||
|
.or_else(|| source.value.name_ref().map(Either::Right))
|
||||||
|
.map(|it| AstPtr::new(&it))
|
||||||
|
else {
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
let dec_loc = DeclarationLocation {
|
||||||
|
hir_file_id: source.file_id,
|
||||||
|
ptr: SyntaxNodePtr::new(source.value.syntax()),
|
||||||
|
name_ptr,
|
||||||
|
};
|
||||||
|
this.symbols.insert(FileSymbol {
|
||||||
|
name: name.symbol().clone(),
|
||||||
|
def: def.into(),
|
||||||
|
container_name: this.current_container_name.clone(),
|
||||||
|
loc: dec_loc,
|
||||||
|
is_alias: false,
|
||||||
|
is_assoc: false,
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
let is_explicit_import = |vis| {
|
||||||
|
match vis {
|
||||||
|
Visibility::Module(_, VisibilityExplicitness::Explicit) => true,
|
||||||
|
Visibility::Module(_, VisibilityExplicitness::Implicit) => {
|
||||||
|
// consider imports in the crate root explicit, as these are visibly
|
||||||
|
// crate-wide anyways
|
||||||
|
module_id.is_crate_root()
|
||||||
}
|
}
|
||||||
|
Visibility::Public => true,
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
let def_map = module_id.def_map(self.db.upcast());
|
||||||
|
let scope = &def_map[module_id.local_id].scope;
|
||||||
|
|
||||||
for impl_id in scope.impls() {
|
for impl_id in scope.impls() {
|
||||||
self.collect_from_impl(impl_id);
|
self.collect_from_impl(impl_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Record renamed imports.
|
for (name, Item { def, vis, import }) in scope.types() {
|
||||||
// FIXME: In case it imports multiple items under different namespaces we just pick one arbitrarily
|
if let Some(i) = import {
|
||||||
// for now.
|
if is_explicit_import(vis) {
|
||||||
for id in scope.imports() {
|
match i {
|
||||||
let source = id.import.child_source(self.db.upcast());
|
ImportOrExternCrate::Import(i) => push_import(self, i, name, def),
|
||||||
let Some(use_tree_src) = source.value.get(id.idx) else { continue };
|
ImportOrExternCrate::ExternCrate(i) => {
|
||||||
let Some(rename) = use_tree_src.rename() else { continue };
|
push_extern_crate(self, i, name, def)
|
||||||
let Some(name) = rename.name() else { continue };
|
}
|
||||||
|
}
|
||||||
let res = scope.fully_resolve_import(self.db.upcast(), id);
|
}
|
||||||
res.iter_items().for_each(|(item, _)| {
|
continue;
|
||||||
let def = match item {
|
}
|
||||||
ItemInNs::Types(def) | ItemInNs::Values(def) => def,
|
// self is a declaration
|
||||||
ItemInNs::Macros(def) => ModuleDefId::from(def),
|
push_decl(self, def, name)
|
||||||
}
|
}
|
||||||
.into();
|
|
||||||
let dec_loc = DeclarationLocation {
|
|
||||||
hir_file_id: source.file_id,
|
|
||||||
ptr: SyntaxNodePtr::new(use_tree_src.syntax()),
|
|
||||||
name_ptr: AstPtr::new(&name),
|
|
||||||
};
|
|
||||||
|
|
||||||
self.symbols.push(FileSymbol {
|
for (name, Item { def, vis, import }) in scope.macros() {
|
||||||
name: name.text().into(),
|
if let Some(i) = import {
|
||||||
def,
|
if is_explicit_import(vis) {
|
||||||
container_name: self.current_container_name.clone(),
|
push_import(self, i, name, def.into());
|
||||||
loc: dec_loc,
|
}
|
||||||
is_alias: false,
|
continue;
|
||||||
is_assoc: false,
|
}
|
||||||
});
|
// self is a declaration
|
||||||
});
|
push_decl(self, def.into(), name)
|
||||||
|
}
|
||||||
|
|
||||||
|
for (name, Item { def, vis, import }) in scope.values() {
|
||||||
|
if let Some(i) = import {
|
||||||
|
if is_explicit_import(vis) {
|
||||||
|
push_import(self, i, name, def);
|
||||||
|
}
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
// self is a declaration
|
||||||
|
push_decl(self, def, name)
|
||||||
}
|
}
|
||||||
|
|
||||||
for const_id in scope.unnamed_consts() {
|
for const_id in scope.unnamed_consts() {
|
||||||
self.collect_from_body(const_id);
|
self.collect_from_body(const_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (_, id) in scope.legacy_macros() {
|
for (name, id) in scope.legacy_macros() {
|
||||||
for &id in id {
|
for &id in id {
|
||||||
if id.module(self.db.upcast()) == module_id {
|
if id.module(self.db.upcast()) == module_id {
|
||||||
match id {
|
match id {
|
||||||
MacroId::Macro2Id(id) => self.push_decl(id, false),
|
MacroId::Macro2Id(id) => self.push_decl(id, name, false),
|
||||||
MacroId::MacroRulesId(id) => self.push_decl(id, false),
|
MacroId::MacroRulesId(id) => self.push_decl(id, name, false),
|
||||||
MacroId::ProcMacroId(id) => self.push_decl(id, false),
|
MacroId::ProcMacroId(id) => self.push_decl(id, name, false),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -223,8 +308,8 @@ impl<'a> SymbolCollector<'a> {
|
|||||||
.to_smolstr(),
|
.to_smolstr(),
|
||||||
);
|
);
|
||||||
self.with_container_name(impl_name, |s| {
|
self.with_container_name(impl_name, |s| {
|
||||||
for &assoc_item_id in impl_data.items.iter() {
|
for &(ref name, assoc_item_id) in &impl_data.items {
|
||||||
s.push_assoc_item(assoc_item_id)
|
s.push_assoc_item(assoc_item_id, name)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@ -232,8 +317,8 @@ impl<'a> SymbolCollector<'a> {
|
|||||||
fn collect_from_trait(&mut self, trait_id: TraitId) {
|
fn collect_from_trait(&mut self, trait_id: TraitId) {
|
||||||
let trait_data = self.db.trait_data(trait_id);
|
let trait_data = self.db.trait_data(trait_id);
|
||||||
self.with_container_name(Some(trait_data.name.as_str().into()), |s| {
|
self.with_container_name(Some(trait_data.name.as_str().into()), |s| {
|
||||||
for &(_, assoc_item_id) in &trait_data.items {
|
for &(ref name, assoc_item_id) in &trait_data.items {
|
||||||
s.push_assoc_item(assoc_item_id);
|
s.push_assoc_item(assoc_item_id, name);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -266,15 +351,15 @@ impl<'a> SymbolCollector<'a> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn push_assoc_item(&mut self, assoc_item_id: AssocItemId) {
|
fn push_assoc_item(&mut self, assoc_item_id: AssocItemId, name: &Name) {
|
||||||
match assoc_item_id {
|
match assoc_item_id {
|
||||||
AssocItemId::FunctionId(id) => self.push_decl(id, true),
|
AssocItemId::FunctionId(id) => self.push_decl(id, name, true),
|
||||||
AssocItemId::ConstId(id) => self.push_decl(id, true),
|
AssocItemId::ConstId(id) => self.push_decl(id, name, true),
|
||||||
AssocItemId::TypeAliasId(id) => self.push_decl(id, true),
|
AssocItemId::TypeAliasId(id) => self.push_decl(id, name, true),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn push_decl<'db, L>(&mut self, id: L, is_assoc: bool)
|
fn push_decl<'db, L>(&mut self, id: L, name: &Name, is_assoc: bool)
|
||||||
where
|
where
|
||||||
L: Lookup<Database<'db> = dyn DefDatabase + 'db> + Into<ModuleDefId>,
|
L: Lookup<Database<'db> = dyn DefDatabase + 'db> + Into<ModuleDefId>,
|
||||||
<L as Lookup>::Data: HasSource,
|
<L as Lookup>::Data: HasSource,
|
||||||
@ -287,13 +372,13 @@ impl<'a> SymbolCollector<'a> {
|
|||||||
let dec_loc = DeclarationLocation {
|
let dec_loc = DeclarationLocation {
|
||||||
hir_file_id: source.file_id,
|
hir_file_id: source.file_id,
|
||||||
ptr: SyntaxNodePtr::new(source.value.syntax()),
|
ptr: SyntaxNodePtr::new(source.value.syntax()),
|
||||||
name_ptr: AstPtr::new(&name_node),
|
name_ptr: AstPtr::new(&name_node).wrap_left(),
|
||||||
};
|
};
|
||||||
|
|
||||||
if let Some(attrs) = def.attrs(self.db) {
|
if let Some(attrs) = def.attrs(self.db) {
|
||||||
for alias in attrs.doc_aliases() {
|
for alias in attrs.doc_aliases() {
|
||||||
self.symbols.push(FileSymbol {
|
self.symbols.insert(FileSymbol {
|
||||||
name: alias.as_str().into(),
|
name: alias.clone(),
|
||||||
def,
|
def,
|
||||||
loc: dec_loc.clone(),
|
loc: dec_loc.clone(),
|
||||||
container_name: self.current_container_name.clone(),
|
container_name: self.current_container_name.clone(),
|
||||||
@ -303,8 +388,8 @@ impl<'a> SymbolCollector<'a> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
self.symbols.push(FileSymbol {
|
self.symbols.insert(FileSymbol {
|
||||||
name: name_node.text().into(),
|
name: name.symbol().clone(),
|
||||||
def,
|
def,
|
||||||
container_name: self.current_container_name.clone(),
|
container_name: self.current_container_name.clone(),
|
||||||
loc: dec_loc,
|
loc: dec_loc,
|
||||||
@ -313,7 +398,7 @@ impl<'a> SymbolCollector<'a> {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
fn push_module(&mut self, module_id: ModuleId) {
|
fn push_module(&mut self, module_id: ModuleId, name: &Name) {
|
||||||
let def_map = module_id.def_map(self.db.upcast());
|
let def_map = module_id.def_map(self.db.upcast());
|
||||||
let module_data = &def_map[module_id.local_id];
|
let module_data = &def_map[module_id.local_id];
|
||||||
let Some(declaration) = module_data.origin.declaration() else { return };
|
let Some(declaration) = module_data.origin.declaration() else { return };
|
||||||
@ -322,15 +407,15 @@ impl<'a> SymbolCollector<'a> {
|
|||||||
let dec_loc = DeclarationLocation {
|
let dec_loc = DeclarationLocation {
|
||||||
hir_file_id: declaration.file_id,
|
hir_file_id: declaration.file_id,
|
||||||
ptr: SyntaxNodePtr::new(module.syntax()),
|
ptr: SyntaxNodePtr::new(module.syntax()),
|
||||||
name_ptr: AstPtr::new(&name_node),
|
name_ptr: AstPtr::new(&name_node).wrap_left(),
|
||||||
};
|
};
|
||||||
|
|
||||||
let def = ModuleDef::Module(module_id.into());
|
let def = ModuleDef::Module(module_id.into());
|
||||||
|
|
||||||
if let Some(attrs) = def.attrs(self.db) {
|
if let Some(attrs) = def.attrs(self.db) {
|
||||||
for alias in attrs.doc_aliases() {
|
for alias in attrs.doc_aliases() {
|
||||||
self.symbols.push(FileSymbol {
|
self.symbols.insert(FileSymbol {
|
||||||
name: alias.as_str().into(),
|
name: alias.clone(),
|
||||||
def,
|
def,
|
||||||
loc: dec_loc.clone(),
|
loc: dec_loc.clone(),
|
||||||
container_name: self.current_container_name.clone(),
|
container_name: self.current_container_name.clone(),
|
||||||
@ -340,8 +425,8 @@ impl<'a> SymbolCollector<'a> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
self.symbols.push(FileSymbol {
|
self.symbols.insert(FileSymbol {
|
||||||
name: name_node.text().into(),
|
name: name.symbol().clone(),
|
||||||
def: ModuleDef::Module(module_id.into()),
|
def: ModuleDef::Module(module_id.into()),
|
||||||
container_name: self.current_container_name.clone(),
|
container_name: self.current_container_name.clone(),
|
||||||
loc: dec_loc,
|
loc: dec_loc,
|
||||||
|
@ -109,6 +109,10 @@ impl<'a> AssistContext<'a> {
|
|||||||
self.trimmed_range
|
self.trimmed_range
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub(crate) fn source_file(&self) -> &SourceFile {
|
||||||
|
&self.source_file
|
||||||
|
}
|
||||||
|
|
||||||
pub(crate) fn token_at_offset(&self) -> TokenAtOffset<SyntaxToken> {
|
pub(crate) fn token_at_offset(&self) -> TokenAtOffset<SyntaxToken> {
|
||||||
self.source_file.syntax().token_at_offset(self.offset())
|
self.source_file.syntax().token_at_offset(self.offset())
|
||||||
}
|
}
|
||||||
|
@ -212,8 +212,7 @@ pub(crate) fn add_missing_match_arms(acc: &mut Assists, ctx: &AssistContext<'_>)
|
|||||||
!hidden
|
!hidden
|
||||||
})
|
})
|
||||||
.map(|(pat, _)| {
|
.map(|(pat, _)| {
|
||||||
make::match_arm(iter::once(pat), None, make::ext::expr_todo())
|
make::match_arm(pat, None, make::ext::expr_todo()).clone_for_update()
|
||||||
.clone_for_update()
|
|
||||||
});
|
});
|
||||||
|
|
||||||
let catch_all_arm = new_match_arm_list
|
let catch_all_arm = new_match_arm_list
|
||||||
@ -243,11 +242,8 @@ pub(crate) fn add_missing_match_arms(acc: &mut Assists, ctx: &AssistContext<'_>)
|
|||||||
|
|
||||||
if needs_catch_all_arm && !has_catch_all_arm {
|
if needs_catch_all_arm && !has_catch_all_arm {
|
||||||
cov_mark::hit!(added_wildcard_pattern);
|
cov_mark::hit!(added_wildcard_pattern);
|
||||||
let arm = make::match_arm(
|
let arm =
|
||||||
iter::once(make::wildcard_pat().into()),
|
make::match_arm(make::wildcard_pat().into(), None, make::ext::expr_todo())
|
||||||
None,
|
|
||||||
make::ext::expr_todo(),
|
|
||||||
)
|
|
||||||
.clone_for_update();
|
.clone_for_update();
|
||||||
todo_placeholders.push(arm.expr().unwrap());
|
todo_placeholders.push(arm.expr().unwrap());
|
||||||
added_arms.push(arm);
|
added_arms.push(arm);
|
||||||
|
@ -189,7 +189,7 @@ pub(crate) fn add_turbo_fish(acc: &mut Assists, ctx: &AssistContext<'_>) -> Opti
|
|||||||
/// This will create a turbofish generic arg list corresponding to the number of arguments
|
/// This will create a turbofish generic arg list corresponding to the number of arguments
|
||||||
fn get_fish_head(make: &SyntaxFactory, number_of_arguments: usize) -> ast::GenericArgList {
|
fn get_fish_head(make: &SyntaxFactory, number_of_arguments: usize) -> ast::GenericArgList {
|
||||||
let args = (0..number_of_arguments).map(|_| make::type_arg(make::ty_placeholder()).into());
|
let args = (0..number_of_arguments).map(|_| make::type_arg(make::ty_placeholder()).into());
|
||||||
make.turbofish_generic_arg_list(args)
|
make.generic_arg_list(args, true)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
|
@ -252,7 +252,7 @@ fn tail_cb_impl(edit: &mut SourceChangeBuilder, e: &ast::Expr) {
|
|||||||
|
|
||||||
/// Add bang and parentheses to the expression.
|
/// Add bang and parentheses to the expression.
|
||||||
fn add_bang_paren(expr: ast::Expr) -> ast::Expr {
|
fn add_bang_paren(expr: ast::Expr) -> ast::Expr {
|
||||||
make::expr_prefix(T![!], make::expr_paren(expr))
|
make::expr_prefix(T![!], make::expr_paren(expr)).into()
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user