Let's say that I'm making a chess system that should work for various nonstandard pieces. To do that, I'd make a trait Piece with some methods. Because some users would just want to play a game of standard chess, I would create a mod standard with a type for standard chess pieces. The logical type name for the standard chess piece type in mod standard would be Piece... which is the exact same as the trait name!
Is there a good system for resolving this issue? What I've looked at:
Making the trait's name be a verb and the type's name a noun: works well, but can't always be done.
Naming them after synonymous nouns: this just feels wrong and seems like it could easily cause mistakes.
Just having them use the same name: this makes the type and trait very annoying to use together.
Have the type specify in the name what kind it is, for example standard::StandardPiece. This feels awkward and seems to be bad practice.
What I'm actually making is similar to this but for another board game, and the exact naming issue that I'm trying to fix has been solved by existing implementations by having a one-size-fits-all type that contains a String, eliminating the trait entirely. I also don't like that solution because it could use a simple enum instead so using a String is wasteful.
If there is no obvious better name, use the obvious straightforward names, i.e. Piece for both. There is precedent: for example, std::io::Error is a type that implements the trait std::error::Error, and there are many other types named Error. This does not usually cause much confusion.
Note that any given module will be either generic, or specific to one rule-set, but usually not both, so it will be using only one of the Piece names, not both. In order to use Piece trait methods while being specific to standard::Piece, you can import a trait for its methods without importing its name:
use crate::Piece as _;
use crate::standard::Piece;
In the module defining enum Piece you can use the trait by qualified path:
Thank you! The tip on being able to use a trait as _ to use that trait's methods was very useful for the one place where I did actually need both the trait methods and the specific type (unit tests) (edit: the crossed out part doesn’t fully make sense because users would also need to do this somewhat frequently). It also does seem like it would be very unlikely for any particular module to need to name both the type and the trait.