Skip to content

Commit 8089d51

Browse files
committed
Update hello world tutorial to use deleate_and_check_components
1 parent d220e82 commit 8089d51

File tree

1 file changed

+13
-34
lines changed

1 file changed

+13
-34
lines changed

content/tutorials/hello.md

+13-34
Original file line numberDiff line numberDiff line change
@@ -107,10 +107,11 @@ We also use the `#[derive(HasField)]` macro to automatically derive `HasField` i
107107

108108
## Delegate Components
109109

110-
Next, we want to define some wirings to link up the `GreetHello` that we defined earlier, so that we can use it on the `Person` context. This is done by using the `delegate_components!` macro as follows:
110+
Next, we want to define some wirings to link up the `GreetHello` that we defined earlier, so that we can use it on the `Person` context. This is done by using the `delegate_and_check_components!` macro as follows:
111111

112112
```rust
113-
delegate_components! {
113+
delegate_and_check_components! {
114+
CanUsePerson for Person;
114115
PersonComponents {
115116
NameTypeProviderComponent:
116117
UseType<String>,
@@ -120,32 +121,17 @@ delegate_components! {
120121
}
121122
```
122123

123-
We use the `delegate_components!` macro on the target provider `PersonComponents`, which was generated eariler by `#[cgp_context]`. For each entry in `delegate_components!`, we use the component name type as the key, and the chosen provider as the value.
124+
We use the `delegate_and_check_components!` macro to perform the wiring of `Person` context with the chosen providers for each component that we want to use with `Person`.
124125

125-
The first mapping, `NameTypeProviderComponent: UseType<String>`, makes use of the generic `UseType` provider to implement the provider trait `NameTypeProvider`. The `String` argument to `UseType` is used to implement the associated type `Name`.
126-
127-
The second mapping, `GreeterComponent: GreetHello`, indicates that we want to use `GreetHello` as the implementation of the `CanGreet` consumer trait.
128-
129-
## Check Components
126+
The first line, `CanUsePerson for Person`, generates a `CanUsePerson` _check trait_, which is used for implementing checks that the `Person` context has correctly implemented the consumer traits for the components in the entries, i.e. `NameTypeProviderComponent` and `GreeterComponent`.
130127

131-
We have now declared the wirings for `PersonComponents` using `delegate_components!`. However, the implementation of the wiring is done _lazily_ in CGP. This means that invalid wiring will only raise compile errors the first time we try to use the concrete implementation.
132-
133-
However, we can make use of `check_components!` to perform compile-time checks that our previous wiring is correct. This can be done as follows:
134-
135-
```rust
136-
check_components! {
137-
CanUsePerson for Person {
138-
NameTypeProviderComponent,
139-
GreeterComponent,
140-
}
141-
}
142-
```
128+
The next line, we set the delegation target to `PersonComponents`, which was generated eariler by `#[cgp_context]`. For each entry in `delegate_components!`, we use the component name type as the key, and the chosen provider as the value.
143129

144-
The `check_components!` macro generates a `CanUsePerson` _check trait_, which is used for implementing checks that the `Person` context has correctly implemented the consumer traits for `NameTypeProviderComponent` and `GreeterComponent`.
130+
The first mapping, `NameTypeProviderComponent: UseType<String>`, makes use of the generic `UseType` provider to implement the provider trait `NameTypeProvider`. The `String` argument to `UseType` is used to implement the associated type `Name`.
145131

146-
If there is any unsatisfied dependency, such as if `Person` does not contain the necessary `name: String` field, then such errors will be raised here.
132+
The second mapping, `GreeterComponent: GreetHello`, indicates that we want to use `GreetHello` as the implementation of the `CanGreet` consumer trait.
147133

148-
We can think of the use of `check_components!` as writing CGP tests that run at compile time. The reason this check is done separately from `delegate_components!`, is that we can use `check_components!` to define more advanced tests, such as when the CGP traits contain additional generic parameters.
134+
During the wiring, if there is any unsatisfied dependency, such as if `Person` does not contain the necessary `name: String` field, then the errors would be raised by the check trait at the first line.
149135

150136
## Calling Greet
151137

@@ -225,8 +211,9 @@ pub struct Person {
225211
pub name: String,
226212
}
227213

228-
// Compile-time wiring of CGP components
229-
delegate_components! {
214+
// Compile-time wiring and checks of CGP components
215+
delegate_and_check_components! {
216+
CanUsePerson for Person;
230217
PersonComponents {
231218
NameTypeProviderComponent:
232219
UseType<String>, // Instantiate the `Name` type to `String`
@@ -235,14 +222,6 @@ delegate_components! {
235222
}
236223
}
237224

238-
// Compile-time checks that all dependencies are wired correctly
239-
check_components! {
240-
CanUsePerson for Person {
241-
NameTypeProviderComponent,
242-
GreeterComponent,
243-
}
244-
}
245-
246225
fn main() {
247226
let person = Person {
248227
name: "Alice".into(),
@@ -251,4 +230,4 @@ fn main() {
251230
// `CanGreet` is automatically implemented for `Person`
252231
person.greet();
253232
}
254-
```
233+
```

0 commit comments

Comments
 (0)