Osy#betaa language · its runtime Osyrin · a hosted platform
Why Osy#Built for agentsAgents as declarationsWorkflows that waitRuns exactly onceSecure by defaultNothing to mockThe editor is the compilerUI in the languageDocuments are dataOne program

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 82 ordinary English words in scope in every app with no `using` — `Slot`, `Group`, `Match`, `Point`, `Month`, `Now`, `Uri`, `Connection`, `Position`, `Display` … 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. Eleven 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 82 type names, many of them ordinary English words: Slot, Group, Match, Point, Month, Schedule, Now, Uri, Connection, Failure, Position, Display, Cursor, Pending, Visitor

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 eleven built-in type names (DateTime, Json, Zone …) — see [[#built-ins]]. Those resolve ahead of everything an app declares and have no full spelling, so a type of yours named after one is unreachable. The compiler warns about those too, and there the remedy is to rename.

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 is in scope in every app with no `using` to write. 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:

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 82, 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 (51)ActionState · Align · AlignSelf · BgSize · BorderStyle · ConnState · Connection · Cursor · DayOfWeek · Display · DragAxis · Failure · FieldSizing · FontVariant · GridAutoFlow · Group · GroupCollection · Justify · MarkdownDocument · Match · MixBlendMode · Month · Navigation · NavigationRoute · Now · ObjectFit · OutlineStyle · Overflow · Pending · Point · PointerEvents · Position · Resize · ScrollBehavior · ScrollbarWidth · TextAlign · TextDecoration · TextOverflow · TextTransform · UiRole · UiSort · Uri · UserSelect · Validation · VerticalAlign · Violation · Visibility · Visitor · WhiteSpace · WordBreak · Wrapping
Osysharp.Workflow (20)AuditKind · CorrelationOutcome · FlowMetrics · Leg · Losers · RequirementStatus · Saga · ServiceException · ServiceHours · ServiceWindow · SlaKind · Slot · SlotStatus · SlotView · StateTime · TransitionView · WorkflowAuditEntry · WorkflowRun · WorkflowRunStatus · WorkflowRunSummary
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.

The eleven names you cannot have#

The built-in types are not in a namespace — they are resolved first, ahead of everything an app declares, and there is no qualified spelling that could reach past them. So a type of yours named after one is unusable: the declaration itself looks fine, and the failure lands later, at a use site.

DateTime · DateOnly · TimeOnly · TimeSpan · Guid · Json · RichText · Markdown · Vector · Zone · Culture

model.osy:1  WARNING  TYPE_SHADOWS_ALWAYS_IN_SCOPE  `enum Zone` has the same name as the BUILT-IN type `Zone` …
             THE BUILT-IN WINS: built-in types resolve ahead of everything an app declares, so a bare `Zone` 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.

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 type carries a public or internal visibility that decides whether code outside its namespace can name it…

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…