diff --git a/src/ptr/external_shared.zig b/src/ptr/external_shared.zig index de59780b7d..bcc62e07ba 100644 --- a/src/ptr/external_shared.zig +++ b/src/ptr/external_shared.zig @@ -7,11 +7,14 @@ /// pub fn deref(T*) void; /// }; pub fn ExternalShared(comptime T: type) type { - _ = T.external_shared_descriptor.ref; // must define a `ref` function - _ = T.external_shared_descriptor.deref; // must define a `deref` function return struct { const Self = @This(); + comptime { + _ = T.external_shared_descriptor.ref; // must define a `ref` function + _ = T.external_shared_descriptor.deref; // must define a `deref` function + } + #impl: *T, /// `incremented_raw` should have already had its ref count incremented by 1. diff --git a/src/ptr/owned.zig b/src/ptr/owned.zig index 3dd2b36d2c..aa99ae7def 100644 --- a/src/ptr/owned.zig +++ b/src/ptr/owned.zig @@ -34,13 +34,12 @@ pub fn Dynamic(comptime Pointer: type) type { /// If `Allocator` is a zero-sized type, the owned pointer has no overhead compared to a raw /// pointer. pub fn OwnedIn(comptime Pointer: type, comptime Allocator: type) type { - const info = PointerInfo.parse(Pointer, .{}); - const NonOptionalPointer = info.NonOptionalPointer; - const Child = info.Child; - const ConstPointer = AddConst(Pointer); - return struct { const Self = @This(); + const info = PointerInfo.parse(Pointer, .{}); + const NonOptionalPointer = info.NonOptionalPointer; + const Child = info.Child; + const ConstPointer = AddConst(Pointer); #pointer: Pointer, #allocator: Allocator, @@ -381,10 +380,9 @@ pub fn OwnedIn(comptime Pointer: type, comptime Allocator: type) type { /// /// This type is accessible as `OwnedIn(Pointer, Allocator).Unmanaged`. fn Unmanaged(comptime Pointer: type, comptime Allocator: type) type { - const info = PointerInfo.parse(Pointer, .{}); - return struct { const Self = @This(); + const info = PointerInfo.parse(Pointer, .{}); #pointer: Pointer, diff --git a/src/ptr/shared.zig b/src/ptr/shared.zig index 208922a981..f9ff6b6951 100644 --- a/src/ptr/shared.zig +++ b/src/ptr/shared.zig @@ -61,12 +61,6 @@ pub fn AtomicSharedIn(comptime Pointer: type, comptime Allocator: type) type { /// Like `Shared`, but takes explicit options. pub fn WithOptions(comptime Pointer: type, comptime options: Options) type { - const Allocator = options.Allocator; - const info = parsePointer(Pointer); - const Child = info.Child; - const NonOptionalPointer = info.NonOptionalPointer; - const Data = FullData(Child, options); - if (options.allow_weak) { // Weak pointers only make sense if `deinit` will be called, since their only function // is to ensure `deinit` can be called before the memory is freed (weak pointers keep @@ -84,6 +78,11 @@ pub fn WithOptions(comptime Pointer: type, comptime options: Options) type { return struct { const Self = @This(); + const Allocator = options.Allocator; + const info = parsePointer(Pointer); + const Child = info.Child; + const NonOptionalPointer = info.NonOptionalPointer; + const Data = FullData(Child, options); #pointer: Pointer, @@ -239,11 +238,28 @@ pub fn WithOptions(comptime Pointer: type, comptime options: Options) type { return .fromValuePtr(self.#pointer); } + /// Turns a shared pointer into a raw pointer without decrementing the reference count. + /// + /// This method invalidates `self`. To avoid leaks, the raw pointer should be turned back + /// into a shared pointer with `adoptRawUnsafe`. + pub fn leak(self: *Self) Pointer { + defer self.* = undefined; + return self.#pointer; + } + + /// Creates a shared pointer from a raw pointer returned by `leak`. + /// + /// `pointer` must have been previously returned by `leak`. `adoptRawUnsafe` should not be + /// called again on this pointer. + pub fn adoptRawUnsafe(pointer: Pointer) Self { + return .{ .#pointer = pointer }; + } + /// Clones a shared pointer, given a raw pointer that originally came from a shared pointer. /// - /// `pointer` must have come from a shared pointer (e.g., from `get` or `leak`), and the shared - /// pointer from which it came must remain valid (i.e., not be deinitialized) at least until - /// this function returns. + /// `pointer` must have come from a shared pointer, and the shared pointer from which it + /// came must remain valid (i.e., not be deinitialized) at least until this function + /// returns. pub fn cloneFromRawUnsafe(pointer: Pointer) Self { const temp: Self = .{ .#pointer = pointer }; return temp.clone(); @@ -252,11 +268,6 @@ pub fn WithOptions(comptime Pointer: type, comptime options: Options) type { } fn Weak(comptime Pointer: type, comptime options: Options) type { - const info = parsePointer(Pointer); - const Child = info.Child; - const NonOptionalPointer = info.NonOptionalPointer; - const Data = FullData(Child, options); - bun.assertf( options.allow_weak and options.deinit, "options incompatible with shared.Weak", @@ -265,6 +276,10 @@ fn Weak(comptime Pointer: type, comptime options: Options) type { return struct { const Self = @This(); + const info = parsePointer(Pointer); + const Child = info.Child; + const NonOptionalPointer = info.NonOptionalPointer; + const Data = FullData(Child, options); #pointer: Pointer,