www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.bugs - [Issue 2073] New: Variant.coerce!() fails

reply d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=2073

           Summary: Variant.coerce!() fails
           Product: D
           Version: 2.014
          Platform: PC
        OS/Version: Windows
            Status: NEW
          Severity: normal
          Priority: P2
         Component: Phobos
        AssignedTo: bugzilla digitalmars.com
        ReportedBy: arkangath gmail.com


The documentation states:

If the VariantN object is a string, a parse of the string to type T is
attempted.

But it doesn't do that.

-----------
test.d:

import std.variant;

void main ()
{
    Variant v="2".dup;
    int n=v.coerce!(int);
}
------------
Runtime:
Error: Variant: attempting to use incompatible types char[] and real


-- 
May 06 2008
next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=2073


Andrei Alexandrescu <andrei metalanguage.com> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
             Status|NEW                         |ASSIGNED
                 CC|                            |andrei metalanguage.com
         AssignedTo|nobody puremagic.com        |andrei metalanguage.com


-- 
Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
Oct 11 2009
prev sibling next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=2073


Michael Rynn <y0uf00bar gmail.com> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
                 CC|                            |y0uf00bar gmail.com


--- Comment #1 from Michael Rynn <y0uf00bar gmail.com> 2010-02-06 19:27:01 PST
---
I looked at coerce because I was trying to make the std.variant pass some of
the tango.core.Variant unit tests. 

coerce needs runtime type checking, and must thereby incur a small runtime
penalty.

As well as the this, there is a failure of cast coercions for object and
interface.


T coerce(T)()
{
   // coerce is awkward because it also depends on the runtime type
    static string coerceMsg(TypeInfo t1, TypeInfo t2)
    {
        return format("Coerce from %s to %s", t1.toString, t2.toString);
    }

    static if (isNumeric!(T))
    {
      // coercive conversions will have a time penalty
      if (type == typeid(immutable(char)[]))
      {
        return to!(T)(*cast(string*)&store);
      } 
      // also do wstring and dstring ?     
      return to!(T)(get!(real));
    }
    else static if( is(T : Object) )
    {

         if (cast(TypeInfo_Class)type)
            {
                return to!(T) (( *cast(Object*) &store ));
            }
            if (cast(TypeInfo_Interface)type)
            {
                // ugly magic borrowed from object.d, to get the original
object and recast
                // why is there no direct facility for this?  like
interface.objectof property?
                // the not quite the same ugliness in _d_toObject in cast_.d
does not work
                void* p = &store;
                Interface* pi = **cast(Interface ***)*cast(void**)p;
                Object o = cast(Object)(*cast(void**)p - pi.offset);
                return to!(T)(o);
            } 
            throw new VariantException(coerceMsg(type, typeid(T)));    

         }
         else static if (is (T == interface ))
         {
            if (cast(TypeInfo_Class)type)
            {    
                return to!(T) (( *cast(Object*) &store ));
            }
            if (cast(TypeInfo_Interface)type)
            {

                void* p = &store;
                Interface* pi = **cast(Interface ***)*cast(void**)p;
                Object o = cast(Object)(*cast(void**)p - pi.offset);

                return to!(T)(o); 
            }
            throw new VariantException(coerceMsg(type, typeid(T)));    
         }
         else static if (isSomeString!(T))
        {
            return to!(T)(toString);
        }
        else
        {
            // Fix for bug 1649
            static assert(false, "unsupported type for coercion");
        }
    }

-- 
Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
Feb 06 2010
prev sibling next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=2073



--- Comment #2 from Michael Rynn <y0uf00bar gmail.com> 2010-02-06 19:43:37 PST
---
Plus once we get a valid object , an extra template is needed in std.conv for
interfaces for the Interface coercion to work, just like the Object-to-Object

For std.conv

/**
Object-to-interface conversions throw exception when the source is
non-null and the target is null.
 */
T to(T, S)(S value) if (is(S : Object) && is(T == interface))
{
    auto result = cast(T) value;
    if (!result && value)
    {
        throw new ConvError("Cannot convert object of static type "
                ~S.classinfo.name~" and dynamic type "~value.classinfo.name
                ~" to type "~T.classinfo.name);
    }
    return result;
}

And it would be nice for the unittest to reflect the increased capability.

unittest {
           interface A {}
            interface Z {}

            interface B : A {}
            class C : B {}
            class D : C {}    
            class E : Z {}


            string K = "123";

            Variant vn1 = K;

            int n1 = vn1.coerce!(int);

            assert(n1 == 123, "failed string to number coercion");

            A a = new D;
            Z x = new E;
            Variant v2 = a;
            //B b =  v2.coerce!(B);
            C c = cast(C) a;

            a = v2.coerce!(A);

            c = v2.coerce!(C);
            D d = v2.coerce!(D);

    try {
       x = v2.coerce!(Z);
    }
    catch( std.conv.ConvError ce)
    {
    //writeln("Convert error");
       x = null;
    }
    assert(x is null, "invalid coercion");
}

Issues.
--------
Should interface ref back to object ref be allowed?
Should there be a facility to do this from a "generic" interface pointer.
Attempts to do it using higher level cast thingos failed.  

There is no generic cast(Interface) like cast(Object), and we know the pointers
are not the same sort of thing.

How about something like eg,  interface(<ptr>).toObject ?, instead of exposing
the icky pointer internals.  (Also object.d and cast_.d seem to differ on how
it is done. cast.d looks like it needs a makeover)

Such a facility implicitly exists to get a this reference into every interface
virtual method call.

Having to know about TypeInfo_Class and TypeInfo_Interface, and Interface*
offsets is icky.

-- 
Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
Feb 06 2010
prev sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=2073


Andrei Alexandrescu <andrei metalanguage.com> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
             Status|ASSIGNED                    |RESOLVED
         Resolution|                            |FIXED


--- Comment #3 from Andrei Alexandrescu <andrei metalanguage.com> 2010-09-25
21:48:13 PDT ---
Fixed in http://www.dsource.org/projects/phobos/changeset/2049

-- 
Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
Sep 25 2010