The upcast would not necessarily fail. When NH loads an object within an inheritance hierarchy from the DB, it loads it into its proper type. If it is saved as a Participant, it is loaded thereas; likewise User. In the example you cite, obviously a User reference can reference a Participant.
So, if you were doing a load from the database of a User without any foreknowledge of the subclass, you would want to "question" the object for its type before attempting such a cast:
Code:
if ( user is Participant ) { ... }
NH has to load the object as it was saved, into it's proper class. In order to do this, it has to figure out what that is. For the joined-subclass strategy (for the time being, until mixed strategies are supported) this requires an outer join to every table in the hierarchy to determine the subclass. This is why the docs list the table-per-hierarchy strategy (which uses a discriminator) as much more performant.
I guess the question would be: if this is so unacceptable, what behavior do you imagine would be preferable?