Coverage Report

Created: 2025-10-10 07:11

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/rust/registry/src/index.crates.io-1949cf8c6b5b557f/async-graphql-7.0.16/src/dynamic/resolve.rs
Line
Count
Source
1
use std::{borrow::Cow, pin::Pin};
2
3
use async_graphql_derive::SimpleObject;
4
use async_graphql_parser::{types::Field, Positioned};
5
use futures_util::{future::BoxFuture, Future, FutureExt};
6
use indexmap::IndexMap;
7
8
use crate::{
9
    dynamic::{
10
        field::FieldValueInner, FieldFuture, FieldValue, Object, ObjectAccessor, ResolverContext,
11
        Schema, Type, TypeRef,
12
    },
13
    extensions::ResolveInfo,
14
    parser::types::Selection,
15
    resolver_utils::create_value_object,
16
    Context, ContextSelectionSet, Error, IntrospectionMode, Name, SDLExportOptions, ServerError,
17
    ServerResult, Value,
18
};
19
20
/// Federation service
21
#[derive(SimpleObject)]
22
#[graphql(internal, name = "_Service")]
23
struct Service {
24
    sdl: Option<String>,
25
}
26
27
type BoxFieldFuture<'a> = Pin<Box<dyn Future<Output = ServerResult<(Name, Value)>> + 'a + Send>>;
28
29
0
pub(crate) async fn resolve_container(
30
0
    schema: &Schema,
31
0
    object: &Object,
32
0
    ctx: &ContextSelectionSet<'_>,
33
0
    parent_value: &FieldValue<'_>,
34
0
    serial: bool,
35
0
) -> ServerResult<Option<Value>> {
36
0
    let mut fields = Vec::new();
37
0
    collect_fields(&mut fields, schema, object, ctx, parent_value)?;
38
39
0
    let res = if !serial {
40
0
        futures_util::future::try_join_all(fields).await?
41
    } else {
42
0
        let mut results = Vec::with_capacity(fields.len());
43
0
        for field in fields {
44
0
            results.push(field.await?);
45
        }
46
0
        results
47
    };
48
49
0
    Ok(Some(create_value_object(res)))
50
0
}
51
52
0
fn collect_typename_field<'a>(
53
0
    fields: &mut Vec<BoxFieldFuture<'a>>,
54
0
    object: &'a Object,
55
0
    field: &'a Positioned<Field>,
56
0
) {
57
0
    fields.push(
58
0
        async move {
59
0
            Ok((
60
0
                field.node.response_key().node.clone(),
61
0
                Value::from(object.name.as_str()),
62
0
            ))
63
0
        }
64
0
        .boxed(),
65
    )
66
0
}
67
68
0
fn collect_schema_field<'a>(
69
0
    fields: &mut Vec<BoxFieldFuture<'a>>,
70
0
    ctx: &ContextSelectionSet<'a>,
71
0
    field: &'a Positioned<Field>,
72
0
) {
73
0
    let ctx = ctx.clone();
74
0
    fields.push(
75
0
        async move {
76
0
            let ctx_field = ctx.with_field(field);
77
0
            let mut ctx_obj = ctx.with_selection_set(&ctx_field.item.node.selection_set);
78
0
            ctx_obj.is_for_introspection = true;
79
0
            let visible_types = ctx.schema_env.registry.find_visible_types(&ctx_field);
80
0
            let value = crate::OutputType::resolve(
81
0
                &crate::model::__Schema::new(&ctx.schema_env.registry, &visible_types),
82
0
                &ctx_obj,
83
0
                ctx_field.item,
84
0
            )
85
0
            .await?;
86
0
            Ok((field.node.response_key().node.clone(), value))
87
0
        }
88
0
        .boxed(),
89
    );
90
0
}
91
92
0
fn collect_type_field<'a>(
93
0
    fields: &mut Vec<BoxFieldFuture<'a>>,
94
0
    ctx: &ContextSelectionSet<'a>,
95
0
    field: &'a Positioned<Field>,
96
0
) {
97
0
    let ctx = ctx.clone();
98
0
    fields.push(
99
0
        async move {
100
0
            let ctx_field = ctx.with_field(field);
101
0
            let (_, type_name) = ctx_field.param_value::<String>("name", None)?;
102
0
            let mut ctx_obj = ctx.with_selection_set(&ctx_field.item.node.selection_set);
103
0
            ctx_obj.is_for_introspection = true;
104
0
            let visible_types = ctx.schema_env.registry.find_visible_types(&ctx_field);
105
0
            let value = crate::OutputType::resolve(
106
0
                &ctx.schema_env
107
0
                    .registry
108
0
                    .types
109
0
                    .get(&type_name)
110
0
                    .filter(|_| visible_types.contains(type_name.as_str()))
111
0
                    .map(|ty| {
112
0
                        crate::model::__Type::new_simple(
113
0
                            &ctx.schema_env.registry,
114
0
                            &visible_types,
115
0
                            ty,
116
                        )
117
0
                    }),
118
0
                &ctx_obj,
119
0
                ctx_field.item,
120
            )
121
0
            .await?;
122
0
            Ok((field.node.response_key().node.clone(), value))
123
0
        }
124
0
        .boxed(),
125
    );
126
0
}
127
128
0
fn collect_service_field<'a>(
129
0
    fields: &mut Vec<BoxFieldFuture<'a>>,
130
0
    ctx: &ContextSelectionSet<'a>,
131
0
    field: &'a Positioned<Field>,
132
0
) {
133
0
    let ctx = ctx.clone();
134
0
    fields.push(
135
0
        async move {
136
0
            let ctx_field = ctx.with_field(field);
137
0
            let mut ctx_obj = ctx.with_selection_set(&ctx_field.item.node.selection_set);
138
0
            ctx_obj.is_for_introspection = true;
139
140
0
            let output_type = crate::OutputType::resolve(
141
0
                &Service {
142
0
                    sdl: Some(
143
0
                        ctx.schema_env
144
0
                            .registry
145
0
                            .export_sdl(SDLExportOptions::new().federation().compose_directive()),
146
0
                    ),
147
0
                },
148
0
                &ctx_obj,
149
0
                ctx_field.item,
150
0
            )
151
0
            .await?;
152
153
0
            Ok((field.node.response_key().node.clone(), output_type))
154
0
        }
155
0
        .boxed(),
156
    );
157
0
}
158
159
0
fn collect_entities_field<'a>(
160
0
    fields: &mut Vec<BoxFieldFuture<'a>>,
161
0
    schema: &'a Schema,
162
0
    ctx: &ContextSelectionSet<'a>,
163
0
    parent_value: &'a FieldValue,
164
0
    field: &'a Positioned<Field>,
165
0
) {
166
0
    let ctx = ctx.clone();
167
0
    fields.push(
168
0
        async move {
169
0
            let ctx_field = ctx.with_field(field);
170
0
            let entity_resolver = schema.0.entity_resolver.as_ref().ok_or_else(|| {
171
0
                ctx_field.set_error_path(
172
0
                    Error::new("internal: missing entity resolver")
173
0
                        .into_server_error(ctx_field.item.pos),
174
                )
175
0
            })?;
176
0
            let entity_type = TypeRef::named_list_nn("_Entity");
177
178
0
            let arguments = ObjectAccessor(Cow::Owned(
179
0
                field
180
0
                    .node
181
0
                    .arguments
182
0
                    .iter()
183
0
                    .map(|(name, value)| {
184
0
                        ctx_field
185
0
                            .resolve_input_value(value.clone())
186
0
                            .map(|value| (name.node.clone(), value))
187
0
                    })
188
0
                    .collect::<ServerResult<IndexMap<Name, Value>>>()?,
189
            ));
190
191
0
            let field_future = (entity_resolver)(ResolverContext {
192
0
                ctx: &ctx_field,
193
0
                args: arguments,
194
0
                parent_value,
195
0
            });
196
197
0
            let field_value = match field_future {
198
0
                FieldFuture::Future(fut) => {
199
0
                    fut.await.map_err(|err| err.into_server_error(field.pos))?
200
                }
201
0
                FieldFuture::Value(value) => value,
202
            };
203
0
            let value = resolve(schema, &ctx_field, &entity_type, field_value.as_ref())
204
0
                .await?
205
0
                .unwrap_or_default();
206
0
            Ok((field.node.response_key().node.clone(), value))
207
0
        }
208
0
        .boxed(),
209
    );
210
0
}
211
212
0
fn collect_field<'a>(
213
0
    fields: &mut Vec<BoxFieldFuture<'a>>,
214
0
    schema: &'a Schema,
215
0
    object: &'a Object,
216
0
    ctx: &ContextSelectionSet<'a>,
217
0
    parent_value: &'a FieldValue,
218
0
    field_def: &'a crate::dynamic::Field,
219
0
    field: &'a Positioned<Field>,
220
0
) {
221
0
    let ctx = ctx.clone();
222
0
    fields.push(
223
0
        async move {
224
0
            let ctx_field = ctx.with_field(field);
225
0
            let arguments = ObjectAccessor(Cow::Owned({
226
0
                let mut args = field
227
0
                    .node
228
0
                    .arguments
229
0
                    .iter()
230
0
                    .map(|(name, value)| {
231
0
                        ctx_field
232
0
                            .resolve_input_value(value.clone())
233
0
                            .map(|value| (name.node.clone(), value))
234
0
                    })
235
0
                    .collect::<ServerResult<IndexMap<Name, Value>>>()?;
236
0
                field_def.arguments.iter().for_each(|(name, arg)| {
237
0
                    if let Some(def) = &arg.default_value {
238
0
                        if !args.contains_key(name.as_str()) {
239
0
                            args.insert(Name::new(name), def.clone());
240
0
                        }
241
0
                    }
242
0
                });
243
0
                args
244
            }));
245
246
0
            let resolve_info = ResolveInfo {
247
0
                path_node: ctx_field.path_node.as_ref().unwrap(),
248
0
                parent_type: &object.name,
249
0
                return_type: &field_def.ty_str,
250
0
                name: &field.node.name.node,
251
0
                alias: field.node.alias.as_ref().map(|alias| &*alias.node),
252
0
                is_for_introspection: ctx_field.is_for_introspection,
253
0
                field: &field.node,
254
            };
255
0
            let resolve_fut = async {
256
0
                let field_future = (field_def.resolver_fn)(ResolverContext {
257
0
                    ctx: &ctx_field,
258
0
                    args: arguments,
259
0
                    parent_value,
260
0
                });
261
262
0
                let field_value = match field_future {
263
0
                    FieldFuture::Value(field_value) => field_value,
264
0
                    FieldFuture::Future(future) => future
265
0
                        .await
266
0
                        .map_err(|err| err.into_server_error(field.pos))?,
267
                };
268
269
0
                let value =
270
0
                    resolve(schema, &ctx_field, &field_def.ty, field_value.as_ref()).await?;
271
272
0
                Ok(value)
273
0
            };
274
0
            futures_util::pin_mut!(resolve_fut);
275
276
0
            let res_value = ctx_field
277
0
                .query_env
278
0
                .extensions
279
0
                .resolve(resolve_info, &mut resolve_fut)
280
0
                .await?
281
0
                .unwrap_or_default();
282
0
            Ok((field.node.response_key().node.clone(), res_value))
283
0
        }
284
0
        .boxed(),
285
    );
286
0
}
287
288
0
fn collect_fields<'a>(
289
0
    fields: &mut Vec<BoxFieldFuture<'a>>,
290
0
    schema: &'a Schema,
291
0
    object: &'a Object,
292
0
    ctx: &ContextSelectionSet<'a>,
293
0
    parent_value: &'a FieldValue,
294
0
) -> ServerResult<()> {
295
0
    for selection in &ctx.item.node.items {
296
0
        match &selection.node {
297
0
            Selection::Field(field) => {
298
0
                if field.node.name.node == "__typename" {
299
0
                    collect_typename_field(fields, object, field);
300
0
                    continue;
301
0
                }
302
303
0
                if object.name == schema.0.env.registry.query_type
304
0
                    && matches!(
305
0
                        ctx.schema_env.registry.introspection_mode,
306
                        IntrospectionMode::Enabled | IntrospectionMode::IntrospectionOnly
307
                    )
308
0
                    && matches!(
309
0
                        ctx.query_env.introspection_mode,
310
                        IntrospectionMode::Enabled | IntrospectionMode::IntrospectionOnly,
311
                    )
312
                {
313
                    // is query root
314
0
                    if field.node.name.node == "__schema" {
315
0
                        collect_schema_field(fields, ctx, field);
316
0
                        continue;
317
0
                    } else if field.node.name.node == "__type" {
318
0
                        collect_type_field(fields, ctx, field);
319
0
                        continue;
320
0
                    } else if ctx.schema_env.registry.enable_federation
321
0
                        && field.node.name.node == "_service"
322
                    {
323
0
                        collect_service_field(fields, ctx, field);
324
0
                        continue;
325
0
                    } else if ctx.schema_env.registry.enable_federation
326
0
                        && field.node.name.node == "_entities"
327
                    {
328
0
                        collect_entities_field(fields, schema, ctx, parent_value, field);
329
0
                        continue;
330
0
                    }
331
0
                }
332
333
0
                if ctx.schema_env.registry.introspection_mode
334
0
                    == IntrospectionMode::IntrospectionOnly
335
0
                    || ctx.query_env.introspection_mode == IntrospectionMode::IntrospectionOnly
336
                {
337
0
                    fields.push(
338
0
                        async move { Ok((field.node.response_key().node.clone(), Value::Null)) }
339
0
                            .boxed(),
340
                    );
341
0
                    continue;
342
0
                }
343
344
0
                if let Some(field_def) = object.fields.get(field.node.name.node.as_str()) {
345
0
                    collect_field(fields, schema, object, ctx, parent_value, field_def, field);
346
0
                }
347
            }
348
0
            selection => {
349
0
                let (type_condition, selection_set) = match selection {
350
0
                    Selection::Field(_) => unreachable!(),
351
0
                    Selection::FragmentSpread(spread) => {
352
0
                        let fragment = ctx.query_env.fragments.get(&spread.node.fragment_name.node);
353
0
                        let fragment = match fragment {
354
0
                            Some(fragment) => fragment,
355
                            None => {
356
0
                                return Err(ServerError::new(
357
0
                                    format!(
358
0
                                        "Unknown fragment \"{}\".",
359
0
                                        spread.node.fragment_name.node
360
0
                                    ),
361
0
                                    Some(spread.pos),
362
0
                                ));
363
                            }
364
                        };
365
0
                        (
366
0
                            Some(&fragment.node.type_condition),
367
0
                            &fragment.node.selection_set,
368
0
                        )
369
                    }
370
0
                    Selection::InlineFragment(fragment) => (
371
0
                        fragment.node.type_condition.as_ref(),
372
0
                        &fragment.node.selection_set,
373
0
                    ),
374
                };
375
376
0
                let type_condition =
377
0
                    type_condition.map(|condition| condition.node.on.node.as_str());
378
0
                let introspection_type_name = &object.name;
379
380
0
                let type_condition_matched = match type_condition {
381
0
                    None => true,
382
0
                    Some(type_condition) if type_condition == introspection_type_name => true,
383
0
                    Some(type_condition) if object.implements.contains(type_condition) => true,
384
0
                    _ => false,
385
                };
386
0
                if type_condition_matched {
387
0
                    collect_fields(
388
0
                        fields,
389
0
                        schema,
390
0
                        object,
391
0
                        &ctx.with_selection_set(selection_set),
392
0
                        parent_value,
393
0
                    )?;
394
0
                }
395
            }
396
        }
397
    }
398
399
0
    Ok(())
400
0
}
401
402
0
pub(crate) fn resolve<'a>(
403
0
    schema: &'a Schema,
404
0
    ctx: &'a Context<'a>,
405
0
    type_ref: &'a TypeRef,
406
0
    value: Option<&'a FieldValue>,
407
0
) -> BoxFuture<'a, ServerResult<Option<Value>>> {
408
0
    async move {
409
0
        match (type_ref, value) {
410
0
            (TypeRef::Named(type_name), Some(value)) => {
411
0
                resolve_value(schema, ctx, &schema.0.types[type_name.as_ref()], value).await
412
            }
413
0
            (TypeRef::Named(_), None) => Ok(None),
414
415
0
            (TypeRef::NonNull(type_ref), Some(value)) => {
416
0
                resolve(schema, ctx, type_ref, Some(value)).await
417
            }
418
0
            (TypeRef::NonNull(_), None) => Err(ctx.set_error_path(
419
0
                Error::new("internal: non-null types require a return value")
420
0
                    .into_server_error(ctx.item.pos),
421
0
            )),
422
423
0
            (TypeRef::List(type_ref), Some(FieldValue(FieldValueInner::List(values)))) => {
424
0
                resolve_list(schema, ctx, type_ref, values).await
425
            }
426
            (
427
0
                TypeRef::List(type_ref),
428
0
                Some(FieldValue(FieldValueInner::Value(Value::List(values)))),
429
            ) => {
430
0
                let values = values
431
0
                    .iter()
432
0
                    .cloned()
433
0
                    .map(FieldValue::value)
434
0
                    .collect::<Vec<_>>();
435
0
                resolve_list(schema, ctx, type_ref, &values).await
436
            }
437
0
            (TypeRef::List(_), Some(_)) => Err(ctx.set_error_path(
438
0
                Error::new("internal: expects an array").into_server_error(ctx.item.pos),
439
0
            )),
440
0
            (TypeRef::List(_), None) => Ok(None),
441
        }
442
0
    }
443
0
    .boxed()
444
0
}
445
446
0
async fn resolve_list<'a>(
447
0
    schema: &'a Schema,
448
0
    ctx: &'a Context<'a>,
449
0
    type_ref: &'a TypeRef,
450
0
    values: &[FieldValue<'_>],
451
0
) -> ServerResult<Option<Value>> {
452
0
    let mut futures = Vec::with_capacity(values.len());
453
0
    for (idx, value) in values.iter().enumerate() {
454
0
        let ctx_item = ctx.with_index(idx);
455
456
0
        futures.push(async move {
457
0
            let parent_type = format!("[{}]", type_ref);
458
0
            let return_type = type_ref.to_string();
459
0
            let resolve_info = ResolveInfo {
460
0
                path_node: ctx_item.path_node.as_ref().unwrap(),
461
0
                parent_type: &parent_type,
462
0
                return_type: &return_type,
463
0
                name: ctx.item.node.name.node.as_str(),
464
0
                alias: ctx
465
0
                    .item
466
0
                    .node
467
0
                    .alias
468
0
                    .as_ref()
469
0
                    .map(|alias| alias.node.as_str()),
470
0
                is_for_introspection: ctx_item.is_for_introspection,
471
0
                field: &ctx_item.item.node,
472
            };
473
474
0
            let resolve_fut = async { resolve(schema, &ctx_item, type_ref, Some(value)).await };
475
0
            futures_util::pin_mut!(resolve_fut);
476
477
0
            let res_value = ctx_item
478
0
                .query_env
479
0
                .extensions
480
0
                .resolve(resolve_info, &mut resolve_fut)
481
0
                .await?;
482
0
            Ok::<_, ServerError>(res_value.unwrap_or_default())
483
0
        });
484
    }
485
0
    let values = futures_util::future::try_join_all(futures).await?;
486
0
    Ok(Some(Value::List(values)))
487
0
}
488
489
0
async fn resolve_value(
490
0
    schema: &Schema,
491
0
    ctx: &Context<'_>,
492
0
    field_type: &Type,
493
0
    value: &FieldValue<'_>,
494
0
) -> ServerResult<Option<Value>> {
495
0
    match (field_type, &value.0) {
496
0
        (Type::Scalar(scalar), FieldValueInner::Value(value)) if scalar.validate(value) => {
497
0
            Ok(Some(value.clone()))
498
        }
499
0
        (Type::Scalar(scalar), _) => Err(ctx.set_error_path(
500
0
            Error::new(format!(
501
0
                "internal: invalid value for scalar \"{}\", expected \"FieldValue::Value\"",
502
0
                scalar.name
503
0
            ))
504
0
            .into_server_error(ctx.item.pos),
505
0
        )),
506
507
0
        (Type::Object(object), _) => {
508
0
            resolve_container(
509
0
                schema,
510
0
                object,
511
0
                &ctx.with_selection_set(&ctx.item.node.selection_set),
512
0
                value,
513
0
                true,
514
0
            )
515
0
            .await
516
        }
517
518
0
        (Type::InputObject(obj), _) => Err(ctx.set_error_path(
519
0
            Error::new(format!(
520
0
                "internal: cannot use input object \"{}\" as output value",
521
0
                obj.name
522
0
            ))
523
0
            .into_server_error(ctx.item.pos),
524
0
        )),
525
526
0
        (Type::Enum(e), FieldValueInner::Value(Value::Enum(name))) => {
527
0
            if !e.enum_values.contains_key(name.as_str()) {
528
0
                return Err(ctx.set_error_path(
529
0
                    Error::new(format!("internal: invalid item for enum \"{}\"", e.name))
530
0
                        .into_server_error(ctx.item.pos),
531
0
                ));
532
0
            }
533
0
            Ok(Some(Value::Enum(name.clone())))
534
        }
535
0
        (Type::Enum(e), FieldValueInner::Value(Value::String(name))) => {
536
0
            if !e.enum_values.contains_key(name) {
537
0
                return Err(ctx.set_error_path(
538
0
                    Error::new(format!("internal: invalid item for enum \"{}\"", e.name))
539
0
                        .into_server_error(ctx.item.pos),
540
0
                ));
541
0
            }
542
0
            Ok(Some(Value::Enum(Name::new(name))))
543
        }
544
0
        (Type::Enum(e), _) => Err(ctx.set_error_path(
545
0
            Error::new(format!("internal: invalid item for enum \"{}\"", e.name))
546
0
                .into_server_error(ctx.item.pos),
547
0
        )),
548
549
0
        (Type::Interface(interface), FieldValueInner::WithType { value, ty }) => {
550
0
            let is_contains_obj = schema
551
0
                .0
552
0
                .env
553
0
                .registry
554
0
                .types
555
0
                .get(&interface.name)
556
0
                .and_then(|meta_type| {
557
0
                    meta_type
558
0
                        .possible_types()
559
0
                        .map(|possible_types| possible_types.contains(ty.as_ref()))
560
0
                })
561
0
                .unwrap_or_default();
562
0
            if !is_contains_obj {
563
0
                return Err(ctx.set_error_path(
564
0
                    Error::new(format!(
565
0
                        "internal: object \"{}\" does not implement interface \"{}\"",
566
0
                        ty, interface.name,
567
0
                    ))
568
0
                    .into_server_error(ctx.item.pos),
569
0
                ));
570
0
            }
571
572
0
            let object_type = schema
573
0
                .0
574
0
                .types
575
0
                .get(ty.as_ref())
576
0
                .ok_or_else(|| {
577
0
                    ctx.set_error_path(
578
0
                        Error::new(format!("internal: object \"{}\" does not registered", ty))
579
0
                            .into_server_error(ctx.item.pos),
580
                    )
581
0
                })?
582
0
                .as_object()
583
0
                .ok_or_else(|| {
584
0
                    ctx.set_error_path(
585
0
                        Error::new(format!("internal: type \"{}\" is not object", ty))
586
0
                            .into_server_error(ctx.item.pos),
587
                    )
588
0
                })?;
589
590
0
            resolve_container(
591
0
                schema,
592
0
                object_type,
593
0
                &ctx.with_selection_set(&ctx.item.node.selection_set),
594
0
                value,
595
0
                true,
596
0
            )
597
0
            .await
598
        }
599
0
        (Type::Interface(interface), _) => Err(ctx.set_error_path(
600
0
            Error::new(format!(
601
0
                "internal: invalid value for interface \"{}\", expected \"FieldValue::WithType\"",
602
0
                interface.name
603
0
            ))
604
0
            .into_server_error(ctx.item.pos),
605
0
        )),
606
607
0
        (Type::Union(union), FieldValueInner::WithType { value, ty }) => {
608
0
            if !union.possible_types.contains(ty.as_ref()) {
609
0
                return Err(ctx.set_error_path(
610
0
                    Error::new(format!(
611
0
                        "internal: union \"{}\" does not contain object \"{}\"",
612
0
                        union.name, ty,
613
0
                    ))
614
0
                    .into_server_error(ctx.item.pos),
615
0
                ));
616
0
            }
617
618
0
            let object_type = schema
619
0
                .0
620
0
                .types
621
0
                .get(ty.as_ref())
622
0
                .ok_or_else(|| {
623
0
                    ctx.set_error_path(
624
0
                        Error::new(format!("internal: object \"{}\" does not registered", ty))
625
0
                            .into_server_error(ctx.item.pos),
626
                    )
627
0
                })?
628
0
                .as_object()
629
0
                .ok_or_else(|| {
630
0
                    ctx.set_error_path(
631
0
                        Error::new(format!("internal: type \"{}\" is not object", ty))
632
0
                            .into_server_error(ctx.item.pos),
633
                    )
634
0
                })?;
635
636
0
            resolve_container(
637
0
                schema,
638
0
                object_type,
639
0
                &ctx.with_selection_set(&ctx.item.node.selection_set),
640
0
                value,
641
0
                true,
642
0
            )
643
0
            .await
644
        }
645
0
        (Type::Union(union), _) => Err(ctx.set_error_path(
646
0
            Error::new(format!(
647
0
                "internal: invalid value for union \"{}\", expected \"FieldValue::WithType\"",
648
0
                union.name
649
0
            ))
650
0
            .into_server_error(ctx.item.pos),
651
0
        )),
652
0
        (Type::Subscription(subscription), _) => Err(ctx.set_error_path(
653
0
            Error::new(format!(
654
0
                "internal: cannot use subscription \"{}\" as output value",
655
0
                subscription.name
656
0
            ))
657
0
            .into_server_error(ctx.item.pos),
658
0
        )),
659
0
        (Type::Upload, _) => Err(ctx.set_error_path(
660
0
            Error::new("internal: cannot use upload as output value")
661
0
                .into_server_error(ctx.item.pos),
662
0
        )),
663
    }
664
0
}