Skip to content

Commit 21a9f5b

Browse files
authored
docs: add impl aliases reference page (#9022)
1 parent 144c7b1 commit 21a9f5b

File tree

1 file changed

+185
-3
lines changed
  • docs/reference/src/components/cairo/modules/language_constructs/pages

1 file changed

+185
-3
lines changed
Lines changed: 185 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,188 @@
11
= Impl aliases
22

3-
This section is a work in progress.
3+
Impl aliases provide alternative names for existing impls.
4+
They do not introduce new impls; instead, they refer to an existing implementation,
5+
possibly with concrete generic arguments.
46

5-
You are very welcome to contribute to this documentation by
6-
link:https://github.com/starkware-libs/cairo/issues?q=is%3Aissue+is%3Aopen+label%3A%22help+wanted%22[submitting a pull request].
7+
Impl aliases are useful for:
8+
9+
- Providing shorter or more descriptive names for complex impls.
10+
- Re-exporting impls from other modules.
11+
- Fixing some generic arguments of an impl while keeping others generic.
12+
13+
See also xref:aliases.adoc[Type and impl aliases],
14+
xref:traits.adoc[Traits and impls] and xref:generics.adoc[Generics].
15+
16+
== Syntax
17+
18+
An impl alias has the following form:
19+
20+
[source,cairo]
21+
----
22+
impl ImplAliasName<GenericParams> = path::to::Impl<GenericArgs>;
23+
----
24+
25+
Where:
26+
27+
- `ImplAliasName` is the new name of the impl.
28+
- `GenericParams` are the generic parameters introduced by the alias (optional).
29+
- `path::to::Impl` is a path to an existing impl or impl alias.
30+
- `GenericArgs` are the concrete generic arguments passed to that impl (optional).
31+
32+
The path on the right-hand side must resolve to an impl (or another impl alias).
33+
If it does not, the compiler reports an error.
34+
35+
== Basic example
36+
37+
The following example defines a trait and an impl, and then introduces an impl alias
38+
to give this implementation a shorter name:
39+
40+
[source,cairo]
41+
----
42+
trait Pow<T> {
43+
fn pow(base: T, exp: u32) -> T;
44+
}
45+
46+
impl AnyAlgebraPow<T, impl AlgImpl: Algebra<T>> of Pow<T> {
47+
fn pow(base: T, exp: u32) -> T {
48+
// Implementation details.
49+
base
50+
}
51+
}
52+
53+
// Impl alias for Pow of felt252.
54+
impl FeltPow = AnyAlgebraPow<felt252, FeltAlgebra>;
55+
56+
fn main() {
57+
// Call through the trait name.
58+
let x = Pow::pow(5, 3);
59+
60+
// Call through the impl alias name.
61+
let y = FeltPow::pow(5, 3);
62+
}
63+
----
64+
65+
Here `FeltPow` is just another name for the concrete impl
66+
`AnyAlgebraPow<felt252, FeltAlgebra>`. No new impl is created.
67+
68+
== Generic impl aliases
69+
70+
Impl aliases can themselves be generic.
71+
This allows fixing some of the generic arguments of an existing impl
72+
while leaving others as parameters of the alias.
73+
74+
[source,cairo]
75+
----
76+
trait MyTrait<T> {
77+
fn foo(x: T) -> usize;
78+
}
79+
80+
mod inner {
81+
impl MyImpl<T> of MyTrait<Option<T>> {
82+
fn foo(x: Option<T>) -> usize {
83+
0_usize
84+
}
85+
}
86+
}
87+
88+
// Fix the outer type to `Box<T>` but keep `T` generic.
89+
impl MyImplAlias<T> = inner::MyImpl<Box<T>>;
90+
91+
fn use_alias(x: Box<usize>) -> usize {
92+
MyTrait::foo(x)
93+
}
94+
----
95+
96+
In this example, `MyImplAlias<T>` is an alias for a family of impls
97+
`inner::MyImpl<Box<T>>`. The generic parameter `T` of the alias is
98+
substituted into the generic parameter of the underlying impl.
99+
100+
== Chaining impl aliases
101+
102+
An impl alias can refer to another impl alias.
103+
The compiler resolves such chains transitively until it reaches the
104+
underlying concrete impl.
105+
106+
[source,cairo]
107+
----
108+
trait Trait1<T> {
109+
fn func1(value: T);
110+
}
111+
112+
trait Trait2<T> {
113+
fn func2(value: T);
114+
}
115+
116+
mod impls {
117+
impl Impl1<T, +Drop<T>> of super::Trait1<T> {
118+
fn func1(value: T) {}
119+
}
120+
121+
// Public alias for a concrete impl of Trait1<felt252>.
122+
pub impl ImplAlias1 = Impl1<felt252>;
123+
124+
impl Impl2<T, +Drop<T>> of super::Trait2<T> {
125+
fn func2(value: T) {}
126+
}
127+
128+
// Public alias for a concrete impl of Trait2<felt252>.
129+
pub impl ImplAlias2 = Impl2<felt252>;
130+
}
131+
132+
use impls::ImplAlias1;
133+
134+
// A second-level alias that refers to an impl alias from another module.
135+
impl Impl2Alias = impls::ImplAlias2;
136+
----
137+
138+
Both `ImplAlias1` and `Impl2Alias` are names for existing impls.
139+
They can be used wherever an impl name is expected, for example
140+
in generic parameters or when calling trait methods.
141+
142+
== Using impl aliases
143+
144+
Impl aliases can be used anywhere a named impl can be used:
145+
146+
- When calling trait methods through an impl name.
147+
- As impl generic arguments in generic functions, structs, enums, and so on.
148+
149+
For example:
150+
151+
[source,cairo]
152+
----
153+
trait Display<T> {
154+
fn display(x: T) -> Array<u8>;
155+
}
156+
157+
impl DisplayFelt of Display<felt252> {
158+
fn display(x: felt252) -> Array<u8> {
159+
// ...
160+
ArrayTrait::new()
161+
}
162+
}
163+
164+
// Provide a shorter name for the concrete impl.
165+
impl FeltDisplay = DisplayFelt;
166+
167+
fn print_value<T, impl D: Display<T>>(value: T) {
168+
let bytes = D::display(value);
169+
// ...
170+
}
171+
172+
fn main() {
173+
// Use the impl alias as a concrete impl argument.
174+
print_value::<felt252, FeltDisplay>(5);
175+
}
176+
----
177+
178+
== Errors and limitations
179+
180+
When working with impl aliases, the compiler enforces several rules:
181+
182+
- The right-hand side of an impl alias must resolve to an impl or another impl alias.
183+
If it resolves to anything else, a compilation error is reported.
184+
- Cyclic impl aliases (where aliases form a cycle through their right-hand sides)
185+
are rejected by the compiler.
186+
187+
Apart from these restrictions, impl aliases behave like their underlying impls
188+
in name resolution and generic argument handling.

0 commit comments

Comments
 (0)