Commit 5f4f5647 authored by Russ Cox's avatar Russ Cox

require type assertions when narrowing.

R=ken
OCL=24350
CL=24914
parent 49e20878
......@@ -827,9 +827,9 @@ Type* fixchan(Type*);
Node* chanop(Node*, int);
Node* arrayop(Node*, int);
Node* ifaceop(Type*, Node*, int);
int ifaceas(Type*, Type*);
int ifaceas1(Type*, Type*);
void ifacecheck(Type*, Type*, int);
int ifaceas(Type*, Type*, int);
int ifaceas1(Type*, Type*, int);
void ifacecheck(Type*, Type*, int, int);
void runifacechecks(void);
Node* convas(Node*);
void arrayconv(Type*, Node*);
......
......@@ -2735,12 +2735,13 @@ struct Icheck
Type *dst;
Type *src;
int lineno;
int explicit;
};
Icheck *icheck;
Icheck *ichecktail;
void
ifacecheck(Type *dst, Type *src, int lineno)
ifacecheck(Type *dst, Type *src, int lineno, int explicit)
{
Icheck *p;
......@@ -2752,6 +2753,7 @@ ifacecheck(Type *dst, Type *src, int lineno)
p->dst = dst;
p->src = src;
p->lineno = lineno;
p->explicit = explicit;
ichecktail = p;
}
......@@ -2761,6 +2763,9 @@ ifacelookdot(Sym *s, Type *t)
int c, d;
Type *m;
if(t == T)
return T;
for(d=0; d<nelem(dotlist); d++) {
c = adddot1(s, t, d, &m);
if(c > 1) {
......@@ -2773,15 +2778,15 @@ ifacelookdot(Sym *s, Type *t)
return T;
}
// check whether non-interface type t
// satisifes inteface type iface.
int
hasiface(Type *t, Type *iface, Type **m)
ifaceokT2I(Type *t, Type *iface, Type **m)
{
Type *im, *tm;
int imhash;
t = methtype(t);
if(t == T)
return 0;
// if this is too slow,
// could sort these first
......@@ -2805,26 +2810,66 @@ hasiface(Type *t, Type *iface, Type **m)
return 1;
}
// check whether interface type i1 satisifes interface type i2.
int
ifaceokI2I(Type *i1, Type *i2, Type **m)
{
Type *m1, *m2;
// if this is too slow,
// could sort these first
// and then do one loop.
for(m2=i2->type; m2; m2=m2->down) {
for(m1=i1->type; m1; m1=m1->down)
if(m1->sym == m2->sym && typehash(m1, 0) == typehash(m2, 0))
goto found;
*m = m2;
return 0;
found:;
}
return 1;
}
void
runifacechecks(void)
{
Icheck *p;
int lno;
Type *m, *l, *r;
int lno, wrong, needexplicit;
Type *m, *t, *iface;
lno = lineno;
for(p=icheck; p; p=p->next) {
lineno = p->lineno;
if(isinter(p->dst)) {
l = p->src;
r = p->dst;
wrong = 0;
needexplicit = 0;
m = nil;
if(isinter(p->dst) && isinter(p->src)) {
iface = p->dst;
t = p->src;
needexplicit = !ifaceokI2I(t, iface, &m);
}
else if(isinter(p->dst)) {
t = p->src;
iface = p->dst;
wrong = !ifaceokT2I(t, iface, &m);
} else {
l = p->dst;
r = p->src;
t = p->dst;
iface = p->src;
wrong = !ifaceokT2I(t, iface, &m);
needexplicit = 1;
}
if(wrong)
yyerror("%T is not %T\n\tmissing %S%hhT",
t, iface, m->sym, m->type);
else if(!p->explicit && needexplicit) {
if(m)
yyerror("need explicit conversion to use %T as %T\n\tmissing %S%hhT",
p->src, p->dst, m->sym, m->type);
else
yyerror("need explicit conversion to use %T as %T",
p->src, p->dst);
}
if(!hasiface(l, r, &m))
yyerror("%T is not %T - missing %S%hhT",
l, r, m->sym, m->type);
}
lineno = lno;
}
......@@ -513,7 +513,7 @@ loop:
walktype(r->left, Erv);
if(r->left == N)
break;
et = ifaceas1(r->type, r->left->type);
et = ifaceas1(r->type, r->left->type, 1);
switch(et) {
case I2T:
et = I2T2;
......@@ -651,7 +651,7 @@ loop:
}
// interface assignment
et = ifaceas(n->type, l->type);
et = ifaceas(n->type, l->type, 1);
if(et != Inone) {
indir(n, ifaceop(n->type, l, et));
goto ret;
......@@ -2812,7 +2812,7 @@ arrayop(Node *n, int top)
* return op to use.
*/
int
ifaceas1(Type *dst, Type *src)
ifaceas1(Type *dst, Type *src, int explicit)
{
if(src == T || dst == T)
return Inone;
......@@ -2821,17 +2821,17 @@ ifaceas1(Type *dst, Type *src)
if(isinter(src)) {
if(eqtype(dst, src, 0))
return I2Isame;
if(!isnilinter(dst))
ifacecheck(dst, src, lineno, explicit);
return I2I;
}
if(isnilinter(dst))
return T2I;
ifacecheck(dst, src, lineno);
ifacecheck(dst, src, lineno, explicit);
return T2I;
}
if(isinter(src)) {
if(isnilinter(src))
return I2T;
ifacecheck(dst, src, lineno);
ifacecheck(dst, src, lineno, explicit);
return I2T;
}
return Inone;
......@@ -2841,11 +2841,11 @@ ifaceas1(Type *dst, Type *src)
* treat convert T to T as noop
*/
int
ifaceas(Type *dst, Type *src)
ifaceas(Type *dst, Type *src, int explicit)
{
int et;
et = ifaceas1(dst, src);
et = ifaceas1(dst, src, explicit);
if(et == I2Isame)
et = Inone;
return et;
......@@ -2987,7 +2987,7 @@ convas(Node *n)
if(eqtype(lt, rt, 0))
goto out;
et = ifaceas(lt, rt);
et = ifaceas(lt, rt, 0);
if(et != Inone) {
n->right = ifaceop(lt, r, et);
goto out;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment