Bug 9361 – Nasty bug and/or error message for template constaints using this
Status
RESOLVED
Resolution
DUPLICATE
Severity
major
Priority
P2
Component
dmd
Product
D
Version
D2
Platform
All
OS
All
Creation time
2013-01-20T14:19:00Z
Last change time
2014-01-24T22:22:54Z
Keywords
ice, pull
Assigned to
nobody
Creator
maidenphil
Comments
Comment #0 by maidenphil — 2013-01-20T14:19:02Z
I tried to make the code as brief as possible:
module rettypeinfer;
import std.stdio;
struct Unit( A ) {
void useMe() {
writeln( isUnit!this );
writeln( is( unitType!this == int ) );
writeln( ( unitType!this ).stringof );
}
void useMoreOfMe( T )( T t ) if( is( atomType!T == unitType!( typeof( this ) ) ) ) {
writeln( "We're ok, but borderline" );
}
void butPleaseDontUseMe( T )( T t ) if( is( atomType!T == unitType!( ( this ) ) ) ) {
writeln( "Look at the error message" );
}
}
template isUnit( alias T ) if( is( T ) ) {
static if( is( T _: Unit!Args, Args... ) ) {
enum isUnit = true;
} else {
enum isUnit = false;
}
}
template isUnit( alias T ) if( !is( T ) ) {
enum isUnit = isUnit!( typeof( T ) );
}
template unitType( alias T ) if( isUnit!T ) {
static if( is( T _: Unit!Args, Args... ) ) {
alias unitType = Args[ 0 ];
} else {
alias unitType = unitType!( typeof( T ) );
}
}
struct Atom( A ) {
}
template isAtom( alias A ) if( is( A ) ) {
static if( is( A _: Atom!Args, Args... ) ) {
enum isAtom = true;
} else {
enum isAtom = false;
}
}
template isAtom( alias A ) if( !is( A ) ) {
enum isAtom = isAtom!( typeof( A ) );
}
template atomType( alias T ) if( isAtom!T ) {
static if( is( T _: Atom!Args, Args... ) ) {
alias atomType = Args[ 0 ];
} else {
alias atomType = atomType!( typeof( T ) );
}
}
void main( string[] args ) {
Unit!int u;
assert( isUnit!u );
assert( isUnit!( typeof( u ) ) );
assert( is( unitType!u == int ) );
assert( is( unitType!( typeof( u ) ) == int ) );
u.useMe();
Atom!int a;
assert( isAtom!a );
assert( isAtom!( typeof( a ) ) );
assert( is( atomType!a == int ) );
assert( is( atomType!( typeof( a ) ) == int ) );
u.useMoreOfMe( a );
//Crashes, with nasty error message.
u.butPleaseDontUseMe( a );
}
Run this and it outputs:
Assertion failure: 'fd && fd->inferRetType' on line 81 in file 'mangle.c'
abnormal program termination
The last function crashes the program. If you replace unitType!this with unitType( typeof( this ) ) the function works properly, as in the previous member declaration.
Comment #1 by k.hara.pg — 2013-01-20T18:33:09Z
Reduced test case:
struct Unit(A)
{
void butPleaseDontUseMe()()
if (is(unitType!((this)))) // !
{}
}
template isUnit(alias T) if ( is(T)) {}
template isUnit(alias T) if (!is(T)) {}
template unitType(alias T) if (isUnit!T) {}
void main()
{
Unit!int u;
u.butPleaseDontUseMe(); // crashes
}
====
I think the instantiation unitType!((this)) in the template constraint for butPleaseDontUseMe template function should always fail, because the 'this' symbol yet not has an actual entity while the constraint evaluation.
That means, the invocation of s.foo() should fail in following.
template Sym(alias A) { enum Sym = true; }
struct S {
void foo()() if (Sym!(this)) {}
// Sym!(this) always make an error, because
// Sym template never be able to access
// valid 'this' symbol.
}
void main() { S s; s.foo(); }
(In reply to comment #1)
> Reduced test case:
>
> struct Unit(A)
> {
> void butPleaseDontUseMe()()
> if (is(unitType!((this)))) // !
> {}
>
> }
> template isUnit(alias T) if ( is(T)) {}
> template isUnit(alias T) if (!is(T)) {}
> template unitType(alias T) if (isUnit!T) {}
> void main()
> {
> Unit!int u;
> u.butPleaseDontUseMe(); // crashes
> }
>
> ====
>
> I think the instantiation unitType!((this)) in the template constraint for
> butPleaseDontUseMe template function should always fail, because the 'this'
> symbol yet not has an actual entity while the constraint evaluation.
>
> That means, the invocation of s.foo() should fail in following.
>
> template Sym(alias A) { enum Sym = true; }
> struct S {
> void foo()() if (Sym!(this)) {}
> // Sym!(this) always make an error, because
> // Sym template never be able to access
> // valid 'this' symbol.
> }
> void main() { S s; s.foo(); }
Yes it makes sense, however the error message is clearly not appropriate!
Something like:
dmd: Error: If you use this in template constraint again I will hate you.
Should do :)
Comment #4 by k.hara.pg — 2013-01-22T19:37:10Z
*** This issue has been marked as a duplicate of issue 6538 ***
Comment #5 by github-bugzilla — 2013-01-22T21:50:19Z