code: func promote2(l, r *Type) *Type {
  	l = promote1(l)
  	r = promote1(r)
  
  	// if mixed signedness, make l signed and r unsigned.
  	// specifically, if l is unsigned, swap with r.
  	if (l.Kind-Char)&1 == 1 {
  		l, r = r, l
  	}
  
  	switch {
  	case l.Kind == Void || r.Kind == Void || l.Kind > Double || r.Kind > Double:
  		return nil
  	case l.Kind == r.Kind:
  		return l
  	// double wins.
  	case l.Kind == Double:
  		return l
  	case r.Kind == Double:
  		return r
  	// float wins.
  	case l.Kind == Float:
  		return l
  	case r.Kind == Float:
  		return r
  	// if both signed or both unsigned, higher kind wins.
  	case (l.Kind-Char)&1 == (r.Kind-Char)&1:
  		if l.Kind < r.Kind {
  			return r
  		}
  		return l
  	// mixed signedness: l is signed, r is unsigned (see above).
  	// if unsigned higher kind than signed, unsigned wins.
  	case r.Kind >= l.Kind:
  		return r
  	// signed is higher kind than unsigned (l.Kind > r.Kind).
  	// if signed bigger than unsigned, signed wins.
  	// only possible way this isn't true
  	case (l.Kind-Char)/2 > (r.Kind-Char)/2 && (l.Kind != Long || r.Kind != Uint):
  		return l
  	// otherwise, use unsigned type corresponding to the signed type.
  	default:
  		return &Type{Kind: l.Kind + 1}
  	}
  	panic(fmt.Sprintf("missing case in promote2(%v, %v)", l, r))
  }
docs: // The "usual arithmetic conversions".