Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 21 additions & 1 deletion core/src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ pub enum GenerationError {
PostGeneration(String),
}

#[derive(Debug, Error)]
#[derive(Debug, Error, Clone)]
#[allow(missing_docs)]
pub enum RustTypeParseError {
#[error("Unsupported type: \"{}\"", .0.iter().join(","))]
Expand All @@ -99,3 +99,23 @@ pub enum RustTypeParseError {
#[error("Could not parse numeric literal")]
NumericLiteral(syn::parse::Error),
}

impl PartialEq for RustTypeParseError {
fn eq(&self, other: &Self) -> bool {
match (self, other) {
(RustTypeParseError::UnsupportedType(a), RustTypeParseError::UnsupportedType(b)) => {
a == b
}
(RustTypeParseError::UnexpectedToken(a), RustTypeParseError::UnexpectedToken(b)) => {
a == b
}
(
RustTypeParseError::UnexpectedParameterizedTuple,
RustTypeParseError::UnexpectedParameterizedTuple,
) => true,
(RustTypeParseError::NumericLiteral(_), RustTypeParseError::NumericLiteral(_)) => true,
_ => false,
}
}
}
impl Eq for RustTypeParseError {}
9 changes: 9 additions & 0 deletions core/src/language/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -215,6 +215,15 @@ pub trait Language {
self.format_generic_type(id, parameters.as_slice(), generic_types)
}
RustType::Special(special) => self.format_special_type(special, generic_types),
RustType::Unrepresentable {
error,
line,
column,
} => Err(RustTypeFormatError::UnrepresentableType {
error: error.clone(),
line: *line,
column: *column,
}),
}
}

Expand Down
1 change: 1 addition & 0 deletions core/src/language/python.rs
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ fn collect_generics_for_variant(variant_type: &RustType, generics: &[String]) ->
}
_ => {}
},
RustType::Unrepresentable { .. } => {}
}
// Remove any duplicates
// E.g. Foo(HashMap<T, T>) should only produce a single type var
Expand Down
1 change: 1 addition & 0 deletions core/src/language/scala.rs
Original file line number Diff line number Diff line change
Expand Up @@ -493,6 +493,7 @@ impl Scala {
}
RustType::Special(_) => vec![ty.clone()],
RustType::Simple { .. } => vec![],
RustType::Unrepresentable { .. } => vec![],
})
.any(|ty| {
matches!(
Expand Down
1 change: 1 addition & 0 deletions core/src/reconcile.rs
Original file line number Diff line number Diff line change
Expand Up @@ -163,6 +163,7 @@ fn check_type(
*id = renamed.to_owned();
}
}
RustType::Unrepresentable { .. } => {}
}
}

Expand Down
33 changes: 30 additions & 3 deletions core/src/rust_types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -212,6 +212,14 @@ pub enum RustType {
#[allow(missing_docs)]
id: String,
},
/// Unrepresentable type due to parsing error. Types may be overridden when emitted, so
/// we don't fail immediately but store the error here. We have to separate the span into
/// line and column because spans aren't Send and so can't be converted into io::Error.
Unrepresentable {
error: RustTypeParseError,
line: usize,
column: usize,
},
}

impl Display for RustType {
Expand All @@ -233,6 +241,13 @@ impl Display for RustType {
}
}
RustType::Special(ty) => &ty.to_string(),
RustType::Unrepresentable {
error,
line,
column,
} => {
return write!(f, "{error:?} at line {line}, column {column}");
}
};
write!(f, "{rust_type}")
}
Expand Down Expand Up @@ -331,9 +346,11 @@ impl TryFrom<&syn::Type> for RustType {
syn::Type::Tuple(tuple) if tuple.elems.iter().count() == 0 => {
Self::Special(SpecialRustType::Unit)
}
syn::Type::Tuple(tt) => {
return Err(RustTypeParseError::UnexpectedParameterizedTuple.with_span(tt.span()))
}
syn::Type::Tuple(tt) => Self::Unrepresentable {
error: RustTypeParseError::UnexpectedParameterizedTuple,
line: tt.span().start().line,
column: tt.span().start().column,
},
syn::Type::Reference(reference) => Self::try_from(reference.elem.as_ref())?,
syn::Type::Path(path) => {
let segment = path.path.segments.iter().next_back().unwrap();
Expand Down Expand Up @@ -441,6 +458,7 @@ impl RustType {
id == ty || parameters.iter().any(|p| p.contains_type(ty))
}
Self::Special(special) => special.contains_type(ty),
Self::Unrepresentable { .. } => false,
}
}

Expand All @@ -449,6 +467,7 @@ impl RustType {
match &self {
Self::Simple { id } | Self::Generic { id, .. } => id.as_str(),
Self::Special(special) => special.id(),
Self::Unrepresentable { .. } => "Unrepresentable",
}
}
/// Check if the type is `Option<T>`
Expand Down Expand Up @@ -482,6 +501,7 @@ impl RustType {
Self::Simple { .. } => Box::new(std::iter::empty()),
Self::Generic { parameters, .. } => Box::new(parameters.iter()),
Self::Special(special) => special.parameters(),
Self::Unrepresentable { .. } => Box::new(std::iter::empty()),
}
}

Expand Down Expand Up @@ -540,6 +560,13 @@ pub enum RustTypeFormatError {
GenericKeyForbiddenInTS(String),
#[error("The special type `{0}` is not supported in this language")]
UnsupportedSpecialType(String),
// An error which occurred at parsing time which makes this type unrepresentable.
#[error("{error} at line {line}, column {column}")]
UnrepresentableType {
error: RustTypeParseError,
line: usize,
column: usize,
},
}

impl SpecialRustType {
Expand Down
1 change: 1 addition & 0 deletions core/src/topsort.rs
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ fn get_dependencies_from_type(
}
_ => {}
},
RustType::Unrepresentable { .. } => {}
};
seen.remove(&tp.id().to_string());
}
Expand Down