Fabulous Adventures In Coding

Eric Lippert's Blog

JScript .NET Type Coercion Semantics, Part Two: Promotability

Last time I gave some vague, high-level definitions of the type system concepts promotable, assignable and coercible. Today I'll give a more precise definition of promotable. The others I'll define more precisely later.

Suppose we have an assignment of an expression to a typed field.

Left Hand Side Expression = Right Hand Side Expression;

where the compiler can infer the type of the left hand side as LHT and the right hand side as RHT. RHT is promotable to LHT if every member of RHT is coercible to LHT.

There are, as you'll see, some bugs and weirdnesses in JScript .NET's implementation of the promotability algorithm. This describes how it is, not how it should be!

In this list of rules there are some contradictions -- in those cases, earlier rules supercede later rules.

General rules

  • If LHT is the same type as RHT then RHT is trivially promotable to LHT.
  • If LHT is System.Object and RHT is a passed-by-reference type then RHT is not promotable to LHT
  • If LHT is System.Object and RHT is anything other than a passed-by-reference type then RHT is promotable to LHT
  • If LHT is any non-array type and RHT is an array type then RHT is not promotable to LHT.
  • If LHT is any array type then see the algorithm below.
  • If LHT or RHT is an enumerated type then see the algorithm below.
  • If either RHT or LHT is a class/interface then see the algorithm below.
  • If RHT is the (single-member) undefined type or the (single member) null type then RHT is promotable to LHT regardless of what LHT is.
  • If LHT and RHT are both primitive Boolean, numeric or date types (Boolean, 1/2/4/8 byte signed/unsigned integers, 4/8 byte floats, decimal, datetime, timespan), see the algorithm below.
  • If LHT is a JScript object wrapper for Boolean or string and RHT is the corresponding primitive type then RHT is promotable to LHT.
  • If LHT is the JScript object wrapper for number and RHT is promotable to a primitive 8-byte float then RHT is promotable to LHT.
  • If LHT is the primitive Boolean, string or datetime and RHT is the corresponding wrapper type then RHT is promotable to LHT.
  • If LHT is a primitive integer or float and RHT is the wrapper type for number then RHT is promotable to LHT. (This one is an exception, as it is potentially lossy.)
  • If LHT has defined an implicit cast operator from RHT then RHT is promotable to LHT.
  • If RHT has defined an implicit cast operator to LHT then RHT is promotable to LHT.
  • Otherwise, RHT is not promotable to LHT.

Rules for the case where LHT is an array type

  • If LHT is any array type and RHT is not an array type then RHT is not promotable to LHT.
  • If LHT is not a JScript array and RHT is a JScript array then RHT is not promotable to LHT.
  • If LHT is System.Array then RHT is promotable to LHT, regardless of RHT.
  • If LHT is any array type and RHT is System.Array then RHT is not promotable to LHT.
  • If LHT is a JScript array and RHT is any array known to be of rank 1 then RHT is promotable to LHT. Note that this is an exception, as it is potentially lossy or error-prone.
  • If LHT is of known type and rank and RHT is of known type and rank, and furthermore, the ranks are equal and RHT is Element Type Compatible with LHT then RHT is promotable to LHT.
  • Otherwise, RHT is not promotable to LHT.

Rules for the case where LHT or RHT is an enumerated type

  • If LHT and RHT are different enumerated types then RHT is not promotable to LHT.
  • If LHT is an enumerated type and RHT is a primitive numeric type promotable to the underlying numeric type of LHT them RHT is promotable to LHT.
  • If LHT is a primitive numeric type and RHT is an enumerated type whose underlying numeric type is promotable to LHT, then RHT is promotable to LHT.
  • If LHT is an enumerated type and RHT is string then RHT is promotable to LHT.
  • Otherwise, RHT is not promotable to LHT.

Note that the rules for enumerated types are exceptions; clearly there are always strings and numbers which are not coercible to a given enumerated type!

Rules for the case where RHT or LHT is a class/interface

  • If LHT is a superclass of RHT then RHT is promotable to LHT.  
  • If LHT is an interface implemented by RHT then RHT is promotable to LHT.
  • Otherwise, RHT is not promotable to LHT.

Rules for the case where RHT and LHT are both primitive types

  • If RHT is Boolean or unsigned 1-byte integer and LHT is char, any integer, float, decimal, datetime or timespan then RHT is promotable to LHT.
  • If RHT is char or unsigned 2-byte integer and LHT is 2-byte unsigned integer, any 4 or 8 byte integer, float, decimal, datetime or timespan then RHT is promotable to LHT.
  • If RHT is signed 1/2-byte integer and LHT is any signed integer, any float, decimal, datetime or timespan then RHT is promotable to LHT. (This appears to be buggy -- a signed 2-byte integer should not be promotable to a signed 1-byte integer! I'll look into it.)
  • If RHT is signed 4-byte integer and LHT is signed 8-byte integer, 8-byte float, decimal, datetime or timespan then RHT is promotable to LHT.
  • If RHT is unsigned 4-byte integer and LHT is any 8-byte integer, 8-byte float, decimal, datetime or timespan then RHT is promotable to LHT.
  • If RHT is any 8-byte integer and LHT is decimal, datetime or timespan then RHT is promotable to LHT.
  • If RHT is any float and LHT is 8-byte float or decimal then RHT is promotable to LHT.
  • Otherwise, RHT is not promotable to LHT.

Next time, assignability.

Published Wednesday, August 04, 2004 5:49 PM by Eric Lippert

Comment Notification

If you would like to receive an email when updates are made to this post, please register here

Subscribe to this post's comments using RSS

Comments

 

Micah LaCombe said:

I wrote a library in Jscript .Net that generates Excel files using Interop.



I started using c# because I felt it was faster to work with than Jscript.



I am trying to use my old jscript library in c# code so I imported the namespace Microsoft.Jscript so that the old library could be compiled properly.





Inside my Jscript code I use a few non-.net objects like a Jscript Array(). When I try to reference this type from c# it says:



Cannot apply indexing with [] to an expression of type 'object'



But I should be able to use the brackets because its an Array object! … would casting this to a collection help?



-micah
April 13, 2006 11:30 AM
 

Eric Lippert said:

A JScript array is NOT a System.Array object, so you can't use it as one.  In a JScript.NET program you can coerce between JScript arrays and system arrays, but that's a copy-on-cast relationship, not an "is a" relationship.

However, in your C# program, you CAN cast the object to public class Microsoft.Jscript.ArrayObject, which DOES have an indexer.  That should solve your problem.

April 13, 2006 12:51 PM

Leave a Comment

(required) 
(optional)
(required) 

  
Enter Code Here: Required
Submit

About Eric Lippert

Eric Lippert is a senior developer on the Microsoft C# compiler team. Before that he worked on the framework of Visual Studio Tools For Office. Before that, he worked on the compilers, runtimes and tools for VBScript, JScript, Windows Script Host and other Microsoft Scripting technologies. He lives in Seattle and spends his free time editing books about programming languages, playing the piano, and trying to keep his tiny sailboat upright in Puget Sound.

This Blog

Syndication


© 2009 Microsoft Corporation. All rights reserved. Terms of Use  |  Trademarks  |  Privacy Statement
Microsoft
Page view tracker