feat: return err if data type contains functions
Due to how PlutusData works it doesn't make sense to allow user defined types to contain functions. ``` type Foo { bar: fn(Int) -> Int } ``` The above definition will now return an error.
This commit is contained in:
parent
95c9be5c52
commit
b69c1f66d7
|
@ -73,6 +73,10 @@ impl Type {
|
|||
matches!(self, Self::Var { tipo } if tipo.borrow().is_unbound())
|
||||
}
|
||||
|
||||
pub fn is_function(&self) -> bool {
|
||||
matches!(self, Self::Fn { .. })
|
||||
}
|
||||
|
||||
pub fn return_type(&self) -> Option<Arc<Self>> {
|
||||
match self {
|
||||
Self::Fn { ret, .. } => Some(ret.clone()),
|
||||
|
|
|
@ -47,6 +47,9 @@ pub enum Error {
|
|||
name: String,
|
||||
},
|
||||
|
||||
#[error("I found a data type that has a function type in it. This is not allowed.")]
|
||||
FunctionTypeInData { location: Span },
|
||||
|
||||
#[error("I saw a {} fields in a context where there should be {}.\n", given.purple(), expected.purple())]
|
||||
IncorrectFieldsArity {
|
||||
location: Span,
|
||||
|
@ -365,6 +368,7 @@ impl Diagnostic for Error {
|
|||
Self::DuplicateField { .. } => Some(Box::new("duplicate_field")),
|
||||
Self::DuplicateName { .. } => Some(Box::new("duplicate_name")),
|
||||
Self::DuplicateTypeName { .. } => Some(Box::new("duplicate_type_name")),
|
||||
Self::FunctionTypeInData { .. } => Some(Box::new("function_type_in_data")),
|
||||
Self::IncorrectFieldsArity { .. } => Some(Box::new("incorrect_fields_arity")),
|
||||
Self::IncorrectFunctionCallArity { .. } => Some(Box::new("incorrect_fn_arity")),
|
||||
Self::IncorrectPatternArity { .. } => Some(Box::new("incorrect_pattern_arity")),
|
||||
|
@ -478,6 +482,8 @@ impl Diagnostic for Error {
|
|||
, cannot = "cannot".red()
|
||||
})),
|
||||
|
||||
Self::FunctionTypeInData { .. } => Some(Box::new("Data types can't have functions in them due to how Plutus Data works.")),
|
||||
|
||||
Self::IncorrectFieldsArity { .. } => None,
|
||||
|
||||
Self::IncorrectFunctionCallArity { expected, .. } => Some(Box::new(formatdoc! {
|
||||
|
@ -1134,6 +1140,9 @@ impl Diagnostic for Error {
|
|||
Self::DuplicateTypeName { location, .. } => Some(Box::new(
|
||||
vec![LabeledSpan::new_with_span(None, *location)].into_iter(),
|
||||
)),
|
||||
Self::FunctionTypeInData { location } => Some(Box::new(
|
||||
vec![LabeledSpan::new_with_span(None, *location)].into_iter(),
|
||||
)),
|
||||
Self::IncorrectFieldsArity { location, .. } => Some(Box::new(
|
||||
vec![LabeledSpan::new_with_span(None, *location)].into_iter(),
|
||||
)),
|
||||
|
@ -1262,6 +1271,7 @@ impl Diagnostic for Error {
|
|||
Self::DuplicateField { .. } => None,
|
||||
Self::DuplicateName { .. } => None,
|
||||
Self::DuplicateTypeName { .. } => None,
|
||||
Self::FunctionTypeInData { .. } => None,
|
||||
Self::IncorrectFieldsArity { .. } => Some(Box::new(
|
||||
"https://aiken-lang.org/language-tour/custom-types",
|
||||
)),
|
||||
|
|
|
@ -281,10 +281,10 @@ fn infer_definition(
|
|||
opaque,
|
||||
name,
|
||||
parameters,
|
||||
constructors,
|
||||
constructors: untyped_constructors,
|
||||
..
|
||||
}) => {
|
||||
let constructors = constructors
|
||||
let constructors = untyped_constructors
|
||||
.into_iter()
|
||||
.map(
|
||||
|RecordConstructor {
|
||||
|
@ -346,7 +346,7 @@ fn infer_definition(
|
|||
.parameters
|
||||
.clone();
|
||||
|
||||
Ok(Definition::DataType(DataType {
|
||||
let typed_data = DataType {
|
||||
doc,
|
||||
location,
|
||||
public,
|
||||
|
@ -355,7 +355,19 @@ fn infer_definition(
|
|||
parameters,
|
||||
constructors,
|
||||
typed_parameters,
|
||||
}))
|
||||
};
|
||||
|
||||
for constr in &typed_data.constructors {
|
||||
for RecordConstructorArg { tipo, location, .. } in &constr.arguments {
|
||||
if tipo.is_function() {
|
||||
return Err(Error::FunctionTypeInData {
|
||||
location: *location,
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Ok(Definition::DataType(typed_data))
|
||||
}
|
||||
|
||||
Definition::Use(Use {
|
||||
|
|
Loading…
Reference in New Issue