Skip to content
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

[stdlib] Fix allow implicit casting MutableOrigin -> ImmutableOrigin #3823

Draft
wants to merge 15 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 3 additions & 5 deletions stdlib/src/builtin/sort.mojo
Original file line number Diff line number Diff line change
Expand Up @@ -216,8 +216,8 @@ fn _quicksort[

# Work with an immutable span so we don't run into exclusivity problems with
# the List[Span].
var imm_span = span.get_immutable()
alias ImmSpan = __type_of(imm_span)
var imm_span = span.immut()
alias ImmSpan = span.ImmutSelf

var stack = List[ImmSpan](capacity=_estimate_initial_height(size))
stack.append(imm_span)
Expand Down Expand Up @@ -342,9 +342,7 @@ fn _stable_sort_impl[
while j + merge_size < size:
var span1 = span[j : j + merge_size]
var span2 = span[j + merge_size : min(size, j + 2 * merge_size)]
_merge[cmp_fn](
span1.get_immutable(), span2.get_immutable(), temp_buff
)
_merge[cmp_fn](span1.immut(), span2, temp_buff)
for i in range(merge_size + len(span2)):
span[j + i] = temp_buff[i]
j += 2 * merge_size
Expand Down
15 changes: 11 additions & 4 deletions stdlib/src/builtin/type_aliases.mojo
Original file line number Diff line number Diff line change
Expand Up @@ -91,10 +91,7 @@ struct Origin[is_mutable: Bool]:
# Life cycle methods
# ===-------------------------------------------------------------------===#

# NOTE:
# Needs to be @implicit convertible for the time being so that
# `__origin_of(..)` can implicilty convert to `Origin` in use cases like:
# Span[Byte, __origin_of(self)]
@doc_private
@implicit
@always_inline("nodebug")
fn __init__(out self, mlir_origin: Self._mlir_type):
Expand All @@ -104,6 +101,16 @@ struct Origin[is_mutable: Bool]:
mlir_origin: The raw MLIR origin value."""
self._mlir_origin = mlir_origin

@doc_private
@implicit
@always_inline("nodebug")
fn __init__(out self: ImmutableOrigin, origin: MutableOrigin):
"""Initialize an ImmutableOrigin from a MutableOrigin.

Args:
origin: The origin value."""
self = rebind[ImmutableOrigin](origin)


struct _lit_mut_cast[
is_mutable: Bool, //,
Expand Down
40 changes: 26 additions & 14 deletions stdlib/src/collections/string/string_slice.mojo
Original file line number Diff line number Diff line change
Expand Up @@ -256,12 +256,29 @@ struct StringSlice[mut: Bool, //, origin: Origin[mut]](
UTF-8.
"""

# Aliases
alias MutSelf = StringSlice[MutableOrigin.cast_from[origin].result]
"""The mutable version of the StringSlice."""
alias ImmutSelf = StringSlice[ImmutableOrigin.cast_from[origin].result]
"""The immutable version of the StringSlice."""
# Fields
var _slice: Span[Byte, origin]

# ===------------------------------------------------------------------===#
# Initializers
# ===------------------------------------------------------------------===#

@doc_private
@implicit
@always_inline("nodebug")
fn __init__(out self: Self.ImmutSelf, other: Self.MutSelf):
"""Implicitly cast the mutable origin of self to an immutable one.

Args:
other: The StringSlice to cast.
"""
self = rebind[Self.ImmutSelf](other)

@always_inline
@implicit
fn __init__(out self: StaticString, lit: StringLiteral):
Expand Down Expand Up @@ -656,6 +673,15 @@ struct StringSlice[mut: Bool, //, origin: Origin[mut]](
# Methods
# ===------------------------------------------------------------------===#

@always_inline
fn immut(self) -> Self.ImmutSelf:
"""Return an immutable version of this StringSlice.

Returns:
An immutable version of the same StringSlice.
"""
return rebind[Self.ImmutSelf](self)

@always_inline
fn strip(self, chars: StringSlice) -> Self:
"""Return a copy of the string with leading and trailing characters
Expand Down Expand Up @@ -825,20 +851,6 @@ struct StringSlice[mut: Bool, //, origin: Origin[mut]](

return len(self.as_bytes())

fn get_immutable(
self,
) -> StringSlice[ImmutableOrigin.cast_from[origin].result]:
"""
Return an immutable version of this string slice.

Returns:
A string slice covering the same elements, but without mutability.
"""
return StringSlice[ImmutableOrigin.cast_from[origin].result](
ptr=self._slice.unsafe_ptr(),
length=len(self),
)

fn startswith(
self, prefix: StringSlice, start: Int = 0, end: Int = -1
) -> Bool:
Expand Down
32 changes: 22 additions & 10 deletions stdlib/src/memory/span.mojo
Original file line number Diff line number Diff line change
Expand Up @@ -107,14 +107,30 @@ struct Span[
origin: The origin of the Span.
"""

# Field
# Aliases
alias MutSelf = Span[T, MutableOrigin.cast_from[origin].result]
"""The mutable version of the Span."""
alias ImmutSelf = Span[T, ImmutableOrigin.cast_from[origin].result]
"""The immutable version of the Span."""
# Fields
var _data: UnsafePointer[T, mut=mut, origin=origin]
var _len: Int

# ===------------------------------------------------------------------===#
# Life cycle methods
# ===------------------------------------------------------------------===#

@doc_private
@implicit
@always_inline("nodebug")
fn __init__(out self: Self.ImmutSelf, other: Self.MutSelf):
"""Implicitly cast the mutable origin of self to an immutable one.

Args:
other: The Span to cast.
"""
self = rebind[Self.ImmutSelf](other)

@always_inline
fn __init__(out self, *, ptr: UnsafePointer[T], length: Int):
"""Unsafe construction from a pointer and length.
Expand Down Expand Up @@ -393,15 +409,11 @@ struct Span[
for element in self:
element[] = value

fn get_immutable(
self,
) -> Span[T, ImmutableOrigin.cast_from[origin].result]:
"""
Return an immutable version of this span.
@always_inline
fn immut(self) -> Self.ImmutSelf:
"""Return an immutable version of this Span.

Returns:
A span covering the same elements, but without mutability.
An immutable version of the same Span.
"""
return Span[T, ImmutableOrigin.cast_from[origin].result](
ptr=self._data, length=self._len
)
return rebind[Self.ImmutSelf](self)
7 changes: 4 additions & 3 deletions stdlib/src/os/path/path.mojo
Original file line number Diff line number Diff line change
Expand Up @@ -549,8 +549,9 @@ fn _parse_variable_name[


fn expandvars[PathLike: os.PathLike, //](path: PathLike) -> String:
"""Replaces `${var}` or `$var` in the path with values from the current environment variables.
Malformed variable names and references to non-existing variables are left unchanged.
"""Replaces `${var}` or `$var` in the path with values from the current
environment variables. Malformed variable names and references to
non-existing variables are left unchanged.

Parameters:
PathLike: The type conforming to the os.PathLike trait.
Expand All @@ -562,7 +563,7 @@ fn expandvars[PathLike: os.PathLike, //](path: PathLike) -> String:
The expanded path.
"""
var path_str = path.__fspath__()
var bytes = path_str.as_bytes().get_immutable()
var bytes = path_str.as_bytes().immut()
var buf = String()

# Byte scanning should be fine, ${} is ASCII.
Expand Down
Loading