go_types/check/
expr.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
12use crate::SourceRead;
13
14use super::super::constant::Value;
15use super::super::lookup;
16use super::super::objects::TypeKey;
17use super::super::operand::{Operand, OperandMode};
18use super::super::typ::{self, BasicType, Type};
19use super::super::universe::ExprKind;
20use super::check::{Checker, ExprInfo, FilesContext};
21use super::stmt::BodyContainer;
22use go_parser::ast::{Expr, Node};
23use go_parser::{Map, Pos, Token};
24use std::collections::HashSet;
25
26///Basic algorithm:
27///
28///Expressions are checked recursively, top down. Expression checker functions
29///are generally of the form:
30///
31///  fn f(x &mut operand, e &Expr, ...)
32///
33///where e is the expression to be checked, and x is the result of the check.
34///The check performed by f may fail in which case x.mode == OperandMode::invalid,
35///and related error messages will have been issued by f.
36///
37///If a hint argument is present, it is the composite literal element type
38///of an outer composite literal; it is used to type-check composite literal
39///elements that have no explicit type specification in the source
40///(e.g.: []T{{...}, {...}}, the hint is the type T in this case).
41///
42///All expressions are checked via raw_expr, which dispatches according
43///to expression kind. Upon returning, raw_expr is recording the types and
44///constant values for all expressions that have an untyped type (those types
45///may change on the way up in the expression tree). Usually these are constants,
46///but the results of comparisons or non-constant shifts of untyped constants
47///may also be untyped, but not constant.
48///
49///Untyped expressions may eventually become fully typed (i.e., not untyped),
50///typically when the value is assigned to a variable, or is used otherwise.
51///The update_expr_type method is used to record this final type and update
52///the recorded types: the type-checked expression tree is again traversed down,
53///and the new type is propagated as needed. Untyped constant expression values
54///that become fully typed must now be representable by the full type (constant
55///sub-expression trees are left alone except for their roots). This mechanism
56///ensures that a client sees the actual (run-time) type an untyped value would
57///have. It also permits type-checking of lhs shift operands "as if the shift
58///were not present": when update_expr_type visits an untyped lhs shift operand
59///and assigns it it's final type, that type must be an integer type, and a
60///constant lhs must be representable as an integer.
61///
62///When an expression gets its final type, either on the way out from raw_expr,
63///on the way down in update_expr_type, or at the end of the type checker run,
64///the type (and constant value, if any) is recorded via Info.Types, if present.
65
66impl<'a, S: SourceRead> Checker<'a, S> {
67    fn op_token(&self, x: &mut Operand, token: &Token, binary: bool) -> bool {
68        let pred = |t: &Token, ty: TypeKey| -> Option<bool> {
69            if binary {
70                match t {
71                    Token::ADD => {
72                        Some(typ::is_numeric(ty, self.tc_objs) || typ::is_string(ty, self.tc_objs))
73                    }
74                    Token::SUB => Some(typ::is_numeric(ty, self.tc_objs)),
75                    Token::MUL => Some(typ::is_numeric(ty, self.tc_objs)),
76                    Token::QUO => Some(typ::is_numeric(ty, self.tc_objs)),
77                    Token::REM => Some(typ::is_integer(ty, self.tc_objs)),
78                    Token::AND => Some(typ::is_integer(ty, self.tc_objs)),
79                    Token::OR => Some(typ::is_integer(ty, self.tc_objs)),
80                    Token::XOR => Some(typ::is_integer(ty, self.tc_objs)),
81                    Token::AND_NOT => Some(typ::is_integer(ty, self.tc_objs)),
82                    Token::LAND => Some(typ::is_boolean(ty, self.tc_objs)),
83                    Token::LOR => Some(typ::is_boolean(ty, self.tc_objs)),
84                    _ => None,
85                }
86            } else {
87                match t {
88                    Token::ADD => Some(typ::is_numeric(ty, self.tc_objs)),
89                    Token::SUB => Some(typ::is_numeric(ty, self.tc_objs)),
90                    Token::XOR => Some(typ::is_integer(ty, self.tc_objs)),
91                    Token::NOT => Some(typ::is_boolean(ty, self.tc_objs)),
92                    _ => None,
93                }
94            }
95        };
96
97        if let Some(ok) = pred(token, x.typ.unwrap()) {
98            if !ok {
99                let xd = self.new_dis(x);
100                self.invalid_op(
101                    xd.pos(),
102                    &format!("operator {} not defined for {}", token, xd),
103                );
104            }
105            ok
106        } else {
107            self.invalid_ast(x.pos(self.ast_objs), &format!("unknown operator {}", token));
108            false
109        }
110    }
111
112    /// The unary expression e may be None. It's passed in for better error messages only.
113    fn unary(&mut self, x: &mut Operand, e: Option<Expr>, op: &Token) {
114        match op {
115            Token::AND => {
116                // spec: "As an exception to the addressability requirement
117                // x may also be a composite literal."
118                match Checker::<S>::unparen(x.expr.as_ref().unwrap()) {
119                    Expr::CompositeLit(_) => {}
120                    _ => {
121                        if x.mode != OperandMode::Variable {
122                            let xd = self.new_dis(x);
123                            self.invalid_op(xd.pos(), &format!("cannot take address of {}", xd));
124                            x.mode = OperandMode::Invalid;
125                            return;
126                        }
127                    }
128                }
129                x.mode = OperandMode::Value;
130                x.typ = Some(self.tc_objs.new_t_pointer(x.typ.unwrap()));
131            }
132            Token::ARROW => {
133                if let Some(chan) = self
134                    .otype(x.typ.unwrap())
135                    .underlying_val(self.tc_objs)
136                    .try_as_chan()
137                {
138                    if chan.dir() == typ::ChanDir::SendOnly {
139                        let xd = self.new_dis(x);
140                        self.invalid_op(
141                            xd.pos(),
142                            &format!("cannot receive from send-only channel {}", xd),
143                        );
144                        return;
145                    }
146                    x.mode = OperandMode::CommaOk;
147                    x.typ = Some(chan.elem());
148                    self.octx.has_call_or_recv = true;
149                    return;
150                } else {
151                    let xd = self.new_dis(x);
152                    self.invalid_op(xd.pos(), &format!("cannot receive from non-channel {}", xd));
153                }
154            }
155            _ => {
156                if !self.op_token(x, op, false) {
157                    x.mode = OperandMode::Invalid;
158                    return;
159                }
160                if let OperandMode::Constant(v) = &mut x.mode {
161                    let ty = typ::underlying_type(x.typ.unwrap(), self.tc_objs);
162                    let tval = self.otype(ty);
163                    let prec = if tval.is_unsigned(self.tc_objs) {
164                        tval.try_as_basic().unwrap().size_of()
165                    } else {
166                        0
167                    };
168                    *v = Value::unary_op(op, v, prec);
169                    // Typed constants must be representable in
170                    // their type after each constant operation.
171                    if tval.is_typed(self.tc_objs) {
172                        if e.is_some() {
173                            x.expr = e // for better error message
174                        }
175                        self.representable(x, ty);
176                    }
177                    return;
178                }
179                x.mode = OperandMode::Value;
180                // x.typ remains unchanged
181            }
182        }
183    }
184
185    fn is_shift(op: &Token) -> bool {
186        match op {
187            Token::SHL | Token::SHR => true,
188            _ => false,
189        }
190    }
191
192    fn is_comparison(op: &Token) -> bool {
193        match op {
194            Token::EQL | Token::NEQ | Token::LSS | Token::LEQ | Token::GTR | Token::GEQ => true,
195            _ => false,
196        }
197    }
198
199    /// representable checks that a constant operand is representable in the given basic type.
200    pub fn representable(&mut self, x: &mut Operand, t: TypeKey) {
201        let tval = self.otype(t);
202        let tbasic = tval.try_as_basic().unwrap();
203        if let OperandMode::Constant(v) = &mut x.mode {
204            let clone = v.clone();
205            if !clone.representable(tbasic, Some(v)) {
206                let o = &self.tc_objs;
207                let xtval = self.otype(x.typ.unwrap());
208                let tval = self.otype(t);
209                let xd = self.new_dis(x);
210                let td = self.new_dis(&t);
211                // numeric conversion : error msg
212                //
213                // integer -> integer : overflows
214                // integer -> float   : overflows (actually not possible)
215                // float   -> integer : truncated
216                // float   -> float   : overflows
217                let msg = if xtval.is_numeric(o) && tval.is_numeric(o) {
218                    if !xtval.is_integer(o) && tval.is_integer(o) {
219                        format!("{} truncated to {}", xd, td)
220                    } else {
221                        format!("{} overflows {}", xd, td)
222                    }
223                } else {
224                    format!("cannot convert {} to {}", xd, td)
225                };
226                self.error(xd.pos(), msg);
227                x.mode = OperandMode::Invalid;
228            }
229        } else {
230            unreachable!()
231        }
232    }
233
234    /// update_expr_type updates the type of x to typ and invokes itself
235    /// recursively for the operands of x, depending on expression kind.
236    /// If typ is still an untyped and not the final type, update_expr_type
237    /// only updates the recorded untyped type for x and possibly its
238    /// operands. Otherwise (i.e., typ is not an untyped type anymore,
239    /// or it is the final type for x), the type and value are recorded.
240    /// Also, if x is a constant, it must be representable as a value of typ,
241    /// and if x is the (formerly untyped) lhs operand of a non-constant
242    /// shift, it must be an integer value.
243    pub fn update_expr_type(
244        &mut self,
245        e: &Expr,
246        t: TypeKey,
247        final_: bool,
248        fctx: &mut FilesContext<S>,
249    ) {
250        let old_opt = fctx.untyped.get(&e.id());
251        if old_opt.is_none() {
252            return; // nothing to do
253        }
254        let old = old_opt.unwrap();
255
256        // update operands of x if necessary
257        match e {
258            Expr::Bad(_)
259            | Expr::FuncLit(_)
260            | Expr::CompositeLit(_)
261            | Expr::Index(_)
262            | Expr::Slice(_)
263            | Expr::TypeAssert(_)
264            | Expr::Star(_)
265            | Expr::KeyValue(_)
266            | Expr::Array(_)
267            | Expr::Struct(_)
268            | Expr::Func(_)
269            | Expr::Interface(_)
270            | Expr::Map(_)
271            | Expr::Chan(_) => {
272                if cfg!(debug_assertions) {
273                    let ed = self.new_dis(e);
274                    let (otd, td) = (self.new_td_o(&old.typ), self.new_dis(&t));
275                    self.dump(
276                        Some(ed.pos()),
277                        &format!("found old type({}): {} (new: {})", ed, otd, td),
278                    );
279                    unreachable!()
280                }
281                return;
282            }
283            Expr::Call(_) => {
284                // Resulting in an untyped constant (e.g., built-in complex).
285                // The respective calls take care of calling update_expr_type
286                // for the arguments if necessary.
287            }
288            Expr::Ident(_) | Expr::BasicLit(_) | Expr::Selector(_) => {
289                // An identifier denoting a constant, a constant literal,
290                // or a qualified identifier (imported untyped constant).
291                // No operands to take care of.
292            }
293            Expr::Paren(p) => {
294                self.update_expr_type(&p.expr, t, final_, fctx);
295            }
296            Expr::Unary(u) => {
297                // If x is a constant, the operands were constants.
298                // The operands don't need to be updated since they
299                // never get "materialized" into a typed value. If
300                // left in the untyped map, they will be processed
301                // at the end of the type check.
302                if old.mode.constant_val().is_none() {
303                    self.update_expr_type(&u.expr, t, final_, fctx);
304                }
305            }
306            Expr::Binary(b) => {
307                if old.mode.constant_val().is_none() {
308                    if Checker::<S>::is_comparison(&b.op) {
309                        // The result type is independent of operand types
310                        // and the operand types must have final types.
311                    } else if Checker::<S>::is_shift(&b.op) {
312                        // The result type depends only on lhs operand.
313                        // The rhs type was updated when checking the shift.
314                        self.update_expr_type(&b.expr_a, t, final_, fctx);
315                    } else {
316                        // The operand types match the result type.
317                        self.update_expr_type(&b.expr_a, t, final_, fctx);
318                        self.update_expr_type(&b.expr_b, t, final_, fctx);
319                    }
320                }
321            }
322            _ => unreachable!(),
323        }
324
325        // If the new type is not final and still untyped, just
326        // update the recorded type.
327        let o = &self.tc_objs;
328        if !final_ && typ::is_untyped(t, o) {
329            let old = fctx.untyped.get_mut(&e.id()).unwrap();
330            old.typ = Some(typ::underlying_type(t, o));
331            return;
332        }
333
334        // Otherwise we have the final (typed or untyped type).
335        // Remove it from the map of yet untyped expressions.
336        let removed = fctx.untyped.remove(&e.id());
337        let old = removed.as_ref().unwrap();
338
339        if old.is_lhs {
340            // If x is the lhs of a shift, its final type must be integer.
341            // We already know from the shift check that it is representable
342            // as an integer if it is a constant.
343            if !typ::is_integer(t, o) {
344                let ed = self.new_dis(e);
345                let td = self.new_dis(&t);
346                self.invalid_op(
347                    ed.pos(),
348                    &format!("shifted operand {} (type {}) must be integer", ed, td),
349                );
350                return;
351            }
352            // Even if we have an integer, if the value is a constant we
353            // still must check that it is representable as the specific
354            // int type requested
355        }
356        if old.mode.constant_val().is_some() {
357            // If x is a constant, it must be representable as a value of typ.
358            let mut c = Operand::with(old.mode.clone(), Some(e.clone()), old.typ);
359            self.convert_untyped(&mut c, t, fctx);
360            if c.invalid() {
361                return;
362            }
363        }
364
365        // Everything's fine, record final type and value for x.
366        self.result.record_type_and_value(e, old.mode.clone(), t);
367    }
368
369    /// update_expr_val updates the value of x to val.
370    fn update_expr_val(e: &Expr, val: Value, fctx: &mut FilesContext<S>) {
371        if let Some(info) = fctx.untyped.get_mut(&e.id()) {
372            if let OperandMode::Constant(v) = &mut info.mode {
373                *v = val;
374            } else {
375                unreachable!()
376            }
377        }
378    }
379
380    /// convert_untyped attempts to set the type of an untyped value to the target type.
381    pub fn convert_untyped(
382        &mut self,
383        x: &mut Operand,
384        target: TypeKey,
385        fctx: &mut FilesContext<S>,
386    ) {
387        let o = &self.tc_objs;
388        if x.invalid() || typ::is_typed(x.typ.unwrap(), o) || target == self.invalid_type() {
389            return;
390        }
391
392        let on_err = |c: &mut Checker<S>, x: &mut Operand| {
393            let xd = c.new_dis(x);
394            let td = c.new_dis(&target);
395            c.error(xd.pos(), format!("cannot convert {} to {}", xd, td));
396            x.mode = OperandMode::Invalid;
397        };
398
399        if typ::is_untyped(target, o) {
400            // both x and target are untyped
401            let order = |bt: BasicType| -> usize {
402                match bt {
403                    BasicType::UntypedInt => 1,
404                    BasicType::UntypedRune => 2,
405                    BasicType::UntypedFloat => 3,
406                    BasicType::UntypedComplex => 4,
407                    _ => unreachable!(),
408                }
409            };
410            let xtval = self.otype(x.typ.unwrap());
411            let ttval = self.otype(target);
412            let xbasic = xtval.try_as_basic().unwrap().typ();
413            let tbasic = ttval.try_as_basic().unwrap().typ();
414            if xbasic != tbasic {
415                if xtval.is_numeric(o) && ttval.is_numeric(o) {
416                    if order(xbasic) < order(tbasic) {
417                        x.typ = Some(target);
418                        self.update_expr_type(x.expr.as_ref().unwrap(), target, false, fctx);
419                    }
420                } else {
421                    return on_err(self, x);
422                }
423            }
424            return;
425        }
426
427        let t = typ::underlying_type(target, o);
428        let xtype = x.typ.unwrap();
429        let tval = self.otype(t);
430        let final_target = match tval {
431            Type::Basic(_) => {
432                if let OperandMode::Constant(v) = &x.mode {
433                    let v_clone = v.clone();
434                    self.representable(x, t);
435                    if x.invalid() {
436                        return;
437                    }
438                    // expression value may have been rounded - update if needed
439                    Checker::update_expr_val(x.expr.as_ref().unwrap(), v_clone, fctx);
440                    Some(target)
441                } else {
442                    // Non-constant untyped values may appear as the
443                    // result of comparisons (untyped bool), intermediate
444                    // (delayed-checked) rhs operands of shifts, and as
445                    // the value nil.
446                    let ok = match self.otype(x.typ.unwrap()).try_as_basic().unwrap().typ() {
447                        BasicType::UntypedBool => tval.is_boolean(o),
448                        BasicType::UntypedInt
449                        | BasicType::UntypedRune
450                        | BasicType::UntypedFloat
451                        | BasicType::UntypedComplex => tval.is_numeric(o),
452                        BasicType::UntypedString => unreachable!(),
453                        BasicType::UntypedNil => tval.has_nil(o),
454                        _ => false,
455                    };
456                    if ok {
457                        Some(target)
458                    } else {
459                        None
460                    }
461                }
462            }
463            Type::Interface(detail) => {
464                // Update operand types to the default type rather then
465                // the target (interface) type: values must have concrete
466                // dynamic types. If the value is nil, keep it untyped
467                if x.is_nil(self.tc_objs.universe()) {
468                    Some(self.basic_type(BasicType::UntypedNil))
469                } else {
470                    if detail.is_empty() {
471                        Some(typ::untyped_default_type(xtype, o))
472                    } else {
473                        // cannot assign untyped values to non-empty interfaces
474                        None
475                    }
476                }
477            }
478            Type::Pointer(_)
479            | Type::Signature(_)
480            | Type::Slice(_)
481            | Type::Map(_)
482            | Type::Chan(_) => {
483                if x.is_nil(self.tc_objs.universe()) {
484                    Some(self.basic_type(BasicType::UntypedNil))
485                } else {
486                    None
487                }
488            }
489            _ => None,
490        };
491
492        if let Some(t) = final_target {
493            x.typ = final_target;
494            self.update_expr_type(x.expr.as_ref().unwrap(), t, true, fctx);
495        } else {
496            on_err(self, x);
497        }
498    }
499
500    pub fn comparison(
501        &mut self,
502        x: &mut Operand,
503        y: &Operand,
504        op: &Token,
505        fctx: &mut FilesContext<S>,
506    ) {
507        // spec: "In any comparison, the first operand must be assignable
508        // to the type of the second operand, or vice versa."
509        let (xtype, ytype) = (x.typ.unwrap(), y.typ.unwrap());
510        let assignable =
511            x.assignable_to(ytype, None, self, fctx) || y.assignable_to(xtype, None, self, fctx);
512        let o = &self.tc_objs;
513        let u = o.universe();
514        let emsg = if assignable {
515            let (xtval, ytval) = (self.otype(xtype), self.otype(ytype));
516            let defined = match op {
517                Token::EQL | Token::NEQ => {
518                    (xtval.comparable(o) && ytval.comparable(o))
519                        || (x.is_nil(u) && ytval.has_nil(o))
520                        || (y.is_nil(u) && xtval.has_nil(o))
521                }
522                Token::LSS | Token::LEQ | Token::GTR | Token::GEQ => {
523                    xtval.is_ordered(o) && ytval.is_ordered(o)
524                }
525                _ => unreachable!(),
526            };
527            if !defined {
528                let t = if x.is_nil(u) { ytype } else { xtype };
529                let td = self.new_dis(&t);
530                Some(format!("operator {} not defined for {}", op, td))
531            } else {
532                None
533            }
534        } else {
535            let (xd, yd) = (self.new_dis(&xtype), self.new_dis(&ytype));
536            Some(format!("mismatched types {} and {}", xd, yd))
537        };
538        if let Some(m) = emsg {
539            let pos = x.pos(self.ast_objs);
540            let xd = self.new_dis(x.expr.as_ref().unwrap());
541            let yd = self.new_dis(y.expr.as_ref().unwrap());
542            self.error(pos, format!("cannot compare {} {} {} ({})", xd, op, yd, m));
543            x.mode = OperandMode::Invalid;
544            return;
545        }
546
547        match (&mut x.mode, &y.mode) {
548            (OperandMode::Constant(vx), OperandMode::Constant(vy)) => {
549                *vx = Value::with_bool(Value::compare(vx, op, vy));
550                // The operands are never materialized; no need to update
551                // their types.
552            }
553            _ => {
554                x.mode = OperandMode::Value;
555                // The operands have now their final types, which at run-
556                // time will be materialized. Update the expression trees.
557                // If the current types are untyped, the materialized type
558                // is the respective default type.
559                self.update_expr_type(
560                    x.expr.as_ref().unwrap(),
561                    typ::untyped_default_type(xtype, self.tc_objs),
562                    true,
563                    fctx,
564                );
565                self.update_expr_type(
566                    y.expr.as_ref().unwrap(),
567                    typ::untyped_default_type(ytype, self.tc_objs),
568                    true,
569                    fctx,
570                );
571            }
572        }
573        // spec: "Comparison operators compare two operands and yield
574        //        an untyped boolean value."
575        x.typ = Some(self.basic_type(BasicType::UntypedBool));
576    }
577
578    fn shift(
579        &mut self,
580        x: &mut Operand,
581        y: &mut Operand,
582        op: &Token,
583        e: Option<&Expr>,
584        fctx: &mut FilesContext<S>,
585    ) {
586        let o = &self.tc_objs;
587        let xtval = self.otype(x.typ.unwrap());
588        let xt_untyped = xtval.is_untyped(o);
589        let xt_integer = xtval.is_integer(o);
590        let x_const = x.mode.constant_val().map(|x| x.to_int().into_owned());
591
592        // The lhs is of integer type or an untyped constant representable
593        // as an integer
594        let lhs_ok =
595            xt_integer || (xt_untyped && x_const.is_some() && x_const.as_ref().unwrap().is_int());
596        if !lhs_ok {
597            let xd = self.new_dis(x);
598            self.invalid_op(xd.pos(), &format!("shifted operand {} must be integer", xd));
599            x.mode = OperandMode::Invalid;
600            return;
601        }
602
603        // spec: "The right operand in a shift expression must have unsigned
604        // integer type or be an untyped constant representable by a value of
605        // type uint."
606        let ytval = self.otype(y.typ.unwrap());
607        if ytval.is_unsigned(o) {
608            //ok
609        } else if ytval.is_untyped(o) {
610            self.convert_untyped(y, self.basic_type(BasicType::Uint), fctx);
611            if y.invalid() {
612                x.mode = OperandMode::Invalid;
613                return;
614            }
615        } else {
616            let yd = self.new_dis(y);
617            self.error(
618                yd.pos(),
619                format!("shift count {} must be unsigned integer", yd),
620            );
621            x.mode = OperandMode::Invalid;
622            return;
623        }
624
625        if let OperandMode::Constant(xv) = &mut x.mode {
626            if let OperandMode::Constant(yv) = &y.mode {
627                // rhs must be an integer value
628                let yval = yv.to_int();
629                if !yval.is_int() {
630                    let yd = self.new_dis(y);
631                    self.invalid_op(
632                        yd.pos(),
633                        &format!("shift count {} must be unsigned integer", yd),
634                    );
635                    x.mode = OperandMode::Invalid;
636                    return;
637                }
638                // rhs must be within reasonable bounds
639                let shift_bound = 1023 - 1 + 52; // so we can express smallestFloat64
640                let (s, ok) = yval.int_as_u64();
641                if !ok || s > shift_bound {
642                    let yd = self.new_dis(y);
643                    self.invalid_op(yd.pos(), &format!("invalid shift count {}", yd));
644                    x.mode = OperandMode::Invalid;
645                    return;
646                }
647                // The lhs is representable as an integer but may not be an integer
648                // (e.g., 2.0, an untyped float) - this can only happen for untyped
649                // non-integer numeric constants. Correct the type so that the shift
650                // result is of integer type.
651                if !xt_integer {
652                    x.typ = Some(self.basic_type(BasicType::UntypedInt));
653                }
654                // x is a constant so xval != nil and it must be of Int kind.
655                *xv = Value::shift(xv.to_int().as_ref(), op, s as usize);
656                // Typed constants must be representable in
657                // their type after each constant operation.
658                if typ::is_typed(x.typ.unwrap(), self.tc_objs) {
659                    if e.is_some() {
660                        x.expr = e.map(|x| x.clone()); // for better error message
661                    }
662                    self.representable(x, x.typ.unwrap());
663                }
664                return;
665            }
666
667            if xt_untyped {
668                // spec: "If the left operand of a non-constant shift
669                // expression is an untyped constant, the type of the
670                // constant is what it would be if the shift expression
671                // were replaced by its left operand alone.".
672                //
673                // Delay operand checking until we know the final type
674                // by marking the lhs expression as lhs shift operand.
675                //
676                // Usually (in correct programs), the lhs expression
677                // is in the untyped map. However, it is possible to
678                // create incorrect programs where the same expression
679                // is evaluated twice (via a declaration cycle) such
680                // that the lhs expression type is determined in the
681                // first round and thus deleted from the map, and then
682                // not found in the second round (double insertion of
683                // the same expr node still just leads to one entry for
684                // that node, and it can only be deleted once).
685                // Be cautious and check for presence of entry.
686                // Example: var e, f = int(1<<""[f])
687                if let Some(info) = fctx.untyped.get_mut(&x.expr.as_ref().unwrap().id()) {
688                    info.is_lhs = true;
689                }
690                // keep x's type
691                x.mode = OperandMode::Value;
692                return;
693            }
694        }
695
696        // constant rhs must be >= 0
697        if let OperandMode::Constant(v) = &y.mode {
698            if v.sign() < 0 {
699                let yd = self.new_dis(y);
700                self.invalid_op(
701                    yd.pos(),
702                    &format!("shift count {} must not be negative", yd),
703                );
704            }
705        }
706
707        if !typ::is_integer(x.typ.unwrap(), self.tc_objs) {
708            let xd = self.new_dis(x);
709            self.invalid_op(xd.pos(), &format!("shifted operand {} must be integer", xd));
710            x.mode = OperandMode::Value;
711            return;
712        }
713        x.mode = OperandMode::Value;
714    }
715
716    /// The binary expression e may be None. It's passed in for better error messages only.
717    pub fn binary(
718        &mut self,
719        x: &mut Operand,
720        e: Option<&Expr>,
721        lhs: &Expr,
722        rhs: &Expr,
723        op: &Token,
724        fctx: &mut FilesContext<S>,
725    ) {
726        let mut y = Operand::new();
727        self.expr(x, &lhs, fctx);
728        self.expr(&mut y, &rhs, fctx);
729
730        if x.invalid() {
731            return;
732        }
733        if y.invalid() {
734            x.mode = OperandMode::Invalid;
735            x.expr = y.expr.clone();
736            return;
737        }
738
739        if Checker::<S>::is_shift(op) {
740            self.shift(x, &mut y, op, e, fctx);
741            return;
742        }
743
744        self.convert_untyped(x, y.typ.unwrap(), fctx);
745        if x.invalid() {
746            return;
747        }
748
749        self.convert_untyped(&mut y, x.typ.unwrap(), fctx);
750        if y.invalid() {
751            x.mode = OperandMode::Invalid;
752            return;
753        }
754
755        if Checker::<S>::is_comparison(op) {
756            self.comparison(x, &y, op, fctx);
757            return;
758        }
759
760        if !typ::identical_o(x.typ, y.typ, self.tc_objs) {
761            // only report an error if we have valid types
762            // (otherwise we had an error reported elsewhere already)
763            let invalid = Some(self.invalid_type());
764            if x.typ != invalid && y.typ != invalid {
765                let xd = self.new_td_o(&x.typ);
766                let yd = self.new_td_o(&y.typ);
767                self.invalid_op(
768                    x.pos(self.ast_objs),
769                    &format!("mismatched types {} and {}", xd, yd),
770                );
771            }
772            x.mode = OperandMode::Invalid;
773            return;
774        }
775
776        if !self.op_token(x, op, true) {
777            x.mode = OperandMode::Invalid;
778            return;
779        }
780
781        let o = &self.tc_objs;
782        if *op == Token::QUO || *op == Token::REM {
783            // check for zero divisor
784            if x.mode.constant_val().is_some() || typ::is_integer(x.typ.unwrap(), o) {
785                if let Some(v) = y.mode.constant_val() {
786                    if v.sign() == 0 {
787                        self.invalid_op(y.pos(self.ast_objs), "division by zero");
788                        x.mode = OperandMode::Invalid;
789                        return;
790                    }
791                }
792            }
793            // check for divisor underflow in complex division
794            if x.mode.constant_val().is_some() && typ::is_complex(x.typ.unwrap(), o) {
795                if let Some(v) = y.mode.constant_val() {
796                    let (re, im) = (v.real(), v.imag());
797                    let re2 = Value::binary_op(&re, &Token::MUL, &re);
798                    let im2 = Value::binary_op(&im, &Token::MUL, &im);
799                    if re2.sign() == 0 && im2.sign() == 0 {
800                        self.invalid_op(y.pos(self.ast_objs), "division by zero");
801                        x.mode = OperandMode::Invalid;
802                        return;
803                    }
804                }
805            }
806        }
807
808        match (&mut x.mode, &y.mode) {
809            (OperandMode::Constant(vx), OperandMode::Constant(vy)) => {
810                let ty = typ::underlying_type(x.typ.unwrap(), o);
811                // force integer division of integer operands
812                // (not real QUO_ASSIGN, just borrowing it)
813                let op2 = if *op == Token::QUO && typ::is_integer(ty, o) {
814                    &Token::QUO_ASSIGN
815                } else {
816                    op
817                };
818                *vx = Value::binary_op(vx, op2, vy);
819                // Typed constants must be representable in
820                // their type after each constant operation.
821                if typ::is_typed(ty, o) {
822                    x.expr = e.map(|x| x.clone()); // for better error message
823                    self.representable(x, ty)
824                }
825            }
826            _ => {
827                x.mode = OperandMode::Value;
828                // x.typ is unchanged
829            }
830        }
831    }
832
833    /// index checks an index expression for validity.
834    /// max is the upper bound for index.
835    /// returns the value of the index when it's a constant, returns None if it's not
836    pub fn index(
837        &mut self,
838        index: &Expr,
839        max: Option<u64>,
840        fctx: &mut FilesContext<S>,
841    ) -> Result<Option<u64>, ()> {
842        let x = &mut Operand::new();
843        self.expr(x, index, fctx);
844        if x.invalid() {
845            return Err(());
846        }
847
848        // an untyped constant must be representable as Int
849        self.convert_untyped(x, self.basic_type(BasicType::Int), fctx);
850        if x.invalid() {
851            return Err(());
852        }
853
854        // the index must be of integer type
855        if !typ::is_integer(x.typ.unwrap(), self.tc_objs) {
856            let xd = self.new_dis(x);
857            self.invalid_arg(xd.pos(), &format!("index {} must be integer", xd));
858            return Err(());
859        }
860
861        // a constant index i must be in bounds
862        if let OperandMode::Constant(v) = &x.mode {
863            if v.sign() < 0 {
864                let xd = self.new_dis(x);
865                self.invalid_arg(xd.pos(), &format!("index {} must not be negative", xd));
866                return Err(());
867            }
868            let (i, valid) = v.to_int().int_as_u64();
869            if !valid || max.map_or(false, |x| i >= x) {
870                let xd = self.new_dis(x);
871                self.invalid_arg(xd.pos(), &format!("index {} out of bounds", xd));
872                return Err(());
873            }
874            return Ok(Some(i));
875        }
876
877        Ok(None)
878    }
879
880    /// indexed_elems checks the elements of an array or slice composite literal
881    /// against the literal's element type, and the element indices against
882    /// the literal length if known . It returns the length of the literal
883    /// (maximum index value + 1).
884    fn indexed_elems(
885        &mut self,
886        elems: &Vec<Expr>,
887        t: TypeKey,
888        length: Option<u64>,
889        fctx: &mut FilesContext<S>,
890    ) -> u64 {
891        let mut visited = HashSet::new();
892        let (_, max) = elems.iter().fold((0, 0), |(index, max), e| {
893            let (valid_index, eval) = if let Expr::KeyValue(kv) = e {
894                let i = self.index(&kv.key, length, fctx);
895                let kv_index = if i.is_ok() {
896                    if let Some(index) = i.unwrap() {
897                        Some(index)
898                    } else {
899                        let pos = e.pos(self.ast_objs);
900                        let kd = self.new_dis(&kv.key);
901                        self.error(pos, format!("index {} must be integer constant", kd));
902                        None
903                    }
904                } else {
905                    None
906                };
907                (kv_index, &kv.val)
908            } else if length.is_some() && index >= length.unwrap() {
909                self.error(
910                    e.pos(self.ast_objs),
911                    format!("index {} is out of bounds (>= {})", index, length.unwrap()),
912                );
913                (None, e)
914            } else {
915                (Some(index), e)
916            };
917
918            let (mut new_index, mut new_max) = (index, max);
919            if let Some(i) = valid_index {
920                if visited.contains(&i) {
921                    self.error(
922                        e.pos(self.ast_objs),
923                        format!("duplicate index {} in array or slice literal", i),
924                    );
925                }
926                visited.insert(i);
927
928                new_index = i + 1;
929                if new_index > new_max {
930                    new_max = new_index;
931                }
932            }
933
934            // check element against composite literal element type
935            let x = &mut Operand::new();
936            self.expr_with_hint(x, eval, t, fctx);
937            self.assignment(x, Some(t), "array or slice literal", fctx);
938
939            (new_index, new_max)
940        });
941        max
942    }
943
944    /// raw_expr typechecks expression e and initializes x with the expression
945    /// value or type. If an error occurred, x.mode is set to invalid.
946    /// If hint is_some(), it is the type of a composite literal element.
947    pub fn raw_expr(
948        &mut self,
949        x: &mut Operand,
950        e: &Expr,
951        hint: Option<TypeKey>,
952        fctx: &mut FilesContext<S>,
953    ) -> ExprKind {
954        if self.trace() {
955            let ed = self.new_dis(e);
956            self.trace_begin(ed.pos(), &format!("{}", ed));
957        }
958
959        let kind = self.raw_internal(x, e, hint, fctx);
960
961        let ty = match &x.mode {
962            OperandMode::Invalid => self.invalid_type(),
963            OperandMode::NoValue => *self.tc_objs.universe().no_value_tuple(),
964            _ => x.typ.unwrap(),
965        };
966
967        if typ::is_untyped(ty, self.tc_objs) {
968            // delay type and value recording until we know the type
969            // or until the end of type checking
970            fctx.remember_untyped(
971                x.expr.as_ref().unwrap(),
972                ExprInfo {
973                    is_lhs: false,
974                    mode: x.mode.clone(),
975                    typ: Some(ty),
976                },
977            )
978        } else {
979            self.result.record_type_and_value(e, x.mode.clone(), ty);
980        }
981
982        if self.trace() {
983            let pos = e.pos(self.ast_objs);
984            self.trace_end(pos, &format!("=> {}", self.new_dis(x)));
985        }
986
987        kind
988    }
989
990    /// raw_internal contains the core of type checking of expressions.
991    /// Must only be called by raw_expr.
992    fn raw_internal(
993        &mut self,
994        x: &mut Operand,
995        e: &Expr,
996        hint: Option<TypeKey>,
997        fctx: &mut FilesContext<S>,
998    ) -> ExprKind {
999        // make sure x has a valid state in case of bailout
1000        x.mode = OperandMode::Invalid;
1001        x.typ = Some(self.invalid_type());
1002        let on_err = |x: &mut Operand| {
1003            x.mode = OperandMode::Invalid;
1004            x.expr = Some(e.clone());
1005            ExprKind::Statement // avoid follow-up errors
1006        };
1007
1008        let epos = e.pos(self.ast_objs);
1009        match e {
1010            Expr::Bad(_) => return on_err(x),
1011            Expr::Ident(i) => self.ident(x, *i, None, false, fctx),
1012            Expr::Ellipsis(_) => {
1013                // ellipses are handled explicitly where they are legal
1014                // (array composite literals and parameter lists)
1015                self.error_str(epos, "invalid use of '...'");
1016                return on_err(x);
1017            }
1018            Expr::BasicLit(bl) => {
1019                x.set_const(&bl.token, self.tc_objs.universe());
1020                if x.invalid() {
1021                    let lit = bl.token.get_literal();
1022                    self.invalid_ast(epos, &format!("invalid literal {}", lit));
1023                    return on_err(x);
1024                }
1025            }
1026            Expr::FuncLit(fl) => {
1027                let t = self.type_expr(&Expr::Func(fl.typ), fctx);
1028                if let Some(_) = self.otype(t).try_as_signature() {
1029                    let decl = self.octx.decl;
1030                    let body = BodyContainer::FuncLitExpr(e.clone());
1031                    let iota = self.octx.iota.clone();
1032                    let f = move |checker: &mut Checker<S>, fctx: &mut FilesContext<S>| {
1033                        checker.func_body(decl, "<function literal>", t, body, iota, fctx);
1034                    };
1035                    fctx.later(Box::new(f));
1036                    x.mode = OperandMode::Value;
1037                    x.typ = Some(t);
1038                } else {
1039                    let ed = self.new_dis(e);
1040                    self.invalid_ast(epos, &format!("invalid function literal {}", ed));
1041                    return on_err(x);
1042                }
1043            }
1044            Expr::CompositeLit(cl) => {
1045                let (ty, base) = if let Some(etype) = &cl.typ {
1046                    // composite literal type present - use it
1047                    // [...]T array types may only appear with composite literals.
1048                    // Check for them here so we don't have to handle ... in general.
1049                    let mut elem = None;
1050                    if let Expr::Array(arr) = etype {
1051                        if let Some(len_expr) = &arr.len {
1052                            if let Expr::Ellipsis(ell) = len_expr {
1053                                if ell.elt.is_none() {
1054                                    elem = Some(&arr.elt);
1055                                }
1056                            }
1057                        }
1058                    }
1059                    let t = if let Some(el) = elem {
1060                        let elem_ty = self.type_expr(el, fctx);
1061                        self.tc_objs.new_t_array(elem_ty, None)
1062                    } else {
1063                        self.type_expr(&etype, fctx)
1064                    };
1065                    (t, t)
1066                } else if let Some(h) = hint {
1067                    // no composite literal type present - use hint (element type of enclosing type)
1068                    let (base, _) =
1069                        lookup::try_deref(typ::underlying_type(h, self.tc_objs), self.tc_objs);
1070                    (h, base)
1071                } else {
1072                    self.error_str(epos, "missing type in composite literal");
1073                    return on_err(x);
1074                };
1075
1076                let utype_key = typ::underlying_type(base, self.tc_objs);
1077                let utype = &self.tc_objs.types[utype_key];
1078                match utype {
1079                    Type::Struct(detail) => {
1080                        if cl.elts.len() > 0 {
1081                            let fields = detail.fields().clone();
1082                            if let Expr::KeyValue(_) = &cl.elts[0] {
1083                                let mut visited: HashSet<usize> = HashSet::new();
1084                                for e in cl.elts.iter() {
1085                                    let kv = if let Expr::KeyValue(kv) = e {
1086                                        kv
1087                                    } else {
1088                                        let msg = "mixture of field:value and value elements in struct literal";
1089                                        self.error_str(e.pos(self.ast_objs), msg);
1090                                        continue;
1091                                    };
1092                                    // do all possible checks early (before exiting due to errors)
1093                                    // so we don't drop information on the floor
1094                                    self.expr(x, &kv.val, fctx);
1095                                    let keykey = if let Expr::Ident(ikey) = kv.key {
1096                                        ikey
1097                                    } else {
1098                                        let ed = self.new_dis(&kv.key);
1099                                        self.error(
1100                                            e.pos(self.ast_objs),
1101                                            format!("invalid field name {} in struct literal", ed),
1102                                        );
1103                                        continue;
1104                                    };
1105                                    let key = &self.ast_objs.idents[keykey];
1106                                    let i = if let Some(i) = lookup::field_index(
1107                                        &fields,
1108                                        Some(self.pkg),
1109                                        &key.name,
1110                                        self.tc_objs,
1111                                    ) {
1112                                        i
1113                                    } else {
1114                                        self.error(
1115                                            e.pos(self.ast_objs),
1116                                            format!(
1117                                                "unknown field {} in struct literal",
1118                                                &key.name
1119                                            ),
1120                                        );
1121                                        continue;
1122                                    };
1123                                    let fld = fields[i];
1124                                    self.result.record_use(keykey, fld);
1125                                    let etype = self.lobj(fld).typ().unwrap();
1126                                    self.assignment(x, Some(etype), "struct literal", fctx);
1127                                    if visited.contains(&i) {
1128                                        self.error(
1129                                            e.pos(self.ast_objs),
1130                                            format!(
1131                                                "duplicate field name {} in struct literal",
1132                                                &self.ast_objs.idents[keykey].name
1133                                            ),
1134                                        );
1135                                        continue;
1136                                    } else {
1137                                        visited.insert(i);
1138                                    }
1139                                }
1140                            } else {
1141                                for (i, e) in cl.elts.iter().enumerate() {
1142                                    if let Expr::KeyValue(_) = e {
1143                                        let msg = "mixture of field:value and value elements in struct literal";
1144                                        self.error_str(e.pos(self.ast_objs), msg);
1145                                        continue;
1146                                    }
1147                                    self.expr(x, e, fctx);
1148                                    if i >= fields.len() {
1149                                        let pos = x.pos(self.ast_objs);
1150                                        self.error_str(pos, "too many values in struct literal");
1151                                        break; // cannot continue
1152                                    }
1153                                    let fld = self.lobj(fields[i]);
1154                                    if !fld.exported() && fld.pkg() != Some(self.pkg) {
1155                                        let pos = x.pos(self.ast_objs);
1156                                        let (n, td) = (fld.name(), self.new_dis(&ty));
1157                                        let msg = format!(
1158                                            "implicit assignment to unexported field {} in {} literal", n, td);
1159                                        self.error(pos, msg);
1160                                        continue;
1161                                    }
1162                                    let field_type = fld.typ();
1163                                    self.assignment(x, field_type, "struct literal", fctx);
1164                                }
1165                                if cl.elts.len() < fields.len() {
1166                                    self.error_str(cl.r_brace, "too few values in struct literal");
1167                                    // ok to continue
1168                                }
1169                            }
1170                        }
1171                    }
1172                    Type::Array(detail) => {
1173                        // todo: the go code checks if detail.elem is nil, do we need that?
1174                        // see the original go code for details
1175                        let arr_len = detail.len();
1176                        let elem = detail.elem();
1177                        let len = detail.len();
1178                        let n = self.indexed_elems(&cl.elts, elem, len, fctx);
1179                        // If we have an array of unknown length (usually [...]T arrays, but also
1180                        // arrays [n]T where n is invalid) set the length now that we know it and
1181                        // record the type for the array (usually done by check.typ which is not
1182                        // called for [...]T). We handle [...]T arrays and arrays with invalid
1183                        // length the same here because it makes sense to "guess" the length for
1184                        // the latter if we have a composite literal; e.g. for [n]int{1, 2, 3}
1185                        // where n is invalid for some reason, it seems fair to assume it should
1186                        // be 3
1187                        if arr_len.is_none() {
1188                            self.otype_mut(utype_key)
1189                                .try_as_array_mut()
1190                                .unwrap()
1191                                .set_len(n as u64);
1192                            // cl.Type is missing if we have a composite literal element
1193                            // that is itself a composite literal with omitted type. In
1194                            // that case there is nothing to record (there is no type in
1195                            // the source at that point).
1196                            if let Some(te) = &cl.typ {
1197                                self.result.record_type_and_value(
1198                                    te,
1199                                    OperandMode::TypeExpr,
1200                                    utype_key,
1201                                );
1202                            }
1203                        }
1204                    }
1205                    Type::Slice(detail) => {
1206                        // todo: the go code checks if detail.elem is nil, do we need that?
1207                        // see the original go code for details
1208                        let elem_t = detail.elem();
1209                        self.indexed_elems(&cl.elts, elem_t, None, fctx);
1210                    }
1211                    Type::Map(detail) => {
1212                        // todo: the go code checks if detail.key/elem is nil, do we need that?
1213                        // see the original go code for details
1214                        let iface_key = self
1215                            .otype(detail.key())
1216                            .underlying_val(self.tc_objs)
1217                            .try_as_interface()
1218                            .is_some();
1219                        let (t_key, t_elem) = (detail.key(), detail.elem());
1220                        let mut visited = Map::new();
1221                        for e in cl.elts.iter() {
1222                            let kv = match e {
1223                                Expr::KeyValue(kv) => kv,
1224                                _ => {
1225                                    let pos = e.pos(self.ast_objs);
1226                                    self.error_str(pos, "missing key in map literal");
1227                                    continue;
1228                                }
1229                            };
1230                            self.expr_with_hint(x, &kv.key, t_key, fctx);
1231                            self.assignment(x, Some(t_key), "map literal", fctx);
1232                            if x.invalid() {
1233                                continue;
1234                            }
1235                            if let OperandMode::Constant(v) = &x.mode {
1236                                // if the key is of interface type, the type is also significant
1237                                // when checking for duplicates
1238                                let duplicate = if iface_key {
1239                                    let o = &self.tc_objs;
1240                                    let xtype = x.typ.unwrap();
1241                                    if !visited.contains_key(v) {
1242                                        visited.insert(v.clone(), Some(vec![]));
1243                                    }
1244                                    let types = visited.get_mut(v).unwrap().as_mut().unwrap();
1245                                    let dup = types
1246                                        .iter()
1247                                        .find(|&&ty| typ::identical(ty, xtype, o))
1248                                        .is_some();
1249                                    types.push(xtype);
1250                                    dup
1251                                } else {
1252                                    let dup = visited.contains_key(v);
1253                                    if !dup {
1254                                        visited.insert(v.clone(), None);
1255                                    }
1256                                    dup
1257                                };
1258                                if duplicate {
1259                                    self.error(
1260                                        x.pos(self.ast_objs),
1261                                        format!("duplicate key {} in map literal", v),
1262                                    );
1263                                    continue;
1264                                }
1265                            }
1266                            self.expr_with_hint(x, &kv.val, t_elem, fctx);
1267                            self.assignment(x, Some(t_elem), "map literal", fctx);
1268                        }
1269                    }
1270                    _ => {
1271                        // when "using" all elements unpack KeyValueExpr
1272                        // explicitly because check.use doesn't accept them
1273                        for e in cl.elts.iter() {
1274                            let unpack = match e {
1275                                // Ideally, we should also "use" kv.Key but we can't know
1276                                // if it's an externally defined struct key or not. Going
1277                                // forward anyway can lead to other errors. Give up instead.
1278                                Expr::KeyValue(kv) => &kv.key,
1279                                _ => e,
1280                            };
1281                            self.use_exprs(&vec![unpack.clone()], fctx);
1282                        }
1283                        // if utype is invalid, an error was reported before
1284                        if utype_key != self.invalid_type() {
1285                            let td = self.new_dis(&ty);
1286                            self.error(epos, format!("invalid composite literal type {}", td));
1287                            return on_err(x);
1288                        }
1289                    }
1290                }
1291
1292                x.mode = OperandMode::Value;
1293                x.typ = Some(ty);
1294            }
1295            Expr::Paren(p) => {
1296                let kind = self.raw_expr(x, &p.expr, None, fctx);
1297                x.expr = Some(e.clone());
1298                return kind;
1299            }
1300            Expr::Selector(s) => {
1301                self.selector(x, s, fctx);
1302            }
1303            Expr::Index(ie) => {
1304                self.expr(x, &ie.expr, fctx);
1305                if x.invalid() {
1306                    self.use_exprs(&vec![ie.index.clone()], fctx);
1307                    return on_err(x);
1308                }
1309
1310                let typ_val = self.otype(x.typ.unwrap()).underlying_val(self.tc_objs);
1311                let (valid, length) = match typ_val {
1312                    Type::Basic(detail) => {
1313                        if detail.info() == typ::BasicInfo::IsString {
1314                            let len = if let OperandMode::Constant(v) = &x.mode {
1315                                Some(v.str_as_string().len() as u64)
1316                            } else {
1317                                None
1318                            };
1319                            // an indexed string always yields a byte value
1320                            // (not a constant) even if the string and the
1321                            // index are constant
1322                            x.mode = OperandMode::Value;
1323                            x.typ = Some(*self.tc_objs.universe().byte());
1324                            (true, len)
1325                        } else {
1326                            (false, None)
1327                        }
1328                    }
1329                    Type::Array(detail) => {
1330                        if x.mode != OperandMode::Variable {
1331                            x.mode = OperandMode::Value;
1332                        }
1333                        x.typ = Some(detail.elem());
1334                        (true, detail.len())
1335                    }
1336                    Type::Pointer(detail) => {
1337                        if let Some(arr) = self
1338                            .otype(detail.base())
1339                            .underlying_val(self.tc_objs)
1340                            .try_as_array()
1341                        {
1342                            x.mode = OperandMode::Variable;
1343                            x.typ = Some(arr.elem());
1344                            (true, arr.len())
1345                        } else {
1346                            (false, None)
1347                        }
1348                    }
1349                    Type::Slice(detail) => {
1350                        x.mode = OperandMode::Variable;
1351                        x.typ = Some(detail.elem());
1352                        (true, None)
1353                    }
1354                    Type::Map(detail) => {
1355                        let (key, elem) = (detail.key(), detail.elem());
1356                        let xkey = &mut Operand::new();
1357                        self.expr(xkey, &ie.index, fctx);
1358                        self.assignment(xkey, Some(key), "map index", fctx);
1359                        if x.invalid() {
1360                            return on_err(x);
1361                        }
1362                        x.mode = OperandMode::MapIndex;
1363                        x.typ = Some(elem);
1364                        x.expr = Some(e.clone());
1365                        return ExprKind::Expression;
1366                    }
1367                    _ => (false, None),
1368                };
1369
1370                if !valid {
1371                    let xd = self.new_dis(x);
1372                    self.invalid_op(xd.pos(), &format!("cannot index {}", xd));
1373                    return on_err(x);
1374                }
1375                let _ = self.index(&ie.index, length, fctx);
1376                // ok to continue
1377            }
1378            Expr::Slice(se) => {
1379                self.expr(x, &se.expr, fctx);
1380                if x.invalid() {
1381                    let exprs = [se.low.as_ref(), se.high.as_ref(), se.max.as_ref()]
1382                        .iter()
1383                        .filter_map(|x| x.map(|ex| ex.clone()))
1384                        .collect();
1385                    self.use_exprs(&exprs, fctx);
1386                    return on_err(x);
1387                }
1388
1389                let typ_val = self.otype(x.typ.unwrap()).underlying_val(self.tc_objs);
1390                let (valid, length) = match typ_val {
1391                    Type::Basic(detail) => {
1392                        if detail.info() == typ::BasicInfo::IsString {
1393                            if se.slice3 {
1394                                self.error_str(epos, "3-index slice of string");
1395                                return on_err(x);
1396                            }
1397                            let len = if let OperandMode::Constant(v) = &x.mode {
1398                                Some(v.str_as_string().len() as u64)
1399                            } else {
1400                                None
1401                            };
1402                            // spec: "For untyped string operands the result
1403                            // is a non-constant value of type string."
1404                            if detail.typ() == typ::BasicType::UntypedString {
1405                                x.typ = Some(self.basic_type(BasicType::Str));
1406                            }
1407                            (true, len)
1408                        } else {
1409                            (false, None)
1410                        }
1411                    }
1412                    Type::Array(detail) => {
1413                        if x.mode != OperandMode::Variable {
1414                            let xd = self.new_dis(x);
1415                            self.invalid_op(
1416                                xd.pos(),
1417                                &format!("cannot slice {} (value not addressable)", xd),
1418                            );
1419                            return on_err(x);
1420                        }
1421                        let (elem, len) = (detail.elem(), detail.len());
1422                        x.typ = Some(self.tc_objs.new_t_slice(elem));
1423                        (true, len)
1424                    }
1425                    Type::Pointer(detail) => {
1426                        if let Some(arr) = self
1427                            .otype(detail.base())
1428                            .underlying_val(self.tc_objs)
1429                            .try_as_array()
1430                        {
1431                            x.mode = OperandMode::Variable;
1432                            let (elem, len) = (arr.elem(), arr.len());
1433                            x.typ = Some(self.tc_objs.new_t_slice(elem));
1434                            (true, len)
1435                        } else {
1436                            (false, None)
1437                        }
1438                    }
1439                    Type::Slice(_) => (true, None),
1440                    _ => (false, None),
1441                };
1442
1443                if !valid {
1444                    let xd = self.new_dis(x);
1445                    self.invalid_op(xd.pos(), &format!("cannot slice {}", xd));
1446                    return on_err(x);
1447                }
1448                x.mode = OperandMode::Value;
1449
1450                // spec: "Only the first index may be omitted; it defaults to 0."
1451                if se.slice3 && (se.high.is_none() || se.max.is_none()) {
1452                    self.error_str(se.r_brack, "2nd and 3rd index required in 3-index slice");
1453                    return on_err(x);
1454                }
1455
1456                // check indices
1457                let ind: Vec<Option<u64>> = [se.low.as_ref(), se.high.as_ref(), se.max.as_ref()]
1458                    .iter()
1459                    .enumerate()
1460                    .map(|(i, x)| {
1461                        if let Some(e) = x {
1462                            // The "capacity" is only known statically for strings, arrays,
1463                            // and pointers to arrays, and it is the same as the length for
1464                            // those types.
1465                            let max = length.map(|x| x + 1);
1466                            self.index(e, max, fctx).unwrap_or(None)
1467                        } else if i == 0 {
1468                            Some(0)
1469                        } else {
1470                            length
1471                        }
1472                    })
1473                    .collect();
1474                // constant indices must be in range
1475                // (check.index already checks that existing indices >= 0)
1476                let pairs = [[ind[2], ind[1]], [ind[2], ind[0]], [ind[1], ind[0]]];
1477                for p in pairs.iter() {
1478                    if let (Some(a), Some(b)) = (p[0], p[1]) {
1479                        if a < b {
1480                            self.error(se.r_brack, format!("invalid slice indices: {} > {}", b, a));
1481                            break; // only report one error
1482                        }
1483                    }
1484                }
1485            }
1486            Expr::TypeAssert(ta) => {
1487                self.expr(x, &ta.expr, fctx);
1488                if x.invalid() {
1489                    return on_err(x);
1490                }
1491                let xtype = typ::underlying_type(x.typ.unwrap(), self.tc_objs);
1492                if self.otype(xtype).try_as_interface().is_none() {
1493                    let dx = self.new_dis(x);
1494                    self.invalid_op(dx.pos(), &format!("{} is not an interface", dx));
1495                    return on_err(x);
1496                }
1497                // x.(type) expressions are handled explicitly in type switches
1498                if ta.typ.is_none() {
1499                    self.invalid_ast(epos, "use of .(type) outside type switch");
1500                    return on_err(x);
1501                }
1502                let t = self.type_expr(ta.typ.as_ref().unwrap(), fctx);
1503                if t == self.invalid_type() {
1504                    return on_err(x);
1505                }
1506                self.type_assertion(None, x, xtype, t, fctx);
1507                x.mode = OperandMode::CommaOk;
1508                x.typ = Some(t)
1509            }
1510            Expr::Call(c) => return self.call(x, c, fctx),
1511            Expr::Star(se) => {
1512                self.expr_or_type(x, &se.expr, fctx);
1513                match &x.mode {
1514                    OperandMode::Invalid => return on_err(x),
1515                    OperandMode::TypeExpr => {
1516                        x.typ = Some(self.tc_objs.new_t_pointer(x.typ.unwrap()))
1517                    }
1518                    _ => {
1519                        if let Some(ptype) = self
1520                            .otype(x.typ.unwrap())
1521                            .underlying_val(self.tc_objs)
1522                            .try_as_pointer()
1523                        {
1524                            x.mode = OperandMode::Variable;
1525                            x.typ = Some(ptype.base());
1526                        } else {
1527                            let xd = self.new_dis(x);
1528                            self.invalid_op(xd.pos(), &format!("cannot indirect {}", xd));
1529                            return on_err(x);
1530                        }
1531                    }
1532                }
1533            }
1534            Expr::Unary(ue) => {
1535                self.expr(x, &ue.expr, fctx);
1536                if x.invalid() {
1537                    return on_err(x);
1538                }
1539                self.unary(x, Some(e.clone()), &ue.op);
1540                if x.invalid() {
1541                    return on_err(x);
1542                }
1543                if ue.op == Token::ARROW {
1544                    x.expr = Some(e.clone());
1545                    // receive operations may appear in statement context
1546                    return ExprKind::Statement;
1547                }
1548            }
1549            Expr::Binary(be) => {
1550                self.binary(x, Some(e), &be.expr_a, &be.expr_b, &be.op, fctx);
1551                if x.invalid() {
1552                    return on_err(x);
1553                }
1554            }
1555            Expr::KeyValue(_) => {
1556                // key:value expressions are handled in composite literals
1557                self.invalid_ast(epos, "no key:value expected");
1558                return on_err(x);
1559            }
1560            Expr::Array(_)
1561            | Expr::Struct(_)
1562            | Expr::Func(_)
1563            | Expr::Interface(_)
1564            | Expr::Map(_)
1565            | Expr::Chan(_) => {
1566                x.mode = OperandMode::TypeExpr;
1567                x.typ = Some(self.type_expr(e, fctx));
1568            }
1569        }
1570
1571        x.expr = Some(e.clone());
1572        ExprKind::Expression
1573    }
1574
1575    /// type_assertion checks that x.(T) is legal; xtyp must be the type of x.
1576    pub fn type_assertion(
1577        &mut self,
1578        pos: Option<Pos>,
1579        x: &mut Operand,
1580        xtype: TypeKey,
1581        t: TypeKey,
1582        fctx: &mut FilesContext<S>,
1583    ) {
1584        if let Some((method, wrong_type)) = lookup::assertable_to(xtype, t, self, fctx) {
1585            let dx = self.new_dis(x);
1586            self.error(
1587                pos.unwrap_or_else(|| dx.pos()),
1588                format!(
1589                    "{} cannot have dynamic type {} ({} {})",
1590                    dx,
1591                    self.new_dis(&t),
1592                    if wrong_type {
1593                        "wrong type for method"
1594                    } else {
1595                        "missing method"
1596                    },
1597                    self.lobj(method).name()
1598                ),
1599            );
1600        }
1601    }
1602
1603    fn expr_value_err(&self, x: &mut Operand) {
1604        let msg = match &x.mode {
1605            OperandMode::NoValue => Some("used as value"),
1606            OperandMode::Builtin(_) => Some("must be called"),
1607            OperandMode::TypeExpr => Some("is not an expression"),
1608            _ => None,
1609        };
1610        if let Some(m) = msg {
1611            let xd = self.new_dis(x);
1612            self.error(xd.pos(), format!("{} {}", xd, m));
1613            x.mode = OperandMode::Invalid;
1614        }
1615    }
1616
1617    pub fn single_value(&self, x: &mut Operand) {
1618        if x.mode == OperandMode::Value {
1619            // tuple types are never named - no need for underlying type below
1620            if let Some(tuple) = self.otype(x.typ.unwrap()).try_as_tuple() {
1621                let len = tuple.vars().len();
1622                assert_ne!(len, 1);
1623                let xd = self.new_dis(x);
1624                self.error(
1625                    xd.pos(),
1626                    format!("{}-valued {} where single value is expected", len, xd),
1627                );
1628                x.mode = OperandMode::Invalid;
1629            }
1630        }
1631    }
1632
1633    /// expr typechecks expression e and initializes x with the expression value.
1634    /// The result must be a single value.
1635    /// If an error occurred, x.mode is set to invalid.
1636    pub fn expr(&mut self, x: &mut Operand, e: &Expr, fctx: &mut FilesContext<S>) {
1637        self.multi_expr(x, e, fctx);
1638        self.single_value(x);
1639    }
1640
1641    /// multi_expr is like expr but the result may be a multi-value.
1642    pub fn multi_expr(&mut self, x: &mut Operand, e: &Expr, fctx: &mut FilesContext<S>) {
1643        self.raw_expr(x, e, None, fctx);
1644        self.expr_value_err(x);
1645    }
1646
1647    /// expr_or_type typechecks expression or type e and initializes x with the expression
1648    /// value or type. If an error occurred, x.mode is set to invalid.
1649    pub fn expr_or_type(&mut self, x: &mut Operand, e: &Expr, fctx: &mut FilesContext<S>) {
1650        self.raw_expr(x, e, None, fctx);
1651        self.single_value(x);
1652        if x.mode == OperandMode::NoValue {
1653            let xd = self.new_dis(x);
1654            self.error(xd.pos(), format!("{} used as value or type", xd));
1655            x.mode = OperandMode::Invalid;
1656        }
1657    }
1658
1659    /// expr_with_hint typechecks expression e and initializes x with the expression value;
1660    /// hint is the type of a composite literal element.
1661    /// If an error occurred, x.mode is set to invalid.
1662    pub fn expr_with_hint(
1663        &mut self,
1664        x: &mut Operand,
1665        e: &Expr,
1666        hint: TypeKey,
1667        fctx: &mut FilesContext<S>,
1668    ) {
1669        self.raw_expr(x, e, Some(hint), fctx);
1670        self.single_value(x);
1671        self.expr_value_err(x);
1672    }
1673}