Skip to content

Commit 51d17b9

Browse files
committed
target enum: propagate parsing error to build() to reduce breakage
1 parent d80832e commit 51d17b9

File tree

4 files changed

+63
-9
lines changed

4 files changed

+63
-9
lines changed

crates/rustc_codegen_spirv-target-specs/src/lib.rs

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,9 @@ pub const TARGET_SPEC_DIR_PATH: &str = concat!(env!("CARGO_MANIFEST_DIR"), "/tar
1212
#[cfg(feature = "include_str")]
1313
mod include_str;
1414
#[cfg(feature = "serde")]
15-
mod serde;
15+
mod serde_feature;
16+
#[cfg(feature = "serde")]
17+
pub use serde_feature::*;
1618

1719
pub const SPIRV_ARCH: &str = "spirv";
1820
pub const SPIRV_VENDOR: &str = "unknown";
@@ -60,7 +62,8 @@ pub enum SpirvTargetEnv {
6062
Vulkan_1_4,
6163
}
6264

63-
#[derive(Error)]
65+
#[derive(Clone, Error)]
66+
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
6467
pub enum SpirvTargetParseError {
6568
#[error("Expected `rustc_codegen_spirv` target with prefix `{SPIRV_TARGET_PREFIX}`, got `{0}`")]
6669
WrongPrefix(String),
@@ -125,6 +128,12 @@ impl IntoSpirvTarget for &str {
125128
}
126129
}
127130

131+
impl IntoSpirvTarget for String {
132+
fn to_spirv_target_env(&self) -> Result<SpirvTargetEnv, SpirvTargetParseError> {
133+
SpirvTargetEnv::parse_triple(self)
134+
}
135+
}
136+
128137
#[cfg(test)]
129138
mod tests {
130139
use super::*;

crates/rustc_codegen_spirv-target-specs/src/serde.rs renamed to crates/rustc_codegen_spirv-target-specs/src/serde_feature.rs

Lines changed: 30 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
use crate::SpirvTargetEnv;
1+
use crate::{SpirvTargetEnv, SpirvTargetParseError};
2+
use serde::ser::Error;
23
use serde::{Deserialize, Deserializer, Serialize, Serializer};
34

45
impl Serialize for SpirvTargetEnv {
@@ -20,6 +21,34 @@ impl<'de> Deserialize<'de> for SpirvTargetEnv {
2021
}
2122
}
2223

24+
pub fn serialize_target<S>(
25+
target: &Option<Result<SpirvTargetEnv, SpirvTargetParseError>>,
26+
serializer: S,
27+
) -> Result<S::Ok, S::Error>
28+
where
29+
S: Serializer,
30+
{
31+
// cannot use `transpose()` due to target being a ref, not a value
32+
match target {
33+
Some(Ok(_)) | None => Serialize::serialize(target, serializer),
34+
Some(Err(_e)) => Err(Error::custom(
35+
"cannot serialize `target` that failed to parse",
36+
)),
37+
}
38+
}
39+
40+
pub fn deserialize_target<'de, D>(
41+
deserializer: D,
42+
) -> Result<Option<Result<SpirvTargetEnv, SpirvTargetParseError>>, D::Error>
43+
where
44+
D: Deserializer<'de>,
45+
{
46+
Ok(Ok(<Option<SpirvTargetEnv> as Deserialize>::deserialize(
47+
deserializer,
48+
)?)
49+
.transpose())
50+
}
51+
2352
#[cfg(test)]
2453
mod tests {
2554
use crate::SpirvTargetEnv;

crates/spirv-builder/src/lib.rs

Lines changed: 21 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,7 @@ use thiserror::Error;
9393
pub use rustc_codegen_spirv_target_specs::{
9494
IntoSpirvTarget, SpirvTargetEnv, SpirvTargetParseError,
9595
};
96+
pub use rustc_codegen_spirv_target_specs::{deserialize_target, serialize_target};
9697
pub use rustc_codegen_spirv_types::*;
9798

9899
#[cfg(feature = "include-target-specs")]
@@ -101,8 +102,10 @@ pub use rustc_codegen_spirv_target_specs::TARGET_SPEC_DIR_PATH;
101102
#[derive(Debug, Error)]
102103
#[non_exhaustive]
103104
pub enum SpirvBuilderError {
104-
#[error("`target` must be set or was invalid, for example `spirv-unknown-vulkan1.2`")]
105+
#[error("`target` must be set, for example `spirv-unknown-vulkan1.2`")]
105106
MissingTarget,
107+
#[error("Error parsing target: {0}")]
108+
SpirvTargetParseError(#[from] SpirvTargetParseError),
106109
#[error("`path_to_crate` must be set")]
107110
MissingCratePath,
108111
#[error("crate path '{0}' does not exist")]
@@ -383,10 +386,14 @@ pub struct SpirvBuilder {
383386
clap(
384387
long,
385388
default_value = "spirv-unknown-vulkan1.2",
386-
value_parser = SpirvTargetEnv::parse_triple
389+
value_parser = Self::parse_target
387390
)
388391
)]
389-
pub target: Option<SpirvTargetEnv>,
392+
#[serde(
393+
serialize_with = "serialize_target",
394+
deserialize_with = "deserialize_target"
395+
)]
396+
pub target: Option<Result<SpirvTargetEnv, SpirvTargetParseError>>,
390397
/// Cargo features specification for building the shader crate.
391398
#[cfg_attr(feature = "clap", clap(flatten))]
392399
#[serde(flatten)]
@@ -455,6 +462,12 @@ pub struct SpirvBuilder {
455462

456463
#[cfg(feature = "clap")]
457464
impl SpirvBuilder {
465+
fn parse_target(
466+
target: &str,
467+
) -> Result<Result<SpirvTargetEnv, SpirvTargetParseError>, clap::Error> {
468+
Ok(SpirvTargetEnv::parse_triple(target))
469+
}
470+
458471
/// Clap value parser for `Capability`.
459472
fn parse_spirv_capability(capability: &str) -> Result<Capability, clap::Error> {
460473
use core::str::FromStr;
@@ -495,7 +508,7 @@ impl SpirvBuilder {
495508
pub fn new(path_to_crate: impl AsRef<Path>, target: impl IntoSpirvTarget) -> Self {
496509
Self {
497510
path_to_crate: Some(path_to_crate.as_ref().to_owned()),
498-
target: target.to_spirv_target_env().ok(),
511+
target: Some(target.to_spirv_target_env()),
499512
..SpirvBuilder::default()
500513
}
501514
}
@@ -762,7 +775,10 @@ fn join_checking_for_separators(strings: Vec<impl Borrow<str>>, sep: &str) -> St
762775

763776
// Returns path to the metadata json.
764777
fn invoke_rustc(builder: &SpirvBuilder) -> Result<PathBuf, SpirvBuilderError> {
765-
let target = builder.target.ok_or(SpirvBuilderError::MissingTarget)?;
778+
let target = builder
779+
.target
780+
.clone()
781+
.ok_or(SpirvBuilderError::MissingTarget)??;
766782
let path_to_crate = builder
767783
.path_to_crate
768784
.as_ref()

crates/spirv-builder/src/tests.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,6 @@ mod clap {
2222
let builder = SpirvBuilder::try_parse_from(["", "--target", &env.target_triple()])
2323
.map_err(|e| e.to_string())
2424
.unwrap();
25-
assert_eq!(builder.target, Some(env));
25+
assert_eq!(builder.target.unwrap().unwrap(), env);
2626
}
2727
}

0 commit comments

Comments
 (0)