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}