cmajor-lang/cmajor

castToRefSkippingReferences error passing std::notes in struct init

Closed this issue · 4 comments

Minimum Reproduction Steps

  • Define a struct that has a std::notes::NoteOn member.
  • Initialize the struct using the “parenthesized list of member values” form
    • Note it’s not necessary to actually pass a value with the parens. Using empty parens to get the default zero’d values still causes the error.
  • Run the patch. Note the error:

    error: Internal compiler error: "castToRefSkippingReferences:87"

processor Untitled  [[ main ]]
{
  output stream float out;
  struct NoteStruct 
  {
    std::notes::NoteOn note;
  }

  void main() 
  {
    let s = NoteStruct(); //> error: Internal compiler error: "castToRefSkippingReferences:87"
    advance();
  }
}

Of Note

This doesn’t seem to be a general problem with structs in structs. If I make my own nominally equivalent NoteOn struct, there’ no error:

processor Untitled  [[ main ]]
{
  output stream float out;
  struct MyNote 
  {
    int32 channel;
    float32 pitch;
    float32 velocity;
  }
  struct NoteStruct 
  {
    MyNote note;
  }

  void main() 
  {
    let s = NoteStruct(); //> No error.
    advance();
  }
}

Workarounds

This only affects initializing struct members via a parenthesized list. Creating a struct and/or directly assigning values works fine:

    NoteStruct s;
    s = NoteStruct(n); //> Error.

    NoteStruct s;
    s.note = n; //> No error.

Actually, maybe this is a namespace lookup thing? Given this code:

processor Untitled  [[ main ]]
{
  output stream float out;
  struct NoteStruct 
  {
    NotARealThing note;
  }

  void main() 
  {
    let s = NoteStruct();
    advance();
  }
}

I’d expect it to emit

Cannot find symbol 'NotARealThing'

But instead I get the same

error: Internal compiler error: "castToRefSkippingReferences:87"

Seems like I get this error for any symbol that’s not in the same namespace as the caller — even if it doesn’t exist.

Yes, looks like an interesting failure case, i'll investigate further

What's going on here is the constant folder is tripping up, as the type is not yet resolved, but it's attempting to check the types of the members too early. This is being triggered by the declaration using the function call type notation. If you change the code to:

processor Untitled  [[ main ]]
{
    output stream float out;
    struct NoteStruct
    {
        std::notes::NoteOn note;
    }

    void main()
    {
        NoteStruct s;
        advance();
    }
}

it works.

The fix is to ensure the type is resolved before attempting to visit the member types. I'll add a test and a fix for this

Fix merged: e94e46d