i-slint-compiler 1.18.0

Internal Slint Compiler Library
Documentation
// Copyright © 2026 Klarälvdalens Datakonsult AB, a KDAB Group company <info@kdab.com>, author Nathan Collins <nathan.collins@kdab.com>
// SPDX-License-Identifier: GPL-3.0-only OR LicenseRef-Slint-Royalty-free-2.0 OR LicenseRef-Slint-Software-3.0

// Delegation via `implement I <=> child`: the child is duck-typed (needs no `implement` of its own)
// but must carry every member of `I`, and the forwarded members must not clash on the parent.

interface ValidInterface {
    in-out property <int> value;
    callback speak();
    public pure function reset();
}

component ComponentA { }

// The child target must exist.
export component MissingChild {
    implement ValidInterface <=> base;
//                               >  <error{'base' does not exist}
}

// The child must carry every member of the interface.
export component ChildMissingMembers {
    implement ValidInterface <=> base;
//                               >  <error{Cannot implement 'ValidInterface' based on 'base'.↵- missing 'pure public function reset() { }'↵- missing 'callback speak();'↵- missing 'in-out property <int> value;'}
    base := ComponentA { }
}

// Member present but with the wrong visibility / type / callback signature / purity / arguments.
component IncorrectVisibility {
    out property <int> value;
//  > <note{'IncorrectVisibility' declares 'value' here, 'ValidInterface' expects 'in-out property <int> value;'}
    callback speak();
    public pure function reset() {}
}

export component ChildWrongVisibility {
    implement ValidInterface <=> impl;
//                               >  <error{Cannot implement 'ValidInterface' based on 'impl'.↵- 'impl.value' must be 'in-out' (found 'out')}
    impl := IncorrectVisibility { }
}

component IncorrectType {
    in-out property <float> value;
//                   >   <note{'IncorrectType' declares 'value' here, 'ValidInterface' expects 'in-out property <int> value;'}
    callback speak();
    public pure function reset() {}
}

export component ChildWrongType {
    implement ValidInterface <=> impl;
//                               >  <error{Cannot implement 'ValidInterface' based on 'impl'.↵- 'impl.value' must be a 'int' property (found a 'float' property)}
    impl := IncorrectType { }
}

component IncorrectCallback {
    in-out property <int> value;
    callback speak() -> string;
//                      >    <note{'IncorrectCallback' declares 'speak' here, 'ValidInterface' expects 'callback speak();'}
    public pure function reset() {}
}

export component ChildWrongCallback {
    implement ValidInterface <=> impl;
//                               >  <error{Cannot implement 'ValidInterface' based on 'impl'.↵- 'impl.speak' must be 'callback speak();' (found 'callback speak() -> string;')}
    impl := IncorrectCallback { }
}

interface FunctionInterface {
    public pure function foo(i: int, s: string) -> bool;
}

component ChildWithDifferentParameterNames {
    // The function is correct even though the parameter names differ
    public pure function foo(int: int, string: string) -> bool {
        return false;
    }
}

export component ValidChildFunctionInterface {
    implement FunctionInterface <=> base;
    base := ChildWithDifferentParameterNames { }
}

interface ImpureFunctionInterface {
    public function bar(i: int, s: string) -> bool;
}

component IncorrectPurity {
    public function foo(i: int, s: string) -> bool {
//                  > <note{'IncorrectPurity' declares 'foo' here, 'FunctionInterface' expects 'pure public function foo(int, string) -> bool { }'}
        return false;
    }

    // Implementation is pure, interface is not - this should not raise an error
    public pure function bar(i: int, s: string) -> bool {
        return false;
    }
}

export component ChildWrongPurity {
    implement FunctionInterface <=> base;
//                                  >  <error{Cannot implement 'FunctionInterface' based on 'base'.↵- 'base.foo' must be 'pure'}
    implement ImpureFunctionInterface <=> base;

    base := IncorrectPurity { }
}

component IncorrectArguments {
    pure public function foo(i: int, s: int) -> bool {
//                                      > <note{'IncorrectArguments' declares 'foo' here, 'FunctionInterface' expects 'pure public function foo(int, string) -> bool { }'}
        return false;
    }
}

export component ChildWrongArguments {
    implement FunctionInterface <=> base;
//                                  >  <error{Cannot implement 'FunctionInterface' based on 'base'.↵- 'base.foo' must be 'pure public function foo(int, string) -> bool { }' (found 'pure public function foo(int, int) -> bool { }')}
    base := IncorrectArguments { }
}

// Each member of the child declared as the wrong kind.
component CrossKindImpl {
    callback value();
//           >   <note{'CrossKindImpl' declares 'value' here, 'ValidInterface' expects 'in-out property <int> value;'}
    in-out property <int> speak;
//                        >   <note{'CrossKindImpl' declares 'speak' here, 'ValidInterface' expects 'callback speak();'}
    in-out property <int> reset;
//                        >   <note{'CrossKindImpl' declares 'reset' here, 'ValidInterface' expects 'pure public function reset() { }'}
}

export component ChildCrossKind {
    implement ValidInterface <=> impl;
//                               >  <error{Cannot implement 'ValidInterface' based on 'impl'.↵- 'impl.reset' must be 'pure public function reset() { }' (found a 'int' property)↵- 'impl.speak' must be 'callback speak();' (found a 'int' property)↵- 'impl.value' must be 'in-out property <int> value;' (found 'callback value();')}
    impl := CrossKindImpl { }
}

component ValidBase {
    in-out property <int> value;
    callback speak();
    public pure function reset() {}
}

// A child element may implicitly implement an interface
export component ChildImplicitlyImplements {
    implement ValidInterface <=> base;
    base := ValidBase { }
}

// A forwarded member must not clash with a member already declared on the parent.
export component OverridesDeclaration {
    implement ValidInterface <=> base;
//            >             <note{'ValidInterface' declares 'reset' as 'pure public function reset() { }'}
//            >             <^note{'ValidInterface' declares 'speak' as 'callback speak();'}
//            >             <^^note{'ValidInterface' declares 'value' as 'in-out property <int> value;'}
    base := ValidBase { }

    in-out property <int> value;
//                        >   <error{Cannot override 'value' from 'ValidInterface'}
    callback speak();
//           >   <error{Cannot override 'speak' from 'ValidInterface'}
    public pure function reset() {}
//                       >   <error{Cannot override 'reset' from 'ValidInterface'}
}

// A forwarded member must not clash with a member inherited by the parent from its own base.
component BaseWithConflicts {
    in-out property <int> value;
//                        >   <note{'BaseWithConflicts' declares 'value' here, 'ValidInterface' expects 'in-out property <int> value;'}
    callback speak();
//           >   <note{'BaseWithConflicts' declares 'speak' here, 'ValidInterface' expects 'callback speak();'}
    public pure function reset() {}
//                       >   <note{'BaseWithConflicts' declares 'reset' here, 'ValidInterface' expects 'pure public function reset() { }'}
    @children
}

export component ConflictsWithBase inherits BaseWithConflicts {
    implement ValidInterface <=> base;
//            >             <error{Cannot implement 'ValidInterface' based on 'base'.↵- 'reset' conflicts with an existing function in 'BaseWithConflicts'↵- 'speak' conflicts with an existing callback in 'BaseWithConflicts'↵- 'value' conflicts with an existing property in 'BaseWithConflicts'}
    base := ValidBase { }
}

interface Viewport {
    in-out property <float> viewport-x;
    in-out property <float> viewport-y;
}

// The Viewport interface properties conflict with the properties on the built-in Flickable component
export component ConflictsWithBuiltIn {
    implement Viewport <=> flickable;
//                         >       <error{Cannot implement 'Viewport' based on 'flickable'.↵- 'flickable.viewport-x' must be a 'float' property (found a 'length' property)↵- 'flickable.viewport-y' must be a 'float' property (found a 'length' property)}

    flickable := Flickable { }
}

// Verify that we don't get the normalized child id in the diagnostic messages.
export component ChildWithProperties {

    implement ValidInterface <=> child_with_conflicts;
//                               >                  <error{Cannot implement 'ValidInterface' based on 'child_with_conflicts'.↵- 'child_with_conflicts.reset' must be 'pure public function reset() { }' (found 'callback reset();')↵- 'child_with_conflicts.speak' must be 'callback speak();' (found 'public function speak() { }')↵- 'child_with_conflicts.value' must be a 'int' property (found a 'float' property)}

    child_with_conflicts := Rectangle {
        in-out property <float> value;
//                       >   <note{'child_with_conflicts' declares 'value' here, 'ValidInterface' expects 'in-out property <int> value;'}
        public function speak() {}
//                      >   <note{'child_with_conflicts' declares 'speak' here, 'ValidInterface' expects 'callback speak();'}
        callback reset();
//               >   <note{'child_with_conflicts' declares 'reset' here, 'ValidInterface' expects 'pure public function reset() { }'}
    }
}