Skip to content
This repository

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP

Issue 1824 - Object not const correct #72

Merged
merged 6 commits into from almost 2 years ago

5 participants

Hara Kenji Daniel Murphy Jonathan M Davis Andrei Alexandrescu Adam Wilson
Hara Kenji
Collaborator

http://d.puremagic.com/issues/show_bug.cgi?id=1824
D-Programming-Language/dmd#387
#72
D-Programming-Language/phobos#262

  1. Change Object.opEquals, opCmp, toHash and toString to const member functions.
  2. Change using TypeInfo objects to const.
Daniel Murphy
Collaborator

You're missing a const in a couple of opApply signatures: http://yebblies.com/results/dmd_387_9rnsr_constApply_druntimebuild.txt

Jonathan M Davis
Collaborator

Personally, I'd argue that all of those consts should go after the functions that they're on. Putting them in front risks confusion, since then it looks like they're marking the return types and not the functions.

Jonathan M Davis
Collaborator

Another thing to consider (though it shouldn't be dealt with in this pull request regardless) is whether some of Object's functions should be pure as well. I'm not sure if we can for sure or not, but their lack of purity could be a problem. If opEquals isn't pure, can objects be compared for equality within a pure function? And not being to use toString in a pure function could be really annoying (though as long as format isn't pure, there's no way that toString could be). To some extent, the problem is solved by the fact that you can override Object's functions with versions with stricter attributes, so as long as you do that and specifically use the derived type, then you should be okay. But if it's actually reasonably to require that functions such as toString be pure, then we should do it. The question though is whether that's reasonable or not. I should probably bring it up in the newsgroup. Regardless, it's not something that should be dealt with in this pull request.

Jonathan M Davis
Collaborator

Another thing, we need to have non-const versions of Object's const functions, so that those who want caching and the like in those functions can have it with non-const objects.

And again, I would strongly argue that const should go after the functions and not before. It's bad enough that it's even legal D to put it in front. It's not something that we should be doing.

Hara Kenji
Collaborator

Hmm, I had not focused so much that ambiguity, but also I can agree to your point.
OK. I'll fix it after a while.

Hara Kenji
Collaborator

Change prefix const to suffix.
And add feature for opEquals migration. See discussion in D-Programming-Language/phobos#262

Hara Kenji
Collaborator

Updated for interface and typedef'ed class/interface comparison for fixing issue 4088.

Andrei Alexandrescu
Owner

rebase? I'll also pull the Phobos request.

Hara Kenji
Collaborator
9rnsr commented April 22, 2012

Rebased.

Jonathan M Davis
Collaborator

According to the pull tester, these changes are currently failing.

Andrei Alexandrescu
Owner

Yah, @9rnsr - this seems to be failing, and is out of sync again. Could you please take a look? I'll be back on this in a week if not earlier. Thanks!

Hara Kenji
Collaborator
9rnsr commented July 08, 2012

OK. Rebased and fixed for git head.

Adam Wilson

@9rnsr, this needs another rebase, we've been doing merges all day and something got changed in object_.d

Hara Kenji
Collaborator
9rnsr commented July 08, 2012

Thanks for the info. Re-rebasing is done.

Andrei Alexandrescu andralex merged commit d39bd49 into from July 08, 2012
Andrei Alexandrescu andralex closed this July 08, 2012
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
This page is out of date. Refresh to see the latest.

Showing 38 changed files with 594 additions and 345 deletions. Show diff stats Hide diff stats

  1. 182  import/object.di
  2. 2  src/core/demangle.d
  3. 6  src/core/runtime.d
  4. 6  src/core/sys/windows/stacktrace.d
  5. 450  src/object_.d
  6. 42  src/rt/lifetime.d
  7. 13  src/rt/typeinfo/ti_AC.d
  8. 7  src/rt/typeinfo/ti_Acdouble.d
  9. 7  src/rt/typeinfo/ti_Acfloat.d
  10. 7  src/rt/typeinfo/ti_Acreal.d
  11. 9  src/rt/typeinfo/ti_Adouble.d
  12. 9  src/rt/typeinfo/ti_Afloat.d
  13. 20  src/rt/typeinfo/ti_Ag.d
  14. 11  src/rt/typeinfo/ti_Aint.d
  15. 9  src/rt/typeinfo/ti_Along.d
  16. 9  src/rt/typeinfo/ti_Areal.d
  17. 11  src/rt/typeinfo/ti_Ashort.d
  18. 7  src/rt/typeinfo/ti_C.d
  19. 2  src/rt/typeinfo/ti_byte.d
  20. 15  src/rt/typeinfo/ti_cdouble.d
  21. 15  src/rt/typeinfo/ti_cfloat.d
  22. 7  src/rt/typeinfo/ti_char.d
  23. 15  src/rt/typeinfo/ti_creal.d
  24. 7  src/rt/typeinfo/ti_dchar.d
  25. 4  src/rt/typeinfo/ti_delegate.d
  26. 12  src/rt/typeinfo/ti_double.d
  27. 10  src/rt/typeinfo/ti_float.d
  28. 2  src/rt/typeinfo/ti_int.d
  29. 4  src/rt/typeinfo/ti_long.d
  30. 4  src/rt/typeinfo/ti_ptr.d
  31. 12  src/rt/typeinfo/ti_real.d
  32. 2  src/rt/typeinfo/ti_short.d
  33. 2  src/rt/typeinfo/ti_ubyte.d
  34. 2  src/rt/typeinfo/ti_uint.d
  35. 4  src/rt/typeinfo/ti_ulong.d
  36. 2  src/rt/typeinfo/ti_ushort.d
  37. 4  src/rt/typeinfo/ti_void.d
  38. 7  src/rt/typeinfo/ti_wchar.d
182  import/object.di
@@ -30,11 +30,11 @@ alias immutable(dchar)[] dstring;
30 30
 
31 31
 class Object
32 32
 {
33  
-    string   toString();
34  
-    hash_t   toHash() @trusted nothrow;
35  
-    int      opCmp(Object o);
36  
-    equals_t opEquals(Object o);
37  
-    equals_t opEquals(Object lhs, Object rhs);
  33
+    string   toString() const;
  34
+    hash_t   toHash() @trusted nothrow const;
  35
+    int      opCmp(const Object o) const;
  36
+    equals_t opEquals(const Object o) const;
  37
+    equals_t opEquals(const Object lhs, const Object rhs) const;
38 38
 
39 39
     interface Monitor
40 40
     {
@@ -45,9 +45,131 @@ class Object
45 45
     static Object factory(string classname);
46 46
 }
47 47
 
48  
-bool opEquals(const Object lhs, const Object rhs);
49  
-bool opEquals(Object lhs, Object rhs);
50  
-//bool opEquals(TypeInfo lhs, TypeInfo rhs);
  48
+bool opEquals(Lhs, Rhs)(Lhs lhs, Rhs rhs)
  49
+    if (is(Lhs == class) && is(Rhs == class))
  50
+{
  51
+    // If aliased to the same object or both null => equal
  52
+    if (lhs is rhs) return true;
  53
+
  54
+    static if (is(Lhs == shared) || is(Rhs == shared))
  55
+    {
  56
+        // If either is shared, is defined only equality comparisons.
  57
+        return false;
  58
+    }
  59
+    else
  60
+    {
  61
+      version (all) // allow direct comparison
  62
+      {
  63
+        // If either is null => non-equal
  64
+        if (lhs is null || rhs is null) return false;
  65
+
  66
+        // If same exact type => one call to method opEquals
  67
+        if (typeid(lhs) is typeid(rhs) || typeid(lhs).opEquals(typeid(rhs)))
  68
+            return lhs.opEquals(rhs);
  69
+
  70
+        // General case => symmetric calls to method opEquals
  71
+        return lhs.opEquals(rhs) && rhs.opEquals(lhs);
  72
+      }
  73
+      else      // always compare with const(Object)
  74
+      {
  75
+        return _ObjectEq(lhs, rhs);
  76
+      }
  77
+    }
  78
+}
  79
+
  80
+bool opEquals(Lhs, Rhs)(Lhs lhs, Rhs rhs)
  81
+    if (is(Lhs == interface) || is(Rhs == interface))
  82
+{
  83
+    // If aliased to the same object or both null => equal
  84
+    static if (is(typeof(lhs is rhs)))
  85
+    {
  86
+        if (lhs is rhs) return true;
  87
+    }
  88
+
  89
+    static if (is(Lhs == shared) || is(Rhs == shared))
  90
+    {
  91
+        // If either is shared, is defined only equality comparisons.
  92
+        return false;
  93
+    }
  94
+    else
  95
+    {
  96
+        // If either is interface, downcast to Object and keep qualifier
  97
+        static if (is(Lhs == interface))
  98
+        {
  99
+            static if (is(Lhs == shared))
  100
+                auto lho = cast(shared const(Object))lhs;
  101
+            else
  102
+                auto lho = cast(const Object)lhs;
  103
+            // If C++ interface, result is null
  104
+        }
  105
+        else
  106
+            alias lhs lho;
  107
+
  108
+        static if (is(Rhs == interface))
  109
+        {
  110
+            static if (is(Rhs == shared))
  111
+                auto rho = cast(shared const(Object))rhs;
  112
+            else
  113
+                auto rho = cast(const Object)rhs;
  114
+        }
  115
+        else
  116
+            alias rhs rho;
  117
+
  118
+        return _ObjectEq(lho, rho);
  119
+    }
  120
+}
  121
+
  122
+deprecated bool opEquals(Lhs, Rhs)(Lhs lhs, Rhs rhs)
  123
+    if (is(Lhs == typedef) || is(Rhs == typedef))
  124
+{
  125
+    static if (is(Lhs LhsB == typedef))
  126
+    {
  127
+        static if (is(Lhs == immutable))
  128
+            alias immutable(LhsB) Lhs2;
  129
+        else static if (is(Lhs == const))
  130
+        {
  131
+            static if (is(Lhs == shared))
  132
+                alias const(shared(LhsB)) Lhs2;
  133
+            else
  134
+                alias const(LhsB) Lhs2;
  135
+        }
  136
+        else
  137
+        {
  138
+            static if (is(Lhs == shared))
  139
+                alias shared(LhsB) Lhs2;
  140
+            else
  141
+                alias LhsB Lhs2;
  142
+        }
  143
+    }
  144
+    else
  145
+        alias Lhs Lhs2;
  146
+
  147
+    static if (is(Rhs RhsB == typedef))
  148
+    {
  149
+        static if (is(Rhs == immutable))
  150
+            alias immutable(RhsB) Rhs2;
  151
+        else static if (is(Rhs == const))
  152
+        {
  153
+            static if (is(Rhs == shared))
  154
+                alias const(shared(RhsB)) Rhs2;
  155
+            else
  156
+                alias const(RhsB) Rhs2;
  157
+        }
  158
+        else
  159
+        {
  160
+            static if (is(Rhs == shared))
  161
+                alias shared(RhsB) Rhs2;
  162
+            else
  163
+                alias RhsB Rhs2;
  164
+        }
  165
+    }
  166
+    else
  167
+        alias Rhs Rhs2;
  168
+
  169
+    return opEquals(cast(Lhs2)lhs, cast(Rhs2)rhs);
  170
+}
  171
+
  172
+private bool _ObjectEq(const Object lhs, const Object rhs);
51 173
 
52 174
 void setSameMutex(shared Object ownee, shared Object owner);
53 175
 
@@ -66,18 +188,18 @@ struct OffsetTypeInfo
66 188
 
67 189
 class TypeInfo
68 190
 {
69  
-    hash_t   getHash(in void* p) @trusted nothrow;
70  
-    equals_t equals(in void* p1, in void* p2);
71  
-    int      compare(in void* p1, in void* p2);
  191
+    hash_t   getHash(in void* p) @trusted nothrow const;
  192
+    equals_t equals(in void* p1, in void* p2) const;
  193
+    int      compare(in void* p1, in void* p2) const;
72 194
     @property size_t   tsize() nothrow pure const @safe;
73  
-    void     swap(void* p1, void* p2);
74  
-    @property TypeInfo next() nothrow pure;
  195
+    void     swap(void* p1, void* p2) const;
  196
+    @property TypeInfo next() nothrow pure const;
75 197
     const(void)[]   init() nothrow pure const @safe; // TODO: make this a property, but may need to be renamed to diambiguate with T.init...
76 198
     @property uint     flags() nothrow pure const @safe;
77 199
     // 1:    // has possible pointers into GC memory
78  
-    OffsetTypeInfo[] offTi();
79  
-    void destroy(void* p);
80  
-    void postblit(void* p);
  200
+    const(OffsetTypeInfo)[] offTi() const;
  201
+    void destroy(void* p) const;
  202
+    void postblit(void* p) const;
81 203
     @property size_t talign() nothrow pure const @safe;
82 204
     version (X86_64) int argTypes(out TypeInfo arg1, out TypeInfo arg2) @safe nothrow;
83 205
     @property immutable(void)* rtInfo() nothrow pure const @safe;
@@ -103,15 +225,15 @@ class TypeInfo_Pointer : TypeInfo
103 225
 class TypeInfo_Array : TypeInfo
104 226
 {
105 227
     override string toString();
106  
-    override equals_t opEquals(Object o);
  228
+    override equals_t opEquals(const Object o);
107 229
     override hash_t getHash(in void* p) @trusted;
108 230
     override equals_t equals(in void* p1, in void* p2);
109 231
     override int compare(in void* p1, in void* p2);
110  
-    @property override size_t tsize() nothrow pure;
  232
+    override @property size_t tsize() nothrow pure;
111 233
     override void swap(void* p1, void* p2);
112  
-    @property override TypeInfo next() nothrow pure;
113  
-    @property override uint flags() nothrow pure;
114  
-    @property override size_t talign() nothrow pure;
  234
+    override @property TypeInfo next() nothrow pure;
  235
+    override @property uint flags() nothrow pure;
  236
+    override @property size_t talign() nothrow pure;
115 237
     version (X86_64) override int argTypes(out TypeInfo arg1, out TypeInfo arg2);
116 238
 
117 239
     TypeInfo value;
@@ -147,8 +269,8 @@ class TypeInfo_Delegate : TypeInfo
147 269
 
148 270
 class TypeInfo_Class : TypeInfo
149 271
 {
150  
-    @property auto info() @safe nothrow pure { return this; }
151  
-    @property auto typeinfo() @safe nothrow pure { return this; }
  272
+    @property auto info() @safe nothrow pure const { return this; }
  273
+    @property auto typeinfo() @safe nothrow pure const { return this; }
152 274
 
153 275
     byte[]      init;   // class static initializer
154 276
     string      name;   // class name
@@ -169,8 +291,8 @@ class TypeInfo_Class : TypeInfo
169 291
     void*       defaultConstructor;
170 292
     immutable(void)*    m_rtInfo;     // data for precise GC
171 293
 
172  
-    static TypeInfo_Class find(in char[] classname);
173  
-    Object create();
  294
+    static const(TypeInfo_Class) find(in char[] classname);
  295
+    Object create() const;
174 296
 }
175 297
 
176 298
 alias TypeInfo_Class ClassInfo;
@@ -239,7 +361,7 @@ class MemberInfo_field : MemberInfo
239 361
 {
240 362
     this(string name, TypeInfo ti, size_t offset);
241 363
 
242  
-    @property override string name() nothrow pure;
  364
+    override @property string name() nothrow pure;
243 365
     @property TypeInfo typeInfo() nothrow pure;
244 366
     @property size_t offset() nothrow pure;
245 367
 }
@@ -255,7 +377,7 @@ class MemberInfo_function : MemberInfo
255 377
 
256 378
     this(string name, TypeInfo ti, void* fp, uint flags);
257 379
 
258  
-    @property override string name() nothrow pure;
  380
+    override @property string name() nothrow pure;
259 381
     @property TypeInfo typeInfo() nothrow pure;
260 382
     @property void* fp() nothrow pure;
261 383
     @property uint flags() nothrow pure;
@@ -316,9 +438,9 @@ class Throwable : Object
316 438
 {
317 439
     interface TraceInfo
318 440
     {
319  
-        int opApply(scope int delegate(ref char[]));
320  
-        int opApply(scope int delegate(ref size_t, ref char[]));
321  
-        string toString();
  441
+        int opApply(scope int delegate(ref const(char[]))) const;
  442
+        int opApply(scope int delegate(ref size_t, ref const(char[]))) const;
  443
+        string toString() const;
322 444
     }
323 445
 
324 446
     string      msg;
2  src/core/demangle.d
@@ -1450,7 +1450,7 @@ private struct Demangle
1450 1450
             {
1451 1451
                 debug(info)
1452 1452
                 {
1453  
-                    auto msg = e.toString;
  1453
+                    auto msg = e.toString();
1454 1454
                     printf( "error: %.*s\n", cast(int) msg.length, msg.ptr );
1455 1455
                 }
1456 1456
                 if( dst.length < buf.length )
6  src/core/runtime.d
@@ -420,15 +420,15 @@ Throwable.TraceInfo defaultTraceHandler( void* ptr = null )
420 420
                 free( framelist );
421 421
             }
422 422
 
423  
-            override int opApply( scope int delegate(ref char[]) dg )
  423
+            override int opApply( scope int delegate(ref const(char[])) dg ) const
424 424
             {
425  
-                return opApply( (ref size_t, ref char[] buf)
  425
+                return opApply( (ref size_t, ref const(char[]) buf)
426 426
                                 {
427 427
                                     return dg( buf );
428 428
                                 } );
429 429
             }
430 430
 
431  
-            override int opApply( scope int delegate(ref size_t, ref char[]) dg )
  431
+            override int opApply( scope int delegate(ref size_t, ref const(char[])) dg ) const
432 432
             {
433 433
                 version( Posix )
434 434
                 {
6  src/core/sys/windows/stacktrace.d
@@ -42,16 +42,16 @@ public:
42 42
     }
43 43
 
44 44
 
45  
-    int opApply( scope int delegate(ref char[]) dg )
  45
+    int opApply( scope int delegate(ref const(char[])) dg ) const
46 46
     {
47  
-        return opApply( (ref size_t, ref char[] buf)
  47
+        return opApply( (ref size_t, ref const(char[]) buf)
48 48
                         {
49 49
                             return dg( buf );
50 50
                         });
51 51
     }
52 52
 
53 53
 
54  
-    int opApply( scope int delegate(ref size_t, ref char[]) dg )
  54
+    int opApply( scope int delegate(ref size_t, ref const(char[])) dg ) const
55 55
     {
56 56
         int result;
57 57
 
450  src/object_.d
@@ -31,9 +31,9 @@ private
31 31
     debug(PRINTF) import core.stdc.stdio;
32 32
 
33 33
     extern (C) void onOutOfMemoryError();
34  
-    extern (C) Object _d_newclass(TypeInfo_Class ci);
35  
-    extern (C) void _d_arrayshrinkfit(TypeInfo ti, void[] arr);
36  
-    extern (C) size_t _d_arraysetcapacity(TypeInfo ti, size_t newcapacity, void *arrptr) pure nothrow;
  34
+    extern (C) Object _d_newclass(const TypeInfo_Class ci);
  35
+    extern (C) void _d_arrayshrinkfit(const TypeInfo ti, void[] arr);
  36
+    extern (C) size_t _d_arraysetcapacity(const TypeInfo ti, size_t newcapacity, void *arrptr) pure nothrow;
37 37
     extern (C) void rt_finalize(void *data, bool det=true);
38 38
 }
39 39
 
@@ -76,7 +76,7 @@ class Object
76 76
     /**
77 77
      * Convert Object to a human readable string.
78 78
      */
79  
-    string toString()
  79
+    string toString() const
80 80
     {
81 81
         return this.classinfo.name;
82 82
     }
@@ -84,7 +84,7 @@ class Object
84 84
     /**
85 85
      * Compute hash function for Object.
86 86
      */
87  
-    hash_t toHash() @trusted nothrow
  87
+    hash_t toHash() @trusted nothrow const
88 88
     {
89 89
         // BUG: this prevents a compacting GC from working, needs to be fixed
90 90
         return cast(hash_t)cast(void*)this;
@@ -99,7 +99,7 @@ class Object
99 99
      *  $(TR $(TD this &gt; obj) $(TD &gt; 0))
100 100
      *  )
101 101
      */
102  
-    int opCmp(Object o)
  102
+    int opCmp(const Object o) const
103 103
     {
104 104
         // BUG: this prevents a compacting GC from working, needs to be fixed
105 105
         //return cast(int)cast(void*)this - cast(int)cast(void*)o;
@@ -111,12 +111,12 @@ class Object
111 111
     /**
112 112
      * Returns !=0 if this object does have the same contents as obj.
113 113
      */
114  
-    equals_t opEquals(Object o)
  114
+    equals_t opEquals(const Object o) const
115 115
     {
116 116
         return this is o;
117 117
     }
118 118
 
119  
-    equals_t opEquals(Object lhs, Object rhs)
  119
+    equals_t opEquals(const Object lhs, const Object rhs) const
120 120
     {
121 121
         if (lhs is rhs)
122 122
             return true;
@@ -155,49 +155,138 @@ class Object
155 155
 /************************
156 156
  * Returns true if lhs and rhs are equal.
157 157
  */
158  
-bool opEquals(const Object lhs, const Object rhs)
  158
+bool opEquals(Lhs, Rhs)(Lhs lhs, Rhs rhs)
  159
+    if (is(Lhs == class) && is(Rhs == class))
159 160
 {
160  
-    // A hack for the moment.
161  
-    return opEquals(cast()lhs, cast()rhs);
  161
+    // If aliased to the same object or both null => equal
  162
+    if (lhs is rhs) return true;
  163
+
  164
+    static if (is(Lhs == shared) || is(Rhs == shared))
  165
+    {
  166
+        // If either is shared, is defined only equality comparisons.
  167
+        return false;
  168
+    }
  169
+    else
  170
+    {
  171
+      version (all) // allow direct comparison
  172
+      {
  173
+        // If either is null => non-equal
  174
+        if (lhs is null || rhs is null) return false;
  175
+
  176
+        // If same exact type => one call to method opEquals
  177
+        if (typeid(lhs) is typeid(rhs) || typeid(lhs).opEquals(typeid(rhs)))
  178
+            return lhs.opEquals(rhs);
  179
+
  180
+        // General case => symmetric calls to method opEquals
  181
+        return lhs.opEquals(rhs) && rhs.opEquals(lhs);
  182
+      }
  183
+      else      // always compare with const(Object)
  184
+      {
  185
+        return _ObjectEq(lhs, rhs);
  186
+      }
  187
+    }
162 188
 }
163 189
 
164  
-bool opEquals(Object lhs, Object rhs)
  190
+bool opEquals(Lhs, Rhs)(Lhs lhs, Rhs rhs)
  191
+    if (is(Lhs == interface) || is(Rhs == interface))
165 192
 {
166 193
     // If aliased to the same object or both null => equal
167  
-    if (lhs is rhs) return true;
  194
+    static if (is(typeof(lhs is rhs)))
  195
+    {
  196
+        if (lhs is rhs) return true;
  197
+    }
168 198
 
169  
-    // If either is null => non-equal
170  
-    if (lhs is null || rhs is null) return false;
  199
+    static if (is(Lhs == shared) || is(Rhs == shared))
  200
+    {
  201
+        // If either is shared, is defined only equality comparisons.
  202
+        return false;
  203
+    }
  204
+    else
  205
+    {
  206
+        // If either is interface, downcast to Object and keep qualifier
  207
+        static if (is(Lhs == interface))
  208
+        {
  209
+            static if (is(Lhs == shared))
  210
+                auto lho = cast(shared const(Object))lhs;
  211
+            else
  212
+                auto lho = cast(const Object)lhs;
  213
+            // If C++ interface, result is null
  214
+        }
  215
+        else
  216
+            alias lhs lho;
171 217
 
172  
-    // If same exact type => one call to method opEquals
173  
-    if (typeid(lhs) is typeid(rhs) || typeid(lhs).opEquals(typeid(rhs)))
174  
-        return lhs.opEquals(rhs);
  218
+        static if (is(Rhs == interface))
  219
+        {
  220
+            static if (is(Rhs == shared))
  221
+                auto rho = cast(shared const(Object))rhs;
  222
+            else
  223
+                auto rho = cast(const Object)rhs;
  224
+        }
  225
+        else
  226
+            alias rhs rho;
175 227
 
176  
-    // General case => symmetric calls to method opEquals
177  
-    return lhs.opEquals(rhs) && rhs.opEquals(lhs);
  228
+        return _ObjectEq(lho, rho);
  229
+    }
178 230
 }
179 231
 
180  
-bool opEquals(TypeInfo lhs, TypeInfo rhs)
  232
+deprecated bool opEquals(Lhs, Rhs)(Lhs lhs, Rhs rhs)
  233
+    if (is(Lhs == typedef) || is(Rhs == typedef))
181 234
 {
182  
-    // If aliased to the same object or both null => equal
183  
-    if (lhs is rhs) return true;
  235
+    static if (is(Lhs LhsB == typedef))
  236
+    {
  237
+        static if (is(Lhs == immutable))
  238
+            alias immutable(LhsB) Lhs2;
  239
+        else static if (is(Lhs == const))
  240
+        {
  241
+            static if (is(Lhs == shared))
  242
+                alias const(shared(LhsB)) Lhs2;
  243
+            else
  244
+                alias const(LhsB) Lhs2;
  245
+        }
  246
+        else
  247
+        {
  248
+            static if (is(Lhs == shared))
  249
+                alias shared(LhsB) Lhs2;
  250
+            else
  251
+                alias LhsB Lhs2;
  252
+        }
  253
+    }
  254
+    else
  255
+        alias Lhs Lhs2;
  256
+
  257
+    static if (is(Rhs RhsB == typedef))
  258
+    {
  259
+        static if (is(Rhs == immutable))
  260
+            alias immutable(RhsB) Rhs2;
  261
+        else static if (is(Rhs == const))
  262
+        {
  263
+            static if (is(Rhs == shared))
  264
+                alias const(shared(RhsB)) Rhs2;
  265
+            else
  266
+                alias const(RhsB) Rhs2;
  267
+        }
  268
+        else
  269
+        {
  270
+            static if (is(Rhs == shared))
  271
+                alias shared(RhsB) Rhs2;
  272
+            else
  273
+                alias RhsB Rhs2;
  274
+        }
  275
+    }
  276
+    else
  277
+        alias Rhs Rhs2;
184 278
 
  279
+    return opEquals(cast(Lhs2)lhs, cast(Rhs2)rhs);
  280
+}
  281
+
  282
+private bool _ObjectEq(const Object lhs, const Object rhs)
  283
+{
185 284
     // If either is null => non-equal
186 285
     if (lhs is null || rhs is null) return false;
187 286
 
188 287
     // If same exact type => one call to method opEquals
189  
-    if (typeid(lhs) == typeid(rhs)) return lhs.opEquals(rhs);
190  
-
191  
-    //printf("%.*s and %.*s, %d %d\n", lhs.toString(), rhs.toString(), lhs.opEquals(rhs), rhs.opEquals(lhs));
192  
-
193  
-    // Factor out top level const
194  
-    // (This still isn't right, should follow same rules as compiler does for type equality.)
195  
-    TypeInfo_Const c = cast(TypeInfo_Const) lhs;
196  
-    if (c)
197  
-        lhs = c.base;
198  
-    c = cast(TypeInfo_Const) rhs;
199  
-    if (c)
200  
-        rhs = c.base;
  288
+    if (typeid(lhs) is typeid(rhs) || typeid(lhs).opEquals(typeid(rhs)))
  289
+        return lhs.opEquals(rhs);
201 290
 
202 291
     // General case => symmetric calls to method opEquals
203 292
     return lhs.opEquals(rhs) && rhs.opEquals(lhs);
@@ -239,7 +328,7 @@ struct OffsetTypeInfo
239 328
  */
240 329
 class TypeInfo
241 330
 {
242  
-    override hash_t toHash() @trusted
  331
+    override hash_t toHash() @trusted const
243 332
     {
244 333
         try
245 334
         {
@@ -255,7 +344,7 @@ class TypeInfo
255 344
         }
256 345
     }
257 346
 
258  
-    override int opCmp(Object o)
  347
+    override int opCmp(const Object o) const
259 348
     {
260 349
         if (this is o)
261 350
             return 0;
@@ -265,7 +354,7 @@ class TypeInfo
265 354
         return dstrcmp(this.toString(), ti.toString());
266 355
     }
267 356
 
268  
-    override equals_t opEquals(Object o)
  357
+    override equals_t opEquals(const Object o) const
269 358
     {
270 359
         /* TypeInfo instances are singletons, but duplicates can exist
271 360
          * across DLL's. Therefore, comparing for a name match is
@@ -273,24 +362,24 @@ class TypeInfo
273 362
          */
274 363
         if (this is o)
275 364
             return true;
276  
-        TypeInfo ti = cast(TypeInfo)o;
  365
+        auto ti = cast(const TypeInfo)o;
277 366
         return ti && this.toString() == ti.toString();
278 367
     }
279 368
 
280 369
     /// Returns a hash of the instance of a type.
281  
-    hash_t getHash(in void* p) @trusted nothrow { return cast(hash_t)p; }
  370
+    hash_t getHash(in void* p) @trusted nothrow const { return cast(hash_t)p; }
282 371
 
283 372
     /// Compares two instances for equality.
284  
-    equals_t equals(in void* p1, in void* p2) { return p1 == p2; }
  373
+    equals_t equals(in void* p1, in void* p2) const { return p1 == p2; }
285 374
 
286 375
     /// Compares two instances for &lt;, ==, or &gt;.
287  
-    int compare(in void* p1, in void* p2) { return 0; }
  376
+    int compare(in void* p1, in void* p2) const { return 0; }
288 377
 
289 378
     /// Returns size of the type.
290 379
     @property size_t tsize() nothrow pure const @safe { return 0; }
291 380
 
292 381
     /// Swaps two instances of the type.
293  
-    void swap(void* p1, void* p2)
  382
+    void swap(void* p1, void* p2) const
294 383
     {
295 384
         size_t n = tsize;
296 385
         for (size_t i = 0; i < n; i++)
@@ -303,7 +392,7 @@ class TypeInfo
303 392
 
304 393
     /// Get TypeInfo for 'next' type, as defined by what kind of type this is,
305 394
     /// null if none.
306  
-    @property TypeInfo next() nothrow pure { return null; }
  395
+    @property const(TypeInfo) next() nothrow pure const { return null; }
307 396
 
308 397
     /// Return default initializer.  If the type should be initialized to all zeros,
309 398
     /// an array with a null ptr and a length equal to the type size will be returned.
@@ -314,11 +403,11 @@ class TypeInfo
314 403
     @property uint flags() nothrow pure const @safe { return 0; }
315 404
 
316 405
     /// Get type information on the contents of the type; null if not available
317  
-    OffsetTypeInfo[] offTi() { return null; }
  406
+    const(OffsetTypeInfo)[] offTi() const { return null; }
318 407
     /// Run the destructor on the object and all its sub-objects
319  
-    void destroy(void* p) {}
  408
+    void destroy(void* p) const {}
320 409
     /// Run the postblit on the object and all its sub-objects
321  
-    void postblit(void* p) {}
  410
+    void postblit(void* p) const {}
322 411
 
323 412
 
324 413
     /// Return alignment of type
@@ -328,7 +417,8 @@ class TypeInfo
328 417
      * See X86-64 ABI 3.2.3
329 418
      */
330 419
     version (X86_64) int argTypes(out TypeInfo arg1, out TypeInfo arg2) @safe nothrow
331  
-    {   arg1 = this;
  420
+    {
  421
+        arg1 = this;
332 422
         return 0;
333 423
     }
334 424
 
@@ -341,25 +431,25 @@ class TypeInfo_Vector : TypeInfo
341 431
 {
342 432
     override string toString() { return "__vector(" ~ base.toString() ~ ")"; }
343 433
 
344  
-    override equals_t opEquals(Object o)
  434
+    override equals_t opEquals(const Object o)
345 435
     {
346  
-        TypeInfo_Vector c;
347  
-        return this is o ||
348  
-               ((c = cast(TypeInfo_Vector)o) !is null &&
349  
-                this.base == c.base);
  436
+        if (this is o)
  437
+            return true;
  438
+        auto c = cast(const TypeInfo_Vector)o;
  439
+        return c && this.base == c.base;
350 440
     }
351 441
 
352 442
     override hash_t getHash(in void* p) { return base.getHash(p); }
353 443
     override equals_t equals(in void* p1, in void* p2) { return base.equals(p1, p2); }
354 444
     override int compare(in void* p1, in void* p2) { return base.compare(p1, p2); }
355  
-    @property override size_t tsize() nothrow pure { return base.tsize; }
  445
+    override @property size_t tsize() nothrow pure { return base.tsize; }
356 446
     override void swap(void* p1, void* p2) { return base.swap(p1, p2); }
357 447
 
358  
-    @property override TypeInfo next() nothrow pure { return base.next; }
359  
-    @property override uint flags() nothrow pure { return base.flags; }
  448
+    override @property const(TypeInfo) next() nothrow pure { return base.next; }
  449
+    override @property uint flags() nothrow pure { return base.flags; }
360 450
     override const(void)[] init() nothrow pure { return base.init(); }
361 451
 
362  
-    @property override size_t talign() nothrow pure { return 16; }
  452
+    override @property size_t talign() nothrow pure { return 16; }
363 453
 
364 454
     version (X86_64) override int argTypes(out TypeInfo arg1, out TypeInfo arg2)
365 455
     {   return base.argTypes(arg1, arg2);
@@ -372,32 +462,33 @@ class TypeInfo_Typedef : TypeInfo
372 462
 {
373 463
     override string toString() { return name; }
374 464
 
375  
-    override equals_t opEquals(Object o)
  465
+    override equals_t opEquals(const Object o)
376 466
     {
377  
-        TypeInfo_Typedef c;
378  
-        return this is o ||
379  
-               ((c = cast(TypeInfo_Typedef)o) !is null &&
380  
-                this.name == c.name &&
381  
-                this.base == c.base);
  467
+        if (this is o)
  468
+            return true;
  469
+        auto c = cast(const TypeInfo_Typedef)o;
  470
+        return c && this.name == c.name &&
  471
+                    this.base == c.base;
382 472
     }
383 473
 
384 474
     override hash_t getHash(in void* p) { return base.getHash(p); }
385 475
     override equals_t equals(in void* p1, in void* p2) { return base.equals(p1, p2); }
386 476
     override int compare(in void* p1, in void* p2) { return base.compare(p1, p2); }
387  
-    @property override size_t tsize() nothrow pure { return base.tsize; }
  477
+    override @property size_t tsize() nothrow pure { return base.tsize; }
388 478
     override void swap(void* p1, void* p2) { return base.swap(p1, p2); }
389 479
 
390  
-    @property override TypeInfo next() nothrow pure { return base.next; }
391  
-    @property override uint flags() nothrow pure { return base.flags; }
  480
+    override @property const(TypeInfo) next() nothrow pure { return base.next; }
  481
+    override @property uint flags() nothrow pure { return base.flags; }
392 482
     override const(void)[] init() nothrow pure const @safe { return m_init.length ? m_init : base.init(); }
393 483
 
394  
-    @property override size_t talign() nothrow pure { return base.talign; }
  484
+    override @property size_t talign() nothrow pure { return base.talign; }
395 485
 
396 486
     version (X86_64) override int argTypes(out TypeInfo arg1, out TypeInfo arg2)
397  
-    {   return base.argTypes(arg1, arg2);
  487
+    {
  488
+        return base.argTypes(arg1, arg2);
398 489
     }
399 490
 
400  
-    @property override immutable(void)* rtInfo() { return base.rtInfo; }
  491
+    override @property immutable(void)* rtInfo() { return base.rtInfo; }
401 492
 
402 493
     TypeInfo base;
403 494
     string   name;
@@ -413,12 +504,12 @@ class TypeInfo_Pointer : TypeInfo
413 504
 {
414 505
     override string toString() { return m_next.toString() ~ "*"; }
415 506
 
416  
-    override equals_t opEquals(Object o)
  507
+    override equals_t opEquals(const Object o)
417 508
     {
418  
-        TypeInfo_Pointer c;
419  
-        return this is o ||
420  
-                ((c = cast(TypeInfo_Pointer)o) !is null &&
421  
-                 this.m_next == c.m_next);
  509
+        if (this is o)
  510
+            return true;
  511
+        auto c = cast(const TypeInfo_Pointer)o;
  512
+        return c && this.m_next == c.m_next;
422 513
     }
423 514
 
424 515
     override hash_t getHash(in void* p) @trusted
@@ -441,7 +532,7 @@ class TypeInfo_Pointer : TypeInfo
441 532
             return 0;
442 533
     }
443 534
 
444  
-    @property override size_t tsize() nothrow pure
  535
+    override @property size_t tsize() nothrow pure
445 536
     {
446 537
         return (void*).sizeof;
447 538
     }
@@ -453,8 +544,8 @@ class TypeInfo_Pointer : TypeInfo
453 544
         *cast(void**)p2 = tmp;
454 545
     }
455 546
 
456  
-    @property override TypeInfo next() nothrow pure { return m_next; }
457  
-    @property override uint flags() nothrow pure { return 1; }
  547
+    override @property const(TypeInfo) next() nothrow pure { return m_next; }
  548
+    override @property uint flags() nothrow pure { return 1; }
458 549
 
459 550
     TypeInfo m_next;
460 551
 }
@@ -463,12 +554,12 @@ class TypeInfo_Array : TypeInfo
463 554
 {
464 555
     override string toString() { return value.toString() ~ "[]"; }
465 556
 
466  
-    override equals_t opEquals(Object o)
  557
+    override equals_t opEquals(const Object o)
467 558
     {
468  
-        TypeInfo_Array c;
469  
-        return this is o ||
470  
-               ((c = cast(TypeInfo_Array)o) !is null &&
471  
-                this.value == c.value);
  559
+        if (this is o)
  560
+            return true;
  561
+        auto c = cast(const TypeInfo_Array)o;
  562
+        return c && this.value == c.value;
472 563
     }
473 564
 
474 565
     override hash_t getHash(in void* p) @trusted
@@ -510,7 +601,7 @@ class TypeInfo_Array : TypeInfo
510 601
         return cast(int)a1.length - cast(int)a2.length;
511 602
     }
512 603
 
513  
-    @property override size_t tsize() nothrow pure
  604
+    override @property size_t tsize() nothrow pure
514 605
     {
515 606
         return (void[]).sizeof;
516 607
     }
@@ -524,20 +615,21 @@ class TypeInfo_Array : TypeInfo
524 615
 
525 616
     TypeInfo value;
526 617
 
527  
-    @property override TypeInfo next() nothrow pure
  618
+    override @property const(TypeInfo) next() nothrow pure
528 619
     {
529 620
         return value;
530 621
     }
531 622
 
532  
-    @property override uint flags() nothrow pure { return 1; }
  623
+    override @property uint flags() nothrow pure { return 1; }
533 624
 
534  
-    @property override size_t talign() nothrow pure
  625
+    override @property size_t talign() nothrow pure
535 626
     {
536 627
         return (void[]).alignof;
537 628
     }
538 629
 
539 630
     version (X86_64) override int argTypes(out TypeInfo arg1, out TypeInfo arg2)
540  
-    {   arg1 = typeid(size_t);
  631
+    {
  632
+        arg1 = typeid(size_t);
541 633
         arg2 = typeid(void*);
542 634
         return 0;
543 635
     }
@@ -551,13 +643,13 @@ class TypeInfo_StaticArray : TypeInfo
551 643
         return cast(string)(value.toString() ~ "[" ~ tmp.intToString(len) ~ "]");
552 644
     }
553 645
 
554  
-    override equals_t opEquals(Object o)
  646
+    override equals_t opEquals(const Object o)
555 647
     {
556  
-        TypeInfo_StaticArray c;
557  
-        return this is o ||
558  
-               ((c = cast(TypeInfo_StaticArray)o) !is null &&
559  
-                this.len == c.len &&
560  
-                this.value == c.value);
  648
+        if (this is o)
  649
+            return true;
  650
+        auto c = cast(const TypeInfo_StaticArray)o;
  651
+        return c && this.len == c.len &&
  652
+                    this.value == c.value;
561 653
     }
562 654
 
563 655
     override hash_t getHash(in void* p) @trusted
@@ -594,7 +686,7 @@ class TypeInfo_StaticArray : TypeInfo
594 686
         return 0;
595 687
     }
596 688
 
597  
-    @property override size_t tsize() nothrow pure
  689
+    override @property size_t tsize() nothrow pure
598 690
     {
599 691
         return len * value.tsize;
600 692
     }
@@ -612,7 +704,8 @@ class TypeInfo_StaticArray : TypeInfo
612 704
             tmp = pbuffer = (new void[sz]).ptr;
613 705
 
614 706
         for (size_t u = 0; u < len; u += sz)
615  
-        {   size_t o = u * sz;
  707
+        {
  708
+            size_t o = u * sz;
616 709
             memcpy(tmp, p1 + o, sz);
617 710
             memcpy(p1 + o, p2 + o, sz);
618 711
             memcpy(p2 + o, tmp, sz);
@@ -622,8 +715,8 @@ class TypeInfo_StaticArray : TypeInfo
622 715
     }
623 716
 
624 717
     override const(void)[] init() nothrow pure { return value.init(); }
625  
-    @property override TypeInfo next() nothrow pure { return value; }
626  
-    @property override uint flags() nothrow pure { return value.flags(); }
  718
+    override @property const(TypeInfo) next() nothrow pure { return value; }
  719
+    override @property uint flags() nothrow pure { return value.flags; }
627 720
 
628 721
     override void destroy(void* p)
629 722
     {
@@ -649,13 +742,14 @@ class TypeInfo_StaticArray : TypeInfo
649 742
     TypeInfo value;
650 743
     size_t   len;
651 744
 
652  
-    @property override size_t talign() nothrow pure
  745
+    override @property size_t talign() nothrow pure
653 746
     {
654 747
         return value.talign;
655 748
     }
656 749
 
657 750
     version (X86_64) override int argTypes(out TypeInfo arg1, out TypeInfo arg2)
658  
-    {   arg1 = typeid(void*);
  751
+    {
  752
+        arg1 = typeid(void*);
659 753
         return 0;
660 754
     }
661 755
 }
@@ -667,37 +761,38 @@ class TypeInfo_AssociativeArray : TypeInfo
667 761
         return cast(string)(next.toString() ~ "[" ~ key.toString() ~ "]");
668 762
     }
669 763
 
670  
-    override equals_t opEquals(Object o)
  764
+    override equals_t opEquals(const Object o)
671 765
     {
672  
-        TypeInfo_AssociativeArray c;
673  
-        return this is o ||
674  
-                ((c = cast(TypeInfo_AssociativeArray)o) !is null &&
675  
-                 this.key == c.key &&
676  
-                 this.value == c.value);
  766
+        if (this is o)
  767
+            return true;
  768
+        auto c = cast(const TypeInfo_AssociativeArray)o;
  769
+        return c && this.key == c.key &&
  770
+                    this.value == c.value;
677 771
     }
678 772
 
679 773
     // BUG: need to add the rest of the functions
680 774
 
681  
-    @property override size_t tsize() nothrow pure
  775
+    override @property size_t tsize() nothrow pure
682 776
     {
683 777
         return (char[int]).sizeof;
684 778
     }
685 779
 
686  
-    @property override TypeInfo next() nothrow pure { return value; }
687  
-    @property override uint flags() nothrow pure { return 1; }
  780
+    override @property const(TypeInfo) next() nothrow pure { return value; }
  781
+    override @property uint flags() nothrow pure { return 1; }
688 782
 
689 783
     TypeInfo value;
690 784
     TypeInfo key;
691 785
 
692 786
     TypeInfo impl;
693 787
 
694  
-    @property override size_t talign() nothrow pure
  788
+    override @property size_t talign() nothrow pure
695 789
     {
696 790
         return (char[int]).alignof;
697 791
     }
698 792
 
699 793
     version (X86_64) override int argTypes(out TypeInfo arg1, out TypeInfo arg2)
700  
-    {   arg1 = typeid(void*);
  794
+    {
  795
+        arg1 = typeid(void*);
701 796
         return 0;
702 797
     }
703 798
 }
@@ -709,17 +804,17 @@ class TypeInfo_Function : TypeInfo
709 804
         return cast(string)(next.toString() ~ "()");
710 805
     }
711 806
 
712  
-    override equals_t opEquals(Object o)
  807
+    override equals_t opEquals(const Object o)
713 808
     {
714  
-        TypeInfo_Function c;
715  
-        return this is o ||
716  
-                ((c = cast(TypeInfo_Function)o) !is null &&
717  
-                 this.deco == c.deco);
  809
+        if (this is o)
  810
+            return true;
  811
+        auto c = cast(const TypeInfo_Function)o;
  812
+        return c && this.deco == c.deco;
718 813
     }
719 814
 
720 815
     // BUG: need to add the rest of the functions
721 816
 
722  
-    @property override size_t tsize() nothrow pure
  817
+    override @property size_t tsize() nothrow pure
723 818
     {
724 819
         return 0;       // no size for functions
725 820
     }
@@ -735,34 +830,35 @@ class TypeInfo_Delegate : TypeInfo
735 830
         return cast(string)(next.toString() ~ " delegate()");
736 831
     }
737 832
 
738  
-    override equals_t opEquals(Object o)
  833
+    override equals_t opEquals(const Object o)
739 834
     {
740  
-        TypeInfo_Delegate c;
741  
-        return this is o ||
742  
-                ((c = cast(TypeInfo_Delegate)o) !is null &&
743  
-                 this.deco == c.deco);
  835
+        if (this is o)
  836
+            return true;
  837
+        auto c = cast(const TypeInfo_Delegate)o;
  838
+        return c && this.deco == c.deco;
744 839
     }
745 840
 
746 841
     // BUG: need to add the rest of the functions
747 842
 
748  
-    @property override size_t tsize() nothrow pure
  843
+    override @property size_t tsize() nothrow pure
749 844
     {
750 845
         alias int delegate() dg;
751 846
         return dg.sizeof;
752 847
     }
753 848
 
754  
-    @property override uint flags() nothrow pure { return 1; }
  849
+    override @property uint flags() nothrow pure { return 1; }
755 850
 
756 851
     TypeInfo next;
757 852
     string deco;
758 853
 
759  
-    @property override size_t talign() nothrow pure
  854
+    override @property size_t talign() nothrow pure
760 855
     {   alias int delegate() dg;
761 856
         return dg.alignof;
762 857
     }
763 858
 
764 859
     version (X86_64) override int argTypes(out TypeInfo arg1, out TypeInfo arg2)
765  
-    {   arg1 = typeid(void*);
  860
+    {
  861
+        arg1 = typeid(void*);
766 862
         arg2 = typeid(void*);
767 863
         return 0;
768 864
     }
@@ -777,17 +873,17 @@ class TypeInfo_Class : TypeInfo
777 873
 {
778 874
     override string toString() { return info.name; }
779 875
 
780  
-    override equals_t opEquals(Object o)
  876
+    override equals_t opEquals(const Object o)
781 877
     {
782  
-        TypeInfo_Class c;
783  
-        return this is o ||
784  
-                ((c = cast(TypeInfo_Class)o) !is null &&
785  
-                 this.info.name == c.info.name);
  878
+        if (this is o)
  879
+            return true;
  880
+        auto c = cast(const TypeInfo_Class)o;
  881
+        return c && this.info.name == c.info.name;
786 882
     }
787 883
 
788 884
     override hash_t getHash(in void* p) @trusted
789 885
     {
790  
-        Object o = *cast(Object*)p;
  886
+        auto o = *cast(const Object*)p;
791 887
         return o ? o.toHash() : 0;
792 888
     }
793 889
 
@@ -821,20 +917,20 @@ class TypeInfo_Class : TypeInfo
821 917
         return c;
822 918
     }
823 919
 
824  
-    @property override size_t tsize() nothrow pure
  920
+    override @property size_t tsize() nothrow pure
825 921
     {
826 922
         return Object.sizeof;
827 923
     }
828 924
 
829  
-    @property override uint flags() nothrow pure { return 1; }
  925
+    override @property uint flags() nothrow pure { return 1; }
830 926
 
831  
-    @property override OffsetTypeInfo[] offTi() nothrow pure
  927
+    override @property const(OffsetTypeInfo)[] offTi() nothrow pure
832 928
     {
833 929
         return m_offTi;
834 930
     }
835 931
 
836  
-    @property auto info() @safe nothrow pure { return this; }
837  
-    @property auto typeinfo() @safe nothrow pure { return this; }
  932
+    @property auto info() @safe nothrow pure const { return this; }
  933
+    @property auto typeinfo() @safe nothrow pure const { return this; }
838 934
 
839 935
     byte[]      init;           /** class static initializer
840 936
                                  * (init.length gives size in bytes of class)
@@ -858,13 +954,13 @@ class TypeInfo_Class : TypeInfo
858 954
     void function(Object) defaultConstructor;   // default Constructor
859 955
 
860 956
     immutable(void)* m_RTInfo;        // data for precise GC
861  
-    @property override immutable(void)* rtInfo() { return m_RTInfo; }
  957
+    override @property immutable(void)* rtInfo() { return m_RTInfo; }
862 958
 
863 959
     /**
864 960
      * Search all modules for TypeInfo_Class corresponding to classname.
865 961
      * Returns: null if not found
866 962
      */
867  
-    static TypeInfo_Class find(in char[] classname)
  963
+    static const(TypeInfo_Class) find(in char[] classname)
868 964
     {
869 965
         foreach (m; ModuleInfo)
870 966
         {
@@ -883,7 +979,7 @@ class TypeInfo_Class : TypeInfo
883 979
     /**
884 980
      * Create instance of Object represented by 'this'.
885 981
      */
886  
-    Object create()
  982
+    Object create() const
887 983
     {
888 984
         if (m_flags & 8 && !defaultConstructor)
889 985
             return null;
@@ -904,12 +1000,12 @@ class TypeInfo_Interface : TypeInfo
904 1000
 {
905 1001
     override string toString() { return info.name; }
906 1002
 
907  
-    override equals_t opEquals(Object o)
  1003
+    override equals_t opEquals(const Object o)
908 1004
     {
909  
-        TypeInfo_Interface c;
910  
-        return this is o ||
911  
-                ((c = cast(TypeInfo_Interface)o) !is null &&
912  
-                 this.info.name == c.classinfo.name);
  1005
+        if (this is o)
  1006
+            return true;
  1007
+        auto c = cast(const TypeInfo_Interface)o;
  1008
+        return c && this.info.name == c.classinfo.name;
913 1009
     }
914 1010
 
915 1011
     override hash_t getHash(in void* p) @trusted
@@ -954,12 +1050,12 @@ class TypeInfo_Interface : TypeInfo
954 1050
         return c;
955 1051
     }
956 1052
 
957  
-    @property override size_t tsize() nothrow pure
  1053
+    override @property size_t tsize() nothrow pure
958 1054
     {
959 1055
         return Object.sizeof;
960 1056
     }
961 1057
 
962  
-    @property override uint flags() nothrow pure { return 1; }
  1058
+    override @property uint flags() nothrow pure { return 1; }
963