Terbium Analyzer Warning/Error Code Index

This document refers to all warnings and errors that could be thrown when trying to compile Terbium code.

Warnings

Warnings are able to be ignored, and do not halt execution or further processing of your code. However, it is recommended to treat warnings as errors and only ignore them if you really have to.

W000

Non-type identifier names should be snake_case.

Other casings such as camelCase are discouraged:

let myVariable = 1; // Bad

Instead, try using snake_case instead:

let my_variable = 1; // Good

This allows for consistent and cleaner casing throughout the entire language and external libraries you may use.

W001

Type identifier names, such as classes or traits should be PascalCase.

When declaring a type, such as a class, try not to use snake_case or any other casing:

class my_class { /* ... */ } // Bad

Instead, use PascalCase, or "UpperCamelCase" as it is known by some:

class MyClass { /* ... */ } // Good

This allows for easier disambiguation between which variables are normal variables or functions, and which are types or classes.

W002

Identifier names should contain only ASCII characters.

Although allowed, try not to use non-ascii characters in identifier names, such as variable names:

Instead, it is best to use characters that can be typed on a normal keyboard:

This allows for you and others who use your code to easily reference variables in your code.

W003

A variable or paramter was declared but never used.

If you've declared a variable, chances are you want to use it later on in your code.

Try not to declare unused variables or parameters:

If it is intentional to declare the unused variable, for example as an artifact of destructuring, or due to it being required when passed as callback, prefix it with an underscore (_), or name it _ in its entirety:

If a variable truly does not need to be declared, then don't declare it!

W004

A variable was declared as mut, but it was never mutated

Don't declare a variable to be mutable if it isn't necessary:

Simply declare it as immutable, and make it mutable when you need to:

For reference, here are Terbium's mutability rules in a flash:

  • Reassignment requires mutability

  • Passing a variable to a parameter declared as mut requires mutability. Objects not assigned to a variable will get their mutability in the function's scope.

  • Scope reservation (e.g. let x; ... x = 1;) does not require mutability

W005

Global mutable variables are highly discouraged.

Try not to declare variables in the top level which are mut:

Instead, mutable variables should only be scoped in something such as a function (like the main function):

Global mutable variables create something called "global mutable state". These can lead to unknown or unwanted behaviors such as data races.

W006

The return values of an if-statement have unbalanced types.

An if-statement that returns multiple types creates a union type implicitly:

It's a general rule of thumb to not do this. Union types can narrow down compatibility significantly.

This error is also emitted if an implicit return was used on an if-statement that doesn't have else:

To fix this, ensure that the return types of the if-condition are equal:

Or, add semicolons:

Errors

Error analyzers cannot be disabled and halt execution or further processing of your code.

E000

Invalid syntax. Rather than being caught during analysis, this is caught during tokenization or parsing.

There are many cases of invalid syntax:

  • Unexpected token, such as an operator right after another operator. In this scenario, the parser expects an expression instead.

  • Unexpected end, such as an incomplete binary infix operator (e.g. 1 + /* EOF */).

  • Expected token. An example would be forgetting a semicolon after a variable declaration (let x = 1).

  • Unclosed or unbalanced delimiters/brackets, such as an unclosed brace: func main() { 0 In this case, simply close the delimiter. The error message should be smart enough to provide you with where and what you should insert.

  • Encountered the const mut declaration. Historically, this syntax used to be valid and instead the error would be thrown by the analyzer. This is now a syntax error - replace const mut with let mut instead.

E001

An identifier (e.g. a variable) could not be found in the current scope.

This may have been a typo, please check spelling carefully:

E002

A variable declared as const was redeclared.

Once you declare a variable as const, you may never redeclare a variable or function with the same name in its same scope:

let is more lenient, although immutable, you can redeclare variables declared with let, even in the same scope:

Let-redeclaration is usually done to persist immutability, to switch a variable's scope, or reassign something of a different type to the same identifier.

E003

An immutable variable was reassigned to.

Variable reassignment, that is assigning to a variable without using any let or const, is only valid for mutable variables:

Declare a variable as mut to fix this:

E004

The operator is not supported for the given object(s).

For example, you cannot add an int and a string together:

Terbium is strongly typed. Implicit type casting does not occur, and so explicitly cast the int above to a string:

Or even better, for this specific example, string interpolation:

E005

Received a type that was incompatible with what was expected.

The error is emitted whenever the analyzer expects an object to be of a certain type, but it is not:

An easy fix is to simply cast, if possible:

Another easy fix is to rely on type inference by removing type annotations:

E006

A type could not be inferred.

Terbium is statically typed, which means that all types must be known before runtime. Terbium runs the type-checker during analysis.

When a type is not explicitly given to the analyzer, the analyzer must infer the type without executing any code.

In some cases, the analyzer may fail to do such inference, and as a result, you are required to specify the type explicitly.

Pretend that here, we don't know the return type of mysterious_function:

The type of x is resolved as the return type of mysterious_function, but pretend that we don't know what that function actually returns. In this case, we must specify the annotation explicitly:

Last updated