Skip to content

"Slicing" due to type unstable parametric type construction #30335

@jagot

Description

@jagot

I'm seeing something that reminds me a little bit about type slicing in C++; I'm trying to generate term symbols (https://en.wikipedia.org/wiki/Term_symbol) from their string representation. I have this type

struct Term{I<:Integer,R<:Rational{I},LT<:Union{I,R}}
    L::LT
    S::R
    parity::I
end

The creation of a Term from a string is accomplished with (input error checks removed)

spectroscopic="spdfghiklmnoqrtuv"

function term_string(s::AbstractString)
    m = match(r"([0-9]+)([A-Z]|\[[0-9/]+\])([oe ]{0,1})", s)
    L = lowercase(m[2])
    L = if L[1] == '['
        L = strip(L, ['[',']'])
        if occursin("/", L)
            Ls = split(L, "/")
            Rational(parse(Int, Ls[1]),parse(Int, Ls[2]))
        else
            parse(Int, L)
        end
    else
        findfirst(L, spectroscopic)[1]-1
    end
    S = (parse(Int, m[1]) - 1)//2
    Term(L, S, m[3] == "o" ? -1 : 1)
end

Input 1S should yield Term.L=0, 1[5] => Term.L=5, 1[3/2] => Term.L=3//2 (rational). The last one however, results in

Term{Int64,Rational{Int64},Int64}
  L: Int64 3
  S: Rational{Int64}
    num: Int64 2
    den: Int64 0
  parity: Int64 1

where it can be seen that the type of L was not correctly inferred, and 3//2 was split such that the numerator ended up in L and the denominator in S.num, etc.

This works as it should on Julia v1.0.2, but not on nightly 1bd316b. I can make it work on nightly by either

  • declaring const spectroscopic="spdfghiklmnoqrtuv" (which is the sane thing to do anyway), or
  • replacing the last line in term_string with Term{Int,Rational{Int},typeof(L)}(L, S, m[3] == "o" ? -1 : 1)

I tried to bisect using the following scripts:

#!/bin/bash
make || make clean && make || make clean && exit 125 # If build fails, we cannot test it
./julia term-test.jl || exit 1

term-test.jl:

using Test

struct Term{I<:Integer,R<:Rational{I},LT<:Union{I,R}}
    L::LT
    S::R
    parity::I
end

spectroscopic = "spdfghiklmnoqrtuv"

function term_string(s::AbstractString)
    m = match(r"([0-9]+)([A-Z]|\[[0-9/]+\])([oe ]{0,1})", s)
    println(m)
    L = lowercase(m[2])
    L = if L[1] == '['
        L = strip(L, ['[',']'])
        if occursin("/", L)
            Ls = split(L, "/")
            Rational(parse(Int, Ls[1]),parse(Int, Ls[2]))
        else
            parse(Int, L)
        end
    else
        findfirst(L, spectroscopic)[1]-1
    end
    S = (parse(Int, m[1]) - 1)//2
    Term(L, S, m[3] == "o" ? -1 : 1)
end

@test term_string("1S") == Term(0, 0//1, 1)
@test term_string("1[5]") == Term(5, 0//1, 1)
@test term_string("1[3/2]") == Term(3//2, 0//1, 1)

but I end up with the unsatisfactory result

There are only 'skip'ped commits left to test.
The first bad commit could be any of:
1bd316b972cb4ef83b9b8e79f435cc4d59029a93
bd21aa75eb4c0e56ef870f6bffea3281c724cbb1
We cannot bisect more!
bisect run cannot continue any more

Metadata

Metadata

Assignees

Labels

bugIndicates an unexpected problem or unintended behaviortypes and dispatchTypes, subtyping and method dispatch

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions