go_types/check/
typexpr.rs

1// Copyright 2022 The Goscript Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style
3// license that can be found in the LICENSE file.
4//
5//
6// This code is adapted from the offical Go code written in Go
7// with license as follows:
8// Copyright 2013 The Go Authors. All rights reserved.
9// Use of this source code is governed by a BSD-style
10// license that can be found in the LICENSE file.
11
12#![allow(dead_code)]
13use super::super::constant;
14use super::super::lookup;
15use super::super::obj::EntityType;
16use super::super::objects::{ObjKey, ScopeKey, TCObjects, TypeKey};
17use super::super::operand::{Operand, OperandMode};
18use super::super::scope::Scope;
19use super::super::typ::{self, Type};
20use super::check::{Checker, FilesContext, ObjContext};
21use super::interface::MethodInfo;
22use crate::SourceRead;
23use go_parser::ast::{self, Expr, FieldList, Node};
24use go_parser::{FuncTypeKey, IdentKey, Map, Pos, Token};
25use std::borrow::Borrow;
26
27impl<'a, S: SourceRead> Checker<'a, S> {
28    /// ident type-checks identifier ikey and initializes x with the value or type of ikey.
29    /// If an error occurred, x.mode is set to invalid.
30    /// For the meaning of def, see Checker.defined_type, below.
31    /// If want_type is set, the identifier e is expected to denote a type.
32    pub fn ident(
33        &mut self,
34        x: &mut Operand,
35        ikey: IdentKey,
36        def: Option<TypeKey>,
37        want_type: bool,
38        fctx: &mut FilesContext<S>,
39    ) {
40        x.mode = OperandMode::Invalid;
41        x.expr = Some(Expr::Ident(ikey));
42
43        // Note that we cannot use check.lookup here because the returned scope
44        // may be different from obj.parent(). See also Scope.lookup_parent doc.
45        let name = &self.ast_ident(ikey).name;
46        if let Some((skey, okey)) =
47            Scope::lookup_parent(&self.octx.scope.unwrap(), name, self.octx.pos, self.tc_objs)
48        {
49            self.result.record_use(ikey, okey);
50
51            // Type-check the object.
52            // Only call Checker.obj_decl if the object doesn't have a type yet
53            // (in which case we must actually determine it) or the object is a
54            // TypeName and we also want a type (in which case we might detect
55            // a cycle which needs to be reported). Otherwise we can skip the
56            // call and avoid a possible cycle error in favor of the more
57            // informative "not a type/value" error that this function's caller
58            // will issue
59            let lobj = self.lobj(okey);
60            let pkg = lobj.pkg();
61            let mut otype = lobj.typ();
62            if otype.is_none() || (lobj.entity_type().is_type_name() && want_type) {
63                self.obj_decl(okey, def, fctx);
64                // type must have been assigned by Checker.obj_decl
65                otype = self.lobj(okey).typ();
66            }
67            debug_assert!(otype.is_some());
68
69            // The object may be dot-imported: If so, remove its package from
70            // the map of unused dot imports for the respective file scope.
71            // (This code is only needed for dot-imports. Without them,
72            // we only have to mark variables, see Var case below).
73            if pkg.is_some() && pkg != Some(self.pkg) {
74                fctx.unused_dot_imports
75                    .get_mut(&skey)
76                    .unwrap()
77                    .remove(&pkg.unwrap());
78            }
79
80            let lobj = self.lobj(okey);
81            let invalid_type = self.invalid_type();
82            match lobj.entity_type() {
83                EntityType::PkgName(_, _) => {
84                    let pos = self.ast_ident(ikey).pos;
85                    let msg = format!("use of package {} not in selector", lobj.name());
86                    self.error(pos, msg);
87                    return;
88                }
89                EntityType::Const(_) => {
90                    self.add_decl_dep(okey);
91                    if otype == Some(invalid_type) {
92                        return;
93                    }
94                    if okey == *self.tc_objs.universe().iota() {
95                        if self.octx.iota.is_none() {
96                            let pos = self.ast_ident(ikey).pos;
97                            self.error_str(pos, "cannot use iota outside constant declaration");
98                            return;
99                        }
100                        x.mode = OperandMode::Constant(self.octx.iota.clone().unwrap());
101                    } else {
102                        x.mode = OperandMode::Constant(self.lobj(okey).const_val().clone());
103                    }
104                }
105                EntityType::TypeName => x.mode = OperandMode::TypeExpr,
106                EntityType::Var(_) => {
107                    // It's ok to mark non-local variables, but ignore variables
108                    // from other packages to avoid potential race conditions with
109                    // dot-imported variables.
110                    if lobj.pkg() == Some(self.pkg) {
111                        self.lobj_mut(okey)
112                            .entity_type_mut()
113                            .var_property_mut()
114                            .used = true;
115                    }
116                    self.add_decl_dep(okey);
117                    if otype == Some(invalid_type) {
118                        return;
119                    }
120                    x.mode = OperandMode::Variable;
121                }
122                EntityType::Func(_) => {
123                    self.add_decl_dep(okey);
124                    x.mode = OperandMode::Value;
125                }
126                EntityType::Label(_) => unreachable!(),
127                EntityType::Builtin(id) => x.mode = OperandMode::Builtin(*id),
128                EntityType::Nil => x.mode = OperandMode::Value,
129            }
130            x.typ = otype;
131        } else {
132            let pos = self.ast_ident(ikey).pos;
133            if name == "_" {
134                self.error(pos, "cannot use _ as value or type".to_owned());
135            } else {
136                self.error(pos, format!("undeclared name: {}", name));
137            }
138        }
139    }
140
141    /// type_expr type-checks the type expression e and returns its type, or Invalid Type.
142    pub fn type_expr(&mut self, e: &Expr, fctx: &mut FilesContext<S>) -> TypeKey {
143        self.defined_type(e, None, fctx)
144    }
145
146    /// defined_type is like type_expr but also accepts a type name def.
147    /// If def is_some(), e is the type specification for the defined type def, declared
148    /// in a type declaration, and def.underlying will be set to the type of e before
149    /// any components of e are type-checked.
150    pub fn defined_type(
151        &mut self,
152        e: &Expr,
153        def: Option<TypeKey>,
154        fctx: &mut FilesContext<S>,
155    ) -> TypeKey {
156        if self.trace() {
157            let ed = self.new_dis(e);
158            self.trace_begin(ed.pos(), &format!("{}", ed));
159        }
160        let t = self.type_internal(e, def, fctx);
161        debug_assert!(typ::is_typed(t, self.tc_objs));
162        self.result
163            .record_type_and_value(e, OperandMode::TypeExpr, t);
164        if self.trace() {
165            let pos = e.pos(self.ast_objs);
166            self.trace_end(pos, &format!("=> {}", self.new_dis(&t)));
167        }
168        t
169    }
170
171    /// indirect_type is like type_expr but it also breaks the (otherwise) infinite size of
172    /// recursivetypes by introducing an indirection. It should be called for components of
173    /// types that are not laid out in place in memory, such as pointer base types, slice or
174    /// map element types, function parameter types, etc.
175    pub fn indirect_type(&mut self, e: &Expr, fctx: &mut FilesContext<S>) -> TypeKey {
176        fctx.push(*self.tc_objs.universe().indir());
177        let t = self.defined_type(e, None, fctx);
178        fctx.pop();
179        t
180    }
181
182    /// func_type type-checks a function or method type.
183    pub fn func_type(
184        &mut self,
185        recv: Option<&FieldList>,
186        ftype: FuncTypeKey,
187        fctx: &mut FilesContext<S>,
188    ) -> TypeKey {
189        let skey = self
190            .tc_objs
191            .new_scope(self.octx.scope, 0, 0, "function".to_owned(), true);
192        self.result.record_scope(&ftype, skey);
193
194        let (recv_list, _) = self.collect_params(skey, recv, false, fctx);
195        let ftype_val = &self.ast_objs.ftypes[ftype];
196        let (p, r) = (ftype_val.params.clone(), ftype_val.results.clone());
197        let (params, variadic) = self.collect_params(skey, Some(&p), true, fctx);
198        let (results, _) = self.collect_params(skey, r.as_ref(), false, fctx);
199
200        let mut recv_okey = None;
201        if recv.is_some() {
202            // recv parameter list present (may be empty)
203            // spec: "The receiver is specified via an extra parameter section preceding the
204            // method name. That parameter section must declare a single parameter, the receiver."
205            let invalid_type = self.invalid_type();
206            let recv_var = match recv_list.len() {
207                x if x == 0 => {
208                    let pos = recv.unwrap().pos(self.ast_objs);
209                    self.error_str(pos, "method is missing receiver");
210                    self.tc_objs
211                        .new_param_var(0, None, "".to_owned(), Some(invalid_type))
212                }
213                x if x > 1 => {
214                    let pos = self.lobj(recv_list[recv_list.len() - 1]).pos();
215                    self.error_str(pos, "method must have exactly one receiver");
216                    recv_list[0] // continue with first receiver
217                }
218                x if x == 1 => recv_list[0],
219                _ => unreachable!(),
220            };
221            recv_okey = Some(recv_var);
222
223            // spec: "The receiver type must be of the form T or *T where T is a type name."
224            // (ignore invalid types - error was reported before)
225            let recv_var_val = self.lobj(recv_var);
226            let recv_type = recv_var_val.typ().unwrap();
227            let (t, _) = lookup::try_deref(recv_type, self.tc_objs);
228            if t != invalid_type {
229                let err_msg = if let Some(n) = self.otype(t).try_as_named() {
230                    // spec: "The type denoted by T is called the receiver base type; it must not
231                    // be a pointer or interface type and it must be declared in the same package
232                    // as the method."
233                    if self.lobj(n.obj().unwrap()).pkg() != Some(self.pkg) {
234                        Some("type not defined in this package")
235                    } else {
236                        match self.otype(n.underlying()) {
237                            typ::Type::Basic(b) => {
238                                if b.typ() == typ::BasicType::UnsafePointer {
239                                    Some("unsafe.Pointer")
240                                } else {
241                                    None
242                                }
243                            }
244                            typ::Type::Pointer(_) | typ::Type::Interface(_) => {
245                                Some("pointer or interface type")
246                            }
247                            _ => None,
248                        }
249                    }
250                } else {
251                    Some("basic or unnamed type")
252                };
253                if let Some(err) = err_msg {
254                    let pos = recv_var_val.pos();
255                    let td = self.new_dis(&recv_type);
256                    self.error(pos, format!("invalid receiver {} ({})", td, err));
257                    // ok to continue
258                }
259            }
260        }
261
262        let params_tuple = self.tc_objs.new_t_tuple(params);
263        let results_tuple = self.tc_objs.new_t_tuple(results);
264        self.tc_objs
265            .new_t_signature(Some(skey), recv_okey, params_tuple, results_tuple, variadic)
266    }
267
268    /// type_internal drives type checking of types.
269    /// Must only be called by defined_type.
270    fn type_internal(
271        &mut self,
272        e: &Expr,
273        def: Option<TypeKey>,
274        fctx: &mut FilesContext<S>,
275    ) -> TypeKey {
276        let set_underlying = |typ: Option<TypeKey>, tc_objs: &mut TCObjects| {
277            if let Some(d) = def {
278                tc_objs.types[d]
279                    .try_as_named_mut()
280                    .unwrap()
281                    .set_underlying(typ.unwrap());
282            }
283        };
284        let pos = e.pos(self.ast_objs);
285        let result_t: Option<TypeKey> = match e {
286            Expr::Bad(_) => None,
287            Expr::Ident(i) => {
288                let mut x = Operand::new();
289                self.ident(&mut x, *i, def, true, fctx);
290                match x.mode {
291                    OperandMode::TypeExpr => {
292                        set_underlying(x.typ, self.tc_objs);
293                        x.typ
294                    }
295                    OperandMode::Invalid => None, // ignore - error reported before
296                    OperandMode::NoValue => {
297                        error_operand!(x, "{} used as type", self);
298                        None
299                    }
300                    _ => {
301                        error_operand!(x, "{} is not a type", self);
302                        None
303                    }
304                }
305            }
306            Expr::Selector(s) => {
307                let mut x = Operand::new();
308                self.selector(&mut x, s, fctx);
309                match x.mode {
310                    OperandMode::TypeExpr => {
311                        set_underlying(x.typ, self.tc_objs);
312                        x.typ
313                    }
314                    OperandMode::Invalid => None, // ignore - error reported before
315                    OperandMode::NoValue => {
316                        error_operand!(x, "{} used as type", self);
317                        None
318                    }
319                    _ => {
320                        error_operand!(x, "{} is not a type", self);
321                        None
322                    }
323                }
324            }
325            Expr::Paren(p) => Some(self.defined_type(&p.expr, def, fctx)),
326            Expr::Array(a) => {
327                if let Some(l) = &a.len {
328                    let len = self.array_len(&l, fctx);
329                    let elem = self.type_expr(&a.elt, fctx);
330                    let t = self.tc_objs.new_t_array(elem, len);
331                    set_underlying(Some(t), self.tc_objs);
332                    Some(t)
333                } else {
334                    let elem = self.indirect_type(&a.elt, fctx);
335                    let t = self.tc_objs.new_t_slice(elem);
336                    set_underlying(Some(t), self.tc_objs);
337                    Some(t)
338                }
339            }
340            Expr::Struct(s) => {
341                let t = self.struct_type(s, fctx);
342                set_underlying(Some(t), self.tc_objs);
343                Some(t)
344            }
345            Expr::Star(s) => {
346                let base = self.indirect_type(&s.expr, fctx);
347                let t = self.tc_objs.new_t_pointer(base);
348                set_underlying(Some(t), self.tc_objs);
349                Some(t)
350            }
351            Expr::Func(f) => {
352                let t = self.func_type(None, *f, fctx);
353                set_underlying(Some(t), self.tc_objs);
354                Some(t)
355            }
356            Expr::Interface(_) => {
357                let t = self.interface_type(e, def, fctx);
358                set_underlying(Some(t), self.tc_objs);
359                Some(t)
360            }
361            Expr::Map(m) => {
362                let k = self.indirect_type(&m.key, fctx);
363                let v = self.indirect_type(&m.val, fctx);
364                let t = self.tc_objs.new_t_map(k, v);
365                set_underlying(Some(t), self.tc_objs);
366
367                let pos = m.key.pos(self.ast_objs);
368                let f = move |checker: &mut Checker<S>, _: &mut FilesContext<S>| {
369                    if !typ::comparable(k, checker.tc_objs) {
370                        let td = checker.new_dis(&k);
371                        checker.error(pos, format!("invalid map key type {}", td));
372                    }
373                };
374                fctx.later(Box::new(f));
375
376                Some(t)
377            }
378            Expr::Chan(chan) => {
379                let dir = match chan.dir {
380                    ast::ChanDir::Send => typ::ChanDir::SendOnly,
381                    ast::ChanDir::Recv => typ::ChanDir::RecvOnly,
382                    ast::ChanDir::SendRecv => typ::ChanDir::SendRecv,
383                };
384                let elem = self.indirect_type(&chan.val, fctx);
385                let t = self.tc_objs.new_t_chan(dir, elem);
386                set_underlying(Some(t), self.tc_objs);
387                Some(t)
388            }
389            _ => {
390                let ed = self.new_dis(e);
391                self.error(pos, format!("{} is not a type", ed));
392                None
393            }
394        };
395        if let Some(t) = result_t {
396            t
397        } else {
398            let invalid_type = self.invalid_type();
399            set_underlying(Some(invalid_type), self.tc_objs);
400            invalid_type
401        }
402    }
403
404    /// type_or_nil type-checks the type expression (or nil value) e
405    /// and returns the typ of e, or None.
406    /// If e is neither a type nor nil, typOrNil returns Typ\[Invalid\].
407    pub fn type_or_nil(&mut self, e: &Expr, fctx: &mut FilesContext<S>) -> Option<TypeKey> {
408        let mut x = Operand::new();
409        self.raw_expr(&mut x, e, None, fctx);
410        let invalid_type = self.invalid_type();
411        match x.mode {
412            OperandMode::Invalid => Some(invalid_type), // ignore - error reported before
413            OperandMode::NoValue => {
414                error_operand!(x, "{} used as type", self);
415                Some(invalid_type)
416            }
417            OperandMode::TypeExpr => x.typ,
418            _ => {
419                if x.mode == OperandMode::Value && x.is_nil(self.tc_objs.universe()) {
420                    None
421                } else {
422                    error_operand!(x, "{} is not a type", self);
423                    Some(invalid_type)
424                }
425            }
426        }
427    }
428
429    fn array_len(&mut self, e: &Expr, fctx: &mut FilesContext<S>) -> Option<u64> {
430        let mut x = Operand::new();
431        self.expr(&mut x, e, fctx);
432        if let OperandMode::Constant(v) = &x.mode {
433            let t = x.typ.unwrap();
434            if typ::is_untyped(t, self.tc_objs) || typ::is_integer(t, self.tc_objs) {
435                let int = v.to_int();
436                let int_type = self
437                    .otype(self.basic_type(typ::BasicType::Int))
438                    .try_as_basic()
439                    .unwrap();
440                if let constant::Value::Int(_) = int.borrow() {
441                    if int.representable(int_type, None) {
442                        let (n, exact) = int.int_as_u64();
443                        if exact {
444                            return Some(n);
445                        } else {
446                            error_operand!(x, "invalid array length {}", self);
447                            return None;
448                        }
449                    }
450                }
451            }
452            error_operand!(x, "array length {} must be integer", self);
453        } else {
454            if x.mode != OperandMode::Invalid {
455                error_operand!(x, "array length {} must be constant", self);
456            }
457        }
458        None
459    }
460
461    fn collect_params(
462        &mut self,
463        skey: ScopeKey,
464        fl: Option<&FieldList>,
465        variadic_ok: bool,
466        fctx: &mut FilesContext<S>,
467    ) -> (Vec<ObjKey>, bool) {
468        if let Some(l) = fl {
469            let (mut named, mut anonymous, mut variadic) = (false, false, false);
470            let mut params = Vec::new();
471            for (i, fkey) in l.list.iter().enumerate() {
472                let field = &self.ast_objs.fields[*fkey];
473                let mut ftype = &field.typ;
474                let field_names = field.names.clone();
475                if let Expr::Ellipsis(elli) = ftype {
476                    ftype = elli.elt.as_ref().unwrap();
477                    if variadic_ok && i == l.list.len() - 1 && field_names.len() <= 1 {
478                        variadic = true
479                    } else {
480                        self.soft_error(
481                            elli.pos,
482                            "can only use ... with final parameter in list".to_owned(),
483                        )
484                        // ignore ... and continue
485                    }
486                }
487                let ftype = &ftype.clone();
488                let ty = self.indirect_type(ftype, fctx);
489                // The parser ensures that f.Tag is nil and we don't
490                // care if a constructed AST contains a non-nil tag.
491                if field_names.len() > 0 {
492                    for name in field_names.iter() {
493                        let ident = &self.ast_objs.idents[*name];
494                        if ident.name == "" {
495                            self.invalid_ast(ident.pos, "anonymous parameter");
496                            // ok to continue
497                        }
498                        let par_name = ident.name.clone();
499                        let par = self.tc_objs.new_param_var(
500                            ident.pos,
501                            Some(self.pkg),
502                            par_name,
503                            Some(ty),
504                        );
505                        let scope_pos = self.scope(skey).pos();
506                        self.declare(skey, Some(*name), par, scope_pos);
507                        params.push(par);
508                    }
509                    named = true;
510                } else {
511                    // anonymous parameter
512                    let par = self.tc_objs.new_param_var(
513                        ftype.pos(self.ast_objs),
514                        Some(self.pkg),
515                        "".to_owned(),
516                        Some(ty),
517                    );
518                    self.result.record_implicit(fkey, par);
519                    params.push(par);
520                    anonymous = true;
521                }
522            }
523            if named && anonymous {
524                self.invalid_ast(
525                    l.pos(self.ast_objs),
526                    "list contains both named and anonymous parameters",
527                )
528                // ok to continue
529            }
530            // For a variadic function, change the last parameter's type from T to []T.
531            // Since we type-checked T rather than ...T, we also need to retro-actively
532            // record the type for ...T.
533            if variadic {
534                let last = params[params.len() - 1];
535                let t = self.tc_objs.new_t_slice(self.lobj(last).typ().unwrap());
536                self.lobj_mut(last).set_type(Some(t));
537                let e = &self.ast_objs.fields[l.list[l.list.len() - 1]].typ;
538                self.result
539                    .record_type_and_value(e, OperandMode::TypeExpr, t);
540            }
541            (params, variadic)
542        } else {
543            (vec![], false)
544        }
545    }
546
547    fn interface_type(
548        &mut self,
549        expr: &ast::Expr,
550        def: Option<TypeKey>,
551        fctx: &mut FilesContext<S>,
552    ) -> TypeKey {
553        let iface = match expr {
554            Expr::Interface(i) => i,
555            _ => unreachable!(),
556        };
557        if iface.methods.list.len() == 0 {
558            return self.tc_objs.new_t_empty_interface();
559        }
560        let trace = self.trace();
561
562        let itype = self.tc_objs.new_t_interface(vec![], vec![]);
563        // collect embedded interfaces
564        // Only needed for printing and API. Delay collection
565        // to end of type-checking (for package-global interfaces)
566        // when all types are complete. Local interfaces are handled
567        // after each statement (as each statement processes delayed
568        // functions).
569        let context_clone = self.octx.clone();
570        let expr_clone = expr.clone();
571        let iface_clone = iface.clone();
572        let f = move |checker: &mut Checker<S>, fctx: &mut FilesContext<S>| {
573            if trace {
574                let ed = checker.new_dis(&expr_clone);
575                let msg = format!("-- delayed checking embedded interfaces of {}", ed);
576                checker.trace_begin(iface_clone.interface, &msg);
577            }
578            //replace checker's ctx with context_clone
579            let ctx_backup = std::mem::replace(&mut checker.octx, context_clone);
580
581            let mut embeds = vec![];
582            for fkey in iface_clone.methods.list.iter() {
583                let field = &checker.ast_objs.fields[*fkey];
584                if field.names.len() == 0 {
585                    let texpr = field.typ.clone();
586                    let ty = checker.indirect_type(&texpr, fctx);
587                    // ty should be a named type denoting an interface
588                    // (the parser will make sure it's a named type but
589                    // constructed ASTs may be wrong).
590                    if ty == checker.invalid_type() {
591                        continue; // error reported before
592                    }
593                    match checker.otype(typ::underlying_type(ty, checker.tc_objs)) {
594                        typ::Type::Interface(embed) => {
595                            // Correct embedded interfaces must be complete
596                            assert!(embed.all_methods().is_some());
597                        }
598                        _ => {
599                            let pos = texpr.pos(checker.ast_objs);
600                            let td = checker.new_dis(&ty);
601                            checker.error(pos, format!("{} is not an interface", td));
602                            continue;
603                        }
604                    }
605                    // collect interface
606                    embeds.push(ty);
607                }
608            }
609            embeds.sort_by(compare_by_type_name!(checker.tc_objs));
610            *checker.otype_interface_mut(itype).embeddeds_mut() = embeds;
611
612            // restore ctx
613            checker.octx = ctx_backup;
614            // trace_end
615            if trace {
616                checker.trace_end(
617                    iface_clone.interface,
618                    "-- end of delayed checking embedded interfaces",
619                )
620            }
621        };
622        fctx.later(Box::new(f));
623
624        // compute method set
625        let (tname, path) = if let Some(d) = def {
626            let t = *self.otype(d).try_as_named().unwrap().obj();
627            (t, vec![t.unwrap()])
628        } else {
629            (None, vec![])
630        };
631        let info = self.info_from_type_lit(self.octx.scope.unwrap(), iface, tname, &path, fctx);
632        if info.is_none() || info.as_ref().unwrap().as_ref().borrow().is_empty() {
633            // we got an error or the empty interface - exit early
634            self.otype_interface_mut(itype).set_empty_complete();
635            return itype;
636        }
637
638        // use named receiver type if available (for better error messages)
639        let recv_type = if let Some(d) = def { d } else { itype };
640
641        // Correct receiver type for all methods explicitly declared
642        // by this interface after we're done with type-checking at
643        // this level. See comment below for details.
644        let f = move |checker: &mut Checker<S>, _: &mut FilesContext<S>| {
645            for m in checker.otype_interface(itype).methods().clone().iter() {
646                let t = checker.lobj(*m).typ().unwrap();
647                let o = checker.otype_signature(t).recv().unwrap();
648                checker.lobj_mut(o).set_type(Some(recv_type));
649            }
650        };
651        fctx.later(Box::new(f));
652
653        // collect methods
654        let info_ref = info.as_ref().unwrap().as_ref().borrow();
655        let explicits = info_ref.explicits;
656        let mut sig_fix: Vec<MethodInfo> = vec![];
657        for (i, minfo) in info_ref.methods.iter().enumerate() {
658            let fun = if minfo.func().is_none() {
659                let name_key = self.ast_objs.fields[minfo.src().unwrap()].names[0];
660                let ident = self.ast_ident(name_key);
661                let name = ident.name.clone();
662                let pos = ident.pos;
663                // Don't type-check signature yet - use an
664                // empty signature now and update it later.
665                // But set up receiver since we know it and
666                // its position, and because interface method
667                // signatures don't get a receiver via regular
668                // type-checking (there isn't a receiver in the
669                // method's AST). Setting the receiver type is
670                // also important for ptrRecv() (see methodset.go).
671                //
672                // Note: For embedded methods, the receiver type
673                // should be the type of the interface that declared
674                // the methods in the first place. Since we get the
675                // methods here via methodInfo, which may be computed
676                // before we have all relevant interface types, we use
677                // the current interface's type (recvType). This may be
678                // the type of the interface embedding the interface that
679                // declared the methods. This doesn't matter for type-
680                // checking (we only care about the receiver type for
681                // the ptrRecv predicate, and it's never a pointer recv
682                // for interfaces), but it matters for go/types clients
683                // and for printing. We correct the receiver after type-
684                // checking.
685
686                let recv_key =
687                    self.tc_objs
688                        .new_var(pos, Some(self.pkg), "".to_owned(), Some(recv_type));
689                let empty_tuple = *self.tc_objs.universe().no_value_tuple();
690                let sig_key = self.tc_objs.new_t_signature(
691                    None,
692                    Some(recv_key),
693                    empty_tuple,
694                    empty_tuple,
695                    false,
696                );
697                let fun_key = self
698                    .tc_objs
699                    .new_func(pos, Some(self.pkg), name, Some(sig_key));
700                minfo.set_func(fun_key);
701                self.result.record_def(name_key, Some(fun_key));
702                sig_fix.push(minfo.clone());
703                fun_key
704            } else {
705                minfo.func().unwrap()
706            };
707            let itype_val = self.otype_interface_mut(itype);
708            if i < explicits {
709                itype_val.methods_mut().push(fun);
710            }
711            itype_val.all_methods_push(fun);
712        }
713        // We used to need this to make the compiler happy:
714        //drop(info_ref);
715
716        // fix signatures now that we have collected all methods
717        let invalid_type = self.invalid_type();
718        let saved_context = self.octx.clone();
719        for minfo in sig_fix {
720            // (possibly embedded) methods must be type-checked within their scope and
721            // type-checking them must not affect the current context
722            self.octx = ObjContext::new();
723            self.octx.scope = minfo.scope();
724            let ftype = self.ast_objs.fields[minfo.src().unwrap()].typ.clone();
725            let ty = self.indirect_type(&ftype, fctx);
726            if let Some(sig) = self.otype(ty).try_as_signature() {
727                let sig_copy = *sig;
728                // update signature, but keep recv that was set up before
729                let old = self.otype_signature_mut(self.lobj(minfo.func().unwrap()).typ().unwrap());
730                let recv = *old.recv(); // save recv
731                *old = sig_copy;
732                old.set_recv(recv); // restore recv
733            } else {
734                if ty != invalid_type {
735                    let pos = ftype.pos(self.ast_objs);
736                    let td = self.new_dis(&ty);
737                    self.invalid_ast(pos, &format!("{} is not a method signature", td));
738                }
739            }
740        }
741        self.octx = saved_context;
742
743        // sort methods
744        let itype_val = self.otype_interface(itype);
745        let mut methods = itype_val.methods().clone();
746        methods.sort_by(compare_by_method_name!(self.tc_objs));
747        *self.otype_interface_mut(itype).methods_mut() = methods;
748        // sort all_methods
749        let itype_val = self.otype_interface(itype);
750        if itype_val.all_methods().is_none() {
751            itype_val.set_empty_complete();
752        } else {
753            itype_val
754                .all_methods_mut()
755                .as_mut()
756                .unwrap()
757                .sort_by(compare_by_method_name!(self.tc_objs));
758        }
759
760        itype
761    }
762
763    fn tag(&self, t: &Option<Expr>) -> Option<String> {
764        if let Some(e) = t {
765            if let Expr::BasicLit(bl) = e {
766                if let Token::STRING(data) = &bl.token {
767                    return Some(data.as_str_str().1.clone());
768                }
769                self.invalid_ast(
770                    e.pos(self.ast_objs),
771                    &format!("incorrect tag syntax: {}", bl.token),
772                )
773            } else {
774                unreachable!()
775            }
776        }
777        None
778    }
779
780    fn declare_in_set(&self, set: &mut Map<String, ObjKey>, fld: ObjKey, pos: Pos) -> bool {
781        if let Some(okey) = self.insert_obj_to_set(set, fld) {
782            self.error(pos, format!("{} redeclared", self.lobj(fld).name()));
783            self.report_alt_decl(okey);
784            false
785        } else {
786            true
787        }
788    }
789
790    fn add_field(
791        &mut self,
792        fields: &mut Vec<ObjKey>,
793        tags: &mut Option<Vec<Option<String>>>,
794        oset: &mut Map<String, ObjKey>,
795        ty: TypeKey,
796        tag: Option<String>,
797        ikey: IdentKey,
798        embedded: bool,
799        pos: Pos,
800    ) {
801        if tag.is_some() && tags.is_none() {
802            *tags = Some(vec![]);
803        }
804        if tags.is_some() {
805            tags.as_mut().unwrap().push(tag);
806        }
807        let name = &self.ast_ident(ikey).name.clone();
808        let fld = self
809            .tc_objs
810            .new_field(pos, Some(self.pkg), name.clone(), Some(ty), embedded);
811        if name == "_" || self.declare_in_set(oset, fld, pos) {
812            fields.push(fld);
813            self.result.record_def(ikey, Some(fld));
814        }
815    }
816
817    fn embedded_field_ident(e: &Expr) -> Option<IdentKey> {
818        match e {
819            Expr::Ident(i) => Some(*i),
820            Expr::Star(s) => match s.expr {
821                // *T is valid, but **T is not
822                Expr::Star(_) => None,
823                _ => Checker::<S>::embedded_field_ident(&s.expr),
824            },
825            Expr::Selector(s) => Some(s.sel),
826            _ => None,
827        }
828    }
829
830    fn struct_type(&mut self, st: &ast::StructType, fctx: &mut FilesContext<S>) -> TypeKey {
831        let fields = &st.fields.list;
832        if fields.len() == 0 {
833            return self.tc_objs.new_t_struct(vec![], None);
834        }
835
836        let mut field_objs: Vec<ObjKey> = vec![];
837        let mut tags: Option<Vec<Option<String>>> = None;
838        let mut oset: Map<String, ObjKey> = Map::new();
839        for f in fields {
840            let field = &self.ast_objs.fields[*f];
841            let fnames = field.names.clone();
842            let ftag = self.tag(&field.tag);
843            let ftype = field.typ.clone();
844            let ty = self.type_expr(&ftype, fctx);
845            if fnames.len() > 0 {
846                // named fields
847                for name in fnames.iter() {
848                    self.add_field(
849                        &mut field_objs,
850                        &mut tags,
851                        &mut oset,
852                        ty,
853                        ftag.clone(),
854                        *name,
855                        false,
856                        self.ast_ident(*name).pos,
857                    );
858                }
859            } else {
860                // embedded field
861                // spec: "An embedded type must be specified as a type name T or as a pointer
862                // to a non-interface type name *T, and T itself may not be a pointer type."
863                let field = &self.ast_objs.fields[*f];
864                let pos = field.typ.pos(self.ast_objs);
865                let invalid_type = self.invalid_type();
866                let mut add_invalid = |c: &mut Checker<S>, ident: IdentKey| {
867                    c.add_field(
868                        &mut field_objs,
869                        &mut tags,
870                        &mut oset,
871                        invalid_type,
872                        None,
873                        ident,
874                        false,
875                        pos,
876                    );
877                };
878                if let Some(ident) = Checker::<S>::embedded_field_ident(&field.typ) {
879                    let (t, is_ptr) = lookup::try_deref(ty, self.tc_objs);
880                    // Because we have a name, typ must be of the form T or *T, where T is the name
881                    // of a (named or alias) type, and t (= deref(typ)) must be the type of T.
882                    let t = typ::underlying_type(t, self.tc_objs);
883                    let type_val = self.otype(t);
884                    match type_val {
885                        typ::Type::Basic(_) if t == invalid_type => {
886                            // error was reported before
887                            add_invalid(self, ident);
888                        }
889                        typ::Type::Basic(b) if b.typ() == typ::BasicType::UnsafePointer => {
890                            self.error_str(pos, "embedded field type cannot be unsafe.Pointer");
891                            add_invalid(self, ident);
892                        }
893                        typ::Type::Pointer(_) => {
894                            self.error_str(pos, "embedded field type cannot be a pointer");
895                            add_invalid(self, ident);
896                        }
897                        typ::Type::Interface(_) if is_ptr => {
898                            self.error_str(
899                                pos,
900                                "embedded field type cannot be a pointer to an interface",
901                            );
902                            add_invalid(self, ident);
903                        }
904                        _ => self.add_field(
905                            &mut field_objs,
906                            &mut tags,
907                            &mut oset,
908                            ty,
909                            ftag.clone(),
910                            ident,
911                            true,
912                            pos,
913                        ),
914                    }
915                } else {
916                    let ed = self.new_dis(&field.typ);
917                    self.invalid_ast(pos, &format!("embedded field type {} has no name", ed));
918                    let ident = self.ast_objs.idents.insert(ast::Ident::blank(pos));
919                    add_invalid(self, ident);
920                }
921            }
922        }
923
924        self.tc_objs.new_t_struct(field_objs, tags)
925    }
926}