@@ -35,149 +35,123 @@ func (check *checker) assignment(x *operand, to Type) bool {
35
35
}
36
36
37
37
// assign1to1 typechecks a single assignment of the form lhs = rhs (if rhs != nil),
38
- // or lhs = x (if rhs == nil). If decl is set, the lhs operand must be an identifier.
39
- // If its type is not set, it is deduced from the type or value of x. If lhs has a
40
- // type it is used as a hint when evaluating rhs, if present .
38
+ // or lhs = x (if rhs == nil). If decl is set, the lhs operand must be an identifier;
39
+ // if its type is not set, it is deduced from the type of x or set to Typ[Invalid] in
40
+ // case of an error .
41
41
//
42
42
func (check * checker ) assign1to1 (lhs , rhs ast.Expr , x * operand , decl bool , iota int ) {
43
- ident , _ := lhs .(* ast.Ident )
43
+ // Start with rhs so we have an expression type
44
+ // for declarations with implicit type.
44
45
if x == nil {
45
- assert (rhs != nil )
46
46
x = new (operand )
47
- }
48
-
49
- if ident != nil && ident .Name == "_" {
50
- // anything can be assigned to a blank identifier - check rhs only, if present
51
- if rhs != nil {
52
- check .expr (x , rhs , nil , iota )
47
+ check .expr (x , rhs , nil , iota )
48
+ // don't exit for declarations - we need the lhs obj first
49
+ if x .mode == invalid && ! decl {
50
+ return
53
51
}
54
- return
55
52
}
53
+ // x.mode == valid || decl
54
+
55
+ // lhs may be an identifier
56
+ ident , _ := lhs .(* ast.Ident )
56
57
58
+ // regular assignment; we know x is valid
57
59
if ! decl {
58
- // regular assignment - start with lhs to obtain a type hint
59
- // TODO(gri) clean this up - we don't need type hints anymore
60
+ // anything can be assigned to the blank identifier
61
+ if ident != nil && ident .Name == "_" {
62
+ return
63
+ }
64
+
60
65
var z operand
61
66
check .expr (& z , lhs , nil , - 1 )
62
67
if z .mode == invalid {
63
- z .typ = nil // so we can proceed with rhs
64
- }
65
-
66
- if rhs != nil {
67
- check .expr (x , rhs , z .typ , - 1 )
68
- if x .mode == invalid {
69
- return
70
- }
71
- }
72
-
73
- if x .mode == invalid || z .mode == invalid {
74
68
return
75
69
}
76
70
77
- if ! check .assignment (x , z .typ ) {
71
+ // TODO(gri) verify that all other z.mode values
72
+ // that may appear here are legal
73
+ if z .mode == constant || ! check .assignment (x , z .typ ) {
78
74
if x .mode != invalid {
79
75
check .errorf (x .pos (), "cannot assign %s to %s" , x , & z )
80
76
}
81
- return
82
- }
83
- if z .mode == constant {
84
- check .errorf (x .pos (), "cannot assign %s to %s" , x , & z )
85
77
}
86
78
return
87
79
}
88
80
89
- // declaration - lhs must be an identifier
81
+ // declaration with initialization; lhs must be an identifier
90
82
if ident == nil {
91
83
check .errorf (lhs .Pos (), "cannot declare %s" , lhs )
92
84
return
93
85
}
94
86
95
- // lhs may or may not be typed yet
96
- obj := check .lookup (ident )
87
+ // Determine typ of lhs: If the object doesn't have a type
88
+ // yet, determine it from the type of x; if x is invalid,
89
+ // set the object type to Typ[Invalid].
97
90
var typ Type
98
- if t := obj .GetType (); t != nil {
99
- typ = t
100
- }
91
+ obj := check .lookup (ident )
92
+ switch obj := obj .(type ) {
93
+ default :
94
+ unreachable ()
101
95
102
- if rhs != nil {
103
- check .expr (x , rhs , typ , iota )
104
- // continue even if x.mode == invalid
105
- }
96
+ case nil :
97
+ // TODO(gri) is this really unreachable?
98
+ unreachable ()
106
99
107
- if typ == nil {
108
- // determine lhs type from rhs expression;
109
- // for variables, convert untyped types to
110
- // default types
111
- typ = Typ [Invalid ]
112
- if x .mode != invalid {
113
- typ = x .typ
114
- if _ , ok := obj .(* Var ); ok && isUntyped (typ ) {
115
- if x .isNil () {
116
- check .errorf (x .pos (), "use of untyped nil" )
117
- x .mode = invalid
118
- } else {
100
+ case * Const :
101
+ typ = obj .Type // may already be Typ[Invalid]
102
+ if typ == nil {
103
+ typ = Typ [Invalid ]
104
+ if x .mode != invalid {
105
+ typ = x .typ
106
+ }
107
+ obj .Type = typ
108
+ }
109
+
110
+ case * Var :
111
+ typ = obj .Type // may already be Typ[Invalid]
112
+ if typ == nil {
113
+ typ = Typ [Invalid ]
114
+ if x .mode != invalid {
115
+ typ = x .typ
116
+ if isUntyped (typ ) {
117
+ // convert untyped types to default types
118
+ if typ == Typ [UntypedNil ] {
119
+ check .errorf (x .pos (), "use of untyped nil" )
120
+ obj .Type = Typ [Invalid ]
121
+ return
122
+ }
119
123
typ = defaultType (typ )
120
124
}
121
125
}
122
- }
123
- switch obj := obj .(type ) {
124
- case * Const :
125
- obj .Type = typ
126
- case * Var :
127
126
obj .Type = typ
128
- default :
129
- unreachable ()
130
127
}
131
128
}
132
129
133
- if x .mode != invalid {
134
- if ! check .assignment (x , typ ) {
135
- if x .mode != invalid {
136
- switch obj .(type ) {
137
- case * Const :
138
- check .errorf (x .pos (), "cannot assign %s to variable of type %s" , x , typ )
139
- case * Var :
140
- check .errorf (x .pos (), "cannot initialize constant of type %s with %s" , typ , x )
141
- default :
142
- unreachable ()
143
- }
144
- x .mode = invalid
130
+ // nothing else to check if we don't have a valid lhs or rhs
131
+ if typ == Typ [Invalid ] || x .mode == invalid {
132
+ return
133
+ }
134
+
135
+ if ! check .assignment (x , typ ) {
136
+ if x .mode != invalid {
137
+ if x .typ != Typ [Invalid ] && typ != Typ [Invalid ] {
138
+ check .errorf (x .pos (), "cannot initialize %s (type %s) with %s" , ident .Name , typ , x )
145
139
}
146
140
}
141
+ return
147
142
}
148
143
149
144
// for constants, set their value
150
- if obj , ok := obj .(* Const ); ok {
151
- assert (obj .Val == nil )
152
- if x .mode != invalid {
153
- if x .mode == constant {
154
- if isConstType (x .typ ) {
155
- obj .Val = x .val
156
- } else {
157
- check .errorf (x .pos (), "%s has invalid constant type" , x )
158
- }
159
- } else {
160
- check .errorf (x .pos (), "%s is not constant" , x )
161
- }
162
- }
163
- if obj .Val == nil {
164
- // set the constant to its type's zero value to reduce spurious errors
165
- switch typ := underlying (obj .Type ); {
166
- case typ == Typ [Invalid ]:
167
- // ignore
168
- case isBoolean (typ ):
169
- obj .Val = false
170
- case isNumeric (typ ):
171
- obj .Val = int64 (0 )
172
- case isString (typ ):
173
- obj .Val = ""
174
- case hasNil (typ ):
175
- obj .Val = nilConst
176
- default :
177
- // in all other cases just prevent use of the constant
178
- // TODO(gri) re-evaluate this code
179
- obj .Val = nilConst
145
+ if obj , _ := obj .(* Const ); obj != nil {
146
+ obj .Val = nil // failure case: we don't know the constant value
147
+ if x .mode == constant {
148
+ if isConstType (x .typ ) {
149
+ obj .Val = x .val
150
+ } else if x .typ != Typ [Invalid ] {
151
+ check .errorf (x .pos (), "%s has invalid constant type" , x )
180
152
}
153
+ } else if x .mode != invalid {
154
+ check .errorf (x .pos (), "%s is not constant" , x )
181
155
}
182
156
}
183
157
}
@@ -494,6 +468,7 @@ func (check *checker) stmt(s ast.Stmt) {
494
468
check .expr (& x , tag , nil , - 1 )
495
469
496
470
check .multipleDefaults (s .Body .List )
471
+ // TODO(gri) check also correct use of fallthrough
497
472
seen := make (map [interface {}]token.Pos )
498
473
for _ , s := range s .Body .List {
499
474
clause , _ := s .(* ast.CaseClause )
0 commit comments