Better errors when using unknown data-type constructor.

## Before

  ```
    × Checking
    ╰─▶ Unknown variable

            Finite

      ╭─[../stdlib/validators/tmp.ak:10:1]
   10 │   let now = when context.transaction.validity_range.lower_bound.bound_type is {
   11 │     Finite { t } -> t
      ·     ────────────
   12 │     NegativeInfinity -> 0
      ╰────
  ```

  ## After

  ```
    × Type-checking
    ╰─▶ Unknown data-type constructor 'Finite'

      ╭─[../stdlib/validators/tmp.ak:10:1]
   10 │   let now = when context.transaction.validity_range.lower_bound.bound_type is {
   11 │     Finite { t } -> t
      ·     ────────────
   12 │     NegativeInfinity -> 0
      ╰────
    help: Did you forget to import it?

          Data-type constructors are not automatically imported, even if their type is
          imported. So, if a module `aiken/pet` defines the following type:

           ┍━ aiken/pet.ak ━━━━━━━━
           │ pub type Pet {
           │   Cat
           │   Dog
           │ }

          You must import its constructors explicitly to use them, or prefix them
          with the module's name.

           ┍━ foo.ak ━━━━━━━━
           │ use aiken/pet.{Pet, Dog}
           │
           │ fn foo(pet : Pet) {
           │   when pet is {
           │     pet.Cat -> // ...
           │     Dog -> // ...
           │   }
           │ }
  ```
This commit is contained in:
KtorZ 2022-12-22 19:31:43 +01:00
parent 2aa4429231
commit 0682781460
No known key found for this signature in database
GPG Key ID: 33173CB6F77F4277
3 changed files with 49 additions and 5 deletions

View File

@ -315,10 +315,20 @@ impl<'a> Environment<'a> {
location: Span,
) -> Result<&ValueConstructor, Error> {
match module {
None => self.scope.get(name).ok_or_else(|| Error::UnknownVariable {
None => self.scope.get(name).ok_or_else(|| {
if name.chars().into_iter().next().unwrap().is_uppercase() {
Error::UnknownTypeConstructor {
name: name.to_string(),
variables: self.local_value_names(),
location,
}
} else {
Error::UnknownVariable {
name: name.to_string(),
variables: self.local_value_names(),
location,
}
}
}),
Some(m) => {

View File

@ -225,6 +225,40 @@ pub enum Error {
variables: Vec<String>,
},
#[error("Unknown data-type constructor '{name}'\n")]
#[diagnostic(help(
r#"Did you forget to import it?
Data-type constructors are not automatically imported, even if their type is
imported. So, if a module `aiken/pet` defines the following type:
aiken/pet.ak
pub type Pet {{
Cat
Dog
}}
You must import its constructors explicitly to use them, or prefix them
with the module's name.
foo.ak
use aiken/pet.{{Pet, Dog}}
fn foo(pet : Pet) {{
when pet is {{
pet.Cat -> // ...
Dog -> // ...
}}
}}
"#
))]
UnknownTypeConstructor {
#[label]
location: Span,
name: String,
variables: Vec<String>,
},
#[error("Unnecessary spread operator\n")]
UnnecessarySpreadOperator {
#[label]

View File

@ -74,7 +74,7 @@ pub enum Error {
error: Box<ParseError>,
},
#[error("Checking")]
#[error("Type-checking")]
Type {
path: PathBuf,
src: String,