Assert that sysroot ABI version matches exactly

Otherwise, fall back to the multi ABI scheme, except in testing, where
it becomes a hard error.

This should make it possible to use a rustup-provided rust-analyzer with
proc macro dylibs compiled by older rustcs, and it'll also catch changes
to the format of `rustc --version` or the `.rustc` section that would
make them impossible to compare for equality.
This commit is contained in:
Amos Wenger 2022-07-21 13:13:24 +02:00
parent 480f555334
commit fdddd83224
5 changed files with 62 additions and 9 deletions

View file

@ -29,6 +29,9 @@ mod abi_1_64;
#[cfg(feature = "sysroot-abi")]
mod abi_sysroot;
// see `build.rs`
include!(concat!(env!("OUT_DIR"), "/rustc_version.rs"));
// Used by `test/utils.rs`
#[cfg(test)]
pub(crate) use abi_1_64::TokenStream as TestTokenStream;
@ -74,13 +77,37 @@ impl Abi {
lib: &Library,
symbol_name: String,
info: RustCInfo,
#[cfg_attr(not(feature = "sysroot-abi"), allow(unused_variables))] version_string: String,
) -> Result<Abi, LoadProcMacroDylibError> {
// Gated behind an env var for now to avoid a change in behavior for
// rustup-installed rust-analyzer
// the sysroot ABI relies on `extern proc_macro` with unstable features,
// instead of a snapshot of the proc macro bridge's source code. it's only
// enabled if we have an exact version match.
#[cfg(feature = "sysroot-abi")]
if std::env::var("PROC_MACRO_SRV_SYSROOT_ABI").is_ok() {
let inner = unsafe { Abi_Sysroot::from_lib(lib, symbol_name) }?;
return Ok(Abi::AbiSysroot(inner));
{
if version_string == RUSTC_VERSION_STRING {
let inner = unsafe { Abi_Sysroot::from_lib(lib, symbol_name) }?;
return Ok(Abi::AbiSysroot(inner));
}
// if we reached this point, versions didn't match. in testing, we
// want that to panic - this could mean that the format of `rustc
// --version` no longer matches the format of the version string
// stored in the `.rustc` section, and we want to catch that in-tree
// with `x.py test`
#[cfg(test)]
{
let allow_mismatch = std::env::var("PROC_MACRO_SRV_ALLOW_SYSROOT_MISMATCH");
if let Ok("1") = allow_mismatch.as_deref() {
// only used by rust-analyzer developers, when working on the
// sysroot ABI from the rust-analyzer repository - which should
// only happen pre-subtree. this can be removed later.
} else {
panic!(
"sysroot ABI mismatch: dylib rustc version (read from .rustc section): {:?} != proc-macro-srv version (read from 'rustc --version'): {:?}",
version_string, RUSTC_VERSION_STRING
);
}
}
}
// FIXME: this should use exclusive ranges when they're stable

View file

@ -12,7 +12,7 @@ use libloading::Library;
use memmap2::Mmap;
use object::Object;
use paths::AbsPath;
use proc_macro_api::{read_dylib_info, ProcMacroKind};
use proc_macro_api::{read_dylib_info, read_version, ProcMacroKind};
use super::abis::Abi;
@ -122,9 +122,10 @@ impl ProcMacroLibraryLibloading {
invalid_data_err(format!("expected an absolute path, got {}", file.display()))
})?;
let version_info = read_dylib_info(abs_file)?;
let version_string = read_version(abs_file)?;
let lib = load_library(file).map_err(invalid_data_err)?;
let abi = Abi::from_lib(&lib, symbol_name, version_info)?;
let abi = Abi::from_lib(&lib, symbol_name, version_info, version_string)?;
Ok(ProcMacroLibraryLibloading { _lib: lib, abi })
}
}