ronantakizawa/codereview-bench huggingface dataset:
Repository: JuliaLang/julia
File: base/iterators.jl (Julia)

Code before:

# Flatten{Take{Repeated{O}}} is the actual type of an Iterators.cycle(iterable::O, m) iterator
function _nth(::Union{HasShape, HasLength}, itr::Flatten{Take{Repeated{O}}}, n::Integer) where {O}
    cycles = itr.it.n
    torepeat = itr.it.xs.x
    k = length(torepeat)
    (n > k*cycles || k == 0) && throw(BoundsError(itr, n))

    # prevent wrap around behaviour and inherit the error handling
    return nth(torepeat, n > 0 ? mod1(n, k) : n)
end

function _nth(::IteratorSize, itr, n::Integer)
    # unrolled version of `first(drop)`
    n > 0 || throw(BoundsError(itr, n))
    y = iterate(itr)
    for _ in 1:n-1
        y === nothing && break
        y = iterate(itr, y[2])
    end
    y === nothing && throw(BoundsError(itr, n))
    y[1]
end

# issue #58922
_nth(::Union{HasShape, HasLength}, z::Zip, n::Integer) = map(nth(n), z.is)

"""
    nth(n::Integer)

Return a function that gets the `n`-th element from any iterator passed to it.
Equivalent to `Base.Fix2(nth, n)` or `itr -> nth(itr, n)`.

See also: [`nth`](@ref), [`Base.Fix2`](@ref)
# Examples
```jldoctest
julia> fifth_element = Iterators.nth(5)
(::Base.Fix2{typeof(Base.Iterators.nth), Int64}) (generic function with 2 methods)

julia> fifth_element(reshape(1:30, (5,6)))
5

julia> map(fifth_element, ("Willis", "Jovovich", "Oldman"))
('i', 'v', 'a')
```
"""
nth(n::Integer) = Base.Fix2(nth, n)

end


Review comment (suggestion):
```suggestion
_nth(::Union{HasShape, HasLength}, z::Zip, n::Integer) = Base.map(nth(n), z.is)
```

Code after:

# Flatten{Take{Repeated{O}}} is the actual type of an Iterators.cycle(iterable::O, m) iterator
function _nth(::Union{HasShape, HasLength}, itr::Flatten{Take{Repeated{O}}}, n::Integer) where {O}
    cycles = itr.it.n
    torepeat = itr.it.xs.x
    k = length(torepeat)
    (n > k*cycles || k == 0) && throw(BoundsError(itr, n))

    # prevent wrap around behaviour and inherit the error handling
    return nth(torepeat, n > 0 ? mod1(n, k) : n)
end

function _nth(::IteratorSize, itr, n::Integer)
    # unrolled version of `first(drop)`
    n > 0 || throw(BoundsError(itr, n))
    y = iterate(itr)
    for _ in 1:n-1
        y === nothing && break
        y = iterate(itr, y[2])
    end
    y === nothing && throw(BoundsError(itr, n))
    y[1]
end

_nth(::IteratorSize, z::Zip, n::Integer) = Base.map(nth(n), z.is)

"""
    nth(n::Integer)

Return a function that gets the `n`-th element from any iterator passed to it.
Equivalent to `Base.Fix2(nth, n)` or `itr -> nth(itr, n)`.

See also: [`nth`](@ref), [`Base.Fix2`](@ref)
# Examples
```jldoctest
julia> fifth_element = Iterators.nth(5)
(::Base.Fix2{typeof(Base.Iterators.nth), Int64}) (generic function with 2 methods)

julia> fifth_element(reshape(1:30, (5,6)))
5

julia> map(fifth_element, ("Willis", "Jovovich", "Oldman"))
('i', 'v', 'a')
```
"""
nth(n::Integer) = Base.Fix2(nth, n)

end
Repository: JuliaLang/julia
File: base/iterators.jl (Julia)

Code before:
end

# Flatten{Take{Repeated{O}}} is the actual type of an Iterators.cycle(iterable::O, m) iterator
function _nth(::Union{HasShape, HasLength}, itr::Flatten{Take{Repeated{O}}}, n::Integer) where {O}
    cycles = itr.it.n
    torepeat = itr.it.xs.x
    k = length(torepeat)
    (n > k*cycles || k == 0) && throw(BoundsError(itr, n))

    # prevent wrap around behaviour and inherit the error handling
    return nth(torepeat, n > 0 ? mod1(n, k) : n)
end

function _nth(::IteratorSize, itr, n::Integer)
    # unrolled version of `first(drop)`
    n > 0 || throw(BoundsError(itr, n))
    y = iterate(itr)
    for _ in 1:n-1
        y === nothing && break
        y = iterate(itr, y[2])
    end
    y === nothing && throw(BoundsError(itr, n))
    y[1]
end

# issue #58922
_nth(::Union{HasShape, HasLength}, z::Zip, n::Integer) = map(nth(n), z.is)

"""
    nth(n::Integer)

Return a function that gets the `n`-th element from any iterator passed to it.
Equivalent to `Base.Fix2(nth, n)` or `itr -> nth(itr, n)`.

See also: [`nth`](@ref), [`Base.Fix2`](@ref)
# Examples
```jldoctest
julia> fifth_element = Iterators.nth(5)
(::Base.Fix2{typeof(Base.Iterators.nth), Int64}) (generic function with 2 methods)

julia> fifth_element(reshape(1:30, (5,6)))
5

julia> map(fifth_element, ("Willis", "Jovovich", "Oldman"))
('i', 'v', 'a')
```
"""
nth(n::Integer) = Base.Fix2(nth, n)

end


Review comment (suggestion):
```suggestion
```

this specialization is reasonable to add no matter the motivating issue :)

Code after:
end

# Flatten{Take{Repeated{O}}} is the actual type of an Iterators.cycle(iterable::O, m) iterator
function _nth(::Union{HasShape, HasLength}, itr::Flatten{Take{Repeated{O}}}, n::Integer) where {O}
    cycles = itr.it.n
    torepeat = itr.it.xs.x
    k = length(torepeat)
    (n > k*cycles || k == 0) && throw(BoundsError(itr, n))

    # prevent wrap around behaviour and inherit the error handling
    return nth(torepeat, n > 0 ? mod1(n, k) : n)
end

function _nth(::IteratorSize, itr, n::Integer)
    # unrolled version of `first(drop)`
    n > 0 || throw(BoundsError(itr, n))
    y = iterate(itr)
    for _ in 1:n-1
        y === nothing && break
        y = iterate(itr, y[2])
    end
    y === nothing && throw(BoundsError(itr, n))
    y[1]
end

_nth(::IteratorSize, z::Zip, n::Integer) = Base.map(nth(n), z.is)

"""
    nth(n::Integer)

Return a function that gets the `n`-th element from any iterator passed to it.
Equivalent to `Base.Fix2(nth, n)` or `itr -> nth(itr, n)`.

See also: [`nth`](@ref), [`Base.Fix2`](@ref)
# Examples
```jldoctest
julia> fifth_element = Iterators.nth(5)
(::Base.Fix2{typeof(Base.Iterators.nth), Int64}) (generic function with 2 methods)

julia> fifth_element(reshape(1:30, (5,6)))
5

julia> map(fifth_element, ("Willis", "Jovovich", "Oldman"))
('i', 'v', 'a')
```
"""
nth(n::Integer) = Base.Fix2(nth, n)

end
Repository: JuliaLang/julia
File: src/gf.c (C)

Code before:
    }
    else if (specializations != NULL) {
        jl_method_instance_t *mi = (jl_method_instance_t*)specializations;
        invalidate_method_instance_caches(mi, world);
    }
    JL_UNLOCK(&method->writelock);
    return 1;
}

static int invalidate_all_caches_visitor(jl_methtable_t *mt, void *env)
{
    return jl_typemap_visitor(jl_atomic_load_relaxed(&mt->defs), invalidate_all_specializations, env);
}

JL_DLLEXPORT void jl_drop_all_caches(void)
{
    JL_LOCK(&world_counter_lock);

    // Get current world age - we'll invalidate everything at this world
    size_t current_world = jl_atomic_load_relaxed(&jl_world_counter);

    // Walk through all method tables and invalidate all code instances
    jl_array_t *mod_array = jl_get_loaded_modules();
    JL_GC_PUSH1(&mod_array);
    jl_foreach_reachable_mtable(invalidate_all_caches_visitor, mod_array, (void*)&current_world);
    JL_GC_POP();

    // Increment world age - this forces all subsequent compilation to happen in the new world
    size_t new_world = current_world + 1;
    jl_atomic_store_release(&jl_world_counter, new_world);

    JL_UNLOCK(&world_counter_lock);
}


#ifdef __cplusplus
}
#endif


Review comment (performance):
There is only one method table now, so you can just examine it directly:
```suggestion
    invalidate_all_caches_visitor(jl_method_table, current_world);
```

Code after:
    }
    else if (specializations != NULL) {
        jl_method_instance_t *mi = (jl_method_instance_t*)specializations;
        invalidate_method_instance_caches(mi, world);
    }
    JL_UNLOCK(&method->writelock);
    return 1;
}

static int invalidate_all_caches_visitor(jl_methtable_t *mt, void *env)
{
    return jl_typemap_visitor(jl_atomic_load_relaxed(&mt->defs), invalidate_all_specializations, env);
}

JL_DLLEXPORT void jl_drop_all_caches(void)
{
    JL_LOCK(&world_counter_lock);

    // Get current world age - we'll invalidate everything at this world
    size_t current_world = jl_atomic_load_relaxed(&jl_world_counter);

    invalidate_all_caches_visitor(jl_method_table, &current_world);

    // Increment world age - this forces all subsequent compilation to happen in the new world
    size_t new_world = current_world + 1;
    jl_atomic_store_release(&jl_world_counter, new_world);

    JL_UNLOCK(&world_counter_lock);
}


#ifdef __cplusplus
}
#endif
Repository: JuliaLang/julia
File: stdlib/REPL/src/REPLCompletions.jl (Julia)

Code before:
    catch err
        # access(2) errors unhandled by ispath: EACCES, EIO, ELOOP, ENAMETOOLONG
        if err isa Base.IOError
            false
        elseif err isa Base.ArgumentError && occursin("embedded NULs", err.msg)
            false
        else
            rethrow()
        end
    end
    expanded && !hint && full_path && return Completion[PathCompletion(escape(path))], true

    # Expand '~' if the user hits TAB on a path ending in '/'.
    expanded && (hint || path != dir * "/") && (dir = contractuser(dir))

    map!(paths) do c::PathCompletion
        p = joinpath_withsep(dir, c.path; dirsep)
        PathCompletion(escape(p))
    end
    return sort!(paths, by=p->p.path), success
end

function __init__()
    if !Base.Compiler.should_insert_coverage(@__MODULE__, debuginfo)
        COMPLETION_WORLD[] = Base.get_world_counter()
    end
    return nothing
end

end # module


Review comment (suggestion):
```suggestion
    COMPLETION_WORLD[] = Base.get_world_counter()
```


Code after:
    catch err
        # access(2) errors unhandled by ispath: EACCES, EIO, ELOOP, ENAMETOOLONG
        if err isa Base.IOError
            false
        elseif err isa Base.ArgumentError && occursin("embedded NULs", err.msg)
            false
        else
            rethrow()
        end
    end
    expanded && !hint && full_path && return Completion[PathCompletion(escape(path))], true

    # Expand '~' if the user hits TAB on a path ending in '/'.
    expanded && (hint || path != dir * "/") && (dir = contractuser(dir))

    map!(paths) do c::PathCompletion
        p = joinpath_withsep(dir, c.path; dirsep)
        PathCompletion(escape(p))
    end
    return sort!(paths, by=p->p.path), success
end

function __init__()
    COMPLETION_WORLD[] = Base.get_world_counter()
    return nothing
end

end # module
Repository: JuliaLang/julia
File: test/client.jl (Julia)

Code before:
        ERROR: ErrorException
        """s, err_str)
end

@testset "defining `ans` and `err`" begin
    @test eval(:(ans = 1)) == 1
    @test eval(:(err = 1)) == 1
end

@testset "scrub REPL-related frames" begin
    repl_bt = [StackFrame(:foo, "foo.jl", 1),
          StackFrame(:__repl_entry_anysuffix, "client.jl", 2),
          StackFrame(:bar, "bar.jl", 3)]
    scrubbed_repl_bt = Base.scrub_repl_backtrace(repl_bt)

    nonrepl_bt = [StackFrame(:foo, "foo.jl", 1),
          StackFrame(:baz, "baz.jl", 2),
          StackFrame(:bar, "bar.jl", 3)]
    scrubbed_nonrepl_bt = Base.scrub_repl_backtrace(nonrepl_bt)

    @test length(scrubbed_repl_bt) == 1
    @test scrubbed_repl_bt[1].func == :foo
    @test length(scrubbed_nonrepl_bt) == 3

    # tests `eval` errors only; lowering by design defers errors to eval, so exceptions
    # from `lower` could only occur in development and cannot be tested here.
    errexpr = :(error("fail"))
    errio = IOBuffer()
    Base.eval_user_input(errio, errexpr, false)
    outstr = String(take!(errio))
    @test !occursin("_repl_entry", outstr)
    @test !occursin("client.jl", outstr)
end


Review comment (suggestion):
I don't understand this comment. `macro bad(); error(); end` with `errexpr = :(@bad)` should be enough.

Code after:
        ERROR: ErrorException
        """s, err_str)
end

@testset "defining `ans` and `err`" begin
    @test eval(:(ans = 1)) == 1
    @test eval(:(err = 1)) == 1
end

@testset "scrub REPL-related frames" begin
    repl_bt = [StackFrame(:foo, "foo.jl", 1),
          StackFrame(:__repl_entry_anysuffix, "client.jl", 2),
          StackFrame(:bar, "bar.jl", 3)]
    scrubbed_repl_bt = Base.scrub_repl_backtrace(repl_bt)

    nonrepl_bt = [StackFrame(:foo, "foo.jl", 1),
          StackFrame(:baz, "baz.jl", 2),
          StackFrame(:bar, "bar.jl", 3)]
    scrubbed_nonrepl_bt = Base.scrub_repl_backtrace(nonrepl_bt)

    @test length(scrubbed_repl_bt) == 1
    @test scrubbed_repl_bt[1].func == :foo
    @test length(scrubbed_nonrepl_bt) == 3

    errio = IOBuffer()
    lower_errexpr = :(@bad)
    Base.eval_user_input(errio, lower_errexpr, false)
    outstr = String(take!(errio))
    @test occursin("ERROR: LoadError: UndefVarError: `@bad`", outstr)
    @test !occursin("_repl_entry", outstr)
    @test !occursin(r"\.[/\\]client.jl", outstr)

    errexpr = :(error("fail"))
    Base.eval_user_input(errio, errexpr, false)
    outstr = String(take!(errio))
    @test occursin("ERROR: fail", outstr)
    @test !occursin("_repl_entry", outstr)
    @test !occursin(r"\.[/\\]client.jl", outstr)
end
Repository: JuliaLang/julia
File: base/scopedvalues.jl (Julia)

Code before:
Dynamic scopes are propagated across tasks.

# Examples

```jldoctest
julia> using Base.ScopedValues;

julia> const sval = ScopedValue(1);

julia> sval[]
1

julia> with(sval => 2) do
           sval[]
       end
2

julia> sval[]
1
```

!!! compat "Julia 1.11"
    Scoped values were introduced in Julia 1.11. In Julia 1.8+ a compatible
    implementation is available from the package ScopedValues.jl.
"""
const ScopedValue{T} = Union{LazyScopedValue{T, Returns{T}}, LazyScopedValue{T, typeof(no_default)}}

ScopedValue{T}() where T = LazyScopedValue{T, typeof(no_default)}(no_default)
ScopedValue{T}(val) where T = LazyScopedValue{T, Returns{T}}(Returns{T}(val))
ScopedValue(val::T) where T = LazyScopedValue{T, Returns{T}}(Returns{T}(val))

Base.eltype(::LazyScopedValue{T}) where {T} = T

"""
    isassigned(val::ScopedValue)

Test whether a `ScopedValue` has an assigned value.

See also: [`ScopedValues.with`](@ref), [`ScopedValues.@with`](@ref), [`ScopedValues.get`](@ref).

# Examples
```jldoctest
julia> using Base.ScopedValues

julia> a = ScopedValue(1); b = ScopedValue{Int}();

julia> isassigned(a)
true

julia> isassigned(b)
false

Review comment (refactor):
Isn't this considered breaking, since `ScopedValue{Foo}` is no longer concrete? Why not create a new abstract type and make `ScopedValue`  subtype that, thereby making handling of `LazyScopedValue` opt-in?

Code after:

Create a container that propagates values across dynamic scopes.
Use [`with`](@ref) to create and enter a new dynamic scope.

Values can only be set when entering a new dynamic scope,
and the value referred to will be constant during the
execution of a dynamic scope.

Dynamic scopes are propagated across tasks.

# Examples

```jldoctest
julia> using Base.ScopedValues;

julia> const sval = ScopedValue(1);

julia> sval[]
1

julia> with(sval => 2) do
           sval[]
       end
2

julia> sval[]
1
```

!!! compat "Julia 1.11"
    Scoped values were introduced in Julia 1.11. In Julia 1.8+ a compatible
    implementation is available from the package ScopedValues.jl.
"""
mutable struct ScopedValue{T} <: AbstractScopedValue{T}
    # NOTE this struct must be defined as mutable one since it's used as a key of
    #      `ScopeStorage` dictionary and thus needs object identity
    const hasdefault::Bool # this field is necessary since isbitstype `default` field may be initialized with undefined value
    const default::T
    ScopedValue{T}() where T = new{T}(false)
    ScopedValue{T}(val) where T = new{T}(true, val)
    ScopedValue(val::T) where T = new{T}(true, val)
end

Base.eltype(::AbstractScopedValue{T}) where {T} = T

hasdefault(val::ScopedValue) = val.hasdefault
hasdefault(val::LazyScopedValue) = true

getdefault(val::ScopedValue) = val.hasdefault ? val.default : throw(KeyError(val))
getdefault(val::LazyScopedValue) = val.getdefault()
Repository: JuliaLang/julia
File: base/scopedvalues.jl (Julia)

Code before:
# This file is a part of Julia. License is MIT: https://julialang.org/license

module ScopedValues

export ScopedValue, LazyScopedValue, with, @with
public get

"""
    AbstractScopedValue{T}

Abstract base type for scoped values that propagate values across
dynamic scopes. All scoped value types must extend this abstract type.

See also: [`ScopedValue`](@ref), [`LazyScopedValue`](@ref)
"""
abstract type AbstractScopedValue{T} end


"""
    LazyScopedValue{T}(f::OncePerProcess{T})

A scoped value that uses an `OncePerProcess{T}` to lazily compute its default value
when none has been set in the current scope. Unlike `ScopedValue`, the default is
not evaluated at construction time but only when first accessed.

# Examples

```julia-repl
julia> using Base.ScopedValues;

julia> const editor = LazyScopedValue(OncePerProcess(() -> ENV["JULIA_EDITOR"]));

julia> editor[]
"vim"

julia> with(editor => "emacs") do
           sval[]
       end
"emacs"

Review comment (refactor):
```suggestion
See also: [`ScopedValue`](@ref), [`LazyScopedValue`](@ref)

!!! compat "Julia 1.13"
    AbstractScopedValue requires Julia 1.13+.
```

Code after:
# This file is a part of Julia. License is MIT: https://julialang.org/license

module ScopedValues

export ScopedValue, LazyScopedValue, with, @with
public get

"""
    AbstractScopedValue{T}

Abstract base type for scoped values that propagate values across
dynamic scopes. All scoped value types must extend this abstract type.

See also: [`ScopedValue`](@ref), [`LazyScopedValue`](@ref)

!!! compat "Julia 1.13"
    AbstractScopedValue requires Julia 1.13+.
"""
abstract type AbstractScopedValue{T} end


"""
    LazyScopedValue{T}(f::OncePerProcess{T})

A scoped value that uses an `OncePerProcess{T}` to lazily compute its default value
when none has been set in the current scope. Unlike `ScopedValue`, the default is
not evaluated at construction time but only when first accessed.

# Examples

```julia-repl
julia> using Base.ScopedValues;

julia> const editor = LazyScopedValue(OncePerProcess(() -> ENV["JULIA_EDITOR"]));

julia> editor[]
"vim"

julia> with(editor => "emacs") do
Repository: JuliaLang/julia
File: base/scopedvalues.jl (Julia)

Code before:
Dynamic scopes are propagated across tasks.

# Examples

```jldoctest
julia> using Base.ScopedValues;

julia> const sval = ScopedValue(1);

julia> sval[]
1

julia> with(sval => 2) do
           sval[]
       end
2

julia> sval[]
1
```

!!! compat "Julia 1.11"
    Scoped values were introduced in Julia 1.11. In Julia 1.8+ a compatible
    implementation is available from the package ScopedValues.jl.
"""
mutable struct ScopedValue{T} <: AbstractScopedValue{T}
    const hasdefault::Bool
    const default::T
    ScopedValue{T}() where T = new{T}(false)
    ScopedValue{T}(val) where T = new{T}(true, val)
    ScopedValue(val::T) where T = new{T}(true, val)
end

Base.eltype(::AbstractScopedValue{T}) where {T} = T

hasdefault(val::ScopedValue) = val.hasdefault
hasdefault(val::LazyScopedValue) = true

getdefault(val::ScopedValue) = val.hasdefault ? val.default : throw(KeyError(val))
getdefault(val::LazyScopedValue) = val.getdefault()

"""
    isassigned(val::ScopedValue)

Test whether a `ScopedValue` has an assigned value.

See also: [`ScopedValues.with`](@ref), [`ScopedValues.@with`](@ref), [`ScopedValues.get`](@ref).

# Examples
```jldoctest
julia> using Base.ScopedValues

Review comment (refactor):
```suggestion
mutable struct ScopedValue{T} <: AbstractScopedValue{T}
    # NOTE this struct must be defined as mutable one since it's used as a key of
    #      `ScopeStorage` dictionary and thus needs object identity
```

Code after:
Dynamic scopes are propagated across tasks.

# Examples

```jldoctest
julia> using Base.ScopedValues;

julia> const sval = ScopedValue(1);

julia> sval[]
1

julia> with(sval => 2) do
           sval[]
       end
2

julia> sval[]
1
```

!!! compat "Julia 1.11"
    Scoped values were introduced in Julia 1.11. In Julia 1.8+ a compatible
    implementation is available from the package ScopedValues.jl.
"""
mutable struct ScopedValue{T} <: AbstractScopedValue{T}
    # NOTE this struct must be defined as mutable one since it's used as a key of
    #      `ScopeStorage` dictionary and thus needs object identity
    const hasdefault::Bool # this field is necessary since isbitstype `default` field may be initialized with undefined value
    const default::T
    ScopedValue{T}() where T = new{T}(false)
    ScopedValue{T}(val) where T = new{T}(true, val)
    ScopedValue(val::T) where T = new{T}(true, val)
end

Base.eltype(::AbstractScopedValue{T}) where {T} = T

hasdefault(val::ScopedValue) = val.hasdefault
hasdefault(val::LazyScopedValue) = true

getdefault(val::ScopedValue) = val.hasdefault ? val.default : throw(KeyError(val))
getdefault(val::LazyScopedValue) = val.getdefault()

"""
    isassigned(val::ScopedValue)

Test whether a `ScopedValue` has an assigned value.

See also: [`ScopedValues.with`](@ref), [`ScopedValues.@with`](@ref), [`ScopedValues.get`](@ref).

# Examples
Repository: JuliaLang/julia
File: base/scopedvalues.jl (Julia)

Code before:

```jldoctest
julia> using Base.ScopedValues;

julia> const sval = ScopedValue(1);

julia> sval[]
1

julia> with(sval => 2) do
           sval[]
       end
2

julia> sval[]
1
```

!!! compat "Julia 1.11"
    Scoped values were introduced in Julia 1.11. In Julia 1.8+ a compatible
    implementation is available from the package ScopedValues.jl.
"""
mutable struct ScopedValue{T} <: AbstractScopedValue{T}
    # NOTE this struct must be defined as mutable one since it's used as a key of
    #      `ScopeStorage` dictionary and thus needs object identity
    const hasdefault::Bool
    const default::T
    ScopedValue{T}() where T = new{T}(false)
    ScopedValue{T}(val) where T = new{T}(true, val)
    ScopedValue(val::T) where T = new{T}(true, val)
end

Base.eltype(::AbstractScopedValue{T}) where {T} = T

hasdefault(val::ScopedValue) = val.hasdefault
hasdefault(val::LazyScopedValue) = true

getdefault(val::ScopedValue) = val.hasdefault ? val.default : throw(KeyError(val))
getdefault(val::LazyScopedValue) = val.getdefault()

"""
    isassigned(val::ScopedValue)

Test whether a `ScopedValue` has an assigned value.

See also: [`ScopedValues.with`](@ref), [`ScopedValues.@with`](@ref), [`ScopedValues.get`](@ref).

# Examples
```jldoctest
julia> using Base.ScopedValues


Review comment (suggestion):
```suggestion
    const hasdefault::Bool # this field is necessary since isbitstype `default` field may be initialized with undefined value
```

Code after:

```jldoctest
julia> using Base.ScopedValues;

julia> const sval = ScopedValue(1);

julia> sval[]
1

julia> with(sval => 2) do
           sval[]
       end
2

julia> sval[]
1
```

!!! compat "Julia 1.11"
    Scoped values were introduced in Julia 1.11. In Julia 1.8+ a compatible
    implementation is available from the package ScopedValues.jl.
"""
mutable struct ScopedValue{T} <: AbstractScopedValue{T}
    # NOTE this struct must be defined as mutable one since it's used as a key of
    #      `ScopeStorage` dictionary and thus needs object identity
    const hasdefault::Bool # this field is necessary since isbitstype `default` field may be initialized with undefined value
    const default::T
    ScopedValue{T}() where T = new{T}(false)
    ScopedValue{T}(val) where T = new{T}(true, val)
    ScopedValue(val::T) where T = new{T}(true, val)
end

Base.eltype(::AbstractScopedValue{T}) where {T} = T

hasdefault(val::ScopedValue) = val.hasdefault
hasdefault(val::LazyScopedValue) = true

getdefault(val::ScopedValue) = val.hasdefault ? val.default : throw(KeyError(val))
getdefault(val::LazyScopedValue) = val.getdefault()

"""
    isassigned(val::ScopedValue)

Test whether a `ScopedValue` has an assigned value.

See also: [`ScopedValues.with`](@ref), [`ScopedValues.@with`](@ref), [`ScopedValues.get`](@ref).

# Examples
```jldoctest
julia> using Base.ScopedValues