Language rules¶
These rules explain why certain declarations or expressions are rejected. Use this page alongside the feature guides when an error points to a language restriction.
At a glance
- These rules explain why the compiler rejects certain declarations and expressions.
- Use this page with the feature guides when an error points to a language rule.
Reserved identifiers¶
These names cannot be reused for a variable, function, parameter, or global:
- Primitives:
int,float,double,string,bool,char,object,void,long,uint,ulong,byte. - These are reserved names, not types:
String,Int32,Int64,UInt32,UInt64,Byte,Single,Double,Boolean,Char,Object,Void. - Literals:
true,false. __print,__println, and any$-prefixed name — you cannot use these names.
Constructors and destructors¶
- Extra constructors in a type body are named
constructor; the destructor isdel. A primary constructor (class Point(x: int, y: int);) synthesizes public fields and a matchingconstructor. delmay not bepublic/internal, and neitherconstructornordelmay declare a return type.deltakes no parameters.
// good
class Box {
public constructor() {}
del() {}
}
// bad — del cannot be public; constructor cannot declare a return type
class Bad {
public del() {}
public constructor(): void {}
}
Call sites are Type(...).
The object protocol¶
overrideapplies only to the protocol methodsto_stringandhash_code. It must bepublic, take no parameters, and use the fixed return type.- Any method that overrides a protocol method must be marked
override.
// good
public override fun to_string(): string {
return "x";
}
// bad — missing override, or not public
public fun to_string(): string {
return "x";
}
Operator overloading¶
fun operator +(...)only applies to a method; the method's own parameter count (0 or 1) fixes whether it overloads the unary or binary form of that symbol.fun implicit(): T/fun explicit(): Tonly apply to a no-parameter method; its return type is the cast's target type.- Binary operators may overload by right-hand operand type; duplicate signatures and ambiguous matches are errors. Unary operators remain unique per symbol, and casts per target type. Equality overloads return
bool. See Operators § Operator overloading.
Indexers and enumerators¶
fun this[i: int]: T/fun this[i: int] = v: Tenableobj[i]andobj[i] = v.- Methods named
iterator(zero parameters, returns a class/struct) andnext(zero parameters, returnsOption<T>) enablefor..in. - A type may declare at most one method per role. A method named
get/setwithoutfun this[...]is ordinary.
Linkage modifiers are exclusive¶
public exposes a symbol to other modules (and, for functions, to the host that runs the program). A function therefore cannot be both public and extern — an extern is an imported host symbol, not an exported one.
@intrinsic declarations are the exception: @intrinsic operations use ordinary member visibility.
A public static extern intrinsic is callable from other types; an internal one requires the
same module; a default-private one is callable only by its declaring type. They bind built-in operations rather than importing host functions.
static declares class members, never top-level variables; a top-level let is file-private unless marked internal / public:
Overloading¶
- Overloads must differ in their parameters; two with identical parameter types are rejected as duplicates.
- Overloads may use default values. An exact-arity match wins over one that fills defaults, and a genuinely ambiguous call is reported at the call site.
- A class/struct's
constructormay be overloaded exactly like any other method:Point(),Point(x: int, y: int), andPoint(both: int)may all coexist, resolved by the same arity/type rules.
The entry point¶
main cannot be overloaded and must be declared as main() or main(args: string[]). args holds the command-line arguments without the executable path, the same values System.args returns.
// good shapes (pick one)
fun main(): void {}
// or:
fun main(args: string[]): void {}
// bad — wrong signature
fun main(n: int): void {}
Control flow¶
break/continueare valid only inside a loop, and any label must resolve to an enclosing loop.- Assigning to a
constbinding is rejected.
Top-level globals¶
Globals initialize in declaration order. An initializer may reference earlier globals but not later ones — there are no forward references at module scope.