Skip to main content Link Menu Expand (external link) Document Search Copy Copied

Error code E100

Unexpected end of file.

Example of erroneous code

fn main() -> i32
{
    var x: []i32 = [17, 50];
    if true == true
    {
        foo(
[E100] Error: Unexpected end of file
   ╭─[<source>:6:13]
   
 6 │         foo(
   ·             
   ·            ╰─ expected literal or identifier
   ·              
   ·            ╰── Expected more after this.
───╯

Error code E101

The source file contains zero bytes of data.

Example of erroneous code

[E101] Error: Unexpected end of file
   ╭─[<source>:1:1]
   
 1 │ 
   ·  
   · ╰─ expected top-level declaration
   · 
   · Note: Provided file contains zero bytes of data.
───╯

Any whitespace character is enough to suppress this error.



Alternatively a comment can be used.

// This file intentionally left blank.

Explanation

A source file being completely empty is quite uncommon, and it may indicate some sort of IO error. One particular example is writing source code to a newly created temporary file and passing the name of that file to the compiler before flushing and closing the temporary file. Because a Penne source file without declarations produces no other errors, this error code is used to warn about such a scenario.

Error code E110

Unexpected character in source file or string literal.

Example of erroneous code

fn main() -> i32
{
    var x = 1 @ 2;
}
[E110] Error: Unexpected character
   ╭─[<source>:3:16]
   
 3 │     var x = 1 @ 2;
   ·                 
   ·               ╰── expected semicolon
───╯

Explanation

Penne source files must be US-ASCII or UTF-8 encoded. In addition, ASCII control characters (U+0000 through U+001F, and U+007F) are disallowed inside string literals and must be escaped. Outside of string literals, only letters, digits, underscores and characters used in Penne operators are allowed.

Error code E140

An integer literal is larger than the maximum value for its type, or smaller than the minimum value.

Example of erroneous code

fn main() -> i32
{
    return: 2138712987321987319321987317931831928i32
}
[E140] Error: Invalid integer literal
   ╭─[<source>:3:53]
   
 3 │     return: 2138712987321987319321987317931831928i32
   ·             ────────────────────┬───────────────────  
   ·                                 ╰───────────────────── expected literal or identifier
   · 
   · Note: number too large to fit in target type
───╯

Error code E141

An integer literal has a suffix that is not a valid integer type.

Example of erroneous code

fn main()
{
    var x = 123127312i63;
}
[E141] Error: Invalid integer literal type suffix
   ╭─[<source>:3:25]
   
 3 │     var x = 123127312i63;
   ·             ──────┬─────  
   ·                   ╰─────── expected literal or identifier
───╯

Error code E142

An integer literal without type suffix is too big to parse.

Example of erroneous code

fn main()
{
    var x: i128 = 1180591620717411303424;
}
[E142] Error: Invalid untyped integer literal
   ╭─[<source>:3:41]
   
 3 │     var x: i128 = 1180591620717411303424;
   ·                   ───────────┬──────────  
   ·                              ╰──────────── expected literal or identifier
   · 
   · Note: Consider adding a type suffix like `i128`.
───╯

To fix this, add an explicit type suffix.

fn main()
{
    var x: i128 = 1180591620717411303424i128;
}

Explanation

An integer literal must have a type suffix if it fits neither an i64 nor a u64 — that is, if it is smaller than -(2^63 - 1) or larger than 2^64 - 1. This type suffix must be i128 or u128.

Error code E143

A hexadecimal or binary integer literal is too big to parse.

Example of erroneous code

fn main()
{
    var x: u128 = 0x46252a329482eaf72058e10b93e6f52;
}
[E143] Error: Invalid bit integer literal
   ╭─[<source>:3:52]
   
 3 │     var x: u128 = 0x46252a329482eaf72058e10b93e6f52;
   ·                   ────────────────┬────────────────  
   ·                                   ╰────────────────── expected literal or identifier
   · 
   · Note: Hexadecimal and binary integer literals have to fit `u64`.
───╯

Explanation

Hexadecimal and binary integer literals have to fit a u64 — that is, they cannot be larger than 2^64 - 1.

Error code E160

A string literal is not closed before the end of the line.

Example of erroneous code

fn main()
{
    var x = "Hello
    world!";
}
[E160] Error: Missing closing quote
   ╭─[<source>:3:19]
   
 3 │     var x = "Hello
   ·             ───┬──  
   ·                ╰──── expected literal or identifier
   · 
   · Note: To continue a string across multiple lines, close it and then reopen it on the next line.
───╯

Multiline strings are not supported. Newlines in strings have to be escaped.

fn main()
{
    var x = "Hello\nworld!";
}

If a string is too large to fit one line according to your formatting preferences, it can be closed and then reopened on a new line.

fn main()
{
    var x = "Hello"
    " world!";
}

This string is identical to "Hello world!".

Error code E161

A string literal contains a backslash just before the end of the line.

Example of erroneous code

fn main()
{
    var x = "Hello \
    world!";
}
[E161] Error: Unexpected trailing backslash
   ╭─[<source>:4:1]
   
 3 │     var x = "Hello \
   ·                    ─┬  
   ·                     ╰── Unexpected trailing backslash
   · 
   · Note: To continue a string across multiple lines, close it and then reopen it on the next line.
───╯

This form of line continuation is seen in other languages but is not supported in Penne. To wrap a string across multiple lines, it can be closed and then reopened on a new line.

fn main()
{
    var x = "Hello "
    "world!";
}

Error code E162

A string literal contains an invalid escape sequence or an unescaped backslash.

Example of erroneous code

fn main()
{
    var x = "C:\Program Files";
}
[E162] Error: Invalid escape sequence
   ╭─[<source>:3:18]
   
 3 │     var x = "C:\Program Files";
   ·                ─┬  
   ·                 ╰── Invalid character escape sequence
───╯

Backslashes must be escaped inside string literals.

fn main()
{
    var x = "C:\\Program Files";
}

Error code E300

The parser expected a different token based on context.

Example of erroneous code

fn main()
{
    var usize = true;
}
[E300] Error: Unexpected token
   ╭─[<source>:3:14]
   
 3 │     var usize = true;
   ·         ──┬──  
   ·           ╰──── expected variable name
───╯

Error code E301

A non-keyword identifier was followed directly by a semicolon.

Example of erroneous code

fn main()
{
    stop;
}
[E301] Error: Unexpected token
   ╭─[<source>:3:10]
   
 3 │     stop;
   ·     ──┬─  
   ·        ╰── Unexpected semicolon
   ·           
   ·       ╰──── This is not a valid statement.
───╯

Error code E302

A return value was followed by a semicolon.

Example of erroneous code

fn main() -> i32
{
    return: 10;
}
[E302] Error: Unexpected semicolon after return value
   ╭─[<source>:3:16]
   
 3 │     return: 10;
   ·             ─┬  
   ·              ╰── Unexpected semicolon
   ·                 
   ·              ╰─── This is the return value of this function.
───╯

To fix this, remove the semicolon after the return value.

fn main() -> i32
{
    return: 10
}

Explanation

Only statements are terminated by semicolons. There is no return statement. A function’s return value is separated from the rest of the function body by the special return label.

Error code E330

The return type is missing from a function with a return value.

Example of erroneous code

fn foo()
{
    return: true
}
[E330] Error: Missing return type
   ╭─[<source>:3:17]
   
 1 │ fn foo()
   ·    ─┬─  
   ·     ╰─── Function declared here.
   · 
 3 │     return: true
   ·             ──┬─  
   ·               ╰─── Value of type `bool` returned here.
───╯

To fix this, add an explicit return type.

fn foo() -> bool
{
    return: true
}

Error code E331

The return type is missing from a function with an ambiguous return value. This is usually accompanied by another type inference error, such as E581 or E582.

Example of erroneous code

fn foo()
{
    return: 500
}
[E582] Error: Ambiguous type
   ╭─[<source>:3:16]
   
 3 │     return: 500
   ·             ─┬─ 
   ·              ╰─── Failed to infer type of integer literal.
   ·                 
   ·                ╰─ Consider adding a type suffix like `i32`.
───╯
[E331] Error: Missing return type
   ╭─[<source>:3:16]
   
 1 │ fn foo()
   ·    ─┬─  
   ·     ╰─── Function declared here.
   · 
 3 │     return: 500
   ·             ─┬─  
   ·              ╰─── Value of indiscernible type returned here.
───╯

To fix both errors, add an explicit return type.

fn foo() -> i32
{
    return: 500
}

Explanation

Type inference does not cross function borders and functions with a return value need an explicit return type. In some cases the compiler cannot infer the type of the return value in order to give a useful suggestion.

Error code E333

The return type does not match the type of the return value.

Example of erroneous code

fn main() -> bool
{
    return: 50
}
[E333] Error: Conflicting return value
   ╭─[<source>:3:15]
   
 1 │ fn main() -> bool
   ·    ──┬─  
   ·      ╰─── Expected `bool` based on this declaration.
   · 
 3 │     return: 50
   ·             ─┬  
   ·              ╰── Value of type `i32` returned here.
───╯

Error code E334

A function with a return type is missing its return value.

Example of erroneous code

fn main() -> bool
{
    var result = true;
}
[E334] Error: Missing return value
   ╭─[<source>:4:2]
   
 1 │ fn main() -> bool
   ·    ──┬─  
   ·      ╰─── Expected `bool` based on this declaration.
   · 
 4 │ }
   ·   
   · ╰── No return value.
───╯

In order to return a value from a function, use the special return label followed by the value you want to return.

fn main() -> bool
{
    var result = true;
    return: result
}

Error code E335

A return value is missing after a return label.

Example of erroneous code

fn main()
{
    return:
}
[E335] Error: Missing return value
   ╭─[<source>:4:2]
   
 3 │     return:
   ·     ───┬─── 
   ·           ╰─ Expected return value...
   ·             
   ·        ╰───── ...after this `return` label.
───╯

Functions that do not return a value must use a different label instead.

fn main()
{
    end:
}

Explanation

Although return is not keyword, the label return has a special meaning. It is used in the body of a function to separate the statements from the return value. Even functions without statements must use the return label to return a value, and return must always be the last label used.

In functions that do not return a value, any identifier other than return may be used as the last label.

Error code E343

A constant declaration is missing its type.

Example of erroneous code

const X = 98;
[E343] Error: Missing type
   ╭─[<source>:1:8]
   
 1 │ const X = 98;
   ·         
   ·       ╰── Constants need an explicit type.
───╯

To fix this, add an explicit type.

const X: i32 = 98;

Error code E344

A function parameter is missing its type.

Example of erroneous code

fn foo(x) -> i32
{
    return: x * x
}
[E344] Error: Missing type
   ╭─[<source>:1:9]
   
 1 │ fn foo(x) -> i32
   ·          
   ·        ╰── Function parameters need an explicit type.
───╯

To fix this, add an explicit type.

fn foo(x: i32) -> i32
{
    return: x * x
}

Error code E346

A structure member is missing its type.

Example of erroneous code

struct Foo
{
    x,
    y,
}
[E346] Error: Missing type
   ╭─[<source>:3:6]
   
 3 │     x,
   ·       
   ·     ╰── Structure members need an explicit type.
───╯
[E346] Error: Missing type
   ╭─[<source>:4:6]
   
 4 │     y,
   ·       
   ·     ╰── Structure members need an explicit type.
───╯

To fix this, add an explicit type.

struct Foo
{
    x: i32,
    y: i32,
}

Error code E350

A compound type is deemed invalid.

Example of erroneous code

fn foo()
{
    var x: [][]i32;
}
[E350] Error: Invalid type
   ╭─[<source>:3:19]
   
 3 │     var x: [][]i32;
   ·            ───┬───  
   ·               ╰───── The type `[][]i32` is invalid.
───╯

Explanation

In addition to primitive types such as i32 or bool, compound types can be created such as [10]i32 (an array of i32 of length 10), &bool (a pointer to a bool) or &[]u8 (a pointer to an array view of u8). Not all such compounds are valid.

In particular, [10]T and []T are only valid if the type T is valid and has a size that is known at compile time. The type []T does not have a compile-time known size, hence compound types such as [10][]u8 and [][]i32 are invalid.

Error code E351

A type that cannot be returned is used as a return type.

Example of erroneous code

fn foo() -> [1000]i32;
[E351] Error: Invalid return type
   ╭─[<source>:1:22]
   
 1 │ fn foo() -> [1000]i32;
   ·             ────┬────  
   ·                 ╰────── The type `[1000]i32` is not allowed as a return value.
───╯

Explanation

Not all valid types can be used as a return type. In particular structs, arrays and array views cannot be returned.

Error code E352

A type that cannot be assigned is used to declare a variable.

Example of erroneous code

fn main()
{
    var x: void;
}
[E352] Error: Invalid variable type
   ╭─[<source>:3:10]
   
 3 │     var x: void;
   ·           
   ·         ╰── A value of type `void` cannot be assigned to a variable.
───╯

Error code E353

A type that cannot be a constant is used to declare a constant.

Example of erroneous code

const X: []i32 = [10, 20, 30];
[E353] Error: Invalid constant type
   ╭─[<source>:1:8]
   
 1 │ const X: []i32 = [10, 20, 30];
   ·         
   ·       ╰── A value of type `[:]i32` cannot be assigned to a constant.
───╯

To fix this, add an explicit size to the array type.

const X: [3]i32 = [10, 20, 30];

Error code E354

A type that cannot be used as a parameter is used to declare a parameter.

Example of erroneous code

fn foo(x: void);
[E354] Error: Invalid parameter type
   ╭─[<source>:1:9]
   
 1 │ fn foo(x: void);
   ·          
   ·        ╰── The type `void` is not allowed as a parameter.
───╯

Error code E356

A type that cannot be part of a struct is used to declare a struct member, or a type that cannot be part of a word is used to declare a word member.

Example of erroneous code

word64 Foo
{
    x: &i32,
}
[E356] Error: Invalid member type
   ╭─[<source>:3:6]
   
 3 │     x: &i32,
   ·       
   ·     ╰── The type `&i32` is not allowed as a member of a word.
───╯

Explanation

The members of word can be fixed size integers, bool or other words.

Error code E358

A type that is not part of the external ABI is used in a function marked extern.

Example of erroneous code

extern fn foo(x: u128);
[E358] Error: Invalid external type
   ╭─[<source>:1:22]
   
 1 │ extern fn foo(x: u128);
   · ───┬──         ───┬──  
   ·                  ╰──── The type `u128` is not allowed in external declarations.
   ·                       
   ·    ╰─────────────────── Declaration marked external here.
───╯

Explanation

For a detailed list of the types that allowed in extern, see the documentation about the external ABI.

Error code E360

A constant expression contains an unsupported operation.

Example of erroneous code

const A: i32 = 200;
const X: &i32 = &A;
[E360] Error: Unsupported expression in constant expression
   ╭─[<source>:2:19]
   
 2 │ const X: &i32 = &A;
   ·                 ─┬  
   ·                  ╰── This expression is not supported in a constant expression.
───╯

Explanation

The value assigned to a constant must be evaluated at compile time. In addition to literals and other constants, constant expressions may use basic arithmetic, bitwise operations and primitive casts.

Error code E361

A constant expression contains a function call.

Example of erroneous code

fn calculate_value() -> i32;
const A: i32 = calculate_value();
[E361] Error: Function in constant expression
   ╭─[<source>:2:31]
   
 2 │ const A: i32 = calculate_value();
   ·                ───────┬───────  
   ·                       ╰───────── Function calls cannot occur in a constant expression.
───╯

Explanation

Function calls are not allowed in constant expressions because their return value is not known at compile time.

Error code E380

The declared size of a word does not match the total size of its members.

Example of erroneous code

word64 Xyz
{
    x: i32,
    y: i32,
    z: i32,
}
[E380] Error: Conflicting type sizes
   ╭─[<source>:1:11]
   
 1 │ word64 Xyz
   ·        ─┬─  
   ·         ╰─── The size of this structure is 96 bits.
   ·            
   ·         ╰─── The structure is declared with `word64` and therefore has a maximum size of 64 bits.
───╯

One way to fix this is to use a larger word size and add padding.

word128 Xyz
{
    x: i32,
    y: i32,
    z: i32,
    _padding: i32,
}

Alternatively a struct can be used, which has no size restrictions.

struct Xyz
{
    x: i32,
    y: i32,
    z: i32,
}

Explanation

Words are declared with a keyword that also specifies the size of the word in bits. For example, a word32 could consist of a single i32 member, or two u16 members, or a word16, a word8 and an i8.

Error code E400

A goto statement uses a label that is not defined or not in scope.

Example of erroneous code

fn main() -> i32
{
    goto inner;
    var i = 1;
    {
        var x = 10;
        {
            inner:
            var y = 20;
            i = y;
        }
        i = x;
    }
    return: i
}
[E400] Error: Undefined label
   ╭─[<source>:3:15]
   
 3 │     goto inner;
   ·          ──┬──  
   ·            ╰──── Reference to undefined label 'inner'.
───╯

Explanation

See the documentation on label scopes and goto.

Error code E401

A function call refers to a function that has not been declared.

Example of erroneous code

fn foo()
{
    bar();
}
[E401] Error: Undefined reference
   ╭─[<source>:3:8]
   
 3 │     bar();
   ·     ─┬─  
   ·      ╰─── Reference to undefined function named 'bar'.
───╯

Functions that are resolved at link time must be predeclared.

fn bar();

fn foo()
{
    bar();
}

Error code E402

An expression refers to a variable, parameter or constant that has not been declared or that is not in scope.

Example of erroneous code

fn foo()
{
    return: x
}
[E402] Error: Undefined reference
   ╭─[<source>:3:14]
   
 3 │     return: x
   ·               
   ·             ╰── There is no variable, parameter or constant named 'x' in this scope.
───╯

Error code E405

An identifier is used as a type, but no struct or word with that name has been declared.

Example of erroneous code

fn foo() -> UndeclaredStruct;
[E405] Error: Undefined reference
   ╭─[<source>:1:29]
   
 1 │ fn foo() -> UndeclaredStruct;
   ·             ────────┬───────  
   ·                     ╰───────── Reference to undefined struct or word named 'UndeclaredStruct'.
───╯

Error code E406

A structure literal or dereference refers to a member that is not part of that structure’s declaration.

Example of erroneous code

struct Digest
{
    buffer: [1024]u8,
    len: usize,
}

fn foo()
{
    var digest = Digest {
        length: 0usize,
    };
    var buffer = &digest.buffre;
}
[E406] Error: Undefined member
    ╭─[<source>:10:15]
    
  1 │ struct Digest
    ·        ───┬──  
    ·           ╰──── The structure 'Digest' is defined here.
    · 
 10 │         length: 0usize,
    ·         ───┬──  
    ·            ╰──── No member 'length' exists for structure 'Digest'.
────╯
[E406] Error: Undefined member
    ╭─[<source>:12:32]
    
  1 │ struct Digest
    ·        ───┬──  
    ·           ╰──── The structure 'Digest' is defined here.
    · 
 12 │     var buffer = &digest.buffre;
    ·                          ───┬──  
    ·                             ╰──── No member 'buffre' exists for structure 'Digest'.
────╯

Error code E413

The definition of a constant depends on its own value.

Example of erroneous code

const X: i32 = Y + 1;
const Y: i32 = X + 1;
[E413] Error: Cyclical definition
   ╭─[<source>:2:8]
   
 2 │ const Y: i32 = X + 1;
   ·         
   ·       ╰── The definition of constant 'Y' depends on itself.
───╯

Error code E415

A structure is embedded into one of its own members.

Example of erroneous code

struct Buffer
{
    data: [1024]u8,
    metadata: Metadata,
}

struct Metadata
{
    debug_code: i32,
    message: Buffer,
}
[E415] Error: Cyclical definition
    ╭─[<source>:7:16]
    
  7 │ struct Metadata
    ·        ────┬───  
    ·            ╰───── Cannot determine size of structure 'Metadata' that contains itself.
    · 
 10 │     message: Buffer,
    ·     ───┬───  
    ·        ╰───── This member contains 'Metadata'.
────╯

Error code E420

Two labels with the same name are present in the same scope.

Example of erroneous code

fn main()
{
    next:
    next:
}
[E420] Error: Duplicate label
   ╭─[<source>:4:10]
   
 3 │     next:
   ·     ──┬──  
   ·       ╰──── Previously defined here.
 4 │     next:
   ·     ──┬──  
   ·       ╰──── The label 'next' is already defined in this scope.
───╯

Error code E421

Two functions with the same name are declared.

Example of erroneous code

fn foo(x: i32);

fn foo(x: i64);
[E421] Error: Duplicate function
   ╭─[<source>:3:7]
   
 1 │ fn foo(x: i32);
   ·    ─┬─  
   ·     ╰─── Previously defined here.
   · 
 3 │ fn foo(x: i64);
   ·    ─┬─  
   ·     ╰─── A function named 'foo' is already defined.
───╯

Error code E422

A variable is declared with the same name as another variable, parameter or constant in scope.

Example of erroneous code

fn foo(x: i32) -> i32
{
    var x = 0;
    return: x
}
[E422] Error: Duplicate variable
   ╭─[<source>:3:10]
   
 1 │ fn foo(x: i32) -> i32
   ·          
   ·        ╰── Previously defined here.
   · 
 3 │     var x = 0;
   ·           
   ·         ╰── A variable named 'x' is already defined in this scope.
───╯

Error code E423

Two constants with the same name are declared.

Example of erroneous code

const X: i32 = 200;
const Y: i32 = 250;
const X: i32 = 300;
[E423] Error: Duplicate constant
   ╭─[<source>:3:8]
   
 1 │ const X: i32 = 200;
   ·         
   ·       ╰── Previously defined here.
   · 
 3 │ const X: i32 = 300;
   ·         
   ·       ╰── The constant 'X' is already defined.
───╯

Error code E424

A parameter is declared with the same name as another parameter or constant in scope.

Example of erroneous code

fn draw_rectangle(x: i32, y: i32, w: i32, w: i32);
[E424] Error: Duplicate parameter
   ╭─[<source>:1:44]
   
 1 │ fn draw_rectangle(x: i32, y: i32, w: i32, w: i32);
   ·                                            
   ·                                   ╰────────── Previously defined here.
   ·                                             
   ·                                           ╰── A parameter named 'w' is already defined for this function.
───╯

Error code E425

Two structures with the same name are declared.

Example of erroneous code

struct Position
{
    x: i32,
    y: i32,
    z: i32,
}

word16 Position
{
    row: i8,
    col: i8,
}
[E425] Error: Duplicate structure
   ╭─[<source>:8:16]
   
 1 │ struct Position
   ·        ────┬───  
   ·            ╰───── Previously defined here.
   · 
 8 │ word16 Position
   ·        ────┬───  
   ·            ╰───── A struct or word named 'Position' is already defined.
───╯

Error code E426

A structure is declared with two members of the same name.

Example of erroneous code

struct ItemCollection
{
    items: [1024]u64,
    items: usize,
}
[E426] Error: Duplicate member
   ╭─[<source>:4:10]
   
 3 │     items: [1024]u64,
   ·     ──┬──  
   ·       ╰──── Previously defined here.
 4 │     items: usize,
   ·     ──┬──  
   ·       ╰──── A member named 'items' is already defined in this structure.
───╯

Error code E470

An import declaration could not be resolved.

Example of erroneous code

import "nice_functionality.pn";
[E470] Error: Unresolved import
   ╭─[<source>:1:7]
   
 1 │ import "nice_functionality.pn";
   · ───┬──  
   ·    ╰──── Reference to unknown file 'nice_functionality.pn'.
───╯

Explanation

The Penne compiler does not search for additional files on its own. In order to include a source file in the compilation process, add it as an extra argument after the main entry point.

$ penne build src/main.pn src/nice_functionality.pn

Error code E482

A goto statement jumps past a variable declaration to a label, but this variable is used afterwards. This results in a variable that is declared in some branches, but not others, which is unsound.

Example of erroneous code

fn main(input: i32) -> i32
{
    var result = 0;
    if input == 1
        goto next;
    var a = 20;
    var b = 5;
    result = result + a + b;
    next:
    result = result + a;
    return: result
}
[E482] Error: Variable declaration may be skipped
    ╭─[<source>:10:24]
    
  5 │         goto next;
    ·         ──┬─  
    ·           ╰─── A jump from this `goto` statement to 'next'...
  6 │     var a = 20;
    ·           
    ·         ╰── ...may skip the declaration of the variable 'a'.
    · 
  9 │     next:
    ·     ──┬──  
    ·       ╰──── After this label, the existence of 'a' is dubious.
 10 │     result = result + a;
    ·                         
    ·                       ╰── The variable is referenced here.
────╯

To fix this, move the variable declaration in front of the offending goto statement.

fn main(input: i32) -> i32
{
    var result = 0;
    var a = 20;
    if input == 1
        goto next;
    var b = 5;
    result = result + a + b;
    next:
    result = result + a;
    return: result
}

Error code E500

Type inference failed because of conflicting type assertions.

Example of erroneous code

const X: i32 = true;
[E500] Error: Conflicting types
   ╭─[<source>:1:8]
   
 1 │ const X: i32 = true;
   ·         
   ·       ╰── 'X' has type `bool`.
   ·         
   ·       ╰── Previously determined to be `i32`.
───╯

Error code E501

The array index operation is used on a value that is not an array.

Example of erroneous code

fn main()
{
    var a: i32 = 10;
    var b: i32 = a[0];
}
[E501] Error: Conflicting types
   ╭─[<source>:4:22]
   
 3 │     var a: i32 = 10;
   ·           
   ·         ╰── Type previously determined here.
 4 │     var b: i32 = a[0];
   ·                  ──┬─  
   ·                    ╰─── Cannot index into value of non-array type `i32`.
───╯

Error code E502

The array length operation is used on a value that is not an array.

Example of erroneous code

fn main()
{
    var a: i32 = 10;
    var b: usize = |a|;
}
[E502] Error: Conflicting types
   ╭─[<source>:4:23]
   
 3 │     var a: i32 = 10;
   ·           
   ·         ╰── Type previously determined here.
 4 │     var b: usize = |a|;
   ·                    ─┬─  
   ·                     ╰─── Cannot take length of value of non-array type `i32`.
───╯

Error code E503

The array index operation is used with an index of type other than usize.

Example of erroneous code

fn main()
{
    var a = [10, 20, 30];
    var i: i8 = 2;
    var b: i32 = a[i];
}
[E503] Error: Mismatched types
   ╭─[<source>:5:21]
   
 5 │     var b: i32 = a[i];
   ·                      
   ·                    ╰── Argument has type `i8`, expected `usize`.
───╯

Error code E504

An assignment occurs between two different types.

Example of erroneous code

fn main()
{
    var a: i32 = 100;
    a = false;
}
[E504] Error: Conflicting types
   ╭─[<source>:4:14]
   
 3 │     var a: i32 = 100;
   ·           
   ·         ╰── 'a' has type `i32`.
 4 │     a = false;
   ·         ──┬──  
   ·           ╰──── Cannot assign this expression of type `bool`.
───╯

Error code E505

The member access operation is used on a value that is not a structure.

Example of erroneous code

fn main()
{
    var a: i32 = 100;
    var b = a.first;
}
[E505] Error: Conflicting types
   ╭─[<source>:4:20]
   
 3 │     var a: i32 = 100;
   ·           
   ·         ╰── Type previously determined here.
 4 │     var b = a.first;
   ·             ───┬───  
   ·                ╰───── Cannot access member of non-structure type `i32`.
───╯

Error code E506

An assignment tries to change an address that is not part of a pointer.

Example of erroneous code

fn main()
{
    var a: i32 = 5;
    var b: i32 = 10;
    &b = &a;
}
[E506] Error: Conflicting types
   ╭─[<source>:5:7]
   
 4 │     var b: i32 = 10;
   ·           
   ·         ╰── 'b' has type `i32`.
 5 │     &b = &a;
   ·     ─┬  
   ·      ╰── Cannot assign to immutable address.
───╯

Error code E507

An assignment occurs between types of different levels of pointer indirection.

When assigning to pointer variables, make sure the number of address markers (&) on either side of the assignment is the same. To change the address assigned to a pointer variable, use &. To change the value that that pointer points to, omit &.

Example of erroneous code

fn main()
{
    var a: i32 = 5;
    var b: i32 = 10;
    var x: &i32 = &a;
    x = &b;
}
[E507] Error: Conflicting types
   ╭─[<source>:6:11]
   
 5 │     var x: &i32 = &a;
   ·           
   ·         ╰── 'x' has type `&i32`.
 6 │     x = &b;
   ·        ─┬  
   ·         ╰── Cannot assign this expression of type `&i32`.
   ·            
   ·     ╰─────── The assignee has type `i32`.
───╯

To change the address assigned to x, use &x:

fn main()
{
    var a: i32 = 5;
    var b: i32 = 10;
    var x: &i32 = &a;
    &x = &b;
}

To instead change the value that x points to, which is the value stored in a, omit the &:

fn main()
{
    var a: i32 = 5;
    var b: i32 = 10;
    var x: &i32 = &a;
    x = b;
}

Error code E510

A function is called with too few arguments.

Example of erroneous code

fn foo(x: i32, y: i32);

fn main()
{
    foo(100);
}
[E510] Error: Too few arguments
   ╭─[<source>:5:8]
   
 1 │ fn foo(x: i32, y: i32);
   ·    ─┬─  
   ·     ╰─── Function declared here.
   · 
 5 │     foo(100);
   ·     ─┬─  
   ·      ╰─── Too few arguments in function call.
───╯

Error code E511

A function is called with too many arguments.

Example of erroneous code

fn foo(x: i32, y: i32);

fn main()
{
    foo(100, 200, 300);
}
[E511] Error: Too many arguments
   ╭─[<source>:5:8]
   
 1 │ fn foo(x: i32, y: i32);
   ·    ─┬─  
   ·     ╰─── Function declared here.
   · 
 5 │     foo(100, 200, 300);
   ·     ─┬─  
   ·      ╰─── Too many arguments in function call.
───╯

Error code E512

A function is called with an argument of the wrong type.

Example of erroneous code

fn foo(x: i32, y: i32);

fn main()
{
    foo(100, true);
}
[E512] Error: Mismatched types
   ╭─[<source>:5:18]
   
 1 │ fn foo(x: i32, y: i32);
   ·                  
   ·                ╰── Parameter 'y' has type `i32`.
   · 
 5 │     foo(100, true);
   ·              ──┬─  
   ·                ╰─── Argument has type `bool`.
───╯

Error code E513

A function is called with an argument of type T when the corresponding parameter is type &T.

Example of erroneous code

fn read_into_buffer(buffer: &[]u8);

fn main()
{
    var databuffer: [1024]u8;
    read_into_buffer(databuffer);
}
[E513] Error: Mismatched types
   ╭─[<source>:6:32]
   
 1 │ fn read_into_buffer(buffer: &[]u8);
   ·                     ───┬──  
   ·                        ╰──── Parameter 'buffer' has type `&[:]u8`.
   · 
 6 │     read_into_buffer(databuffer);
   ·                      ────┬────  
   ·                          ╰────── Argument has type `[1024]u8`.
   ·                                 
   ·                      ╰─────────── Add `&` here to pass by reference pointer.
───╯

Error code E530

A constant or parameter of a non-pointer type is mutated, or a variable of a non-mutable type is mutated.

Example of erroneous code

fn main(x: i32)
{
    x = 10;
}
[E530] Error: Illegal mutation
   ╭─[<source>:3:6]
   
 1 │ fn main(x: i32)
   ·           
   ·         ╰── This value is not mutable.
   · 
 3 │     x = 10;
   ·       
   ·     ╰── Cannot mutate this value.
───╯

A reference pointer can be used to create mutable function parameters.

fn main(x: &i32)
{
    x = 10;
}

Error code E531

An array is used in its entirety in an assignment.

Example of erroneous code

const DATA: [10]i32 = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9];

fn main()
{
    var data = DATA;
}
[E531] Error: Cannot copy array
   ╭─[<source>:5:20]
   
 5 │     var data = DATA;
   ·                ──┬─  
   ·                  ╰─── Cannot copy this array.
───╯

Error code E532

An array view is used in its entirety in an assignment.

Example of erroneous code

fn main(data: []i32)
{
    var copy_of_data = data;
}
[E532] Error: Cannot copy array view
   ╭─[<source>:3:28]
   
 3 │     var copy_of_data = data;
   ·                        ──┬─  
   ·                          ╰─── Cannot copy this array view.
───╯
[E352] Error: Invalid variable type
   ╭─[<source>:3:21]
   
 3 │     var copy_of_data = data;
   ·         ──────┬─────  
   ·               ╰─────── A value of type `[:]i32` cannot be assigned to a variable.
───╯

Error code E533

A struct is used in its entirety in an assignment.

Example of erroneous code

struct DataBuffer
{
    buffer: [1024]u8,
}

fn main(data: DataBuffer)
{
    var copy_of_data = data;
}
[E500] Error: Conflicting types
   ╭─[<source>:8:28]
   
 6 │ fn main(data: DataBuffer)
   ·         ──┬─  
   ·           ╰─── Previously determined to be `(DataBuffer)`.
   · 
 8 │     var copy_of_data = data;
   ·                        ──┬─  
   ·                          ╰─── 'data' has type `DataBuffer`.
───╯

Error code E538

The address of a temporary value is taken

Example of erroneous code

fn main()
{
    var a: i32 = 100;
    var x: &&i32 = &&a;
}
[E538] Error: Address of temporary address
   ╭─[<source>:4:23]
   
 4 │     var x: &&i32 = &&a;
   ·                    ─┬  
   ·                     ╰─── Cannot take address of temporary address.
   ·                        
   ·                      ╰── This reference has type `i32`.
───╯

Error code E550

An operator is used that is not valid for the type of its operand(s).

Example of erroneous code

fn main()
{
    var a: u16 = 20;
    var b = -a;
}
[E550] Error: Invalid operand type
   ╭─[<source>:4:14]
   
 4 │     var b = -a;
   ·               
   ·             ╰── This has type `u16`.
   ·                
   ·             ╰─── Expected one of `i8`, `i16`, `i32`, `i64`, `i128`.
───╯

Error code E551

The types of the left and right operand of a binary operator do not match.

Example of erroneous code

fn main(data: []u8)
{
    var a: i32 = 10;
    var b: i32 = |data| + a;
}
[E551] Error: Mismatched operand types
   ╭─[<source>:4:26]
   
 4 │     var b: i32 = |data| + a;
   ·                  ───┬──    
   ·                     ╰──────── This has type `usize`.
   ·                            
   ·                         ╰──── This operator expects operands with equal types.
   ·                             
   ·                           ╰── This has type `i32`.
───╯
[E504] Error: Conflicting types
   ╭─[<source>:4:28]
   
 4 │     var b: i32 = |data| + a;
   ·                 ─────┬────  
   ·         ╰──────────────────── 'b' has type `i32`.
   ·                             
   ·                       ╰────── Cannot assign this expression of type `usize`.
───╯

If the operands are primitives types, you can use primitive casting to do the conversion.

fn main(data: []u8)
{
    var a: i32 = 10;
    var b: i32 = |data| as i32 + a;
}

Error code E552

A primitive cast is attempted between incompatible types.

Example of erroneous code

fn main()
{
    var a: i32 = 1;
    var b = a as bool;
}
[E552] Error: Invalid primitive cast
   ╭─[<source>:4:14]
   
 4 │     var b = a as bool;
   ·                 ──┬─  
   ·             ╰────────── This has type `i32`.
   ·                       
   ·                    ╰─── Cannot cast `i32` into `bool`.
   · 
   · Note: Can cast `i32` into one of `i8`, `i16`, `i64`, `i128`, `u8`, `u16`, `u32`, `u64`, `u128`, `usize`.
───╯

The only way to get a bool from another type is using conditionals.

fn main()
{
    var a: i32 = 1;
    var b: bool;
    if a == 0
    {
        b = false;
    }
    else
    {
        b = true;
    }
}

Error code E581

The compiler failed to infer the type of a variable declaration.

Example of erroneous code

fn main()
{
    var a = 1;
}
[E581] Error: Ambiguous type
   ╭─[<source>:3:8]
   
 3 │     var a = 1;
   ·     ─┬─  
   ·      ╰─── Failed to infer type of variable.
   · 
   · Note: Consider adding a type to this declaration.
───╯

If the compiler cannot infer the type of a variable declaration, an explicit type must be added.

fn main()
{
    var a: i64 = 1;
}

Error code E582

The compiler failed to infer the type of an integer literal without type suffix.

Example of erroneous code

fn foo()
{
    return: 500
}
[E582] Error: Ambiguous type
   ╭─[<source>:3:16]
   
 3 │     return: 500
   ·             ─┬─ 
   ·              ╰─── Failed to infer type of integer literal.
   ·                 
   ·                ╰─ Consider adding a type suffix like `i32`.
───╯
[E331] Error: Missing return type
   ╭─[<source>:3:16]
   
 1 │ fn foo()
   ·    ─┬─  
   ·     ╰─── Function declared here.
   · 
 3 │     return: 500
   ·             ─┬─  
   ·              ╰─── Value of indiscernible type returned here.
───╯

To fix this specific error, add an integer suffix.

    return: 500i32

However this error is usually accompanied by a different error, such as E331. Adding an explicit type elsewhere is usually enough to fix both errors.

fn foo() -> i32
{
    return: 500
}

Error code E585

The compiler refused to infer the type of a variable declaration because it is a pointer type.

Example of erroneous code

fn main()
{
    var a: i32 = 20;
    var x = &a;
}
[E585] Error: Ambiguous type
   ╭─[<source>:4:10]
   
 4 │     var x = &a;
   ·          
   ·         ╰── Failed to infer type of variable.
   ·           
   ·          ╰─ Consider adding `: &i32` here.
   · 
   · Note: Pointer variables require an explicit type.
───╯

Variables used to store pointers must have an explicit type.

fn main()
{
    var a: i32 = 20;
    var x: &i32 = &a;
}

Error code E800

A loop statement is not the final statement of the block in which it appears.

Example of erroneous code

fn main() -> i32
{
    var result;
    var i: i32 = 0;
    {
        var y = 3000 + i;
        i = i + 1;
        if i == 10
            goto exit_loop;
        loop;
        exit_loop:
        result = y;
    }
    result = result * 2;
    return: result
}
[E800] Error: Misplaced loop statement
    ╭─[<source>:10:13]
    
  5 │ ╭─▶     {
     
 10 │            loop;
    ·            ──┬─  
    ·              ╰─── This is not the final statement...
     
 13 │ ├─▶     }
    ·            
    · ╰─────────── ...of this block.
    ·     
    ·     Note: The `loop` statement must always be the final statement of a block.
────╯

A loop statement may only appear as the final statement in a block. The code needs to be restructured.

fn main() -> i32
{
    var result;
    var i: i32 = 0;
    {
        var y = 3000 + i;
        i = i + 1;
        if i == 10
        {
            result = y;
            goto exit_loop;
        }
        loop;
    }
    exit_loop:
    result = result * 2;
    return: result
}

Error code E801

A loop statement appears on its own in the body of a function.

Example of erroneous code

fn read_from_client(buffer: &[]u8, exact_size: usize);
fn handle_message_from_client(buffer: []u8, message_size: usize);

fn listen_to_client()
{
    var header_buffer: [1]u8;
    var message_buffer: [256]u8;
    read_from_client(&header_buffer, 1);
    var header: u8 = header_buffer[0];
    var message_size: usize = header as usize;
    read_from_client(&message_buffer, message_size);
    handle_message_from_client(message_buffer, message_size);
    loop;
}
[E801] Error: Misplaced loop statement
    ╭─[<source>:13:9]
    
 13 │     loop;
    ·     ──┬─  
    ·       ╰─── This is not allowed here.
    · 
    · Note: The `loop` statement must always be the final statement of a block.
────╯

To fix this, wrap the looping statements in a block.

fn read_from_client(buffer: &[]u8, exact_size: usize);
fn handle_message_from_client(buffer: []u8, message_size: usize);

fn listen_to_client()
{
    var header_buffer: [1]u8;
    var message_buffer: [256]u8;
    {
        read_from_client(&header_buffer, 1);
        var header: u8 = header_buffer[0];
        var message_size: usize = header as usize;
        read_from_client(&message_buffer, message_size);
        handle_message_from_client(message_buffer, message_size);
        loop;
    }
}

Error code E840

Missing braces around a conditional branch.

Example of erroneous code

fn main(x: i32) -> i32
{
    var result = 1;
    if x == 0
        result = 10;
    return: result
}
[E840] Error: Missing braces
   ╭─[<source>:5:15]
   
 5 │         result = 10;
   ·         ───┬──  
   ·            ╰──── Add braces around this statement.
   · 
   · Note: Braces around conditional branches can only be omitted for `goto` statements.
───╯

To fix this, add braces around the statement (or statements) that belong to that branch.

fn main(x: i32) -> i32
{
    var result = 1;
    if x == 0
    {
        result = 10;
    }
    return: result
}

Error code L1800

A loop statement appears on its own in the branch of an if statement.

Example of erroneous code

fn main() -> i32
{
    var x = 33;
    var i = 1;
    {
        x = x * i;
        i = i + 1;
        if i != 10
        {
            loop;
        }
    }
    x = x + 1;
    return: x
}
[L1800] Warning: Conditional infinite loop
    ╭─[<source>:10:17]
    
  8 │             if i != 10
    ·                ───┬───  
    ·                   ╰───── If this condition is met...
  9 │ ╭─▶         {
 10 │                loop;
    ·                ──┬─  
    ·                  ╰─── ...this loop statement will cause an infinite loop...
 11 │ ├─▶         }
    ·                
    · ╰─────────────── ...because it belongs to this block.
    ·     
    ·     Note: Perhaps use `goto` instead to jump to a `loop` elsewhere. To surpress this warning, add a label.
────╯

Explanation

The branches of an if statement must be either goto statements or block statements. Therefore the following code is not valid:

        if i != 10
            loop;

One might attempt to solve this by wrapping the loop statement in braces:

        if i != 10
        {
            loop;
        }

However this usually does not have the intended effect. Instead of looping back into whatever block contains the if statement, the branch is its own block containing only a loop statement. Because a loop statement causes execution to continue with the first statement of the block it is contained in, entering this block immediately creates an inescapable infinite loop. If that is intended, this lint can be suppresed by adding a harmless second statement to the block, such as an unused label.

        if i != 10
        {
            this_is_an_infinite_loop:
            loop;
        }

If the intention is to create a conditional loop, such as in the erroneous example above, it is usually better to invert the condition and use a goto statement.

fn main() -> i32
{
    var x = 33;
    var i = 1;
    {
        x = x * i;
        i = i + 1;
        if i == 10
            goto end;
        loop;
    }
    end:
    x = x + 1;
    return: x
}