mirror of
https://github.com/rust-lang/rust-analyzer.git
synced 2025-11-03 21:25:25 +00:00
Merge pull request #20642 from ChayimFriedman2/wasm-safe
Some checks failed
metrics / build_metrics (push) Has been cancelled
rustdoc / rustdoc (push) Has been cancelled
metrics / other_metrics (diesel-1.4.8) (push) Has been cancelled
metrics / other_metrics (hyper-0.14.18) (push) Has been cancelled
metrics / other_metrics (ripgrep-13.0.0) (push) Has been cancelled
metrics / other_metrics (self) (push) Has been cancelled
metrics / other_metrics (webrender-2022) (push) Has been cancelled
metrics / generate_final_metrics (push) Has been cancelled
Some checks failed
metrics / build_metrics (push) Has been cancelled
rustdoc / rustdoc (push) Has been cancelled
metrics / other_metrics (diesel-1.4.8) (push) Has been cancelled
metrics / other_metrics (hyper-0.14.18) (push) Has been cancelled
metrics / other_metrics (ripgrep-13.0.0) (push) Has been cancelled
metrics / other_metrics (self) (push) Has been cancelled
metrics / other_metrics (webrender-2022) (push) Has been cancelled
metrics / generate_final_metrics (push) Has been cancelled
fix: Make `#[target_feature]` always safe on WASM
This commit is contained in:
commit
db0420c278
27 changed files with 257 additions and 89 deletions
|
|
@ -295,8 +295,6 @@ impl CrateDisplayName {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub type TargetLayoutLoadResult = Result<Arc<str>, Arc<str>>;
|
|
||||||
|
|
||||||
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
|
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
|
||||||
pub enum ReleaseChannel {
|
pub enum ReleaseChannel {
|
||||||
Stable,
|
Stable,
|
||||||
|
|
@ -929,7 +927,7 @@ mod tests {
|
||||||
use super::{CrateGraphBuilder, CrateName, CrateOrigin, Edition::Edition2018, Env, FileId};
|
use super::{CrateGraphBuilder, CrateName, CrateOrigin, Edition::Edition2018, Env, FileId};
|
||||||
|
|
||||||
fn empty_ws_data() -> Arc<CrateWorkspaceData> {
|
fn empty_ws_data() -> Arc<CrateWorkspaceData> {
|
||||||
Arc::new(CrateWorkspaceData { data_layout: Err("".into()), toolchain: None })
|
Arc::new(CrateWorkspaceData { target: Err("".into()), toolchain: None })
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
|
|
||||||
|
|
@ -6,6 +6,7 @@ pub use salsa_macros;
|
||||||
// FIXME: Rename this crate, base db is non descriptive
|
// FIXME: Rename this crate, base db is non descriptive
|
||||||
mod change;
|
mod change;
|
||||||
mod input;
|
mod input;
|
||||||
|
pub mod target;
|
||||||
|
|
||||||
use std::{
|
use std::{
|
||||||
cell::RefCell,
|
cell::RefCell,
|
||||||
|
|
@ -20,8 +21,7 @@ pub use crate::{
|
||||||
BuiltCrateData, BuiltDependency, Crate, CrateBuilder, CrateBuilderId, CrateDataBuilder,
|
BuiltCrateData, BuiltDependency, Crate, CrateBuilder, CrateBuilderId, CrateDataBuilder,
|
||||||
CrateDisplayName, CrateGraphBuilder, CrateName, CrateOrigin, CratesIdMap, CratesMap,
|
CrateDisplayName, CrateGraphBuilder, CrateName, CrateOrigin, CratesIdMap, CratesMap,
|
||||||
DependencyBuilder, Env, ExtraCrateData, LangCrateOrigin, ProcMacroLoadingError,
|
DependencyBuilder, Env, ExtraCrateData, LangCrateOrigin, ProcMacroLoadingError,
|
||||||
ProcMacroPaths, ReleaseChannel, SourceRoot, SourceRootId, TargetLayoutLoadResult,
|
ProcMacroPaths, ReleaseChannel, SourceRoot, SourceRootId, UniqueCrateData,
|
||||||
UniqueCrateData,
|
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
use dashmap::{DashMap, mapref::entry::Entry};
|
use dashmap::{DashMap, mapref::entry::Entry};
|
||||||
|
|
@ -359,8 +359,7 @@ impl Nonce {
|
||||||
/// Crate related data shared by the whole workspace.
|
/// Crate related data shared by the whole workspace.
|
||||||
#[derive(Debug, PartialEq, Eq, Hash, Clone)]
|
#[derive(Debug, PartialEq, Eq, Hash, Clone)]
|
||||||
pub struct CrateWorkspaceData {
|
pub struct CrateWorkspaceData {
|
||||||
// FIXME: Consider removing this, making HirDatabase::target_data_layout an input query
|
pub target: Result<target::TargetData, target::TargetLoadError>,
|
||||||
pub data_layout: TargetLayoutLoadResult,
|
|
||||||
/// Toolchain version used to compile the crate.
|
/// Toolchain version used to compile the crate.
|
||||||
pub toolchain: Option<Version>,
|
pub toolchain: Option<Version>,
|
||||||
}
|
}
|
||||||
|
|
|
||||||
50
crates/base-db/src/target.rs
Normal file
50
crates/base-db/src/target.rs
Normal file
|
|
@ -0,0 +1,50 @@
|
||||||
|
//! Information about the target.
|
||||||
|
|
||||||
|
use std::fmt;
|
||||||
|
|
||||||
|
use triomphe::Arc;
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
|
||||||
|
pub enum Arch {
|
||||||
|
// Only what we need is present here.
|
||||||
|
Wasm32,
|
||||||
|
Wasm64,
|
||||||
|
Other,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, PartialEq, Eq, Hash, Clone)]
|
||||||
|
pub struct TargetData {
|
||||||
|
pub data_layout: Box<str>,
|
||||||
|
pub arch: Arch,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, PartialEq, Eq, Hash)]
|
||||||
|
pub struct TargetLoadError(Arc<str>);
|
||||||
|
|
||||||
|
impl fmt::Debug for TargetLoadError {
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
|
fmt::Debug::fmt(&self.0, f)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl fmt::Display for TargetLoadError {
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
|
fmt::Display::fmt(&self.0, f)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl std::error::Error for TargetLoadError {}
|
||||||
|
|
||||||
|
impl From<String> for TargetLoadError {
|
||||||
|
fn from(value: String) -> Self {
|
||||||
|
Self(value.into())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<&str> for TargetLoadError {
|
||||||
|
fn from(value: &str) -> Self {
|
||||||
|
Self(value.into())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub type TargetLoadResult = Result<TargetData, TargetLoadError>;
|
||||||
|
|
@ -84,7 +84,7 @@ pub const BAZ: u32 = 0;
|
||||||
)
|
)
|
||||||
.unwrap(),
|
.unwrap(),
|
||||||
),
|
),
|
||||||
Arc::new(CrateWorkspaceData { data_layout: Err("".into()), toolchain: None }),
|
Arc::new(CrateWorkspaceData { target: Err("".into()), toolchain: None }),
|
||||||
)
|
)
|
||||||
};
|
};
|
||||||
let a = add_crate("a", 0);
|
let a = add_crate("a", 0);
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,7 @@
|
||||||
//! type inference-related queries.
|
//! type inference-related queries.
|
||||||
|
|
||||||
use base_db::Crate;
|
use base_db::Crate;
|
||||||
|
use base_db::target::TargetLoadError;
|
||||||
use hir_def::{
|
use hir_def::{
|
||||||
AdtId, BlockId, CallableDefId, ConstParamId, DefWithBodyId, EnumVariantId, FunctionId,
|
AdtId, BlockId, CallableDefId, ConstParamId, DefWithBodyId, EnumVariantId, FunctionId,
|
||||||
GeneralConstId, GenericDefId, ImplId, LifetimeParamId, LocalFieldId, StaticId, TraitId,
|
GeneralConstId, GenericDefId, ImplId, LifetimeParamId, LocalFieldId, StaticId, TraitId,
|
||||||
|
|
@ -108,7 +109,7 @@ pub trait HirDatabase: DefDatabase + std::fmt::Debug {
|
||||||
) -> Result<Arc<Layout>, LayoutError>;
|
) -> Result<Arc<Layout>, LayoutError>;
|
||||||
|
|
||||||
#[salsa::invoke(crate::layout::target_data_layout_query)]
|
#[salsa::invoke(crate::layout::target_data_layout_query)]
|
||||||
fn target_data_layout(&self, krate: Crate) -> Result<Arc<TargetDataLayout>, Arc<str>>;
|
fn target_data_layout(&self, krate: Crate) -> Result<Arc<TargetDataLayout>, TargetLoadError>;
|
||||||
|
|
||||||
#[salsa::invoke(crate::dyn_compatibility::dyn_compatibility_of_trait_query)]
|
#[salsa::invoke(crate::dyn_compatibility::dyn_compatibility_of_trait_query)]
|
||||||
fn dyn_compatibility_of_trait(&self, trait_: TraitId) -> Option<DynCompatibilityViolation>;
|
fn dyn_compatibility_of_trait(&self, trait_: TraitId) -> Option<DynCompatibilityViolation>;
|
||||||
|
|
|
||||||
|
|
@ -15,8 +15,9 @@ use hir_def::{
|
||||||
use span::Edition;
|
use span::Edition;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
InferenceResult, Interner, TargetFeatures, TyExt, TyKind, db::HirDatabase,
|
InferenceResult, Interner, TargetFeatures, TyExt, TyKind,
|
||||||
utils::is_fn_unsafe_to_call,
|
db::HirDatabase,
|
||||||
|
utils::{is_fn_unsafe_to_call, target_feature_is_safe_in_target},
|
||||||
};
|
};
|
||||||
|
|
||||||
#[derive(Debug, Default)]
|
#[derive(Debug, Default)]
|
||||||
|
|
@ -144,6 +145,9 @@ struct UnsafeVisitor<'db> {
|
||||||
def_target_features: TargetFeatures,
|
def_target_features: TargetFeatures,
|
||||||
// FIXME: This needs to be the edition of the span of each call.
|
// FIXME: This needs to be the edition of the span of each call.
|
||||||
edition: Edition,
|
edition: Edition,
|
||||||
|
/// On some targets (WASM), calling safe functions with `#[target_feature]` is always safe, even when
|
||||||
|
/// the target feature is not enabled. This flag encodes that.
|
||||||
|
target_feature_is_safe: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'db> UnsafeVisitor<'db> {
|
impl<'db> UnsafeVisitor<'db> {
|
||||||
|
|
@ -159,7 +163,12 @@ impl<'db> UnsafeVisitor<'db> {
|
||||||
DefWithBodyId::FunctionId(func) => TargetFeatures::from_attrs(&db.attrs(func.into())),
|
DefWithBodyId::FunctionId(func) => TargetFeatures::from_attrs(&db.attrs(func.into())),
|
||||||
_ => TargetFeatures::default(),
|
_ => TargetFeatures::default(),
|
||||||
};
|
};
|
||||||
let edition = resolver.module().krate().data(db).edition;
|
let krate = resolver.module().krate();
|
||||||
|
let edition = krate.data(db).edition;
|
||||||
|
let target_feature_is_safe = match &krate.workspace_data(db).target {
|
||||||
|
Ok(target) => target_feature_is_safe_in_target(target),
|
||||||
|
Err(_) => false,
|
||||||
|
};
|
||||||
Self {
|
Self {
|
||||||
db,
|
db,
|
||||||
infer,
|
infer,
|
||||||
|
|
@ -172,6 +181,7 @@ impl<'db> UnsafeVisitor<'db> {
|
||||||
callback: unsafe_expr_cb,
|
callback: unsafe_expr_cb,
|
||||||
def_target_features,
|
def_target_features,
|
||||||
edition,
|
edition,
|
||||||
|
target_feature_is_safe,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -184,7 +194,13 @@ impl<'db> UnsafeVisitor<'db> {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn check_call(&mut self, node: ExprId, func: FunctionId) {
|
fn check_call(&mut self, node: ExprId, func: FunctionId) {
|
||||||
let unsafety = is_fn_unsafe_to_call(self.db, func, &self.def_target_features, self.edition);
|
let unsafety = is_fn_unsafe_to_call(
|
||||||
|
self.db,
|
||||||
|
func,
|
||||||
|
&self.def_target_features,
|
||||||
|
self.edition,
|
||||||
|
self.target_feature_is_safe,
|
||||||
|
);
|
||||||
match unsafety {
|
match unsafety {
|
||||||
crate::utils::Unsafety::Safe => {}
|
crate::utils::Unsafety::Safe => {}
|
||||||
crate::utils::Unsafety::Unsafe => {
|
crate::utils::Unsafety::Unsafe => {
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
//! Target dependent parameters needed for layouts
|
//! Target dependent parameters needed for layouts
|
||||||
|
|
||||||
use base_db::Crate;
|
use base_db::{Crate, target::TargetLoadError};
|
||||||
use hir_def::layout::TargetDataLayout;
|
use hir_def::layout::TargetDataLayout;
|
||||||
use rustc_abi::{AddressSpace, AlignFromBytesError, TargetDataLayoutErrors};
|
use rustc_abi::{AddressSpace, AlignFromBytesError, TargetDataLayoutErrors};
|
||||||
use triomphe::Arc;
|
use triomphe::Arc;
|
||||||
|
|
@ -10,9 +10,9 @@ use crate::db::HirDatabase;
|
||||||
pub fn target_data_layout_query(
|
pub fn target_data_layout_query(
|
||||||
db: &dyn HirDatabase,
|
db: &dyn HirDatabase,
|
||||||
krate: Crate,
|
krate: Crate,
|
||||||
) -> Result<Arc<TargetDataLayout>, Arc<str>> {
|
) -> Result<Arc<TargetDataLayout>, TargetLoadError> {
|
||||||
match &krate.workspace_data(db).data_layout {
|
match &krate.workspace_data(db).target {
|
||||||
Ok(it) => match TargetDataLayout::parse_from_llvm_datalayout_string(it, AddressSpace::ZERO) {
|
Ok(target) => match TargetDataLayout::parse_from_llvm_datalayout_string(&target.data_layout, AddressSpace::ZERO) {
|
||||||
Ok(it) => Ok(Arc::new(it)),
|
Ok(it) => Ok(Arc::new(it)),
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
Err(match e {
|
Err(match e {
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,4 @@
|
||||||
|
use base_db::target::TargetData;
|
||||||
use chalk_ir::{AdtId, TyKind};
|
use chalk_ir::{AdtId, TyKind};
|
||||||
use either::Either;
|
use either::Either;
|
||||||
use hir_def::db::DefDatabase;
|
use hir_def::db::DefDatabase;
|
||||||
|
|
@ -18,8 +19,8 @@ use crate::{
|
||||||
|
|
||||||
mod closure;
|
mod closure;
|
||||||
|
|
||||||
fn current_machine_data_layout() -> String {
|
fn current_machine_target_data() -> TargetData {
|
||||||
project_model::toolchain_info::target_data_layout::get(
|
project_model::toolchain_info::target_data::get(
|
||||||
QueryConfig::Rustc(&Sysroot::empty(), &std::env::current_dir().unwrap()),
|
QueryConfig::Rustc(&Sysroot::empty(), &std::env::current_dir().unwrap()),
|
||||||
None,
|
None,
|
||||||
&FxHashMap::default(),
|
&FxHashMap::default(),
|
||||||
|
|
@ -32,7 +33,8 @@ fn eval_goal(
|
||||||
minicore: &str,
|
minicore: &str,
|
||||||
) -> Result<Arc<Layout>, LayoutError> {
|
) -> Result<Arc<Layout>, LayoutError> {
|
||||||
let _tracing = setup_tracing();
|
let _tracing = setup_tracing();
|
||||||
let target_data_layout = current_machine_data_layout();
|
let target_data = current_machine_target_data();
|
||||||
|
let target_data_layout = target_data.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}",
|
||||||
);
|
);
|
||||||
|
|
@ -104,7 +106,8 @@ fn eval_expr(
|
||||||
minicore: &str,
|
minicore: &str,
|
||||||
) -> Result<Arc<Layout>, LayoutError> {
|
) -> Result<Arc<Layout>, LayoutError> {
|
||||||
let _tracing = setup_tracing();
|
let _tracing = setup_tracing();
|
||||||
let target_data_layout = current_machine_data_layout();
|
let target_data = current_machine_target_data();
|
||||||
|
let target_data_layout = target_data.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}}};}}",
|
||||||
);
|
);
|
||||||
|
|
|
||||||
|
|
@ -132,7 +132,10 @@ pub use mapping::{
|
||||||
pub use method_resolution::check_orphan_rules;
|
pub use method_resolution::check_orphan_rules;
|
||||||
pub use target_feature::TargetFeatures;
|
pub use target_feature::TargetFeatures;
|
||||||
pub use traits::TraitEnvironment;
|
pub use traits::TraitEnvironment;
|
||||||
pub use utils::{Unsafety, all_super_traits, direct_super_traits, is_fn_unsafe_to_call};
|
pub use utils::{
|
||||||
|
Unsafety, all_super_traits, direct_super_traits, is_fn_unsafe_to_call,
|
||||||
|
target_feature_is_safe_in_target,
|
||||||
|
};
|
||||||
pub use variance::Variance;
|
pub use variance::Variance;
|
||||||
|
|
||||||
pub use chalk_ir::{
|
pub use chalk_ir::{
|
||||||
|
|
|
||||||
|
|
@ -3,6 +3,7 @@
|
||||||
use std::{borrow::Cow, cell::RefCell, fmt::Write, iter, mem, ops::Range};
|
use std::{borrow::Cow, cell::RefCell, fmt::Write, iter, mem, ops::Range};
|
||||||
|
|
||||||
use base_db::Crate;
|
use base_db::Crate;
|
||||||
|
use base_db::target::TargetLoadError;
|
||||||
use chalk_ir::{Mutability, cast::Cast};
|
use chalk_ir::{Mutability, cast::Cast};
|
||||||
use either::Either;
|
use either::Either;
|
||||||
use hir_def::{
|
use hir_def::{
|
||||||
|
|
@ -337,7 +338,7 @@ impl Address {
|
||||||
pub enum MirEvalError {
|
pub enum MirEvalError {
|
||||||
ConstEvalError(String, Box<ConstEvalError>),
|
ConstEvalError(String, Box<ConstEvalError>),
|
||||||
LayoutError(LayoutError, Ty),
|
LayoutError(LayoutError, Ty),
|
||||||
TargetDataLayoutNotAvailable(Arc<str>),
|
TargetDataLayoutNotAvailable(TargetLoadError),
|
||||||
/// Means that code had undefined behavior. We don't try to actively detect UB, but if it was detected
|
/// Means that code had undefined behavior. We don't try to actively detect UB, but if it was detected
|
||||||
/// then use this type of error.
|
/// then use this type of error.
|
||||||
UndefinedBehavior(String),
|
UndefinedBehavior(String),
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,10 @@
|
||||||
|
|
||||||
use std::{cell::LazyCell, iter};
|
use std::{cell::LazyCell, iter};
|
||||||
|
|
||||||
use base_db::Crate;
|
use base_db::{
|
||||||
|
Crate,
|
||||||
|
target::{self, TargetData},
|
||||||
|
};
|
||||||
use chalk_ir::{DebruijnIndex, fold::FallibleTypeFolder};
|
use chalk_ir::{DebruijnIndex, fold::FallibleTypeFolder};
|
||||||
use hir_def::{
|
use hir_def::{
|
||||||
EnumId, EnumVariantId, FunctionId, Lookup, TraitId, TypeAliasId, TypeOrConstParamId,
|
EnumId, EnumVariantId, FunctionId, Lookup, TraitId, TypeAliasId, TypeOrConstParamId,
|
||||||
|
|
@ -275,18 +278,23 @@ pub enum Unsafety {
|
||||||
DeprecatedSafe2024,
|
DeprecatedSafe2024,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn target_feature_is_safe_in_target(target: &TargetData) -> bool {
|
||||||
|
matches!(target.arch, target::Arch::Wasm32 | target::Arch::Wasm64)
|
||||||
|
}
|
||||||
|
|
||||||
pub fn is_fn_unsafe_to_call(
|
pub fn is_fn_unsafe_to_call(
|
||||||
db: &dyn HirDatabase,
|
db: &dyn HirDatabase,
|
||||||
func: FunctionId,
|
func: FunctionId,
|
||||||
caller_target_features: &TargetFeatures,
|
caller_target_features: &TargetFeatures,
|
||||||
call_edition: Edition,
|
call_edition: Edition,
|
||||||
|
target_feature_is_safe: bool,
|
||||||
) -> Unsafety {
|
) -> Unsafety {
|
||||||
let data = db.function_signature(func);
|
let data = db.function_signature(func);
|
||||||
if data.is_unsafe() {
|
if data.is_unsafe() {
|
||||||
return Unsafety::Unsafe;
|
return Unsafety::Unsafe;
|
||||||
}
|
}
|
||||||
|
|
||||||
if data.has_target_feature() {
|
if data.has_target_feature() && !target_feature_is_safe {
|
||||||
// RFC 2396 <https://rust-lang.github.io/rfcs/2396-target-feature-1.1.html>.
|
// RFC 2396 <https://rust-lang.github.io/rfcs/2396-target-feature-1.1.html>.
|
||||||
let callee_target_features =
|
let callee_target_features =
|
||||||
TargetFeatures::from_attrs_no_implications(&db.attrs(func.into()));
|
TargetFeatures::from_attrs_no_implications(&db.attrs(func.into()));
|
||||||
|
|
|
||||||
|
|
@ -2542,11 +2542,26 @@ impl Function {
|
||||||
caller: Option<Function>,
|
caller: Option<Function>,
|
||||||
call_edition: Edition,
|
call_edition: Edition,
|
||||||
) -> bool {
|
) -> bool {
|
||||||
let target_features = caller
|
let (target_features, target_feature_is_safe_in_target) = caller
|
||||||
.map(|caller| hir_ty::TargetFeatures::from_attrs(&db.attrs(caller.id.into())))
|
.map(|caller| {
|
||||||
.unwrap_or_default();
|
let target_features =
|
||||||
|
hir_ty::TargetFeatures::from_attrs(&db.attrs(caller.id.into()));
|
||||||
|
let target_feature_is_safe_in_target =
|
||||||
|
match &caller.krate(db).id.workspace_data(db).target {
|
||||||
|
Ok(target) => hir_ty::target_feature_is_safe_in_target(target),
|
||||||
|
Err(_) => false,
|
||||||
|
};
|
||||||
|
(target_features, target_feature_is_safe_in_target)
|
||||||
|
})
|
||||||
|
.unwrap_or_else(|| (hir_ty::TargetFeatures::default(), false));
|
||||||
matches!(
|
matches!(
|
||||||
hir_ty::is_fn_unsafe_to_call(db, self.id, &target_features, call_edition),
|
hir_ty::is_fn_unsafe_to_call(
|
||||||
|
db,
|
||||||
|
self.id,
|
||||||
|
&target_features,
|
||||||
|
call_edition,
|
||||||
|
target_feature_is_safe_in_target
|
||||||
|
),
|
||||||
hir_ty::Unsafety::Unsafe
|
hir_ty::Unsafety::Unsafe
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -998,4 +998,20 @@ extern "C" fn naked() {
|
||||||
"#,
|
"#,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn target_feature_safe_on_wasm() {
|
||||||
|
check_diagnostics(
|
||||||
|
r#"
|
||||||
|
//- target_arch: wasm32
|
||||||
|
|
||||||
|
#[target_feature(enable = "simd128")]
|
||||||
|
fn requires_target_feature() {}
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
requires_target_feature();
|
||||||
|
}
|
||||||
|
"#,
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -263,7 +263,7 @@ impl Analysis {
|
||||||
false,
|
false,
|
||||||
proc_macro_cwd,
|
proc_macro_cwd,
|
||||||
Arc::new(CrateWorkspaceData {
|
Arc::new(CrateWorkspaceData {
|
||||||
data_layout: Err("fixture has no layout".into()),
|
target: Err("fixture has no layout".into()),
|
||||||
toolchain: None,
|
toolchain: None,
|
||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
|
|
|
||||||
|
|
@ -18,7 +18,7 @@
|
||||||
pub mod project_json;
|
pub mod project_json;
|
||||||
pub mod toolchain_info {
|
pub mod toolchain_info {
|
||||||
pub mod rustc_cfg;
|
pub mod rustc_cfg;
|
||||||
pub mod target_data_layout;
|
pub mod target_data;
|
||||||
pub mod target_tuple;
|
pub mod target_tuple;
|
||||||
pub mod version;
|
pub mod version;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -9,7 +9,6 @@ use paths::{AbsPath, AbsPathBuf, Utf8Path, Utf8PathBuf};
|
||||||
use rustc_hash::FxHashMap;
|
use rustc_hash::FxHashMap;
|
||||||
use serde::de::DeserializeOwned;
|
use serde::de::DeserializeOwned;
|
||||||
use span::FileId;
|
use span::FileId;
|
||||||
use triomphe::Arc;
|
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
CargoWorkspace, CfgOverrides, ManifestPath, ProjectJson, ProjectJsonData, ProjectWorkspace,
|
CargoWorkspace, CfgOverrides, ManifestPath, ProjectJson, ProjectJsonData, ProjectWorkspace,
|
||||||
|
|
@ -47,7 +46,7 @@ fn load_workspace_from_metadata(file: &str) -> ProjectWorkspace {
|
||||||
sysroot: Sysroot::empty(),
|
sysroot: Sysroot::empty(),
|
||||||
rustc_cfg: Vec::new(),
|
rustc_cfg: Vec::new(),
|
||||||
toolchain: None,
|
toolchain: None,
|
||||||
target_layout: Err("target_data_layout not loaded".into()),
|
target: Err("target_data_layout not loaded".into()),
|
||||||
extra_includes: Vec::new(),
|
extra_includes: Vec::new(),
|
||||||
set_test: true,
|
set_test: true,
|
||||||
}
|
}
|
||||||
|
|
@ -62,7 +61,7 @@ fn load_rust_project(file: &str) -> (CrateGraphBuilder, ProcMacroPaths) {
|
||||||
sysroot,
|
sysroot,
|
||||||
rustc_cfg: Vec::new(),
|
rustc_cfg: Vec::new(),
|
||||||
toolchain: None,
|
toolchain: None,
|
||||||
target_layout: Err(Arc::from("test has no data layout")),
|
target: Err("test has no target data".into()),
|
||||||
cfg_overrides: Default::default(),
|
cfg_overrides: Default::default(),
|
||||||
extra_includes: Vec::new(),
|
extra_includes: Vec::new(),
|
||||||
set_test: true,
|
set_test: true,
|
||||||
|
|
@ -265,7 +264,7 @@ fn smoke_test_real_sysroot_cargo() {
|
||||||
rustc_cfg: Vec::new(),
|
rustc_cfg: Vec::new(),
|
||||||
cfg_overrides: Default::default(),
|
cfg_overrides: Default::default(),
|
||||||
toolchain: None,
|
toolchain: None,
|
||||||
target_layout: Err("target_data_layout not loaded".into()),
|
target: Err("target_data_layout not loaded".into()),
|
||||||
extra_includes: Vec::new(),
|
extra_includes: Vec::new(),
|
||||||
set_test: true,
|
set_test: true,
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -1,23 +1,54 @@
|
||||||
//! Runs `rustc --print target-spec-json` to get the target_data_layout.
|
//! Runs `rustc --print target-spec-json` to get the target_data_layout.
|
||||||
|
|
||||||
use anyhow::Context;
|
use anyhow::Context;
|
||||||
|
use base_db::target;
|
||||||
use rustc_hash::FxHashMap;
|
use rustc_hash::FxHashMap;
|
||||||
|
use serde_derive::Deserialize;
|
||||||
use toolchain::Tool;
|
use toolchain::Tool;
|
||||||
|
|
||||||
use crate::{Sysroot, toolchain_info::QueryConfig, utf8_stdout};
|
use crate::{Sysroot, toolchain_info::QueryConfig, utf8_stdout};
|
||||||
|
|
||||||
|
#[derive(Debug, Deserialize)]
|
||||||
|
#[serde(rename_all = "kebab-case")]
|
||||||
|
pub enum Arch {
|
||||||
|
Wasm32,
|
||||||
|
Wasm64,
|
||||||
|
#[serde(other)]
|
||||||
|
Other,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<Arch> for target::Arch {
|
||||||
|
fn from(value: Arch) -> Self {
|
||||||
|
match value {
|
||||||
|
Arch::Wasm32 => target::Arch::Wasm32,
|
||||||
|
Arch::Wasm64 => target::Arch::Wasm64,
|
||||||
|
Arch::Other => target::Arch::Other,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Deserialize)]
|
||||||
|
#[serde(rename_all = "kebab-case")]
|
||||||
|
pub struct TargetSpec {
|
||||||
|
pub data_layout: String,
|
||||||
|
pub arch: Arch,
|
||||||
|
}
|
||||||
|
|
||||||
/// Uses `rustc --print target-spec-json`.
|
/// Uses `rustc --print target-spec-json`.
|
||||||
pub fn get(
|
pub fn get(
|
||||||
config: QueryConfig<'_>,
|
config: QueryConfig<'_>,
|
||||||
target: Option<&str>,
|
target: Option<&str>,
|
||||||
extra_env: &FxHashMap<String, Option<String>>,
|
extra_env: &FxHashMap<String, Option<String>>,
|
||||||
) -> anyhow::Result<String> {
|
) -> anyhow::Result<target::TargetData> {
|
||||||
const RUSTC_ARGS: [&str; 2] = ["--print", "target-spec-json"];
|
const RUSTC_ARGS: [&str; 2] = ["--print", "target-spec-json"];
|
||||||
let process = |output: String| {
|
let process = |output: String| {
|
||||||
(|| Some(output.split_once(r#""data-layout": ""#)?.1.split_once('"')?.0.to_owned()))()
|
let target_spec = serde_json::from_str::<TargetSpec>(&output).map_err(|_| {
|
||||||
.ok_or_else(|| {
|
anyhow::format_err!("could not parse target-spec-json from command output")
|
||||||
anyhow::format_err!("could not parse target-spec-json from command output")
|
})?;
|
||||||
})
|
Ok(target::TargetData {
|
||||||
|
arch: target_spec.arch.into(),
|
||||||
|
data_layout: target_spec.data_layout.into_boxed_str(),
|
||||||
|
})
|
||||||
};
|
};
|
||||||
let (sysroot, current_dir) = match config {
|
let (sysroot, current_dir) = match config {
|
||||||
QueryConfig::Cargo(sysroot, cargo_toml, _) => {
|
QueryConfig::Cargo(sysroot, cargo_toml, _) => {
|
||||||
|
|
@ -8,7 +8,7 @@ use anyhow::Context;
|
||||||
use base_db::{
|
use base_db::{
|
||||||
CrateBuilderId, CrateDisplayName, CrateGraphBuilder, CrateName, CrateOrigin,
|
CrateBuilderId, CrateDisplayName, CrateGraphBuilder, CrateName, CrateOrigin,
|
||||||
CrateWorkspaceData, DependencyBuilder, Env, LangCrateOrigin, ProcMacroLoadingError,
|
CrateWorkspaceData, DependencyBuilder, Env, LangCrateOrigin, ProcMacroLoadingError,
|
||||||
ProcMacroPaths, TargetLayoutLoadResult,
|
ProcMacroPaths, target::TargetLoadResult,
|
||||||
};
|
};
|
||||||
use cfg::{CfgAtom, CfgDiff, CfgOptions};
|
use cfg::{CfgAtom, CfgDiff, CfgOptions};
|
||||||
use intern::{Symbol, sym};
|
use intern::{Symbol, sym};
|
||||||
|
|
@ -30,7 +30,7 @@ use crate::{
|
||||||
env::{cargo_config_env, inject_cargo_env, inject_cargo_package_env, inject_rustc_tool_env},
|
env::{cargo_config_env, inject_cargo_env, inject_cargo_package_env, inject_rustc_tool_env},
|
||||||
project_json::{Crate, CrateArrayIdx},
|
project_json::{Crate, CrateArrayIdx},
|
||||||
sysroot::RustLibSrcWorkspace,
|
sysroot::RustLibSrcWorkspace,
|
||||||
toolchain_info::{QueryConfig, rustc_cfg, target_data_layout, target_tuple, version},
|
toolchain_info::{QueryConfig, rustc_cfg, target_data, target_tuple, version},
|
||||||
utf8_stdout,
|
utf8_stdout,
|
||||||
};
|
};
|
||||||
use tracing::{debug, error, info};
|
use tracing::{debug, error, info};
|
||||||
|
|
@ -63,7 +63,7 @@ pub struct ProjectWorkspace {
|
||||||
/// The toolchain version used by this workspace.
|
/// The toolchain version used by this workspace.
|
||||||
pub toolchain: Option<Version>,
|
pub toolchain: Option<Version>,
|
||||||
/// The target data layout queried for workspace.
|
/// The target data layout queried for workspace.
|
||||||
pub target_layout: TargetLayoutLoadResult,
|
pub target: TargetLoadResult,
|
||||||
/// A set of cfg overrides for this workspace.
|
/// A set of cfg overrides for this workspace.
|
||||||
pub cfg_overrides: CfgOverrides,
|
pub cfg_overrides: CfgOverrides,
|
||||||
/// Additional includes to add for the VFS.
|
/// Additional includes to add for the VFS.
|
||||||
|
|
@ -115,7 +115,7 @@ impl fmt::Debug for ProjectWorkspace {
|
||||||
sysroot,
|
sysroot,
|
||||||
rustc_cfg,
|
rustc_cfg,
|
||||||
toolchain,
|
toolchain,
|
||||||
target_layout,
|
target: target_layout,
|
||||||
cfg_overrides,
|
cfg_overrides,
|
||||||
extra_includes,
|
extra_includes,
|
||||||
set_test,
|
set_test,
|
||||||
|
|
@ -309,8 +309,8 @@ impl ProjectWorkspace {
|
||||||
let rustc_cfg = s.spawn(|| {
|
let rustc_cfg = s.spawn(|| {
|
||||||
rustc_cfg::get(toolchain_config, targets.first().map(Deref::deref), extra_env)
|
rustc_cfg::get(toolchain_config, targets.first().map(Deref::deref), extra_env)
|
||||||
});
|
});
|
||||||
let data_layout = s.spawn(|| {
|
let target_data = s.spawn(|| {
|
||||||
target_data_layout::get(
|
target_data::get(
|
||||||
toolchain_config,
|
toolchain_config,
|
||||||
targets.first().map(Deref::deref),
|
targets.first().map(Deref::deref),
|
||||||
extra_env,
|
extra_env,
|
||||||
|
|
@ -392,7 +392,7 @@ impl ProjectWorkspace {
|
||||||
s.spawn(move || cargo_config_env(cargo_toml, &config_file));
|
s.spawn(move || cargo_config_env(cargo_toml, &config_file));
|
||||||
thread::Result::Ok((
|
thread::Result::Ok((
|
||||||
rustc_cfg.join()?,
|
rustc_cfg.join()?,
|
||||||
data_layout.join()?,
|
target_data.join()?,
|
||||||
rustc_dir.join()?,
|
rustc_dir.join()?,
|
||||||
loaded_sysroot.join()?,
|
loaded_sysroot.join()?,
|
||||||
cargo_metadata.join()?,
|
cargo_metadata.join()?,
|
||||||
|
|
@ -442,7 +442,7 @@ impl ProjectWorkspace {
|
||||||
rustc_cfg,
|
rustc_cfg,
|
||||||
cfg_overrides: cfg_overrides.clone(),
|
cfg_overrides: cfg_overrides.clone(),
|
||||||
toolchain,
|
toolchain,
|
||||||
target_layout: data_layout.map(Arc::from).map_err(|it| Arc::from(it.to_string())),
|
target: data_layout.map_err(|it| it.to_string().into()),
|
||||||
extra_includes: extra_includes.clone(),
|
extra_includes: extra_includes.clone(),
|
||||||
set_test: *set_test,
|
set_test: *set_test,
|
||||||
})
|
})
|
||||||
|
|
@ -480,11 +480,7 @@ impl ProjectWorkspace {
|
||||||
rustc_cfg::get(query_config, targets.first().map(Deref::deref), &config.extra_env)
|
rustc_cfg::get(query_config, targets.first().map(Deref::deref), &config.extra_env)
|
||||||
});
|
});
|
||||||
let data_layout = s.spawn(|| {
|
let data_layout = s.spawn(|| {
|
||||||
target_data_layout::get(
|
target_data::get(query_config, targets.first().map(Deref::deref), &config.extra_env)
|
||||||
query_config,
|
|
||||||
targets.first().map(Deref::deref),
|
|
||||||
&config.extra_env,
|
|
||||||
)
|
|
||||||
});
|
});
|
||||||
let loaded_sysroot = s.spawn(|| {
|
let loaded_sysroot = s.spawn(|| {
|
||||||
if let Some(sysroot_project) = sysroot_project {
|
if let Some(sysroot_project) = sysroot_project {
|
||||||
|
|
@ -513,7 +509,7 @@ impl ProjectWorkspace {
|
||||||
thread::Result::Ok((rustc_cfg.join()?, data_layout.join()?, loaded_sysroot.join()?))
|
thread::Result::Ok((rustc_cfg.join()?, data_layout.join()?, loaded_sysroot.join()?))
|
||||||
});
|
});
|
||||||
|
|
||||||
let (rustc_cfg, target_layout, loaded_sysroot) = match join {
|
let (rustc_cfg, target_data, loaded_sysroot) = match join {
|
||||||
Ok(it) => it,
|
Ok(it) => it,
|
||||||
Err(e) => std::panic::resume_unwind(e),
|
Err(e) => std::panic::resume_unwind(e),
|
||||||
};
|
};
|
||||||
|
|
@ -527,7 +523,7 @@ impl ProjectWorkspace {
|
||||||
sysroot,
|
sysroot,
|
||||||
rustc_cfg,
|
rustc_cfg,
|
||||||
toolchain,
|
toolchain,
|
||||||
target_layout: target_layout.map(Arc::from).map_err(|it| Arc::from(it.to_string())),
|
target: target_data.map_err(|it| it.to_string().into()),
|
||||||
cfg_overrides: config.cfg_overrides.clone(),
|
cfg_overrides: config.cfg_overrides.clone(),
|
||||||
extra_includes: config.extra_includes.clone(),
|
extra_includes: config.extra_includes.clone(),
|
||||||
set_test: config.set_test,
|
set_test: config.set_test,
|
||||||
|
|
@ -551,7 +547,7 @@ impl ProjectWorkspace {
|
||||||
let targets = target_tuple::get(query_config, config.target.as_deref(), &config.extra_env)
|
let targets = target_tuple::get(query_config, config.target.as_deref(), &config.extra_env)
|
||||||
.unwrap_or_default();
|
.unwrap_or_default();
|
||||||
let rustc_cfg = rustc_cfg::get(query_config, None, &config.extra_env);
|
let rustc_cfg = rustc_cfg::get(query_config, None, &config.extra_env);
|
||||||
let data_layout = target_data_layout::get(query_config, None, &config.extra_env);
|
let target_data = target_data::get(query_config, None, &config.extra_env);
|
||||||
let target_dir = config
|
let target_dir = config
|
||||||
.target_dir
|
.target_dir
|
||||||
.clone()
|
.clone()
|
||||||
|
|
@ -610,7 +606,7 @@ impl ProjectWorkspace {
|
||||||
sysroot,
|
sysroot,
|
||||||
rustc_cfg,
|
rustc_cfg,
|
||||||
toolchain,
|
toolchain,
|
||||||
target_layout: data_layout.map(Arc::from).map_err(|it| Arc::from(it.to_string())),
|
target: target_data.map_err(|it| it.to_string().into()),
|
||||||
cfg_overrides: config.cfg_overrides.clone(),
|
cfg_overrides: config.cfg_overrides.clone(),
|
||||||
extra_includes: config.extra_includes.clone(),
|
extra_includes: config.extra_includes.clone(),
|
||||||
set_test: config.set_test,
|
set_test: config.set_test,
|
||||||
|
|
@ -942,7 +938,7 @@ impl ProjectWorkspace {
|
||||||
let Self { kind, sysroot, cfg_overrides, rustc_cfg, .. } = self;
|
let Self { kind, sysroot, cfg_overrides, rustc_cfg, .. } = self;
|
||||||
let crate_ws_data = Arc::new(CrateWorkspaceData {
|
let crate_ws_data = Arc::new(CrateWorkspaceData {
|
||||||
toolchain: self.toolchain.clone(),
|
toolchain: self.toolchain.clone(),
|
||||||
data_layout: self.target_layout.clone(),
|
target: self.target.clone(),
|
||||||
});
|
});
|
||||||
let (crate_graph, proc_macros) = match kind {
|
let (crate_graph, proc_macros) = match kind {
|
||||||
ProjectWorkspaceKind::Json(project) => project_json_to_crate_graph(
|
ProjectWorkspaceKind::Json(project) => project_json_to_crate_graph(
|
||||||
|
|
@ -1000,13 +996,15 @@ impl ProjectWorkspace {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn eq_ignore_build_data(&self, other: &Self) -> bool {
|
pub fn eq_ignore_build_data(&self, other: &Self) -> bool {
|
||||||
let Self { kind, sysroot, rustc_cfg, toolchain, target_layout, cfg_overrides, .. } = self;
|
let Self {
|
||||||
|
kind, sysroot, rustc_cfg, toolchain, target: target_layout, cfg_overrides, ..
|
||||||
|
} = self;
|
||||||
let Self {
|
let Self {
|
||||||
kind: o_kind,
|
kind: o_kind,
|
||||||
sysroot: o_sysroot,
|
sysroot: o_sysroot,
|
||||||
rustc_cfg: o_rustc_cfg,
|
rustc_cfg: o_rustc_cfg,
|
||||||
toolchain: o_toolchain,
|
toolchain: o_toolchain,
|
||||||
target_layout: o_target_layout,
|
target: o_target_layout,
|
||||||
cfg_overrides: o_cfg_overrides,
|
cfg_overrides: o_cfg_overrides,
|
||||||
..
|
..
|
||||||
} = other;
|
} = other;
|
||||||
|
|
|
||||||
|
|
@ -70,7 +70,7 @@
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
ws_data: CrateWorkspaceData {
|
ws_data: CrateWorkspaceData {
|
||||||
data_layout: Err(
|
target: Err(
|
||||||
"target_data_layout not loaded",
|
"target_data_layout not loaded",
|
||||||
),
|
),
|
||||||
toolchain: None,
|
toolchain: None,
|
||||||
|
|
@ -155,7 +155,7 @@
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
ws_data: CrateWorkspaceData {
|
ws_data: CrateWorkspaceData {
|
||||||
data_layout: Err(
|
target: Err(
|
||||||
"target_data_layout not loaded",
|
"target_data_layout not loaded",
|
||||||
),
|
),
|
||||||
toolchain: None,
|
toolchain: None,
|
||||||
|
|
@ -240,7 +240,7 @@
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
ws_data: CrateWorkspaceData {
|
ws_data: CrateWorkspaceData {
|
||||||
data_layout: Err(
|
target: Err(
|
||||||
"target_data_layout not loaded",
|
"target_data_layout not loaded",
|
||||||
),
|
),
|
||||||
toolchain: None,
|
toolchain: None,
|
||||||
|
|
@ -325,7 +325,7 @@
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
ws_data: CrateWorkspaceData {
|
ws_data: CrateWorkspaceData {
|
||||||
data_layout: Err(
|
target: Err(
|
||||||
"target_data_layout not loaded",
|
"target_data_layout not loaded",
|
||||||
),
|
),
|
||||||
toolchain: None,
|
toolchain: None,
|
||||||
|
|
@ -406,7 +406,7 @@
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
ws_data: CrateWorkspaceData {
|
ws_data: CrateWorkspaceData {
|
||||||
data_layout: Err(
|
target: Err(
|
||||||
"target_data_layout not loaded",
|
"target_data_layout not loaded",
|
||||||
),
|
),
|
||||||
toolchain: None,
|
toolchain: None,
|
||||||
|
|
|
||||||
|
|
@ -70,7 +70,7 @@
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
ws_data: CrateWorkspaceData {
|
ws_data: CrateWorkspaceData {
|
||||||
data_layout: Err(
|
target: Err(
|
||||||
"target_data_layout not loaded",
|
"target_data_layout not loaded",
|
||||||
),
|
),
|
||||||
toolchain: None,
|
toolchain: None,
|
||||||
|
|
@ -155,7 +155,7 @@
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
ws_data: CrateWorkspaceData {
|
ws_data: CrateWorkspaceData {
|
||||||
data_layout: Err(
|
target: Err(
|
||||||
"target_data_layout not loaded",
|
"target_data_layout not loaded",
|
||||||
),
|
),
|
||||||
toolchain: None,
|
toolchain: None,
|
||||||
|
|
@ -240,7 +240,7 @@
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
ws_data: CrateWorkspaceData {
|
ws_data: CrateWorkspaceData {
|
||||||
data_layout: Err(
|
target: Err(
|
||||||
"target_data_layout not loaded",
|
"target_data_layout not loaded",
|
||||||
),
|
),
|
||||||
toolchain: None,
|
toolchain: None,
|
||||||
|
|
@ -325,7 +325,7 @@
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
ws_data: CrateWorkspaceData {
|
ws_data: CrateWorkspaceData {
|
||||||
data_layout: Err(
|
target: Err(
|
||||||
"target_data_layout not loaded",
|
"target_data_layout not loaded",
|
||||||
),
|
),
|
||||||
toolchain: None,
|
toolchain: None,
|
||||||
|
|
@ -406,7 +406,7 @@
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
ws_data: CrateWorkspaceData {
|
ws_data: CrateWorkspaceData {
|
||||||
data_layout: Err(
|
target: Err(
|
||||||
"target_data_layout not loaded",
|
"target_data_layout not loaded",
|
||||||
),
|
),
|
||||||
toolchain: None,
|
toolchain: None,
|
||||||
|
|
|
||||||
|
|
@ -69,7 +69,7 @@
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
ws_data: CrateWorkspaceData {
|
ws_data: CrateWorkspaceData {
|
||||||
data_layout: Err(
|
target: Err(
|
||||||
"target_data_layout not loaded",
|
"target_data_layout not loaded",
|
||||||
),
|
),
|
||||||
toolchain: None,
|
toolchain: None,
|
||||||
|
|
@ -153,7 +153,7 @@
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
ws_data: CrateWorkspaceData {
|
ws_data: CrateWorkspaceData {
|
||||||
data_layout: Err(
|
target: Err(
|
||||||
"target_data_layout not loaded",
|
"target_data_layout not loaded",
|
||||||
),
|
),
|
||||||
toolchain: None,
|
toolchain: None,
|
||||||
|
|
@ -237,7 +237,7 @@
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
ws_data: CrateWorkspaceData {
|
ws_data: CrateWorkspaceData {
|
||||||
data_layout: Err(
|
target: Err(
|
||||||
"target_data_layout not loaded",
|
"target_data_layout not loaded",
|
||||||
),
|
),
|
||||||
toolchain: None,
|
toolchain: None,
|
||||||
|
|
@ -321,7 +321,7 @@
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
ws_data: CrateWorkspaceData {
|
ws_data: CrateWorkspaceData {
|
||||||
data_layout: Err(
|
target: Err(
|
||||||
"target_data_layout not loaded",
|
"target_data_layout not loaded",
|
||||||
),
|
),
|
||||||
toolchain: None,
|
toolchain: None,
|
||||||
|
|
@ -402,7 +402,7 @@
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
ws_data: CrateWorkspaceData {
|
ws_data: CrateWorkspaceData {
|
||||||
data_layout: Err(
|
target: Err(
|
||||||
"target_data_layout not loaded",
|
"target_data_layout not loaded",
|
||||||
),
|
),
|
||||||
toolchain: None,
|
toolchain: None,
|
||||||
|
|
|
||||||
|
|
@ -43,8 +43,8 @@
|
||||||
entries: {},
|
entries: {},
|
||||||
},
|
},
|
||||||
ws_data: CrateWorkspaceData {
|
ws_data: CrateWorkspaceData {
|
||||||
data_layout: Err(
|
target: Err(
|
||||||
"test has no data layout",
|
"test has no target data",
|
||||||
),
|
),
|
||||||
toolchain: None,
|
toolchain: None,
|
||||||
},
|
},
|
||||||
|
|
@ -93,8 +93,8 @@
|
||||||
entries: {},
|
entries: {},
|
||||||
},
|
},
|
||||||
ws_data: CrateWorkspaceData {
|
ws_data: CrateWorkspaceData {
|
||||||
data_layout: Err(
|
target: Err(
|
||||||
"test has no data layout",
|
"test has no target data",
|
||||||
),
|
),
|
||||||
toolchain: None,
|
toolchain: None,
|
||||||
},
|
},
|
||||||
|
|
|
||||||
|
|
@ -40,8 +40,8 @@
|
||||||
entries: {},
|
entries: {},
|
||||||
},
|
},
|
||||||
ws_data: CrateWorkspaceData {
|
ws_data: CrateWorkspaceData {
|
||||||
data_layout: Err(
|
target: Err(
|
||||||
"test has no data layout",
|
"test has no target data",
|
||||||
),
|
),
|
||||||
toolchain: None,
|
toolchain: None,
|
||||||
},
|
},
|
||||||
|
|
|
||||||
|
|
@ -11,7 +11,7 @@ use ide_db::base_db;
|
||||||
use itertools::Either;
|
use itertools::Either;
|
||||||
use paths::Utf8PathBuf;
|
use paths::Utf8PathBuf;
|
||||||
use profile::StopWatch;
|
use profile::StopWatch;
|
||||||
use project_model::toolchain_info::{QueryConfig, target_data_layout};
|
use project_model::toolchain_info::{QueryConfig, target_data};
|
||||||
use project_model::{
|
use project_model::{
|
||||||
CargoConfig, ManifestPath, ProjectWorkspace, ProjectWorkspaceKind, RustLibSource,
|
CargoConfig, ManifestPath, ProjectWorkspace, ProjectWorkspaceKind, RustLibSource,
|
||||||
RustSourceWorkspaceConfig, Sysroot,
|
RustSourceWorkspaceConfig, Sysroot,
|
||||||
|
|
@ -19,7 +19,6 @@ use project_model::{
|
||||||
|
|
||||||
use load_cargo::{LoadCargoConfig, ProcMacroServerChoice, load_workspace};
|
use load_cargo::{LoadCargoConfig, ProcMacroServerChoice, load_workspace};
|
||||||
use rustc_hash::FxHashMap;
|
use rustc_hash::FxHashMap;
|
||||||
use triomphe::Arc;
|
|
||||||
use vfs::{AbsPathBuf, FileId};
|
use vfs::{AbsPathBuf, FileId};
|
||||||
use walkdir::WalkDir;
|
use walkdir::WalkDir;
|
||||||
|
|
||||||
|
|
@ -87,7 +86,7 @@ impl Tester {
|
||||||
sysroot.set_workspace(loaded_sysroot);
|
sysroot.set_workspace(loaded_sysroot);
|
||||||
}
|
}
|
||||||
|
|
||||||
let data_layout = target_data_layout::get(
|
let target_data = target_data::get(
|
||||||
QueryConfig::Rustc(&sysroot, tmp_file.parent().unwrap().as_ref()),
|
QueryConfig::Rustc(&sysroot, tmp_file.parent().unwrap().as_ref()),
|
||||||
None,
|
None,
|
||||||
&cargo_config.extra_env,
|
&cargo_config.extra_env,
|
||||||
|
|
@ -101,7 +100,7 @@ impl Tester {
|
||||||
sysroot,
|
sysroot,
|
||||||
rustc_cfg: vec![],
|
rustc_cfg: vec![],
|
||||||
toolchain: None,
|
toolchain: None,
|
||||||
target_layout: data_layout.map(Arc::from).map_err(|it| Arc::from(it.to_string())),
|
target: target_data.map_err(|it| it.to_string().into()),
|
||||||
cfg_overrides: Default::default(),
|
cfg_overrides: Default::default(),
|
||||||
extra_includes: vec![],
|
extra_includes: vec![],
|
||||||
set_test: true,
|
set_test: true,
|
||||||
|
|
|
||||||
|
|
@ -97,6 +97,7 @@ impl Project<'_> {
|
||||||
proc_macro_names,
|
proc_macro_names,
|
||||||
toolchain,
|
toolchain,
|
||||||
target_data_layout: _,
|
target_data_layout: _,
|
||||||
|
target_arch: _,
|
||||||
} = FixtureWithProjectMeta::parse(self.fixture);
|
} = FixtureWithProjectMeta::parse(self.fixture);
|
||||||
assert!(proc_macro_names.is_empty());
|
assert!(proc_macro_names.is_empty());
|
||||||
assert!(mini_core.is_none());
|
assert!(mini_core.is_none());
|
||||||
|
|
@ -177,6 +178,7 @@ impl Project<'_> {
|
||||||
proc_macro_names,
|
proc_macro_names,
|
||||||
toolchain,
|
toolchain,
|
||||||
target_data_layout: _,
|
target_data_layout: _,
|
||||||
|
target_arch: _,
|
||||||
} = FixtureWithProjectMeta::parse(self.fixture);
|
} = FixtureWithProjectMeta::parse(self.fixture);
|
||||||
assert!(proc_macro_names.is_empty());
|
assert!(proc_macro_names.is_empty());
|
||||||
assert!(mini_core.is_none());
|
assert!(mini_core.is_none());
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
//! A set of high-level utility fixture methods to use in tests.
|
//! A set of high-level utility fixture methods to use in tests.
|
||||||
use std::{any::TypeId, mem, str::FromStr, sync};
|
use std::{any::TypeId, mem, str::FromStr, sync};
|
||||||
|
|
||||||
|
use base_db::target::TargetData;
|
||||||
use base_db::{
|
use base_db::{
|
||||||
Crate, CrateDisplayName, CrateGraphBuilder, CrateName, CrateOrigin, CrateWorkspaceData,
|
Crate, CrateDisplayName, CrateGraphBuilder, CrateName, CrateOrigin, CrateWorkspaceData,
|
||||||
DependencyBuilder, Env, FileChange, FileSet, FxIndexMap, LangCrateOrigin, SourceDatabase,
|
DependencyBuilder, Env, FileChange, FileSet, FxIndexMap, LangCrateOrigin, SourceDatabase,
|
||||||
|
|
@ -136,8 +137,11 @@ impl ChangeFixture {
|
||||||
proc_macro_names,
|
proc_macro_names,
|
||||||
toolchain,
|
toolchain,
|
||||||
target_data_layout,
|
target_data_layout,
|
||||||
|
target_arch,
|
||||||
} = FixtureWithProjectMeta::parse(ra_fixture);
|
} = FixtureWithProjectMeta::parse(ra_fixture);
|
||||||
let target_data_layout = Ok(target_data_layout.into());
|
let target_data_layout = target_data_layout.into();
|
||||||
|
let target_arch = parse_target_arch(&target_arch);
|
||||||
|
let target = Ok(TargetData { arch: target_arch, data_layout: target_data_layout });
|
||||||
let toolchain = Some({
|
let toolchain = Some({
|
||||||
let channel = toolchain.as_deref().unwrap_or("stable");
|
let channel = toolchain.as_deref().unwrap_or("stable");
|
||||||
Version::parse(&format!("1.76.0-{channel}")).unwrap()
|
Version::parse(&format!("1.76.0-{channel}")).unwrap()
|
||||||
|
|
@ -163,8 +167,7 @@ impl ChangeFixture {
|
||||||
|
|
||||||
let mut file_position = None;
|
let mut file_position = None;
|
||||||
|
|
||||||
let crate_ws_data =
|
let crate_ws_data = Arc::new(CrateWorkspaceData { target, toolchain });
|
||||||
Arc::new(CrateWorkspaceData { data_layout: target_data_layout, toolchain });
|
|
||||||
|
|
||||||
// FIXME: This is less than ideal
|
// FIXME: This is less than ideal
|
||||||
let proc_macro_cwd = Arc::new(AbsPathBuf::assert_utf8(std::env::current_dir().unwrap()));
|
let proc_macro_cwd = Arc::new(AbsPathBuf::assert_utf8(std::env::current_dir().unwrap()));
|
||||||
|
|
@ -395,6 +398,15 @@ impl ChangeFixture {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn parse_target_arch(arch: &str) -> base_db::target::Arch {
|
||||||
|
use base_db::target::Arch::*;
|
||||||
|
match arch {
|
||||||
|
"wasm32" => Wasm32,
|
||||||
|
"wasm64" => Wasm64,
|
||||||
|
_ => Other,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn default_test_proc_macros() -> Box<[(String, ProcMacro)]> {
|
fn default_test_proc_macros() -> Box<[(String, ProcMacro)]> {
|
||||||
Box::new([
|
Box::new([
|
||||||
(
|
(
|
||||||
|
|
|
||||||
|
|
@ -149,6 +149,8 @@ pub struct FixtureWithProjectMeta {
|
||||||
/// You probably don't want to manually specify this. See LLVM manual for the
|
/// You probably don't want to manually specify this. See LLVM manual for the
|
||||||
/// syntax, if you must: <https://llvm.org/docs/LangRef.html#data-layout>
|
/// syntax, if you must: <https://llvm.org/docs/LangRef.html#data-layout>
|
||||||
pub target_data_layout: String,
|
pub target_data_layout: String,
|
||||||
|
/// Specifies the target architecture.
|
||||||
|
pub target_arch: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl FixtureWithProjectMeta {
|
impl FixtureWithProjectMeta {
|
||||||
|
|
@ -178,6 +180,7 @@ impl FixtureWithProjectMeta {
|
||||||
let mut toolchain = None;
|
let mut toolchain = None;
|
||||||
let mut target_data_layout =
|
let mut target_data_layout =
|
||||||
"e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128".to_owned();
|
"e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128".to_owned();
|
||||||
|
let mut target_arch = "x86_64".to_owned();
|
||||||
let mut mini_core = None;
|
let mut mini_core = None;
|
||||||
let mut res: Vec<Fixture> = Vec::new();
|
let mut res: Vec<Fixture> = Vec::new();
|
||||||
let mut proc_macro_names = vec![];
|
let mut proc_macro_names = vec![];
|
||||||
|
|
@ -194,6 +197,12 @@ impl FixtureWithProjectMeta {
|
||||||
fixture = remain;
|
fixture = remain;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if let Some(meta) = fixture.strip_prefix("//- target_arch:") {
|
||||||
|
let (meta, remain) = meta.split_once('\n').unwrap();
|
||||||
|
meta.trim().clone_into(&mut target_arch);
|
||||||
|
fixture = remain;
|
||||||
|
}
|
||||||
|
|
||||||
if let Some(meta) = fixture.strip_prefix("//- proc_macros:") {
|
if let Some(meta) = fixture.strip_prefix("//- proc_macros:") {
|
||||||
let (meta, remain) = meta.split_once('\n').unwrap();
|
let (meta, remain) = meta.split_once('\n').unwrap();
|
||||||
proc_macro_names = meta.split(',').map(|it| it.trim().to_owned()).collect();
|
proc_macro_names = meta.split(',').map(|it| it.trim().to_owned()).collect();
|
||||||
|
|
@ -232,7 +241,14 @@ impl FixtureWithProjectMeta {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Self { fixture: res, mini_core, proc_macro_names, toolchain, target_data_layout }
|
Self {
|
||||||
|
fixture: res,
|
||||||
|
mini_core,
|
||||||
|
proc_macro_names,
|
||||||
|
toolchain,
|
||||||
|
target_data_layout,
|
||||||
|
target_arch,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//- /lib.rs crate:foo deps:bar,baz cfg:foo=a,bar=b env:OUTDIR=path/to,OTHER=foo
|
//- /lib.rs crate:foo deps:bar,baz cfg:foo=a,bar=b env:OUTDIR=path/to,OTHER=foo
|
||||||
|
|
@ -511,6 +527,7 @@ fn parse_fixture_gets_full_meta() {
|
||||||
proc_macro_names,
|
proc_macro_names,
|
||||||
toolchain,
|
toolchain,
|
||||||
target_data_layout: _,
|
target_data_layout: _,
|
||||||
|
target_arch: _,
|
||||||
} = FixtureWithProjectMeta::parse(
|
} = FixtureWithProjectMeta::parse(
|
||||||
r#"
|
r#"
|
||||||
//- toolchain: nightly
|
//- toolchain: nightly
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue