Summary#
Every app has the Osyrin core namespace in scope with no using to write, and that namespace exports 70
type names, many of them ordinary English words: Group, Match, Point, Month, Now,
Uri, Connection, Failure, Position, Display, Cursor, Pending, Visitor …
A capability you use brings its own names in on top — Slot from Osysharp.Workflow, Schedule from
Osysharp.Scheduling — and they shadow exactly the same way. The note tells you which of the two you are reading:
for a core name it says "in scope in every app", for an imported one it names the using that brought it. (The
using may sit in another file of the app — it is the APP's imports that decide, and the note is attached to the
declaration, which is where you can act on it.)
Declaring your own type with one of those names is legal, and yours wins. A bare Slot anywhere in your app
means your Slot, in every position — a property type, a local, a parameter, a cast, an enum member access. The
compiler says so once, as a note at the declaration (INFO, not a warning — nothing is broken and nothing is
owed), and the platform's type stays reachable by its full name (Osysharp.Workflow.Slot). Nothing needs renaming: if
Slot is the word your domain uses, keep it.
The one exception is the thirteen built-in type names (DateTime, Json, Geography …) — see [[#built-ins]]. They
have no full spelling, so a ROOT type of yours named after one is unreachable and the remedy is to rename; one in a
namespace of yours wins inside that namespace, as C#.
Signature#
enum Slot { Morning, Afternoon } // legal — and a bare `Slot` now means THIS one, everywhere
Osysharp.Workflow.Slot // the platform's, still reachable, by its full nameDescription#
What happens if I name my type after a platform one?#
Yours wins — the same rule C# uses. The name you declare in your own app is nearer than a name that arrived from an import, so it is the one a bare spelling binds to. That holds in every position; there is no corner where the platform's type quietly comes back.
What the compiler owes you is to say it, and it does — once, on the declaration:
model.osy:1 INFO TYPE_SHADOWS_ALWAYS_IN_SCOPE `enum Slot` has the same name as 'Osysharp.Workflow.Slot',
which this app imports (`using Osysharp.Workflow;`). YOURS WINS: a bare `Slot` anywhere in this
app means this enum, and 'Osysharp.Workflow.Slot' can only be reached by its full name from here on.That is the whole cost of the collision: a diagnostic that mentions Slot may be talking about either type, so you
need to know which one you are reading. There is nothing to accept and nothing to write down — just write the app you
meant to write:
// `Slot` is the workflow runtime's, so this page takes that capability: there is nothing to SHADOW in an app
// that does not carry it. (It became opt-in in 2026-09; before that every app had `Slot` with no `use` at all,
// which is why the examples below were written without this line.)
using Osysharp.Workflow;
enum Slot { Morning, Afternoon, Evening }
entity Booking {
[Required, MaxLength(120)] string Guest;
Slot Period; // the property type binds to the enum above…
}
Slot PeriodOf(Booking b) {
Slot pick = Slot.Morning; // …and so does the local, and the member access
return b.Period == pick ? pick : b.Period;
}Can a field be named after its own type?#
Naming a field after the type it holds is ordinary, and it works:
component Screen() {
Valley valley = new Valley(); // the field is named after its own type
on frame (double dt) {
valley.Paint(); // this is the FIELD, not a static call on the type
}
}A value in scope — a local, a parameter, a class field or a component member — shadows a type of the same name,
so valley.Paint() is a call on the object you are holding. To reach a static member of the type while a value
shadows it, see [[#qualifying]].
My variable has the same name as my entity — which wins?#
Your declaration wins, for as long as it is in scope, and it is decided by its declared TYPE — never by how the name is spelled. This is the other axis of the same question, and the same C# answer: a local shadows a type name in its block, and nobody finds that surprising.
Every binder shadows: a local, a foreach variable, a lambda's range variable, a function parameter, a class
field read through implicit this, and a component's parameters and members read inside an action or method
body. The entity is untouched everywhere the name is not taken — shadowing hides a name, it does not remove one.
entity Ticket { [Required, MaxLength(80)] string Subject; }
class Envelope {
public List<string> Ticket; // a field named after the entity…
public int Held() { return Ticket.Take(100).Count; } // …so this counts the FIELD's strings
}
int InTheStore() { return Ticket.Take(100).Count; } // nothing shadows it here — the TABLEThat matters most for a name you did not choose. A capability you use ships components whose parameters were
named without knowing your model — the UI kit alone has item, user, entry, row — and you cannot rename
them. They bind to their own declarations, whatever your app calls its entities.
And the spelling has to match exactly. Osy# is case-sensitive, as C# is, so ticket does not name Ticket and
never silently reads it:
model.osy:7 ERROR RESOLVE_ERROR unknown identifier 'ticket'. Did you mean 'Ticket'?Which names are already taken?#
All 181, by the namespace each comes from. Taking one costs you a one-line note and nothing else — this is a list to recognise a diagnostic by, not a list to avoid.
| Namespace | Names |
|---|---|
Osyrin (142) | ActionChoice · ActionEffects · ActionInfo · ActionOutcome · ActionParameter · ActionParameterKind · ActionResult · ActionState · ActionValue · AggregateException · Align · AlignSelf · Allowance · AllowanceState · AnimationTimeline · ApiResponse · ArgumentException · ArgumentNullException · ArgumentOutOfRangeException · ArithmeticException · BgSize · BorderStyle · CameraFacing · CompareOptions · ConflictException · ConnState · Connection · ContainerType · Cursor · DataTranslation · DateTimeKind · DateTimeStyles · DayOfWeek · Device · DeviceUnavailableException · Display · DivideByZeroException · DragAxis · EdgeFade · EmailInlineImage · EmailNode · Event · EventDelivery · EventInfo · EventProblemKind · Exception · ExternalServiceException · Failure · FieldSizing · FlowDirection · FontStyle · FontVariant · FormatException · GridAutoFlow · Ground · Group · GroupCollection · HeadTag · HttpHeader · IDisposable · IndexOutOfRangeException · InvalidCastException · InvalidOperationException · JsonException · JsonIgnoreCondition · JsonLd · JsonSerializerOptions · Justify · KeyNotFoundException · Match · MidpointRounding · Mirror · MixBlendMode · Month · Navigation · NavigationRoute · NormalizationForm · NotAuthorized · NotFoundException · NotImplementedException · NotSupportedException · Now · NullReferenceException · OAuthConnectionFailedException · ObjectFit · OperationCanceledException · OutlineStyle · Overflow · OverflowException · ParallelOptions · Pending · Personal · PlatformNotSupportedException · Point · PointerEvents · Position · RaisedEventState · RecordField · RecordFieldKind · Redirect · RenderedEmail · RequirementsNotMet · Resize · ScrollBehavior · ScrollSnapAlign · ScrollSnapType · ScrollbarWidth · SecretSetDestination · SecretSetResult · SemaphoreFullException · StringComparison · StringSplitOptions · TaskCanceledException · TaskStatus · TextAlign · TextDecoration · TextOverflow · TextTransform · TextWrap · TimeBucket · TimeZoneNotFoundException · TimeoutException · TranslationText · Type · TypeCode · UiRole · UiSort · Uri · UriFormatException · UserSelect · Validation · ValidationException · VerticalAlign · Violation · Visibility · Visitor · WhiteSpace · WordBreak · WorkflowCancelled · WorkflowError · WorkflowRunInfo · Wrapping |
Osysharp.Workflow (24) | AuditKind · CorrelationOutcome · FlowMetrics · Leg · Losers · RequirementStatus · Saga · SlaKind · Slot · SlotStatus · SlotView · StateTime · TransitionView · WorkflowAuditEntry · WorkflowGraph · WorkflowRun · WorkflowRunEnd · WorkflowRunEnded · WorkflowRunMoved · WorkflowRunStarted · WorkflowRunStatus · WorkflowRunSummary · WorkflowStateInfo · WorkflowTransitionInfo |
Osysharp.ServiceHours (3) | ServiceException · ServiceHours · ServiceWindow |
Osysharp.Markdown (1) | MarkdownDocument |
Osysharp.Scheduling (11) | Schedule · ScheduleExclusion · ScheduleFrequency · ScheduleOccurrenceOutcome · ScheduleOverlap · ScheduleRule · ScheduleRuleMonth · ScheduleRuleMonthDay · ScheduleRuleTime · ScheduleRuleWeekday · ScheduleStatus |
A capability you use brings more names in (the UI kit's controls, for instance). Those follow the same rule and
raise the same note.
How do I still reach the platform's type?#
By its full name, which is what the note prints. There is nothing else to configure:
Guid DefinitionOf(Osysharp.Workflow.Slot s) {
return s.Definition; // the PLATFORM's Slot — spelled in full
}
Slot MyDefault() { return Slot.Morning; } // …and a bare `Slot` is still yoursIf you ever see a diagnostic like cannot assign 'Slot' to 'Slot' (type 'Osysharp.Workflow.Slot'), it now carries a
note saying that the two words are two different types and which one the bare spelling means. That is this rule
speaking at a use site.
Which thirteen names are built in?#
The built-in types are not in a namespace and have no full spelling of their own. A type of yours in the root namespace named after one is unusable: the built-in keeps the bare name — if yours took it, the built-in would be unreachable from the whole app — so the declaration looks fine and the failure lands later, at a use site.
Culture · DateOnly · DateTime · DateTimeOffset · Geography · Guid · Json · Markdown · RichText ·
TimeOnly · TimeSpan · TimeZoneInfo · Vector
model.osy:1 WARNING TYPE_SHADOWS_ALWAYS_IN_SCOPE `enum TimeZoneInfo` has the same name as the BUILT-IN type `TimeZoneInfo` …
THE BUILT-IN WINS: built-in types resolve ahead of everything an app declares, so a bare `TimeZoneInfo` never
means this enum — and there is no qualified name that reaches it either, so this enum is unusable.Rename yours. [SuppressWarning] silences the warning but not the problem — the type stays unreachable. The full
set of built-in types is Every type, in one list; the ones an entity may store are in entity members.
Inside a namespace of your own, yours wins there — as C# resolves it. public entity Markdown in
namespace Acme.Lighting; is Acme.Lighting.Markdown, and inside Acme.Lighting and every namespace under it a bare
Markdown means it — as a member's type, a parameter, a local, a cast. Everywhere else the bare Markdown is still the
built-in, and the full name Acme.Lighting.Markdown reaches yours from anywhere. The compiler still warns at the
declaration, because the same word now means two things in one app:
model.osy:3 WARNING TYPE_SHADOWS_ALWAYS_IN_SCOPE `entity Markdown` has the same name as the BUILT-IN type
`Markdown`. Inside `Acme.Lighting` (and the namespaces under it) a bare `Markdown` means
`Acme.Lighting.Markdown`, as C# resolves a name to the enclosing namespace first; everywhere else it is
the BUILT-IN `Markdown`. …Markdown is on this list although its storage needs use Osysharp.Markdown;: that capability decides where a value
is written, not what the word means.
If you would rather have no collision at all#
You do not have to do anything: the namespace collision is a note, so no gate counts it and nothing fails. If you would rather the two names never met, there are two ways out — rename your type, or put it in a namespace of its own, which gives it a full name and stops it shadowing anything.
[SuppressWarning("TYPE_SHADOWS_ALWAYS_IN_SCOPE")] still works on the declaration if you simply want the line gone
(see [SuppressWarning]), but it is no longer what the compiler suggests: a note asks for nothing, so
there is nothing to put down. It IS the right tool for the built-in half above, where the warning is real.
See also#
- Every type, in one list — every built-in type in one list
- namespace —
namespace X;, and why a namespaced type shadows nothing - entity members — which of these types an entity member may hold
- [SuppressWarning] —
[SuppressWarning("CODE")], and where it may sit