Black Lives Matter. Support the Equal Justice Initiative.

Source file src/cmd/compile/internal/typecheck/type.go

Documentation: cmd/compile/internal/typecheck

     1  // Copyright 2009 The Go 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  package typecheck
     6  
     7  import (
     8  	"go/constant"
     9  
    10  	"cmd/compile/internal/base"
    11  	"cmd/compile/internal/ir"
    12  	"cmd/compile/internal/types"
    13  )
    14  
    15  // tcArrayType typechecks an OTARRAY node.
    16  func tcArrayType(n *ir.ArrayType) ir.Node {
    17  	n.Elem = typecheckNtype(n.Elem)
    18  	if n.Elem.Type() == nil {
    19  		return n
    20  	}
    21  	if n.Len == nil { // [...]T
    22  		if !n.Diag() {
    23  			n.SetDiag(true)
    24  			base.Errorf("use of [...] array outside of array literal")
    25  		}
    26  		return n
    27  	}
    28  	n.Len = indexlit(Expr(n.Len))
    29  	size := n.Len
    30  	if ir.ConstType(size) != constant.Int {
    31  		switch {
    32  		case size.Type() == nil:
    33  			// Error already reported elsewhere.
    34  		case size.Type().IsInteger() && size.Op() != ir.OLITERAL:
    35  			base.Errorf("non-constant array bound %v", size)
    36  		default:
    37  			base.Errorf("invalid array bound %v", size)
    38  		}
    39  		return n
    40  	}
    41  
    42  	v := size.Val()
    43  	if ir.ConstOverflow(v, types.Types[types.TINT]) {
    44  		base.Errorf("array bound is too large")
    45  		return n
    46  	}
    47  
    48  	if constant.Sign(v) < 0 {
    49  		base.Errorf("array bound must be non-negative")
    50  		return n
    51  	}
    52  
    53  	bound, _ := constant.Int64Val(v)
    54  	t := types.NewArray(n.Elem.Type(), bound)
    55  	n.SetOTYPE(t)
    56  	types.CheckSize(t)
    57  	return n
    58  }
    59  
    60  // tcChanType typechecks an OTCHAN node.
    61  func tcChanType(n *ir.ChanType) ir.Node {
    62  	n.Elem = typecheckNtype(n.Elem)
    63  	l := n.Elem
    64  	if l.Type() == nil {
    65  		return n
    66  	}
    67  	if l.Type().NotInHeap() {
    68  		base.Errorf("chan of incomplete (or unallocatable) type not allowed")
    69  	}
    70  	n.SetOTYPE(types.NewChan(l.Type(), n.Dir))
    71  	return n
    72  }
    73  
    74  // tcFuncType typechecks an OTFUNC node.
    75  func tcFuncType(n *ir.FuncType) ir.Node {
    76  	misc := func(f *types.Field, nf *ir.Field) {
    77  		f.SetIsDDD(nf.IsDDD)
    78  		if nf.Decl != nil {
    79  			nf.Decl.SetType(f.Type)
    80  			f.Nname = nf.Decl
    81  		}
    82  	}
    83  
    84  	lno := base.Pos
    85  
    86  	var recv *types.Field
    87  	if n.Recv != nil {
    88  		recv = tcField(n.Recv, misc)
    89  	}
    90  
    91  	t := types.NewSignature(types.LocalPkg, recv, nil, tcFields(n.Params, misc), tcFields(n.Results, misc))
    92  	checkdupfields("argument", t.Recvs().FieldSlice(), t.Params().FieldSlice(), t.Results().FieldSlice())
    93  
    94  	base.Pos = lno
    95  
    96  	n.SetOTYPE(t)
    97  	return n
    98  }
    99  
   100  // tcInterfaceType typechecks an OTINTER node.
   101  func tcInterfaceType(n *ir.InterfaceType) ir.Node {
   102  	if len(n.Methods) == 0 {
   103  		n.SetOTYPE(types.Types[types.TINTER])
   104  		return n
   105  	}
   106  
   107  	lno := base.Pos
   108  	methods := tcFields(n.Methods, nil)
   109  	base.Pos = lno
   110  
   111  	n.SetOTYPE(types.NewInterface(types.LocalPkg, methods))
   112  	return n
   113  }
   114  
   115  // tcMapType typechecks an OTMAP node.
   116  func tcMapType(n *ir.MapType) ir.Node {
   117  	n.Key = typecheckNtype(n.Key)
   118  	n.Elem = typecheckNtype(n.Elem)
   119  	l := n.Key
   120  	r := n.Elem
   121  	if l.Type() == nil || r.Type() == nil {
   122  		return n
   123  	}
   124  	if l.Type().NotInHeap() {
   125  		base.Errorf("incomplete (or unallocatable) map key not allowed")
   126  	}
   127  	if r.Type().NotInHeap() {
   128  		base.Errorf("incomplete (or unallocatable) map value not allowed")
   129  	}
   130  	n.SetOTYPE(types.NewMap(l.Type(), r.Type()))
   131  	mapqueue = append(mapqueue, n) // check map keys when all types are settled
   132  	return n
   133  }
   134  
   135  // tcSliceType typechecks an OTSLICE node.
   136  func tcSliceType(n *ir.SliceType) ir.Node {
   137  	n.Elem = typecheckNtype(n.Elem)
   138  	if n.Elem.Type() == nil {
   139  		return n
   140  	}
   141  	t := types.NewSlice(n.Elem.Type())
   142  	n.SetOTYPE(t)
   143  	types.CheckSize(t)
   144  	return n
   145  }
   146  
   147  // tcStructType typechecks an OTSTRUCT node.
   148  func tcStructType(n *ir.StructType) ir.Node {
   149  	lno := base.Pos
   150  
   151  	fields := tcFields(n.Fields, func(f *types.Field, nf *ir.Field) {
   152  		if nf.Embedded {
   153  			checkembeddedtype(f.Type)
   154  			f.Embedded = 1
   155  		}
   156  		f.Note = nf.Note
   157  	})
   158  	checkdupfields("field", fields)
   159  
   160  	base.Pos = lno
   161  	n.SetOTYPE(types.NewStruct(types.LocalPkg, fields))
   162  	return n
   163  }
   164  
   165  // tcField typechecks a generic Field.
   166  // misc can be provided to handle specialized typechecking.
   167  func tcField(n *ir.Field, misc func(*types.Field, *ir.Field)) *types.Field {
   168  	base.Pos = n.Pos
   169  	if n.Ntype != nil {
   170  		n.Type = typecheckNtype(n.Ntype).Type()
   171  		n.Ntype = nil
   172  	}
   173  	f := types.NewField(n.Pos, n.Sym, n.Type)
   174  	if misc != nil {
   175  		misc(f, n)
   176  	}
   177  	return f
   178  }
   179  
   180  // tcFields typechecks a slice of generic Fields.
   181  // misc can be provided to handle specialized typechecking.
   182  func tcFields(l []*ir.Field, misc func(*types.Field, *ir.Field)) []*types.Field {
   183  	fields := make([]*types.Field, len(l))
   184  	for i, n := range l {
   185  		fields[i] = tcField(n, misc)
   186  	}
   187  	return fields
   188  }
   189  

View as plain text