Skip to content

Ownership of arguments and return types isn't checked correctly for methods implemented through traits #948

@yorickpeterse

Description

@yorickpeterse

Please describe the bug

This is similar to #718 and came up when looking into that issue:

When we check if the implementation of a method matches the definition in the corresponding trait, we perform the comparison of implementation -> requirement. This however allows changing of ownership in ways that isn't sound, such as when a requirement defines a ref Foo argument but the implementation uses mut Foo. In the below example this allows mutating of A even though the contract of Example.method states that its argument should not be mutable.

type A {
  let mut @value: Int
}

type B {}

trait Example {
  fn method(argument: ref A)
}

impl Example for B {
  fn method(argument: mut A) {
    argument.value = 42
  }
}

type async Main {
  fn async main {
    let a = A(0)
    let b = B()

    b.method(a)
  }
}

Similar to closures we probably have to invert the comparison and check if the signature of the requirement is compatible with that of the implementation. In the above example that means we'd end up comparing ref A -> mut A which is invalid and thus the compiler would correctly produce a compile-time error.

Operating system

Fedora

Inko version

main

Metadata

Metadata

Assignees

No one assigned

    Labels

    accepting contributionsIssues that are suitable to be worked on by anybody, not just maintainerscompilerChanges related to the compiler

    Type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions