Skip to content

Expected-Type Shorthand

Accepted

Accepted for V1 leading-dot members and contextual aggregate literals.

Some expressions intentionally omit an owner type and are completed from the expected type of their expression position.

Expected-type shorthand is not ordinary name lookup. Sema first determines a unique expected type for the position, then resolves the shorthand against that type. If no unique expected type is available, the shorthand is invalid unless the specific form defines another completion rule.

Expected Type Sources

An expected type may come from:

  • an explicit local declaration annotation
  • a function or attribute parameter type
  • an explicit function return type
  • an aggregate field type
  • another type-checked expression form that supplies a required operand type

Expected types flow only through positions whose surrounding syntax already commits to a type. They do not let a shorthand expression choose among unrelated APIs, overloads, or namespaces.

Leading-Dot Members

.name resolves against the expected type.

If the expected type is CallConv, then .c is sugar for:

CallConv.c

Example:

@callconv(.c)

The @callconv provider declares the type expected for its first argument, so .c resolves as the c case of that type. It is not a string, not a local binding, and not a global name lookup.

The same shorthand is used by C interop attributes with their own expected enum domain:

@export(.c)
@extern(.c)

For these attributes, .c resolves as InteropAbi.c, not CallConv.c.

Leading-dot members are valid for enum cases, error cases, and other case-like comptime values whose owner is supplied by the expected type. If the expected type has no matching visible case, sema reports a member-resolution error on the expected type.

For enum unions, the shorthand must resolve to exactly one member enum case. If multiple member enums contain the same case name, write the qualified case spelling:

const status: A | B = A.ready

For error-set unions, the shorthand follows the same ambiguity rule. If multiple member error sets contain the same case name, write the qualified case spelling:

const err: FileError | NetworkError = FileError.Timeout

The top Error type is not finite and does not supply leading-dot case context.

Contextual Aggregate Literals

.{ .field = value, ... } constructs the expected aggregate type when one is available.

If the expected type is Bla, then:

const x: Bla = .{ .foo = 4 }

is sugar for:

const x: Bla = Bla{ .foo = 4 }

Field initializers receive expected types from their corresponding fields:

const opts: ExportOptions = .{
  .call_conv = .c,
}

Inside aggregate construction, .call_conv = is a field designator. The value expression .c resolves through the declared type of ExportOptions.call_conv.

The fully qualified aggregate form Bla{ ... } is valid without another expected type because the owner type is written explicitly. The shorthand form .{ ... } is invalid when the context does not provide a unique expected aggregate type.

Boundaries

Invalid without a unique expected owner type:

const conv = .c
const opts = .{ .call_conv = .c }

The programmer must write the owner type or add an annotation:

const conv = CallConv.c
const opts: ExportOptions = .{ .call_conv = .c }

Expected-type shorthand does not:

  • search unrelated namespaces
  • infer a declaration type from the shorthand alone
  • choose among overloads or candidate APIs
  • make field names available as local bindings
  • bypass normal visibility checks

Inside aggregate construction, .field = expr is a field designator, not a leading-dot member shorthand. Outside aggregate construction, .name is an expected-type member shorthand.

Diagnostics should report the missing or ambiguous expected type. For example, const conv = .c should not be reported as an unknown local name c; it is a leading-dot member with no expected owner type.

  • Attributes: attribute arguments supply expected types through provider signatures.
  • C ABI Interop: .c as the first concrete leading-dot attribute argument for ABI attributes.
  • Enums: enum cases and enum-union shorthand.
  • Errors: error cases and error-set union shorthand.
  • Structs and Methods: aggregate type and method semantics.
  • Type System: general inference and coercion boundaries.