Auto merge of #147372 - jieyouxu:rust-analyzer-main-tests, r=Kobzol

Run main rust-analyzer tests in rust-lang/rust CI

Part of rust-lang/rust#147370.
MCP: https://github.com/rust-lang/compiler-team/issues/923

This PR prepares `rust-analyzer` crates with `in-rust-tree` cargo featues where needed, and and updates bootstrap to run the main `rust-analyzer` tests in rust-lang/rust CI, not just the `proc-macro-srv` crate tests.

This supersedes the earlier attempt at https://github.com/rust-lang/rust/pull/136779. I was honestly expecting more failures in this PR, but looking back at the previous attempt, that makes sense because we no longer run `i686-mingw` (32-bit windows-gnu) which had a _bunch_ of these failures. In the earlier attempt I also disabled the `i686-mingw`-related failures for `i686-msvc` since I didn't feel like digging into 32-bit msvc at the time. Try results from this PR shows that it's most likely limited to 32-bit windows-gnu specifically.

### `rust-analyzer` test remarks

- I actually had to _remove_ the `CARGO_WORKSPACE_DIR` `expect-test`-hack in order for `expect-test` to be able to find the test expectation HTML files (for `syntax_highlighting` tests in `ide`). When I added the hack, ironically, it made `expect-test` unable to find the expectation files. I think this was because previously the path was of the `proc-macro-srv` crate specifically, now we point to the root r-a workspace?
- The `cfg`-related differences on `aarch64-apple-darwin` might've been fixed? I can't tell, but we don't seem to be observing the differences now.
- I'm not sure why `config::{generate_config_documentation, generate_package_json_config}` no longer fails. Perhaps they were fixed to no longer try to write to source directory?

### Review remarks

- Commit 1 updates r-a crates that are involved in tests needing artifacts from `rustc_private` compiler crates to use the `in-rust-tree` cargo feature. I briefly tried to use a plain `--cfg=in_rust_tree`, but quickly realized it was very hacky, and needed invasive bootstrap changes. The cargo feature approach seems most "natural"/well-supported to both bootstrap and cargo.
- Commit 2 updates bootstrap to not only run the `proc-macro-srv` tests, but the whole r-a tests.
- Commit 3 restricts r-a main tests to non-32-bit targets we test in CI, since (1) r-a repo does not run tests against 32-bit platforms, and (2) there are some target pointer width sensitive hash differences causing tests to fail. Notably, this means that we also no longer run r-a `proc-macro-srv` tests against 32-bit targets, but we don't expect that crate to be have target pointer width differences. Discussed this in [#t-compiler/rust-analyzer > 32-bit tests?](https://rust-lang.zulipchat.com/#narrow/channel/185405-t-compiler.2Frust-analyzer/topic/32-bit.20tests.3F/with/563145736).

---

// try-job: aarch64-gnu
// try-job: aarch64-apple
// try-job: x86_64-mingw-1
// try-job: i686-msvc-1
// try-job: x86_64-msvc-1
// try-job: aarch64-msvc-1
This commit is contained in:
bors 2025-12-13 10:11:41 +00:00
commit eb171a227f
31 changed files with 179 additions and 18 deletions

View file

@ -465,35 +465,73 @@ impl Step for RustAnalyzer {
/// Runs `cargo test` for rust-analyzer
fn run(self, builder: &Builder<'_>) {
let host = self.compilers.target();
let build_compiler = self.compilers.build_compiler();
let target = self.compilers.target();
// NOTE: rust-analyzer repo currently (as of 2025-12-11) does not run tests against 32-bit
// targets, so we also don't run them in rust-lang/rust CI (because that will just mean that
// subtree syncs will keep getting 32-bit-specific failures that are not observed in
// rust-analyzer repo CI).
//
// Some 32-bit specific failures include e.g. target pointer width specific hashes.
// FIXME: eventually, we should probably reduce the amount of target tuple substring
// matching in bootstrap.
if target.starts_with("i686") {
return;
}
let workspace_path = "src/tools/rust-analyzer";
// until the whole RA test suite runs on `i686`, we only run
// `proc-macro-srv` tests
let crate_path = "src/tools/rust-analyzer/crates/proc-macro-srv";
let mut cargo = tool::prepare_tool_cargo(
builder,
self.compilers.build_compiler(),
build_compiler,
Mode::ToolRustcPrivate,
host,
target,
Kind::Test,
crate_path,
"src/tools/rust-analyzer",
SourceType::InTree,
&["in-rust-tree".to_owned()],
);
cargo.allow_features(tool::RustAnalyzer::ALLOW_FEATURES);
let dir = builder.src.join(workspace_path);
// needed by rust-analyzer to find its own text fixtures, cf.
// https://github.com/rust-analyzer/expect-test/issues/33
cargo.env("CARGO_WORKSPACE_DIR", &dir);
// N.B. it turns out _setting_ `CARGO_WORKSPACE_DIR` actually somehow breaks `expect-test`,
// even though previously we actually needed to set that hack to allow `expect-test` to
// correctly discover the r-a workspace instead of the outer r-l/r workspace.
// RA's test suite tries to write to the source directory, that can't
// work in Rust CI
// FIXME: RA's test suite tries to write to the source directory, that can't work in Rust CI
// without properly wiring up the writable test dir.
cargo.env("SKIP_SLOW_TESTS", "1");
// NOTE: we need to skip `src/tools/rust-analyzer/xtask` as they seem to exercise rustup /
// stable rustfmt.
//
// NOTE: you can only skip a specific workspace package via `--exclude=...` if you *also*
// specify `--workspace`.
cargo.arg("--workspace");
cargo.arg("--exclude=xtask");
let mut skip_tests = vec![];
// NOTE: the following test skips is a bit cheeky in that it assumes there are no
// identically named tests across different r-a packages, where we want to run the
// identically named test in one package but not another. If we want to support that use
// case, we'd have to run the r-a tests in two batches (with one excluding the package that
// we *don't* want to run the test for, and the other batch including).
// Across all platforms.
skip_tests.extend_from_slice(&[
// FIXME: this test wants to find a `rustc`. We need to provide it with a path to staged
// in-tree `rustc`, but setting `RUSTC` env var requires some reworking of bootstrap.
"tests::smoke_test_real_sysroot_cargo",
// NOTE: part of `smol-str` test suite; this tries to access a stable rustfmt from the
// environment, which is not something we want to do.
"check_code_formatting",
]);
let skip_tests = skip_tests.iter().map(|name| format!("--skip={name}")).collect::<Vec<_>>();
let skip_tests = skip_tests.iter().map(|s| s.as_str()).collect::<Vec<_>>();
cargo.add_rustc_lib_path(builder);
run_cargo_test(cargo, &[], &[], "rust-analyzer", host, builder);
run_cargo_test(cargo, skip_tests.as_slice(), &[], "rust-analyzer", target, builder);
}
fn metadata(&self) -> Option<StepMetadata> {

View file

@ -31,5 +31,9 @@ vfs.workspace = true
span.workspace = true
intern.workspace = true
[features]
default = []
in-rust-tree = []
[lints]
workspace = true

View file

@ -1,5 +1,10 @@
//! base_db defines basic database traits. The concrete DB is defined by ide.
#![cfg_attr(feature = "in-rust-tree", feature(rustc_private))]
#[cfg(feature = "in-rust-tree")]
extern crate rustc_driver as _;
pub use salsa;
pub use salsa_macros;

View file

@ -33,5 +33,9 @@ syntax.workspace = true
# tt is needed for testing
cfg = { path = ".", default-features = false, features = ["tt"] }
[features]
default = []
in-rust-tree = []
[lints]
workspace = true

View file

@ -1,5 +1,10 @@
//! cfg defines conditional compiling options, `cfg` attribute parser and evaluator
#![cfg_attr(feature = "in-rust-tree", feature(rustc_private))]
#[cfg(feature = "in-rust-tree")]
extern crate rustc_driver as _;
mod cfg_expr;
mod dnf;
#[cfg(test)]

View file

@ -37,5 +37,9 @@ expect-test = "1.5.1"
test-utils.workspace = true
test-fixture.workspace = true
[features]
default = []
in-rust-tree = []
[lints]
workspace = true

View file

@ -3,6 +3,11 @@
// It's useful to refer to code that is private in doc comments.
#![allow(rustdoc::private_intra_doc_links)]
#![cfg_attr(feature = "in-rust-tree", feature(rustc_private))]
#[cfg(feature = "in-rust-tree")]
extern crate rustc_driver as _;
mod completions;
mod config;
mod context;

View file

@ -52,5 +52,9 @@ line-index.workspace = true
[dev-dependencies]
expect-test = "1.5.1"
[features]
default = []
in-rust-tree = []
[lints]
workspace = true

View file

@ -2,6 +2,11 @@
//!
//! It is mainly a `HirDatabase` for semantic analysis, plus a `SymbolsDatabase`, for fuzzy search.
#![cfg_attr(feature = "in-rust-tree", feature(rustc_private))]
#[cfg(feature = "in-rust-tree")]
extern crate rustc_driver as _;
extern crate self as ide_db;
mod apply_change;

View file

@ -34,5 +34,9 @@ expect-test = "1.5.1"
test-utils.workspace = true
test-fixture.workspace = true
[features]
default = []
in-rust-tree = []
[lints]
workspace = true

View file

@ -23,6 +23,11 @@
//! There are also a couple of ad-hoc diagnostics implemented directly here, we
//! don't yet have a great pattern for how to do them properly.
#![cfg_attr(feature = "in-rust-tree", feature(rustc_private))]
#[cfg(feature = "in-rust-tree")]
extern crate rustc_driver as _;
mod handlers {
pub(crate) mod await_outside_of_async;
pub(crate) mod bad_rtn;

View file

@ -30,5 +30,9 @@ triomphe.workspace = true
test-utils.workspace = true
test-fixture.workspace = true
[features]
default = []
in-rust-tree = []
[lints]
workspace = true

View file

@ -63,6 +63,11 @@
// // foo($a, $b) ==>> ($a).foo($b)
// ```
#![cfg_attr(feature = "in-rust-tree", feature(rustc_private))]
#[cfg(feature = "in-rust-tree")]
extern crate rustc_driver as _;
mod fragments;
mod from_comment;
mod matching;

View file

@ -2,6 +2,12 @@
//! for incorporating changes.
// Note, don't remove any public api from this. This API is consumed by external tools
// to run rust-analyzer as a library.
#![cfg_attr(feature = "in-rust-tree", feature(rustc_private))]
#[cfg(feature = "in-rust-tree")]
extern crate rustc_driver as _;
use std::{any::Any, collections::hash_map::Entry, mem, path::Path, sync};
use crossbeam_channel::{Receiver, unbounded};

View file

@ -25,6 +25,8 @@
extern crate ra_ap_rustc_lexer as rustc_lexer;
#[cfg(feature = "in-rust-tree")]
extern crate rustc_lexer;
#[cfg(feature = "in-rust-tree")]
extern crate rustc_driver as _;
mod event;
mod frontmatter;

View file

@ -34,6 +34,8 @@ semver.workspace = true
[features]
sysroot-abi = ["proc-macro-srv", "proc-macro-srv/sysroot-abi"]
default = []
in-rust-tree = []
[lints]
workspace = true

View file

@ -12,6 +12,11 @@
)]
#![allow(internal_features)]
#![cfg_attr(feature = "in-rust-tree", feature(rustc_private))]
#[cfg(feature = "in-rust-tree")]
extern crate rustc_driver as _;
mod codec;
mod framing;
pub mod legacy_protocol;

View file

@ -39,5 +39,9 @@ toolchain.workspace = true
[dev-dependencies]
expect-test = "1.5.1"
[features]
default = []
in-rust-tree = []
[lints]
workspace = true

View file

@ -18,6 +18,11 @@
// It's useful to refer to code that is private in doc comments.
#![allow(rustdoc::private_intra_doc_links)]
#![cfg_attr(feature = "in-rust-tree", feature(rustc_private))]
#[cfg(feature = "in-rust-tree")]
extern crate rustc_driver as _;
pub mod project_json;
pub mod toolchain_info {
pub mod rustc_cfg;

View file

@ -98,12 +98,16 @@ syntax-bridge.workspace = true
jemalloc = ["jemallocator", "profile/jemalloc"]
force-always-assert = ["stdx/force-always-assert"]
in-rust-tree = [
"syntax/in-rust-tree",
"parser/in-rust-tree",
"hir/in-rust-tree",
"cfg/in-rust-tree",
"hir-def/in-rust-tree",
"hir-ty/in-rust-tree",
"hir/in-rust-tree",
"ide-ssr/in-rust-tree",
"ide/in-rust-tree",
"load-cargo/in-rust-tree",
"parser/in-rust-tree",
"proc-macro-api/in-rust-tree",
"syntax/in-rust-tree",
]
dhat = ["dep:dhat"]

View file

@ -9,6 +9,11 @@
//! The `cli` submodule implements some batch-processing analysis, primarily as
//! a debugging aid.
#![cfg_attr(feature = "in-rust-tree", feature(rustc_private))]
#[cfg(feature = "in-rust-tree")]
extern crate rustc_driver as _;
extern crate ra_ap_rustc_type_ir as rustc_type_ir;
/// Any toolchain less than this version will likely not work with rust-analyzer built from this revision.

View file

@ -9,6 +9,10 @@
//! be sure without a real client anyway.
#![allow(clippy::disallowed_types)]
#![cfg_attr(feature = "in-rust-tree", feature(rustc_private))]
#[cfg(feature = "in-rust-tree")]
extern crate rustc_driver as _;
mod cli;
mod ratoml;

View file

@ -27,6 +27,7 @@ syntax.workspace = true
[features]
default = ["salsa"]
in-rust-tree = []
[lints]
workspace = true

View file

@ -1,4 +1,10 @@
//! File and span related types.
#![cfg_attr(feature = "in-rust-tree", feature(rustc_private))]
#[cfg(feature = "in-rust-tree")]
extern crate rustc_driver as _;
use std::fmt::{self, Write};
mod ast_id;

View file

@ -1,5 +1,10 @@
//! Conversions between [`SyntaxNode`] and [`tt::TokenTree`].
#![cfg_attr(feature = "in-rust-tree", feature(rustc_private))]
#[cfg(feature = "in-rust-tree")]
extern crate rustc_driver as _;
use std::{collections::VecDeque, fmt, hash::Hash};
use intern::Symbol;

View file

@ -33,6 +33,7 @@ rustc_apfloat = "0.2.3"
test-utils.workspace = true
[features]
default = []
in-rust-tree = []
[lints]

View file

@ -19,6 +19,11 @@
//! [RFC]: <https://github.com/rust-lang/rfcs/pull/2256>
//! [Swift]: <https://github.com/apple/swift/blob/13d593df6f359d0cb2fc81cfaac273297c539455/lib/Syntax/README.md>
#![cfg_attr(feature = "in-rust-tree", feature(rustc_private))]
#[cfg(feature = "in-rust-tree")]
extern crate rustc_driver as _;
mod parsing;
mod ptr;
mod syntax_error;

View file

@ -21,5 +21,9 @@ intern.workspace = true
triomphe.workspace = true
paths.workspace = true
[features]
default = []
in-rust-tree = []
[lints]
workspace = true

View file

@ -1,4 +1,10 @@
//! A set of high-level utility fixture methods to use in tests.
#![cfg_attr(feature = "in-rust-tree", feature(rustc_private))]
#[cfg(feature = "in-rust-tree")]
extern crate rustc_driver as _;
use std::{any::TypeId, mem, str::FromStr, sync};
use base_db::target::TargetData;

View file

@ -21,6 +21,7 @@ intern.workspace = true
ra-ap-rustc_lexer.workspace = true
[features]
default = []
in-rust-tree = []
[lints]

View file

@ -5,6 +5,9 @@
#![cfg_attr(feature = "in-rust-tree", feature(rustc_private))]
#[cfg(feature = "in-rust-tree")]
extern crate rustc_driver as _;
#[cfg(not(feature = "in-rust-tree"))]
extern crate ra_ap_rustc_lexer as rustc_lexer;
#[cfg(feature = "in-rust-tree")]