Methods

Methods are functions defined inside a struct block that can be called on instances of that struct.

struct_def = [ directives ] [ "pub" ] "struct" IDENT "{" [ field_list ] [ method_list ] "}" ;
field_list = field_def { "," field_def } [ "," ] ;
field_def = [ "pub" ] IDENT ":" type ;
method_list = method_def { method_def } ;
method_def = [ directives ] [ "pub" ] "fn" IDENT "(" [ method_params ] ")" [ "->" type ] block ;
method_params = method_param { "," method_param } [ "," ] ;
method_param = "self" | ( IDENT ":" type ) ;

Method Definition

A method is a function defined inside a struct block that takes self as its first parameter.

The self parameter represents the receiver value and has the type of the enclosing struct.

struct Point {
    x: i32,
    y: i32,

    fn get_x(self) -> i32 {
        self.x
    }
}

fn main() -> i32 {
    let p = Point { x: 42, y: 10 };
    p.get_x()  // Returns 42
}

Method Calls

Methods are called using dot notation: receiver.method(args).

A method call receiver.method(args) is desugared to a function call with the receiver as the first argument.

Methods MAY have additional parameters after self.

struct Point {
    x: i32,
    y: i32,

    fn add(self, dx: i32, dy: i32) -> Point {
        Point { x: self.x + dx, y: self.y + dy }
    }
}

fn main() -> i32 {
    let p = Point { x: 10, y: 20 };
    let p2 = p.add(32, 0);
    p2.x  // Returns 42
}

Method Chaining

When a method returns the same struct type, method calls MAY be chained.

struct Counter {
    value: i32,

    fn inc(self) -> Counter {
        Counter { value: self.value + 1 }
    }
}

fn main() -> i32 {
    let c = Counter { value: 39 };
    c.inc().inc().inc().value  // Returns 42
}

Associated Functions

A function in a struct block that does not take self as its first parameter is an associated function.

Associated functions are called using path notation: Type::function(args).

struct Point {
    x: i32,
    y: i32,

    fn origin() -> Point {
        Point { x: 0, y: 0 }
    }
}

fn main() -> i32 {
    let p = Point::origin();
    p.x  // Returns 0
}

Multiple Methods

A struct may have multiple methods defined in its block.

Method names MUST be unique within a struct definition.

struct Point {
    x: i32,
    y: i32,

    fn get_x(self) -> i32 { self.x }

    fn get_y(self) -> i32 { self.y }
}

fn main() -> i32 {
    let p = Point { x: 42, y: 10 };
    p.get_x()  // Returns 42
}

Error Conditions

Calling a method on a non-struct type is a compile-time error.

Calling an undefined method is a compile-time error.

Calling an associated function with method call syntax (receiver.function()) is a compile-time error.

Calling a method with associated function syntax (Type::method()) is a compile-time error.

Method Visibility

(ADR-0073.) A method definition MAY be prefixed with the pub keyword. A method marked pub is callable from any module that can name the enclosing struct or enum. A method without pub is callable only from within the same module as the type definition.

The visibility check applies to both instance method calls (receiver.method(...)) and associated function calls (Type::function(...)). Interface methods (declared in interface blocks) are not subject to this check; an interface's methods are part of the interface's public contract wherever the interface itself is in scope.

pub struct Counter {
    value: i32,

    pub fn new() -> Counter { Counter { value: 0 } }     // public
    pub fn get(self) -> i32 { self.value }               // public
    fn validate(self) -> bool { self.value >= 0 }        // module-private
}

Self Inside Methods and Associated Functions (ADR-0076)

Inside any method or associated function defined within a struct or enum body, the type symbol Self denotes the enclosing struct or enum type. Self is in scope for the method's parameter types, return type, local-binding type annotations, struct/enum literals, enum variant paths, and pattern paths.

Self substitutes uniformly at every depth of a type expression: inside Ref(Self), MutRef(Self), Ptr(Self), MutPtr(Self), Vec(Self), Option(Self), Result(Self, E), [Self; N], (Self, T), and any user-defined parameterised type. There is no position in a type expression where Self is meaningful but does not resolve.

Associated functions — methods declared without a self parameter — also have Self in scope. Their return type and parameter types MAY mention Self, and so MAY their bodies via expressions such as Self { ... } (struct literal), Self::Variant(...) (enum variant constructor), and Self::associated_fn(...) (associated call).

struct Pair {
    a: i32,
    b: i32,

    fn new(a: i32, b: i32) -> Self {                    // 6.4:29
        Self { a: a, b: b }                             // 6.4:29
    }

    fn combine(self: Ref(Self), other: Ref(Self)) -> Self {       // 6.4:28 (Ref(Self))
        Self { a: self.a + other.a, b: self.b + other.b }
    }
}

Using Self in a position where no enclosing struct, enum, derive, or interface body is in scope (for example, in a free top-level function) is a compile-time error.