//! returns: 0 //! Test trait methods returning aggregate types. //! //! Exercises: trait methods that return structs (both small and larger //! than pointer size) and optionals via v-table dispatch. record Point { x: i32, y: i32, } record Vec3 { x: i32, y: i32, z: i32, } trait Geometry { fn (&Geometry) origin() -> Point; fn (&Geometry) center() -> Vec3; fn (&Geometry) maybe() -> ?i32; } record Circle { cx: i32, cy: i32, radius: i32, } instance Geometry for Circle { fn (c: &Circle) origin() -> Point { return Point { x: c.cx, y: c.cy }; } fn (c: &Circle) center() -> Vec3 { return Vec3 { x: c.cx, y: c.cy, z: 0 }; } fn (c: &Circle) maybe() -> ?i32 { if c.radius > 0 { return c.radius; } return nil; } } fn checkCircle(g: &opaque Geometry) -> i32 { // Small struct return (Point, 8 bytes = pointer size). let p = g.origin(); assert p.x == 10; assert p.y == 20; // Larger struct return (Vec3, 12 bytes > pointer size). let v = g.center(); assert v.x == 10; assert v.y == 20; assert v.z == 0; // Optional return - Some case. let m = g.maybe(); if let val = m { assert val == 5; } else { return 7; } return 0; } fn checkEmptyCircle(g: &opaque Geometry) -> i32 { // Optional return - None case. let m = g.maybe(); if let _ = m { return 8; } return 0; } @default fn main() -> i32 { let c = Circle { cx: 10, cy: 20, radius: 5 }; let result = checkCircle(&c); if result <> 0 { return result; } let c2 = Circle { cx: 0, cy: 0, radius: 0 }; return checkEmptyCircle(&c2); }