BorrowScript icon indicating copy to clipboard operation
BorrowScript copied to clipboard

[Design] How to write interfaces to describe ownership?

Open alshdavid opened this issue 2 years ago • 5 comments

interface IFoobar {
  read foo(): void  // You must be the owner or have read access
  write bar(): void  // You must be the owner or have write access
}

And functions?

function foobar(read f: IFoobar ) { }

let f = new Foobar()
foobar(read f)

alshdavid avatar Oct 01 '21 01:10 alshdavid

Hey, I think this language is a great idea! It's exactly what's missing for me in the Wasm ecosystem.

My 2 cents: It would be cool if inference of both types and borrow permissions were automatic, wherever possible. E.g. there are builtin operations that need read access and there are builtin ops that need write access. If a function takes an argument and performs an operation that needs read access on it, then by extension that function needs read access. I think the compiler should at that point just assume that, whoever passes a value to this function, gives that function read access -- no read annotation needed. The compiler should, in my mind, only ever complain if there's a conflict (e.g., another function that potentially runs in parallel to this function gets write access). Same for types.

Disclaimer: I'm not familiar with Rust and thus do not have good intuitions about what we'd want from borrowing syntax. I also don't know how feasible automatic inference is.

mitschabaude avatar Oct 01 '21 13:10 mitschabaude

Syntax looks good to me.

On Thu, Sep 30, 2021, 9:47 PM David Alsh @.***> wrote:

interface IFoobar { read foo(): void // You must be the owner or have read access write bar(): void // You must be the owner or have write access}

And functions?

function foobar(read f: IFoobar ) { } let f = new Foobar()foobar(read f)

— You are receiving this because you are subscribed to this thread. Reply to this email directly, view it on GitHub https://github.com/alshdavid/BorrowScript/issues/16, or unsubscribe https://github.com/notifications/unsubscribe-auth/AGDQCMV2GT3BKCQPNZNU22LUEUHKRANCNFSM5FDTDF7A .

SuperSonicHub1 avatar Oct 01 '21 19:10 SuperSonicHub1

I agree with @mitschabaude. Some automatic borrow checking would be great.

Also, it would be nice to have the default semantics to be write ownership rather than move. Mainly because that is what TypeScript typically assumes.

Circling back the the automatic borrow checking idea, BorrowScript can default to move if that can't be applied (meaning there is a complication error with that assumption) then, read then, write or copy where appropriate (e.g. primitive types).

Geo25rey avatar Oct 01 '21 20:10 Geo25rey

My 2 cents: It would be cool if inference of both types and borrow permissions were automatic, wherever possible. E.g. there are builtin operations that need read access and there are builtin ops that need write access. If a function takes an argument and performs an operation that needs read access on it, then by extension that function needs read access. I think the compiler should at that point just assume that, whoever passes a value to this function, gives that function read access -- no read annotation needed. The compiler should, in my mind, only ever complain if there's a conflict (e.g., another function that potentially runs in parallel to this function gets write access). Same for types.

Disclaimer: I'm not familiar with Rust and thus do not have good intuitions about what we'd want from borrowing syntax. I also don't know how feasible automatic inference is.

Having used Rust a solid amount, I'm not sure I agree with this. In Rust, I have to think very carefully about the mutability of the interfaces I'm exposing because it strongly constrains the structure of the calling code. You can copy a read pointer, but the data needs to be frozen, or you can pass around a single instance of a mutable pointer. I think a mutability inference system like this might result in very surprising updates, where a bunch of the code you wrote no longer works because some function you're calling changed its mutability requirements.

That being said, there are things that could be done to make this smoother. Automatic downgrading of references from own to write to read is nice. Having Mutexes be easy to use is a good idea. RefCell/RWLock (a mutex which can be locked for reading or for writing) is also a super common tool in Rust for getting away from mutability issues. (Name might want some bike shedding, or honestly just make Mutex a RWLock.)

I'm not sure about annotations for mutability on function arguments. I think you want them on declarations ("parameters"), but you might be able to drop them for invocations. It is nice to be able to see when scanning through code... But it would be fairly easy to back-fill with an IDE / annotations in VSCode. Won't show up in code review or low-tech editors though.

I'm also curious how the lifetime system is gonna interact with anonymous union and struct types.

kazimuth avatar Oct 05 '21 00:10 kazimuth

I feel like this should be left to be decided later once more of the language is finalised such as const vs let declarations and readonly / / mut property modifiers.

Isaac-Leonard avatar Oct 23 '21 22:10 Isaac-Leonard