From 1d0fb1e7507a5c08a9c4a1ec0e72a7ca87c4bb30 Mon Sep 17 00:00:00 2001 From: Matthew Fishman Date: Tue, 21 Jul 2026 15:51:15 -0400 Subject: [PATCH] Give `AbstractNamedTensor` a generic `dimnametype` default `dimnametype` fell back to `Any` for any `AbstractNamedTensor` subtype that did not define its own method, so `NamedTensorOperator` reported `Any` even though it carries its dimname type as a parameter. That broke factorizations that mint a fresh bond name on an operator (`qr_compact`, `svd`, and friends), which minted the new name from `Any`. Since `AbstractNamedTensor{DimName}` already carries the dimname type, the default reads it from the supertype, covering every subtype uniformly and subsuming the per-type methods on `NamedTensor` and `SymbolicNamedTensor`, which are removed. The `Any` fallback remains for a fully unparameterized `AbstractNamedTensor`. Co-Authored-By: Claude Opus 4.8 (1M context) --- Project.toml | 2 +- src/abstractnamedtensor.jl | 3 ++- src/lazyitensors/symbolicitensor.jl | 1 - src/namedtensor.jl | 2 -- test/test_basics.jl | 10 +++++++--- 5 files changed, 10 insertions(+), 8 deletions(-) diff --git a/Project.toml b/Project.toml index 6499f65..0adb7f2 100644 --- a/Project.toml +++ b/Project.toml @@ -1,6 +1,6 @@ name = "ITensorBase" uuid = "4795dd04-0d67-49bb-8f44-b89c448a1dc7" -version = "0.13.0" +version = "0.13.1" authors = ["ITensor developers and contributors"] [workspace] diff --git a/src/abstractnamedtensor.jl b/src/abstractnamedtensor.jl index ff3a9a0..8ed058b 100644 --- a/src/abstractnamedtensor.jl +++ b/src/abstractnamedtensor.jl @@ -79,7 +79,8 @@ Symbol """ function dimnametype end dimnametype(a::AbstractNamedTensor) = dimnametype(typeof(a)) -dimnametype(type::Type{<:AbstractNamedTensor}) = Any +dimnametype(::Type{<:AbstractNamedTensor{DimName}}) where {DimName} = DimName +dimnametype(::Type{<:AbstractNamedTensor}) = Any # Unwrapping the names (named-array interface). # TODO: Use `IsNamed` trait? diff --git a/src/lazyitensors/symbolicitensor.jl b/src/lazyitensors/symbolicitensor.jl index cc6ebad..6ea2f2b 100644 --- a/src/lazyitensors/symbolicitensor.jl +++ b/src/lazyitensors/symbolicitensor.jl @@ -23,7 +23,6 @@ dimnames(a::SymbolicNamedTensor) = getfield(a, :dimnames) function Base.axes(a::SymbolicNamedTensor) return named.(Tuple(Base.OneTo.(getfield(a, :size))), Tuple(getfield(a, :dimnames))) end -dimnametype(::Type{<:SymbolicNamedTensor{DimName}}) where {DimName} = DimName Base.ndims(a::SymbolicNamedTensor) = length(getfield(a, :dimnames)) function Base.:(==)(a::SymbolicNamedTensor, b::SymbolicNamedTensor) diff --git a/src/namedtensor.jl b/src/namedtensor.jl index dbba7ea..c8ad977 100644 --- a/src/namedtensor.jl +++ b/src/namedtensor.jl @@ -69,8 +69,6 @@ dimnames(a::NamedTensor) = a.dimnames unnamed(a::NamedTensor) = a.unnamed Base.parent(a::NamedTensor) = unnamed(a) -dimnametype(::Type{<:NamedTensor{DimName}}) where {DimName} = DimName - # The parent array is erased at the field level, so its concrete type is not part # of `NamedTensor`'s signature. An instance still carries the parent, so the instance # methods recover the concrete type while the type methods report `AbstractArray`. diff --git a/test/test_basics.jl b/test/test_basics.jl index 834a994..3d69f5f 100644 --- a/test/test_basics.jl +++ b/test/test_basics.jl @@ -1,8 +1,8 @@ using ITensorBase: ITensorBase, AbstractNamedTensor, ITensor, Index, IndexName, NamedTensor, commonind, commoninds, dimnametype, gettag, hascommoninds, hastag, id, inds, mapinds, - name, named, noncommonind, noncommoninds, noprime, plev, prime, replaceinds, setplev, - settag, sim, tags, trycommonind, trynoncommonind, tryuniqueind, unioninds, uniqueind, - uniqueinds, uniquename, unname, unnamed, unsettag, uuid + name, named, noncommonind, noncommoninds, noprime, operator, plev, prime, replaceinds, + setplev, settag, sim, tags, trycommonind, trynoncommonind, tryuniqueind, unioninds, + uniqueind, uniqueinds, uniquename, unname, unnamed, unsettag, uuid using Test: @test, @test_broken, @test_throws, @testset using UUIDs: UUID @@ -172,6 +172,10 @@ using UUIDs: UUID @test dimnametype(a) === IndexName @test dimnametype(typeof(a)) === IndexName @test dimnametype(NamedTensor{IndexName}) === IndexName + # An operator reports the dimname flavor of its underlying tensor. + op = operator(a, (name(i),), (name(j),)) + @test dimnametype(op) === IndexName + @test dimnametype(typeof(op)) === IndexName # Unparameterized `NamedTensor` does not fix its dimname flavor, like `eltype(Array)`. @test dimnametype(NamedTensor) === Any end