Thread overview
[dmd-internals] Type matching / type deduction with pointers
Dec 29, 2010
Michel Fortin
Dec 29, 2010
Michel Fortin
Dec 29, 2010
Walter Bright
December 29, 2010
I was looking at improving my patch for the "const(Object)ref" syntax so it works correctly with type matching and type deduction. To get a feel of how things should work, I built a few test cases with pointers with the intent to use them as a reference for how it should behave with classes.

**The problem is that the results for pointers don't make any sense.**

First, type matching. All the static asserts below passes. That doesn't look normal.

	// Type matching

	template cp(T : const(int)*) {
	    enum cp = 1;
	}

	static assert(cp!(int*));
	static assert(cp!(const(int*)));
	static assert(cp!(const(int)*));
	static assert(cp!(immutable(int*)));
	static assert(cp!(immutable(int)*));
	static assert(cp!(shared(int*)));
	static assert(cp!(shared(int)*));

I'd expect at least the 'shared' ones to fail, and also those where the pointer is not mutable.

Second, type deduction. All of these pragma(msg) print "int", except the last one where the template doesn't match.

	// Type deduction

	template ep(T : const(U)*, U) {
	    alias U ep;
	}

	pragma(msg, ep!(int*).stringof);            // int
	pragma(msg, ep!(const(int)*).stringof);     // int
	pragma(msg, ep!(const(int*)).stringof);     // int
	pragma(msg, ep!(immutable(int*)).stringof); // int
	pragma(msg, ep!(immutable(int)*).stringof); // int
	pragma(msg, ep!(shared(int*)).stringof);    // int
	pragma(msg, ep!(shared(int)*).stringof);    // error: no match

I'd have expected both tests with 'shared' to fail, as well as those where the pointer is not mutable.

How am I supposed to make things work correctly for class references if it doesn't even work for pointers? :-)

That said, with what I have now, type matching and type deduction seem to work equally well for class references and pointers (perhaps even a little better for class references). So I'm leaning on soon posting a new patch with what I have.

And I should probably post the above as a separate bug.


-- 
Michel Fortin
michel.fortin at michelf.com
http://michelf.com/



December 29, 2010
Le 2010-12-29 ? 11:13, Michel Fortin a ?crit :

> I was looking at improving my patch for the "const(Object)ref" syntax so it works correctly with type matching and type deduction. To get a feel of how things should work, I built a few test cases with pointers with the intent to use them as a reference for how it should behave with classes.
> 
> **The problem is that the results for pointers don't make any sense.**

Well, with a second look I see I got one thing wrong in my last message. But there's plenty of bugs that remains.

I've made a big unit test that checks a lot of things. I rigged the test so it passes for everything but added FIXME annotations for the asserts I think aren't right. There are currently 17 FIXMEs for test cases involving pointers and 13 for test cases involving Object ref.

I would appreciate if someone could pass through them all and validate whether or not I've put the FIXME annotations at the right place.


// Template matching

template a(T : Object) {
    enum a = 1;
}

static assert(a!(Object));
static assert(!is(typeof(a!(const(Object))))); // no match
static assert(!is(typeof(a!(const(Object)ref)))); // no match
static assert(!is(typeof(a!(immutable(Object))))); // no match
static assert(!is(typeof(a!(immutable(Object)ref)))); // no match
static assert(!is(typeof(a!(shared(Object))))); // no match
static assert(!is(typeof(a!(shared(Object)ref)))); // no match

template ap(T : int*) {
    enum ap = 1;
}

static assert(ap!(int*));
static assert(ap!(const(int*))); // FIXME: should not match
static assert(ap!(const(int)*)); // FIXME: should not match
static assert(ap!(immutable(int*))); // FIXME: should not match
static assert(ap!(immutable(int)*)); // FIXME: should not match
static assert(ap!(shared(int*))); // FIXME: should not match
static assert(ap!(shared(int)*)); // FIXME: should not match


template b(T : const(Object)) {
    enum b = 1;
}

static assert(b!(Object));
static assert(b!(const(Object)));
static assert(b!(const(Object)ref));
static assert(b!(immutable(Object)));
static assert(b!(immutable(Object)ref));
static assert(!is(typeof(b!(shared(Object))))); // no match
static assert(!is(typeof(b!(shared(Object)ref)))); // no match

template bp(T : const(int*)) {
    enum bp = 1;
}

static assert(bp!(int*));
static assert(bp!(const(int*)));
static assert(bp!(const(int)*));
static assert(bp!(immutable(int*)));
static assert(bp!(immutable(int)*));
static assert(bp!(shared(int*))); // FIXME: should not match
static assert(bp!(shared(int)*)); // FIXME: should not match


template c(T : const(Object)ref) {
    enum c = 1;
}

static assert(c!(Object));
static assert(c!(const(Object))); // FIXME: should not match (const ref)
static assert(c!(const(Object)ref));
static assert(c!(immutable(Object))); // FIXME: should not match (immutable ref)
static assert(c!(immutable(Object)ref));
static assert(!is(typeof(c!(shared(Object))))); // no match
static assert(!is(typeof(c!(shared(Object)ref)))); // no match

template cp(T : const(int)*) {
    enum cp = 1;
}

static assert(cp!(int*));
static assert(cp!(const(int*))); // FIXME: should not match (const ptr)
static assert(cp!(const(int)*));
static assert(cp!(immutable(int*))); // FIXME: should not match (immutable ptr)
static assert(cp!(immutable(int)*));
static assert(cp!(shared(int*))); // FIXME: should not match
static assert(cp!(shared(int)*)); // FIXME: should not match


// Type deduction

template d(T : U ref, U) {
    alias U d;
}

static assert(is(d!(Object) == Object));
static assert(is(d!(const(Object)) == const(Object))); // FIXME: should not match (const ref)
static assert(is(d!(const(Object)ref) == const(Object)ref));
static assert(is(d!(immutable(Object)) == immutable(Object))); // FIXME: should not match (immutable ref)
static assert(is(d!(immutable(Object)ref) == immutable(Object)ref));
static assert(is(d!(shared(Object)) == shared(Object))); // FIXME: should not match (shared ref)
static assert(is(d!(shared(Object)ref) == shared(Object)ref));

static assert(!is(d!(int))); // no match: 'ref' prevents matching non-class

template dp(T : U*, U) {
    alias U dp;
}

static assert(is(dp!(int*) == int));
static assert(is(dp!(const(int*)) == const(int))); // FIXME: should not match (const ptr)
static assert(is(dp!(const(int)*) == const(int)));
static assert(is(dp!(immutable(int*)) == immutable(int))); // FIXME: should not match (immutable ptr)
static assert(is(dp!(immutable(int)*) == immutable(int)));
static assert(is(dp!(shared(int*)) == shared(int))); // FIXME: should not match (shared ptr)
static assert(is(dp!(shared(int)*) == shared(int)));


template e(T : const(U), U) {
    alias U e;
}

static assert(is(e!(Object) == Object));
static assert(is(e!(const(Object)) == const(Object)ref)); // FIXME: should == Object
static assert(is(e!(const(Object)ref) == const(Object)ref)); // FIXME: should == Object
static assert(is(e!(immutable(Object)) == immutable(Object)ref)); // FIXME: should == Object
static assert(is(e!(immutable(Object)ref) == immutable(Object)ref)); // FIXME: should == Object
static assert(!is(e!(shared(Object)))); // no match
static assert(!is(e!(shared(Object)ref))); // no match

template ep(T : const(U*), U) {
    alias U ep;
}

static assert(is(ep!(int*) == int));
static assert(is(ep!(const(int*)) == int));
static assert(is(ep!(const(int)*) == int));
static assert(is(ep!(immutable(int*)) == int));
static assert(is(ep!(immutable(int)*) == int));
static assert(!is(ep!(shared(int*)))); // no match
static assert(!is(ep!(shared(int)*))); // no match


template f(T : const(U)ref, U) {
    alias U f;
}

static assert(is(f!(Object) == Object));
static assert(is(f!(const(Object)) == const(Object)ref)); // FIXME: should not match (const ref)
static assert(is(f!(const(Object)ref) == const(Object)ref)); // FIXME: should == Object
static assert(is(f!(immutable(Object)) == immutable(Object)ref)); // FIXME: should not match (immutable ref)
static assert(is(f!(immutable(Object)ref) == immutable(Object)ref)); // FIXME: should == Object
static assert(!is(f!(shared(Object)))); // no match
static assert(!is(f!(shared(Object)ref))); // no match

template fp(T : const(U)*, U) {
    alias U fp;
}

static assert(is(fp!(int*) == int));
static assert(is(fp!(const(int*)) == int)); // FIXME: should not match (const ptr)
static assert(is(fp!(const(int)*) == int));
static assert(is(fp!(immutable(int*)) == int)); // FIXME: should not match (immutable ptr)
static assert(is(fp!(immutable(int)*) == int));
static assert(!is(fp!(shared(int*)))); // no match
static assert(!is(fp!(shared(int)*))); // no match




-- 
Michel Fortin
michel.fortin at michelf.com
http://michelf.com/



December 29, 2010
Please add these to bugzilla! Thanks, -Walter

Michel Fortin wrote:
> Le 2010-12-29 ? 11:13, Michel Fortin a ?crit :
>
> 
>> I was looking at improving my patch for the "const(Object)ref" syntax so it works correctly with type matching and type deduction. To get a feel of how things should work, I built a few test cases with pointers with the intent to use them as a reference for how it should behave with classes.
>>
>> **The problem is that the results for pointers don't make any sense.**
>> 
>
> Well, with a second look I see I got one thing wrong in my last message. But there's plenty of bugs that remains.
>
> I've made a big unit test that checks a lot of things. I rigged the test so it passes for everything but added FIXME annotations for the asserts I think aren't right. There are currently 17 FIXMEs for test cases involving pointers and 13 for test cases involving Object ref.
>
> I would appreciate if someone could pass through them all and validate whether or not I've put the FIXME annotations at the right place.
>
>
> // Template matching
>
> template a(T : Object) {
>     enum a = 1;
> }
>
> static assert(a!(Object));
> static assert(!is(typeof(a!(const(Object))))); // no match
> static assert(!is(typeof(a!(const(Object)ref)))); // no match
> static assert(!is(typeof(a!(immutable(Object))))); // no match
> static assert(!is(typeof(a!(immutable(Object)ref)))); // no match
> static assert(!is(typeof(a!(shared(Object))))); // no match
> static assert(!is(typeof(a!(shared(Object)ref)))); // no match
>
> template ap(T : int*) {
>     enum ap = 1;
> }
>
> static assert(ap!(int*));
> static assert(ap!(const(int*))); // FIXME: should not match
> static assert(ap!(const(int)*)); // FIXME: should not match
> static assert(ap!(immutable(int*))); // FIXME: should not match
> static assert(ap!(immutable(int)*)); // FIXME: should not match
> static assert(ap!(shared(int*))); // FIXME: should not match
> static assert(ap!(shared(int)*)); // FIXME: should not match
>
>
> template b(T : const(Object)) {
>     enum b = 1;
> }
>
> static assert(b!(Object));
> static assert(b!(const(Object)));
> static assert(b!(const(Object)ref));
> static assert(b!(immutable(Object)));
> static assert(b!(immutable(Object)ref));
> static assert(!is(typeof(b!(shared(Object))))); // no match
> static assert(!is(typeof(b!(shared(Object)ref)))); // no match
>
> template bp(T : const(int*)) {
>     enum bp = 1;
> }
>
> static assert(bp!(int*));
> static assert(bp!(const(int*)));
> static assert(bp!(const(int)*));
> static assert(bp!(immutable(int*)));
> static assert(bp!(immutable(int)*));
> static assert(bp!(shared(int*))); // FIXME: should not match
> static assert(bp!(shared(int)*)); // FIXME: should not match
>
>
> template c(T : const(Object)ref) {
>     enum c = 1;
> }
>
> static assert(c!(Object));
> static assert(c!(const(Object))); // FIXME: should not match (const ref)
> static assert(c!(const(Object)ref));
> static assert(c!(immutable(Object))); // FIXME: should not match (immutable ref)
> static assert(c!(immutable(Object)ref));
> static assert(!is(typeof(c!(shared(Object))))); // no match
> static assert(!is(typeof(c!(shared(Object)ref)))); // no match
>
> template cp(T : const(int)*) {
>     enum cp = 1;
> }
>
> static assert(cp!(int*));
> static assert(cp!(const(int*))); // FIXME: should not match (const ptr)
> static assert(cp!(const(int)*));
> static assert(cp!(immutable(int*))); // FIXME: should not match (immutable ptr)
> static assert(cp!(immutable(int)*));
> static assert(cp!(shared(int*))); // FIXME: should not match
> static assert(cp!(shared(int)*)); // FIXME: should not match
>
>
> // Type deduction
>
> template d(T : U ref, U) {
>     alias U d;
> }
>
> static assert(is(d!(Object) == Object));
> static assert(is(d!(const(Object)) == const(Object))); // FIXME: should not match (const ref)
> static assert(is(d!(const(Object)ref) == const(Object)ref));
> static assert(is(d!(immutable(Object)) == immutable(Object))); // FIXME: should not match (immutable ref)
> static assert(is(d!(immutable(Object)ref) == immutable(Object)ref));
> static assert(is(d!(shared(Object)) == shared(Object))); // FIXME: should not match (shared ref)
> static assert(is(d!(shared(Object)ref) == shared(Object)ref));
>
> static assert(!is(d!(int))); // no match: 'ref' prevents matching non-class
>
> template dp(T : U*, U) {
>     alias U dp;
> }
>
> static assert(is(dp!(int*) == int));
> static assert(is(dp!(const(int*)) == const(int))); // FIXME: should not match (const ptr)
> static assert(is(dp!(const(int)*) == const(int)));
> static assert(is(dp!(immutable(int*)) == immutable(int))); // FIXME: should not match (immutable ptr)
> static assert(is(dp!(immutable(int)*) == immutable(int)));
> static assert(is(dp!(shared(int*)) == shared(int))); // FIXME: should not match (shared ptr)
> static assert(is(dp!(shared(int)*) == shared(int)));
>
>
> template e(T : const(U), U) {
>     alias U e;
> }
>
> static assert(is(e!(Object) == Object));
> static assert(is(e!(const(Object)) == const(Object)ref)); // FIXME: should == Object
> static assert(is(e!(const(Object)ref) == const(Object)ref)); // FIXME: should == Object
> static assert(is(e!(immutable(Object)) == immutable(Object)ref)); // FIXME: should == Object
> static assert(is(e!(immutable(Object)ref) == immutable(Object)ref)); // FIXME: should == Object
> static assert(!is(e!(shared(Object)))); // no match
> static assert(!is(e!(shared(Object)ref))); // no match
>
> template ep(T : const(U*), U) {
>     alias U ep;
> }
>
> static assert(is(ep!(int*) == int));
> static assert(is(ep!(const(int*)) == int));
> static assert(is(ep!(const(int)*) == int));
> static assert(is(ep!(immutable(int*)) == int));
> static assert(is(ep!(immutable(int)*) == int));
> static assert(!is(ep!(shared(int*)))); // no match
> static assert(!is(ep!(shared(int)*))); // no match
>
>
> template f(T : const(U)ref, U) {
>     alias U f;
> }
>
> static assert(is(f!(Object) == Object));
> static assert(is(f!(const(Object)) == const(Object)ref)); // FIXME: should not match (const ref)
> static assert(is(f!(const(Object)ref) == const(Object)ref)); // FIXME: should == Object
> static assert(is(f!(immutable(Object)) == immutable(Object)ref)); // FIXME: should not match (immutable ref)
> static assert(is(f!(immutable(Object)ref) == immutable(Object)ref)); // FIXME: should == Object
> static assert(!is(f!(shared(Object)))); // no match
> static assert(!is(f!(shared(Object)ref))); // no match
>
> template fp(T : const(U)*, U) {
>     alias U fp;
> }
>
> static assert(is(fp!(int*) == int));
> static assert(is(fp!(const(int*)) == int)); // FIXME: should not match (const ptr)
> static assert(is(fp!(const(int)*) == int));
> static assert(is(fp!(immutable(int*)) == int)); // FIXME: should not match (immutable ptr)
> static assert(is(fp!(immutable(int)*) == int));
> static assert(!is(fp!(shared(int*)))); // no match
> static assert(!is(fp!(shared(int)*))); // no match
>
>
>
>
>