Identifier and StringAttr essentially serve the same purpose,
i.e. to hold a string value. Keeping these seemingly identical
pieces of functionality separate has caused problems in certain situations:
- Identifier has nice accessors that StringAttr doesn't
- Identifier can't be used as an Attribute, meaning strings are often duplicated between Identifier/StringAttr (e.g. in PDL)
The only thing that Identifier has that StringAttr doesn't is support
for caching a dialect that is referenced by the string (e.g. dialect.foo).
This functionality is added to StringAttr, as this is useful for StringAttr
in generally the same ways it was useful for Identifier.