Not registering a new type with the dialect in MLIR results in error "LLVM ERROR: can't create type... because storage uniquer isn't initialized: the dialect was likely not loaded."

Hello.
I would like to report how I solved a strange parser issue I encountered last week on which I spent more than 1 day.
During this time I tried to figure out why the parser was silently failing at OpAsmParser::parseTypeList().
I had added a new SectionType type in my new MLIR dialect and my specified assemblyFormat in TableGen was basically:
let assemblyFormat = [{
attr-dict
-> type(results)
}];

Since I was using the release version of my MLIR project, I decided to build the debug version to be able to use GDB on it.
After building the debug version of my project, when I ran the compiler on my input it provided the following error:
  "LLVM ERROR: can't create type 'MyType' because storage uniquer isn't initialized: the dialect was likely not loaded."
Therefore, I checked if I am registering my dialect with the DialectRegistry::insert() method.

Spent also about 1 hour to debug with gdb --tui my compiler project, but wasn't able to figure out why my compiler says when it fails that the storage uniquer isn't initialized.

In the end it turned out, with some help, after more than 1 day of work, that I forgot to register my new type in Dialect::Initialize() with the addTypes<>() function.
Now, it is true that information about registering a new type with its dialect can be found at least in these 2 documents:
    - https://mlir.llvm.org/docs/Tutorials/DefiningAttributesAndTypes/#registering-types-with-a-dialect
    - https://mlir.llvm.org/docs/Tutorials/Toy/Ch-7/#defining-the-type-class-2
But I didn't remember about these documents and I forgot to register the new type with the dialect, hence all my trouble for more than 1 day.

Even if it might be a small detail, I'm wondering if it's possible to change this error message that I received, which comes from the source file llvm/mlir/include/mlir/IR/TypeSupport.h:
  "LLVM ERROR: can't create type 'MyType' because storage uniquer isn't initialized: the dialect was likely not loaded."
 to say also that the error might be also because the type was not registered with the dialect.

Anyhow, I hope this will help others with similar issues with mine.

Best regards,
  Alex

I wonder if we can do better than your suggestion even. Theoretically, we should know if the dialect was loaded, but not the type. Can we give a different error in that case?

Note: I haven’t looked at the code, so no idea how feasible this would be in practice

Pushed Improve fatal error message when an Attribute or Type wasn't initiali… · llvm/llvm-project@d0d991c · GitHub to improve the error message for now.

If would be possible if the Type and Attribute concrete implementation would have something like using dialect = MyDialect; or something like that that could be queried, but it’s not the case right now.
The only thing we have access to is:


  class NoneType : public ::mlir::Type::TypeBase<NoneType, ::mlir::Type, ::mlir::TypeStorage> {
  public:
    /// Inherit some necessary constructors from 'TypeBase'.
    using Base::Base;

    static NoneType get(MLIRContext *context);
  
  };

And keep in mind that this happens before the instance is created (in the static method, so no this->getDialect() is possible).

Yeah this error is probably getting thrown further down in the stack, but the parser at least should know the dialect because it just parsed the dialect prefix. Not sure if propagating that information is infeasible.

(Alex’s original suggestion seems like an easy win though :slightly_smiling_face:)

I don’t think you can ever get there when parsing the attribute and the dialect isn’t registered/loaded.

This is thrown when the type or attribute is programmatically created, that is when you write a pass doing NoneType::get(ctx);. During parsing, you would get this error only in the case reported here: the dialect is loaded, the code to parse the attribute (or type) exists and calls MyAttr::get() which then traps…

Well in that case we should certainly know that it’s the latter case if we hit this during parsing. I wonder if we can propagate that information

It isn’t in control of the framework, the calls to MyAttr::get() is in custom C++ code in the client dialect.

That said @Mogball declarative assembly for Types and Attributes could be safer here and have better diagnostics!