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*); ...@@ -827,9 +827,9 @@ Type* fixchan(Type*);
Node* chanop(Node*, int); Node* chanop(Node*, int);
Node* arrayop(Node*, int); Node* arrayop(Node*, int);
Node* ifaceop(Type*, Node*, int); Node* ifaceop(Type*, Node*, int);
int ifaceas(Type*, Type*); int ifaceas(Type*, Type*, int);
int ifaceas1(Type*, Type*); int ifaceas1(Type*, Type*, int);
void ifacecheck(Type*, Type*, int); void ifacecheck(Type*, Type*, int, int);
void runifacechecks(void); void runifacechecks(void);
Node* convas(Node*); Node* convas(Node*);
void arrayconv(Type*, Node*); void arrayconv(Type*, Node*);
......
...@@ -2735,12 +2735,13 @@ struct Icheck ...@@ -2735,12 +2735,13 @@ struct Icheck
Type *dst; Type *dst;
Type *src; Type *src;
int lineno; int lineno;
int explicit;
}; };
Icheck *icheck; Icheck *icheck;
Icheck *ichecktail; Icheck *ichecktail;
void void
ifacecheck(Type *dst, Type *src, int lineno) ifacecheck(Type *dst, Type *src, int lineno, int explicit)
{ {
Icheck *p; Icheck *p;
...@@ -2752,6 +2753,7 @@ ifacecheck(Type *dst, Type *src, int lineno) ...@@ -2752,6 +2753,7 @@ ifacecheck(Type *dst, Type *src, int lineno)
p->dst = dst; p->dst = dst;
p->src = src; p->src = src;
p->lineno = lineno; p->lineno = lineno;
p->explicit = explicit;
ichecktail = p; ichecktail = p;
} }
...@@ -2761,6 +2763,9 @@ ifacelookdot(Sym *s, Type *t) ...@@ -2761,6 +2763,9 @@ ifacelookdot(Sym *s, Type *t)
int c, d; int c, d;
Type *m; Type *m;
if(t == T)
return T;
for(d=0; d<nelem(dotlist); d++) { for(d=0; d<nelem(dotlist); d++) {
c = adddot1(s, t, d, &m); c = adddot1(s, t, d, &m);
if(c > 1) { if(c > 1) {
...@@ -2773,15 +2778,15 @@ ifacelookdot(Sym *s, Type *t) ...@@ -2773,15 +2778,15 @@ ifacelookdot(Sym *s, Type *t)
return T; return T;
} }
// check whether non-interface type t
// satisifes inteface type iface.
int int
hasiface(Type *t, Type *iface, Type **m) ifaceokT2I(Type *t, Type *iface, Type **m)
{ {
Type *im, *tm; Type *im, *tm;
int imhash; int imhash;
t = methtype(t); t = methtype(t);
if(t == T)
return 0;
// if this is too slow, // if this is too slow,
// could sort these first // could sort these first
...@@ -2805,26 +2810,66 @@ hasiface(Type *t, Type *iface, Type **m) ...@@ -2805,26 +2810,66 @@ hasiface(Type *t, Type *iface, Type **m)
return 1; 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 void
runifacechecks(void) runifacechecks(void)
{ {
Icheck *p; Icheck *p;
int lno; int lno, wrong, needexplicit;
Type *m, *l, *r; Type *m, *t, *iface;
lno = lineno; lno = lineno;
for(p=icheck; p; p=p->next) { for(p=icheck; p; p=p->next) {
lineno = p->lineno; lineno = p->lineno;
if(isinter(p->dst)) { wrong = 0;
l = p->src; needexplicit = 0;
r = p->dst; 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 { } else {
l = p->dst; t = p->dst;
r = p->src; 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; lineno = lno;
} }
...@@ -513,7 +513,7 @@ loop: ...@@ -513,7 +513,7 @@ loop:
walktype(r->left, Erv); walktype(r->left, Erv);
if(r->left == N) if(r->left == N)
break; break;
et = ifaceas1(r->type, r->left->type); et = ifaceas1(r->type, r->left->type, 1);
switch(et) { switch(et) {
case I2T: case I2T:
et = I2T2; et = I2T2;
...@@ -651,7 +651,7 @@ loop: ...@@ -651,7 +651,7 @@ loop:
} }
// interface assignment // interface assignment
et = ifaceas(n->type, l->type); et = ifaceas(n->type, l->type, 1);
if(et != Inone) { if(et != Inone) {
indir(n, ifaceop(n->type, l, et)); indir(n, ifaceop(n->type, l, et));
goto ret; goto ret;
...@@ -2812,7 +2812,7 @@ arrayop(Node *n, int top) ...@@ -2812,7 +2812,7 @@ arrayop(Node *n, int top)
* return op to use. * return op to use.
*/ */
int int
ifaceas1(Type *dst, Type *src) ifaceas1(Type *dst, Type *src, int explicit)
{ {
if(src == T || dst == T) if(src == T || dst == T)
return Inone; return Inone;
...@@ -2821,17 +2821,17 @@ ifaceas1(Type *dst, Type *src) ...@@ -2821,17 +2821,17 @@ ifaceas1(Type *dst, Type *src)
if(isinter(src)) { if(isinter(src)) {
if(eqtype(dst, src, 0)) if(eqtype(dst, src, 0))
return I2Isame; return I2Isame;
if(!isnilinter(dst))
ifacecheck(dst, src, lineno, explicit);
return I2I; return I2I;
} }
if(isnilinter(dst)) if(isnilinter(dst))
return T2I; return T2I;
ifacecheck(dst, src, lineno); ifacecheck(dst, src, lineno, explicit);
return T2I; return T2I;
} }
if(isinter(src)) { if(isinter(src)) {
if(isnilinter(src)) ifacecheck(dst, src, lineno, explicit);
return I2T;
ifacecheck(dst, src, lineno);
return I2T; return I2T;
} }
return Inone; return Inone;
...@@ -2841,11 +2841,11 @@ ifaceas1(Type *dst, Type *src) ...@@ -2841,11 +2841,11 @@ ifaceas1(Type *dst, Type *src)
* treat convert T to T as noop * treat convert T to T as noop
*/ */
int int
ifaceas(Type *dst, Type *src) ifaceas(Type *dst, Type *src, int explicit)
{ {
int et; int et;
et = ifaceas1(dst, src); et = ifaceas1(dst, src, explicit);
if(et == I2Isame) if(et == I2Isame)
et = Inone; et = Inone;
return et; return et;
...@@ -2987,7 +2987,7 @@ convas(Node *n) ...@@ -2987,7 +2987,7 @@ convas(Node *n)
if(eqtype(lt, rt, 0)) if(eqtype(lt, rt, 0))
goto out; goto out;
et = ifaceas(lt, rt); et = ifaceas(lt, rt, 0);
if(et != Inone) { if(et != Inone) {
n->right = ifaceop(lt, r, et); n->right = ifaceop(lt, r, et);
goto out; 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