> ## Documentation Index
> Fetch the complete documentation index at: https://www.osohq.com/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# Polar Polymorphism

Polar's type system offers [subtype polymorphism](https://en.wikipedia.org/wiki/Subtyping) through its `extends` feature.

This lets you write rules that apply to a general type and automatically apply to all of its subtypes.

## `Actor` and `Resource` Types

Every `actor` or `resource` declaration in Polar implicitly extends the abstract `Actor` or `Resource` types.

This means that any rule that references `Actor` can also accept types declared as `actor`.

Consider this policy snippet:

```polar theme={null}
actor User {};
resource Issue {};
```

This creates the following relationships:

| Supertype  | Subtype |
| ---------- | ------- |
| `Actor`    | `User`  |
| `Resource` | `Issue` |

When you use shorthand rules, Polar rewrites them into generic rules that rely on these supertypes. For example, a shorthand rule may expand into:

```polar theme={null}
has_permission(actor: Actor, action: String, resource: Resource)...
```

You can then query this rule with concrete types:

```
oso-cloud query has_permission User:alice read Issue:123
```

This works because `User` is a subtype of `Actor`, and `Issue` is a subtype of `Resource`. Polar’s type system ensures that subtype values can be used wherever their supertypes appear.

## Type Inheritance With `extends`

### `Actor` Extends `Resource`

The built-in `Actor` type extends `Resource`. This means any parameter expecting a `Resource` value will also accept an `Actor`.

As a result, you can define roles, permissions, and relations over actors using `actor resource` blocks. While uncommon, this is useful when modeling authorization logic over user-like entities.

## Extending Custom Types

Use the `extends` keyword to define custom inheritance relationships:

```
(actor | resource) Subtype extends Supertype {}
```

Extending types enables two features:

* Rule polymorphism: rules written for a supertype apply to all its subtypes.
* Inheritance: subtypes inherit permissions, roles, and relations defined on the supertype.

This is useful when multiple resource types share common logic.

### Rule Polymorphism

Subtype values satisfy rules defined over their supertypes.

For example:

```polar theme={null}
actor User {}

resource File {
  permissions = ["read"];
  relations = {owner: User};
}

resource Document extends File {}

has_permission(actor: Actor, "read", file: File) if
  is_public(file) or
  has_relation(actor, "owner", file);

# Even though `has_permission` is defined for `File`, it applies to `Document`
test "extends" {
  setup {
    has_relation(User{"alice"}, "owner", Document{"public.txt"});
    is_public(Document{"public.txt"});
    has_relation(User{"alice"}, "owner", Document{"private.txt"});
  }

  # Though `has_permission` is defined on `File`, `Document` behaves in the
  # same way because it extends `File`.
  assert allow(User{"bob"}, "read", Document{"public.txt"});
  assert_not allow(User{"bob"}, "read", Document{"private.txt"});
  assert allow(User{"alice"}, "read", Document{"private.txt"});
}
```

### Inherited Roles, Permissions, and Relations

Subtypes inherit all roles, permissions, and relations from their supertype. The supertype definition remains unchanged.

Example:

```polar theme={null}
actor User {}

resource File {
  permissions = ["read", "write"];
  roles = ["reader", "writer"];

  "read" if "reader";
  "write" if "writer";

  "read" if "write";
}

resource Document extends File {}

test "extends" {
  setup {
    has_role(User{"alice"}, "writer", Document{"xyz.doc"});
  }

  # Though roles + permissions are defined on `File`, `Document` behaves in
  # the same way because it extends `File`.
  assert allow(User{"alice"}, "read", Document{"xyz.doc"});
}
```

## Details

### Unification

Subtype values do not unify with their supertypes.

For example, given the following definition:

```polar theme={null}
resource Document extends File {}
```

This condition always returns `false`:

```polar theme={null}
Document{"a"} = File{"a"}
```

### Query Type Filtering

Query filters do not match subtypes.

For example:

```polar theme={null}
resource Document extends File {}
```

This query excludes `Document` values, even with a wildcard:

```
oso-cloud query has_permission User:alice read File:_
```
