x.expr = iexpr
check.record(x)
} else {
- check.exprOrType(x, call.Fun)
+ check.exprOrType(x, call.Fun, true)
}
+ // x.typ may be generic
switch x.mode {
case invalid:
case typexpr:
// conversion
+ check.nonGeneric(x)
+ if x.mode == invalid {
+ return conversion
+ }
T := x.typ
x.mode = invalid
switch n := len(call.ArgList); n {
return conversion
case builtin:
+ // no need to check for non-genericity here
id := x.id
if !check.builtin(x, call, id) {
x.mode = invalid
}
// ordinary function/method call
+ // signature may be generic
cgocall := x.mode == cgofunc
sig := asSignature(x.typ)
}
}
- check.exprOrType(x, e.X)
+ check.exprOrType(x, e.X, false)
if x.mode == invalid {
goto Error
}
- if x.mode == typexpr {
- x.typ = check.varType(e.X)
- }
-
obj, index, indirect = LookupFieldOrMethod(x.typ, x.mode == variable, check.pkg, sel)
if obj == nil {
switch {
check.use(l.ElemList...)
continue
}
- check.rawExpr(&x, e, nil)
+ check.rawExpr(&x, e, nil, false)
}
}
}
}
}
- check.rawExpr(&x, e, nil)
+ check.rawExpr(&x, e, nil, false)
if v != nil {
v.used = v_used // restore v.used
}
// rawExpr typechecks expression e and initializes x with the expression
// value or type. If an error occurred, x.mode is set to invalid.
// If hint != nil, it is the type of a composite literal element.
+// If allowGeneric is set, the operand type may be an uninstantiated
+// parameterized type or function value.
//
-func (check *Checker) rawExpr(x *operand, e syntax.Expr, hint Type) exprKind {
+func (check *Checker) rawExpr(x *operand, e syntax.Expr, hint Type, allowGeneric bool) exprKind {
if check.conf.Trace {
check.trace(e.Pos(), "expr %s", e)
check.indent++
}
kind := check.exprInternal(x, e, hint)
+
+ if !allowGeneric {
+ check.nonGeneric(x)
+ }
+
check.record(x)
return kind
}
+// If x is a generic function or type, nonGeneric reports an error and invalidates x.mode and x.typ.
+// Otherwise it leaves x alone.
+func (check *Checker) nonGeneric(x *operand) {
+ if x.mode == invalid || x.mode == novalue {
+ return
+ }
+ var what string
+ switch t := x.typ.(type) {
+ case *Named:
+ if isGeneric(t) {
+ what = "type"
+ }
+ case *Signature:
+ if t.tparams != nil {
+ what = "function"
+ }
+ }
+ if what != "" {
+ check.errorf(x.expr, "cannot use generic %s %s without instantiation", what, x.expr)
+ x.mode = invalid
+ x.typ = Typ[Invalid]
+ }
+}
+
// exprInternal contains the core of type checking of expressions.
// Must only be called by rawExpr.
//
x.typ = typ
case *syntax.ParenExpr:
- kind := check.rawExpr(x, e.X, nil)
+ kind := check.rawExpr(x, e.X, nil, false)
x.expr = e
return kind
// unary expression
if e.Op == syntax.Mul {
// pointer indirection
- check.exprOrType(x, e.X)
+ check.exprOrType(x, e.X, false)
switch x.mode {
case invalid:
goto Error
// If an error occurred, x.mode is set to invalid.
//
func (check *Checker) expr(x *operand, e syntax.Expr) {
- check.rawExpr(x, e, nil)
+ check.rawExpr(x, e, nil, false)
check.exclude(x, 1<<novalue|1<<builtin|1<<typexpr)
check.singleValue(x)
}
// multiExpr is like expr but the result may also be a multi-value.
func (check *Checker) multiExpr(x *operand, e syntax.Expr) {
- check.rawExpr(x, e, nil)
+ check.rawExpr(x, e, nil, false)
check.exclude(x, 1<<novalue|1<<builtin|1<<typexpr)
}
//
func (check *Checker) exprWithHint(x *operand, e syntax.Expr, hint Type) {
assert(hint != nil)
- check.rawExpr(x, e, hint)
+ check.rawExpr(x, e, hint, false)
check.exclude(x, 1<<novalue|1<<builtin|1<<typexpr)
check.singleValue(x)
}
// exprOrType typechecks expression or type e and initializes x with the expression value or type.
+// If allowGeneric is set, the operand type may be an uninstantiated parameterized type or function
+// value.
// If an error occurred, x.mode is set to invalid.
//
-func (check *Checker) exprOrType(x *operand, e syntax.Expr) {
- check.rawExpr(x, e, nil)
+func (check *Checker) exprOrType(x *operand, e syntax.Expr, allowGeneric bool) {
+ check.rawExpr(x, e, nil, allowGeneric)
check.exclude(x, 1<<novalue)
check.singleValue(x)
}