Skip to content

Commit db0420c

Browse files
authored
Merge pull request #20642 from ChayimFriedman2/wasm-safe
fix: Make `#[target_feature]` always safe on WASM
2 parents f9675f0 + fcab4fb commit db0420c

File tree

27 files changed

+257
-89
lines changed

27 files changed

+257
-89
lines changed

crates/base-db/src/input.rs

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -295,8 +295,6 @@ impl CrateDisplayName {
295295
}
296296
}
297297

298-
pub type TargetLayoutLoadResult = Result<Arc<str>, Arc<str>>;
299-
300298
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
301299
pub enum ReleaseChannel {
302300
Stable,
@@ -929,7 +927,7 @@ mod tests {
929927
use super::{CrateGraphBuilder, CrateName, CrateOrigin, Edition::Edition2018, Env, FileId};
930928

931929
fn empty_ws_data() -> Arc<CrateWorkspaceData> {
932-
Arc::new(CrateWorkspaceData { data_layout: Err("".into()), toolchain: None })
930+
Arc::new(CrateWorkspaceData { target: Err("".into()), toolchain: None })
933931
}
934932

935933
#[test]

crates/base-db/src/lib.rs

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ pub use salsa_macros;
66
// FIXME: Rename this crate, base db is non descriptive
77
mod change;
88
mod input;
9+
pub mod target;
910

1011
use std::{
1112
cell::RefCell,
@@ -20,8 +21,7 @@ pub use crate::{
2021
BuiltCrateData, BuiltDependency, Crate, CrateBuilder, CrateBuilderId, CrateDataBuilder,
2122
CrateDisplayName, CrateGraphBuilder, CrateName, CrateOrigin, CratesIdMap, CratesMap,
2223
DependencyBuilder, Env, ExtraCrateData, LangCrateOrigin, ProcMacroLoadingError,
23-
ProcMacroPaths, ReleaseChannel, SourceRoot, SourceRootId, TargetLayoutLoadResult,
24-
UniqueCrateData,
24+
ProcMacroPaths, ReleaseChannel, SourceRoot, SourceRootId, UniqueCrateData,
2525
},
2626
};
2727
use dashmap::{DashMap, mapref::entry::Entry};
@@ -359,8 +359,7 @@ impl Nonce {
359359
/// Crate related data shared by the whole workspace.
360360
#[derive(Debug, PartialEq, Eq, Hash, Clone)]
361361
pub struct CrateWorkspaceData {
362-
// FIXME: Consider removing this, making HirDatabase::target_data_layout an input query
363-
pub data_layout: TargetLayoutLoadResult,
362+
pub target: Result<target::TargetData, target::TargetLoadError>,
364363
/// Toolchain version used to compile the crate.
365364
pub toolchain: Option<Version>,
366365
}

crates/base-db/src/target.rs

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
//! Information about the target.
2+
3+
use std::fmt;
4+
5+
use triomphe::Arc;
6+
7+
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
8+
pub enum Arch {
9+
// Only what we need is present here.
10+
Wasm32,
11+
Wasm64,
12+
Other,
13+
}
14+
15+
#[derive(Debug, PartialEq, Eq, Hash, Clone)]
16+
pub struct TargetData {
17+
pub data_layout: Box<str>,
18+
pub arch: Arch,
19+
}
20+
21+
#[derive(Clone, PartialEq, Eq, Hash)]
22+
pub struct TargetLoadError(Arc<str>);
23+
24+
impl fmt::Debug for TargetLoadError {
25+
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
26+
fmt::Debug::fmt(&self.0, f)
27+
}
28+
}
29+
30+
impl fmt::Display for TargetLoadError {
31+
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
32+
fmt::Display::fmt(&self.0, f)
33+
}
34+
}
35+
36+
impl std::error::Error for TargetLoadError {}
37+
38+
impl From<String> for TargetLoadError {
39+
fn from(value: String) -> Self {
40+
Self(value.into())
41+
}
42+
}
43+
44+
impl From<&str> for TargetLoadError {
45+
fn from(value: &str) -> Self {
46+
Self(value.into())
47+
}
48+
}
49+
50+
pub type TargetLoadResult = Result<TargetData, TargetLoadError>;

crates/hir-def/src/nameres/tests/incremental.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,7 @@ pub const BAZ: u32 = 0;
8484
)
8585
.unwrap(),
8686
),
87-
Arc::new(CrateWorkspaceData { data_layout: Err("".into()), toolchain: None }),
87+
Arc::new(CrateWorkspaceData { target: Err("".into()), toolchain: None }),
8888
)
8989
};
9090
let a = add_crate("a", 0);

crates/hir-ty/src/db.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
//! type inference-related queries.
33
44
use base_db::Crate;
5+
use base_db::target::TargetLoadError;
56
use hir_def::{
67
AdtId, BlockId, CallableDefId, ConstParamId, DefWithBodyId, EnumVariantId, FunctionId,
78
GeneralConstId, GenericDefId, ImplId, LifetimeParamId, LocalFieldId, StaticId, TraitId,
@@ -108,7 +109,7 @@ pub trait HirDatabase: DefDatabase + std::fmt::Debug {
108109
) -> Result<Arc<Layout>, LayoutError>;
109110

110111
#[salsa::invoke(crate::layout::target_data_layout_query)]
111-
fn target_data_layout(&self, krate: Crate) -> Result<Arc<TargetDataLayout>, Arc<str>>;
112+
fn target_data_layout(&self, krate: Crate) -> Result<Arc<TargetDataLayout>, TargetLoadError>;
112113

113114
#[salsa::invoke(crate::dyn_compatibility::dyn_compatibility_of_trait_query)]
114115
fn dyn_compatibility_of_trait(&self, trait_: TraitId) -> Option<DynCompatibilityViolation>;

crates/hir-ty/src/diagnostics/unsafe_check.rs

Lines changed: 20 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,9 @@ use hir_def::{
1515
use span::Edition;
1616

1717
use crate::{
18-
InferenceResult, Interner, TargetFeatures, TyExt, TyKind, db::HirDatabase,
19-
utils::is_fn_unsafe_to_call,
18+
InferenceResult, Interner, TargetFeatures, TyExt, TyKind,
19+
db::HirDatabase,
20+
utils::{is_fn_unsafe_to_call, target_feature_is_safe_in_target},
2021
};
2122

2223
#[derive(Debug, Default)]
@@ -144,6 +145,9 @@ struct UnsafeVisitor<'db> {
144145
def_target_features: TargetFeatures,
145146
// FIXME: This needs to be the edition of the span of each call.
146147
edition: Edition,
148+
/// On some targets (WASM), calling safe functions with `#[target_feature]` is always safe, even when
149+
/// the target feature is not enabled. This flag encodes that.
150+
target_feature_is_safe: bool,
147151
}
148152

149153
impl<'db> UnsafeVisitor<'db> {
@@ -159,7 +163,12 @@ impl<'db> UnsafeVisitor<'db> {
159163
DefWithBodyId::FunctionId(func) => TargetFeatures::from_attrs(&db.attrs(func.into())),
160164
_ => TargetFeatures::default(),
161165
};
162-
let edition = resolver.module().krate().data(db).edition;
166+
let krate = resolver.module().krate();
167+
let edition = krate.data(db).edition;
168+
let target_feature_is_safe = match &krate.workspace_data(db).target {
169+
Ok(target) => target_feature_is_safe_in_target(target),
170+
Err(_) => false,
171+
};
163172
Self {
164173
db,
165174
infer,
@@ -172,6 +181,7 @@ impl<'db> UnsafeVisitor<'db> {
172181
callback: unsafe_expr_cb,
173182
def_target_features,
174183
edition,
184+
target_feature_is_safe,
175185
}
176186
}
177187

@@ -184,7 +194,13 @@ impl<'db> UnsafeVisitor<'db> {
184194
}
185195

186196
fn check_call(&mut self, node: ExprId, func: FunctionId) {
187-
let unsafety = is_fn_unsafe_to_call(self.db, func, &self.def_target_features, self.edition);
197+
let unsafety = is_fn_unsafe_to_call(
198+
self.db,
199+
func,
200+
&self.def_target_features,
201+
self.edition,
202+
self.target_feature_is_safe,
203+
);
188204
match unsafety {
189205
crate::utils::Unsafety::Safe => {}
190206
crate::utils::Unsafety::Unsafe => {

crates/hir-ty/src/layout/target.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
//! Target dependent parameters needed for layouts
22
3-
use base_db::Crate;
3+
use base_db::{Crate, target::TargetLoadError};
44
use hir_def::layout::TargetDataLayout;
55
use rustc_abi::{AddressSpace, AlignFromBytesError, TargetDataLayoutErrors};
66
use triomphe::Arc;
@@ -10,9 +10,9 @@ use crate::db::HirDatabase;
1010
pub fn target_data_layout_query(
1111
db: &dyn HirDatabase,
1212
krate: Crate,
13-
) -> Result<Arc<TargetDataLayout>, Arc<str>> {
14-
match &krate.workspace_data(db).data_layout {
15-
Ok(it) => match TargetDataLayout::parse_from_llvm_datalayout_string(it, AddressSpace::ZERO) {
13+
) -> Result<Arc<TargetDataLayout>, TargetLoadError> {
14+
match &krate.workspace_data(db).target {
15+
Ok(target) => match TargetDataLayout::parse_from_llvm_datalayout_string(&target.data_layout, AddressSpace::ZERO) {
1616
Ok(it) => Ok(Arc::new(it)),
1717
Err(e) => {
1818
Err(match e {

crates/hir-ty/src/layout/tests.rs

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
use base_db::target::TargetData;
12
use chalk_ir::{AdtId, TyKind};
23
use either::Either;
34
use hir_def::db::DefDatabase;
@@ -18,8 +19,8 @@ use crate::{
1819

1920
mod closure;
2021

21-
fn current_machine_data_layout() -> String {
22-
project_model::toolchain_info::target_data_layout::get(
22+
fn current_machine_target_data() -> TargetData {
23+
project_model::toolchain_info::target_data::get(
2324
QueryConfig::Rustc(&Sysroot::empty(), &std::env::current_dir().unwrap()),
2425
None,
2526
&FxHashMap::default(),
@@ -32,7 +33,8 @@ fn eval_goal(
3233
minicore: &str,
3334
) -> Result<Arc<Layout>, LayoutError> {
3435
let _tracing = setup_tracing();
35-
let target_data_layout = current_machine_data_layout();
36+
let target_data = current_machine_target_data();
37+
let target_data_layout = target_data.data_layout;
3638
let ra_fixture = format!(
3739
"//- target_data_layout: {target_data_layout}\n{minicore}//- /main.rs crate:test\n{ra_fixture}",
3840
);
@@ -104,7 +106,8 @@ fn eval_expr(
104106
minicore: &str,
105107
) -> Result<Arc<Layout>, LayoutError> {
106108
let _tracing = setup_tracing();
107-
let target_data_layout = current_machine_data_layout();
109+
let target_data = current_machine_target_data();
110+
let target_data_layout = target_data.data_layout;
108111
let ra_fixture = format!(
109112
"//- target_data_layout: {target_data_layout}\n{minicore}//- /main.rs crate:test\nfn main(){{let goal = {{{ra_fixture}}};}}",
110113
);

crates/hir-ty/src/lib.rs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -132,7 +132,10 @@ pub use mapping::{
132132
pub use method_resolution::check_orphan_rules;
133133
pub use target_feature::TargetFeatures;
134134
pub use traits::TraitEnvironment;
135-
pub use utils::{Unsafety, all_super_traits, direct_super_traits, is_fn_unsafe_to_call};
135+
pub use utils::{
136+
Unsafety, all_super_traits, direct_super_traits, is_fn_unsafe_to_call,
137+
target_feature_is_safe_in_target,
138+
};
136139
pub use variance::Variance;
137140

138141
pub use chalk_ir::{

crates/hir-ty/src/mir/eval.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
use std::{borrow::Cow, cell::RefCell, fmt::Write, iter, mem, ops::Range};
44

55
use base_db::Crate;
6+
use base_db::target::TargetLoadError;
67
use chalk_ir::{Mutability, cast::Cast};
78
use either::Either;
89
use hir_def::{
@@ -337,7 +338,7 @@ impl Address {
337338
pub enum MirEvalError {
338339
ConstEvalError(String, Box<ConstEvalError>),
339340
LayoutError(LayoutError, Ty),
340-
TargetDataLayoutNotAvailable(Arc<str>),
341+
TargetDataLayoutNotAvailable(TargetLoadError),
341342
/// Means that code had undefined behavior. We don't try to actively detect UB, but if it was detected
342343
/// then use this type of error.
343344
UndefinedBehavior(String),

0 commit comments

Comments
 (0)