1use go_parser::ast::{Expr, Node, NodeId};
6use go_parser::{IdentKey, Map};
7use go_types::{
8 check::TypeInfo, typ::BasicType, typ::ChanDir, typ::Type, ConstValue, EntityType,
9 ObjKey as TCObjKey, OperandMode, PackageKey as TCPackageKey, SelectionKind as TCSelectionKind,
10 TCObjects, TypeKey as TCTypeKey,
11};
12use go_vm::types::*;
13use go_vm::*;
14use std::vec;
15
16pub type TypeCache = Map<TCTypeKey, Meta>;
17
18#[derive(PartialEq)]
19pub enum SelectionType {
20 NonMethod,
21 MethodNonPtrRecv,
22 MethodPtrRecv,
23}
24
25pub(crate) struct TypeLookup<'a> {
26 tc_objs: &'a TCObjects,
27 ti: &'a TypeInfo,
28 types_cache: &'a mut TypeCache,
29}
30
31impl<'a> TypeLookup<'a> {
32 pub fn new(
33 tc_objs: &'a TCObjects,
34 ti: &'a TypeInfo,
35 types_cache: &'a mut TypeCache,
36 ) -> TypeLookup<'a> {
37 TypeLookup {
38 tc_objs,
39 ti,
40 types_cache,
41 }
42 }
43
44 #[inline]
45 pub fn type_info(&self) -> &TypeInfo {
46 self.ti
47 }
48
49 #[inline]
50 pub fn try_tc_const_value(&self, id: NodeId) -> Option<&ConstValue> {
51 let typ_val = self.ti.types.get(&id).unwrap();
52 typ_val.get_const_val()
53 }
54
55 #[inline]
56 pub fn const_type_value(&self, id: NodeId) -> (TCTypeKey, GosValue) {
57 let typ_val = self.ti.types.get(&id).unwrap();
58 let const_val = typ_val.get_const_val().unwrap();
59 (typ_val.typ, self.const_value(typ_val.typ, const_val))
60 }
61
62 #[inline]
63 pub fn ident_const_value(&self, id: &IdentKey) -> GosValue {
64 let lobj_key = self.ti.defs[id].unwrap();
65 let lobj = &self.tc_objs.lobjs[lobj_key];
66 let tkey = lobj.typ().unwrap();
67 self.const_value(tkey, lobj.const_val())
68 }
69
70 #[inline]
71 pub fn expr_tc_type(&self, e: &Expr) -> TCTypeKey {
72 self.node_tc_type(e.id())
73 }
74
75 #[inline]
76 pub fn node_tc_type(&self, id: NodeId) -> TCTypeKey {
77 self.ti.types.get(&id).unwrap().typ
78 }
79
80 #[inline]
81 pub fn try_expr_mode(&self, e: &Expr) -> Option<&OperandMode> {
82 self.ti.types.get(&e.id()).map(|x| &x.mode)
83 }
84
85 #[inline]
86 pub fn expr_mode(&self, e: &Expr) -> &OperandMode {
87 &self.ti.types.get(&e.id()).unwrap().mode
88 }
89
90 pub fn try_expr_tc_type(&self, e: &Expr) -> Option<TCTypeKey> {
92 self.ti
93 .types
94 .get(&e.id())
95 .map(|x| {
96 let typ = x.typ;
97 if self.tc_objs.types[typ].is_invalid(self.tc_objs) {
98 None
99 } else {
100 Some(typ)
101 }
102 })
103 .flatten()
104 }
105
106 pub fn try_pkg_key(&self, e: &Expr) -> Option<TCPackageKey> {
107 if let Expr::Ident(ikey) = e {
108 self.ti
109 .uses
110 .get(ikey)
111 .map(|x| {
112 if let EntityType::PkgName(pkg, _) = self.tc_objs.lobjs[*x].entity_type() {
113 Some(*pkg)
114 } else {
115 None
116 }
117 })
118 .flatten()
119 } else {
120 None
121 }
122 }
123
124 pub fn expr_value_type(&self, e: &Expr) -> ValueType {
125 let tv = self.ti.types.get(&e.id()).unwrap();
126 if tv.mode == OperandMode::TypeExpr {
127 ValueType::Metadata
128 } else {
129 let t = self.expr_tc_type(e);
130 self.tc_type_to_value_type(t)
131 }
132 }
133
134 pub fn sliceable_expr_value_types(
135 &mut self,
136 e: &Expr,
137 vmctx: &mut CodeGenVMCtx,
138 ) -> (ValueType, TCTypeKey) {
139 let tc_type = self.expr_tc_type(&e);
140 let typ = self.tc_objs.types[tc_type].underlying().unwrap_or(tc_type);
141 let meta = self.tc_type_to_meta(typ, vmctx);
142 let metas = &vmctx.metas();
143 match &metas[meta.key] {
144 MetadataType::Array(_, _) => (
145 ValueType::Array,
146 self.tc_objs.types[typ].try_as_array().unwrap().elem(),
147 ),
148 MetadataType::Slice(_) => (
149 ValueType::Slice,
150 self.tc_objs.types[typ].try_as_slice().unwrap().elem(),
151 ),
152 MetadataType::Str => (
153 ValueType::String,
154 self.tc_objs.universe().types()[&BasicType::Uint8],
155 ),
156 _ => unreachable!(),
157 }
158 }
159
160 pub fn node_meta(&mut self, id: NodeId, vmctx: &mut CodeGenVMCtx) -> Meta {
161 let tv = self.ti.types.get(&id).unwrap();
162 let md = self.tc_type_to_meta(tv.typ, vmctx);
163 if tv.mode == OperandMode::TypeExpr {
164 md.into_type_category()
165 } else {
166 md
167 }
168 }
169
170 #[inline]
171 pub fn object_use(&self, ikey: IdentKey) -> TCObjKey {
172 self.ti.uses[&ikey]
173 }
174
175 #[inline]
176 pub fn object_def(&self, ikey: IdentKey) -> TCObjKey {
177 self.ti.defs[&ikey].unwrap()
178 }
179
180 #[inline]
181 pub fn object_implicit(&self, id: &NodeId) -> TCObjKey {
182 self.ti.implicits[id]
183 }
184
185 #[inline]
186 pub fn obj_use_tc_type(&self, ikey: IdentKey) -> TCTypeKey {
187 self.obj_tc_type(self.object_use(ikey))
188 }
189
190 #[inline]
191 pub fn obj_use_value_type(&self, ikey: IdentKey) -> ValueType {
192 self.tc_type_to_value_type(self.obj_use_tc_type(ikey))
193 }
194
195 #[inline]
196 pub fn obj_def_tc_type(&self, ikey: IdentKey) -> TCTypeKey {
197 self.obj_tc_type(self.object_def(ikey))
198 }
199
200 #[inline]
201 pub fn obj_tc_type(&self, okey: TCObjKey) -> TCTypeKey {
202 let obj = &self.tc_objs.lobjs[okey];
203 obj.typ().unwrap()
204 }
205
206 #[inline]
207 pub fn ident_is_def(&self, ikey: &IdentKey) -> bool {
208 self.ti.defs.contains_key(ikey)
209 }
210
211 #[inline]
212 pub fn obj_def_meta(&mut self, ikey: IdentKey, vmctx: &mut CodeGenVMCtx) -> Meta {
213 self.tc_type_to_meta(self.obj_def_tc_type(ikey), vmctx)
214 }
215
216 #[inline]
217 pub fn expr_range_tc_types(&self, e: &Expr) -> [TCTypeKey; 3] {
218 let typ = self.ti.types.get(&e.id()).unwrap().typ;
219 self.range_tc_types(typ)
220 }
221
222 #[inline]
223 pub fn expr_tuple_tc_types(&self, e: &Expr) -> Vec<TCTypeKey> {
224 let typ = self.ti.types.get(&e.id()).unwrap().typ;
225 self.tuple_tc_types(typ)
226 }
227
228 pub fn selection_vtypes_indices_sel_typ(
229 &self,
230 id: NodeId,
231 ) -> (TCTypeKey, TCTypeKey, &Vec<usize>, SelectionType) {
232 let sel = &self.ti.selections[&id];
233 let recv_type = sel.recv().unwrap();
234 let obj = &self.tc_objs.lobjs[sel.obj()];
235 let expr_type = obj.typ().unwrap();
236 let sel_typ = if self.tc_objs.types[expr_type].try_as_signature().is_some() {
237 match obj.entity_type() {
238 EntityType::Func(ptr_recv) => match ptr_recv {
239 true => SelectionType::MethodPtrRecv,
240 false => SelectionType::MethodNonPtrRecv,
241 },
242 _ => SelectionType::NonMethod,
243 }
244 } else {
245 SelectionType::NonMethod
246 };
247 (recv_type, expr_type, &sel.indices(), sel_typ)
248 }
249
250 pub fn need_cast_container_index(&self, container: &Expr, index: &Expr) -> Option<TCTypeKey> {
251 let index_key = self.node_tc_type(index.id());
252 if self.tc_type_to_value_type(index_key) == ValueType::Interface {
253 return None;
254 }
255 let container_key = self.node_tc_type(container.id());
256 match &self.tc_objs.types[container_key] {
257 Type::Map(detail) => (self.tc_type_to_value_type(detail.key()) == ValueType::Interface)
258 .then_some(detail.key()),
259 _ => None,
260 }
261 }
262
263 pub fn tc_type_to_meta(&mut self, typ: TCTypeKey, vmctx: &mut CodeGenVMCtx) -> Meta {
264 if !self.types_cache.contains_key(&typ) {
265 let val = self.tc_type_to_meta_impl(typ, vmctx);
266 self.types_cache.insert(typ, val);
267 }
268 self.types_cache.get(&typ).unwrap().clone()
269 }
270
271 pub fn sig_params_tc_types(&self, func: TCTypeKey) -> (Vec<TCTypeKey>, Option<TCTypeKey>) {
272 let typ = &self.tc_objs.types[func].underlying_val(self.tc_objs);
273 let sig = typ.try_as_signature().unwrap();
274 let params: Vec<TCTypeKey> = self.tc_objs.types[sig.params()]
275 .try_as_tuple()
276 .unwrap()
277 .vars()
278 .iter()
279 .map(|&x| self.tc_objs.lobjs[x].typ().unwrap())
280 .collect();
281 let variadic = if sig.variadic() {
282 let slice_key = *params.last().unwrap();
283 match &self.tc_objs.types[slice_key] {
284 Type::Slice(s) => Some(s.elem()),
285 Type::Basic(_) => Some(*self.tc_objs.universe().byte()),
289 _ => unreachable!(),
290 }
291 } else {
292 None
293 };
294 (params, variadic)
295 }
296
297 pub fn sig_returns_tc_types(&self, func: TCTypeKey) -> Vec<TCTypeKey> {
298 let typ = &self.tc_objs.types[func].underlying_val(self.tc_objs);
299 let sig = typ.try_as_signature().unwrap();
300 self.tuple_tc_types(sig.results())
301 }
302
303 pub fn is_method(&self, expr: &Expr) -> bool {
304 match expr {
305 Expr::Selector(sel_expr) => match self.ti.selections.get(&sel_expr.id()) {
306 Some(sel) => match sel.kind() {
307 TCSelectionKind::MethodVal => true,
308 _ => false,
309 },
310 None => false,
311 },
312 _ => false,
313 }
314 }
315
316 pub fn basic_type_meta(&self, tkey: TCTypeKey, prim_meta: &PrimitiveMeta) -> Option<Meta> {
318 self.tc_objs.types[tkey].try_as_basic().map(|x| {
319 let typ = x.typ();
320 match typ {
321 BasicType::Bool | BasicType::UntypedBool => prim_meta.mbool,
322 BasicType::Int | BasicType::UntypedInt => prim_meta.mint,
323 BasicType::Int8 => prim_meta.mint8,
324 BasicType::Int16 => prim_meta.mint16,
325 BasicType::Int32 | BasicType::Rune | BasicType::UntypedRune => prim_meta.mint32,
326 BasicType::Int64 => prim_meta.mint64,
327 BasicType::Uint | BasicType::Uintptr => prim_meta.muint,
328 BasicType::Uint8 | BasicType::Byte => prim_meta.muint8,
329 BasicType::Uint16 => prim_meta.muint16,
330 BasicType::Uint32 => prim_meta.muint32,
331 BasicType::Uint64 => prim_meta.muint64,
332 BasicType::Float32 => prim_meta.mfloat32,
333 BasicType::Float64 | BasicType::UntypedFloat => prim_meta.mfloat64,
334 BasicType::Complex64 => prim_meta.mcomplex64,
335 BasicType::Complex128 => prim_meta.mcomplex128,
336 BasicType::Str | BasicType::UntypedString => prim_meta.mstr,
337 BasicType::UnsafePointer => prim_meta.unsafe_ptr,
338 BasicType::UntypedNil => prim_meta.none,
339 _ => {
340 dbg!(typ);
341 unreachable!()
342 }
343 }
344 })
345 }
346
347 fn const_value(&self, tkey: TCTypeKey, val: &ConstValue) -> GosValue {
349 let underlying_type = self.tc_objs.types[tkey].underlying().unwrap_or(tkey);
350 let typ = self.tc_type_to_value_type(underlying_type);
351 match typ {
352 ValueType::Bool => val.bool_as_bool().into(),
353 ValueType::Int => (val.to_int().int_as_i64().0 as isize).into(),
354 ValueType::Int8 => (val.to_int().int_as_i64().0 as i8).into(),
355 ValueType::Int16 => (val.to_int().int_as_i64().0 as i16).into(),
356 ValueType::Int32 => (val.to_int().int_as_i64().0 as i32).into(),
357 ValueType::Int64 => val.to_int().int_as_i64().0.into(),
358 ValueType::Uint => (val.to_int().int_as_u64().0 as usize).into(),
359 ValueType::UintPtr => FfiCtx::new_uint_ptr(val.to_int().int_as_u64().0 as usize),
360 ValueType::Uint8 => (val.to_int().int_as_u64().0 as u8).into(),
361 ValueType::Uint16 => (val.to_int().int_as_u64().0 as u16).into(),
362 ValueType::Uint32 => (val.to_int().int_as_u64().0 as u32).into(),
363 ValueType::Uint64 => val.to_int().int_as_u64().0.into(),
364 ValueType::Float32 => val.num_as_f32().0.into_inner().into(),
365 ValueType::Float64 => val.num_as_f64().0.into_inner().into(),
366 ValueType::Complex64 => {
367 let (cr, ci, _) = val.to_complex().complex_as_complex64();
368 FfiCtx::new_complex64(cr.0, ci.0)
369 }
370 ValueType::Complex128 => {
371 let (cr, ci, _) = val.to_complex().complex_as_complex128();
372 FfiCtx::new_complex128(cr.0, ci.0)
373 }
374 ValueType::String => FfiCtx::new_string(&val.str_as_string()),
375 ValueType::UnsafePtr => FfiCtx::new_nil(ValueType::UnsafePtr),
376 _ => {
377 dbg!(typ);
378 unreachable!();
379 }
380 }
381 }
382
383 fn tc_type_to_meta_impl(&mut self, typ: TCTypeKey, vmctx: &mut CodeGenVMCtx) -> Meta {
385 match &self.tc_objs.types[typ] {
386 Type::Basic(_) => self.basic_type_meta(typ, vmctx.prim_meta()).unwrap(),
387 Type::Array(detail) => {
388 let elem = self.tc_type_to_meta_impl(detail.elem(), vmctx);
389 Meta::new_array(elem, detail.len().unwrap() as usize, vmctx.metas_mut())
390 }
391 Type::Slice(detail) => {
392 let el_type = self.tc_type_to_meta(detail.elem(), vmctx);
393 Meta::new_slice(el_type, vmctx.metas_mut())
394 }
395 Type::Map(detail) => {
396 let ktype = self.tc_type_to_meta(detail.key(), vmctx);
397 let vtype = self.tc_type_to_meta(detail.elem(), vmctx);
398 Meta::new_map(ktype, vtype, vmctx.metas_mut())
399 }
400 Type::Struct(detail) => {
401 let fields = self.build_fields(detail.fields(), detail.tags(), vmctx);
402 vmctx.new_struct_meta(fields)
403 }
404 Type::Interface(detail) => {
405 let methods = detail.all_methods();
406 let fields = self.build_fields(methods.as_ref().unwrap(), &None, vmctx);
407 Meta::new_interface(fields, vmctx.metas_mut())
408 }
409 Type::Chan(detail) => {
410 let typ = match detail.dir() {
411 ChanDir::RecvOnly => ChannelType::Recv,
412 ChanDir::SendOnly => ChannelType::Send,
413 ChanDir::SendRecv => ChannelType::SendRecv,
414 };
415 let vmeta = self.tc_type_to_meta(detail.elem(), vmctx);
416 Meta::new_channel(typ, vmeta, vmctx.metas_mut())
417 }
418 Type::Signature(detail) => {
419 let mut convert = |tuple_key| -> Vec<Meta> {
420 self.tc_objs.types[tuple_key]
421 .try_as_tuple()
422 .unwrap()
423 .vars()
424 .iter()
425 .map(|&x| self.tc_type_to_meta(self.tc_objs.lobjs[x].typ().unwrap(), vmctx))
426 .collect()
427 };
428 let params = convert(detail.params());
429 let results = convert(detail.results());
430 let mut recv = None;
431 if let Some(r) = detail.recv() {
432 let recv_tc_type = self.tc_objs.lobjs[*r].typ().unwrap();
433 if !self.tc_objs.types[recv_tc_type].is_interface(self.tc_objs) {
435 recv = Some(self.tc_type_to_meta(recv_tc_type, vmctx));
436 }
437 }
438 let variadic = if detail.variadic() {
439 let slice = params.last().unwrap();
440 match &vmctx.metas()[slice.key] {
441 MetadataType::Slice(elem) => Some((*slice, elem.clone())),
442 _ => unreachable!(),
443 }
444 } else {
445 None
446 };
447 Meta::new_sig(recv, params, results, variadic, vmctx.metas_mut())
448 }
449 Type::Pointer(detail) => {
450 let inner = self.tc_type_to_meta(detail.base(), vmctx);
451 inner.ptr_to()
452 }
453 Type::Named(detail) => {
454 let md = Meta::new_named(vmctx.prim_meta().mint, vmctx.metas_mut());
456 for key in detail.methods().iter() {
457 let mobj = &self.tc_objs.lobjs[*key];
458 md.add_method(
459 mobj.name().clone(),
460 mobj.entity_type().func_has_ptr_recv(),
461 vmctx.metas_mut(),
462 )
463 }
464 self.types_cache.insert(typ, md);
465 let underlying = self.tc_type_to_meta(detail.underlying(), vmctx);
466 let (_, underlying_mut) = vmctx.metas_mut()[md.key].as_named_mut();
467 *underlying_mut = underlying;
468 md
469 }
470 _ => {
471 dbg!(&self.tc_objs.types[typ]);
472 unimplemented!()
473 }
474 }
475 }
476
477 pub fn underlying_tc(&self, typ: TCTypeKey) -> TCTypeKey {
478 match &self.tc_objs.types[typ] {
479 Type::Named(n) => n.underlying(),
480 _ => typ,
481 }
482 }
483
484 pub fn obj_underlying_value_type(&self, typ: TCTypeKey) -> ValueType {
485 self.tc_type_to_value_type(self.underlying_tc(typ))
486 }
487
488 pub fn tc_type_to_value_type(&self, typ: TCTypeKey) -> ValueType {
489 match &self.tc_objs.types[typ] {
490 Type::Basic(detail) => match detail.typ() {
491 BasicType::Bool | BasicType::UntypedBool => ValueType::Bool,
492 BasicType::Int | BasicType::UntypedInt => ValueType::Int,
493 BasicType::Int8 => ValueType::Int8,
494 BasicType::Int16 => ValueType::Int16,
495 BasicType::Int32 | BasicType::Rune | BasicType::UntypedRune => ValueType::Int32,
496 BasicType::Int64 => ValueType::Int64,
497 BasicType::Uint => ValueType::Uint,
498 BasicType::Uintptr => ValueType::UintPtr,
499 BasicType::Uint8 | BasicType::Byte => ValueType::Uint8,
500 BasicType::Uint16 => ValueType::Uint16,
501 BasicType::Uint32 => ValueType::Uint32,
502 BasicType::Uint64 => ValueType::Uint64,
503 BasicType::Float32 => ValueType::Float32,
504 BasicType::Float64 | BasicType::UntypedFloat => ValueType::Float64,
505 BasicType::Complex64 => ValueType::Complex64,
506 BasicType::Complex128 => ValueType::Complex128,
507 BasicType::Str | BasicType::UntypedString => ValueType::String,
508 BasicType::UnsafePointer => ValueType::UnsafePtr,
509 BasicType::UntypedNil => ValueType::Void,
510 _ => {
511 dbg!(detail.typ());
512 unreachable!()
513 }
514 },
515 Type::Array(_) => ValueType::Array,
516 Type::Slice(_) => ValueType::Slice,
517 Type::Map(_) => ValueType::Map,
518 Type::Struct(_) => ValueType::Struct,
519 Type::Interface(_) => ValueType::Interface,
520 Type::Chan(_) => ValueType::Channel,
521 Type::Signature(_) => ValueType::Closure,
522 Type::Pointer(_) => ValueType::Pointer,
523 Type::Named(n) => self.tc_type_to_value_type(n.underlying()),
524 _ => {
525 dbg!(&self.tc_objs.types[typ]);
526 unimplemented!()
527 }
528 }
529 }
530
531 pub fn slice_elem_type(&self, typ: TCTypeKey) -> ValueType {
532 match &self.tc_objs.types[typ] {
533 Type::Slice(s) => self.tc_type_to_value_type(s.elem()),
534 _ => unreachable!(),
535 }
536 }
537
538 pub fn bool_tc_type(&self) -> TCTypeKey {
539 self.tc_objs.universe().types()[&BasicType::Bool]
540 }
541
542 pub fn should_cast_to_iface(&self, lhs: TCTypeKey, rhs: TCTypeKey) -> bool {
543 let vt1 = self.obj_underlying_value_type(rhs);
544 self.obj_underlying_value_type(lhs) == ValueType::Interface
545 && vt1 != ValueType::Interface
546 && vt1 != ValueType::Void
547 }
548
549 fn range_tc_types(&self, typ: TCTypeKey) -> [TCTypeKey; 3] {
550 let t_int = self.tc_objs.universe().types()[&BasicType::Int];
551 let typ = self.tc_objs.types[typ].underlying().unwrap_or(typ);
552 match &self.tc_objs.types[typ] {
553 Type::Basic(detail) => match detail.typ() {
554 BasicType::Str | BasicType::UntypedString => [typ, t_int, t_int],
555 _ => unreachable!(),
556 },
557 Type::Slice(detail) => [typ, t_int, detail.elem()],
558 Type::Array(detail) => [typ, t_int, detail.elem()],
559 Type::Map(detail) => [typ, detail.key(), detail.elem()],
560 _ => {
561 dbg!(&self.tc_objs.types[typ]);
562 unreachable!()
563 }
564 }
565 }
566
567 fn tuple_tc_types(&self, typ: TCTypeKey) -> Vec<TCTypeKey> {
568 match &self.tc_objs.types[typ] {
569 Type::Tuple(detail) => detail
570 .vars()
571 .iter()
572 .map(|x| self.tc_objs.lobjs[*x].typ().unwrap())
573 .collect(),
574 _ => unreachable!(),
575 }
576 }
577
578 pub fn iface_binding_info(
579 &mut self,
580 i_s: (TCTypeKey, TCTypeKey),
581 vmctx: &mut CodeGenVMCtx,
582 ) -> (Meta, Vec<IfaceBinding>) {
583 let iface = self.tc_type_to_meta(i_s.0, vmctx);
584 let named = self.tc_type_to_meta(i_s.1, vmctx);
585 let metas = vmctx.metas();
586 iface.bind_with_iface(named, metas)
587 }
588
589 fn build_fields(
590 &mut self,
591 fields: &Vec<TCObjKey>,
592 tags: &Option<Vec<Option<String>>>,
593 vmctx: &mut CodeGenVMCtx,
594 ) -> Fields {
595 let mut infos = Vec::new();
596 let mut embedded_fields = Vec::new();
597 for (i, f) in fields.iter().enumerate() {
598 let field = &self.tc_objs.lobjs[*f];
599 let tag = match tags {
600 Some(tags) => tags[i].clone(),
601 None => None,
602 };
603 let meta = self.tc_type_to_meta(field.typ().unwrap(), vmctx);
604 let embedded =
605 field.entity_type().is_var() && field.entity_type().var_property().embedded;
606 infos.push(FieldInfo {
607 meta,
608 name: field.name().clone(),
609 tag,
610 embedded_indices: None,
611 });
612 if embedded {
613 embedded_fields.push((meta, i));
614 }
615 }
616
617 for (meta, i) in embedded_fields {
618 match meta.mtype_unwraped(&vmctx.metas()) {
619 MetadataType::Struct(fields) => {
620 for (j, f) in fields.infos().iter().enumerate() {
621 let mut indices = vec![i];
622 match f.embedded_indices.clone() {
623 Some(mut ins) => indices.append(&mut ins),
624 None => indices.push(j),
625 };
626 infos.push(FieldInfo {
627 meta: f.meta,
628 name: f.name.clone(),
629 tag: f.tag.clone(),
630 embedded_indices: Some(indices),
631 });
632 }
633 }
634 _ => {}
635 }
636 }
637
638 Fields::new(infos)
639 }
640}