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

inconsistent truncating behavior of converting <:Tuple constructors #52657

Open
nsajko opened this issue Dec 28, 2023 · 8 comments · May be fixed by #53265
Open

inconsistent truncating behavior of converting <:Tuple constructors #52657

nsajko opened this issue Dec 28, 2023 · 8 comments · May be fixed by #53265
Labels
domain:collections Data structures holding multiple items, e.g. sets kind:bug Indicates an unexpected problem or unintended behavior

Comments

@nsajko
Copy link
Contributor

nsajko commented Dec 28, 2023

julia> Tuple{Int}([3, 4])
(3,)

julia> Tuple{Int}((3, 4))
ERROR: MethodError: Cannot `convert` an object of type 
  Tuple{Int64{},Int64} to an object of type 
  Tuple{Int64{}}

  ...

Stacktrace:
 [1] _tuple_error(T::Type, x::Tuple{Int64, Int64})
   @ Base ./essentials.jl:409
 [2] convert(#unused#::Type{Tuple{Int64}}, x::Tuple{Int64, Int64})
   @ Base ./essentials.jl:416
 [3] Tuple{Int64}(x::Tuple{Int64, Int64})
   @ Base ./tuple.jl:364
 [4] top-level scope
   @ REPL[1]:1

julia> versioninfo()
Julia Version 1.9.4
Commit 8e5136fa297 (2023-11-14 08:46 UTC)
Build Info:
  Official https://julialang.org/ release
Platform Info:
  OS: Linux (x86_64-linux-gnu)
  CPU: 8 × AMD Ryzen 3 5300U with Radeon Graphics
  WORD_SIZE: 64
  LIBM: libopenlibm
  LLVM: libLLVM-14.0.6 (ORCJIT, znver2)
  Threads: 1 on 8 virtual cores
Environment:
  JULIA_NUM_PRECOMPILE_TASKS = 3
  JULIA_PKG_PRECOMPILE_AUTO = 0

It doesn't seem right for Tuple{Int}([3, 4]) to succeed (giving a truncated output, however), while Tuple{Int}((3, 4)) throws. IMO ideally both calls would throw, but I'm not sure if making that change would violate backwards compatibility.

The problem with Tuple{Int}([3, 4]) == (3,) is that (3,) == [3, 4] doesn't hold, in case it's not clear.

This is similarly silly: Tuple{}(1:10) == ().

What does any relevant documentation on constructors say? EDIT: there's no relevant documentation as far as I can tell, so I guess it wouldn't be breaking to make Tuple{Int}([3, 4]) and Tuple{}(1:10) throw.

@AmanDoesntCode

This comment was marked as off-topic.

@DilumAluthge
Copy link
Member

Yeah, it would make sense to me that both should throw.

@DilumAluthge DilumAluthge added kind:bug Indicates an unexpected problem or unintended behavior domain:collections Data structures holding multiple items, e.g. sets labels Dec 30, 2023
@jakobnissen
Copy link
Contributor

Related: #40495
Not quite a duplicate, because a resolution to this issue could be to allow the latter case.

@tpapp
Copy link
Contributor

tpapp commented Jan 19, 2024

I ran into this with NTuples (#52963, marked as a duplicate, thanks!) and I also agree that it should throw. Specifically, if the argument supports length (iterator, ::AbstractVector), length should match the number of elements in the Tuple.

But what to do about infinite iterators (IsInfinite())? Should they just silently take the first N elements, which is what currently happens? I think it would be cleaner to ask the user to Iterators.take first, but that may be breaking.

@nsajko
Copy link
Contributor Author

nsajko commented Jan 19, 2024

IMO, an infinite iterator is longer than any tuple, so trying to construct any type of tuple from an infinite iterator would ideally throw.

@nsajko
Copy link
Contributor Author

nsajko commented Jan 19, 2024

Should the exception be ArgumentError, DimensionMismatch, InexactError or a custom exception type?

@tpapp
Copy link
Contributor

tpapp commented Jan 19, 2024

AFAIK DimensionMismatch is inter-argument mismatch. I would go with ArgumentError and an informative message.

I agree about infinite objects throwing.

nsajko added a commit to nsajko/julia that referenced this issue Feb 9, 2024
Make tuple construction from overlong iterators throw instead of
truncating the input iterator.

Fixes JuliaLang#40495

Fixes JuliaLang#52657

Make tuple construction from known constant-length iterators inferrable
and prevent allocation.

Fixes JuliaLang#52993

Compute more accurate tuple element types in many cases using
`typeintersect`, with a fallback to the old behavior. This prevents
some cases of `convert` throwing due to ambiguity.

Instead of just calling `typeintersect` on the tuple types, do
`typeintersect` again once `fieldtype` computes the element type.

Fixes JuliaLang#53181

Separate the tuple construction from tuple element conversion, allowing
dropping the `tuple_type_tail` dependency.

Fixes JuliaLang#53182

Trying to construct a tuple from an infinite iterator now results in an
`ArgumentError` instead of in a `MethodError`.
@nsajko nsajko linked a pull request Feb 9, 2024 that will close this issue
nsajko added a commit to nsajko/julia that referenced this issue Feb 9, 2024
Make tuple construction from overlong iterators throw instead of
truncating the input iterator.

Fixes JuliaLang#40495

Fixes JuliaLang#52657

Make tuple construction from known constant-length iterators inferrable
and prevent allocation.

Fixes JuliaLang#52993

Compute more accurate tuple element types in many cases using
`typeintersect`, with a fallback to the old behavior. This prevents
some cases of `convert` throwing due to ambiguity.

Instead of just calling `typeintersect` on the tuple types, do
`typeintersect` again once `fieldtype` computes the element type.

Fixes JuliaLang#53181

Separate the tuple construction from tuple element conversion, allowing
dropping the `tuple_type_tail` dependency.

Fixes JuliaLang#53182

Trying to construct a tuple from an infinite iterator now throws an
`ArgumentError` instead of succeeding or throwing a `MethodError`.
nsajko added a commit to nsajko/julia that referenced this issue Feb 9, 2024
Make tuple construction from overlong iterators throw instead of
truncating the input iterator.

Fixes JuliaLang#40495

Fixes JuliaLang#52657

Make tuple construction from known constant-length iterators inferrable
and prevent allocation.

Fixes JuliaLang#52993

Compute more accurate tuple element types in many cases using
`typeintersect`, with a fallback to the old behavior. This prevents
some cases of `convert` throwing due to ambiguity.

Instead of just calling `typeintersect` on the tuple types, do
`typeintersect` again once `fieldtype` computes the element type.

Fixes JuliaLang#53181

Separate the tuple construction from tuple element conversion, allowing
dropping the `tuple_type_tail` dependency.

Fixes JuliaLang#53182

Trying to construct a tuple from an infinite iterator now throws an
`ArgumentError` instead of succeeding or throwing a `MethodError`.
nsajko added a commit to nsajko/julia that referenced this issue Feb 9, 2024
Make tuple construction from overlong iterators throw instead of
truncating the input iterator.

Fixes JuliaLang#40495

Fixes JuliaLang#52657

Make tuple construction from known constant-length iterators inferrable
and prevent allocation.

Fixes JuliaLang#52993

Compute more accurate tuple element types in many cases using
`typeintersect`, with a fallback to the old behavior. This prevents
some cases of `convert` throwing due to ambiguity.

Instead of just calling `typeintersect` on the tuple types, do
`typeintersect` again once `fieldtype` computes the element type.

Fixes JuliaLang#53181

Separate the tuple construction from tuple element conversion, allowing
dropping the `tuple_type_tail` dependency.

Fixes JuliaLang#53182

Trying to construct a tuple from an infinite iterator now throws an
`ArgumentError` instead of succeeding or throwing a `MethodError`.
nsajko added a commit to nsajko/julia that referenced this issue Feb 9, 2024
Make tuple construction from overlong iterators throw instead of
truncating the input iterator.

Trying to construct a tuple from an infinite iterator now throws an
`ArgumentError` instead of succeeding or throwing a `MethodError`.

Fixes JuliaLang#40495

Fixes JuliaLang#52657

Make tuple construction from known constant-length iterators inferrable
and prevent allocation.

Fixes JuliaLang#52993

Compute more accurate tuple element types in many cases using
`typeintersect`, with a fallback to the old behavior. This prevents
some cases of `convert` throwing due to ambiguity.

Instead of just calling `typeintersect` on the tuple types, do
`typeintersect` again once `fieldtype` computes the element type.

Fixes JuliaLang#53181

Separate the tuple construction from tuple element conversion, allowing
dropping the `tuple_type_tail` dependency.

Fixes JuliaLang#53182
nsajko added a commit to nsajko/julia that referenced this issue Feb 9, 2024
Make tuple construction from overlong iterators throw instead of
truncating the input iterator.

Trying to construct a tuple from an infinite iterator now throws an
`ArgumentError` instead of succeeding or throwing a `MethodError`.

Fixes JuliaLang#40495

Fixes JuliaLang#52657

Make tuple construction from known constant-length iterators inferrable
and prevent allocation.

Fixes JuliaLang#52993

Compute more accurate tuple element types in many cases using
`typeintersect`, with a fallback to the old behavior. This prevents
some cases of `convert` throwing due to ambiguity.

Instead of just calling `typeintersect` on the tuple types, do
`typeintersect` again once `fieldtype` computes the element type.

Fixes JuliaLang#53181

Separate the tuple construction from tuple element conversion, allowing
dropping the `tuple_type_tail` dependency.

Fixes JuliaLang#53182
@nsajko
Copy link
Contributor Author

nsajko commented May 30, 2024

Analogous issue for NamedTuple:

julia> (@NamedTuple{})(1:3)
NamedTuple()

julia> (@NamedTuple{})((10, 20))
ERROR: ArgumentError: Wrong number of arguments to named tuple constructor.
Stacktrace:
 [1] @NamedTuple{}(args::Tuple{Int64, Int64})
   @ Base ./namedtuple.jl:117
 [2] top-level scope
   @ REPL[2]:1

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
domain:collections Data structures holding multiple items, e.g. sets kind:bug Indicates an unexpected problem or unintended behavior
Projects
None yet
Development

Successfully merging a pull request may close this issue.

5 participants