You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: content/tutorials/hello.md
+13-34
Original file line number
Diff line number
Diff line change
@@ -107,10 +107,11 @@ We also use the `#[derive(HasField)]` macro to automatically derive `HasField` i
107
107
108
108
## Delegate Components
109
109
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:
111
111
112
112
```rust
113
-
delegate_components! {
113
+
delegate_and_check_components! {
114
+
CanUsePersonforPerson;
114
115
PersonComponents {
115
116
NameTypeProviderComponent:
116
117
UseType<String>,
@@ -120,32 +121,17 @@ delegate_components! {
120
121
}
121
122
```
122
123
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`.
124
125
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`.
130
127
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
-
CanUsePersonforPerson {
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.
143
129
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`.
145
131
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.
147
133
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.
149
135
150
136
## Calling Greet
151
137
@@ -225,8 +211,9 @@ pub struct Person {
225
211
pubname:String,
226
212
}
227
213
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
+
CanUsePersonforPerson;
230
217
PersonComponents {
231
218
NameTypeProviderComponent:
232
219
UseType<String>, // Instantiate the `Name` type to `String`
@@ -235,14 +222,6 @@ delegate_components! {
235
222
}
236
223
}
237
224
238
-
// Compile-time checks that all dependencies are wired correctly
239
-
check_components! {
240
-
CanUsePersonforPerson {
241
-
NameTypeProviderComponent,
242
-
GreeterComponent,
243
-
}
244
-
}
245
-
246
225
fnmain() {
247
226
letperson=Person {
248
227
name:"Alice".into(),
@@ -251,4 +230,4 @@ fn main() {
251
230
// `CanGreet` is automatically implemented for `Person`
0 commit comments