]> Cypherpunks repositories - gostls13.git/commitdiff
implement new spec language regarding conversions
authorRuss Cox <rsc@golang.org>
Fri, 19 Jun 2009 21:00:53 +0000 (14:00 -0700)
committerRuss Cox <rsc@golang.org>
Fri, 19 Jun 2009 21:00:53 +0000 (14:00 -0700)
R=ken
OCL=30519
CL=30534

src/cmd/gc/subr.c
src/cmd/gc/walk.c

index 0ff75248b80c418394932cd1d5831a4562108241..43cde4ac4f6549cc30e98d98d81e6e1ec6591103 100644 (file)
@@ -1723,10 +1723,29 @@ eqtype(Type *t1, Type *t2)
        return eqtype1(t1, t2, 0, 1);
 }
 
+/*
+ * can we convert from type src to dst with
+ * a trivial conversion (no bits changing)?
+ */
 int
-cvttype(Type *t1, Type *t2)
+cvttype(Type *dst, Type *src)
 {
-       return eqtype1(t1, t2, 0, 0);
+       Sym *ds, *ss;
+       int ret;
+
+       if(eqtype1(dst, src, 0, 0))
+               return 1;
+
+       // Can convert if assignment compatible when
+       // top-level names are ignored.
+       ds = dst->sym;
+       dst->sym = nil;
+       ss = src->sym;
+       src->sym = nil;
+       ret = ascompat(dst, src);
+       dst->sym = ds;
+       src->sym = ss;
+       return ret == 1;
 }
 
 int
index e29d608cd85248fadb44215502b8c5e71178c31e..bcd139f4baa785e0bc55df17459008ac5f203fac 100644 (file)
@@ -1301,7 +1301,7 @@ walkconv(Node *n)
                return;
 
        // no-op conversion
-       if(cvttype(t, l->type)) {
+       if(cvttype(t, l->type) == 1) {
        nop:
                if(l->op != ONAME) {
                        indir(n, l);
@@ -2217,7 +2217,8 @@ exportasok(Type *t)
 }
 
 /*
- * can we assign var of type src to var of type dst
+ * can we assign var of type src to var of type dst?
+ * return 0 if not, 1 if conversion is trivial, 2 if conversion is non-trivial.
  */
 int
 ascompat(Type *dst, Type *src)
@@ -2230,6 +2231,28 @@ ascompat(Type *dst, Type *src)
        if(dst == T || src == T)
                return 0;
 
+       if(dst->etype == TFORWINTER || dst->etype == TFORWSTRUCT || dst->etype == TFORW)
+               return 0;
+       if(src->etype == TFORWINTER || src->etype == TFORWSTRUCT || src->etype == TFORW)
+               return 0;
+
+       // interfaces go through even if names don't match
+       if(isnilinter(dst) || isnilinter(src))
+               return 2;
+
+       if(isinter(dst) && isinter(src))
+               return 2;
+
+       if(isinter(dst) && methtype(src))
+               return 2;
+
+       if(isinter(src) && methtype(dst))
+               return 2;
+
+       // otherwise, if concrete types have names, they must match
+       if(dst->sym && src->sym && dst != src)
+               return 0;
+
        if(dst->etype == TCHAN && src->etype == TCHAN) {
                if(!eqtype(dst->type, src->type))
                        return 0;
@@ -2242,19 +2265,7 @@ ascompat(Type *dst, Type *src)
        && isptr[src->etype]
        && isfixedarray(src->type)
        && eqtype(dst->type, src->type->type))
-               return 1;
-
-       if(isnilinter(dst) || isnilinter(src))
-               return 1;
-
-       if(isinter(dst) && isinter(src))
-               return 1;
-
-       if(isinter(dst) && methtype(src))
-               return 1;
-
-       if(isinter(src) && methtype(dst))
-               return 1;
+               return 2;
 
        return 0;
 }