Unnamed repository; edit this file 'description' to name the repository.
-rw-r--r--Cargo.lock1
-rw-r--r--Cargo.toml1
-rw-r--r--crates/base-db/Cargo.toml1
-rw-r--r--crates/base-db/src/input.rs13
-rw-r--r--crates/base-db/src/lib.rs2
-rw-r--r--crates/hir-def/src/macro_expansion_tests/mbe/meta_syntax.rs4
-rw-r--r--crates/hir-def/src/macro_expansion_tests/mbe/metavar_expr.rs78
-rw-r--r--crates/hir-expand/src/db.rs67
-rw-r--r--crates/ide-completion/src/context.rs2
-rw-r--r--crates/ide/src/doc_links.rs2
-rw-r--r--crates/ide/src/shuffle_crate_graph.rs2
-rw-r--r--crates/mbe/src/benchmark.rs13
-rw-r--r--crates/mbe/src/expander.rs5
-rw-r--r--crates/mbe/src/expander/matcher.rs6
-rw-r--r--crates/mbe/src/expander/transcriber.rs50
-rw-r--r--crates/mbe/src/lib.rs31
-rw-r--r--crates/mbe/src/parser.rs70
-rw-r--r--crates/mbe/src/tt_iter.rs7
-rw-r--r--crates/project-model/Cargo.toml2
-rw-r--r--crates/project-model/src/workspace.rs38
-rw-r--r--crates/project-model/test_data/output/cargo_hello_world_project_model.txt10
-rw-r--r--crates/project-model/test_data/output/cargo_hello_world_project_model_with_selective_overrides.txt10
-rw-r--r--crates/project-model/test_data/output/cargo_hello_world_project_model_with_wildcard_overrides.txt10
-rw-r--r--crates/project-model/test_data/output/rust_project_hello_world_project_model.txt22
-rw-r--r--crates/test-fixture/src/lib.rs22
25 files changed, 316 insertions, 153 deletions
diff --git a/Cargo.lock b/Cargo.lock
index d1892b7689..2cb26d0c59 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -74,6 +74,7 @@ dependencies = [
"profile",
"rust-analyzer-salsa",
"rustc-hash",
+ "semver",
"span",
"stdx",
"syntax",
diff --git a/Cargo.toml b/Cargo.toml
index fdca4f6d16..80ec679db3 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -110,6 +110,7 @@ nohash-hasher = "0.2.0"
rayon = "1.8.0"
rust-analyzer-salsa = "0.17.0-pre.4"
rustc-hash = "1.1.0"
+semver = "1.0.14"
serde = { version = "1.0.192", features = ["derive"] }
serde_json = "1.0.108"
smallvec = { version = "1.10.0", features = [
diff --git a/crates/base-db/Cargo.toml b/crates/base-db/Cargo.toml
index 371d6ee74b..13b2665558 100644
--- a/crates/base-db/Cargo.toml
+++ b/crates/base-db/Cargo.toml
@@ -16,6 +16,7 @@ la-arena.workspace = true
rust-analyzer-salsa.workspace = true
rustc-hash.workspace = true
triomphe.workspace = true
+semver.workspace = true
# local deps
cfg.workspace = true
diff --git a/crates/base-db/src/input.rs b/crates/base-db/src/input.rs
index c3cddd0e07..4fb204e625 100644
--- a/crates/base-db/src/input.rs
+++ b/crates/base-db/src/input.rs
@@ -11,6 +11,7 @@ use std::{fmt, mem, ops, str::FromStr};
use cfg::CfgOptions;
use la_arena::{Arena, Idx};
use rustc_hash::{FxHashMap, FxHashSet};
+use semver::Version;
use syntax::SmolStr;
use triomphe::Arc;
use vfs::{file_set::FileSet, AbsPathBuf, AnchoredPath, FileId, VfsPath};
@@ -258,7 +259,7 @@ impl ReleaseChannel {
pub fn from_str(str: &str) -> Option<Self> {
Some(match str {
- "" => ReleaseChannel::Stable,
+ "" | "stable" => ReleaseChannel::Stable,
"nightly" => ReleaseChannel::Nightly,
_ if str.starts_with("beta") => ReleaseChannel::Beta,
_ => return None,
@@ -289,7 +290,7 @@ pub struct CrateData {
// things. This info does need to be somewhat present though as to prevent deduplication from
// happening across different workspaces with different layouts.
pub target_layout: TargetLayoutLoadResult,
- pub channel: Option<ReleaseChannel>,
+ pub toolchain: Option<Version>,
}
impl CrateData {
@@ -346,6 +347,10 @@ impl CrateData {
slf_deps.eq(other_deps)
}
+
+ pub fn channel(&self) -> Option<ReleaseChannel> {
+ self.toolchain.as_ref().and_then(|v| ReleaseChannel::from_str(&v.pre))
+ }
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
@@ -428,7 +433,7 @@ impl CrateGraph {
is_proc_macro: bool,
origin: CrateOrigin,
target_layout: Result<Arc<str>, Arc<str>>,
- channel: Option<ReleaseChannel>,
+ toolchain: Option<Version>,
) -> CrateId {
let data = CrateData {
root_file_id,
@@ -442,7 +447,7 @@ impl CrateGraph {
origin,
target_layout,
is_proc_macro,
- channel,
+ toolchain,
};
self.arena.alloc(data)
}
diff --git a/crates/base-db/src/lib.rs b/crates/base-db/src/lib.rs
index 918c1cd3e0..a0a55df5f9 100644
--- a/crates/base-db/src/lib.rs
+++ b/crates/base-db/src/lib.rs
@@ -23,6 +23,8 @@ pub use salsa::{self, Cancelled};
pub use span::{FilePosition, FileRange};
pub use vfs::{file_set::FileSet, AnchoredPath, AnchoredPathBuf, FileId, VfsPath};
+pub use semver::{BuildMetadata, Prerelease, Version, VersionReq};
+
#[macro_export]
macro_rules! impl_intern_key {
($name:ident) => {
diff --git a/crates/hir-def/src/macro_expansion_tests/mbe/meta_syntax.rs b/crates/hir-def/src/macro_expansion_tests/mbe/meta_syntax.rs
index 7e7b400442..e875950e4e 100644
--- a/crates/hir-def/src/macro_expansion_tests/mbe/meta_syntax.rs
+++ b/crates/hir-def/src/macro_expansion_tests/mbe/meta_syntax.rs
@@ -18,7 +18,7 @@ macro_rules! m {
($($false:ident)*) => ($false);
(double_dollar) => ($$);
($) => (m!($););
- ($($t:tt)*) => ($( ${ignore(t)} ${index()} )-*);
+ ($($t:tt)*) => ($( ${ignore($t)} ${index()} )-*);
}
m!($);
"#,
@@ -33,7 +33,7 @@ macro_rules! m {
($($false:ident)*) => ($false);
(double_dollar) => ($$);
($) => (m!($););
- ($($t:tt)*) => ($( ${ignore(t)} ${index()} )-*);
+ ($($t:tt)*) => ($( ${ignore($t)} ${index()} )-*);
}
m!($);
"#]],
diff --git a/crates/hir-def/src/macro_expansion_tests/mbe/metavar_expr.rs b/crates/hir-def/src/macro_expansion_tests/mbe/metavar_expr.rs
index 967b5ad36b..6560d0ec46 100644
--- a/crates/hir-def/src/macro_expansion_tests/mbe/metavar_expr.rs
+++ b/crates/hir-def/src/macro_expansion_tests/mbe/metavar_expr.rs
@@ -77,13 +77,13 @@ fn test_metavar_exprs() {
check(
r#"
macro_rules! m {
- ( $( $t:tt )* ) => ( $( ${ignore(t)} -${index()} )-* );
+ ( $( $t:tt )* ) => ( $( ${ignore($t)} -${index()} )-* );
}
const _: i32 = m!(a b c);
"#,
expect![[r#"
macro_rules! m {
- ( $( $t:tt )* ) => ( $( ${ignore(t)} -${index()} )-* );
+ ( $( $t:tt )* ) => ( $( ${ignore($t)} -${index()} )-* );
}
const _: i32 = -0--1--2;
"#]],
@@ -96,7 +96,7 @@ fn count_basic() {
r#"
macro_rules! m {
($($t:ident),*) => {
- ${count(t)}
+ ${count($t)}
}
}
@@ -109,7 +109,7 @@ fn test() {
expect![[r#"
macro_rules! m {
($($t:ident),*) => {
- ${count(t)}
+ ${count($t)}
}
}
@@ -130,9 +130,9 @@ macro_rules! foo {
($( $( $($t:ident)* ),* );*) => {
$(
{
- let depth_none = ${count(t)};
- let depth_zero = ${count(t, 0)};
- let depth_one = ${count(t, 1)};
+ let depth_none = ${count($t)};
+ let depth_zero = ${count($t, 0)};
+ let depth_one = ${count($t, 1)};
}
)*
}
@@ -150,9 +150,9 @@ macro_rules! foo {
($( $( $($t:ident)* ),* );*) => {
$(
{
- let depth_none = ${count(t)};
- let depth_zero = ${count(t, 0)};
- let depth_one = ${count(t, 1)};
+ let depth_none = ${count($t)};
+ let depth_zero = ${count($t, 0)};
+ let depth_one = ${count($t, 1)};
}
)*
}
@@ -160,11 +160,11 @@ macro_rules! foo {
fn bar() {
{
- let depth_none = 6;
+ let depth_none = 3;
let depth_zero = 3;
let depth_one = 6;
} {
- let depth_none = 3;
+ let depth_none = 1;
let depth_zero = 1;
let depth_one = 3;
}
@@ -178,12 +178,12 @@ fn count_depth_out_of_bounds() {
check(
r#"
macro_rules! foo {
- ($($t:ident)*) => { ${count(t, 1)} };
- ($( $( $l:literal )* );*) => { $(${count(l, 1)};)* }
+ ($($t:ident)*) => { ${count($t, 1)} };
+ ($( $( $l:literal )* );*) => { $(${count($l, 1)};)* }
}
macro_rules! bar {
- ($($t:ident)*) => { ${count(t, 1024)} };
- ($( $( $l:literal )* );*) => { $(${count(l, 8192)};)* }
+ ($($t:ident)*) => { ${count($t, 1024)} };
+ ($( $( $l:literal )* );*) => { $(${count($l, 8192)};)* }
}
fn test() {
@@ -195,19 +195,21 @@ fn test() {
"#,
expect![[r#"
macro_rules! foo {
- ($($t:ident)*) => { ${count(t, 1)} };
- ($( $( $l:literal )* );*) => { $(${count(l, 1)};)* }
+ ($($t:ident)*) => { ${count($t, 1)} };
+ ($( $( $l:literal )* );*) => { $(${count($l, 1)};)* }
}
macro_rules! bar {
- ($($t:ident)*) => { ${count(t, 1024)} };
- ($( $( $l:literal )* );*) => { $(${count(l, 8192)};)* }
+ ($($t:ident)*) => { ${count($t, 1024)} };
+ ($( $( $l:literal )* );*) => { $(${count($l, 8192)};)* }
}
fn test() {
- /* error: ${count} out of bounds */;
- /* error: ${count} out of bounds */;
- /* error: ${count} out of bounds */;
- /* error: ${count} out of bounds */;
+ 2;
+ 2;
+ 1;;
+ 2;
+ 2;
+ 1;;
}
"#]],
);
@@ -218,8 +220,8 @@ fn misplaced_count() {
check(
r#"
macro_rules! foo {
- ($($t:ident)*) => { $(${count(t)})* };
- ($l:literal) => { ${count(l)} }
+ ($($t:ident)*) => { $(${count($t)})* };
+ ($l:literal) => { ${count($l)} }
}
fn test() {
@@ -229,13 +231,13 @@ fn test() {
"#,
expect![[r#"
macro_rules! foo {
- ($($t:ident)*) => { $(${count(t)})* };
- ($l:literal) => { ${count(l)} }
+ ($($t:ident)*) => { $(${count($t)})* };
+ ($l:literal) => { ${count($l)} }
}
fn test() {
- /* error: ${count} misplaced */;
- /* error: ${count} misplaced */;
+ 1 1 1;
+ 1;
}
"#]],
);
@@ -246,13 +248,13 @@ fn malformed_count() {
check(
r#"
macro_rules! too_many_args {
- ($($t:ident)*) => { ${count(t, 1, leftover)} }
+ ($($t:ident)*) => { ${count($t, 1, leftover)} }
}
macro_rules! depth_suffixed {
- ($($t:ident)*) => { ${count(t, 0usize)} }
+ ($($t:ident)*) => { ${count($t, 0usize)} }
}
macro_rules! depth_too_large {
- ($($t:ident)*) => { ${count(t, 18446744073709551616)} }
+ ($($t:ident)*) => { ${count($t, 18446744073709551616)} }
}
fn test() {
@@ -263,13 +265,13 @@ fn test() {
"#,
expect![[r#"
macro_rules! too_many_args {
- ($($t:ident)*) => { ${count(t, 1, leftover)} }
+ ($($t:ident)*) => { ${count($t, 1, leftover)} }
}
macro_rules! depth_suffixed {
- ($($t:ident)*) => { ${count(t, 0usize)} }
+ ($($t:ident)*) => { ${count($t, 0usize)} }
}
macro_rules! depth_too_large {
- ($($t:ident)*) => { ${count(t, 18446744073709551616)} }
+ ($($t:ident)*) => { ${count($t, 18446744073709551616)} }
}
fn test() {
@@ -288,7 +290,7 @@ fn count_interaction_with_empty_binding() {
r#"
macro_rules! m {
($($t:ident),*) => {
- ${count(t, 100)}
+ ${count($t, 100)}
}
}
@@ -299,7 +301,7 @@ fn test() {
expect![[r#"
macro_rules! m {
($($t:ident),*) => {
- ${count(t, 100)}
+ ${count($t, 100)}
}
}
diff --git a/crates/hir-expand/src/db.rs b/crates/hir-expand/src/db.rs
index dab9d5d560..4585a532ab 100644
--- a/crates/hir-expand/src/db.rs
+++ b/crates/hir-expand/src/db.rs
@@ -1,8 +1,10 @@
//! Defines database & queries for macro expansion.
+use std::sync::OnceLock;
+
use base_db::{
salsa::{self, debug::DebugQueryTable},
- CrateId, Edition, FileId, SourceDatabase,
+ CrateId, Edition, FileId, SourceDatabase, VersionReq,
};
use either::Either;
use limit::Limit;
@@ -45,6 +47,9 @@ pub struct DeclarativeMacroExpander {
pub transparency: Transparency,
}
+// FIXME: Remove this once we drop support for 1.76
+static REQUIREMENT: OnceLock<VersionReq> = OnceLock::new();
+
impl DeclarativeMacroExpander {
pub fn expand(
&self,
@@ -52,6 +57,18 @@ impl DeclarativeMacroExpander {
tt: tt::Subtree,
call_id: MacroCallId,
) -> ExpandResult<tt::Subtree> {
+ let toolchain = &db.crate_graph()[db.lookup_intern_macro_call(call_id).def.krate].toolchain;
+ let new_meta_vars = toolchain.as_ref().map_or(false, |version| {
+ REQUIREMENT.get_or_init(|| VersionReq::parse(">=1.76").unwrap()).matches(
+ &base_db::Version {
+ pre: base_db::Prerelease::EMPTY,
+ build: base_db::BuildMetadata::EMPTY,
+ major: version.major,
+ minor: version.minor,
+ patch: version.patch,
+ },
+ )
+ });
match self.mac.err() {
Some(e) => ExpandResult::new(
tt::Subtree::empty(tt::DelimSpan::DUMMY),
@@ -59,18 +76,39 @@ impl DeclarativeMacroExpander {
),
None => self
.mac
- .expand(&tt, |s| s.ctx = apply_mark(db, s.ctx, call_id, self.transparency))
+ .expand(
+ &tt,
+ |s| s.ctx = apply_mark(db, s.ctx, call_id, self.transparency),
+ new_meta_vars,
+ )
.map_err(Into::into),
}
}
- pub fn expand_unhygienic(&self, tt: tt::Subtree) -> ExpandResult<tt::Subtree> {
+ pub fn expand_unhygienic(
+ &self,
+ db: &dyn ExpandDatabase,
+ tt: tt::Subtree,
+ krate: CrateId,
+ ) -> ExpandResult<tt::Subtree> {
+ let toolchain = &db.crate_graph()[krate].toolchain;
+ let new_meta_vars = toolchain.as_ref().map_or(false, |version| {
+ REQUIREMENT.get_or_init(|| VersionReq::parse(">=1.76").unwrap()).matches(
+ &base_db::Version {
+ pre: base_db::Prerelease::EMPTY,
+ build: base_db::BuildMetadata::EMPTY,
+ major: version.major,
+ minor: version.minor,
+ patch: version.patch,
+ },
+ )
+ });
match self.mac.err() {
Some(e) => ExpandResult::new(
tt::Subtree::empty(tt::DelimSpan::DUMMY),
ExpandError::other(format!("invalid macro definition: {e}")),
),
- None => self.mac.expand(&tt, |_| ()).map_err(Into::into),
+ None => self.mac.expand(&tt, |_| (), new_meta_vars).map_err(Into::into),
}
}
}
@@ -278,7 +316,7 @@ pub fn expand_speculative(
expander.expand(db, actual_macro_call, &adt, span_map)
}
MacroDefKind::Declarative(it) => {
- db.decl_macro_expander(loc.krate, it).expand_unhygienic(tt)
+ db.decl_macro_expander(loc.krate, it).expand_unhygienic(db, tt, loc.def.krate)
}
MacroDefKind::BuiltIn(it, _) => it.expand(db, actual_macro_call, &tt).map_err(Into::into),
MacroDefKind::BuiltInEager(it, _) => {
@@ -525,7 +563,8 @@ fn decl_macro_expander(
def_crate: CrateId,
id: AstId<ast::Macro>,
) -> Arc<DeclarativeMacroExpander> {
- let is_2021 = db.crate_graph()[def_crate].edition >= Edition::Edition2021;
+ let crate_data = &db.crate_graph()[def_crate];
+ let is_2021 = crate_data.edition >= Edition::Edition2021;
let (root, map) = parse_with_map(db, id.file_id);
let root = root.syntax_node();
@@ -549,13 +588,25 @@ fn decl_macro_expander(
_ => None,
}
};
+ let toolchain = crate_data.toolchain.as_ref();
+ let new_meta_vars = toolchain.as_ref().map_or(false, |version| {
+ REQUIREMENT.get_or_init(|| VersionReq::parse(">=1.76").unwrap()).matches(
+ &base_db::Version {
+ pre: base_db::Prerelease::EMPTY,
+ build: base_db::BuildMetadata::EMPTY,
+ major: version.major,
+ minor: version.minor,
+ patch: version.patch,
+ },
+ )
+ });
let (mac, transparency) = match id.to_ptr(db).to_node(&root) {
ast::Macro::MacroRules(macro_rules) => (
match macro_rules.token_tree() {
Some(arg) => {
let tt = mbe::syntax_node_to_token_tree(arg.syntax(), map.as_ref());
- let mac = mbe::DeclarativeMacro::parse_macro_rules(&tt, is_2021);
+ let mac = mbe::DeclarativeMacro::parse_macro_rules(&tt, is_2021, new_meta_vars);
mac
}
None => mbe::DeclarativeMacro::from_err(
@@ -569,7 +620,7 @@ fn decl_macro_expander(
match macro_def.body() {
Some(arg) => {
let tt = mbe::syntax_node_to_token_tree(arg.syntax(), map.as_ref());
- let mac = mbe::DeclarativeMacro::parse_macro2(&tt, is_2021);
+ let mac = mbe::DeclarativeMacro::parse_macro2(&tt, is_2021, new_meta_vars);
mac
}
None => mbe::DeclarativeMacro::from_err(
diff --git a/crates/ide-completion/src/context.rs b/crates/ide-completion/src/context.rs
index 0da7ba6d00..49acc3d703 100644
--- a/crates/ide-completion/src/context.rs
+++ b/crates/ide-completion/src/context.rs
@@ -693,7 +693,7 @@ impl<'a> CompletionContext<'a> {
let krate = scope.krate();
let module = scope.module();
- let toolchain = db.crate_graph()[krate.into()].channel;
+ let toolchain = db.crate_graph()[krate.into()].channel();
// `toolchain == None` means we're in some detached files. Since we have no information on
// the toolchain being used, let's just allow unstable items to be listed.
let is_nightly = matches!(toolchain, Some(base_db::ReleaseChannel::Nightly) | None);
diff --git a/crates/ide/src/doc_links.rs b/crates/ide/src/doc_links.rs
index 9760f9daf0..a36082bafc 100644
--- a/crates/ide/src/doc_links.rs
+++ b/crates/ide/src/doc_links.rs
@@ -492,7 +492,7 @@ fn get_doc_base_urls(
let Some(krate) = def.krate(db) else { return Default::default() };
let Some(display_name) = krate.display_name(db) else { return Default::default() };
let crate_data = &db.crate_graph()[krate.into()];
- let channel = crate_data.channel.map_or("nightly", ReleaseChannel::as_str);
+ let channel = crate_data.channel().unwrap_or(ReleaseChannel::Nightly).as_str();
let (web_base, local_base) = match &crate_data.origin {
// std and co do not specify `html_root_url` any longer so we gotta handwrite this ourself.
diff --git a/crates/ide/src/shuffle_crate_graph.rs b/crates/ide/src/shuffle_crate_graph.rs
index af55b9cc98..bf6ad47a49 100644
--- a/crates/ide/src/shuffle_crate_graph.rs
+++ b/crates/ide/src/shuffle_crate_graph.rs
@@ -40,7 +40,7 @@ pub(crate) fn shuffle_crate_graph(db: &mut RootDatabase) {
data.is_proc_macro,
data.origin.clone(),
data.target_layout.clone(),
- data.channel,
+ data.toolchain.clone(),
);
new_proc_macros.insert(new_id, proc_macros[&old_id].clone());
map.insert(old_id, new_id);
diff --git a/crates/mbe/src/benchmark.rs b/crates/mbe/src/benchmark.rs
index f503aecce2..22e962a814 100644
--- a/crates/mbe/src/benchmark.rs
+++ b/crates/mbe/src/benchmark.rs
@@ -20,7 +20,10 @@ fn benchmark_parse_macro_rules() {
let rules = macro_rules_fixtures_tt();
let hash: usize = {
let _pt = bench("mbe parse macro rules");
- rules.values().map(|it| DeclarativeMacro::parse_macro_rules(it, true).rules.len()).sum()
+ rules
+ .values()
+ .map(|it| DeclarativeMacro::parse_macro_rules(it, true, true).rules.len())
+ .sum()
};
assert_eq!(hash, 1144);
}
@@ -38,7 +41,7 @@ fn benchmark_expand_macro_rules() {
invocations
.into_iter()
.map(|(id, tt)| {
- let res = rules[&id].expand(&tt, |_| ());
+ let res = rules[&id].expand(&tt, |_| (), true);
assert!(res.err.is_none());
res.value.token_trees.len()
})
@@ -50,7 +53,7 @@ fn benchmark_expand_macro_rules() {
fn macro_rules_fixtures() -> FxHashMap<String, DeclarativeMacro<DummyTestSpanData>> {
macro_rules_fixtures_tt()
.into_iter()
- .map(|(id, tt)| (id, DeclarativeMacro::parse_macro_rules(&tt, true)))
+ .map(|(id, tt)| (id, DeclarativeMacro::parse_macro_rules(&tt, true, true)))
.collect()
}
@@ -105,7 +108,7 @@ fn invocation_fixtures(
for op in rule.lhs.iter() {
collect_from_op(op, &mut subtree, &mut seed);
}
- if it.expand(&subtree, |_| ()).err.is_none() {
+ if it.expand(&subtree, |_| (), true).err.is_none() {
res.push((name.clone(), subtree));
break;
}
@@ -199,7 +202,7 @@ fn invocation_fixtures(
});
parent.token_trees.push(subtree.into());
}
- Op::Ignore { .. } | Op::Index { .. } | Op::Count { .. } => {}
+ Op::Ignore { .. } | Op::Index { .. } | Op::Count { .. } | Op::Length { .. } => {}
};
// Simple linear congruential generator for deterministic result
diff --git a/crates/mbe/src/expander.rs b/crates/mbe/src/expander.rs
index 0e755f69bf..11c0ac2582 100644
--- a/crates/mbe/src/expander.rs
+++ b/crates/mbe/src/expander.rs
@@ -16,6 +16,7 @@ pub(crate) fn expand_rules<S: Span>(
input: &tt::Subtree<S>,
marker: impl Fn(&mut S) + Copy,
is_2021: bool,
+ new_meta_vars: bool,
) -> ExpandResult<tt::Subtree<S>> {
let mut match_: Option<(matcher::Match<S>, &crate::Rule<S>)> = None;
for rule in rules {
@@ -26,7 +27,7 @@ pub(crate) fn expand_rules<S: Span>(
// Unconditionally returning the transcription here makes the
// `test_repeat_bad_var` test fail.
let ExpandResult { value, err: transcribe_err } =
- transcriber::transcribe(&rule.rhs, &new_match.bindings, marker);
+ transcriber::transcribe(&rule.rhs, &new_match.bindings, marker, new_meta_vars);
if transcribe_err.is_none() {
return ExpandResult::ok(value);
}
@@ -45,7 +46,7 @@ pub(crate) fn expand_rules<S: Span>(
if let Some((match_, rule)) = match_ {
// if we got here, there was no match without errors
let ExpandResult { value, err: transcribe_err } =
- transcriber::transcribe(&rule.rhs, &match_.bindings, marker);
+ transcriber::transcribe(&rule.rhs, &match_.bindings, marker, new_meta_vars);
ExpandResult { value, err: match_.err.or(transcribe_err) }
} else {
ExpandResult::new(
diff --git a/crates/mbe/src/expander/matcher.rs b/crates/mbe/src/expander/matcher.rs
index 012b02a3f8..b7e865a68e 100644
--- a/crates/mbe/src/expander/matcher.rs
+++ b/crates/mbe/src/expander/matcher.rs
@@ -588,7 +588,9 @@ fn match_loop_inner<'t, S: Span>(
item.is_error = true;
error_items.push(item);
}
- OpDelimited::Op(Op::Ignore { .. } | Op::Index { .. } | Op::Count { .. }) => {
+ OpDelimited::Op(
+ Op::Ignore { .. } | Op::Index { .. } | Op::Count { .. } | Op::Length { .. },
+ ) => {
stdx::never!("metavariable expression in lhs found");
}
OpDelimited::Open => {
@@ -851,7 +853,7 @@ fn collect_vars<S: Span>(collector_fun: &mut impl FnMut(SmolStr), pattern: &Meta
Op::Subtree { tokens, .. } => collect_vars(collector_fun, tokens),
Op::Repeat { tokens, .. } => collect_vars(collector_fun, tokens),
Op::Literal(_) | Op::Ident(_) | Op::Punct(_) => {}
- Op::Ignore { .. } | Op::Index { .. } | Op::Count { .. } => {
+ Op::Ignore { .. } | Op::Index { .. } | Op::Count { .. } | Op::Length { .. } => {
stdx::never!("metavariable expression in lhs found");
}
}
diff --git a/crates/mbe/src/expander/transcriber.rs b/crates/mbe/src/expander/transcriber.rs
index 9fccf5f424..d1bcf3dbcc 100644
--- a/crates/mbe/src/expander/transcriber.rs
+++ b/crates/mbe/src/expander/transcriber.rs
@@ -131,8 +131,9 @@ pub(super) fn transcribe<S: Span>(
template: &MetaTemplate<S>,
bindings: &Bindings<S>,
marker: impl Fn(&mut S) + Copy,
+ new_meta_vars: bool,
) -> ExpandResult<tt::Subtree<S>> {
- let mut ctx = ExpandCtx { bindings, nesting: Vec::new() };
+ let mut ctx = ExpandCtx { bindings, nesting: Vec::new(), new_meta_vars };
let mut arena: Vec<tt::TokenTree<S>> = Vec::new();
expand_subtree(&mut ctx, template, None, &mut arena, marker)
}
@@ -152,6 +153,7 @@ struct NestingState {
struct ExpandCtx<'a, S> {
bindings: &'a Bindings<S>,
nesting: Vec<NestingState>,
+ new_meta_vars: bool,
}
fn expand_subtree<S: Span>(
@@ -232,6 +234,21 @@ fn expand_subtree<S: Span>(
.into(),
);
}
+ Op::Length { depth } => {
+ let length = ctx.nesting.get(ctx.nesting.len() - 1 - depth).map_or(0, |_nest| {
+ // FIXME: to be implemented
+ 0
+ });
+ arena.push(
+ tt::Leaf::Literal(tt::Literal {
+ text: length.to_string().into(),
+ // FIXME
+ #[allow(deprecated)]
+ span: S::DUMMY,
+ })
+ .into(),
+ );
+ }
Op::Count { name, depth } => {
let mut binding = match ctx.bindings.get(name.as_str()) {
Ok(b) => b,
@@ -269,7 +286,13 @@ fn expand_subtree<S: Span>(
}
}
- let c = match count(ctx, binding, 0, *depth) {
+ let res = if ctx.new_meta_vars {
+ count(ctx, binding, 0, depth.unwrap_or(0))
+ } else {
+ count_old(ctx, binding, 0, *depth)
+ };
+
+ let c = match res {
Ok(c) => c,
Err(e) => {
// XXX: It *might* make sense to emit a dummy integer value like `0` here.
@@ -518,14 +541,33 @@ fn fix_up_and_push_path_tt<S: Span>(buf: &mut Vec<tt::TokenTree<S>>, subtree: tt
fn count<S>(
ctx: &ExpandCtx<'_, S>,
binding: &Binding<S>,
+ depth_curr: usize,
+ depth_max: usize,
+) -> Result<usize, CountError> {
+ match binding {
+ Binding::Nested(bs) => {
+ if depth_curr == depth_max {
+ Ok(bs.len())
+ } else {
+ bs.iter().map(|b| count(ctx, b, depth_curr + 1, depth_max)).sum()
+ }
+ }
+ Binding::Empty => Ok(0),
+ Binding::Fragment(_) | Binding::Missing(_) => Ok(1),
+ }
+}
+
+fn count_old<S>(
+ ctx: &ExpandCtx<'_, S>,
+ binding: &Binding<S>,
our_depth: usize,
count_depth: Option<usize>,
) -> Result<usize, CountError> {
match binding {
Binding::Nested(bs) => match count_depth {
- None => bs.iter().map(|b| count(ctx, b, our_depth + 1, None)).sum(),
+ None => bs.iter().map(|b| count_old(ctx, b, our_depth + 1, None)).sum(),
Some(0) => Ok(bs.len()),
- Some(d) => bs.iter().map(|b| count(ctx, b, our_depth + 1, Some(d - 1))).sum(),
+ Some(d) => bs.iter().map(|b| count_old(ctx, b, our_depth + 1, Some(d - 1))).sum(),
},
Binding::Empty => Ok(0),
Binding::Fragment(_) | Binding::Missing(_) => {
diff --git a/crates/mbe/src/lib.rs b/crates/mbe/src/lib.rs
index ee9b2bf700..d0b0da9724 100644
--- a/crates/mbe/src/lib.rs
+++ b/crates/mbe/src/lib.rs
@@ -147,7 +147,12 @@ impl<S: Span> DeclarativeMacro<S> {
}
/// The old, `macro_rules! m {}` flavor.
- pub fn parse_macro_rules(tt: &tt::Subtree<S>, is_2021: bool) -> DeclarativeMacro<S> {
+ pub fn parse_macro_rules(
+ tt: &tt::Subtree<S>,
+ is_2021: bool,
+ // FIXME: Remove this once we drop support for rust 1.76 (defaults to true then)
+ new_meta_vars: bool,
+ ) -> DeclarativeMacro<S> {
// Note: this parsing can be implemented using mbe machinery itself, by
// matching against `$($lhs:tt => $rhs:tt);*` pattern, but implementing
// manually seems easier.
@@ -156,7 +161,7 @@ impl<S: Span> DeclarativeMacro<S> {
let mut err = None;
while src.len() > 0 {
- let rule = match Rule::parse(&mut src, true) {
+ let rule = match Rule::parse(&mut src, true, new_meta_vars) {
Ok(it) => it,
Err(e) => {
err = Some(Box::new(e));
@@ -183,7 +188,12 @@ impl<S: Span> DeclarativeMacro<S> {
}
/// The new, unstable `macro m {}` flavor.
- pub fn parse_macro2(tt: &tt::Subtree<S>, is_2021: bool) -> DeclarativeMacro<S> {
+ pub fn parse_macro2(
+ tt: &tt::Subtree<S>,
+ is_2021: bool,
+ // FIXME: Remove this once we drop support for rust 1.76 (defaults to true then)
+ new_meta_vars: bool,
+ ) -> DeclarativeMacro<S> {
let mut src = TtIter::new(tt);
let mut rules = Vec::new();
let mut err = None;
@@ -191,7 +201,7 @@ impl<S: Span> DeclarativeMacro<S> {
if tt::DelimiterKind::Brace == tt.delimiter.kind {
cov_mark::hit!(parse_macro_def_rules);
while src.len() > 0 {
- let rule = match Rule::parse(&mut src, true) {
+ let rule = match Rule::parse(&mut src, true, new_meta_vars) {
Ok(it) => it,
Err(e) => {
err = Some(Box::new(e));
@@ -210,7 +220,7 @@ impl<S: Span> DeclarativeMacro<S> {
}
} else {
cov_mark::hit!(parse_macro_def_simple);
- match Rule::parse(&mut src, false) {
+ match Rule::parse(&mut src, false, new_meta_vars) {
Ok(rule) => {
if src.len() != 0 {
err = Some(Box::new(ParseError::expected("remaining tokens in macro def")));
@@ -241,13 +251,18 @@ impl<S: Span> DeclarativeMacro<S> {
&self,
tt: &tt::Subtree<S>,
marker: impl Fn(&mut S) + Copy,
+ new_meta_vars: bool,
) -> ExpandResult<tt::Subtree<S>> {
- expander::expand_rules(&self.rules, &tt, marker, self.is_2021)
+ expander::expand_rules(&self.rules, &tt, marker, self.is_2021, new_meta_vars)
}
}
impl<S: Span> Rule<S> {
- fn parse(src: &mut TtIter<'_, S>, expect_arrow: bool) -> Result<Self, ParseError> {
+ fn parse(
+ src: &mut TtIter<'_, S>,
+ expect_arrow: bool,
+ new_meta_vars: bool,
+ ) -> Result<Self, ParseError> {
let lhs = src.expect_subtree().map_err(|()| ParseError::expected("expected subtree"))?;
if expect_arrow {
src.expect_char('=').map_err(|()| ParseError::expected("expected `=`"))?;
@@ -256,7 +271,7 @@ impl<S: Span> Rule<S> {
let rhs = src.expect_subtree().map_err(|()| ParseError::expected("expected subtree"))?;
let lhs = MetaTemplate::parse_pattern(lhs)?;
- let rhs = MetaTemplate::parse_template(rhs)?;
+ let rhs = MetaTemplate::parse_template(rhs, new_meta_vars)?;
Ok(crate::Rule { lhs, rhs })
}
diff --git a/crates/mbe/src/parser.rs b/crates/mbe/src/parser.rs
index 00ba35377a..afdbbef231 100644
--- a/crates/mbe/src/parser.rs
+++ b/crates/mbe/src/parser.rs
@@ -25,23 +25,26 @@ pub(crate) struct MetaTemplate<S>(pub(crate) Box<[Op<S>]>);
impl<S: Span> MetaTemplate<S> {
pub(crate) fn parse_pattern(pattern: &tt::Subtree<S>) -> Result<Self, ParseError> {
- MetaTemplate::parse(pattern, Mode::Pattern)
+ MetaTemplate::parse(pattern, Mode::Pattern, false)
}
- pub(crate) fn parse_template(template: &tt::Subtree<S>) -> Result<Self, ParseError> {
- MetaTemplate::parse(template, Mode::Template)
+ pub(crate) fn parse_template(
+ template: &tt::Subtree<S>,
+ new_meta_vars: bool,
+ ) -> Result<Self, ParseError> {
+ MetaTemplate::parse(template, Mode::Template, new_meta_vars)
}
pub(crate) fn iter(&self) -> impl Iterator<Item = &Op<S>> {
self.0.iter()
}
- fn parse(tt: &tt::Subtree<S>, mode: Mode) -> Result<Self, ParseError> {
+ fn parse(tt: &tt::Subtree<S>, mode: Mode, new_meta_vars: bool) -> Result<Self, ParseError> {
let mut src = TtIter::new(tt);
let mut res = Vec::new();
while let Some(first) = src.peek_n(0) {
- let op = next_op(first, &mut src, mode)?;
+ let op = next_op(first, &mut src, mode, new_meta_vars)?;
res.push(op);
}
@@ -51,12 +54,35 @@ impl<S: Span> MetaTemplate<S> {
#[derive(Clone, Debug, PartialEq, Eq)]
pub(crate) enum Op<S> {
- Var { name: SmolStr, kind: Option<MetaVarKind>, id: S },
- Ignore { name: SmolStr, id: S },
- Index { depth: usize },
- Count { name: SmolStr, depth: Option<usize> },
- Repeat { tokens: MetaTemplate<S>, kind: RepeatKind, separator: Option<Separator<S>> },
- Subtree { tokens: MetaTemplate<S>, delimiter: tt::Delimiter<S> },
+ Var {
+ name: SmolStr,
+ kind: Option<MetaVarKind>,
+ id: S,
+ },
+ Ignore {
+ name: SmolStr,
+ id: S,
+ },
+ Index {
+ depth: usize,
+ },
+ Length {
+ depth: usize,
+ },
+ Count {
+ name: SmolStr,
+ // FIXME: `usize`` once we drop support for 1.76
+ depth: Option<usize>,
+ },
+ Repeat {
+ tokens: MetaTemplate<S>,
+ kind: RepeatKind,
+ separator: Option<Separator<S>>,
+ },
+ Subtree {
+ tokens: MetaTemplate<S>,
+ delimiter: tt::Delimiter<S>,
+ },
Literal(tt::Literal<S>),
Punct(SmallVec<[tt::Punct<S>; 3]>),
Ident(tt::Ident<S>),
@@ -122,6 +148,7 @@ fn next_op<S: Span>(
first_peeked: &tt::TokenTree<S>,
src: &mut TtIter<'_, S>,
mode: Mode,
+ new_meta_vars: bool,
) -> Result<Op<S>, ParseError> {
let res = match first_peeked {
tt::TokenTree::Leaf(tt::Leaf::Punct(p @ tt::Punct { char: '$', .. })) => {
@@ -135,14 +162,14 @@ fn next_op<S: Span>(
tt::TokenTree::Subtree(subtree) => match subtree.delimiter.kind {
tt::DelimiterKind::Parenthesis => {
let (separator, kind) = parse_repeat(src)?;
- let tokens = MetaTemplate::parse(subtree, mode)?;
+ let tokens = MetaTemplate::parse(subtree, mode, new_meta_vars)?;
Op::Repeat { tokens, separator, kind }
}
tt::DelimiterKind::Brace => match mode {
Mode::Template => {
- parse_metavar_expr(&mut TtIter::new(subtree)).map_err(|()| {
- ParseError::unexpected("invalid metavariable expression")
- })?
+ parse_metavar_expr(new_meta_vars, &mut TtIter::new(subtree)).map_err(
+ |()| ParseError::unexpected("invalid metavariable expression"),
+ )?
}
Mode::Pattern => {
return Err(ParseError::unexpected(
@@ -206,7 +233,7 @@ fn next_op<S: Span>(
tt::TokenTree::Subtree(subtree) => {
src.next().expect("first token already peeked");
- let tokens = MetaTemplate::parse(subtree, mode)?;
+ let tokens = MetaTemplate::parse(subtree, mode, new_meta_vars)?;
Op::Subtree { tokens, delimiter: subtree.delimiter }
}
};
@@ -287,7 +314,7 @@ fn parse_repeat<S: Span>(
Err(ParseError::InvalidRepeat)
}
-fn parse_metavar_expr<S: Span>(src: &mut TtIter<'_, S>) -> Result<Op<S>, ()> {
+fn parse_metavar_expr<S: Span>(new_meta_vars: bool, src: &mut TtIter<'_, S>) -> Result<Op<S>, ()> {
let func = src.expect_ident()?;
let args = src.expect_subtree()?;
@@ -299,14 +326,19 @@ fn parse_metavar_expr<S: Span>(src: &mut TtIter<'_, S>) -> Result<Op<S>, ()> {
let op = match &*func.text {
"ignore" => {
+ if new_meta_vars {
+ args.expect_dollar()?;
+ }
let ident = args.expect_ident()?;
Op::Ignore { name: ident.text.clone(), id: ident.span }
}
"index" => Op::Index { depth: parse_depth(&mut args)? },
+ "length" => Op::Length { depth: parse_depth(&mut args)? },
"count" => {
+ if new_meta_vars {
+ args.expect_dollar()?;
+ }
let ident = args.expect_ident()?;
- // `${count(t)}` and `${count(t,)}` have different meanings. Not sure if this is a bug
- // but that's how it's implemented in rustc as of this writing. See rust-lang/rust#111904.
let depth = if try_eat_comma(&mut args) { Some(parse_depth(&mut args)?) } else { None };
Op::Count { name: ident.text.clone(), depth }
}
diff --git a/crates/mbe/src/tt_iter.rs b/crates/mbe/src/tt_iter.rs
index 40e8a2385f..97b37b24ad 100644
--- a/crates/mbe/src/tt_iter.rs
+++ b/crates/mbe/src/tt_iter.rs
@@ -51,6 +51,13 @@ impl<'a, S: Span> TtIter<'a, S> {
}
}
+ pub(crate) fn expect_dollar(&mut self) -> Result<(), ()> {
+ match self.expect_leaf()? {
+ tt::Leaf::Punct(tt::Punct { char: '$', .. }) => Ok(()),
+ _ => Err(()),
+ }
+ }
+
pub(crate) fn expect_ident(&mut self) -> Result<&'a tt::Ident<S>, ()> {
match self.expect_leaf()? {
tt::Leaf::Ident(it) if it.text != "_" => Ok(it),
diff --git a/crates/project-model/Cargo.toml b/crates/project-model/Cargo.toml
index c1243b5932..a36c9aca52 100644
--- a/crates/project-model/Cargo.toml
+++ b/crates/project-model/Cargo.toml
@@ -15,7 +15,7 @@ doctest = false
anyhow.workspace = true
cargo_metadata.workspace = true
rustc-hash.workspace = true
-semver = "1.0.14"
+semver.workspace = true
serde_json.workspace = true
serde.workspace = true
tracing.workspace = true
diff --git a/crates/project-model/src/workspace.rs b/crates/project-model/src/workspace.rs
index 9333570354..4057493fa3 100644
--- a/crates/project-model/src/workspace.rs
+++ b/crates/project-model/src/workspace.rs
@@ -7,7 +7,7 @@ use std::{collections::VecDeque, fmt, fs, iter, process::Command, str::FromStr,
use anyhow::{format_err, Context};
use base_db::{
CrateDisplayName, CrateGraph, CrateId, CrateName, CrateOrigin, Dependency, DependencyKind,
- Edition, Env, FileId, LangCrateOrigin, ProcMacroPaths, ReleaseChannel, TargetLayoutLoadResult,
+ Edition, Env, FileId, LangCrateOrigin, ProcMacroPaths, TargetLayoutLoadResult,
};
use cfg::{CfgDiff, CfgOptions};
use paths::{AbsPath, AbsPathBuf};
@@ -619,7 +619,7 @@ impl ProjectWorkspace {
sysroot.as_ref().ok(),
extra_env,
Err("rust-project.json projects have no target layout set".into()),
- toolchain.as_ref().and_then(|it| ReleaseChannel::from_str(it.pre.as_str())),
+ toolchain.clone(),
)
}
ProjectWorkspace::Cargo {
@@ -644,7 +644,7 @@ impl ProjectWorkspace {
Ok(it) => Ok(Arc::from(it.as_str())),
Err(it) => Err(Arc::from(it.as_str())),
},
- toolchain.as_ref().and_then(|it| ReleaseChannel::from_str(it.pre.as_str())),
+ toolchain.as_ref(),
),
ProjectWorkspace::DetachedFiles { files, sysroot, rustc_cfg } => {
detached_files_to_crate_graph(
@@ -733,7 +733,7 @@ fn project_json_to_crate_graph(
sysroot: Option<&Sysroot>,
extra_env: &FxHashMap<String, String>,
target_layout: TargetLayoutLoadResult,
- channel: Option<ReleaseChannel>,
+ toolchain: Option<Version>,
) -> (CrateGraph, ProcMacroPaths) {
let mut res = (CrateGraph::default(), ProcMacroPaths::default());
let (crate_graph, proc_macros) = &mut res;
@@ -744,7 +744,7 @@ fn project_json_to_crate_graph(
rustc_cfg.clone(),
target_layout.clone(),
load,
- channel,
+ toolchain.as_ref(),
)
});
@@ -807,7 +807,7 @@ fn project_json_to_crate_graph(
CrateOrigin::Local { repo: None, name: None }
},
target_layout.clone(),
- channel,
+ toolchain.clone(),
);
if *is_proc_macro {
if let Some(path) = proc_macro_dylib_path.clone() {
@@ -853,7 +853,7 @@ fn cargo_to_crate_graph(
forced_cfg: Option<CfgOptions>,
build_scripts: &WorkspaceBuildScripts,
target_layout: TargetLayoutLoadResult,
- channel: Option<ReleaseChannel>,
+ toolchain: Option<&Version>,
) -> (CrateGraph, ProcMacroPaths) {
let _p = profile::span("cargo_to_crate_graph");
let mut res = (CrateGraph::default(), ProcMacroPaths::default());
@@ -866,7 +866,7 @@ fn cargo_to_crate_graph(
rustc_cfg.clone(),
target_layout.clone(),
load,
- channel,
+ toolchain,
),
None => (SysrootPublicDeps::default(), None),
};
@@ -950,7 +950,7 @@ fn cargo_to_crate_graph(
is_proc_macro,
target_layout.clone(),
false,
- channel,
+ toolchain.cloned(),
);
if kind == TargetKind::Lib {
lib_tgt = Some((crate_id, name.clone()));
@@ -1038,7 +1038,7 @@ fn cargo_to_crate_graph(
rustc_build_scripts
},
target_layout,
- channel,
+ toolchain,
);
}
}
@@ -1117,7 +1117,7 @@ fn handle_rustc_crates(
override_cfg: &CfgOverrides,
build_scripts: &WorkspaceBuildScripts,
target_layout: TargetLayoutLoadResult,
- channel: Option<ReleaseChannel>,
+ toolchain: Option<&Version>,
) {
let mut rustc_pkg_crates = FxHashMap::default();
// The root package of the rustc-dev component is rustc_driver, so we match that
@@ -1172,7 +1172,7 @@ fn handle_rustc_crates(
rustc_workspace[tgt].is_proc_macro,
target_layout.clone(),
true,
- channel,
+ toolchain.cloned(),
);
pkg_to_lib_crate.insert(pkg, crate_id);
// Add dependencies on core / std / alloc for this crate
@@ -1248,7 +1248,7 @@ fn add_target_crate_root(
is_proc_macro: bool,
target_layout: TargetLayoutLoadResult,
rustc_crate: bool,
- channel: Option<ReleaseChannel>,
+ toolchain: Option<Version>,
) -> CrateId {
let edition = pkg.edition;
let potential_cfg_options = if pkg.features.is_empty() {
@@ -1304,7 +1304,7 @@ fn add_target_crate_root(
CrateOrigin::Library { repo: pkg.repository.clone(), name: pkg.name.clone() }
},
target_layout,
- channel,
+ toolchain,
);
if is_proc_macro {
let proc_macro = match build_data.as_ref().map(|it| it.proc_macro_dylib_path.as_ref()) {
@@ -1346,7 +1346,7 @@ fn sysroot_to_crate_graph(
rustc_cfg: Vec<CfgFlag>,
target_layout: TargetLayoutLoadResult,
load: &mut dyn FnMut(&AbsPath) -> Option<FileId>,
- channel: Option<ReleaseChannel>,
+ toolchain: Option<&Version>,
) -> (SysrootPublicDeps, Option<CrateId>) {
let _p = profile::span("sysroot_to_crate_graph");
let cfg_options = create_cfg_options(rustc_cfg.clone());
@@ -1357,7 +1357,7 @@ fn sysroot_to_crate_graph(
rustc_cfg,
cfg_options,
target_layout,
- channel,
+ toolchain,
crate_graph,
sysroot,
),
@@ -1380,7 +1380,7 @@ fn sysroot_to_crate_graph(
false,
CrateOrigin::Lang(LangCrateOrigin::from(&*sysroot[krate].name)),
target_layout.clone(),
- channel,
+ toolchain.cloned(),
);
Some((krate, crate_id))
})
@@ -1412,7 +1412,7 @@ fn handle_hack_cargo_workspace(
rustc_cfg: Vec<CfgFlag>,
cfg_options: CfgOptions,
target_layout: Result<Arc<str>, Arc<str>>,
- channel: Option<ReleaseChannel>,
+ toolchain: Option<&Version>,
crate_graph: &mut CrateGraph,
sysroot: &Sysroot,
) -> FxHashMap<SysrootCrate, CrateId> {
@@ -1426,7 +1426,7 @@ fn handle_hack_cargo_workspace(
Some(cfg_options),
&WorkspaceBuildScripts::default(),
target_layout,
- channel,
+ toolchain,
);
crate_graph.extend(cg, &mut pm);
for crate_name in ["std", "alloc", "core"] {
diff --git a/crates/project-model/test_data/output/cargo_hello_world_project_model.txt b/crates/project-model/test_data/output/cargo_hello_world_project_model.txt
index e98f016ca7..d8d9e559e5 100644
--- a/crates/project-model/test_data/output/cargo_hello_world_project_model.txt
+++ b/crates/project-model/test_data/output/cargo_hello_world_project_model.txt
@@ -62,7 +62,7 @@
target_layout: Err(
"target_data_layout not loaded",
),
- channel: None,
+ toolchain: None,
},
1: CrateData {
root_file_id: FileId(
@@ -135,7 +135,7 @@
target_layout: Err(
"target_data_layout not loaded",
),
- channel: None,
+ toolchain: None,
},
2: CrateData {
root_file_id: FileId(
@@ -208,7 +208,7 @@
target_layout: Err(
"target_data_layout not loaded",
),
- channel: None,
+ toolchain: None,
},
3: CrateData {
root_file_id: FileId(
@@ -281,7 +281,7 @@
target_layout: Err(
"target_data_layout not loaded",
),
- channel: None,
+ toolchain: None,
},
4: CrateData {
root_file_id: FileId(
@@ -350,6 +350,6 @@
target_layout: Err(
"target_data_layout not loaded",
),
- channel: None,
+ toolchain: None,
},
} \ No newline at end of file
diff --git a/crates/project-model/test_data/output/cargo_hello_world_project_model_with_selective_overrides.txt b/crates/project-model/test_data/output/cargo_hello_world_project_model_with_selective_overrides.txt
index e98f016ca7..d8d9e559e5 100644
--- a/crates/project-model/test_data/output/cargo_hello_world_project_model_with_selective_overrides.txt
+++ b/crates/project-model/test_data/output/cargo_hello_world_project_model_with_selective_overrides.txt
@@ -62,7 +62,7 @@
target_layout: Err(
"target_data_layout not loaded",
),
- channel: None,
+ toolchain: None,
},
1: CrateData {
root_file_id: FileId(
@@ -135,7 +135,7 @@
target_layout: Err(
"target_data_layout not loaded",
),
- channel: None,
+ toolchain: None,
},
2: CrateData {
root_file_id: FileId(
@@ -208,7 +208,7 @@
target_layout: Err(
"target_data_layout not loaded",
),
- channel: None,
+ toolchain: None,
},
3: CrateData {
root_file_id: FileId(
@@ -281,7 +281,7 @@
target_layout: Err(
"target_data_layout not loaded",
),
- channel: None,
+ toolchain: None,
},
4: CrateData {
root_file_id: FileId(
@@ -350,6 +350,6 @@
target_layout: Err(
"target_data_layout not loaded",
),
- channel: None,
+ toolchain: None,
},
} \ No newline at end of file
diff --git a/crates/project-model/test_data/output/cargo_hello_world_project_model_with_wildcard_overrides.txt b/crates/project-model/test_data/output/cargo_hello_world_project_model_with_wildcard_overrides.txt
index 7ecd53572e..e0ba5ed498 100644
--- a/crates/project-model/test_data/output/cargo_hello_world_project_model_with_wildcard_overrides.txt
+++ b/crates/project-model/test_data/output/cargo_hello_world_project_model_with_wildcard_overrides.txt
@@ -61,7 +61,7 @@
target_layout: Err(
"target_data_layout not loaded",
),
- channel: None,
+ toolchain: None,
},
1: CrateData {
root_file_id: FileId(
@@ -133,7 +133,7 @@
target_layout: Err(
"target_data_layout not loaded",
),
- channel: None,
+ toolchain: None,
},
2: CrateData {
root_file_id: FileId(
@@ -205,7 +205,7 @@
target_layout: Err(
"target_data_layout not loaded",
),
- channel: None,
+ toolchain: None,
},
3: CrateData {
root_file_id: FileId(
@@ -277,7 +277,7 @@
target_layout: Err(
"target_data_layout not loaded",
),
- channel: None,
+ toolchain: None,
},
4: CrateData {
root_file_id: FileId(
@@ -346,6 +346,6 @@
target_layout: Err(
"target_data_layout not loaded",
),
- channel: None,
+ toolchain: None,
},
} \ No newline at end of file
diff --git a/crates/project-model/test_data/output/rust_project_hello_world_project_model.txt b/crates/project-model/test_data/output/rust_project_hello_world_project_model.txt
index 581a6afc14..e35f0fc732 100644
--- a/crates/project-model/test_data/output/rust_project_hello_world_project_model.txt
+++ b/crates/project-model/test_data/output/rust_project_hello_world_project_model.txt
@@ -39,7 +39,7 @@
target_layout: Err(
"rust-project.json projects have no target layout set",
),
- channel: None,
+ toolchain: None,
},
1: CrateData {
root_file_id: FileId(
@@ -72,7 +72,7 @@
target_layout: Err(
"rust-project.json projects have no target layout set",
),
- channel: None,
+ toolchain: None,
},
2: CrateData {
root_file_id: FileId(
@@ -105,7 +105,7 @@
target_layout: Err(
"rust-project.json projects have no target layout set",
),
- channel: None,
+ toolchain: None,
},
3: CrateData {
root_file_id: FileId(
@@ -138,7 +138,7 @@
target_layout: Err(
"rust-project.json projects have no target layout set",
),
- channel: None,
+ toolchain: None,
},
4: CrateData {
root_file_id: FileId(
@@ -188,7 +188,7 @@
target_layout: Err(
"rust-project.json projects have no target layout set",
),
- channel: None,
+ toolchain: None,
},
5: CrateData {
root_file_id: FileId(
@@ -221,7 +221,7 @@
target_layout: Err(
"rust-project.json projects have no target layout set",
),
- channel: None,
+ toolchain: None,
},
6: CrateData {
root_file_id: FileId(
@@ -319,7 +319,7 @@
target_layout: Err(
"rust-project.json projects have no target layout set",
),
- channel: None,
+ toolchain: None,
},
7: CrateData {
root_file_id: FileId(
@@ -352,7 +352,7 @@
target_layout: Err(
"rust-project.json projects have no target layout set",
),
- channel: None,
+ toolchain: None,
},
8: CrateData {
root_file_id: FileId(
@@ -385,7 +385,7 @@
target_layout: Err(
"rust-project.json projects have no target layout set",
),
- channel: None,
+ toolchain: None,
},
9: CrateData {
root_file_id: FileId(
@@ -418,7 +418,7 @@
target_layout: Err(
"rust-project.json projects have no target layout set",
),
- channel: None,
+ toolchain: None,
},
10: CrateData {
root_file_id: FileId(
@@ -495,6 +495,6 @@
target_layout: Err(
"rust-project.json projects have no target layout set",
),
- channel: None,
+ toolchain: None,
},
} \ No newline at end of file
diff --git a/crates/test-fixture/src/lib.rs b/crates/test-fixture/src/lib.rs
index 8c5f930907..1a042b2dea 100644
--- a/crates/test-fixture/src/lib.rs
+++ b/crates/test-fixture/src/lib.rs
@@ -3,8 +3,8 @@ use std::{mem, ops::Not, str::FromStr, sync};
use base_db::{
CrateDisplayName, CrateGraph, CrateId, CrateName, CrateOrigin, Dependency, DependencyKind,
- Edition, Env, FileChange, FileSet, LangCrateOrigin, ReleaseChannel, SourceDatabaseExt,
- SourceRoot, VfsPath,
+ Edition, Env, FileChange, FileSet, LangCrateOrigin, SourceDatabaseExt, SourceRoot, Version,
+ VfsPath,
};
use cfg::CfgOptions;
use hir_expand::{
@@ -120,12 +120,10 @@ impl ChangeFixture {
) -> ChangeFixture {
let FixtureWithProjectMeta { fixture, mini_core, proc_macro_names, toolchain } =
FixtureWithProjectMeta::parse(ra_fixture);
- let toolchain = toolchain
- .map(|it| {
- ReleaseChannel::from_str(&it)
- .unwrap_or_else(|| panic!("unknown release channel found: {it}"))
- })
- .unwrap_or(ReleaseChannel::Stable);
+ let toolchain = Some({
+ let channel = toolchain.as_deref().unwrap_or("stable");
+ Version::parse(&format!("1.76.0-{channel}")).unwrap()
+ });
let mut source_change = FileChange::new();
let mut files = Vec::new();
@@ -193,7 +191,7 @@ impl ChangeFixture {
.as_deref()
.map(From::from)
.ok_or_else(|| "target_data_layout unset".into()),
- Some(toolchain),
+ toolchain.clone(),
);
let prev = crates.insert(crate_name.clone(), crate_id);
assert!(prev.is_none(), "multiple crates with same name: {}", crate_name);
@@ -233,7 +231,7 @@ impl ChangeFixture {
default_target_data_layout
.map(|it| it.into())
.ok_or_else(|| "target_data_layout unset".into()),
- Some(toolchain),
+ toolchain.clone(),
);
} else {
for (from, to, prelude) in crate_deps {
@@ -280,7 +278,7 @@ impl ChangeFixture {
false,
CrateOrigin::Lang(LangCrateOrigin::Core),
target_layout.clone(),
- Some(toolchain),
+ toolchain.clone(),
);
for krate in all_crates {
@@ -325,7 +323,7 @@ impl ChangeFixture {
true,
CrateOrigin::Local { repo: None, name: None },
target_layout,
- Some(toolchain),
+ toolchain,
);
proc_macros.insert(proc_macros_crate, Ok(proc_macro));