Skip to content

Commit 1d64638

Browse files
committed
target enum: propagate parsing error to build() to reduce breakage
1 parent f547feb commit 1d64638

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
@@ -92,6 +92,7 @@ use thiserror::Error;
9292
pub use rustc_codegen_spirv_target_specs::{
9393
IntoSpirvTarget, SpirvTargetEnv, SpirvTargetParseError,
9494
};
95+
pub use rustc_codegen_spirv_target_specs::{deserialize_target, serialize_target};
9596
pub use rustc_codegen_spirv_types::*;
9697

9798
#[cfg(feature = "include-target-specs")]
@@ -100,8 +101,10 @@ pub use rustc_codegen_spirv_target_specs::TARGET_SPEC_DIR_PATH;
100101
#[derive(Debug, Error)]
101102
#[non_exhaustive]
102103
pub enum SpirvBuilderError {
103-
#[error("`target` must be set or was invalid, for example `spirv-unknown-vulkan1.2`")]
104+
#[error("`target` must be set, for example `spirv-unknown-vulkan1.2`")]
104105
MissingTarget,
106+
#[error("Error parsing target: {0}")]
107+
SpirvTargetParseError(#[from] SpirvTargetParseError),
105108
#[error("`path_to_crate` must be set")]
106109
MissingCratePath,
107110
#[error("crate path '{0}' does not exist")]
@@ -382,10 +385,14 @@ pub struct SpirvBuilder {
382385
clap(
383386
long,
384387
default_value = "spirv-unknown-vulkan1.2",
385-
value_parser = SpirvTargetEnv::parse_triple
388+
value_parser = Self::parse_target
386389
)
387390
)]
388-
pub target: Option<SpirvTargetEnv>,
391+
#[serde(
392+
serialize_with = "serialize_target",
393+
deserialize_with = "deserialize_target"
394+
)]
395+
pub target: Option<Result<SpirvTargetEnv, SpirvTargetParseError>>,
389396
/// Cargo features specification for building the shader crate.
390397
#[cfg_attr(feature = "clap", clap(flatten))]
391398
#[serde(flatten)]
@@ -454,6 +461,12 @@ pub struct SpirvBuilder {
454461

455462
#[cfg(feature = "clap")]
456463
impl SpirvBuilder {
464+
fn parse_target(
465+
target: &str,
466+
) -> Result<Result<SpirvTargetEnv, SpirvTargetParseError>, clap::Error> {
467+
Ok(SpirvTargetEnv::parse_triple(target))
468+
}
469+
457470
/// Clap value parser for `Capability`.
458471
fn parse_spirv_capability(capability: &str) -> Result<Capability, clap::Error> {
459472
use core::str::FromStr;
@@ -494,7 +507,7 @@ impl SpirvBuilder {
494507
pub fn new(path_to_crate: impl AsRef<Path>, target: impl IntoSpirvTarget) -> Self {
495508
Self {
496509
path_to_crate: Some(path_to_crate.as_ref().to_owned()),
497-
target: target.to_spirv_target_env().ok(),
510+
target: Some(target.to_spirv_target_env()),
498511
..SpirvBuilder::default()
499512
}
500513
}
@@ -761,7 +774,10 @@ fn join_checking_for_separators(strings: Vec<impl Borrow<str>>, sep: &str) -> St
761774

762775
// Returns path to the metadata json.
763776
fn invoke_rustc(builder: &SpirvBuilder) -> Result<PathBuf, SpirvBuilderError> {
764-
let target = builder.target.ok_or(SpirvBuilderError::MissingTarget)?;
777+
let target = builder
778+
.target
779+
.clone()
780+
.ok_or(SpirvBuilderError::MissingTarget)??;
765781
let path_to_crate = builder
766782
.path_to_crate
767783
.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)