D issues are now tracked on GitHub. This Bugzilla instance remains as a read-only archive.
Issue 5531 - Erratic type deduction with pointers and type modifiers
Summary: Erratic type deduction with pointers and type modifiers
Status: RESOLVED WORKSFORME
Alias: None
Product: D
Classification: Unclassified
Component: dmd (show other issues)
Version: D2
Hardware: Other All
: P2 normal
Assignee: No Owner
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2011-02-06 07:38 UTC by Michel Fortin
Modified: 2017-07-21 08:56 UTC (History)
0 users

See Also:


Attachments

Note You need to log in before you can comment on or make changes to this issue.
Description Michel Fortin 2011-02-06 07:38:12 UTC
Type deduction should match types which are a specialization of the given base type, but this doesn't work when type modifiers are involved. Here is a list of test cases which have been rigged to pass with the current compiler, but each test with a FIXME on should be considered wrong.

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 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 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

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 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 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 ref)
static assert(is(fp!(immutable(int)*) == int));
static assert(!is(fp!(shared(int*)))); // no match
static assert(!is(fp!(shared(int)*))); // no match
Comment 1 Vladimir Panteleev 2017-07-21 08:56:48 UTC
These seem to have been mostly fixed (or, at least, changed) since they were posted.

(In reply to Michel Fortin from comment #0)
> 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

All fixed.

> 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

Also fixed.

> 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)*));

Here it looks like it's intentionally allowing it to strip head const, which is generally harmless.

> 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)));
> 
> 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 ref)
> static assert(is(fp!(immutable(int)*) == int));

Ditto.

> static assert(cp!(shared(int*))); // FIXME: should not match
> static assert(cp!(shared(int)*)); // FIXME: should not match
> 
> static assert(is(dp!(shared(int*)) == shared(int))); // FIXME: should not
> match (shared ptr)
> static assert(is(dp!(shared(int)*) == shared(int)));
> 
> template ep(T : const(U*), U) {
>     alias U ep;
> }
> 
> static assert(!is(ep!(shared(int*)))); // no match
> static assert(!is(ep!(shared(int)*))); // no match
> 
> static assert(!is(fp!(shared(int*)))); // no match
> static assert(!is(fp!(shared(int)*))); // no match

Not sure about shared. I believe finalizing shared is still a work in progress.

In any case, if any of these are still pertinent, they need to be filed as separate bugs. Aggregate bugs are not very actionable.

I'll close this as it looks like the situation changed quite a bit in the 6 years since this was posted. Please file any remaining problems you believe are still pertinent today as new issues.