Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Issue 6288 - std.conv.to removes const/immutable when converting a class #271

Merged
merged 6 commits into from Sep 22, 2011
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
108 changes: 106 additions & 2 deletions std/conv.d
Expand Up @@ -550,9 +550,45 @@ non-null and the target is null.
*/
T toImpl(T, S)(S value)
if (!isImplicitlyConvertible!(S, T) &&
is(S : Object) && !is(typeof(value.opCast!T()) : T) &&
is(T : Object) && !is(typeof(new T(value))))
(is(S == class) || is(S == interface)) && !is(typeof(value.opCast!T()) : T) &&
(is(T == class) || is(T == interface)) && !is(typeof(new T(value))))
{
static if (is(T == immutable))
{
// immutable <- immutable
enum isModConvertible = is(S == immutable);
}
else static if (is(T == const))
{
static if (is(T == shared))
{
// shared const <- shared
// shared const <- shared const
// shared const <- immutable
enum isModConvertible = is(S == shared) || is(S == immutable);
}
else
{
// const <- mutable
// const <- immutable
enum isModConvertible = !is(S == shared);
}
}
else
{
static if (is(T == shared))
{
// shared <- shared mutable
enum isModConvertible = is(S == shared) && !is(S == const);
}
else
{
// (mutable) <- (mutable)
enum isModConvertible = is(Unqual!S == S);
}
}
static assert(isModConvertible, "Bad modifier conversion: "~S.stringof~" to "~T.stringof);

auto result = cast(T) value;
if (!result && value)
{
Expand All @@ -576,6 +612,74 @@ unittest
assertThrown!ConvException(to!B(a3));
}

// Unittest for 6288
version (unittest)
{
private template Identity(T) { alias T Identity; }
private template toConst(T) { alias const(T) toConst; }
private template toShared(T) { alias shared(T) toShared; }
private template toSharedConst(T) { alias shared(const(T)) toSharedConst; }
private template toImmutable(T) { alias immutable(T) toImmutable; }
private template AddModifier(int n) if (0 <= n && n < 5)
{
static if (n == 0) alias Identity AddModifier;
else static if (n == 1) alias toConst AddModifier;
else static if (n == 2) alias toShared AddModifier;
else static if (n == 3) alias toSharedConst AddModifier;
else static if (n == 4) alias toImmutable AddModifier;
}
}
unittest
{
interface I {}
interface J {}

class A {}
class B : A {}
class C : B, I, J {}
class D : I {}

foreach (m1; TypeTuple!(0,1,2,3,4)) // enumerate modifiers
foreach (m2; TypeTuple!(0,1,2,3,4)) // ditto
{
alias AddModifier!m1 srcmod;
alias AddModifier!m2 tgtmod;
//pragma(msg, srcmod!Object, " -> ", tgtmod!Object, ", convertible = ",
// isImplicitlyConvertible!(srcmod!Object, tgtmod!Object));

// Compile time convertible equals to modifier convertible.
static if (isImplicitlyConvertible!(srcmod!Object, tgtmod!Object))
{
// Test runtime conversions: class to class, class to interface,
// interface to class, and interface to interface

// Check that the runtime conversion to succeed
srcmod!A ac = new srcmod!C();
srcmod!I ic = new srcmod!C();
assert(to!(tgtmod!C)(ac) !is null); // A(c) to C
assert(to!(tgtmod!I)(ac) !is null); // A(c) to I
assert(to!(tgtmod!C)(ic) !is null); // I(c) to C
assert(to!(tgtmod!J)(ic) !is null); // I(c) to J

// Check that the runtime conversion fails
srcmod!A ab = new srcmod!B();
srcmod!I id = new srcmod!D();
assertThrown(to!(tgtmod!C)(ab)); // A(b) to C
assertThrown(to!(tgtmod!I)(ab)); // A(b) to I
assertThrown(to!(tgtmod!C)(id)); // I(d) to C
assertThrown(to!(tgtmod!J)(id)); // I(d) to J
}
else
{
// Check that the conversion is rejected statically
static assert(!is(typeof(to!(tgtmod!C)(srcmod!A.init)))); // A to C
static assert(!is(typeof(to!(tgtmod!I)(srcmod!A.init)))); // A to I
static assert(!is(typeof(to!(tgtmod!C)(srcmod!I.init)))); // I to C
static assert(!is(typeof(to!(tgtmod!J)(srcmod!I.init)))); // I to J
}
}
}

/**
Stringnize conversion from all types is supported.
$(UL
Expand Down