Osy#betaRun it on Osyrin: osyrin.com

Reference / Types

When your name is already the platform's

enum Slot { … } // yours wins · write 'Osysharp.Workflow.Slot' in full for the platform's

The platform puts 70 ordinary English words in scope in every app with no `using` — `Group`, `Match`, `Point`, `Month`, `Now`, `Uri`, `Connection`, `Position`, `Display` … and a capability you `use` brings more (`Slot`, `Schedule`). Declaring your own type with one of those names is LEGAL and YOURS WINS everywhere; the compiler NOTES it once, at the declaration, and the platform's type is still reachable by its full name. Nothing is owed and there is nothing to suppress. Thirteen names are the exception — the built-in types — and those you cannot take, so those are a warning.

stable3 examples compiled by CItypesnamingresolutiondiagnostics

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 name

Description#

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 TABLE

That 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.

NamespaceNames
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 yours

If 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#

Related

namespace

Declares the namespace a file's types belong to, written once at the top of the file. It is optional — a file without…

Every type, in one list

The complete vocabulary of built-in types — the scalars you can store, the collections, the two callable spellings…

type visibility (public / internal)

A top-level declaration carries a public or internal visibility that decides whether code outside its package can name…

entity members

The typed members an entity holds — text, numbers, dates, booleans, Guids, enums and references. A member's type…

enum

A fixed set of named values, used as a member type. Stored as a number by default, or as the member's own name with…

[SuppressWarning]

Accept ONE named warning about ONE declaration. Put it on whatever the finding is reported against — a function, an…