Skip to content
Draft
Show file tree
Hide file tree
Changes from 1 commit
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
30 changes: 28 additions & 2 deletions src/types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,9 @@ pub enum TypeInner<A> {
/// Nominal enum type, represented as a balanced sum of its variants'
/// payload types
Enum(EnumInfo),
/// Type of a recovered subtree. Compatible with every type; never re-reported.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In fdfae8b:

What is a "recovered subtree" what does it mean to "re-report" a type?

/// A diagnostic was already emitted for its span.
Never,
}

/// One variant of a nominal enum type: its name and payload types.
Expand Down Expand Up @@ -201,6 +204,7 @@ impl<A> TypeInner<A> {
}
},
TypeInner::Enum(info) => write!(f, "{}", info.name()),
TypeInner::Never => write!(f, "<never>"),
}
}
}
Expand Down Expand Up @@ -459,6 +463,14 @@ impl ResolvedType {
pub fn as_inner(&self) -> &TypeInner<Arc<Self>> {
&self.0
}

pub const fn never() -> Self {
Self(TypeInner::Never)
}

pub fn is_never(&self) -> bool {
matches!(self.0, TypeInner::Never)
}
}

/// Nominal enum types.
Expand Down Expand Up @@ -571,7 +583,9 @@ impl TypeDeconstructible for ResolvedType {
impl TreeLike for &ResolvedType {
fn as_node(&self) -> Tree<Self> {
match &self.0 {
TypeInner::Boolean | TypeInner::UInt(..) | TypeInner::Enum(..) => Tree::Nullary,
TypeInner::Boolean | TypeInner::UInt(..) | TypeInner::Enum(..) | TypeInner::Never => {
Tree::Nullary
}
TypeInner::Option(l) | TypeInner::Array(l, _) | TypeInner::List(l, _) => Tree::Unary(l),
TypeInner::Either(l, r) => Tree::Binary(l, r),
TypeInner::Tuple(elements) => Tree::Nary(elements.iter().map(Arc::as_ref).collect()),
Expand Down Expand Up @@ -729,6 +743,10 @@ impl AliasedType {
Self(AliasedInner::Builtin(builtin))
}

pub const fn error() -> Self {
Self(AliasedInner::Inner(TypeInner::Never))
}

/// Resolve all aliases in the type based on the given map of `aliases` to types.
pub fn resolve<F, E>(&self, mut get_alias: F) -> Result<ResolvedType, E>
where
Expand Down Expand Up @@ -775,6 +793,7 @@ impl AliasedType {
TypeInner::Enum(info) => {
output.push(ResolvedType::enumeration(info.clone()));
}
TypeInner::Never => output.push(ResolvedType::never()),
},
}
}
Expand Down Expand Up @@ -809,6 +828,7 @@ impl_require_feature!(TypeInner<Arc<AliasedType>> {
Array(element, _),
List(element, _),
Enum(_),
Never,
});

impl TypeConstructible for AliasedType {
Expand Down Expand Up @@ -901,7 +921,10 @@ impl TreeLike for &AliasedType {
match &self.0 {
AliasedInner::Alias(_) | AliasedInner::Builtin(_) => Tree::Nullary,
AliasedInner::Inner(inner) => match inner {
TypeInner::Boolean | TypeInner::UInt(..) | TypeInner::Enum(..) => Tree::Nullary,
TypeInner::Boolean
| TypeInner::UInt(..)
| TypeInner::Enum(..)
| TypeInner::Never => Tree::Nullary,
TypeInner::Option(l) | TypeInner::Array(l, _) | TypeInner::List(l, _) => {
Tree::Unary(l)
}
Expand Down Expand Up @@ -1205,6 +1228,9 @@ impl From<&ResolvedType> for StructuralType {
TypeInner::Enum(info) => {
output.push(StructuralType::balanced_sum(info.structural_variants()));
}
TypeInner::Never => unreachable!(
"poisoned type reached codegen; compilation must be gated on zero errors"
),
}
}
debug_assert_eq!(output.len(), 1);
Expand Down
4 changes: 3 additions & 1 deletion src/value.rs
Original file line number Diff line number Diff line change
Expand Up @@ -864,6 +864,7 @@ impl Value {
}
}
}
TypeInner::Never => unreachable!("poisoned type in value reconstruction; values exist only for error-free programs"),
}
}
debug_assert_eq!(output.len(), 1);
Expand Down Expand Up @@ -937,6 +938,7 @@ impl crate::ArbitraryOfType for Value {
.collect::<arbitrary::Result<Vec<Self>>>()?;
Ok(Self::list(elements, ty.as_ref().clone(), *bound))
}
TypeInner::Never => unreachable!("cannot generate a value of a poisoned type"),

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In fdfae8b:

This one is not unreachable. We should return an Arbitrary error here indicating that there is no value of the never type.

}
}
}
Expand Down Expand Up @@ -1257,7 +1259,7 @@ impl TreeLike for Destructor<'_> {
Self::WrongType => return Tree::Nullary,
};
match ty.as_inner() {
TypeInner::Boolean | TypeInner::UInt(..) => Tree::Nullary,
TypeInner::Boolean | TypeInner::UInt(..) | TypeInner::Never => Tree::Nullary,
TypeInner::Enum(info) => match destruct::as_enum_leaf(value, info.variants().len()) {
Some((index, leaf)) => {
Tree::Unary(Self::new(leaf, info.variants()[index].payload_type()))
Expand Down