feat: allow importing off validators in validators/tests/*

This commit is contained in:
rvcas 2023-12-11 18:27:08 -05:00
parent b25e82ed36
commit 07122aaa88
No known key found for this signature in database
GPG Key ID: C09B64E263F7D68C
4 changed files with 43 additions and 75 deletions

View File

@ -66,25 +66,6 @@ fn validator_illegal_return_type() {
)) ))
} }
#[test]
fn validator_useless_pub() {
let source_code = r#"
type Datum {
thing: Int
}
validator {
pub fn foo(_d: Datum, _r, _c) {
True
}
}
"#;
let (warnings, _) = check_validator(parse(source_code)).unwrap();
assert!(matches!(warnings[0], Warning::PubInValidatorModule { .. }))
}
#[test] #[test]
fn validator_illegal_arity() { fn validator_illegal_arity() {
let source_code = r#" let source_code = r#"

View File

@ -33,6 +33,7 @@ pub struct Environment<'a> {
/// Accessors defined in the current module /// Accessors defined in the current module
pub accessors: HashMap<String, AccessorsMap>, pub accessors: HashMap<String, AccessorsMap>,
pub current_module: &'a String, pub current_module: &'a String,
pub current_kind: &'a ModuleKind,
/// entity_usages is a stack of scopes. When an entity is created it is /// entity_usages is a stack of scopes. When an entity is created it is
/// added to the top scope. When an entity is used we crawl down the scope /// added to the top scope. When an entity is used we crawl down the scope
/// stack for an entity with that name and mark it as used. /// stack for an entity with that name and mark it as used.
@ -244,12 +245,44 @@ impl<'a> Environment<'a> {
can_error, can_error,
}) })
} }
Definition::Validator(Validator {
doc,
end_position,
fun,
other_fun,
location,
params,
}) => {
let Definition::Fn(fun) =
self.generalise_definition(Definition::Fn(fun), module_name)
else {
unreachable!()
};
let other_fun = other_fun.map(|other_fun| {
let Definition::Fn(other_fun) =
self.generalise_definition(Definition::Fn(other_fun), module_name)
else {
unreachable!()
};
other_fun
});
Definition::Validator(Validator {
doc,
end_position,
fun,
other_fun,
location,
params,
})
}
definition @ (Definition::TypeAlias { .. } definition @ (Definition::TypeAlias { .. }
| Definition::DataType { .. } | Definition::DataType { .. }
| Definition::Use { .. } | Definition::Use { .. }
| Definition::Test { .. } | Definition::Test { .. }
| Definition::Validator { .. }
| Definition::ModuleConstant { .. }) => definition, | Definition::ModuleConstant { .. }) => definition,
} }
} }
@ -600,6 +633,7 @@ impl<'a> Environment<'a> {
pub fn new( pub fn new(
id_gen: IdGenerator, id_gen: IdGenerator,
current_module: &'a String, current_module: &'a String,
current_kind: &'a ModuleKind,
importable_modules: &'a HashMap<String, TypeInfo>, importable_modules: &'a HashMap<String, TypeInfo>,
warnings: &'a mut Vec<Warning>, warnings: &'a mut Vec<Warning>,
) -> Self { ) -> Self {
@ -622,6 +656,7 @@ impl<'a> Environment<'a> {
importable_modules, importable_modules,
imported_types: HashSet::new(), imported_types: HashSet::new(),
current_module, current_module,
current_kind,
warnings, warnings,
entity_usages: vec![HashMap::new()], entity_usages: vec![HashMap::new()],
} }
@ -677,7 +712,9 @@ impl<'a> Environment<'a> {
imported_modules: self.imported_modules.keys().cloned().collect(), imported_modules: self.imported_modules.keys().cloned().collect(),
})?; })?;
if module_info.kind.is_validator() { if module_info.kind.is_validator()
&& (self.current_kind.is_lib() || !self.current_module.starts_with("tests"))
{
return Err(Error::ValidatorImported { return Err(Error::ValidatorImported {
location: *location, location: *location,
name, name,
@ -1086,7 +1123,7 @@ impl<'a> Environment<'a> {
&fun.location, &fun.location,
)?; )?;
if !fun.public && kind.is_lib() { if !fun.public {
self.init_usage(fun.name.clone(), EntityKind::PrivateFunction, fun.location); self.init_usage(fun.name.clone(), EntityKind::PrivateFunction, fun.location);
} }
} }

View File

@ -1363,13 +1363,6 @@ pub enum Warning {
location: Span, location: Span,
}, },
#[error("I found a public definition in a validator module.\nDefinitions in validator modules do not need to be public.\n")]
#[diagnostic(code("redundant::pub"))]
PubInValidatorModule {
#[label]
location: Span,
},
#[error("I found a when expression with a single clause.")] #[error("I found a when expression with a single clause.")]
#[diagnostic( #[diagnostic(
code("single_when_clause"), code("single_when_clause"),
@ -1607,7 +1600,6 @@ impl ExtraData for Warning {
Warning::AllFieldsRecordUpdate { .. } Warning::AllFieldsRecordUpdate { .. }
| Warning::ImplicitlyDiscardedResult { .. } | Warning::ImplicitlyDiscardedResult { .. }
| Warning::NoFieldsRecordUpdate { .. } | Warning::NoFieldsRecordUpdate { .. }
| Warning::PubInValidatorModule { .. }
| Warning::SingleConstructorExpect { .. } | Warning::SingleConstructorExpect { .. }
| Warning::SingleWhenClause { .. } | Warning::SingleWhenClause { .. }
| Warning::Todo { .. } | Warning::Todo { .. }

View File

@ -3,7 +3,7 @@ use std::collections::HashMap;
use crate::{ use crate::{
ast::{ ast::{
ArgName, DataType, Definition, Function, Layer, ModuleConstant, ModuleKind, ArgName, DataType, Definition, Function, Layer, ModuleConstant, ModuleKind,
RecordConstructor, RecordConstructorArg, Span, Tracing, TypeAlias, TypedDefinition, RecordConstructor, RecordConstructorArg, Tracing, TypeAlias, TypedDefinition,
TypedFunction, TypedModule, UntypedDefinition, UntypedModule, Use, Validator, TypedFunction, TypedModule, UntypedDefinition, UntypedModule, Use, Validator,
}, },
builtins, builtins,
@ -19,8 +19,6 @@ use super::{
TypeInfo, ValueConstructor, ValueConstructorVariant, TypeInfo, ValueConstructor, ValueConstructorVariant,
}; };
const PUB_OFFSET: usize = 3;
impl UntypedModule { impl UntypedModule {
pub fn infer( pub fn infer(
mut self, mut self,
@ -33,7 +31,7 @@ impl UntypedModule {
) -> Result<TypedModule, Error> { ) -> Result<TypedModule, Error> {
let name = self.name.clone(); let name = self.name.clone();
let docs = std::mem::take(&mut self.docs); let docs = std::mem::take(&mut self.docs);
let mut environment = Environment::new(id_gen.clone(), &name, modules, warnings); let mut environment = Environment::new(id_gen.clone(), &name, &kind, modules, warnings);
let mut type_names = HashMap::with_capacity(self.definitions.len()); let mut type_names = HashMap::with_capacity(self.definitions.len());
let mut value_names = HashMap::with_capacity(self.definitions.len()); let mut value_names = HashMap::with_capacity(self.definitions.len());
@ -82,7 +80,7 @@ impl UntypedModule {
for def in consts.into_iter().chain(not_consts) { for def in consts.into_iter().chain(not_consts) {
let definition = let definition =
infer_definition(def, &name, &mut hydrators, &mut environment, tracing, kind)?; infer_definition(def, &name, &mut hydrators, &mut environment, tracing)?;
definitions.push(definition); definitions.push(definition);
} }
@ -148,7 +146,6 @@ fn infer_definition(
hydrators: &mut HashMap<String, Hydrator>, hydrators: &mut HashMap<String, Hydrator>,
environment: &mut Environment<'_>, environment: &mut Environment<'_>,
tracing: Tracing, tracing: Tracing,
kind: ModuleKind,
) -> Result<TypedDefinition, Error> { ) -> Result<TypedDefinition, Error> {
match def { match def {
Definition::Fn(Function { Definition::Fn(Function {
@ -163,15 +160,6 @@ fn infer_definition(
can_error, can_error,
.. ..
}) => { }) => {
if public && kind.is_validator() {
environment.warnings.push(Warning::PubInValidatorModule {
location: Span {
start: location.start,
end: location.start + PUB_OFFSET,
},
})
}
let preregistered_fn = environment let preregistered_fn = environment
.get_variable(&name) .get_variable(&name)
.expect("Could not find preregistered type for function"); .expect("Could not find preregistered type for function");
@ -306,7 +294,6 @@ fn infer_definition(
hydrators, hydrators,
environment, environment,
tracing, tracing,
kind,
)? )?
else { else {
unreachable!( unreachable!(
@ -357,7 +344,6 @@ fn infer_definition(
hydrators, hydrators,
environment, environment,
tracing, tracing,
kind,
)? )?
else { else {
unreachable!( unreachable!(
@ -419,7 +405,6 @@ fn infer_definition(
hydrators, hydrators,
environment, environment,
tracing, tracing,
kind,
)? { )? {
environment.unify(f.return_type.clone(), builtins::bool(), f.location, false)?; environment.unify(f.return_type.clone(), builtins::bool(), f.location, false)?;
@ -438,15 +423,6 @@ fn infer_definition(
annotation, annotation,
.. ..
}) => { }) => {
if public && kind.is_validator() {
environment.warnings.push(Warning::PubInValidatorModule {
location: Span {
start: location.start,
end: location.start + PUB_OFFSET,
},
})
}
let tipo = environment let tipo = environment
.get_type_constructor(&None, &alias, location) .get_type_constructor(&None, &alias, location)
.expect("Could not find existing type for type alias") .expect("Could not find existing type for type alias")
@ -474,15 +450,6 @@ fn infer_definition(
constructors: untyped_constructors, constructors: untyped_constructors,
.. ..
}) => { }) => {
if public && kind.is_validator() {
environment.warnings.push(Warning::PubInValidatorModule {
location: Span {
start: location.start,
end: location.start + PUB_OFFSET,
},
})
}
let constructors = untyped_constructors let constructors = untyped_constructors
.into_iter() .into_iter()
.map( .map(
@ -617,15 +584,6 @@ fn infer_definition(
value, value,
.. ..
}) => { }) => {
if public && kind.is_validator() {
environment.warnings.push(Warning::PubInValidatorModule {
location: Span {
start: location.start,
end: location.start + PUB_OFFSET,
},
})
}
let typed_expr = let typed_expr =
ExprTyper::new(environment, tracing).infer_const(&annotation, *value)?; ExprTyper::new(environment, tracing).infer_const(&annotation, *value)?;