Skip to content

Rc mixin vs Rc wrapper #1488

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
andrew-johnson-4 opened this issue May 7, 2025 · 5 comments
Open

Rc mixin vs Rc wrapper #1488

andrew-johnson-4 opened this issue May 7, 2025 · 5 comments

Comments

@andrew-johnson-4
Copy link
Collaborator

andrew-johnson-4 commented May 7, 2025

Rc<A> vs A=>Rc

Benefits of Rc<A>:

  • can be used with all types, not just LM-style structures
  • affects typechecking
  • sometimes may require syntactic intervention from the programmer
  • depends on Into semantics to "feel good"
  • Rc<t> implements Rc

Benefits of A implements Rc

  • can be used to force all instances of the type to be reference counted
  • does not affect typechecking
  • can only be used with LM-style structures
@alex-s168
Copy link
Collaborator

I think we should have Rc<t> and interface AutoDeref<t>

@andrew-johnson-4
Copy link
Collaborator Author

What does AutoDeref do? Could you elaborate?

All I was thinking for Rc was something like this

interface Rc {
   let .reference-count(): USize;
   let set.reference-count(c: USize): Nil;
}

this interface would be satisfied by simply having a "reference-count" field.

@alex-s168
Copy link
Collaborator

I don't think that makes sense in practice.

re AutoDeref: it should be named Deref<t> instead

interface Deref<T> {
    let .deref(self): T;
};

(bad) example:

type Money => Deref<F64> { v: F64 };
let .deref(self: Money): F64 = ( self.v );

# `x` is of type Money
x + 1   # IS INVALID
*x + 1  # valid
x.fract()   # valid: auto-deref

@andrew-johnson-4
Copy link
Collaborator Author

andrew-johnson-4 commented May 8, 2025

Here is my view on the Rc interface: it is easy to do right now. It doesn't affect typechecking other than the parts that proactively do depend on reference counting. The Rc<t> wrapper type can just implement Rc and the compiler will acknowledge that, but anything that implements the Rc interface will be reference counted. By comparison, the Rc interface is not a container, so it is compatible with arbitrarily specific/contrived memory layouts, just so long as it supports the reference counter getter/setter. It is not adversely affected by move semantics, it just flows with however things are setup ad-hoc.

We can always back out and move to a different approach, but right now, the Rc interface is a concrete way that I can see of moving to GC in the short term.

@andrew-johnson-4
Copy link
Collaborator Author

andrew-johnson-4 commented May 8, 2025

One of the coolest thing about Rc interface is that data structures and any type can be marked as reference counted. So all List, Vector, AST, Type, whatever can be marked as GC-enabled and used without any change in the type signatures or other code interactions.

# I don't know what syntax this would look like.
# I think a syntax was proposed, but I can't find the ticket right now.
[derive Rc]
type AST = ASTEOF | ASTNil | ...;

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
Status: No status
Development

No branches or pull requests

2 participants