<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
		<id>https://dev.eiffel.com/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Juliant</id>
		<title>EiffelStudio: an EiffelSoftware project - User contributions [en]</title>
		<link rel="self" type="application/atom+xml" href="https://dev.eiffel.com/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Juliant"/>
		<link rel="alternate" type="text/html" href="https://dev.eiffel.com/Special:Contributions/Juliant"/>
		<updated>2026-04-26T06:12:22Z</updated>
		<subtitle>User contributions</subtitle>
		<generator>MediaWiki 1.24.1</generator>

	<entry>
		<id>https://dev.eiffel.com/index.php?title=Compiling_EiffelStudio&amp;diff=13871</id>
		<title>Compiling EiffelStudio</title>
		<link rel="alternate" type="text/html" href="https://dev.eiffel.com/index.php?title=Compiling_EiffelStudio&amp;diff=13871"/>
				<updated>2010-05-31T15:28:12Z</updated>
		
		<summary type="html">&lt;p&gt;Juliant: Reverted edits by Jacksonsophia (Talk) to last version by Manus&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Category:Compiler]]&lt;br /&gt;
[[Category:EiffelStudio]]&lt;br /&gt;
&lt;br /&gt;
== Installing EiffelStudio ==&lt;br /&gt;
&lt;br /&gt;
To compile EiffelStudio, you need an already working EiffelStudio compiler on your machine. The current source tree '''requires at least version 6.5''' of EiffelStudio. You can download it from http://dev.eiffel.com/Downloads. Read the [http://docs.eiffel.com/eiffelstudio/installation/index.html existing documentation] to install EiffelStudio.&lt;br /&gt;
&lt;br /&gt;
'''Note:''' on Windows you will need the Microsoft C compiler to compile Eiffel Studio. How to install the free version of the Microsoft C compiler: [[Installing Microsoft C compiler]]. It is not possible to compile EiffelStudio with the free Borland compiler.&lt;br /&gt;
&lt;br /&gt;
===Compilation methods===&lt;br /&gt;
Currently there are two compilation methods. &lt;br /&gt;
* You can compile EiffelStudio from scratch following the instructions in this document ('''This is the recommended approach''').&lt;br /&gt;
* You can use one of the [[Automatic Build Scripts]], and if you encounter any errors please report them to the [http://forums.eiffel.com EiffelStudio Development forum].&lt;br /&gt;
&lt;br /&gt;
==Extracting source code==&lt;br /&gt;
&lt;br /&gt;
===Checking out from SVN===&lt;br /&gt;
#Point the environment variables called '''EIFFEL_SRC''' and '''ISE_LIBRARY''' to the directory where you want to compile EiffelStudio.&amp;lt;br&amp;gt;Usually we use the '''XXdev''' convention for this directory name - where XX is the version number of the currently developed version of the compiler.&lt;br /&gt;
#Make sure that '''ISE_EIFFEL''', '''ISE_PLATFORM''' and '''ISE_C_COMPILER''' (on Windows only) are properly defined.&lt;br /&gt;
#Perform the following checkout procedures:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''DOS'''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
set SVNURL=https://svn.eiffel.com/eiffelstudio/trunk&lt;br /&gt;
svn co %SVNURL%/Src 65dev&lt;br /&gt;
svn co %SVNURL%/Delivery 65dev/Delivery&lt;br /&gt;
svn co %SVNURL%/Documentation 65dev/Documentation&lt;br /&gt;
svn co %SVNURL%/free_add_ons 65dev/free_add_ons&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Bash'''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
export SVNURL=https://svn.eiffel.com/eiffelstudio/trunk&lt;br /&gt;
svn co $SVNURL/Src 65dev&lt;br /&gt;
svn co $SVNURL/Delivery 65dev/Delivery&lt;br /&gt;
svn co $SVNURL/Documentation 65dev/Documentation&lt;br /&gt;
svn co $SVNURL/free_add_ons 65dev/free_add_ons&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
To update the source files to the latest revision, perform the following steps:&lt;br /&gt;
&lt;br /&gt;
'''Bash and DOS'''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
cd 65dev&lt;br /&gt;
svn up&lt;br /&gt;
svn up free_add_ons&lt;br /&gt;
svn up Delivery&lt;br /&gt;
svn up Documentation&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Compiling C libraries==&lt;br /&gt;
&lt;br /&gt;
===Compiling run-time on Windows===&lt;br /&gt;
&lt;br /&gt;
'''DOS'''&lt;br /&gt;
&amp;lt;pre&amp;gt;cd %EIFFEL_SRC%/C&lt;br /&gt;
configure [win32|win64] [b|g|m|m6]&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Bash'''&lt;br /&gt;
&amp;lt;pre&amp;gt;cd $EIFFEL_SRC/C&lt;br /&gt;
./configure.bat [win32|win64] [b|g|m|m6]&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The first argument indicated whether you are compiling the run-time for 32 or 64 bits. The second one is to tell which C compiler will be used. For now only `b' (Borland), `g' (MinGW), `m' (Microsoft) and `m6' (for those forced to use Microsoft VC++ 6.0) are officially supported.&lt;br /&gt;
&lt;br /&gt;
On Windows 32 bits to clean up all the generated files '''(including the library files needed by EiffelStudio)''' it suffices to do:&lt;br /&gt;
&lt;br /&gt;
'''DOS'''&lt;br /&gt;
&amp;lt;pre&amp;gt;configure clean&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''Bash'''&lt;br /&gt;
&amp;lt;pre&amp;gt;./configure.bat clean&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Compiling run-time on Unix===&lt;br /&gt;
&lt;br /&gt;
The command is simply:&lt;br /&gt;
&amp;lt;pre&amp;gt;cd $EIFFEL_SRC/C&lt;br /&gt;
./quick_configure&amp;lt;/pre&amp;gt;&lt;br /&gt;
This requires that '''ISE_PLATFORM''' is properly defined. The `quick_configure' script will look for the file CONFIGS/$ISE_PLATFORM and use it to extract the platform specific information to compile the run-time. If not found then an error will be reported.&lt;br /&gt;
&lt;br /&gt;
To clean up the generated files '''including the library files needed by EiffelStudio''':&lt;br /&gt;
&amp;lt;pre&amp;gt;make clobber&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Compiling C code from libraries===&lt;br /&gt;
&lt;br /&gt;
Here is the list of commands to compile all required C libraries on Windows:&lt;br /&gt;
&lt;br /&gt;
'''DOS'''&lt;br /&gt;
&amp;lt;pre&amp;gt;cd %EIFFEL_SRC%\library\net\Clib&lt;br /&gt;
finish_freezing -library&lt;br /&gt;
cd %EIFFEL_SRC%\library\vision2\Clib&lt;br /&gt;
finish_freezing -library&lt;br /&gt;
cd %EIFFEL_SRC%\library\wel\Clib&lt;br /&gt;
finish_freezing -library&lt;br /&gt;
cd %EIFFEL_SRC%\library\cURL\Clib&lt;br /&gt;
finish_freezing -library&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''Bash'''&lt;br /&gt;
&amp;lt;pre&amp;gt;cd $EIFFEL_SRC/library/net/Clib&lt;br /&gt;
finish_freezing -library&lt;br /&gt;
cd $EIFFEL_SRC/library/vision2/Clib&lt;br /&gt;
finish_freezing -library&lt;br /&gt;
cd $EIFFEL_SRC/library/wel/Clib&lt;br /&gt;
finish_freezing -library&lt;br /&gt;
cd %EIFFEL_SRC%/library/cURL/Clib&lt;br /&gt;
finish_freezing -library&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
On Unix it is slightly different:&lt;br /&gt;
&amp;lt;pre&amp;gt;cd $EIFFEL_SRC/library/net/Clib&lt;br /&gt;
finish_freezing -library&lt;br /&gt;
cd $EIFFEL_SRC/library/vision2/Clib&lt;br /&gt;
finish_freezing -library&lt;br /&gt;
cd $EIFFEL_SRC/library/vision2/implementation/gtk/Clib&lt;br /&gt;
finish_freezing -library&lt;br /&gt;
cd $EIFFEL_SRC/library/cURL/Clib&lt;br /&gt;
finish_freezing -library&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Make sure that '''ISE_EIFFEL''' is set correctly to your current &amp;quot;EiffelStudio&amp;quot; installation!&lt;br /&gt;
&lt;br /&gt;
===Compiling C code from C_library===&lt;br /&gt;
&lt;br /&gt;
This is only required on Windows to read PNG file. On Unix, this is not required because it is included in GTK+2.4. So on Windows, simply do the following:&lt;br /&gt;
&lt;br /&gt;
'''DOS'''&lt;br /&gt;
&amp;lt;pre&amp;gt;cd %EIFFEL_SRC%/C_library/zlib&lt;br /&gt;
finish_freezing -library&lt;br /&gt;
cd %EIFFEL_SRC%/C_library/libpng&lt;br /&gt;
finish_freezing -library&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''Bash'''&lt;br /&gt;
&amp;lt;pre&amp;gt;cd $EIFFEL_SRC/C_library/zlib&lt;br /&gt;
finish_freezing -library&lt;br /&gt;
cd $EIFFEL_SRC/C_library/libpng&lt;br /&gt;
finish_freezing -library&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Compiling C code from compiler===&lt;br /&gt;
&lt;br /&gt;
This is only required on Windows as this C code is a tiny wrapper around the Microsoft C++ API to generate and to debug .NET code.&lt;br /&gt;
&lt;br /&gt;
To compile it, you first need to install the Microsoft .NET SDK. You can download it from their website.&lt;br /&gt;
&lt;br /&gt;
After installing it, you need to update your '''LIB''' and '''INCLUDE''' environment variable to include the path the lib and include directory of the .NET Framework SDK.&lt;br /&gt;
&lt;br /&gt;
Once properly installed, you can do:&lt;br /&gt;
&lt;br /&gt;
'''DOS'''&lt;br /&gt;
&amp;lt;pre&amp;gt;cd %EIFFEL_SRC%/framework/cli_writer/Clib&lt;br /&gt;
finish_freezing -library&lt;br /&gt;
cd %EIFFEL_SRC%/framework/cli_debugger/Clib&lt;br /&gt;
finish_freezing -library&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''Bash'''&lt;br /&gt;
&amp;lt;pre&amp;gt;cd $EIFFEL_SRC/framework/cli_writer/Clib&lt;br /&gt;
finish_freezing -library&lt;br /&gt;
cd $EIFFEL_SRC/framework/cli_debugger/Clib&lt;br /&gt;
finish_freezing -library&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Compiling EiffelStudio==&lt;br /&gt;
&lt;br /&gt;
Now that we have taken care of the C code compilation we can compile the compiler. We assume that '''ec''' is in your path.&lt;br /&gt;
&lt;br /&gt;
The configuration file of the compiler contains two active targets:&lt;br /&gt;
* '''batch''': for the command line compiler.&lt;br /&gt;
* '''bench''': for the graphical compiler, aka EiffelStudio.&lt;br /&gt;
&lt;br /&gt;
Go to $EIFFEL_SRC/Eiffel/Ace and type the following command and replace ''target_name'' with either '''batch''' or '''bench'''.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;ec -config ec.ecf -target target_name -c_compile&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Mac OS X specific===&lt;br /&gt;
&lt;br /&gt;
Get a mac binary from [[EiffelOnMac|here]], then follow the instructions for unix.&lt;br /&gt;
&lt;br /&gt;
==Launching the Compiler==&lt;br /&gt;
&lt;br /&gt;
There are two ways of launching the compiler:&lt;br /&gt;
# Command line compiler: add the following arguments '''-config path_to_config_file.ecf'''. This will compile the project represented by `path_to_config_file.ecf'&lt;br /&gt;
# Graphical compiler (aka EiffelStudio): add the following argument '''-gui'''.&lt;/div&gt;</summary>
		<author><name>Juliant</name></author>	</entry>

	<entry>
		<id>https://dev.eiffel.com/index.php?title=Downloads&amp;diff=13870</id>
		<title>Downloads</title>
		<link rel="alternate" type="text/html" href="https://dev.eiffel.com/index.php?title=Downloads&amp;diff=13870"/>
				<updated>2010-05-31T15:25:38Z</updated>
		
		<summary type="html">&lt;p&gt;Juliant: Reverted edits by Jacksonsophia (Talk) to last version by Manus&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Category:EiffelStudio]]&lt;br /&gt;
[[Category:Compiler]]&lt;br /&gt;
==EiffelStudio 6.x Pre-releases==&lt;br /&gt;
We provide versions of EiffelStudio for most popular platforms (Linux, Windows, Solaris, Irix, ...). &lt;br /&gt;
&lt;br /&gt;
You can find the latest builds:&lt;br /&gt;
* from the download page of [http://sourceforge.net/project/showfiles.php?group_id=196408 the sourceforge area]&lt;br /&gt;
* as well as in [ftp://beta:beta57@ftp.eiffel.com the Eiffel Software beta area] (beware it also includes some nightly build which are untested).&lt;br /&gt;
* in [http://eiffelstudio.origo.ethz.ch/download the Origo download area] for the PorterPackage.&lt;br /&gt;
&lt;br /&gt;
Details about new features and bug fixes in the builds are on the [[EiffelStudio_Releases| releases page]].&lt;br /&gt;
&lt;br /&gt;
{{Note|Please be aware that the 6.x versions released through this site are intermediate builds on the road towards official EiffelStudio 6.x. If you are experiencing problems with this release, please use the [http://eiffelstudio.origo.ethz.ch/forum EiffelStudio developer forums] for discussions.}}&lt;br /&gt;
&lt;br /&gt;
The convention used for filenames is the following:&lt;br /&gt;
 Eiffel65_gpl_$BUILD-$ISE_PLATFORM.[tar.bz2|msi]&lt;br /&gt;
Where '''$BUILD''' is a build number, the higher number the more recent release it is, and where '''$ISE_PLATFORM''' is the name of your platform.&lt;br /&gt;
&lt;br /&gt;
Mac OS X builds can be found [[EiffelOnMac|here]].&lt;br /&gt;
&lt;br /&gt;
On Windows, you can use [[Installing_Microsoft_C_compiler|the latest Microsoft C compiler]], but EiffelStudio 6.1 needs [[Installing_Microsoft_C_compiler_6.1_and_older|an older compiler]].&lt;br /&gt;
&lt;br /&gt;
==EiffelStudio 6.x==&lt;br /&gt;
You can download the official EiffelStudio 6.x release from [http://www.eiffel.com/downloads/eiffelstudio.html Eiffel Software]. The GPL release can also be downloaded from [http://sourceforge.net/project/showfiles.php?group_id=196408 http://sflogo.sourceforge.net/sflogo.php?group_id=196408.png].&lt;br /&gt;
&lt;br /&gt;
==Doc Builder==&lt;br /&gt;
You can download the documentation generation tool for Windows 32-bit with .NET 1.1 installed by extracting the content of [http://download.origo.ethz.ch/eiffelstudio/174/doc_builder.zip doc_builder.zip] (or [http://download.origo.ethz.ch/eiffelstudio/174/doc_builder_64-bit.zip doc_builder_64-bit.zip] for the 64-bit version) onto your hard-drive. Once installed, you can launch the tool by launching the '''doc_builder.exe''' executable.&lt;br /&gt;
&lt;br /&gt;
If you have both .NET 1.1 and .NET 2.0 (or greater), you need to force the loading of .NET 1.1. To do so, edit the file '''doc_builder.exe.config''' so that its content looks like:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;xml&amp;gt;&lt;br /&gt;
&amp;lt;configuration&amp;gt; &lt;br /&gt;
	&amp;lt;startup&amp;gt; &lt;br /&gt;
		&amp;lt;requiredRuntime version=&amp;quot;v1.1.4322&amp;quot; safemode=&amp;quot;true&amp;quot;/&amp;gt; &lt;br /&gt;
	&amp;lt;/startup&amp;gt; &lt;br /&gt;
	&amp;lt;runtime&amp;gt; &lt;br /&gt;
		&amp;lt;assemblyBinding xmlns=&amp;quot;urn:schemas-microsoft-com:asm.v1&amp;quot;&amp;gt; &lt;br /&gt;
			&amp;lt;probing privatePath=&amp;quot;Assemblies&amp;quot;/&amp;gt; &lt;br /&gt;
		&amp;lt;/assemblyBinding&amp;gt; &lt;br /&gt;
	&amp;lt;/runtime&amp;gt; &lt;br /&gt;
&amp;lt;/configuration&amp;gt;&lt;br /&gt;
&amp;lt;/xml&amp;gt;&lt;/div&gt;</summary>
		<author><name>Juliant</name></author>	</entry>

	<entry>
		<id>https://dev.eiffel.com/index.php?title=CddBranch&amp;diff=13869</id>
		<title>CddBranch</title>
		<link rel="alternate" type="text/html" href="https://dev.eiffel.com/index.php?title=CddBranch&amp;diff=13869"/>
				<updated>2010-05-31T15:23:45Z</updated>
		
		<summary type="html">&lt;p&gt;Juliant: Reverted edits by Jacksonsophia (Talk) to last version by Aleitner&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Category:Testing]]&lt;br /&gt;
[[Category:EiffelDebugger]]&lt;br /&gt;
[[Category:CDD]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== What is the CDD EiffelStudio? ==&lt;br /&gt;
&lt;br /&gt;
[[Image:cdd_logo.png|center]]&lt;br /&gt;
&amp;lt;center&amp;gt;&lt;br /&gt;
[http://se.ethz.ch/people/leitner/cdd/video/ '''Play CDD Video''', click here]&lt;br /&gt;
&amp;lt;/center&amp;gt;&lt;br /&gt;
CDD (short for Contract Driven Development) is a project developed at [http://se.ethz.ch ETH Zurich]. It adds advanced support for unit testing to EiffelStudio. With CDD EiffelStudio you can&lt;br /&gt;
&lt;br /&gt;
* Write test cases&lt;br /&gt;
* Manage test cases (using tags)&lt;br /&gt;
* Run test cases&lt;br /&gt;
* View test outcomes&lt;br /&gt;
* '''Automatically extract test cases'''&lt;br /&gt;
&lt;br /&gt;
If you have questions, feedback, or would like to report a bug please visit the [http://eiffelstudio.origo.ethz.ch/forum/20 CDD forum]. &lt;br /&gt;
&lt;br /&gt;
CDD EiffelStudio adds the following panel to regular EiffelStudio:&lt;br /&gt;
&lt;br /&gt;
[[Image:cdd_panel.png|center]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Publications ==&lt;br /&gt;
&lt;br /&gt;
Leitner, A., Ciupa, I., Oriol, M., Meyer, B., Fiva, A., &amp;quot;Contract Driven Development = Test Driven Development - Writing Test Cases&amp;quot;, in Proceedings of ESEC/FSE'07: European Software Engineering Conference and the ACM SIGSOFT Symposium on the Foundations of Software Engineering 2007, (Dubrovnik, Croatia), September 2007 [http://se.ethz.ch/people/leitner/publications/cdd_leitner_esec_fse_2007.pdf pdf] [http://se.ethz.ch/people/leitner/publications/ESEC_FSE2007.bib.txt bibtex]&lt;br /&gt;
&lt;br /&gt;
Leitner, A., Pretschner A., Mori S., Meyer B., Oriol M., &amp;quot;On the Effectiveness of Test Extraction without Overhead&amp;quot;, under submission&lt;br /&gt;
&lt;br /&gt;
== News ==&lt;br /&gt;
14.May 2008: Added patch for Windows and Linux that fixes a bug that can cause a crash during extraction.&lt;br /&gt;
&lt;br /&gt;
10.April 2008: If installation exits with cryptic error codes, please have a look at the [[CDD Common Problems|Common Problems]] page.&lt;br /&gt;
&lt;br /&gt;
08.April 2008: CDD EiffelStudio final 7 available&lt;br /&gt;
* Important bug fix: EiffelStudio no longer freezes when opening projects with many test cases&lt;br /&gt;
&lt;br /&gt;
02.April 2008: CDD EiffelStudio Final 6 available&lt;br /&gt;
* Less mess: Redundant or duplicate test cases are no longer extracted&lt;br /&gt;
* Smoother upgrade: Cleaning a project will automatically clean the test suite&lt;br /&gt;
* Fixed bug in invarant checking&lt;br /&gt;
* Fixed bug that caused EiffelStudio to freeze in some situations&lt;br /&gt;
* Improved logging&lt;br /&gt;
* Installer ''might'' work with mingw on Windows now. (Not yet tested, reports welcome)&lt;br /&gt;
&lt;br /&gt;
== Download CDD ==&lt;br /&gt;
&lt;br /&gt;
The following packages contain the full EiffelStudio 6.1 plus the CDD extension. You do not need to have EiffelStudio installed already in order to install below packages. On Windows you do have to have either the Platform SDK or Visual C++ installed. Do not use EiffelStudio with the gcc/mingw or the .Net backend.&lt;br /&gt;
&lt;br /&gt;
=== Linux ===&lt;br /&gt;
* Full Linux version: http://se.ethz.ch/people/leitner/cdd/Eiffel61_cdd_final_7.tar.bz2&lt;br /&gt;
* Full Linux version (for Debian stable): http://se.ethz.ch/people/leitner/cdd/Eiffel61_cdd_final_7_debian_stable.tar.bz2&lt;br /&gt;
* Installation instructions: http://docs.eiffel.com/eiffelstudio/installation/studio/060_linux.html&lt;br /&gt;
Notes:&lt;br /&gt;
* If you are '''upgrading''' from a previous version, make sure you delete the old version first (rm -rf)&lt;br /&gt;
&lt;br /&gt;
Download the above file and install it just like you would install a EiffelStudio tar ball. Afterwards proceed to section &amp;quot;Using CDD&amp;quot;. Make sure you set/update the environment variables PATH, ISE_EIFFEL, and ISE_PLATFORM according to the installation instructions.&lt;br /&gt;
&lt;br /&gt;
=== Linux Patch ===&lt;br /&gt;
* Patch for CDD EiffelStudio Final 7: Download http://se.ethz.ch/people/leitner/cdd/ec and replace it with the '$ISE_EIFFEL/studio/spec/linux-x86/bin/ec' from Final 7. This patch fixes a crash that sometimes occurs during extraction of test cases. You may need to delete the precompile and EIFGENs of your project after applying the patch.&lt;br /&gt;
&lt;br /&gt;
=== Windows ===&lt;br /&gt;
&lt;br /&gt;
* Full Windows version (with installer): http://n.ethz.ch/~moris/download/Eiffel61_cdd_final_7-windows.msi&lt;br /&gt;
Notes:&lt;br /&gt;
* Installation is independent of installations of official EiffelStudio 6.1 (neither overwrites nor invalidates nor is influenced by those) &lt;br /&gt;
* If you are '''upgrading''' from a previous version, you first have to uninstall the old version then delete the existing precompilations (= delete EIFGENs in subdirectories of &amp;lt;INSTALL_DIRECTORY&amp;gt;/precomp/spec/windows/) and then install the new version.&lt;br /&gt;
* Which C compiler to install?&lt;br /&gt;
** Use the Microsoft C compiler either from Visual Studio or the Windows SDK:&lt;br /&gt;
*** Visual Studio (up to Visual Studio 2005, but no later, and only the non-express version)&lt;br /&gt;
*** Windows SDK (up to version 6.0, but no later)&lt;br /&gt;
** Do not use the gcc/mingw.&lt;br /&gt;
** Do not use the .NET compiler backend. &lt;br /&gt;
&lt;br /&gt;
Have a look at http://dev.eiffel.com/Installing_Microsoft_C_compiler_6.1_and_older to learn how to install either Visual C++ or the Windows SDK for use with EiffelStudio. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Windows Patch ====&lt;br /&gt;
&lt;br /&gt;
* Patch for CDD EiffelStudio Final 7: Download http://se.ethz.ch/people/leitner/cdd/ec.exe and replace it with the '$ISE_EIFFEL/studio/spec/windows/bin/ec.exe' from Final 7. This patch fixes a crash that sometimes occurs during extraction of test cases. You may need to delete the precompile and EIFGENs of your project after applying the patch.&lt;br /&gt;
&lt;br /&gt;
== Documentation ==&lt;br /&gt;
&lt;br /&gt;
=== Manually Written Test Cases ===&lt;br /&gt;
CDD Eiffelstudio allows you to create a new “empty” test case. These test cases are similar to jUnit test cases. A manually written test class must start with the word “TEST” and all test routines also have to start with the word “test”. It also has to inherit from class CDD_TEST_CASE.&lt;br /&gt;
&lt;br /&gt;
=== Extracted Test Cases ===&lt;br /&gt;
CDD EiffelStudio automatically extracts test cases whenever you run your program and an exception is triggered. This feature is novel and not yet part of any other testing environment. You will be the first to try it out.&lt;br /&gt;
&lt;br /&gt;
=== Test outcomes ===&lt;br /&gt;
A test case checks whether your program contains a particular bug. A test cases can fail indicating that the bug is present in your program, or pass indicating your program does not contain this bug. Sometimes test cases will be unresolved, in which case the testing framework was unable to find out whether the test case passed or failed. A test case can be unresolved for several reasons.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Image:cdd_buttons.png|center]]&lt;br /&gt;
&lt;br /&gt;
=== Debug Test Case === &lt;br /&gt;
Select a test case and press this button to run a test case in the debugger.&lt;br /&gt;
&lt;br /&gt;
=== Enable/Disable Execution of Test Cases in Background === &lt;br /&gt;
If enabled, all test cases are retested every time you press compile. If disabled no test cases are executed.&lt;br /&gt;
&lt;br /&gt;
=== Enable/Disable automatic extraction of Test Cases === &lt;br /&gt;
If enabled every time an exception is triggered a set of test cases that try to reproduce this exception is extracted. If disabled no test cases are extracted.&lt;br /&gt;
&lt;br /&gt;
=== Clean up/Delete === &lt;br /&gt;
You can use the “Clean Up/Delete” button in two different ways. By simply pressing it you will delete all unresolved test cases. By pick and dropping a test case to the “Clean up/Delete” button (right click on test case, move mouse to button and right click again) you can delete a test case. By the way, test cases are just regular classes. So you can use all existing tools that apply to classes in EiffelStudio too.&lt;br /&gt;
&lt;br /&gt;
Update: To remove duplicate test cases (until the next cdd update), please use the command-line tool from the [http://clean-cdd.origo.ethz.ch/ clean-cdd project].&lt;br /&gt;
&lt;br /&gt;
=== Create new manual test class ===&lt;br /&gt;
Press this button to create a empty test class. You can then edit the class to add manually written test cases. This is how a manually written test case can look like:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;eiffel&amp;gt;&lt;br /&gt;
class TEST_BANK_ACCOUNT&lt;br /&gt;
inherit CDD_TEST_CASE&lt;br /&gt;
feature&lt;br /&gt;
  test_deposit&lt;br /&gt;
    local&lt;br /&gt;
      ba: BANK_ACCOUNT&lt;br /&gt;
    do&lt;br /&gt;
      create ba.make_with_balance (0)&lt;br /&gt;
      ba.deposit (100)&lt;br /&gt;
      check&lt;br /&gt;
         money_depisited: ba.balance = 100&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/eiffel&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Redefine routine `set_up' or `tear_down' if you want something to be executed before resp. after every test routine of a class.&lt;br /&gt;
&lt;br /&gt;
[[Image:cdd_buttons_2.png|center]]&lt;br /&gt;
&lt;br /&gt;
=== Search for tags ===&lt;br /&gt;
Enter keywords to search for paritcular test cases. Some tags are automatically set for you like the name of the test case. You can also easily add your own tags by adding an indexing item &amp;quot;tag&amp;quot; to your test class or routine:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;eiffel&amp;gt;&lt;br /&gt;
indexing&lt;br /&gt;
  tag: &amp;quot;fixme&amp;quot;&lt;br /&gt;
class TEST_BANK_ACCOUNT&lt;br /&gt;
inherit CDD_TEST_CASE&lt;br /&gt;
feature&lt;br /&gt;
   ...&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/eiffel&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Tags can be adde to all test routines and classes. Whether they are extracted or manually written does not matter.&lt;br /&gt;
&lt;br /&gt;
=== Restrict execution of test cases ===&lt;br /&gt;
&lt;br /&gt;
Once you have many test cases, you will run into situation where you don't want to execute all of them. The restrict button will help you to achieve this. As long as the &amp;quot;Restrict&amp;quot; button is pushed test cases that don't show up in the test case view will not be tested. Execution is restricted to those test cases that do show up.&lt;br /&gt;
&lt;br /&gt;
=== Change test case view ===&lt;br /&gt;
&lt;br /&gt;
Select one of several predefined test case views. For example you can group test cases by their outcome to quickly see only failing test cases.&lt;br /&gt;
&lt;br /&gt;
== Further Documentation and Common Problems ==&lt;br /&gt;
Please visit [[Using CDD]] for further documentation or look at &lt;br /&gt;
[[CDD Common Problems|Common Problems]] if you run into problems.&lt;br /&gt;
&lt;br /&gt;
== Related Publications ==&lt;br /&gt;
&lt;br /&gt;
* Sunghun Kim, Shay Artzi, and Michael D. Ernst, &amp;quot;reCrash: Making Crash Reproducible&amp;quot; MIT Computer Science and Artificial Intelligence Laboratory technical report MIT-CSAIL-TR-2007-054, (Cambridge, MA), November 20, 2007. [http://recrash.googlecode.com/files/MIT-CSAIL-TR-2007-054.pdf (pdf)]&lt;br /&gt;
&lt;br /&gt;
== Project Internal Stuff ==&lt;br /&gt;
&lt;br /&gt;
[[CddBranchInternal]]&lt;/div&gt;</summary>
		<author><name>Juliant</name></author>	</entry>

	<entry>
		<id>https://dev.eiffel.com/index.php?title=2010_News&amp;diff=13865</id>
		<title>2010 News</title>
		<link rel="alternate" type="text/html" href="https://dev.eiffel.com/index.php?title=2010_News&amp;diff=13865"/>
				<updated>2010-05-31T09:48:18Z</updated>
		
		<summary type="html">&lt;p&gt;Juliant: fixed typo&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Category:News]]&lt;br /&gt;
All the exciting news of the year 2010.&lt;br /&gt;
&lt;br /&gt;
==May 26th==&lt;br /&gt;
EiffelStudio 6.6 release available&lt;br /&gt;
&lt;br /&gt;
==March 24th==&lt;br /&gt;
Dr. Meyer is the recipient of the 2009 Harlan D. Mills award&lt;/div&gt;</summary>
		<author><name>Juliant</name></author>	</entry>

	<entry>
		<id>https://dev.eiffel.com/index.php?title=Talk:Single-level_call_rule_and_generics&amp;diff=9019</id>
		<title>Talk:Single-level call rule and generics</title>
		<link rel="alternate" type="text/html" href="https://dev.eiffel.com/index.php?title=Talk:Single-level_call_rule_and_generics&amp;diff=9019"/>
				<updated>2007-07-15T17:16:04Z</updated>
		
		<summary type="html">&lt;p&gt;Juliant: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Look very close to my suggestion, only that I had suggested to reuse the keyword 'invariant' instead of introducing a new keyword 'monomorphic', that not average developer will understand --[[User:Schoelle|Schoelle]] 14:02, 15 July 2007 (CEST)&lt;br /&gt;
&lt;br /&gt;
'''--[[User:Juliant|Juliant]] 19:16, 15 July 2007 (CEST)''' This is a different problem. Your proposal about invariant generics is about ''conformance'' between generic parameters, i.e. conformance between &amp;lt;e&amp;gt;X [A]&amp;lt;/e&amp;gt; and &amp;lt;e&amp;gt;X [B]&amp;lt;/e&amp;gt;. What I'm trying to point out is the ''use'' of features on a formal generic parameter which are covariantly redefined. The possible solution for ''like Current'' features with the monomorphic keyword is about the instantation of the generic. A monomorphic generic can only be instantiated with a monomorphic type.&lt;br /&gt;
&lt;br /&gt;
You can also look at it that way: With your ''invariant'' generic, you can use the generic as a feature argument. With a ''monomorph'' generic, you can call covariant features which have ''like Current'' in the argument.&lt;/div&gt;</summary>
		<author><name>Juliant</name></author>	</entry>

	<entry>
		<id>https://dev.eiffel.com/index.php?title=Single-level_call_rule_and_generics&amp;diff=9015</id>
		<title>Single-level call rule and generics</title>
		<link rel="alternate" type="text/html" href="https://dev.eiffel.com/index.php?title=Single-level_call_rule_and_generics&amp;diff=9015"/>
				<updated>2007-07-14T18:58:07Z</updated>
		
		<summary type="html">&lt;p&gt;Juliant: /* Monomorph formal generics */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Category:ECMA]]&lt;br /&gt;
[[Category:Catcall]]&lt;br /&gt;
== Problem ==&lt;br /&gt;
&lt;br /&gt;
The single-level call rule says that every call has to be valid for all possible dynamic types of an entity. So for a formal generic &amp;lt;e&amp;gt;G&amp;lt;/e&amp;gt; this means that the call has to be valid for all possible descendants of the constraint (or at least for every instantiation which happens in a system).&lt;br /&gt;
&lt;br /&gt;
Let's look at an example using &amp;lt;e&amp;gt;NUMERIC&amp;lt;/e&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;e&amp;gt;&lt;br /&gt;
class X [G -&amp;gt; NUMERIC]&lt;br /&gt;
&lt;br /&gt;
feature&lt;br /&gt;
&lt;br /&gt;
  f (g1, g2: G): G&lt;br /&gt;
    do&lt;br /&gt;
      Result := g1 + g2&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/e&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Here, the call to &amp;lt;e&amp;gt;+&amp;lt;/e&amp;gt; has to be valid for all possible descendants of &amp;lt;e&amp;gt;NUMERIC&amp;lt;/e&amp;gt;. Since the signature of the feature is &amp;lt;e&amp;gt;like Current&amp;lt;/e&amp;gt;, the call is never valid. This has to be the case as otherwise, the following code would produce a catcall:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;e&amp;gt;&lt;br /&gt;
x: X [NUMERIC]&lt;br /&gt;
x.f (1, 1.0)&lt;br /&gt;
&amp;lt;/e&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The problem is that the formal generic &amp;lt;e&amp;gt;G&amp;lt;/e&amp;gt; is always assumed to be of any type which satisfies the constraint, so normally the formal generic is polymorph.&lt;br /&gt;
&lt;br /&gt;
As the above example show, the use of features on formal generic parameters which are covariantly redefined is severely limited. But as the purpose of &amp;lt;e&amp;gt;NUMERIC&amp;lt;/e&amp;gt; is exactly to allow creation of generic algorithms over numeric types, this has to be addressed (Note that also &amp;lt;e&amp;gt;COMPARABLE&amp;lt;/e&amp;gt; is a problem).&lt;br /&gt;
&lt;br /&gt;
== Possible solutions ==&lt;br /&gt;
&lt;br /&gt;
=== Monomorph formal generics ===&lt;br /&gt;
&lt;br /&gt;
The first idea is to be able to mark a formal generic as monomorph:&lt;br /&gt;
&amp;lt;e&amp;gt;&lt;br /&gt;
class X [monomorph G -&amp;gt; NUMERIC]&lt;br /&gt;
&lt;br /&gt;
  f (g1, g2: G): G&lt;br /&gt;
    do&lt;br /&gt;
      Result := g1 + g2&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/e&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The generic class can then only be instantiated with monomorphic types, i.e. using [[interval types]] &amp;lt;e&amp;gt;X [INTEGER..INTEGER]&amp;lt;/e&amp;gt; or &amp;lt;e&amp;gt;X [REAL..REAL]&amp;lt;/e&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
For the check we can now assume that &amp;lt;e&amp;gt;G&amp;lt;/e&amp;gt; will be monomorphic. This helps a little bit further: For every feature argument which is &amp;lt;e&amp;gt;like Current&amp;lt;/e&amp;gt; we can assume that the exact type will be given. But this works only for covariant features which have &amp;lt;e&amp;gt;like Current&amp;lt;/e&amp;gt; arguments which are never redefined into something else. Take the following classes for an example:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;e&amp;gt;&lt;br /&gt;
class A&lt;br /&gt;
feature&lt;br /&gt;
  f (a: like Current) do end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
class B&lt;br /&gt;
inherit A&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
class C&lt;br /&gt;
inherit A redefine f&lt;br /&gt;
feature&lt;br /&gt;
  f (a: D) do end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
class D&lt;br /&gt;
inherit C&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/e&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Now assume the following generic class:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;e&amp;gt;&lt;br /&gt;
class X [monomorph G -&amp;gt; A]&lt;br /&gt;
feature&lt;br /&gt;
  f&lt;br /&gt;
    local&lt;br /&gt;
      g1, g2: G&lt;br /&gt;
    do&lt;br /&gt;
      g1.f (g2)&lt;br /&gt;
    end&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/e&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The call to &amp;lt;e&amp;gt;g1.f&amp;lt;/e&amp;gt; is not valid since &amp;lt;e&amp;gt;G&amp;lt;/e&amp;gt; could be of type &amp;lt;e&amp;gt;C&amp;lt;/e&amp;gt;, and then the argument has to be of type &amp;lt;e&amp;gt;D&amp;lt;/e&amp;gt;. So now, not even the &amp;lt;e&amp;gt;like Current&amp;lt;/e&amp;gt; feature is callable with monomorphic generics. Basically it is the same as the declaration without ''monomorphic'' for the generic.&lt;br /&gt;
&lt;br /&gt;
So this solution works only for the case of &amp;lt;e&amp;gt;like Current&amp;lt;/e&amp;gt; features never change the signature. Only then it can be guaranteed for a monomorphic generic formal, that the signature will match the formal generic exactly. Other covariant features have still to be valid for all possible descendants.&lt;br /&gt;
&lt;br /&gt;
For the case of &amp;lt;e&amp;gt;NUMERIC&amp;lt;/e&amp;gt; and &amp;lt;e&amp;gt;COMPARABLE&amp;lt;/e&amp;gt; the use of monomorphic formal arguments would work as they define only &amp;lt;e&amp;gt;like Current&amp;lt;/e&amp;gt; features which are normally kept that way in subclasses. A more general mechanism would be nice but at the moment it is unclear how such a mechanism should look like.&lt;br /&gt;
&lt;br /&gt;
=== Remodeling library ===&lt;br /&gt;
&lt;br /&gt;
Another way to solve the problem of &amp;lt;e&amp;gt;NUMERIC&amp;lt;/e&amp;gt; and &amp;lt;e&amp;gt;COMPARABLE&amp;lt;/e&amp;gt; would be to change the library. As these classes have mostly &amp;lt;e&amp;gt;like Current&amp;lt;/e&amp;gt; arguments and result types, they can be modeled via generics in the first place.&lt;br /&gt;
&lt;br /&gt;
For example:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;e&amp;gt;&lt;br /&gt;
class NUMERIC [G -&amp;gt; NUMERIC [G]]&lt;br /&gt;
feature&lt;br /&gt;
  infix &amp;quot;+&amp;quot; (other: G): G&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
class COMPARABLE [G -&amp;gt; COMPARABLE [G]]&lt;br /&gt;
feature&lt;br /&gt;
  less_than (other: G): BOOLEAN&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/e&amp;gt;&lt;br /&gt;
&lt;br /&gt;
With this approach, the use of the general class &amp;lt;e&amp;gt;NUMERIC&amp;lt;/e&amp;gt; and &amp;lt;e&amp;gt;COMPARABLE&amp;lt;/e&amp;gt; will become more complicated, but since they appear in libraries most of the time it could be done.&lt;/div&gt;</summary>
		<author><name>Juliant</name></author>	</entry>

	<entry>
		<id>https://dev.eiffel.com/index.php?title=Single-level_call_rule_and_generics&amp;diff=9014</id>
		<title>Single-level call rule and generics</title>
		<link rel="alternate" type="text/html" href="https://dev.eiffel.com/index.php?title=Single-level_call_rule_and_generics&amp;diff=9014"/>
				<updated>2007-07-14T18:32:06Z</updated>
		
		<summary type="html">&lt;p&gt;Juliant: /* Monomorph formal generics */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Category:ECMA]]&lt;br /&gt;
[[Category:Catcall]]&lt;br /&gt;
== Problem ==&lt;br /&gt;
&lt;br /&gt;
The single-level call rule says that every call has to be valid for all possible dynamic types of an entity. So for a formal generic &amp;lt;e&amp;gt;G&amp;lt;/e&amp;gt; this means that the call has to be valid for all possible descendants of the constraint (or at least for every instantiation which happens in a system).&lt;br /&gt;
&lt;br /&gt;
Let's look at an example using &amp;lt;e&amp;gt;NUMERIC&amp;lt;/e&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;e&amp;gt;&lt;br /&gt;
class X [G -&amp;gt; NUMERIC]&lt;br /&gt;
&lt;br /&gt;
feature&lt;br /&gt;
&lt;br /&gt;
  f (g1, g2: G): G&lt;br /&gt;
    do&lt;br /&gt;
      Result := g1 + g2&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/e&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Here, the call to &amp;lt;e&amp;gt;+&amp;lt;/e&amp;gt; has to be valid for all possible descendants of &amp;lt;e&amp;gt;NUMERIC&amp;lt;/e&amp;gt;. Since the signature of the feature is &amp;lt;e&amp;gt;like Current&amp;lt;/e&amp;gt;, the call is never valid. This has to be the case as otherwise, the following code would produce a catcall:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;e&amp;gt;&lt;br /&gt;
x: X [NUMERIC]&lt;br /&gt;
x.f (1, 1.0)&lt;br /&gt;
&amp;lt;/e&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The problem is that the formal generic &amp;lt;e&amp;gt;G&amp;lt;/e&amp;gt; is always assumed to be of any type which satisfies the constraint, so normally the formal generic is polymorph.&lt;br /&gt;
&lt;br /&gt;
As the above example show, the use of features on formal generic parameters which are covariantly redefined is severely limited. But as the purpose of &amp;lt;e&amp;gt;NUMERIC&amp;lt;/e&amp;gt; is exactly to allow creation of generic algorithms over numeric types, this has to be addressed (Note that also &amp;lt;e&amp;gt;COMPARABLE&amp;lt;/e&amp;gt; is a problem).&lt;br /&gt;
&lt;br /&gt;
== Possible solutions ==&lt;br /&gt;
&lt;br /&gt;
=== Monomorph formal generics ===&lt;br /&gt;
&lt;br /&gt;
The first idea is to be able to mark a formal generic as monomorph:&lt;br /&gt;
&amp;lt;e&amp;gt;&lt;br /&gt;
class X [monomorph G -&amp;gt; NUMERIC]&lt;br /&gt;
&lt;br /&gt;
  f (g1, g2: G): G&lt;br /&gt;
    do&lt;br /&gt;
      Result := g1 + g2&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/e&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The generic class can then only be instantiated with monomorphic types, i.e. using [[interval types]] &amp;lt;e&amp;gt;X [INTEGER..INTEGER]&amp;lt;/e&amp;gt; or &amp;lt;e&amp;gt;X [REAL..REAL]&amp;lt;/e&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
For the check we can now assume that &amp;lt;e&amp;gt;G&amp;lt;/e&amp;gt; will be monomorphic. This helps a little bit further: For every feature argument which is &amp;lt;e&amp;gt;like Current&amp;lt;/e&amp;gt; we can assume that the exact type will be given. But this works only for covariant features which have &amp;lt;e&amp;gt;like Current&amp;lt;/e&amp;gt; arguments which are never redefined into something else. Take the following classes for an example:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;e&amp;gt;&lt;br /&gt;
class A&lt;br /&gt;
feature&lt;br /&gt;
  f (a: like Current) do end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
class B&lt;br /&gt;
inherit A&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
class C&lt;br /&gt;
inherit A redefine f&lt;br /&gt;
feature&lt;br /&gt;
  f (a: D) do end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
class D&lt;br /&gt;
inherit C&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/e&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Now assume the following generic class:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;e&amp;gt;&lt;br /&gt;
class X [monomorph G -&amp;gt; A]&lt;br /&gt;
feature&lt;br /&gt;
  f&lt;br /&gt;
    local&lt;br /&gt;
      g1, g2: G&lt;br /&gt;
    do&lt;br /&gt;
      g1.f (g2)&lt;br /&gt;
    end&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/e&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The call to &amp;lt;e&amp;gt;g1.f&amp;lt;/e&amp;gt; is not valid since &amp;lt;e&amp;gt;G&amp;lt;/e&amp;gt; could be of type &amp;lt;e&amp;gt;C&amp;lt;/e&amp;gt;, and then the argument has to be of type &amp;lt;e&amp;gt;D&amp;lt;/e&amp;gt;. So now, not even the &amp;lt;e&amp;gt;like Current&amp;lt;/e&amp;gt; feature is callable with monomorphic generics. Basically it is the same as the declaration without ''monomorphic'' for the generic.&lt;br /&gt;
&lt;br /&gt;
So this solution works only for the case of &amp;lt;e&amp;gt;like Current&amp;lt;/e&amp;gt; features which are never redefined. Only then it can be guaranteed for a monomorphic generic formal, that the signature will match the formal generic exactly. Other covariant features have still to be valid for all possible descendants.&lt;br /&gt;
&lt;br /&gt;
For the case of &amp;lt;e&amp;gt;NUMERIC&amp;lt;/e&amp;gt; and &amp;lt;e&amp;gt;COMPARABLE&amp;lt;/e&amp;gt; the use of monomorphic formal arguments would work as they define only &amp;lt;e&amp;gt;like Current&amp;lt;/e&amp;gt; features which are normally kept that way in subclasses. A more general mechanism would be nice but at the moment it is unclear how such a mechanism should look like.&lt;br /&gt;
&lt;br /&gt;
=== Remodeling library ===&lt;br /&gt;
&lt;br /&gt;
Another way to solve the problem of &amp;lt;e&amp;gt;NUMERIC&amp;lt;/e&amp;gt; and &amp;lt;e&amp;gt;COMPARABLE&amp;lt;/e&amp;gt; would be to change the library. As these classes have mostly &amp;lt;e&amp;gt;like Current&amp;lt;/e&amp;gt; arguments and result types, they can be modeled via generics in the first place.&lt;br /&gt;
&lt;br /&gt;
For example:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;e&amp;gt;&lt;br /&gt;
class NUMERIC [G -&amp;gt; NUMERIC [G]]&lt;br /&gt;
feature&lt;br /&gt;
  infix &amp;quot;+&amp;quot; (other: G): G&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
class COMPARABLE [G -&amp;gt; COMPARABLE [G]]&lt;br /&gt;
feature&lt;br /&gt;
  less_than (other: G): BOOLEAN&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/e&amp;gt;&lt;br /&gt;
&lt;br /&gt;
With this approach, the use of the general class &amp;lt;e&amp;gt;NUMERIC&amp;lt;/e&amp;gt; and &amp;lt;e&amp;gt;COMPARABLE&amp;lt;/e&amp;gt; will become more complicated, but since they appear in libraries most of the time it could be done.&lt;/div&gt;</summary>
		<author><name>Juliant</name></author>	</entry>

	<entry>
		<id>https://dev.eiffel.com/index.php?title=Single-level_call_rule_and_generics&amp;diff=9012</id>
		<title>Single-level call rule and generics</title>
		<link rel="alternate" type="text/html" href="https://dev.eiffel.com/index.php?title=Single-level_call_rule_and_generics&amp;diff=9012"/>
				<updated>2007-07-14T01:01:23Z</updated>
		
		<summary type="html">&lt;p&gt;Juliant: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Category:ECMA]]&lt;br /&gt;
[[Category:Catcall]]&lt;br /&gt;
== Problem ==&lt;br /&gt;
&lt;br /&gt;
The single-level call rule says that every call has to be valid for all possible dynamic types of an entity. So for a formal generic &amp;lt;e&amp;gt;G&amp;lt;/e&amp;gt; this means that the call has to be valid for all possible descendants of the constraint (or at least for every instantiation which happens in a system).&lt;br /&gt;
&lt;br /&gt;
Let's look at an example using &amp;lt;e&amp;gt;NUMERIC&amp;lt;/e&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;e&amp;gt;&lt;br /&gt;
class X [G -&amp;gt; NUMERIC]&lt;br /&gt;
&lt;br /&gt;
feature&lt;br /&gt;
&lt;br /&gt;
  f (g1, g2: G): G&lt;br /&gt;
    do&lt;br /&gt;
      Result := g1 + g2&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/e&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Here, the call to &amp;lt;e&amp;gt;+&amp;lt;/e&amp;gt; has to be valid for all possible descendants of &amp;lt;e&amp;gt;NUMERIC&amp;lt;/e&amp;gt;. Since the signature of the feature is &amp;lt;e&amp;gt;like Current&amp;lt;/e&amp;gt;, the call is never valid. This has to be the case as otherwise, the following code would produce a catcall:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;e&amp;gt;&lt;br /&gt;
x: X [NUMERIC]&lt;br /&gt;
x.f (1, 1.0)&lt;br /&gt;
&amp;lt;/e&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The problem is that the formal generic &amp;lt;e&amp;gt;G&amp;lt;/e&amp;gt; is always assumed to be of any type which satisfies the constraint, so normally the formal generic is polymorph.&lt;br /&gt;
&lt;br /&gt;
As the above example show, the use of features on formal generic parameters which are covariantly redefined is severely limited. But as the purpose of &amp;lt;e&amp;gt;NUMERIC&amp;lt;/e&amp;gt; is exactly to allow creation of generic algorithms over numeric types, this has to be addressed (Note that also &amp;lt;e&amp;gt;COMPARABLE&amp;lt;/e&amp;gt; is a problem).&lt;br /&gt;
&lt;br /&gt;
== Possible solutions ==&lt;br /&gt;
&lt;br /&gt;
=== Monomorph formal generics ===&lt;br /&gt;
&lt;br /&gt;
The first idea is to be able to mark a formal generic as monomorph:&lt;br /&gt;
&amp;lt;e&amp;gt;&lt;br /&gt;
class X [monomorph G -&amp;gt; NUMERIC]&lt;br /&gt;
&lt;br /&gt;
  f (g1, g2: G): G&lt;br /&gt;
    do&lt;br /&gt;
      Result := g1 + g2&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/e&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The generic class can then only be instantiated with monomorphic types, i.e. using [[interval types]] &amp;lt;e&amp;gt;X [INTEGER..INTEGER]&amp;lt;/e&amp;gt; or &amp;lt;e&amp;gt;X [REAL..REAL]&amp;lt;/e&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
For the check we can now assume that &amp;lt;e&amp;gt;G&amp;lt;/e&amp;gt; will be monomorphic. This helps a little bit further: For every feature argument which is &amp;lt;e&amp;gt;like Current&amp;lt;/e&amp;gt; we can assume that the exact type will be given. But this works only for covariant features which have &amp;lt;e&amp;gt;like Current&amp;lt;/e&amp;gt; arguments which are never redefined into something else. Take the following classes for an example:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;e&amp;gt;&lt;br /&gt;
class A&lt;br /&gt;
feature&lt;br /&gt;
  f (a: like Current) do end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
class B&lt;br /&gt;
inherit A&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
class C&lt;br /&gt;
inherit A redefine f&lt;br /&gt;
feature&lt;br /&gt;
  f (a: D) do end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
class D&lt;br /&gt;
inherit C&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/e&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Now assume the following generic class:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;e&amp;gt;&lt;br /&gt;
class X [monomorph G -&amp;gt; A]&lt;br /&gt;
feature&lt;br /&gt;
  f&lt;br /&gt;
    local&lt;br /&gt;
      g1, g2: G&lt;br /&gt;
    do&lt;br /&gt;
      g1.f (g2)&lt;br /&gt;
    end&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/e&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The call to &amp;lt;e&amp;gt;g1.f&amp;lt;/e&amp;gt; is not valid since &amp;lt;e&amp;gt;G&amp;lt;/e&amp;gt; could be of type &amp;lt;e&amp;gt;C&amp;lt;/e&amp;gt;, and then the argument has to be of type &amp;lt;e&amp;gt;D&amp;lt;/e&amp;gt;. So now, not even the &amp;lt;e&amp;gt;like Current&amp;lt;/e&amp;gt; feature is callable with monomorphic generics. Basically it is the same as the declaration without ''monomorphic'' for the generic.&lt;br /&gt;
&lt;br /&gt;
So this solution works only for the case of &amp;lt;e&amp;gt;like Current&amp;lt;/e&amp;gt; features which are never redefined. Only then it can be guaranteed for a monomorphic generic formal, that the signature will match the formal generic exactly. Other covariant features have still to be valid for all possible descendants.&lt;br /&gt;
&lt;br /&gt;
For the case of &amp;lt;e&amp;gt;NUMERIC&amp;lt;/e&amp;gt; and &amp;lt;e&amp;gt;COMPARABLE&amp;lt;/e&amp;gt; the use of monomorphic formal arguments would work as they define only &amp;lt;e&amp;gt;like Current&amp;lt;/e&amp;gt; features which are normally not redefined in subclasses. A more general mechanism would be nice but at the moment it is unclear how such a mechanism should look like.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Remodeling library ===&lt;br /&gt;
&lt;br /&gt;
Another way to solve the problem of &amp;lt;e&amp;gt;NUMERIC&amp;lt;/e&amp;gt; and &amp;lt;e&amp;gt;COMPARABLE&amp;lt;/e&amp;gt; would be to change the library. As these classes have mostly &amp;lt;e&amp;gt;like Current&amp;lt;/e&amp;gt; arguments and result types, they can be modeled via generics in the first place.&lt;br /&gt;
&lt;br /&gt;
For example:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;e&amp;gt;&lt;br /&gt;
class NUMERIC [G -&amp;gt; NUMERIC [G]]&lt;br /&gt;
feature&lt;br /&gt;
  infix &amp;quot;+&amp;quot; (other: G): G&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
class COMPARABLE [G -&amp;gt; COMPARABLE [G]]&lt;br /&gt;
feature&lt;br /&gt;
  less_than (other: G): BOOLEAN&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/e&amp;gt;&lt;br /&gt;
&lt;br /&gt;
With this approach, the use of the general class &amp;lt;e&amp;gt;NUMERIC&amp;lt;/e&amp;gt; and &amp;lt;e&amp;gt;COMPARABLE&amp;lt;/e&amp;gt; will become more complicated, but since they appear in libraries most of the time it could be done.&lt;/div&gt;</summary>
		<author><name>Juliant</name></author>	</entry>

	<entry>
		<id>https://dev.eiffel.com/index.php?title=Single-level_call_rule_and_generics&amp;diff=9011</id>
		<title>Single-level call rule and generics</title>
		<link rel="alternate" type="text/html" href="https://dev.eiffel.com/index.php?title=Single-level_call_rule_and_generics&amp;diff=9011"/>
				<updated>2007-07-14T01:00:48Z</updated>
		
		<summary type="html">&lt;p&gt;Juliant: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Category:ECMA]]&lt;br /&gt;
[[Category:Catcall]]&lt;br /&gt;
{{Research}}&lt;br /&gt;
== Problem ==&lt;br /&gt;
&lt;br /&gt;
The single-level call rule says that every call has to be valid for all possible dynamic types of an entity. So for a formal generic &amp;lt;e&amp;gt;G&amp;lt;/e&amp;gt; this means that the call has to be valid for all possible descendants of the constraint (or at least for every instantiation which happens in a system).&lt;br /&gt;
&lt;br /&gt;
Let's look at an example using &amp;lt;e&amp;gt;NUMERIC&amp;lt;/e&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;e&amp;gt;&lt;br /&gt;
class X [G -&amp;gt; NUMERIC]&lt;br /&gt;
&lt;br /&gt;
feature&lt;br /&gt;
&lt;br /&gt;
  f (g1, g2: G): G&lt;br /&gt;
    do&lt;br /&gt;
      Result := g1 + g2&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/e&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Here, the call to &amp;lt;e&amp;gt;+&amp;lt;/e&amp;gt; has to be valid for all possible descendants of &amp;lt;e&amp;gt;NUMERIC&amp;lt;/e&amp;gt;. Since the signature of the feature is &amp;lt;e&amp;gt;like Current&amp;lt;/e&amp;gt;, the call is never valid. This has to be the case as otherwise, the following code would produce a catcall:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;e&amp;gt;&lt;br /&gt;
x: X [NUMERIC]&lt;br /&gt;
x.f (1, 1.0)&lt;br /&gt;
&amp;lt;/e&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The problem is that the formal generic &amp;lt;e&amp;gt;G&amp;lt;/e&amp;gt; is always assumed to be of any type which satisfies the constraint, so normally the formal generic is polymorph.&lt;br /&gt;
&lt;br /&gt;
As the above example show, the use of features on formal generic parameters which are covariantly redefined is severely limited. But as the purpose of &amp;lt;e&amp;gt;NUMERIC&amp;lt;/e&amp;gt; is exactly to allow creation of generic algorithms over numeric types, this has to be addressed (Note that also &amp;lt;e&amp;gt;COMPARABLE&amp;lt;/e&amp;gt; is a problem).&lt;br /&gt;
&lt;br /&gt;
== Possible solutions ==&lt;br /&gt;
&lt;br /&gt;
=== Monomorph formal generics ===&lt;br /&gt;
&lt;br /&gt;
The first idea is to be able to mark a formal generic as monomorph:&lt;br /&gt;
&amp;lt;e&amp;gt;&lt;br /&gt;
class X [monomorph G -&amp;gt; NUMERIC]&lt;br /&gt;
&lt;br /&gt;
  f (g1, g2: G): G&lt;br /&gt;
    do&lt;br /&gt;
      Result := g1 + g2&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/e&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The generic class can then only be instantiated with monomorphic types, i.e. using [[interval types]] &amp;lt;e&amp;gt;X [INTEGER..INTEGER]&amp;lt;/e&amp;gt; or &amp;lt;e&amp;gt;X [REAL..REAL]&amp;lt;/e&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
For the check we can now assume that &amp;lt;e&amp;gt;G&amp;lt;/e&amp;gt; will be monomorphic. This helps a little bit further: For every feature argument which is &amp;lt;e&amp;gt;like Current&amp;lt;/e&amp;gt; we can assume that the exact type will be given. But this works only for covariant features which have &amp;lt;e&amp;gt;like Current&amp;lt;/e&amp;gt; arguments which are never redefined into something else. Take the following classes for an example:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;e&amp;gt;&lt;br /&gt;
class A&lt;br /&gt;
feature&lt;br /&gt;
  f (a: like Current) do end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
class B&lt;br /&gt;
inherit A&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
class C&lt;br /&gt;
inherit A redefine f&lt;br /&gt;
feature&lt;br /&gt;
  f (a: D) do end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
class D&lt;br /&gt;
inherit C&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/e&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Now assume the following generic class:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;e&amp;gt;&lt;br /&gt;
class X [monomorph G -&amp;gt; A]&lt;br /&gt;
feature&lt;br /&gt;
  f&lt;br /&gt;
    local&lt;br /&gt;
      g1, g2: G&lt;br /&gt;
    do&lt;br /&gt;
      g1.f (g2)&lt;br /&gt;
    end&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/e&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The call to &amp;lt;e&amp;gt;g1.f&amp;lt;/e&amp;gt; is not valid since &amp;lt;e&amp;gt;G&amp;lt;/e&amp;gt; could be of type &amp;lt;e&amp;gt;C&amp;lt;/e&amp;gt;, and then the argument has to be of type &amp;lt;e&amp;gt;D&amp;lt;/e&amp;gt;. So now, not even the &amp;lt;e&amp;gt;like Current&amp;lt;/e&amp;gt; feature is callable with monomorphic generics. Basically it is the same as the declaration without ''monomorphic'' for the generic.&lt;br /&gt;
&lt;br /&gt;
So this solution works only for the case of &amp;lt;e&amp;gt;like Current&amp;lt;/e&amp;gt; features which are never redefined. Only then it can be guaranteed for a monomorphic generic formal, that the signature will match the formal generic exactly. Other covariant features have still to be valid for all possible descendants.&lt;br /&gt;
&lt;br /&gt;
For the case of &amp;lt;e&amp;gt;NUMERIC&amp;lt;/e&amp;gt; and &amp;lt;e&amp;gt;COMPARABLE&amp;lt;/e&amp;gt; the use of monomorphic formal arguments would work as they define only &amp;lt;e&amp;gt;like Current&amp;lt;/e&amp;gt; features which are normally not redefined in subclasses. A more general mechanism would be nice but at the moment it is unclear how such a mechanism should look like.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Remodeling library ===&lt;br /&gt;
&lt;br /&gt;
Another way to solve the problem of &amp;lt;e&amp;gt;NUMERIC&amp;lt;/e&amp;gt; and &amp;lt;e&amp;gt;COMPARABLE&amp;lt;/e&amp;gt; would be to change the library. As these classes have mostly &amp;lt;e&amp;gt;like Current&amp;lt;/e&amp;gt; arguments and result types, they can be modeled via generics in the first place.&lt;br /&gt;
&lt;br /&gt;
For example:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;e&amp;gt;&lt;br /&gt;
class NUMERIC [G -&amp;gt; NUMERIC [G]]&lt;br /&gt;
feature&lt;br /&gt;
  infix &amp;quot;+&amp;quot; (other: G): G&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
class COMPARABLE [G -&amp;gt; COMPARABLE [G]]&lt;br /&gt;
feature&lt;br /&gt;
  less_than (other: G): BOOLEAN&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/e&amp;gt;&lt;br /&gt;
&lt;br /&gt;
With this approach, the use of the general class &amp;lt;e&amp;gt;NUMERIC&amp;lt;/e&amp;gt; and &amp;lt;e&amp;gt;COMPARABLE&amp;lt;/e&amp;gt; will become more complicated, but since they appear in libraries most of the time it could be done.&lt;/div&gt;</summary>
		<author><name>Juliant</name></author>	</entry>

	<entry>
		<id>https://dev.eiffel.com/index.php?title=Single-level_call_rule_and_generics&amp;diff=9009</id>
		<title>Single-level call rule and generics</title>
		<link rel="alternate" type="text/html" href="https://dev.eiffel.com/index.php?title=Single-level_call_rule_and_generics&amp;diff=9009"/>
				<updated>2007-07-14T00:55:29Z</updated>
		
		<summary type="html">&lt;p&gt;Juliant: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Problem ==&lt;br /&gt;
&lt;br /&gt;
The single-level call rule says that every call has to be valid for all possible dynamic types of an entity. So for a formal generic &amp;lt;e&amp;gt;g&amp;lt;/e&amp;gt; this means that the call has to be valid for all possible descendants of the constraint (or at least for every instantiation which happens in a system).&lt;br /&gt;
&lt;br /&gt;
Let's look at an example using &amp;lt;e&amp;gt;NUMERIC&amp;lt;/e&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;e&amp;gt;&lt;br /&gt;
class X [G -&amp;gt; NUMERIC]&lt;br /&gt;
&lt;br /&gt;
feature&lt;br /&gt;
&lt;br /&gt;
  f (g1, g2: G): G&lt;br /&gt;
    do&lt;br /&gt;
      Result := g1 + g2&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/e&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Here, the call to &amp;lt;e&amp;gt;+&amp;lt;/e&amp;gt; has to be valid for all possible descendants of &amp;lt;e&amp;gt;NUMERIC&amp;lt;/e&amp;gt;. Since the signature of the feature is &amp;lt;e&amp;gt;like Current&amp;lt;/e&amp;gt;, the call is never valid. This has to be the case as otherwise, the following code would produce a catcall:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;e&amp;gt;&lt;br /&gt;
x: X [NUMERIC]&lt;br /&gt;
x.f (1, 1.0)&lt;br /&gt;
&amp;lt;/e&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The problem is that the formal generic &amp;lt;e&amp;gt;G&amp;lt;/e&amp;gt; is always assumed to be of any type which satisfies the constraint, so normally the formal generic is polymorph.&lt;br /&gt;
&lt;br /&gt;
As the above example show, the use of features on formal generic parameters which are covariantly redefined is severely limited. But as the purpose of &amp;lt;e&amp;gt;NUMERIC&amp;lt;/e&amp;gt; is exactly to allow creation of generic algorithms over numeric types, this has to be addressed (Note that also &amp;lt;e&amp;gt;COMPARABLE&amp;lt;/e&amp;gt; is a problem).&lt;br /&gt;
&lt;br /&gt;
== Possible solutions ==&lt;br /&gt;
&lt;br /&gt;
=== Monomorph formal generics ===&lt;br /&gt;
&lt;br /&gt;
The first idea is to be able to mark a formal generic as monomorph:&lt;br /&gt;
&amp;lt;e&amp;gt;&lt;br /&gt;
class X [monomorph G -&amp;gt; NUMERIC]&lt;br /&gt;
&lt;br /&gt;
  f (g1, g2: G): G&lt;br /&gt;
    do&lt;br /&gt;
      Result := g1 + g2&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/e&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The generic class can then only be instantiated with monomorphic types, i.e. using [[interval types]] &amp;lt;e&amp;gt;X [INTEGER..INTEGER]&amp;lt;/e&amp;gt; or &amp;lt;e&amp;gt;X [REAL..REAL]&amp;lt;/e&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
For the check we can now assume that &amp;lt;e&amp;gt;G&amp;lt;/e&amp;gt; will be monomorphic. This helps a little bit further: For every feature argument which is &amp;lt;e&amp;gt;like Current&amp;lt;/e&amp;gt; we can assume that the exact type will be given. But this works only for covariant features which have &amp;lt;e&amp;gt;like Current&amp;lt;/e&amp;gt; arguments which are never redefined into something else. Take the following classes for an example:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;e&amp;gt;&lt;br /&gt;
class A&lt;br /&gt;
feature&lt;br /&gt;
  f (a: like Current) do end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
class B&lt;br /&gt;
inherit A&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
class C&lt;br /&gt;
inherit A redefine f&lt;br /&gt;
feature&lt;br /&gt;
  f (a: D) do end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
class D&lt;br /&gt;
inherit C&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/e&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Now assume the following generic class:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;e&amp;gt;&lt;br /&gt;
class X [monomorph G -&amp;gt; A]&lt;br /&gt;
feature&lt;br /&gt;
  f&lt;br /&gt;
    local&lt;br /&gt;
      g1, g2: G&lt;br /&gt;
    do&lt;br /&gt;
      g1.f (g2)&lt;br /&gt;
    end&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/e&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The call to &amp;lt;e&amp;gt;g1.f&amp;lt;/e&amp;gt; is not valid since &amp;lt;e&amp;gt;G&amp;lt;/e&amp;gt; could be of type &amp;lt;e&amp;gt;C&amp;lt;/e&amp;gt;, and then the argument has to be of type &amp;lt;e&amp;gt;D&amp;lt;/e&amp;gt;. So now, not even the &amp;lt;e&amp;gt;like Current&amp;lt;/e&amp;gt; feature is callable with monomorphic generics. Basically it is the same as the declaration without ''monomorphic'' for the generic.&lt;br /&gt;
&lt;br /&gt;
So this solution works only for the case of &amp;lt;e&amp;gt;like Current&amp;lt;/e&amp;gt; features which are never redefined. Only then it can be guaranteed for a monomorphic generic formal, that the signature will match the formal generic exactly. Other covariant features have still to be valid for all possible descendants.&lt;br /&gt;
&lt;br /&gt;
For the case of &amp;lt;e&amp;gt;NUMERIC&amp;lt;/e&amp;gt; and &amp;lt;e&amp;gt;COMPARABLE&amp;lt;/e&amp;gt; the use of monomorphic formal arguments would work as they define only &amp;lt;e&amp;gt;like Current&amp;lt;/e&amp;gt; features which are normally not redefined in subclasses. A more general mechanism would be nice but at the moment it is unclear how such a mechanism should look like.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Remodeling library ===&lt;br /&gt;
&lt;br /&gt;
Another way to solve the problem of &amp;lt;e&amp;gt;NUMERIC&amp;lt;/e&amp;gt; and &amp;lt;e&amp;gt;COMPARABLE&amp;lt;/e&amp;gt; would be to change the library. As these classes have mostly &amp;lt;e&amp;gt;like Current&amp;lt;/e&amp;gt; arguments and result types, they can be modeled via generics in the first place.&lt;br /&gt;
&lt;br /&gt;
For example:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;e&amp;gt;&lt;br /&gt;
class NUMERIC [G -&amp;gt; NUMERIC [G]]&lt;br /&gt;
feature&lt;br /&gt;
  infix &amp;quot;+&amp;quot; (other: G): G&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
class COMPARABLE [G -&amp;gt; COMPARABLE [G]]&lt;br /&gt;
feature&lt;br /&gt;
  less_than (other: G): BOOLEAN&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/e&amp;gt;&lt;br /&gt;
&lt;br /&gt;
With this approach, the use of the general class &amp;lt;e&amp;gt;NUMERIC&amp;lt;/e&amp;gt; and &amp;lt;e&amp;gt;COMPARABLE&amp;lt;/e&amp;gt; will become more complicated, but since they appear in libraries most of the time it could be done.&lt;/div&gt;</summary>
		<author><name>Juliant</name></author>	</entry>

	<entry>
		<id>https://dev.eiffel.com/index.php?title=Single-level_call_rule_and_generics&amp;diff=9008</id>
		<title>Single-level call rule and generics</title>
		<link rel="alternate" type="text/html" href="https://dev.eiffel.com/index.php?title=Single-level_call_rule_and_generics&amp;diff=9008"/>
				<updated>2007-07-14T00:51:34Z</updated>
		
		<summary type="html">&lt;p&gt;Juliant: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Problem ==&lt;br /&gt;
&lt;br /&gt;
The single-level call rule says that every call has to be valid for all possible dynamic types of an entity. So for a formal generic &amp;lt;e&amp;gt;g&amp;lt;/e&amp;gt; this means that the call has to be valid for all possible descendants of the constraint (or at least for every instantiation which happens in a system).&lt;br /&gt;
&lt;br /&gt;
Let's look at an example using &amp;lt;e&amp;gt;NUMERIC&amp;lt;/e&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;e&amp;gt;&lt;br /&gt;
class X [G -&amp;gt; NUMERIC]&lt;br /&gt;
&lt;br /&gt;
feature&lt;br /&gt;
&lt;br /&gt;
  f (g1, g2: G): G&lt;br /&gt;
    do&lt;br /&gt;
      Result := g1 + g2&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/e&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Here, the call to &amp;lt;e&amp;gt;+&amp;lt;/e&amp;gt; has to be valid for all possible descendants of &amp;lt;e&amp;gt;NUMERIC&amp;lt;/e&amp;gt;. Since the signature of the feature is &amp;lt;e&amp;gt;like Current&amp;lt;/e&amp;gt;, the call is never valid. This has to be the case as otherwise, the following code would produce a catcall:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;e&amp;gt;&lt;br /&gt;
x: X [NUMERIC]&lt;br /&gt;
x.f (1, 1.0)&lt;br /&gt;
&amp;lt;/e&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The problem is that the formal generic &amp;lt;e&amp;gt;G&amp;lt;/e&amp;gt; is always assumed to be of any type which satisfies the constraint, so normally the formal generic is polymorph.&lt;br /&gt;
&lt;br /&gt;
As the above example show, the use of features on formal generic parameters which are covariantly redefined is severly limited. But as the purpose of &amp;lt;e&amp;gt;NUMERIC&amp;lt;/e&amp;gt; is exactly to allow creation of generic algorithms over numeric types, this has to be addressed (Note that also &amp;lt;e&amp;gt;COMPARABLE&amp;lt;/e&amp;gt; is a problem).&lt;br /&gt;
&lt;br /&gt;
== Possible solutions ==&lt;br /&gt;
&lt;br /&gt;
=== Monomorph formal generics ===&lt;br /&gt;
&lt;br /&gt;
The first idea is to be able to mark a formal generic as monomorph:&lt;br /&gt;
&amp;lt;e&amp;gt;&lt;br /&gt;
class X [monomorph G -&amp;gt; NUMERIC]&lt;br /&gt;
&lt;br /&gt;
  f (g1, g2: G): G&lt;br /&gt;
    do&lt;br /&gt;
      Result := g1 + g2&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/e&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The generic class can then only be instantiated with monomorphic types, i.e. using [[interval types]] &amp;lt;e&amp;gt;X [INTEGER..INTEGER]&amp;lt;/e&amp;gt; or &amp;lt;e&amp;gt;X [REAL..REAL]&amp;lt;/e&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
For the check we can now assume that &amp;lt;e&amp;gt;G&amp;lt;/e&amp;gt; will be monomorphic. This helps a little bit furhter: For every feature argument which is &amp;lt;e&amp;gt;like Current&amp;lt;/e&amp;gt; we can assume that the exact type will be given. But this works only for covariant features which have &amp;lt;e&amp;gt;like Current&amp;lt;/e&amp;gt; arguments which are never redefined into something else. Take the following classes for an example:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;e&amp;gt;&lt;br /&gt;
class A&lt;br /&gt;
feature&lt;br /&gt;
  f (a: like Current) do end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
class B&lt;br /&gt;
inherit A&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
class C&lt;br /&gt;
inherit A redefine f&lt;br /&gt;
feature&lt;br /&gt;
  f (a: D) do end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
class D&lt;br /&gt;
inherit C&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/e&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Now assume the following generic class:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;e&amp;gt;&lt;br /&gt;
class X [monomorph G -&amp;gt; A]&lt;br /&gt;
feature&lt;br /&gt;
  f&lt;br /&gt;
    local&lt;br /&gt;
      g1, g2: G&lt;br /&gt;
    do&lt;br /&gt;
      g1.f (g2)&lt;br /&gt;
    end&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/e&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The call to &amp;lt;e&amp;gt;g1.f&amp;lt;/e&amp;gt; is not valid since &amp;lt;e&amp;gt;G&amp;lt;/e&amp;gt; could be of type &amp;lt;e&amp;gt;C&amp;lt;/e&amp;gt;, and then the argument has to be of type &amp;lt;e&amp;gt;D&amp;lt;/e&amp;gt;. So now, not even the &amp;lt;e&amp;gt;like Current&amp;lt;/e&amp;gt; feature is callable with monomorphic generics. Basically it is the same as the declaration without ''monomorphic'' for the generic.&lt;br /&gt;
&lt;br /&gt;
So this solution works only for the case of &amp;lt;e&amp;gt;like Current&amp;lt;/e&amp;gt; features which are never redefined. Only then it can be guaranteed for a monomorphic generic formal, that the signature will match the formal generic exactly. Other covariant features have still to be valid for all possible descendants.&lt;br /&gt;
&lt;br /&gt;
For the case of &amp;lt;e&amp;gt;NUMERIC&amp;lt;/e&amp;gt; and &amp;lt;e&amp;gt;COMPARABLE&amp;lt;/e&amp;gt; the use of monomorphic formal arguments would work as they define only &amp;lt;e&amp;gt;like Current&amp;lt;/e&amp;gt; features which are normally not redefined in subclasses. A more general mechanism would be nice but at the moment it is unclear how such a mechanism should look like.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Remodeling library ===&lt;br /&gt;
&lt;br /&gt;
Another way to solve the problem of &amp;lt;e&amp;gt;NUMERIC&amp;lt;/e&amp;gt; and &amp;lt;e&amp;gt;COMPARABLE&amp;lt;/e&amp;gt; would be to change the library. As these classes have mostly &amp;lt;e&amp;gt;like Current&amp;lt;/e&amp;gt; arguments and result types, they can be modeled via generics in the first place.&lt;br /&gt;
&lt;br /&gt;
For example:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;e&amp;gt;&lt;br /&gt;
class NUMERIC [G -&amp;gt; NUMERIC [G]]&lt;br /&gt;
feature&lt;br /&gt;
  infix &amp;quot;+&amp;quot; (other: G): G&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
class COMPARABLE [G -&amp;gt; COMPARABLE [G]]&lt;br /&gt;
feature&lt;br /&gt;
  less_than (other: G): BOOLEAN&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/e&amp;gt;&lt;br /&gt;
&lt;br /&gt;
With this approach, the use of the general class &amp;lt;e&amp;gt;NUMERIC&amp;lt;/e&amp;gt; and &amp;lt;e&amp;gt;COMPARABLE&amp;lt;/e&amp;gt; will become more complicated, but since they appear in libraries most of the time it could be done.&lt;/div&gt;</summary>
		<author><name>Juliant</name></author>	</entry>

	<entry>
		<id>https://dev.eiffel.com/index.php?title=Talk:Interval_types&amp;diff=8988</id>
		<title>Talk:Interval types</title>
		<link rel="alternate" type="text/html" href="https://dev.eiffel.com/index.php?title=Talk:Interval_types&amp;diff=8988"/>
				<updated>2007-07-11T17:01:04Z</updated>
		
		<summary type="html">&lt;p&gt;Juliant: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;'''--[[User:Schoelle|Schoelle]] 12:33, 8 July 2007 (CEST)''': Could somebody illustrate how this solves the problem of convariant argument redefinition using 'like Current' or similar? &lt;br /&gt;
&lt;br /&gt;
:'''--[[User:Manus|manus]] 18:14, 8 July 2007 (CEST)''': This case is just a typical case of implicit covariance. The rules are the same and therefore any feature involving `like Current' in its arguments will most likely be rejected in some cases unless the target is monomorphic. Dont' forget that it is mostly the case with `is_equal' and `copy' which are getting new signatures in the new ECMA standard. For COMPARABLE then it just mean that you won't be able to compare apple with oranges which is exactly what we are trying to avoid.&lt;br /&gt;
&lt;br /&gt;
'''--[[User:Schoelle|Schoelle]] 15:30, 10 July 2007 (CEST)''' Thanks for the answer, this was enlighting. Second question: can anybody give examples from the practice that are different from A..A and A..NONE ? Something like A..B that really is needed and makes sense?&lt;br /&gt;
&lt;br /&gt;
:'''--[[User:Seilerm|Seilerm]] 20:33, 10 July 2007 (CEST)''': I think this comes down to the very question where covariance on ordinary types is needed. If you want I can give a lot of examples for generics, probably because it is the main source where I personally use covariance. Besides that: I have seen code where one uses anchored types (i.e. the like keyword) to anchor argument types to the type of queries (mostly attributes). And then the query result type is redefined covariantly. This might be interesting if otherwise you would need a lot of generic parameters, but you only redefine a few times different query (attribute) types in your class hierarchy. That being said, I personally don't like this style of coding.&lt;br /&gt;
&lt;br /&gt;
'''--[[User:Schoelle|Schoelle]] 12:13, 11 July 2007 (CEST)''' Ok, lets me see if I can correctly summarize, relating to my article [http://www.fams.de/text/type-safe-eiffel.html]. I am not doing this to advertise for my solution, but just because it is easier for me to understand something new by relating it to something that I have understood.&lt;br /&gt;
&lt;br /&gt;
For ''Covariant arguments and anchored types'', we are (more or less) removing covariance from the language (the conformance rules have been made so restrictive that the BOAT/SKIPPER/CAT/CAT_SKIPPER example becomes illegal), as demanded in my article.      '''(1)'''&lt;br /&gt;
&lt;br /&gt;
For ''Genericity'', we are using rules similar to Wildcard types in Java, which disallows calls to features with arguments of a generic type (X[A..A] is X&amp;lt;A&amp;gt; in Java, X[A..NONE] is X&amp;lt;? extends A&amp;gt; in Java).     '''(2)'''&lt;br /&gt;
&lt;br /&gt;
I think that the approach of invariant arguments described in my paper is more elegant (I am probably just locked into own ideas), as the decision of using a generic parameter covariantly is made by the supplier and not the client, i.e. it becomes part of the library design. But if Java people can live with Wildcard types, so can we ... ;-)        '''(3)'''&lt;br /&gt;
&lt;br /&gt;
:'''--[[User:Juliant|Juliant]] 19:01, 11 July 2007 (CEST)''' &lt;br /&gt;
:for '''(1)''': Actually it's not the conformance rules that have been restricted, but the feature call rules. Per default you still have full conformance between normal types, but you mostly cannot call covariant features. In the end it is the same, restricting covariance as much as you probably won't use it anymore.&lt;br /&gt;
:for '''(2)''': Yes, they are very similar.&lt;br /&gt;
:for '''(3)''': The problem with the [[definition-site variance#Conclusion|invariant arguments]] you described is that they break the library for sure. Since one of the criterias for a catcall solution is backwards compatibility, this is not an option. If you would be starting from scratch, it may be a good option as the use of a generic is dictated by the library designer and it could be easier to use by the programmer.&lt;/div&gt;</summary>
		<author><name>Juliant</name></author>	</entry>

	<entry>
		<id>https://dev.eiffel.com/index.php?title=Comparison_of_catcall_solutions&amp;diff=8957</id>
		<title>Comparison of catcall solutions</title>
		<link rel="alternate" type="text/html" href="https://dev.eiffel.com/index.php?title=Comparison_of_catcall_solutions&amp;diff=8957"/>
				<updated>2007-07-06T16:34:03Z</updated>
		
		<summary type="html">&lt;p&gt;Juliant: /* Overview of general solutions */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Category:ECMA]]&lt;br /&gt;
[[Category:Catcall]]&lt;br /&gt;
== Motivation ==&lt;br /&gt;
&lt;br /&gt;
By allowing covariant feature redefinition and hiding of features, the Eiffel language introduces the problem of catcalls (Changed Availability or Type). Currently the ECMA Eiffel standard does not specify how the occurrence of catcalls should be statically rejected.&lt;br /&gt;
&lt;br /&gt;
The purpose of this document is to show a comparison between different proposals on how to handle the issue of preventing catcalls.&lt;br /&gt;
&lt;br /&gt;
== Criteria for a solution ==&lt;br /&gt;
&lt;br /&gt;
To be able to judge a solution we use the following criteria which we consider as important:&lt;br /&gt;
&lt;br /&gt;
; Syntax overhead : How much syntax will be added to the language in order to express safe covariance and generics?&lt;br /&gt;
; Covariance on non-generic types : Are covariant argument redefinitions addressed in the solution? How does the programmer express it?&lt;br /&gt;
; Export status restrictions : Is restriction of export status addressed in the solution? How does the programmer express it?&lt;br /&gt;
; Use of generic types : How is conformance of generics? Are catcalls for generics addressed in the solution? How does the programmer express it? Can generics be used as now or are there restrictions?&lt;br /&gt;
:; Agents : Can agents be modeled with the solution while being type safe and expressive?&lt;br /&gt;
:; Comparator : Can comparator types be modeled with the solution while being type safe and expressive?&lt;br /&gt;
; Complexity of the compiler check : Is it just a matter of doing one check or several?&lt;br /&gt;
; Complexity of the runtime : Does the runtime need more information to do assignment attempts or object tests?&lt;br /&gt;
; Whole-system analysis : Is a whole-system analysis necessary?&lt;br /&gt;
; Dynamic class and type loading : Is it safe to dynamically load new classes at runtime and instantiate new types?&lt;br /&gt;
; Backward compatibility : Is the solution backward compatible to existing source code?&lt;br /&gt;
:; Applicable per cluster : Can the solution be applied on a per cluster basis?&lt;br /&gt;
; Support of compiler/IDE : Can the compiler/IDE help in updating existing source code? How?&lt;br /&gt;
&lt;br /&gt;
== General remarks ==&lt;br /&gt;
&lt;br /&gt;
=== Checking feature calls ===&lt;br /&gt;
&lt;br /&gt;
As the ''Single-level Call rule'' (8.25.3, VUSC) describes, a feature call is only valid if it is valid for every type in the dynamic type set. A simple solution would be that every feature call has to be checked for all possible descendants of the static target type. If this check is performed on a system, it will catch all catcalls - but also report false positives.&lt;br /&gt;
&lt;br /&gt;
Some of the proposed solutions try to address this problem by finding a better approximation to the dynamic type set so that the false positives can be ruled out.&lt;br /&gt;
&lt;br /&gt;
In general this is problematic as it requires a whole-system analysis, thus preventing the dynamic loading of new classes at run-time. The reason for this is that it is not known at compile time which features will be covariantly redefined by dynamically loaded classes.&lt;br /&gt;
&lt;br /&gt;
This is only the case with non-generic types. For generics, it is known at compile time that all features containing a formal in the parameter list can be treated as covariantly redefined and corresponding precautions can be implemented via the type system and conformance rules which allow to load even generic types at run-time.&lt;br /&gt;
&lt;br /&gt;
By the way, Eiffel Software has started to [[Single level call rule implementation|implement the basis of the ''single-level call rule'']] in it's Eiffel compiler. It is work in progress which revealed some implementation problems.&lt;br /&gt;
&lt;br /&gt;
=== Generic vs. non-generic covariance ===&lt;br /&gt;
&lt;br /&gt;
We can distinguish two different kinds of covariant argument redefinition:&lt;br /&gt;
&lt;br /&gt;
* When a generic type is derived, the formal generic parameters will be replaced by the actual generic parameters. Given the current conformance rules for generics, this can be seen as a covariant redefinition for all features which contain a formal generic as an argument. A simple example is the change from &amp;lt;e&amp;gt;LIST [ANY]&amp;lt;/e&amp;gt; to &amp;lt;e&amp;gt;LIST [INTEGER]&amp;lt;/e&amp;gt; where the feature &amp;lt;e&amp;gt;put&amp;lt;/e&amp;gt; changes signature from &amp;lt;e&amp;gt;ANY&amp;lt;/e&amp;gt; to &amp;lt;e&amp;gt;INTEGER&amp;lt;/e&amp;gt;.&lt;br /&gt;
* In the non-generic case, covariance happens for certain anchored type declarations and in the case of explicitly changing an argument type to a descendant. This happens in general only on a small subset of the features.&lt;br /&gt;
&lt;br /&gt;
The main difference is that in the generic case, all features which have a formal generic parameter automatically change the signature in different derivations whereas the non-generic case only specific features are covariantly redefined (if any at all). Also, in the generic case it is known for all possible descendants which features are redefined covariantly.&lt;br /&gt;
&lt;br /&gt;
This observation helps to understand the various proposals and to see their strengths and weaknesses:&lt;br /&gt;
* A proposal which operates on the feature level can be good for non-generic classes as you generally have a small number of features covariantly redefined and you only have to specify these features. In the case of generics this can become cumbersome as all features with formal generic parameters are always considered as covariantly redefined and thus for generics they always have to be considered.&lt;br /&gt;
* A proposal which operates on the type level is better suited for generics as you don't have to specify every single feature which has a formal generic parameter as argument. But they run into problems in the non-generic case if you look at anchored types - for example &amp;lt;e&amp;gt;like Current&amp;lt;/e&amp;gt;. Due to the fact that you have a covariant redeclaration in every descendant with such a feature, operating on the type level means that you have to handle every descendant specifically whereas if you operated on the feature level you could just handle this single feature.&lt;br /&gt;
* You see that there are two families of features: Features with formal arguments and ordinary features which are covariantly redefined. The fundamental difference between these two families is that they can change their signature independently. From &amp;lt;e&amp;gt;LIST [ANY]&amp;lt;/e&amp;gt; to &amp;lt;e&amp;gt;LIST [INTEGER]&amp;lt;/e&amp;gt; only the features based on the formal change their signature while they don't change from &amp;lt;e&amp;gt;LIST [ANY]&amp;lt;/e&amp;gt; to &amp;lt;e&amp;gt;LINKED_LIST [ANY]&amp;lt;/e&amp;gt; where the ordinary ones do. If you don't want to restrict the programmers expressiveness these feature families have to be addressed separately and a ''one fits all'' solution does not exist.&lt;br /&gt;
&lt;br /&gt;
=== Contravariant generics ===&lt;br /&gt;
&lt;br /&gt;
The modeling of certain problems involving generics requires contravariance. The two examples which will be used are comparator objects and agents:&lt;br /&gt;
&lt;br /&gt;
* If you want to compare objects using a comparator, it either needs to be able to compare objects of the exact type, or an ancestor. Thus if you want to compare strings, either a comparator for &amp;lt;e&amp;gt;STRING&amp;lt;/e&amp;gt; or one for &amp;lt;e&amp;gt;ANY&amp;lt;/e&amp;gt; is suitable. &lt;br /&gt;
* If you want to pass an argument of type &amp;lt;e&amp;gt;STRING&amp;lt;/e&amp;gt; to an agent, the agent either has to accept a &amp;lt;e&amp;gt;STRING&amp;lt;/e&amp;gt; or &amp;lt;e&amp;gt;ANY&amp;lt;/e&amp;gt; argument (or no argument at all).&lt;br /&gt;
&lt;br /&gt;
These problems can only be modeled if there is a way to express contravariant conformance for generics. This means that all proposed solutions which don't offer this possibility can't be used to model agents or comparator correctly and safely.&lt;br /&gt;
&lt;br /&gt;
=== Catcall benchmark ===&lt;br /&gt;
&lt;br /&gt;
[[Catcall checkpoints]]&lt;br /&gt;
&lt;br /&gt;
== Overview of general solutions ==&lt;br /&gt;
&lt;br /&gt;
The following proposals handle the case of covariance on non-generic and generic types.&lt;br /&gt;
&lt;br /&gt;
=== [[Novariance]] ===&lt;br /&gt;
&lt;br /&gt;
In the novariance proposal, covariant redefinition for arguments is prohibited. If covariance is needed for modeling purposes it can be [http://dev.eiffel.com/Covariance_through_renaming simulated by renaming].&lt;br /&gt;
&lt;br /&gt;
The conformance between generics with different formal parameters is removed.&lt;br /&gt;
&lt;br /&gt;
=== [[Forget / keep]] ===&lt;br /&gt;
&lt;br /&gt;
With the forget and keep mechanisms you specify per type on the feature level which features need not to be called - these features can safely be redefined covariantly - or which features have to be available - these features have to be typesafe for all possible values of a caller object.&lt;br /&gt;
&lt;br /&gt;
Reference: [http://dev.eiffel.com/Forget_/_Keep_Mechanism Article on dev.eiffel.com]&lt;br /&gt;
&lt;br /&gt;
=== Dynamic typeset algorithm ===&lt;br /&gt;
&lt;br /&gt;
The dynamic typeset algorithm does not change any semantics of the types or the conformance as it is in Eiffel already, it only does an abstract execution of the system to limit the possibilities per feature call which have to be checked if they are safe.&lt;br /&gt;
&lt;br /&gt;
=== [[Interval types]] ===&lt;br /&gt;
&lt;br /&gt;
Interval types allow to define each type as an interval with a lower and upper type as boundary. This limits the dynamic type set and thus restricts the number of features which need to be checked for system-validity. In addition to this, it defines rules which handle the case of features with formal arguments.&lt;br /&gt;
&lt;br /&gt;
=== [[Read-write types]] ===&lt;br /&gt;
&lt;br /&gt;
Read-write types are a solution which can model interval types and usage-site variance. It splits a type into a ''read'' type and a ''write'' type. The read type defines the applicable features and the write type the signature to check for valid arguments.&lt;br /&gt;
&lt;br /&gt;
== Overview of solutions for non-generics ==&lt;br /&gt;
&lt;br /&gt;
These proposal only address the case for non-generics. For generic catcalls another solution (e.g. wildcard generics) can be used.&lt;br /&gt;
&lt;br /&gt;
=== [[Restrict types]] ===&lt;br /&gt;
&lt;br /&gt;
With restrict types you specify per type on the type level which descendant types that are allowed. Only these types can be assigned to such a variable, and all feature calls on these variables have to be valid for all possible types in this list.&lt;br /&gt;
&lt;br /&gt;
Reference: [http://se.inf.ethz.ch/cgi-bin/ecma/index.cgi?IssueFLEX_CATCALL IssueFLEX_CATCALL on ECMA wiki]&amp;lt;br/&amp;gt;&lt;br /&gt;
Reference: Discussion in ECMA mailinglist named ''Catcall removal: another proposal'', [[Restrict types mail|available in parts]]&lt;br /&gt;
&lt;br /&gt;
=== [[DOG proposal]] ===&lt;br /&gt;
&lt;br /&gt;
With the DOG proposal, features which can be covariantly redefined have to be marked as such. These features can only be called on specially marked entities which have a restricted conformance, thus preventing assignments from descendants with potential covariantly redefined arguments.&lt;br /&gt;
&lt;br /&gt;
Reference: [http://se.inf.ethz.ch/cgi-bin/ecma/index.cgi?IssueDOG IssueDOG on ECMA wiki]&lt;br /&gt;
&lt;br /&gt;
== Overview of solutions for generics ==&lt;br /&gt;
&lt;br /&gt;
These proposal only address the case for generics. For non-generic catcalls another solution (e.g. novariance) can be used.&lt;br /&gt;
&lt;br /&gt;
=== [[Usage-site variance]] ===&lt;br /&gt;
&lt;br /&gt;
This solution lets the programmer decide on the instantiation of a generic if the generic parameter should be covariant, contravariant or invariant. Depending on the variance, the applicable features of the type and the conformance rules to other generic types are changed.&lt;br /&gt;
&lt;br /&gt;
Reference: [http://pag.csail.mit.edu/reading-group/variance-ECOOP02.pdf On variance-based subtyping for parametric types]&lt;br /&gt;
&lt;br /&gt;
=== [[Definition-site variance]] ===&lt;br /&gt;
&lt;br /&gt;
This solution lets the programmer decide in the definition of a generic class if the generic parameter should be covariant, contravariant or invariant. Depending on the variance, the formal generic can only appear at the argument, only appear as a result type or appear in both places. Also the conformance is adapted depending on the variance of the generic parameter.&lt;br /&gt;
&lt;br /&gt;
This is the solution which is implemented in the CLR, although not supported by generics in C# which are novariant.&lt;br /&gt;
&lt;br /&gt;
Reference: [http://blogs.msdn.com/rmbyers/archive/2006/06/01/613690.aspx Article about generics in CLR]&lt;br /&gt;
&lt;br /&gt;
Note: There is also a [http://fams.de/text/type-safe-eiffel.html proposal by Bernd Schoeller] about ''variant and invariant'' generics which is a subset of this one and thus not explained in detail.&lt;br /&gt;
&lt;br /&gt;
=== Wildcard generics ===&lt;br /&gt;
&lt;br /&gt;
This mechanism extends the [[usage-site variance]] by adding a wildcard to the generic derivation. This wildcard denotes unspecified types and limits the use of features with generic parameters or result types over conformance to the wildcard types.&lt;br /&gt;
&lt;br /&gt;
Since the mechanism is almost identical to the usage-site variance, it will not be looked at in more detail. Please refer to the reference article for more information.&lt;br /&gt;
&lt;br /&gt;
Reference: [http://www.jot.fm/issues/issue_2004_12/article5 Adding Wildcards to the Java Programming Language]&lt;br /&gt;
&lt;br /&gt;
== Overview of dynamic solutions ==&lt;br /&gt;
&lt;br /&gt;
These proposals do not prevent catcalls at compile-time but introduce means to handle catcalls at runtime.&lt;br /&gt;
&lt;br /&gt;
=== [[Detachable types]] ===&lt;br /&gt;
&lt;br /&gt;
This solution allows covariantly redefined features only to use detachable types. Through this mechanism, an object test is necessary before an argument can be used. This forces the programmer to test arguments for validity.&lt;br /&gt;
&lt;br /&gt;
Reference: [http://se.ethz.ch/~meyer/publications/lncs/attached.pdf Article about ''attached types'' by Bertrand Meyer]&amp;lt;br/&amp;gt;&lt;br /&gt;
Reference: [http://www.ecma-international.org/publications/standards/Ecma-367.htm ECMA Eiffel standard 2nd edition of June 2006]&lt;br /&gt;
&lt;br /&gt;
=== Recast ===&lt;br /&gt;
&lt;br /&gt;
In the recast proposal, the programmer has to specify a transformation function when covariantly redefining a feature which can transform the old argument types to the new ones.&lt;br /&gt;
&lt;br /&gt;
Reference: [http://se.inf.ethz.ch/cgi-bin/ecma/index.cgi?IssueCAT IssueCAT on ECMA wiki]&amp;lt;br/&amp;gt;&lt;br /&gt;
Reference: [http://www.inf.ethz.ch/~meyer/ongoing/covariance/recast.pdf Article about recast]&lt;br /&gt;
&lt;br /&gt;
=== Exceptions ===&lt;br /&gt;
&lt;br /&gt;
Another way of handling catcalls at runtime is to raise exceptions. It can be required or not to provide a rescue clause which handles the case of the catcall.&lt;br /&gt;
&lt;br /&gt;
== Combinations ==&lt;br /&gt;
&lt;br /&gt;
It is also possible to combine different proposals:&lt;br /&gt;
&lt;br /&gt;
* Novariance for non-generic features and usage-site variance for generics .&lt;br /&gt;
* Forget / keep for non-generic features and definition-site variance for generics.&lt;br /&gt;
* DOG proposal for non-generic features and wildcard generics.&lt;br /&gt;
* ...&lt;br /&gt;
&lt;br /&gt;
== Results ==&lt;br /&gt;
&lt;br /&gt;
The following table summarizes the support of the various solutions to the criteria described above which can be used to judge a catcall solution.&lt;br /&gt;
&lt;br /&gt;
This results can be differently interpreted, so the colors may not be totally accurate. See the [[Comparison of catcall solutions#Table_explained|explanation at the end of the table]] for more information&lt;br /&gt;
&lt;br /&gt;
=== General solutions ===&lt;br /&gt;
&lt;br /&gt;
{| border=1 cellpadding=2&lt;br /&gt;
&lt;br /&gt;
|- style=&amp;quot;visibility: hidden&amp;quot;&lt;br /&gt;
| style=&amp;quot;width:25%&amp;quot; |&lt;br /&gt;
| style=&amp;quot;width:25%&amp;quot; |&lt;br /&gt;
| style=&amp;quot;width:25%&amp;quot; |&lt;br /&gt;
| style=&amp;quot;width:25%&amp;quot; |&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
&lt;br /&gt;
! Criteria&lt;br /&gt;
! [[Novariance]]&lt;br /&gt;
! [[Forget / keep]]&lt;br /&gt;
! Dynamic typeset algorithm&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
&lt;br /&gt;
! Syntax overhead&lt;br /&gt;
| {{Green|No}}&lt;br /&gt;
| {{Red|Big}}: forget/keep clauses per type&lt;br /&gt;
| {{Green|No}}&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
&lt;br /&gt;
! Covariance on non-generic types &lt;br /&gt;
| {{Red|Not allowed}}&lt;br /&gt;
| {{Green|Allowed}}&lt;br /&gt;
| {{Green|Allowed}}&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
&lt;br /&gt;
! Export status restrictions&lt;br /&gt;
| {{Red|Not allowed}}&lt;br /&gt;
| {{Green|Allowed}}&lt;br /&gt;
| {{Green|Allowed}}&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
&lt;br /&gt;
! Use of generic types&lt;br /&gt;
| {{Red|Very limited}}: Only invariant conformance&lt;br /&gt;
| {{Orange|Limited}}: Conformance restricted (''keep all'' as default)&amp;lt;br/&amp;gt;{{Orange|Limited}}: Use restricted (''forget all'' as default)&lt;br /&gt;
| {{Green|As it is now}}&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
&lt;br /&gt;
! Agents&lt;br /&gt;
| {{Orange|Limited}}&amp;lt;br/&amp;gt;{{Green|Safe}}&lt;br /&gt;
| {{Orange|Limited}}&amp;lt;br/&amp;gt;{{Green|Safe}}&lt;br /&gt;
| {{Red|As it is now}}&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
&lt;br /&gt;
! Comparator&lt;br /&gt;
| {{Red|Not supported}}&lt;br /&gt;
| {{Red|Not supported}}&lt;br /&gt;
| {{Red|Not supported}}&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
&lt;br /&gt;
! Complexity of compiler check&lt;br /&gt;
| {{Green|Small}}&lt;br /&gt;
| {{Orange|Medium}}: Check of feature call for all descendants; Conformance check on forget/keep clauses&lt;br /&gt;
| {{Red|Big}}: Iterative abstract system execution&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
&lt;br /&gt;
! Complexity of runtime&lt;br /&gt;
| {{Green|Small}}: As it is now&lt;br /&gt;
| {{Orange|Medium}}: Need to know cat features for object tests&lt;br /&gt;
| {{Green|Small}}: As it is now&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
&lt;br /&gt;
! Whole-system analysis&lt;br /&gt;
| {{Green|No}}&lt;br /&gt;
| {{Red|Yes}}: use of ''forget all'' depends on system&lt;br /&gt;
| {{Red|Yes}}&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
&lt;br /&gt;
! Dynamic class and type loading&lt;br /&gt;
| {{Green|Yes}}&lt;br /&gt;
| {{Red|No}}&lt;br /&gt;
| {{Red|No}}&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
&lt;br /&gt;
! Backward compatibility&lt;br /&gt;
| {{Red|Very limited}}&lt;br /&gt;
| {{Orange|Limited}}&lt;br /&gt;
| {{Green|Full}}&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
&lt;br /&gt;
! Support of IDE (Source changes)&lt;br /&gt;
| {{Green|Not needed}}&lt;br /&gt;
| {{Orange|Possible}}: Can propose forget/keep clauses&lt;br /&gt;
| {{Green|Not needed}}&lt;br /&gt;
&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Solutions for non-generics ===&lt;br /&gt;
&lt;br /&gt;
{| border=1 cellpadding=2&lt;br /&gt;
&lt;br /&gt;
|- style=&amp;quot;visibility: hidden&amp;quot;&lt;br /&gt;
| style=&amp;quot;width:25%&amp;quot; |&lt;br /&gt;
| style=&amp;quot;width:25%&amp;quot; |&lt;br /&gt;
| style=&amp;quot;width:25%&amp;quot; |&lt;br /&gt;
| style=&amp;quot;width:25%&amp;quot; |&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
&lt;br /&gt;
! Criteria&lt;br /&gt;
! [[Restrict types]]&lt;br /&gt;
! [[DOG proposal]]&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
&lt;br /&gt;
! Syntax overhead&lt;br /&gt;
| {{Red|Big}}: Restrict clause per type declaration&lt;br /&gt;
| {{Orange|Medium}}: ''cat'' on features and on type declarations&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
&lt;br /&gt;
! Covariance on non-generic types &lt;br /&gt;
| {{Green|Allowed}}&lt;br /&gt;
| {{Green|Allowed}}&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
&lt;br /&gt;
! Export status restrictions&lt;br /&gt;
| {{Green|Allowed}}&lt;br /&gt;
| {{Green|Allowed}}&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
&lt;br /&gt;
! Use of generic types&lt;br /&gt;
| Not addressed&lt;br /&gt;
| Not addressed&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
&lt;br /&gt;
! Agents&lt;br /&gt;
| Not addressed&lt;br /&gt;
| Not addressed&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
&lt;br /&gt;
! Comparator&lt;br /&gt;
| Not addressed&lt;br /&gt;
| Not addressed&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
&lt;br /&gt;
! Complexity of compiler check&lt;br /&gt;
| {{Orange|Medium}}: Check of feature call for all descendants; Conformance check on restrict clauses&lt;br /&gt;
| {{Green|Small}}: Check of ''cat'' on conformance&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
&lt;br /&gt;
! Complexity of runtime&lt;br /&gt;
| not yet considered&lt;br /&gt;
| {{Green|Small}}&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
&lt;br /&gt;
! Whole-system analysis&lt;br /&gt;
| {{Orange|Partial}}&lt;br /&gt;
| {{Green|No}}&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
&lt;br /&gt;
! Dynamic class and type loading&lt;br /&gt;
| {{Orange|Limited}}&lt;br /&gt;
| {{Green|Yes}}&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
&lt;br /&gt;
! Backward compatibility&lt;br /&gt;
| {{Red|Very limited}}&lt;br /&gt;
| {{Red|Very limited}}&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
&lt;br /&gt;
! Support of IDE (Source changes)&lt;br /&gt;
| {{Orange|Possible}}: Can propose restrict clauses&lt;br /&gt;
| {{Orange|Possible}}: Can propose ''cat'' marks&lt;br /&gt;
&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Solutions for generics ===&lt;br /&gt;
&lt;br /&gt;
{| border=1 cellpadding=2&lt;br /&gt;
&lt;br /&gt;
|- style=&amp;quot;visibility: hidden&amp;quot;&lt;br /&gt;
| style=&amp;quot;width:25%&amp;quot; |&lt;br /&gt;
| style=&amp;quot;width:25%&amp;quot; |&lt;br /&gt;
| style=&amp;quot;width:25%&amp;quot; |&lt;br /&gt;
| style=&amp;quot;width:25%&amp;quot; |&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
&lt;br /&gt;
! Criteria&lt;br /&gt;
! [[Usage-site variance]]&lt;br /&gt;
! [[Definition-site variance]]&lt;br /&gt;
! Wildcard generics&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
&lt;br /&gt;
! Syntax overhead&lt;br /&gt;
| {{Orange|Medium}}: Variance marks per generic type&lt;br /&gt;
| {{Green|Small}}: Variance marks per generic class definition&lt;br /&gt;
| {{Orange|Medium}}: Variance marks per generic type&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
&lt;br /&gt;
! Covariance on non-generic types &lt;br /&gt;
| Not addressed&lt;br /&gt;
| Not addressed&lt;br /&gt;
| Not addressed&lt;br /&gt;
|-&lt;br /&gt;
&lt;br /&gt;
! Export status restrictions&lt;br /&gt;
| Not addressed&lt;br /&gt;
| Not addressed&lt;br /&gt;
| Not addressed&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
&lt;br /&gt;
! Use of generic types&lt;br /&gt;
| {{Orange|Limited}}: Conformance is limited&amp;lt;br/&amp;gt;{{Green|Safe}}&lt;br /&gt;
| {{Orange|Limited}}: Conformance is limited&amp;lt;br/&amp;gt;{{Green|Safe}}&lt;br /&gt;
| {{Orange|Limited}}: Conformance is limited&amp;lt;br/&amp;gt;{{Green|Safe}}&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
&lt;br /&gt;
! Agents&lt;br /&gt;
| {{Green|Fully supported}}&amp;lt;br/&amp;gt;{{Green|Safe}}&lt;br /&gt;
| {{Green|Fully supported}}: If tuples can be specified covariantly&amp;lt;br/&amp;gt;{{Green|Safe}}&lt;br /&gt;
| {{Green|Fully supported}}&amp;lt;br/&amp;gt;{{Green|Safe}}&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
&lt;br /&gt;
! Comparator&lt;br /&gt;
| {{Green|Supported}}&lt;br /&gt;
| {{Green|Supported}}&lt;br /&gt;
| {{Green|Supported}}&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
&lt;br /&gt;
! Complexity of compiler check&lt;br /&gt;
| {{Green|Small}}: Consider variance in conformance check&lt;br /&gt;
| {{Green|Small}}: Consider variance in conformance check&lt;br /&gt;
| {{Green|Small}}: Consider variance in conformance check&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
&lt;br /&gt;
! Complexity of runtime&lt;br /&gt;
| {{Green|Small}}: Consider variance in object test&lt;br /&gt;
| {{Green|Small}}: Consider variance in object test&lt;br /&gt;
| {{Green|Small}}: Consider variance in object test&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
&lt;br /&gt;
! Whole-system analysis&lt;br /&gt;
| {{Green|No}}&lt;br /&gt;
| {{Green|No}}&lt;br /&gt;
| {{Green|No}}&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
&lt;br /&gt;
! Dynamic class and type loading&lt;br /&gt;
| {{Green|Yes}}&lt;br /&gt;
| {{Green|Yes}}&lt;br /&gt;
| {{Green|Yes}}&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
&lt;br /&gt;
! Backward compatibility&lt;br /&gt;
| {{Orange|Limited}}: Use of generics changed due to conformance&lt;br /&gt;
| {{Red|Very limited}}: Libraries need redesign&lt;br /&gt;
| {{Orange|Limited}}: Use of generics changed due to conformance&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
&lt;br /&gt;
! Support of IDE (Source changes)&lt;br /&gt;
| {{Orange|Possible}}: Can propose variance marks&lt;br /&gt;
| {{Red|Not possible}}: Libraries need redesign&lt;br /&gt;
| {{Orange|Possible}}: Can propose variance marks/wildcards&lt;br /&gt;
&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Dynamic solutions ===&lt;br /&gt;
&lt;br /&gt;
{| border=1 cellpadding=2&lt;br /&gt;
&lt;br /&gt;
|- style=&amp;quot;visibility: hidden&amp;quot;&lt;br /&gt;
| style=&amp;quot;width:25%&amp;quot; |&lt;br /&gt;
| style=&amp;quot;width:25%&amp;quot; |&lt;br /&gt;
| style=&amp;quot;width:25%&amp;quot; |&lt;br /&gt;
| style=&amp;quot;width:25%&amp;quot; |&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
&lt;br /&gt;
! Criteria&lt;br /&gt;
! [[Detachable types]]&lt;br /&gt;
! Recast&lt;br /&gt;
! Exceptions&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
&lt;br /&gt;
! Syntax overhead&lt;br /&gt;
| {{Green|Small}}: Detachment marks&lt;br /&gt;
| {{Red|Big}}: Recast clauses, recast features&lt;br /&gt;
| {{Orange|Medium}}: If rescue clause mandatory&amp;lt;br/&amp;gt;{{Green|No}}: If rescue clause not needed&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
&lt;br /&gt;
! Covariance on non-generic types &lt;br /&gt;
| {{Red|Very limited}}: Only detached arguments, no expanded arguments&lt;br /&gt;
| {{Green|Allowed}}&lt;br /&gt;
| {{Green|Allowed}}&lt;br /&gt;
|-&lt;br /&gt;
&lt;br /&gt;
! Export status restrictions&lt;br /&gt;
| Not addressed&lt;br /&gt;
| Not addressed&lt;br /&gt;
| Not addressed&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
&lt;br /&gt;
! Use of generics&lt;br /&gt;
| {{Red|Very limited}}: Only detachable formal arguments&lt;br /&gt;
| {{Red|Very limited}}: Recast clause for all features with formal generics&lt;br /&gt;
| {{Green|As it is now}}&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
&lt;br /&gt;
! Agents&lt;br /&gt;
| {{Red|As it is now}} &lt;br /&gt;
| {{Red|As it is now}} &lt;br /&gt;
| {{Red|As it is now}} &lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
&lt;br /&gt;
! Comparator&lt;br /&gt;
| {{Red|Not supported}}&lt;br /&gt;
| {{Red|Not supported}}&lt;br /&gt;
| {{Red|Not supported}}&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
&lt;br /&gt;
! Complexity of compiler check&lt;br /&gt;
| {{Green|Small}}: As it is now&lt;br /&gt;
| {{Green|Small}}: As it is now&lt;br /&gt;
| {{Green|Small}}: As it is now&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
&lt;br /&gt;
! Complexity of runtime&lt;br /&gt;
| {{Green|Small}}: As it is now&lt;br /&gt;
| {{Orange|Medium}}: Check for catcalls and do recast&lt;br /&gt;
| {{Orange|Medium}}: Check for catcalls and raise exception&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
&lt;br /&gt;
! Whole-system analysis&lt;br /&gt;
| {{Green|No}}&lt;br /&gt;
| {{Green|No}}&lt;br /&gt;
| {{Green|No}}&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
&lt;br /&gt;
! Dynamic class and type loading&lt;br /&gt;
| {{Green|Yes}}&lt;br /&gt;
| {{Green|Yes}}&lt;br /&gt;
| {{Green|Yes}}&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
&lt;br /&gt;
! Backward compatibility&lt;br /&gt;
| {{Red|Very limited}}: All covariant and generic features become detached&lt;br /&gt;
| {{Red|Very limited}}: All covariant and generic features need recast clause&lt;br /&gt;
| {{Orange|Limited}}: If rescue clause is mandatory&amp;lt;br/&amp;gt;{{Green|Full}}: If rescue clause not needed&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
&lt;br /&gt;
! Support of IDE (Source changes)&lt;br /&gt;
| {{Orange|Possible}}: Can propose detachment marks&lt;br /&gt;
| {{Red|Not possible}}: Programmer must provide recast clause&lt;br /&gt;
| {{Red|Not possible}}: If rescue clause mandatory&amp;lt;br/&amp;gt;{{Green|Not needed}}: If rescue clause not needed&lt;br /&gt;
&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Table explained ===&lt;br /&gt;
&lt;br /&gt;
; Syntax overhead : {{Green|Small}} if a keyword/mark is needed per class/feature declaration; {{Orange|Medium}} if a keyword/mark is neede per type declaration; {{Red|Big}} if a clause is needed per type declaration.&lt;br /&gt;
; Use of generics : {{Green|As it is now}} if assignments are possible if generic parameters conform; {{Orange|Limited}} is some restrictions in the use or the conformance between generics exist; {{Red|Very limited}} a lot of restrictions in the use or the conformance between generics exist.&lt;br /&gt;
; Agents : {{Green|Fully supported}} if all safe assignments are allowed; {{Orange|Limited}} if not all safe assignments are allowed; {{Red|As it is now}} if unsafe assignments are still possible.&lt;br /&gt;
; Comparator : {{Green|Supported}} if for a comparator all safe assignments are permitted (i.e. contravariant assignments); {{Red|Not supported}} if only exact type or even (unsafe) subtypes can be assigned.&lt;br /&gt;
; Support of IDE (Source changes) : {{Green|Not needed}} if everything still works the same; {{Orange|Possible}} if the compiler can suggest clauses or marks; {{Red|Not possible}} if the programmer has to specify additional features/instructions.&lt;br /&gt;
&lt;br /&gt;
== Personal opinions ==&lt;br /&gt;
&lt;br /&gt;
[[Personal view about catcall solution]]&lt;/div&gt;</summary>
		<author><name>Juliant</name></author>	</entry>

	<entry>
		<id>https://dev.eiffel.com/index.php?title=Read-write_types&amp;diff=8956</id>
		<title>Read-write types</title>
		<link rel="alternate" type="text/html" href="https://dev.eiffel.com/index.php?title=Read-write_types&amp;diff=8956"/>
				<updated>2007-07-06T16:31:21Z</updated>
		
		<summary type="html">&lt;p&gt;Juliant: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Category:ECMA]]&lt;br /&gt;
[[Category:Catcall]]&lt;br /&gt;
{{Research}}&lt;br /&gt;
== Introduction ==&lt;br /&gt;
&lt;br /&gt;
The read-write proposal gives the programmer the possibility to specify per type declaration a ''read type'' and a ''write type''. The read type is used to specify applicable features and their return type (reading from the type). The write type is used to do the check on the feature signature for calling features (writing to the type).&lt;br /&gt;
&lt;br /&gt;
This solution is a superset of two other solutions: [[interval types]] (without the generic rule) and [[usage-site variance]]. Thus it is the more general mechanism than these two as it solves normal and generic types in the same way and can express the same and more than the other two solutions.&lt;br /&gt;
&lt;br /&gt;
It involves syntax overhead for complex problems which is due to the greater expressiveness. But with sensible default values it is as easy to use in the normal case as the other two solutions.&lt;br /&gt;
&lt;br /&gt;
== Syntax ==&lt;br /&gt;
&lt;br /&gt;
In order to express the read type and the write type, a type declaration is split into two parts. For the following discussion two keywords - '''read''' and '''write''' - are used.&lt;br /&gt;
&lt;br /&gt;
If either the read or the write type is omitted, a default behaviour is assumed which will be shown later on. A type can be declared in the following way:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;e&amp;gt;&lt;br /&gt;
a: ANY  -- Default semantics apply&lt;br /&gt;
b: read ANY write ANY &lt;br /&gt;
c: read LIST [read ANY write NONE] write NONE&lt;br /&gt;
d: read LIST [STRING] write NONE [STRING]&lt;br /&gt;
&amp;lt;/e&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The syntax is very similar to the interval types, just replace '''write''' with '''..''' and omit the '''read''' keyword. Then the only difference is the generic parameters in the write type which don't appear in the interval definition, especially the generic parameters for class NONE are a special notation.&lt;br /&gt;
&lt;br /&gt;
== Semantics ==&lt;br /&gt;
&lt;br /&gt;
The meaning of a read-write type &amp;lt;e&amp;gt;read A write B&amp;lt;/e&amp;gt; is the following: All features which are available are those of &amp;lt;e&amp;gt;A&amp;lt;/e&amp;gt; and all calls have to be valid with the signature of the type &amp;lt;e&amp;gt;B&amp;lt;/e&amp;gt;. If the write type is &amp;lt;e&amp;gt;NONE&amp;lt;/e&amp;gt;, then the call has to be system-valid for all descendants of the read type. This is essentially the same as interval types.&lt;br /&gt;
&lt;br /&gt;
The difference is, that the write type can be &amp;lt;e&amp;gt;NONE&amp;lt;/e&amp;gt; but still has generic parameters. This is needed to distinguish the covariantly redefined features from the formal features and apply different settings for these feature groups.&lt;br /&gt;
&lt;br /&gt;
If the read type has generic parameters, but the write type does not, then no features with formal arguments may be called. If the read type has generics and the write type has too, than the formal arguments for the signature are taken from the write type. This is the same as for covariantly redefined features where the signature is taken from the write type.&lt;br /&gt;
&lt;br /&gt;
Some examples:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;e&amp;gt;&lt;br /&gt;
local&lt;br /&gt;
  a: read ANY write NONE       -- features from ANY, whole-system analysis (polymorphic)&lt;br /&gt;
  b: read ANY write STRING     -- features from ANY, signature from STRING&lt;br /&gt;
  c: read STRING write STRING  -- features from STRING, signature from STRING (monomorphic)&lt;br /&gt;
    -- read-only list&lt;br /&gt;
  d: read LIST [read ANY write NONE] write NONE&lt;br /&gt;
    -- list with monomorphic STRING elements&lt;br /&gt;
  e: read LIST [read STRING write STRING] write NONE [read STRING write STRING]&lt;br /&gt;
do&lt;br /&gt;
  b.is_equal ({STRING})&lt;br /&gt;
  -- b.to_upper -- feature 'to_upper' is not in ANY&lt;br /&gt;
  c.is_equal ({STRING})&lt;br /&gt;
  c.to_upper&lt;br /&gt;
  d.item = {read ANY write NONE}&lt;br /&gt;
  -- d.put -- no generics in write type, thus no features with formal arguments&lt;br /&gt;
  e.item = {read STRING write STRING}&lt;br /&gt;
  e.put ({read STRING write STRING})&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/e&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Conformance rules ===&lt;br /&gt;
&lt;br /&gt;
* A read-write type &amp;lt;e&amp;gt;a&amp;lt;/e&amp;gt; conforms to a read-write type &amp;lt;e&amp;gt;b&amp;lt;/e&amp;gt; if the read type of &amp;lt;e&amp;gt;a&amp;lt;/e&amp;gt; conforms to the read type of &amp;lt;e&amp;gt;b&amp;lt;/e&amp;gt; and the write type of &amp;lt;e&amp;gt;b&amp;lt;/e&amp;gt; conforms to the write type of &amp;lt;e&amp;gt;a&amp;lt;/e&amp;gt;.&lt;br /&gt;
* The same goes for the generics part, the generics of the read type of &amp;lt;e&amp;gt;a&amp;lt;/e&amp;gt; have to conform to the generics of the read type of &amp;lt;e&amp;gt;a&amp;lt;/e&amp;gt; and the generics of the write type of &amp;lt;e&amp;gt;b&amp;lt;/e&amp;gt; have to conform to the generics of the write type of &amp;lt;e&amp;gt;a&amp;lt;/e&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Some examples:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;e&amp;gt;&lt;br /&gt;
local&lt;br /&gt;
  a: read ANY write NONE&lt;br /&gt;
  b: read ANY write STRING&lt;br /&gt;
  c: read STRING write STRING&lt;br /&gt;
  d: read LIST [read ANY write NONE] write NONE -- read-only list&lt;br /&gt;
  e: read LIST [read STRING write STRING] write NONE [read STRING write STRING]&lt;br /&gt;
  f: read LINKED_LIST [read ANY write NONE] write LINKED_LIST [read ANY write NONE]&lt;br /&gt;
do&lt;br /&gt;
    -- valid&lt;br /&gt;
  a := b&lt;br /&gt;
  a := c&lt;br /&gt;
  b := c&lt;br /&gt;
  d := e&lt;br /&gt;
  d := f&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/e&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Default behaviour ===&lt;br /&gt;
&lt;br /&gt;
Although this solution has some syntax overhead, the default behaviour gets rid of most of it. &lt;br /&gt;
&lt;br /&gt;
It is assumed here that &amp;lt;e&amp;gt;NONE&amp;lt;/e&amp;gt; also conforms to expanded types. See the [[Interval_types#Conclusion|conclusion of interval types]] for more information.&lt;br /&gt;
&lt;br /&gt;
The default for a normal type &amp;lt;e&amp;gt;X&amp;lt;/e&amp;gt; is a polymorphic type:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;e&amp;gt;&lt;br /&gt;
a: X  -- means 'read X write NONE'&lt;br /&gt;
&amp;lt;/e&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The default for a generic type is a read-write type which is polymorphic in the base class and invariant in the generic parameter:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;e&amp;gt;&lt;br /&gt;
b: X [Y] -- means 'read X [Y] write NONE [Y]'&lt;br /&gt;
&amp;lt;/e&amp;gt;&lt;br /&gt;
&lt;br /&gt;
And if you write the ''read'' type but omit the ''write'' type, then the write type is always &amp;lt;e&amp;gt;NONE&amp;lt;/e&amp;gt;. This is useful for generics as you can define a read-only type which is covariantly in the generic parameter:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;e&amp;gt;&lt;br /&gt;
c: read X     -- means 'read X write NONE', (the same as just 'X')&lt;br /&gt;
d: read X [Y] -- means 'read X [Y] write NONE'&lt;br /&gt;
&amp;lt;/e&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Thanks to these defaults, code which does not rely on generic conformance should work as before:&lt;br /&gt;
&lt;br /&gt;
By choosing these defaults, most code which does not rely on covariant generic conformance should work as before:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;e&amp;gt;&lt;br /&gt;
local&lt;br /&gt;
  any: ANY                  -- means 'read ANY write NONE'&lt;br /&gt;
  list: LIST [ANY]          -- means 'read LIST [read ANY write NONE] write NONE [read ANY write NONE]'&lt;br /&gt;
  l_list: LINKED_LIST [ANY] -- means 'read LINKED_LIST [read ANY write NONE] write NONE [read ANY write NONE]'&lt;br /&gt;
do&lt;br /&gt;
  any := &amp;quot;abc&amp;quot;&lt;br /&gt;
  any := 8&lt;br /&gt;
  list := l_list&lt;br /&gt;
  list.put (any)&lt;br /&gt;
  list.put (&amp;quot;abc&amp;quot;)&lt;br /&gt;
  any := list.item.out&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/e&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If you want to assign generics with different parameters, you need to mark the target as read-only by specifying the type only as a ''read'' type, i.e. &amp;lt;e&amp;gt;read LIST [ANY]&amp;lt;/e&amp;gt; if you want to assign any possible list.&lt;br /&gt;
&lt;br /&gt;
== Comparison with other solutions ==&lt;br /&gt;
&lt;br /&gt;
Interesting about this solution is that it two others can be mapped to it:&lt;br /&gt;
&lt;br /&gt;
=== [[Interval types]] ===&lt;br /&gt;
&lt;br /&gt;
For non-generic types, the read-write types are just like interval types:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;e&amp;gt;&lt;br /&gt;
a: ANY..NONE  &amp;lt;=&amp;gt;  read ANY write NONE&lt;br /&gt;
b: X..Y       &amp;lt;=&amp;gt;  read X write Y&lt;br /&gt;
&amp;lt;/e&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The conformance rules and the default behaviour is the same.&lt;br /&gt;
&lt;br /&gt;
=== [[Usage-site variance]] ===&lt;br /&gt;
&lt;br /&gt;
The usage-site variance can also be expressed by read-write types:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;e&amp;gt;&lt;br /&gt;
  -- invariant&lt;br /&gt;
a: LIST [ STRING]  &amp;lt;=&amp;gt; read LIST [STRING] write NONE [STRING]&lt;br /&gt;
  -- covariant&lt;br /&gt;
b: LIST [+STRING]  &amp;lt;=&amp;gt; read LIST [STRING] write NONE&lt;br /&gt;
  -- contravariant&lt;br /&gt;
c: LIST [-STRING]  &amp;lt;=&amp;gt; read LIST [ANY] write NONE [STRING]&lt;br /&gt;
&amp;lt;/e&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note that due to the default behaviour of read-write types, the invariant generics can be expressed the same in read-write types and that covariant generics can be defined as &amp;lt;e&amp;gt;read LIST [STRING]&amp;lt;/e&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== Examples ==&lt;br /&gt;
&lt;br /&gt;
See the [[introduction to examples]] for information about the classes used.&lt;br /&gt;
&lt;br /&gt;
For more examples, look at the examples section of [[interval types]] and [[usage-site variance]]. With the above mapping, all examples can easily be changed into read-write type examples.&lt;br /&gt;
&lt;br /&gt;
=== A simple generic algorithm ===&lt;br /&gt;
&lt;br /&gt;
It is easy to declare an algorithm over generics as long as only read-access is needed. Just declare input to the algorithm as read-only list.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;e&amp;gt;&lt;br /&gt;
class PERSON_PRINTER&lt;br /&gt;
feature&lt;br /&gt;
  print_all (a_list: read LIST [PERSON])&lt;br /&gt;
      -- Print all attributes of each person in the list.&lt;br /&gt;
    do&lt;br /&gt;
      from&lt;br /&gt;
        a_list.start&lt;br /&gt;
      until&lt;br /&gt;
        a_list.after&lt;br /&gt;
      do &lt;br /&gt;
          -- Reading is valid on a read-only list&lt;br /&gt;
        a_list.item.print&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
end&lt;br /&gt;
 &lt;br /&gt;
class EXAMPLE&lt;br /&gt;
feature&lt;br /&gt;
  make&lt;br /&gt;
    local&lt;br /&gt;
      l_students: LIST [STUDENT]&lt;br /&gt;
      l_professors: LIST [PROFESSOR]&lt;br /&gt;
      l_person_printer: PERSON_PRINTER&lt;br /&gt;
    do&lt;br /&gt;
      create l_person_printer&lt;br /&gt;
        -- LIST [STUDENT] conforms to read LIST [PERSON]&lt;br /&gt;
      l_person_printer.print_all (l_students)&lt;br /&gt;
        -- LIST [PROFESSPR] conforms to read LIST [PERSON]&lt;br /&gt;
      l_person_printer.print_all (l_professor)&lt;br /&gt;
    end&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/e&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Issues ==&lt;br /&gt;
&lt;br /&gt;
=== Keywords ===&lt;br /&gt;
&lt;br /&gt;
For this description, the keywords '''read''' and '''write''' were used. This can easily be changed. For example, to be more like the interval types the '''read''' keyword can be omitted and the '''write''' keyword replaced by two dots.&lt;br /&gt;
&lt;br /&gt;
=== Syntax overhead ===&lt;br /&gt;
&lt;br /&gt;
The read-write types can produce a considerable amount of syntax overhead. Thanks to the default behaviour and the shorthand for read-only types, the average situation requires only one keyword '''read''' from time to time. In general no annotation should be necessary at all.&lt;br /&gt;
&lt;br /&gt;
== Conclusion ==&lt;br /&gt;
&lt;br /&gt;
The read-write types are a powerful solution. It can handle non-generic and generic types in the same way but still allows to address features with formal arguments and other covariantly redefined features separately. Since both interval types and usage-site variance can be expressed through it, it has all the advantages of these and with sensible default values does not produce much syntax overhead in the general case.&lt;/div&gt;</summary>
		<author><name>Juliant</name></author>	</entry>

	<entry>
		<id>https://dev.eiffel.com/index.php?title=Interval_types_and_usage-site_variance&amp;diff=8950</id>
		<title>Interval types and usage-site variance</title>
		<link rel="alternate" type="text/html" href="https://dev.eiffel.com/index.php?title=Interval_types_and_usage-site_variance&amp;diff=8950"/>
				<updated>2007-07-06T03:00:55Z</updated>
		
		<summary type="html">&lt;p&gt;Juliant: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Category:ECMA]]&lt;br /&gt;
[[Category:Catcall]]&lt;br /&gt;
{{Research}}&lt;br /&gt;
== Introduction ==&lt;br /&gt;
&lt;br /&gt;
This is a proposition to combine two mechanisms to prevent catcalls, the [[interval types]] for non-generics and the [[usage-site variance]] for generics.&lt;br /&gt;
&lt;br /&gt;
The reason for this is that up to now all approaches failed to deliver an easy and concise solution to solve the problem of catcalls in general. &lt;br /&gt;
&lt;br /&gt;
Interval types work well for non-generic types and the overhead for the type declaration is minimal with a sensitive default behaviour, but for generics it does not really work.&lt;br /&gt;
&lt;br /&gt;
Usage-site variance is a promising solution for generics with just the small addition of a flag for the kind of variance needed on a generic derivation. And again, the default behaviour will allow most uses of a generic type as the programmer expects it to work.&lt;br /&gt;
&lt;br /&gt;
== Syntax ==&lt;br /&gt;
&lt;br /&gt;
Types can be specified as an interval:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;e&amp;gt;LOWER..UPPER&amp;lt;/e&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Generic parameters can be marked to select the variance:&lt;br /&gt;
&lt;br /&gt;
* To specify a novariant generic, the normal syntax can be used: &amp;lt;e&amp;gt;LIST [ANY]&amp;lt;/e&amp;gt;&lt;br /&gt;
* To specify a covariant generic, we use a plus sign: &amp;lt;e&amp;gt;LIST [+ANY]&amp;lt;/e&amp;gt;&lt;br /&gt;
* To specify a contravariant generic, we use a minus sign: &amp;lt;e&amp;gt;LIST [-ANY]&amp;lt;/e&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Semantics ==&lt;br /&gt;
&lt;br /&gt;
Each interval type describes the set of types which belong to the interval. A type belongs to the interval if it conforms to the lower bound (&amp;lt;e&amp;gt;LOWER&amp;lt;/e&amp;gt;) and if the upper bound (&amp;lt;e&amp;gt;UPPER&amp;lt;/e&amp;gt;) conforms to it. All feature calls will be subject to whole-system validity and by restricting the dynamic type set to the types in the interval this check can be influenced.&lt;br /&gt;
&lt;br /&gt;
For generics the applicable features depend on the variance mark used:&lt;br /&gt;
&lt;br /&gt;
* On a novariant generic, all features can be used.&lt;br /&gt;
* On a covariant generic, only features which have the formal generic as a result type can be used. If the formal generic appears in an argument this feature is invalid.&lt;br /&gt;
* On a contravariant generic, only feature which have the formal generic as an argument type can be used. If the formal generic appears as a result type this feature is invalid.&lt;br /&gt;
&lt;br /&gt;
The two mechanisms can also be combined. A generic parameter can be an interval type and can also have a variance modifier. The normal generic substitution applies to every formal generic by replacing the generic with the interval type. The variance marks are only used for conformance checks and don't affect the generic substitution.&lt;br /&gt;
&lt;br /&gt;
=== Conformance rules ===&lt;br /&gt;
&lt;br /&gt;
A type &amp;lt;e&amp;gt;b: C..D&amp;lt;/e&amp;gt; conforms to the type &amp;lt;e&amp;gt;a: A..B&amp;lt;/e&amp;gt; if &amp;lt;e&amp;gt;C&amp;lt;/e&amp;gt; conforms to &amp;lt;e&amp;gt;A&amp;lt;/e&amp;gt; and &amp;lt;e&amp;gt;B&amp;lt;/e&amp;gt; conforms to &amp;lt;e&amp;gt;D&amp;lt;/e&amp;gt;. The conformance rules for generics differ depending on the variance mark:&lt;br /&gt;
&lt;br /&gt;
* A generic conforms to a novariant generic if it has the exact same generic parameter. Thus &amp;lt;e&amp;gt;LIST [T]&amp;lt;/e&amp;gt; only conforms to &amp;lt;e&amp;gt;LIST [T]&amp;lt;/e&amp;gt;.&lt;br /&gt;
* A generic conforms to a covariant generic if its generic parameter conforms to the generic parameter of the covariant generic. Thus &amp;lt;e&amp;gt;LIST [U]&amp;lt;/e&amp;gt; conforms to &amp;lt;e&amp;gt;LIST [+T]&amp;lt;/e&amp;gt;.&lt;br /&gt;
* A generic conforms to a contravariant generic if its generic parameter is a parent of the generic parameter of the contravariant generic. Thus &amp;lt;e&amp;gt;LIST [T]&amp;lt;/e&amp;gt; conforms to &amp;lt;e&amp;gt;LIST [-U]&amp;lt;/e&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Default behaviour ===&lt;br /&gt;
&lt;br /&gt;
The default for a type declaration is that the interval contains the type up to &amp;lt;e&amp;gt;NONE&amp;lt;/e&amp;gt; (note that it is assumed that &amp;lt;e&amp;gt;NONE&amp;lt;/e&amp;gt; also conforms to expanded types. See the [[Interval_types#Conclusion|conclusion of interval types]] for more information.):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;e&amp;gt;&lt;br /&gt;
a: ANY  -- means ANY..NONE&lt;br /&gt;
&amp;lt;/e&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This allows that in the default case all descendants of a type can be assigned.&lt;br /&gt;
&lt;br /&gt;
The default for generic arguments is novariance. This allows that all features can be called on a generic without restrictions.&lt;br /&gt;
&lt;br /&gt;
By choosing these defaults, most code which does not rely on covariant generic conformance should work as before:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;e&amp;gt;&lt;br /&gt;
local&lt;br /&gt;
  any: ANY                  -- means ANY..NONE&lt;br /&gt;
  list: LIST [ANY]          -- means LIST [ANY..NONE] .. NONE&lt;br /&gt;
  l_list: LINKED_LIST [ANY] -- means LINKED_LIST [ANY..NONE] .. NONE&lt;br /&gt;
do&lt;br /&gt;
  any := &amp;quot;abc&amp;quot;&lt;br /&gt;
  any := 8&lt;br /&gt;
  list := l_list&lt;br /&gt;
  list.put (any)&lt;br /&gt;
  list.put (&amp;quot;abc&amp;quot;)&lt;br /&gt;
  any := list.item.out&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/e&amp;gt;&lt;br /&gt;
&lt;br /&gt;
What won't work as before is conformance of generics. The generic parameter of the target type will have to be marked as covariant, thus the features which have formal arguments cannot be called anymore.&lt;br /&gt;
&lt;br /&gt;
== Examples ==&lt;br /&gt;
&lt;br /&gt;
See the [[introduction to examples]] for information about the classes used.&lt;br /&gt;
&lt;br /&gt;
=== Combining the mechanisms ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;e&amp;gt;&lt;br /&gt;
local&lt;br /&gt;
  dog: DOG        -- means DOG..NONE&lt;br /&gt;
  cat: CAT        -- means CAT..NONE&lt;br /&gt;
  animal: ANIMAL  -- means ANIMAL..NONE&lt;br /&gt;
  animal_list: LIST [ANIMAL]  -- means LIST [ANIMAL..NONE] .. NONE&lt;br /&gt;
  animal_dog_list: LIST [ANIMAL..DOG]&lt;br /&gt;
  read_any_list: LIST [+ANY]  -- means LIST [+ ANY..NONE] .. NONE&lt;br /&gt;
do&lt;br /&gt;
    -- valid&lt;br /&gt;
  dog.eat (food)&lt;br /&gt;
  cat.eat (cat_food)&lt;br /&gt;
  animal.eat (cat_food)&lt;br /&gt;
&lt;br /&gt;
    -- invalid&lt;br /&gt;
  animal.eat (food) -- could be a CAT&lt;br /&gt;
&lt;br /&gt;
    -- valid&lt;br /&gt;
  animal_list.put (dog)&lt;br /&gt;
  animal_list.put (cat)&lt;br /&gt;
  animal_list.eat (cat_food)&lt;br /&gt;
  animal_dog_list.eat (food)&lt;br /&gt;
  read_any_list := animal_list&lt;br /&gt;
&lt;br /&gt;
    -- invalid&lt;br /&gt;
  read_any_list.put (&amp;quot;abc&amp;quot;)   -- contravariant list&lt;br /&gt;
  animal_list.item.eat (food) -- could be a CAT&lt;br /&gt;
&lt;br /&gt;
    -- types&lt;br /&gt;
  animal_list.item = {ANIMAL..NONE}&lt;br /&gt;
  animal_dog_list.item = {ANIMAL..DOG}&lt;br /&gt;
  read_any_list.item = {ANY..NONE}&lt;br /&gt;
&lt;br /&gt;
  animal_dog_list.put ({ANIMAL..DOG})  &lt;br /&gt;
  animal_list.put ({ANIMAL..NONE})&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/e&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Cats and dogs ===&lt;br /&gt;
&lt;br /&gt;
See the [[Interval_types#Cats_and_dogs|interval types]] example.&lt;br /&gt;
&lt;br /&gt;
=== A simple generic algorithm ===&lt;br /&gt;
&lt;br /&gt;
See the [[Usage-site_variance#A_simple_generic_algorithm|usage-site variance]] example.&lt;/div&gt;</summary>
		<author><name>Juliant</name></author>	</entry>

	<entry>
		<id>https://dev.eiffel.com/index.php?title=Interval_types&amp;diff=8949</id>
		<title>Interval types</title>
		<link rel="alternate" type="text/html" href="https://dev.eiffel.com/index.php?title=Interval_types&amp;diff=8949"/>
				<updated>2007-07-06T03:00:09Z</updated>
		
		<summary type="html">&lt;p&gt;Juliant: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Category:ECMA]]&lt;br /&gt;
[[Category:Catcall]]&lt;br /&gt;
{{Research}}&lt;br /&gt;
== Introduction ==&lt;br /&gt;
&lt;br /&gt;
With interval types, the programmer can restrict the conforming types for an entity. This way, the type set which needs to be checked for system validity of a feature call is restricted to a smaller set of types. In addition, certain rules for generic types will prohibit the unsafe use of generics.&lt;br /&gt;
&lt;br /&gt;
== Syntax ==&lt;br /&gt;
&lt;br /&gt;
At every location where a normal type is expected, an interval type can be specified by adding an upper bound for each type:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;e&amp;gt;&lt;br /&gt;
LOWER..UPPER&lt;br /&gt;
&amp;lt;/e&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This specifies an interval of all types between the types &amp;lt;e&amp;gt;LOWER&amp;lt;/e&amp;gt; and &amp;lt;e&amp;gt;UPPER&amp;lt;/e&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== Semantics ==&lt;br /&gt;
&lt;br /&gt;
The intention of an interval type is to specify that an entity can only be attached to a type which lies inside the interval. Thus a type declared as &amp;lt;e&amp;gt;ANY..STRING&amp;lt;/e&amp;gt; can be attached to an object of dynamic type &amp;lt;e&amp;gt;ANY&amp;lt;/e&amp;gt; or dynamic type &amp;lt;e&amp;gt;STRING&amp;lt;/e&amp;gt;. It cannot be attached to an object of a type which lies outside this interval, for example &amp;lt;e&amp;gt;INTEGER&amp;lt;/e&amp;gt; or &amp;lt;e&amp;gt;PATH_NAME&amp;lt;/e&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Each interval type describes the set of types which belong to the interval. A type belongs to the interval if it conforms to the lower bound (&amp;lt;e&amp;gt;LOWER&amp;lt;/e&amp;gt;) and if the upper bound (&amp;lt;e&amp;gt;UPPER&amp;lt;/e&amp;gt;) conforms to it.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;e&amp;gt;&lt;br /&gt;
a: A .. C &amp;lt;=&amp;gt; {A, B, C}&lt;br /&gt;
b: A .. B &amp;lt;=&amp;gt; {A, B}&lt;br /&gt;
c: A .. NONE &amp;lt;=&amp;gt; {A, B, C, ...}&lt;br /&gt;
&amp;lt;/e&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Conformance rules ===&lt;br /&gt;
&lt;br /&gt;
An interval type ''b'' conforms to an interval type ''a'' if it is a sub-interval of ''a''. So if ''a'' fully encloses the interval ''b'', ''b'' conforms to ''a''.&lt;br /&gt;
&lt;br /&gt;
The conformance rules can also be explained by differently:&lt;br /&gt;
&lt;br /&gt;
* An interval type ''b'' conforms to an interval type ''a'' if the set of types described by the interval of ''b'' is a subset of the set described by the interval of ''a''.&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;e&amp;gt;&lt;br /&gt;
a := b -- Is valid as {A, B} is a subset of {A, B, C}&lt;br /&gt;
&amp;lt;/e&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* A type &amp;lt;e&amp;gt;b: C..D&amp;lt;/e&amp;gt; conforms to the type &amp;lt;e&amp;gt;a: A..B&amp;lt;/e&amp;gt; if &amp;lt;e&amp;gt;C&amp;lt;/e&amp;gt; conforms to &amp;lt;e&amp;gt;A&amp;lt;/e&amp;gt; and &amp;lt;e&amp;gt;B&amp;lt;/e&amp;gt; conforms to &amp;lt;e&amp;gt;D&amp;lt;/e&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Generic conformance is the same as it is now: A generic type ''b'' conforms to a generic type ''a'' if the base class of ''b'' conforms to ''a'' and all generic parameters conform as well.&lt;br /&gt;
&lt;br /&gt;
=== Generic features ===&lt;br /&gt;
&lt;br /&gt;
For features with formal arguments, another rule exists: A call on a feature which contains a formal argument is only valid if the generic substitution is monomorphic.&lt;br /&gt;
&lt;br /&gt;
This means that a call on a feature &amp;lt;e&amp;gt;f (g: G)&amp;lt;/e&amp;gt; of a class &amp;lt;e&amp;gt;X [G]&amp;lt;/e&amp;gt; is only valid if &amp;lt;e&amp;gt;G&amp;lt;/e&amp;gt; is monomorphic. Thus the type has to be instantiated with &amp;lt;e&amp;gt;X [Y..Y]&amp;lt;/e&amp;gt;. So a call to &amp;lt;e&amp;gt;f&amp;lt;/e&amp;gt; on a type &amp;lt;e&amp;gt;X [Y..NONE]&amp;lt;/e&amp;gt; is not allowed.&lt;br /&gt;
&lt;br /&gt;
=== Default behaviour ===&lt;br /&gt;
&lt;br /&gt;
As a shorthand for interval definition, we define the following default behaviour which is different for ordinary types and for actual generic type parameters. Ordinary types are per default polymorphic and actual formal parameters monomorphic:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;e&amp;gt;&lt;br /&gt;
x: T &amp;lt;=&amp;gt; T .. NONE&lt;br /&gt;
y: A [T] &amp;lt;=&amp;gt; A [T .. T] .. NONE&lt;br /&gt;
&amp;lt;/e&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Examples ==&lt;br /&gt;
&lt;br /&gt;
See the [[introduction to examples]] for information about the classes used.&lt;br /&gt;
&lt;br /&gt;
=== Cats and dogs ===&lt;br /&gt;
&lt;br /&gt;
A feature call on a target ''t'' is only valid if it is valid for all polymorphic types which can possibly be assigned to ''t''. With interval types the set of conforming types can be restricted in order to be able to perform calls to features which are covariantly redefined in descendants by excluding such descendants from the dynamic type set. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;e&amp;gt;&lt;br /&gt;
a_none: ANIMAL &amp;lt;=&amp;gt; ANIMAL .. NONE&lt;br /&gt;
c_none: CAT &amp;lt;=&amp;gt; ANIMAL .. NONE&lt;br /&gt;
d_none: DOG &amp;lt;=&amp;gt; ANIMAL .. NONE&lt;br /&gt;
a_a: ANIMAL .. ANIMAL&lt;br /&gt;
c_c: CAT .. CAT&lt;br /&gt;
d_d: DOG .. DOG&lt;br /&gt;
a_c: ANIMAL .. CAT&lt;br /&gt;
a_d: ANIMAL .. DOG&lt;br /&gt;
&amp;lt;/e&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Valid assignments:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;e&amp;gt;&lt;br /&gt;
a_none := c_none&lt;br /&gt;
a_none := d_none&lt;br /&gt;
a_none := a_a&lt;br /&gt;
a_none := c_c&lt;br /&gt;
a_none := d_d&lt;br /&gt;
c_none := c_c&lt;br /&gt;
d_none := d_d&lt;br /&gt;
&lt;br /&gt;
a_c := a_a&lt;br /&gt;
a_c := c_c&lt;br /&gt;
a_d := a_a&lt;br /&gt;
a_d := d_d&lt;br /&gt;
&amp;lt;/e&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Invalid assignments:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;e&amp;gt;&lt;br /&gt;
-- Invalid: a_a := a_none&lt;br /&gt;
-- Invalid: c_c := c_none&lt;br /&gt;
-- Invalid: d_d := d_none&lt;br /&gt;
-- Invalid: a_c := c_none&lt;br /&gt;
-- Invalid: a_d := d_none&lt;br /&gt;
&amp;lt;/e&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Valid calls:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;e&amp;gt;&lt;br /&gt;
a_none.eat (cat_food)&lt;br /&gt;
a_a.eat (food)&lt;br /&gt;
a_d.eat (food)&lt;br /&gt;
&amp;lt;/e&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Invalid calls:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;e&amp;gt;&lt;br /&gt;
a_none.eat (food)&lt;br /&gt;
&amp;lt;/e&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== A simple generic algorithm ===&lt;br /&gt;
&lt;br /&gt;
It is easy to declare an algorithm which needs only read-access on a list:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;e&amp;gt;&lt;br /&gt;
class PERSON_PRINTER&lt;br /&gt;
feature&lt;br /&gt;
  print_all (a_list: LIST [PERSON..NONE])&lt;br /&gt;
      -- Print all attributes of each person in the list.&lt;br /&gt;
    do&lt;br /&gt;
      from&lt;br /&gt;
        a_list.start&lt;br /&gt;
      until&lt;br /&gt;
        a_list.after&lt;br /&gt;
      do &lt;br /&gt;
          -- Reading is valid on a covariant list&lt;br /&gt;
        a_list.item.print&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
end&lt;br /&gt;
 &lt;br /&gt;
class EXAMPLE&lt;br /&gt;
feature&lt;br /&gt;
  make&lt;br /&gt;
    local&lt;br /&gt;
      l_students: LIST [STUDENT]       &amp;lt;=&amp;gt; LIST [STUDENT..STUDENT]&lt;br /&gt;
      l_professors: LIST [PROFESSOR]   &amp;lt;=&amp;gt; LIST [PROFESSOR..PROFESSOR]&lt;br /&gt;
      l_person_printer: PERSON_PRINTER&lt;br /&gt;
    do&lt;br /&gt;
      create l_person_printer&lt;br /&gt;
        -- LIST [STUDENT..STUDENT] conforms to LIST [PERSON..NONE]&lt;br /&gt;
      l_person_printer.print_all (l_students)&lt;br /&gt;
        -- LIST [PROFESSOR..PROFESSOR] conforms to LIST [PERSON..NONE]&lt;br /&gt;
      l_person_printer.print_all (l_professor)&lt;br /&gt;
    end&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/e&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Issues ==&lt;br /&gt;
&lt;br /&gt;
=== Generic features ===&lt;br /&gt;
&lt;br /&gt;
The rule about calling features with formal parameters is too restrictive. Let's look at the following code:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;e&amp;gt;&lt;br /&gt;
deferred class COMPONENT&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
class COMPOSITE&lt;br /&gt;
inherit COMPONENT&lt;br /&gt;
feature&lt;br /&gt;
  components: LIST [COMPONENT]&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/e&amp;gt;&lt;br /&gt;
&lt;br /&gt;
What should the type of feature &amp;lt;e&amp;gt;components&amp;lt;/e&amp;gt; be? In order to be able to call &amp;lt;e&amp;gt;extend&amp;lt;/e&amp;gt; on the list, it has to be monomorphic, thus &amp;lt;e&amp;gt;LIST [COMPONENT..COMPONENT]&amp;lt;/e&amp;gt;. But since the argument type is now &amp;lt;e&amp;gt;COMPONENT..COMPONENT&amp;lt;/e&amp;gt; we actually cannot add anything to the list as no descendant of &amp;lt;e&amp;gt;COMPONENT&amp;lt;/e&amp;gt; is in the interval. Actually, since &amp;lt;e&amp;gt;COMPONENT&amp;lt;/e&amp;gt; is deferred nothing can be added to the list at all.&lt;br /&gt;
&lt;br /&gt;
But if we define the list as &amp;lt;e&amp;gt;LIST [COMPONENT..NONE]&amp;lt;/e&amp;gt; - thus allowing descendants of &amp;lt;e&amp;gt;COMPONENT&amp;lt;/e&amp;gt; in the list - then the rule about features with formal arguments disallows any calls to feature &amp;lt;e&amp;gt;extend&amp;lt;/e&amp;gt; as the argument is not monomorphic anymore.&lt;br /&gt;
&lt;br /&gt;
=== Expanded and Void ===&lt;br /&gt;
&lt;br /&gt;
Look at the following code snippet:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;e&amp;gt;&lt;br /&gt;
local&lt;br /&gt;
  any_none: ANY..NONE&lt;br /&gt;
  any_string: ANY..STRING&lt;br /&gt;
do&lt;br /&gt;
    -- invalid as NONE does not conform to INTEGER&lt;br /&gt;
  any_none := 5&lt;br /&gt;
    -- invalid as NONE is not in the interval ANY..STRING&lt;br /&gt;
  any_string := Void&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/e&amp;gt;&lt;br /&gt;
&lt;br /&gt;
It illustrates two problems in conjunction with &amp;lt;e&amp;gt;NONE&amp;lt;/e&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
* The first is that &amp;lt;e&amp;gt;NONE&amp;lt;/e&amp;gt; does not conform to expanded types. This makes it impossible to declare a type interval which includes all types in the system, reference or expanded. This prevents the programmer to write code which works with reference types and expanded types, say a generic print algorithm.&lt;br /&gt;
* The second one is that &amp;lt;e&amp;gt;Void&amp;lt;/e&amp;gt; is of type &amp;lt;e&amp;gt;NONE&amp;lt;/e&amp;gt;. This raises the question how &amp;lt;e&amp;gt;Void&amp;lt;/e&amp;gt; should be assigned to an interval type of references, or how such a type is initialized in the first place.&lt;br /&gt;
&lt;br /&gt;
== Conclusion ==&lt;br /&gt;
&lt;br /&gt;
The rule about features with formal parameters must be changed to make this solution usable as otherwise the use of generics is restricted too much.&lt;br /&gt;
&lt;br /&gt;
The problem with &amp;lt;e&amp;gt;Void&amp;lt;/e&amp;gt; and &amp;lt;e&amp;gt;NONE&amp;lt;/e&amp;gt; can easily be solved by declaring that &amp;lt;e&amp;gt;NONE&amp;lt;/e&amp;gt; inherits from all types regardless of reference or expanded status. To solve the problem of assigning &amp;lt;e&amp;gt;Void&amp;lt;/e&amp;gt; to an interval type it can be defined that &amp;lt;e&amp;gt;Void&amp;lt;/e&amp;gt; is of any (detached) reference type. You could for example say that &amp;lt;e&amp;gt;Void&amp;lt;/e&amp;gt; always has the type of the lower bound of the target interval if this type is a (detached) reference type. That way it can be assigned to any interval of a reference type, even a monomorphic one, and it is still disallowed to assign it to expanded types.&lt;/div&gt;</summary>
		<author><name>Juliant</name></author>	</entry>

	<entry>
		<id>https://dev.eiffel.com/index.php?title=Interval_types_and_usage-site_variance&amp;diff=8948</id>
		<title>Interval types and usage-site variance</title>
		<link rel="alternate" type="text/html" href="https://dev.eiffel.com/index.php?title=Interval_types_and_usage-site_variance&amp;diff=8948"/>
				<updated>2007-07-06T02:58:18Z</updated>
		
		<summary type="html">&lt;p&gt;Juliant: /* Combining the mechanisms */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Category:ECMA]]&lt;br /&gt;
[[Category:Catcall]]&lt;br /&gt;
{{Research}}&lt;br /&gt;
== Introduction ==&lt;br /&gt;
&lt;br /&gt;
This is a proposition to combine two mechanisms to prevent catcalls, the [[interval types]] for non-generics and the [[usage-site variance]] for generics.&lt;br /&gt;
&lt;br /&gt;
The reason for this is that up to now all approaches failed to deliver an easy and concise solution to solve the problem of catcalls in general. &lt;br /&gt;
&lt;br /&gt;
Interval types work well for non-generic types and the overhead for the type declaration is minimal with a sensitive default behaviour, but for generics it does not really work.&lt;br /&gt;
&lt;br /&gt;
Usage-site variance is a promising solution for generics with just the small addition of a flag for the kind of variance needed on a generic derivation. And again, the default behaviour will allow most uses of a generic type as the programmer expects it to work.&lt;br /&gt;
&lt;br /&gt;
== Syntax ==&lt;br /&gt;
&lt;br /&gt;
Types can be specified as an interval:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;e&amp;gt;LOWER..UPPER&amp;lt;/e&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Generic parameters can be marked to select the variance:&lt;br /&gt;
&lt;br /&gt;
* To specify a novariant generic, the normal syntax can be used: &amp;lt;e&amp;gt;LIST [ANY]&amp;lt;/e&amp;gt;&lt;br /&gt;
* To specify a covariant generic, we use a plus sign: &amp;lt;e&amp;gt;LIST [+ANY]&amp;lt;/e&amp;gt;&lt;br /&gt;
* To specify a contravariant generic, we use a minus sign: &amp;lt;e&amp;gt;LIST [-ANY]&amp;lt;/e&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Semantics ==&lt;br /&gt;
&lt;br /&gt;
Each interval type describes the set of types which belong to the interval. A type belongs to the inverval if it conforms to the lower bound (&amp;lt;e&amp;gt;LOWER&amp;lt;/e&amp;gt;) and if the upper bound (&amp;lt;e&amp;gt;UPPER&amp;lt;/e&amp;gt;) conforms to it. All feature calls will be subject to whole-system validity and by restricting the dynamic type set to the types in the interval this check can be influenced.&lt;br /&gt;
&lt;br /&gt;
For generics the applicable features depend on the variance mark used:&lt;br /&gt;
&lt;br /&gt;
* On a novariant generic, all features can be used.&lt;br /&gt;
* On a covariant generic, only features which have the formal generic as a result type can be used. If the formal generic appears in an argument this feature is invalid.&lt;br /&gt;
* On a contravariant generic, only feature which have the formal generc as an argument type can be used. If the formal generic appears as a result type this feature is invalid.&lt;br /&gt;
&lt;br /&gt;
The two mechanisms can also be combined. A generic parameter can be an interval type and can also have a variance modifier. The normal generic substituion applies to every formal generic by replacing the generic with the interval type. The variance marks are only used for conformance checks and don't affect the generic substitution.&lt;br /&gt;
&lt;br /&gt;
=== Conformance rules ===&lt;br /&gt;
&lt;br /&gt;
A type &amp;lt;e&amp;gt;b: C..D&amp;lt;/e&amp;gt; conforms to the type &amp;lt;e&amp;gt;a: A..B&amp;lt;/e&amp;gt; if &amp;lt;e&amp;gt;C&amp;lt;/e&amp;gt; conforms to &amp;lt;e&amp;gt;A&amp;lt;/e&amp;gt; and &amp;lt;e&amp;gt;B&amp;lt;/e&amp;gt; conforms to &amp;lt;e&amp;gt;D&amp;lt;/e&amp;gt;. The conformance rules for generics differ depending on the variance mark:&lt;br /&gt;
&lt;br /&gt;
* A generic conforms to a novariant generic if it has the exact same generic parameter. Thus &amp;lt;e&amp;gt;LIST [T]&amp;lt;/e&amp;gt; only conforms to &amp;lt;e&amp;gt;LIST [T]&amp;lt;/e&amp;gt;.&lt;br /&gt;
* A generic conforms to a covariant generic if its generic parameter conforms to the generic parameter of the covariant generic. Thus &amp;lt;e&amp;gt;LIST [U]&amp;lt;/e&amp;gt; conforms to &amp;lt;e&amp;gt;LIST [+T]&amp;lt;/e&amp;gt;.&lt;br /&gt;
* A generic conforms to a contravariant generic if its generic parameter is a parent of the generic parameter of the contravariant generic. Thus &amp;lt;e&amp;gt;LIST [T]&amp;lt;/e&amp;gt; conforms to &amp;lt;e&amp;gt;LIST [-U]&amp;lt;/e&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Default behaviour ===&lt;br /&gt;
&lt;br /&gt;
The default for a type declaration is that the interval contains the type up to &amp;lt;e&amp;gt;NONE&amp;lt;/e&amp;gt; (note that it is assumed that &amp;lt;e&amp;gt;NONE&amp;lt;/e&amp;gt; also conforms to expanded types. See the [[Interval_types#Conclusion|conclusion of interval types]] for more information.):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;e&amp;gt;&lt;br /&gt;
a: ANY  -- means ANY..NONE&lt;br /&gt;
&amp;lt;/e&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This allows that in the default case all descendants of a type can be assigned.&lt;br /&gt;
&lt;br /&gt;
The default for generic arguments is novariance. This allows that all features can be called on a generic without restrictions.&lt;br /&gt;
&lt;br /&gt;
By choosing these defaults, most code which does not rely on covariant generic conformance should work as before:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;e&amp;gt;&lt;br /&gt;
local&lt;br /&gt;
  any: ANY                  -- means ANY..NONE&lt;br /&gt;
  list: LIST [ANY]          -- means LIST [ANY..NONE] .. NONE&lt;br /&gt;
  l_list: LINKED_LIST [ANY] -- means LINKED_LIST [ANY..NONE] .. NONE&lt;br /&gt;
do&lt;br /&gt;
  any := &amp;quot;abc&amp;quot;&lt;br /&gt;
  any := 8&lt;br /&gt;
  list := l_list&lt;br /&gt;
  list.put (any)&lt;br /&gt;
  list.put (&amp;quot;abc&amp;quot;)&lt;br /&gt;
  any := list.item.out&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/e&amp;gt;&lt;br /&gt;
&lt;br /&gt;
What won't work as before is conformance of generics. The generic parameter of the target type will have to be marked as covariant, thus the features which have formal arguments cannot be called anymore.&lt;br /&gt;
&lt;br /&gt;
== Examples ==&lt;br /&gt;
&lt;br /&gt;
See the [[introduction to examples]] for information about the classes used.&lt;br /&gt;
&lt;br /&gt;
=== Combining the mechanisms ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;e&amp;gt;&lt;br /&gt;
local&lt;br /&gt;
  dog: DOG        -- means DOG..NONE&lt;br /&gt;
  cat: CAT        -- means CAT..NONE&lt;br /&gt;
  animal: ANIMAL  -- means ANIMAL..NONE&lt;br /&gt;
  animal_list: LIST [ANIMAL]  -- means LIST [ANIMAL..NONE] .. NONE&lt;br /&gt;
  animal_dog_list: LIST [ANIMAL..DOG]&lt;br /&gt;
  read_any_list: LIST [+ANY]  -- means LIST [+ ANY..NONE] .. NONE&lt;br /&gt;
do&lt;br /&gt;
    -- valid&lt;br /&gt;
  dog.eat (food)&lt;br /&gt;
  cat.eat (cat_food)&lt;br /&gt;
  animal.eat (cat_food)&lt;br /&gt;
&lt;br /&gt;
    -- invalid&lt;br /&gt;
  animal.eat (food) -- could be a CAT&lt;br /&gt;
&lt;br /&gt;
    -- valid&lt;br /&gt;
  animal_list.put (dog)&lt;br /&gt;
  animal_list.put (cat)&lt;br /&gt;
  animal_list.eat (cat_food)&lt;br /&gt;
  animal_dog_list.eat (food)&lt;br /&gt;
  read_any_list := animal_list&lt;br /&gt;
&lt;br /&gt;
    -- invalid&lt;br /&gt;
  read_any_list.put (&amp;quot;abc&amp;quot;)   -- contravariant list&lt;br /&gt;
  animal_list.item.eat (food) -- could be a CAT&lt;br /&gt;
&lt;br /&gt;
    -- types&lt;br /&gt;
  animal_list.item = {ANIMAL..NONE}&lt;br /&gt;
  animal_dog_list.item = {ANIMAL..DOG}&lt;br /&gt;
  read_any_list.item = {ANY..NONE}&lt;br /&gt;
&lt;br /&gt;
  animal_dog_list.put ({ANIMAL..DOG})  &lt;br /&gt;
  animal_list.put ({ANIMAL..NONE})&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/e&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Cats and dogs ===&lt;br /&gt;
&lt;br /&gt;
See the [[Interval_types#Cats_and_dogs|interval types]] example.&lt;br /&gt;
&lt;br /&gt;
=== A simple generic algorithm ===&lt;br /&gt;
&lt;br /&gt;
See the [[Usage-site_variance#A_simple_generic_algorithm|usage-site variance]] example.&lt;/div&gt;</summary>
		<author><name>Juliant</name></author>	</entry>

	<entry>
		<id>https://dev.eiffel.com/index.php?title=Comparison_of_catcall_solutions&amp;diff=8947</id>
		<title>Comparison of catcall solutions</title>
		<link rel="alternate" type="text/html" href="https://dev.eiffel.com/index.php?title=Comparison_of_catcall_solutions&amp;diff=8947"/>
				<updated>2007-07-06T02:55:42Z</updated>
		
		<summary type="html">&lt;p&gt;Juliant: /* Overview of general solutions */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Category:ECMA]]&lt;br /&gt;
[[Category:Catcall]]&lt;br /&gt;
== Motivation ==&lt;br /&gt;
&lt;br /&gt;
By allowing covariant feature redefinition and hiding of features, the Eiffel language introduces the problem of catcalls (Changed Availability or Type). Currently the ECMA Eiffel standard does not specify how the occurrence of catcalls should be statically rejected.&lt;br /&gt;
&lt;br /&gt;
The purpose of this document is to show a comparison between different proposals on how to handle the issue of preventing catcalls.&lt;br /&gt;
&lt;br /&gt;
== Criteria for a solution ==&lt;br /&gt;
&lt;br /&gt;
To be able to judge a solution we use the following criteria which we consider as important:&lt;br /&gt;
&lt;br /&gt;
; Syntax overhead : How much syntax will be added to the language in order to express safe covariance and generics?&lt;br /&gt;
; Covariance on non-generic types : Are covariant argument redefinitions addressed in the solution? How does the programmer express it?&lt;br /&gt;
; Export status restrictions : Is restriction of export status addressed in the solution? How does the programmer express it?&lt;br /&gt;
; Use of generic types : How is conformance of generics? Are catcalls for generics addressed in the solution? How does the programmer express it? Can generics be used as now or are there restrictions?&lt;br /&gt;
:; Agents : Can agents be modeled with the solution while being type safe and expressive?&lt;br /&gt;
:; Comparator : Can comparator types be modeled with the solution while being type safe and expressive?&lt;br /&gt;
; Complexity of the compiler check : Is it just a matter of doing one check or several?&lt;br /&gt;
; Complexity of the runtime : Does the runtime need more information to do assignment attempts or object tests?&lt;br /&gt;
; Whole-system analysis : Is a whole-system analysis necessary?&lt;br /&gt;
; Dynamic class and type loading : Is it safe to dynamically load new classes at runtime and instantiate new types?&lt;br /&gt;
; Backward compatibility : Is the solution backward compatible to existing source code?&lt;br /&gt;
:; Applicable per cluster : Can the solution be applied on a per cluster basis?&lt;br /&gt;
; Support of compiler/IDE : Can the compiler/IDE help in updating existing source code? How?&lt;br /&gt;
&lt;br /&gt;
== General remarks ==&lt;br /&gt;
&lt;br /&gt;
=== Checking feature calls ===&lt;br /&gt;
&lt;br /&gt;
As the ''Single-level Call rule'' (8.25.3, VUSC) describes, a feature call is only valid if it is valid for every type in the dynamic type set. A simple solution would be that every feature call has to be checked for all possible descendants of the static target type. If this check is performed on a system, it will catch all catcalls - but also report false positives.&lt;br /&gt;
&lt;br /&gt;
Some of the proposed solutions try to address this problem by finding a better approximation to the dynamic type set so that the false positives can be ruled out.&lt;br /&gt;
&lt;br /&gt;
In general this is problematic as it requires a whole-system analysis, thus preventing the dynamic loading of new classes at run-time. The reason for this is that it is not known at compile time which features will be covariantly redefined by dynamically loaded classes.&lt;br /&gt;
&lt;br /&gt;
This is only the case with non-generic types. For generics, it is known at compile time that all features containing a formal in the parameter list can be treated as covariantly redefined and corresponding precautions can be implemented via the type system and conformance rules which allow to load even generic types at run-time.&lt;br /&gt;
&lt;br /&gt;
By the way, Eiffel Software has started to [[Single level call rule implementation|implement the basis of the ''single-level call rule'']] in it's Eiffel compiler. It is work in progress which revealed some implementation problems.&lt;br /&gt;
&lt;br /&gt;
=== Generic vs. non-generic covariance ===&lt;br /&gt;
&lt;br /&gt;
We can distinguish two different kinds of covariant argument redefinition:&lt;br /&gt;
&lt;br /&gt;
* When a generic type is derived, the formal generic parameters will be replaced by the actual generic parameters. Given the current conformance rules for generics, this can be seen as a covariant redefinition for all features which contain a formal generic as an argument. A simple example is the change from &amp;lt;e&amp;gt;LIST [ANY]&amp;lt;/e&amp;gt; to &amp;lt;e&amp;gt;LIST [INTEGER]&amp;lt;/e&amp;gt; where the feature &amp;lt;e&amp;gt;put&amp;lt;/e&amp;gt; changes signature from &amp;lt;e&amp;gt;ANY&amp;lt;/e&amp;gt; to &amp;lt;e&amp;gt;INTEGER&amp;lt;/e&amp;gt;.&lt;br /&gt;
* In the non-generic case, covariance happens for certain anchored type declarations and in the case of explicitly changing an argument type to a descendant. This happens in general only on a small subset of the features.&lt;br /&gt;
&lt;br /&gt;
The main difference is that in the generic case, all features which have a formal generic parameter automatically change the signature in different derivations whereas the non-generic case only specific features are covariantly redefined (if any at all). Also, in the generic case it is known for all possible descendants which features are redefined covariantly.&lt;br /&gt;
&lt;br /&gt;
This observation helps to understand the various proposals and to see their strengths and weaknesses:&lt;br /&gt;
* A proposal which operates on the feature level can be good for non-generic classes as you generally have a small number of features covariantly redefined and you only have to specify these features. In the case of generics this can become cumbersome as all features with formal generic parameters are always considered as covariantly redefined and thus for generics they always have to be considered.&lt;br /&gt;
* A proposal which operates on the type level is better suited for generics as you don't have to specify every single feature which has a formal generic parameter as argument. But they run into problems in the non-generic case if you look at anchored types - for example &amp;lt;e&amp;gt;like Current&amp;lt;/e&amp;gt;. Due to the fact that you have a covariant redeclaration in every descendant with such a feature, operating on the type level means that you have to handle every descendant specifically whereas if you operated on the feature level you could just handle this single feature.&lt;br /&gt;
* You see that there are two families of features: Features with formal arguments and ordinary features which are covariantly redefined. The fundamental difference between these two families is that they can change their signature independently. From &amp;lt;e&amp;gt;LIST [ANY]&amp;lt;/e&amp;gt; to &amp;lt;e&amp;gt;LIST [INTEGER]&amp;lt;/e&amp;gt; only the features based on the formal change their signature while they don't change from &amp;lt;e&amp;gt;LIST [ANY]&amp;lt;/e&amp;gt; to &amp;lt;e&amp;gt;LINKED_LIST [ANY]&amp;lt;/e&amp;gt; where the ordinary ones do. If you don't want to restrict the programmers expressiveness these feature families have to be addressed separately and a ''one fits all'' solution does not exist.&lt;br /&gt;
&lt;br /&gt;
=== Contravariant generics ===&lt;br /&gt;
&lt;br /&gt;
The modeling of certain problems involving generics requires contravariance. The two examples which will be used are comparator objects and agents:&lt;br /&gt;
&lt;br /&gt;
* If you want to compare objects using a comparator, it either needs to be able to compare objects of the exact type, or an ancestor. Thus if you want to compare strings, either a comparator for &amp;lt;e&amp;gt;STRING&amp;lt;/e&amp;gt; or one for &amp;lt;e&amp;gt;ANY&amp;lt;/e&amp;gt; is suitable. &lt;br /&gt;
* If you want to pass an argument of type &amp;lt;e&amp;gt;STRING&amp;lt;/e&amp;gt; to an agent, the agent either has to accept a &amp;lt;e&amp;gt;STRING&amp;lt;/e&amp;gt; or &amp;lt;e&amp;gt;ANY&amp;lt;/e&amp;gt; argument (or no argument at all).&lt;br /&gt;
&lt;br /&gt;
These problems can only be modeled if there is a way to express contravariant conformance for generics. This means that all proposed solutions which don't offer this possibility can't be used to model agents or comparator correctly and safely.&lt;br /&gt;
&lt;br /&gt;
=== Catcall benchmark ===&lt;br /&gt;
&lt;br /&gt;
[[Catcall checkpoints]]&lt;br /&gt;
&lt;br /&gt;
== Overview of general solutions ==&lt;br /&gt;
&lt;br /&gt;
The following proposals handle the case of covariance on non-generic and generic types.&lt;br /&gt;
&lt;br /&gt;
=== [[Novariance]] ===&lt;br /&gt;
&lt;br /&gt;
In the novariance proposal, covariant redefinition for arguments is prohibited. If covariance is needed for modeling purposes it can be [http://dev.eiffel.com/Covariance_through_renaming simulated by renaming].&lt;br /&gt;
&lt;br /&gt;
The conformance between generics with different formal parameters is removed.&lt;br /&gt;
&lt;br /&gt;
=== [[Forget / keep]] ===&lt;br /&gt;
&lt;br /&gt;
With the forget and keep mechanisms you specify per type on the feature level which features need not to be called - these features can safely be redefined covariantly - or which features have to be available - these features have to be typesafe for all possible values of a caller object.&lt;br /&gt;
&lt;br /&gt;
Reference: [http://dev.eiffel.com/Forget_/_Keep_Mechanism Article on dev.eiffel.com]&lt;br /&gt;
&lt;br /&gt;
=== Dynamic typeset algorithm ===&lt;br /&gt;
&lt;br /&gt;
The dynamic typeset algorithm does not change any semantics of the types or the conformance as it is in Eiffel already, it only does an abstract execution of the system to limit the possibilities per feature call which have to be checked if they are safe.&lt;br /&gt;
&lt;br /&gt;
=== [[Interval types]] ===&lt;br /&gt;
&lt;br /&gt;
Interval types allow to define each type as an interval with a lower and upper type as boundary. This limits the dynamic type set and thus restricts the number of features which need to be checked for system-validity. In addition to this, it defines rules which handle the case of features with formal arguments.&lt;br /&gt;
&lt;br /&gt;
== Overview of solutions for non-generics ==&lt;br /&gt;
&lt;br /&gt;
These proposal only address the case for non-generics. For generic catcalls another solution (e.g. wildcard generics) can be used.&lt;br /&gt;
&lt;br /&gt;
=== [[Restrict types]] ===&lt;br /&gt;
&lt;br /&gt;
With restrict types you specify per type on the type level which descendant types that are allowed. Only these types can be assigned to such a variable, and all feature calls on these variables have to be valid for all possible types in this list.&lt;br /&gt;
&lt;br /&gt;
Reference: [http://se.inf.ethz.ch/cgi-bin/ecma/index.cgi?IssueFLEX_CATCALL IssueFLEX_CATCALL on ECMA wiki]&amp;lt;br/&amp;gt;&lt;br /&gt;
Reference: Discussion in ECMA mailinglist named ''Catcall removal: another proposal'', [[Restrict types mail|available in parts]]&lt;br /&gt;
&lt;br /&gt;
=== [[DOG proposal]] ===&lt;br /&gt;
&lt;br /&gt;
With the DOG proposal, features which can be covariantly redefined have to be marked as such. These features can only be called on specially marked entities which have a restricted conformance, thus preventing assignments from descendants with potential covariantly redefined arguments.&lt;br /&gt;
&lt;br /&gt;
Reference: [http://se.inf.ethz.ch/cgi-bin/ecma/index.cgi?IssueDOG IssueDOG on ECMA wiki]&lt;br /&gt;
&lt;br /&gt;
== Overview of solutions for generics ==&lt;br /&gt;
&lt;br /&gt;
These proposal only address the case for generics. For non-generic catcalls another solution (e.g. novariance) can be used.&lt;br /&gt;
&lt;br /&gt;
=== [[Usage-site variance]] ===&lt;br /&gt;
&lt;br /&gt;
This solution lets the programmer decide on the instantiation of a generic if the generic parameter should be covariant, contravariant or invariant. Depending on the variance, the applicable features of the type and the conformance rules to other generic types are changed.&lt;br /&gt;
&lt;br /&gt;
Reference: [http://pag.csail.mit.edu/reading-group/variance-ECOOP02.pdf On variance-based subtyping for parametric types]&lt;br /&gt;
&lt;br /&gt;
=== [[Definition-site variance]] ===&lt;br /&gt;
&lt;br /&gt;
This solution lets the programmer decide in the definition of a generic class if the generic parameter should be covariant, contravariant or invariant. Depending on the variance, the formal generic can only appear at the argument, only appear as a result type or appear in both places. Also the conformance is adapted depending on the variance of the generic parameter.&lt;br /&gt;
&lt;br /&gt;
This is the solution which is implemented in the CLR, although not supported by generics in C# which are novariant.&lt;br /&gt;
&lt;br /&gt;
Reference: [http://blogs.msdn.com/rmbyers/archive/2006/06/01/613690.aspx Article about generics in CLR]&lt;br /&gt;
&lt;br /&gt;
Note: There is also a [http://fams.de/text/type-safe-eiffel.html proposal by Bernd Schoeller] about ''variant and invariant'' generics which is a subset of this one and thus not explained in detail.&lt;br /&gt;
&lt;br /&gt;
=== Wildcard generics ===&lt;br /&gt;
&lt;br /&gt;
This mechanism extends the [[usage-site variance]] by adding a wildcard to the generic derivation. This wildcard denotes unspecified types and limits the use of features with generic parameters or result types over conformance to the wildcard types.&lt;br /&gt;
&lt;br /&gt;
Since the mechanism is almost identical to the usage-site variance, it will not be looked at in more detail. Please refer to the reference article for more information.&lt;br /&gt;
&lt;br /&gt;
Reference: [http://www.jot.fm/issues/issue_2004_12/article5 Adding Wildcards to the Java Programming Language]&lt;br /&gt;
&lt;br /&gt;
== Overview of dynamic solutions ==&lt;br /&gt;
&lt;br /&gt;
These proposals do not prevent catcalls at compile-time but introduce means to handle catcalls at runtime.&lt;br /&gt;
&lt;br /&gt;
=== [[Detachable types]] ===&lt;br /&gt;
&lt;br /&gt;
This solution allows covariantly redefined features only to use detachable types. Through this mechanism, an object test is necessary before an argument can be used. This forces the programmer to test arguments for validity.&lt;br /&gt;
&lt;br /&gt;
Reference: [http://se.ethz.ch/~meyer/publications/lncs/attached.pdf Article about ''attached types'' by Bertrand Meyer]&amp;lt;br/&amp;gt;&lt;br /&gt;
Reference: [http://www.ecma-international.org/publications/standards/Ecma-367.htm ECMA Eiffel standard 2nd edition of June 2006]&lt;br /&gt;
&lt;br /&gt;
=== Recast ===&lt;br /&gt;
&lt;br /&gt;
In the recast proposal, the programmer has to specify a transformation function when covariantly redefining a feature which can transform the old argument types to the new ones.&lt;br /&gt;
&lt;br /&gt;
Reference: [http://se.inf.ethz.ch/cgi-bin/ecma/index.cgi?IssueCAT IssueCAT on ECMA wiki]&amp;lt;br/&amp;gt;&lt;br /&gt;
Reference: [http://www.inf.ethz.ch/~meyer/ongoing/covariance/recast.pdf Article about recast]&lt;br /&gt;
&lt;br /&gt;
=== Exceptions ===&lt;br /&gt;
&lt;br /&gt;
Another way of handling catcalls at runtime is to raise exceptions. It can be required or not to provide a rescue clause which handles the case of the catcall.&lt;br /&gt;
&lt;br /&gt;
== Combinations ==&lt;br /&gt;
&lt;br /&gt;
It is also possible to combine different proposals:&lt;br /&gt;
&lt;br /&gt;
* Novariance for non-generic features and usage-site variance for generics .&lt;br /&gt;
* Forget / keep for non-generic features and definition-site variance for generics.&lt;br /&gt;
* DOG proposal for non-generic features and wildcard generics.&lt;br /&gt;
* ...&lt;br /&gt;
&lt;br /&gt;
== Results ==&lt;br /&gt;
&lt;br /&gt;
The following table summarizes the support of the various solutions to the criteria described above which can be used to judge a catcall solution.&lt;br /&gt;
&lt;br /&gt;
This results can be differently interpreted, so the colors may not be totally accurate. See the [[Comparison of catcall solutions#Table_explained|explanation at the end of the table]] for more information&lt;br /&gt;
&lt;br /&gt;
=== General solutions ===&lt;br /&gt;
&lt;br /&gt;
{| border=1 cellpadding=2&lt;br /&gt;
&lt;br /&gt;
|- style=&amp;quot;visibility: hidden&amp;quot;&lt;br /&gt;
| style=&amp;quot;width:25%&amp;quot; |&lt;br /&gt;
| style=&amp;quot;width:25%&amp;quot; |&lt;br /&gt;
| style=&amp;quot;width:25%&amp;quot; |&lt;br /&gt;
| style=&amp;quot;width:25%&amp;quot; |&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
&lt;br /&gt;
! Criteria&lt;br /&gt;
! [[Novariance]]&lt;br /&gt;
! [[Forget / keep]]&lt;br /&gt;
! Dynamic typeset algorithm&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
&lt;br /&gt;
! Syntax overhead&lt;br /&gt;
| {{Green|No}}&lt;br /&gt;
| {{Red|Big}}: forget/keep clauses per type&lt;br /&gt;
| {{Green|No}}&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
&lt;br /&gt;
! Covariance on non-generic types &lt;br /&gt;
| {{Red|Not allowed}}&lt;br /&gt;
| {{Green|Allowed}}&lt;br /&gt;
| {{Green|Allowed}}&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
&lt;br /&gt;
! Export status restrictions&lt;br /&gt;
| {{Red|Not allowed}}&lt;br /&gt;
| {{Green|Allowed}}&lt;br /&gt;
| {{Green|Allowed}}&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
&lt;br /&gt;
! Use of generic types&lt;br /&gt;
| {{Red|Very limited}}: Only invariant conformance&lt;br /&gt;
| {{Orange|Limited}}: Conformance restricted (''keep all'' as default)&amp;lt;br/&amp;gt;{{Orange|Limited}}: Use restricted (''forget all'' as default)&lt;br /&gt;
| {{Green|As it is now}}&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
&lt;br /&gt;
! Agents&lt;br /&gt;
| {{Orange|Limited}}&amp;lt;br/&amp;gt;{{Green|Safe}}&lt;br /&gt;
| {{Orange|Limited}}&amp;lt;br/&amp;gt;{{Green|Safe}}&lt;br /&gt;
| {{Red|As it is now}}&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
&lt;br /&gt;
! Comparator&lt;br /&gt;
| {{Red|Not supported}}&lt;br /&gt;
| {{Red|Not supported}}&lt;br /&gt;
| {{Red|Not supported}}&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
&lt;br /&gt;
! Complexity of compiler check&lt;br /&gt;
| {{Green|Small}}&lt;br /&gt;
| {{Orange|Medium}}: Check of feature call for all descendants; Conformance check on forget/keep clauses&lt;br /&gt;
| {{Red|Big}}: Iterative abstract system execution&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
&lt;br /&gt;
! Complexity of runtime&lt;br /&gt;
| {{Green|Small}}: As it is now&lt;br /&gt;
| {{Orange|Medium}}: Need to know cat features for object tests&lt;br /&gt;
| {{Green|Small}}: As it is now&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
&lt;br /&gt;
! Whole-system analysis&lt;br /&gt;
| {{Green|No}}&lt;br /&gt;
| {{Red|Yes}}: use of ''forget all'' depends on system&lt;br /&gt;
| {{Red|Yes}}&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
&lt;br /&gt;
! Dynamic class and type loading&lt;br /&gt;
| {{Green|Yes}}&lt;br /&gt;
| {{Red|No}}&lt;br /&gt;
| {{Red|No}}&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
&lt;br /&gt;
! Backward compatibility&lt;br /&gt;
| {{Red|Very limited}}&lt;br /&gt;
| {{Orange|Limited}}&lt;br /&gt;
| {{Green|Full}}&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
&lt;br /&gt;
! Support of IDE (Source changes)&lt;br /&gt;
| {{Green|Not needed}}&lt;br /&gt;
| {{Orange|Possible}}: Can propose forget/keep clauses&lt;br /&gt;
| {{Green|Not needed}}&lt;br /&gt;
&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Solutions for non-generics ===&lt;br /&gt;
&lt;br /&gt;
{| border=1 cellpadding=2&lt;br /&gt;
&lt;br /&gt;
|- style=&amp;quot;visibility: hidden&amp;quot;&lt;br /&gt;
| style=&amp;quot;width:25%&amp;quot; |&lt;br /&gt;
| style=&amp;quot;width:25%&amp;quot; |&lt;br /&gt;
| style=&amp;quot;width:25%&amp;quot; |&lt;br /&gt;
| style=&amp;quot;width:25%&amp;quot; |&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
&lt;br /&gt;
! Criteria&lt;br /&gt;
! [[Restrict types]]&lt;br /&gt;
! [[DOG proposal]]&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
&lt;br /&gt;
! Syntax overhead&lt;br /&gt;
| {{Red|Big}}: Restrict clause per type declaration&lt;br /&gt;
| {{Orange|Medium}}: ''cat'' on features and on type declarations&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
&lt;br /&gt;
! Covariance on non-generic types &lt;br /&gt;
| {{Green|Allowed}}&lt;br /&gt;
| {{Green|Allowed}}&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
&lt;br /&gt;
! Export status restrictions&lt;br /&gt;
| {{Green|Allowed}}&lt;br /&gt;
| {{Green|Allowed}}&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
&lt;br /&gt;
! Use of generic types&lt;br /&gt;
| Not addressed&lt;br /&gt;
| Not addressed&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
&lt;br /&gt;
! Agents&lt;br /&gt;
| Not addressed&lt;br /&gt;
| Not addressed&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
&lt;br /&gt;
! Comparator&lt;br /&gt;
| Not addressed&lt;br /&gt;
| Not addressed&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
&lt;br /&gt;
! Complexity of compiler check&lt;br /&gt;
| {{Orange|Medium}}: Check of feature call for all descendants; Conformance check on restrict clauses&lt;br /&gt;
| {{Green|Small}}: Check of ''cat'' on conformance&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
&lt;br /&gt;
! Complexity of runtime&lt;br /&gt;
| not yet considered&lt;br /&gt;
| {{Green|Small}}&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
&lt;br /&gt;
! Whole-system analysis&lt;br /&gt;
| {{Orange|Partial}}&lt;br /&gt;
| {{Green|No}}&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
&lt;br /&gt;
! Dynamic class and type loading&lt;br /&gt;
| {{Orange|Limited}}&lt;br /&gt;
| {{Green|Yes}}&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
&lt;br /&gt;
! Backward compatibility&lt;br /&gt;
| {{Red|Very limited}}&lt;br /&gt;
| {{Red|Very limited}}&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
&lt;br /&gt;
! Support of IDE (Source changes)&lt;br /&gt;
| {{Orange|Possible}}: Can propose restrict clauses&lt;br /&gt;
| {{Orange|Possible}}: Can propose ''cat'' marks&lt;br /&gt;
&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Solutions for generics ===&lt;br /&gt;
&lt;br /&gt;
{| border=1 cellpadding=2&lt;br /&gt;
&lt;br /&gt;
|- style=&amp;quot;visibility: hidden&amp;quot;&lt;br /&gt;
| style=&amp;quot;width:25%&amp;quot; |&lt;br /&gt;
| style=&amp;quot;width:25%&amp;quot; |&lt;br /&gt;
| style=&amp;quot;width:25%&amp;quot; |&lt;br /&gt;
| style=&amp;quot;width:25%&amp;quot; |&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
&lt;br /&gt;
! Criteria&lt;br /&gt;
! [[Usage-site variance]]&lt;br /&gt;
! [[Definition-site variance]]&lt;br /&gt;
! Wildcard generics&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
&lt;br /&gt;
! Syntax overhead&lt;br /&gt;
| {{Orange|Medium}}: Variance marks per generic type&lt;br /&gt;
| {{Green|Small}}: Variance marks per generic class definition&lt;br /&gt;
| {{Orange|Medium}}: Variance marks per generic type&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
&lt;br /&gt;
! Covariance on non-generic types &lt;br /&gt;
| Not addressed&lt;br /&gt;
| Not addressed&lt;br /&gt;
| Not addressed&lt;br /&gt;
|-&lt;br /&gt;
&lt;br /&gt;
! Export status restrictions&lt;br /&gt;
| Not addressed&lt;br /&gt;
| Not addressed&lt;br /&gt;
| Not addressed&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
&lt;br /&gt;
! Use of generic types&lt;br /&gt;
| {{Orange|Limited}}: Conformance is limited&amp;lt;br/&amp;gt;{{Green|Safe}}&lt;br /&gt;
| {{Orange|Limited}}: Conformance is limited&amp;lt;br/&amp;gt;{{Green|Safe}}&lt;br /&gt;
| {{Orange|Limited}}: Conformance is limited&amp;lt;br/&amp;gt;{{Green|Safe}}&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
&lt;br /&gt;
! Agents&lt;br /&gt;
| {{Green|Fully supported}}&amp;lt;br/&amp;gt;{{Green|Safe}}&lt;br /&gt;
| {{Green|Fully supported}}: If tuples can be specified covariantly&amp;lt;br/&amp;gt;{{Green|Safe}}&lt;br /&gt;
| {{Green|Fully supported}}&amp;lt;br/&amp;gt;{{Green|Safe}}&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
&lt;br /&gt;
! Comparator&lt;br /&gt;
| {{Green|Supported}}&lt;br /&gt;
| {{Green|Supported}}&lt;br /&gt;
| {{Green|Supported}}&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
&lt;br /&gt;
! Complexity of compiler check&lt;br /&gt;
| {{Green|Small}}: Consider variance in conformance check&lt;br /&gt;
| {{Green|Small}}: Consider variance in conformance check&lt;br /&gt;
| {{Green|Small}}: Consider variance in conformance check&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
&lt;br /&gt;
! Complexity of runtime&lt;br /&gt;
| {{Green|Small}}: Consider variance in object test&lt;br /&gt;
| {{Green|Small}}: Consider variance in object test&lt;br /&gt;
| {{Green|Small}}: Consider variance in object test&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
&lt;br /&gt;
! Whole-system analysis&lt;br /&gt;
| {{Green|No}}&lt;br /&gt;
| {{Green|No}}&lt;br /&gt;
| {{Green|No}}&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
&lt;br /&gt;
! Dynamic class and type loading&lt;br /&gt;
| {{Green|Yes}}&lt;br /&gt;
| {{Green|Yes}}&lt;br /&gt;
| {{Green|Yes}}&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
&lt;br /&gt;
! Backward compatibility&lt;br /&gt;
| {{Orange|Limited}}: Use of generics changed due to conformance&lt;br /&gt;
| {{Red|Very limited}}: Libraries need redesign&lt;br /&gt;
| {{Orange|Limited}}: Use of generics changed due to conformance&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
&lt;br /&gt;
! Support of IDE (Source changes)&lt;br /&gt;
| {{Orange|Possible}}: Can propose variance marks&lt;br /&gt;
| {{Red|Not possible}}: Libraries need redesign&lt;br /&gt;
| {{Orange|Possible}}: Can propose variance marks/wildcards&lt;br /&gt;
&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Dynamic solutions ===&lt;br /&gt;
&lt;br /&gt;
{| border=1 cellpadding=2&lt;br /&gt;
&lt;br /&gt;
|- style=&amp;quot;visibility: hidden&amp;quot;&lt;br /&gt;
| style=&amp;quot;width:25%&amp;quot; |&lt;br /&gt;
| style=&amp;quot;width:25%&amp;quot; |&lt;br /&gt;
| style=&amp;quot;width:25%&amp;quot; |&lt;br /&gt;
| style=&amp;quot;width:25%&amp;quot; |&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
&lt;br /&gt;
! Criteria&lt;br /&gt;
! [[Detachable types]]&lt;br /&gt;
! Recast&lt;br /&gt;
! Exceptions&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
&lt;br /&gt;
! Syntax overhead&lt;br /&gt;
| {{Green|Small}}: Detachment marks&lt;br /&gt;
| {{Red|Big}}: Recast clauses, recast features&lt;br /&gt;
| {{Orange|Medium}}: If rescue clause mandatory&amp;lt;br/&amp;gt;{{Green|No}}: If rescue clause not needed&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
&lt;br /&gt;
! Covariance on non-generic types &lt;br /&gt;
| {{Red|Very limited}}: Only detached arguments, no expanded arguments&lt;br /&gt;
| {{Green|Allowed}}&lt;br /&gt;
| {{Green|Allowed}}&lt;br /&gt;
|-&lt;br /&gt;
&lt;br /&gt;
! Export status restrictions&lt;br /&gt;
| Not addressed&lt;br /&gt;
| Not addressed&lt;br /&gt;
| Not addressed&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
&lt;br /&gt;
! Use of generics&lt;br /&gt;
| {{Red|Very limited}}: Only detachable formal arguments&lt;br /&gt;
| {{Red|Very limited}}: Recast clause for all features with formal generics&lt;br /&gt;
| {{Green|As it is now}}&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
&lt;br /&gt;
! Agents&lt;br /&gt;
| {{Red|As it is now}} &lt;br /&gt;
| {{Red|As it is now}} &lt;br /&gt;
| {{Red|As it is now}} &lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
&lt;br /&gt;
! Comparator&lt;br /&gt;
| {{Red|Not supported}}&lt;br /&gt;
| {{Red|Not supported}}&lt;br /&gt;
| {{Red|Not supported}}&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
&lt;br /&gt;
! Complexity of compiler check&lt;br /&gt;
| {{Green|Small}}: As it is now&lt;br /&gt;
| {{Green|Small}}: As it is now&lt;br /&gt;
| {{Green|Small}}: As it is now&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
&lt;br /&gt;
! Complexity of runtime&lt;br /&gt;
| {{Green|Small}}: As it is now&lt;br /&gt;
| {{Orange|Medium}}: Check for catcalls and do recast&lt;br /&gt;
| {{Orange|Medium}}: Check for catcalls and raise exception&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
&lt;br /&gt;
! Whole-system analysis&lt;br /&gt;
| {{Green|No}}&lt;br /&gt;
| {{Green|No}}&lt;br /&gt;
| {{Green|No}}&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
&lt;br /&gt;
! Dynamic class and type loading&lt;br /&gt;
| {{Green|Yes}}&lt;br /&gt;
| {{Green|Yes}}&lt;br /&gt;
| {{Green|Yes}}&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
&lt;br /&gt;
! Backward compatibility&lt;br /&gt;
| {{Red|Very limited}}: All covariant and generic features become detached&lt;br /&gt;
| {{Red|Very limited}}: All covariant and generic features need recast clause&lt;br /&gt;
| {{Orange|Limited}}: If rescue clause is mandatory&amp;lt;br/&amp;gt;{{Green|Full}}: If rescue clause not needed&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
&lt;br /&gt;
! Support of IDE (Source changes)&lt;br /&gt;
| {{Orange|Possible}}: Can propose detachment marks&lt;br /&gt;
| {{Red|Not possible}}: Programmer must provide recast clause&lt;br /&gt;
| {{Red|Not possible}}: If rescue clause mandatory&amp;lt;br/&amp;gt;{{Green|Not needed}}: If rescue clause not needed&lt;br /&gt;
&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Table explained ===&lt;br /&gt;
&lt;br /&gt;
; Syntax overhead : {{Green|Small}} if a keyword/mark is needed per class/feature declaration; {{Orange|Medium}} if a keyword/mark is neede per type declaration; {{Red|Big}} if a clause is needed per type declaration.&lt;br /&gt;
; Use of generics : {{Green|As it is now}} if assignments are possible if generic parameters conform; {{Orange|Limited}} is some restrictions in the use or the conformance between generics exist; {{Red|Very limited}} a lot of restrictions in the use or the conformance between generics exist.&lt;br /&gt;
; Agents : {{Green|Fully supported}} if all safe assignments are allowed; {{Orange|Limited}} if not all safe assignments are allowed; {{Red|As it is now}} if unsafe assignments are still possible.&lt;br /&gt;
; Comparator : {{Green|Supported}} if for a comparator all safe assignments are permitted (i.e. contravariant assignments); {{Red|Not supported}} if only exact type or even (unsafe) subtypes can be assigned.&lt;br /&gt;
; Support of IDE (Source changes) : {{Green|Not needed}} if everything still works the same; {{Orange|Possible}} if the compiler can suggest clauses or marks; {{Red|Not possible}} if the programmer has to specify additional features/instructions.&lt;br /&gt;
&lt;br /&gt;
== Personal opinions ==&lt;br /&gt;
&lt;br /&gt;
[[Personal view about catcall solution]]&lt;/div&gt;</summary>
		<author><name>Juliant</name></author>	</entry>

	<entry>
		<id>https://dev.eiffel.com/index.php?title=Comparison_of_catcall_solutions&amp;diff=8946</id>
		<title>Comparison of catcall solutions</title>
		<link rel="alternate" type="text/html" href="https://dev.eiffel.com/index.php?title=Comparison_of_catcall_solutions&amp;diff=8946"/>
				<updated>2007-07-06T02:55:29Z</updated>
		
		<summary type="html">&lt;p&gt;Juliant: /* Overview of general solutions */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Category:ECMA]]&lt;br /&gt;
[[Category:Catcall]]&lt;br /&gt;
== Motivation ==&lt;br /&gt;
&lt;br /&gt;
By allowing covariant feature redefinition and hiding of features, the Eiffel language introduces the problem of catcalls (Changed Availability or Type). Currently the ECMA Eiffel standard does not specify how the occurrence of catcalls should be statically rejected.&lt;br /&gt;
&lt;br /&gt;
The purpose of this document is to show a comparison between different proposals on how to handle the issue of preventing catcalls.&lt;br /&gt;
&lt;br /&gt;
== Criteria for a solution ==&lt;br /&gt;
&lt;br /&gt;
To be able to judge a solution we use the following criteria which we consider as important:&lt;br /&gt;
&lt;br /&gt;
; Syntax overhead : How much syntax will be added to the language in order to express safe covariance and generics?&lt;br /&gt;
; Covariance on non-generic types : Are covariant argument redefinitions addressed in the solution? How does the programmer express it?&lt;br /&gt;
; Export status restrictions : Is restriction of export status addressed in the solution? How does the programmer express it?&lt;br /&gt;
; Use of generic types : How is conformance of generics? Are catcalls for generics addressed in the solution? How does the programmer express it? Can generics be used as now or are there restrictions?&lt;br /&gt;
:; Agents : Can agents be modeled with the solution while being type safe and expressive?&lt;br /&gt;
:; Comparator : Can comparator types be modeled with the solution while being type safe and expressive?&lt;br /&gt;
; Complexity of the compiler check : Is it just a matter of doing one check or several?&lt;br /&gt;
; Complexity of the runtime : Does the runtime need more information to do assignment attempts or object tests?&lt;br /&gt;
; Whole-system analysis : Is a whole-system analysis necessary?&lt;br /&gt;
; Dynamic class and type loading : Is it safe to dynamically load new classes at runtime and instantiate new types?&lt;br /&gt;
; Backward compatibility : Is the solution backward compatible to existing source code?&lt;br /&gt;
:; Applicable per cluster : Can the solution be applied on a per cluster basis?&lt;br /&gt;
; Support of compiler/IDE : Can the compiler/IDE help in updating existing source code? How?&lt;br /&gt;
&lt;br /&gt;
== General remarks ==&lt;br /&gt;
&lt;br /&gt;
=== Checking feature calls ===&lt;br /&gt;
&lt;br /&gt;
As the ''Single-level Call rule'' (8.25.3, VUSC) describes, a feature call is only valid if it is valid for every type in the dynamic type set. A simple solution would be that every feature call has to be checked for all possible descendants of the static target type. If this check is performed on a system, it will catch all catcalls - but also report false positives.&lt;br /&gt;
&lt;br /&gt;
Some of the proposed solutions try to address this problem by finding a better approximation to the dynamic type set so that the false positives can be ruled out.&lt;br /&gt;
&lt;br /&gt;
In general this is problematic as it requires a whole-system analysis, thus preventing the dynamic loading of new classes at run-time. The reason for this is that it is not known at compile time which features will be covariantly redefined by dynamically loaded classes.&lt;br /&gt;
&lt;br /&gt;
This is only the case with non-generic types. For generics, it is known at compile time that all features containing a formal in the parameter list can be treated as covariantly redefined and corresponding precautions can be implemented via the type system and conformance rules which allow to load even generic types at run-time.&lt;br /&gt;
&lt;br /&gt;
By the way, Eiffel Software has started to [[Single level call rule implementation|implement the basis of the ''single-level call rule'']] in it's Eiffel compiler. It is work in progress which revealed some implementation problems.&lt;br /&gt;
&lt;br /&gt;
=== Generic vs. non-generic covariance ===&lt;br /&gt;
&lt;br /&gt;
We can distinguish two different kinds of covariant argument redefinition:&lt;br /&gt;
&lt;br /&gt;
* When a generic type is derived, the formal generic parameters will be replaced by the actual generic parameters. Given the current conformance rules for generics, this can be seen as a covariant redefinition for all features which contain a formal generic as an argument. A simple example is the change from &amp;lt;e&amp;gt;LIST [ANY]&amp;lt;/e&amp;gt; to &amp;lt;e&amp;gt;LIST [INTEGER]&amp;lt;/e&amp;gt; where the feature &amp;lt;e&amp;gt;put&amp;lt;/e&amp;gt; changes signature from &amp;lt;e&amp;gt;ANY&amp;lt;/e&amp;gt; to &amp;lt;e&amp;gt;INTEGER&amp;lt;/e&amp;gt;.&lt;br /&gt;
* In the non-generic case, covariance happens for certain anchored type declarations and in the case of explicitly changing an argument type to a descendant. This happens in general only on a small subset of the features.&lt;br /&gt;
&lt;br /&gt;
The main difference is that in the generic case, all features which have a formal generic parameter automatically change the signature in different derivations whereas the non-generic case only specific features are covariantly redefined (if any at all). Also, in the generic case it is known for all possible descendants which features are redefined covariantly.&lt;br /&gt;
&lt;br /&gt;
This observation helps to understand the various proposals and to see their strengths and weaknesses:&lt;br /&gt;
* A proposal which operates on the feature level can be good for non-generic classes as you generally have a small number of features covariantly redefined and you only have to specify these features. In the case of generics this can become cumbersome as all features with formal generic parameters are always considered as covariantly redefined and thus for generics they always have to be considered.&lt;br /&gt;
* A proposal which operates on the type level is better suited for generics as you don't have to specify every single feature which has a formal generic parameter as argument. But they run into problems in the non-generic case if you look at anchored types - for example &amp;lt;e&amp;gt;like Current&amp;lt;/e&amp;gt;. Due to the fact that you have a covariant redeclaration in every descendant with such a feature, operating on the type level means that you have to handle every descendant specifically whereas if you operated on the feature level you could just handle this single feature.&lt;br /&gt;
* You see that there are two families of features: Features with formal arguments and ordinary features which are covariantly redefined. The fundamental difference between these two families is that they can change their signature independently. From &amp;lt;e&amp;gt;LIST [ANY]&amp;lt;/e&amp;gt; to &amp;lt;e&amp;gt;LIST [INTEGER]&amp;lt;/e&amp;gt; only the features based on the formal change their signature while they don't change from &amp;lt;e&amp;gt;LIST [ANY]&amp;lt;/e&amp;gt; to &amp;lt;e&amp;gt;LINKED_LIST [ANY]&amp;lt;/e&amp;gt; where the ordinary ones do. If you don't want to restrict the programmers expressiveness these feature families have to be addressed separately and a ''one fits all'' solution does not exist.&lt;br /&gt;
&lt;br /&gt;
=== Contravariant generics ===&lt;br /&gt;
&lt;br /&gt;
The modeling of certain problems involving generics requires contravariance. The two examples which will be used are comparator objects and agents:&lt;br /&gt;
&lt;br /&gt;
* If you want to compare objects using a comparator, it either needs to be able to compare objects of the exact type, or an ancestor. Thus if you want to compare strings, either a comparator for &amp;lt;e&amp;gt;STRING&amp;lt;/e&amp;gt; or one for &amp;lt;e&amp;gt;ANY&amp;lt;/e&amp;gt; is suitable. &lt;br /&gt;
* If you want to pass an argument of type &amp;lt;e&amp;gt;STRING&amp;lt;/e&amp;gt; to an agent, the agent either has to accept a &amp;lt;e&amp;gt;STRING&amp;lt;/e&amp;gt; or &amp;lt;e&amp;gt;ANY&amp;lt;/e&amp;gt; argument (or no argument at all).&lt;br /&gt;
&lt;br /&gt;
These problems can only be modeled if there is a way to express contravariant conformance for generics. This means that all proposed solutions which don't offer this possibility can't be used to model agents or comparator correctly and safely.&lt;br /&gt;
&lt;br /&gt;
=== Catcall benchmark ===&lt;br /&gt;
&lt;br /&gt;
[[Catcall checkpoints]]&lt;br /&gt;
&lt;br /&gt;
== Overview of general solutions ==&lt;br /&gt;
&lt;br /&gt;
The following proposals handle the case of covariance on non-generic and generic types.&lt;br /&gt;
&lt;br /&gt;
=== [[Novariance]] ===&lt;br /&gt;
&lt;br /&gt;
In the novariance proposal, covariant redefinition for arguments is prohibited. If covariance is needed for modeling purposes it can be [http://dev.eiffel.com/Covariance_through_renaming simulated by renaming].&lt;br /&gt;
&lt;br /&gt;
The conformance between generics with different formal parameters is removed.&lt;br /&gt;
&lt;br /&gt;
=== [[Forget / keep]] ===&lt;br /&gt;
&lt;br /&gt;
With the forget and keep mechanisms you specify per type on the feature level which features need not to be called - these features can safely be redefined covariantly - or which features have to be available - these features have to be typesafe for all possible values of a caller object.&lt;br /&gt;
&lt;br /&gt;
Reference: [http://dev.eiffel.com/Forget_/_Keep_Mechanism Article on dev.eiffel.com]&lt;br /&gt;
&lt;br /&gt;
=== Dynamic typeset algorithm ===&lt;br /&gt;
&lt;br /&gt;
The dynamic typeset algorithm does not change any semantics of the types or the conformance as it is in Eiffel already, it only does an abstract execution of the system to limit the possibilities per feature call which have to be checked if they are safe.&lt;br /&gt;
&lt;br /&gt;
=== [[Interval types]]] ===&lt;br /&gt;
&lt;br /&gt;
Interval types allow to define each type as an interval with a lower and upper type as boundary. This limits the dynamic type set and thus restricts the number of features which need to be checked for system-validity. In addition to this, it defines rules which handle the case of features with formal arguments.&lt;br /&gt;
&lt;br /&gt;
== Overview of solutions for non-generics ==&lt;br /&gt;
&lt;br /&gt;
These proposal only address the case for non-generics. For generic catcalls another solution (e.g. wildcard generics) can be used.&lt;br /&gt;
&lt;br /&gt;
=== [[Restrict types]] ===&lt;br /&gt;
&lt;br /&gt;
With restrict types you specify per type on the type level which descendant types that are allowed. Only these types can be assigned to such a variable, and all feature calls on these variables have to be valid for all possible types in this list.&lt;br /&gt;
&lt;br /&gt;
Reference: [http://se.inf.ethz.ch/cgi-bin/ecma/index.cgi?IssueFLEX_CATCALL IssueFLEX_CATCALL on ECMA wiki]&amp;lt;br/&amp;gt;&lt;br /&gt;
Reference: Discussion in ECMA mailinglist named ''Catcall removal: another proposal'', [[Restrict types mail|available in parts]]&lt;br /&gt;
&lt;br /&gt;
=== [[DOG proposal]] ===&lt;br /&gt;
&lt;br /&gt;
With the DOG proposal, features which can be covariantly redefined have to be marked as such. These features can only be called on specially marked entities which have a restricted conformance, thus preventing assignments from descendants with potential covariantly redefined arguments.&lt;br /&gt;
&lt;br /&gt;
Reference: [http://se.inf.ethz.ch/cgi-bin/ecma/index.cgi?IssueDOG IssueDOG on ECMA wiki]&lt;br /&gt;
&lt;br /&gt;
== Overview of solutions for generics ==&lt;br /&gt;
&lt;br /&gt;
These proposal only address the case for generics. For non-generic catcalls another solution (e.g. novariance) can be used.&lt;br /&gt;
&lt;br /&gt;
=== [[Usage-site variance]] ===&lt;br /&gt;
&lt;br /&gt;
This solution lets the programmer decide on the instantiation of a generic if the generic parameter should be covariant, contravariant or invariant. Depending on the variance, the applicable features of the type and the conformance rules to other generic types are changed.&lt;br /&gt;
&lt;br /&gt;
Reference: [http://pag.csail.mit.edu/reading-group/variance-ECOOP02.pdf On variance-based subtyping for parametric types]&lt;br /&gt;
&lt;br /&gt;
=== [[Definition-site variance]] ===&lt;br /&gt;
&lt;br /&gt;
This solution lets the programmer decide in the definition of a generic class if the generic parameter should be covariant, contravariant or invariant. Depending on the variance, the formal generic can only appear at the argument, only appear as a result type or appear in both places. Also the conformance is adapted depending on the variance of the generic parameter.&lt;br /&gt;
&lt;br /&gt;
This is the solution which is implemented in the CLR, although not supported by generics in C# which are novariant.&lt;br /&gt;
&lt;br /&gt;
Reference: [http://blogs.msdn.com/rmbyers/archive/2006/06/01/613690.aspx Article about generics in CLR]&lt;br /&gt;
&lt;br /&gt;
Note: There is also a [http://fams.de/text/type-safe-eiffel.html proposal by Bernd Schoeller] about ''variant and invariant'' generics which is a subset of this one and thus not explained in detail.&lt;br /&gt;
&lt;br /&gt;
=== Wildcard generics ===&lt;br /&gt;
&lt;br /&gt;
This mechanism extends the [[usage-site variance]] by adding a wildcard to the generic derivation. This wildcard denotes unspecified types and limits the use of features with generic parameters or result types over conformance to the wildcard types.&lt;br /&gt;
&lt;br /&gt;
Since the mechanism is almost identical to the usage-site variance, it will not be looked at in more detail. Please refer to the reference article for more information.&lt;br /&gt;
&lt;br /&gt;
Reference: [http://www.jot.fm/issues/issue_2004_12/article5 Adding Wildcards to the Java Programming Language]&lt;br /&gt;
&lt;br /&gt;
== Overview of dynamic solutions ==&lt;br /&gt;
&lt;br /&gt;
These proposals do not prevent catcalls at compile-time but introduce means to handle catcalls at runtime.&lt;br /&gt;
&lt;br /&gt;
=== [[Detachable types]] ===&lt;br /&gt;
&lt;br /&gt;
This solution allows covariantly redefined features only to use detachable types. Through this mechanism, an object test is necessary before an argument can be used. This forces the programmer to test arguments for validity.&lt;br /&gt;
&lt;br /&gt;
Reference: [http://se.ethz.ch/~meyer/publications/lncs/attached.pdf Article about ''attached types'' by Bertrand Meyer]&amp;lt;br/&amp;gt;&lt;br /&gt;
Reference: [http://www.ecma-international.org/publications/standards/Ecma-367.htm ECMA Eiffel standard 2nd edition of June 2006]&lt;br /&gt;
&lt;br /&gt;
=== Recast ===&lt;br /&gt;
&lt;br /&gt;
In the recast proposal, the programmer has to specify a transformation function when covariantly redefining a feature which can transform the old argument types to the new ones.&lt;br /&gt;
&lt;br /&gt;
Reference: [http://se.inf.ethz.ch/cgi-bin/ecma/index.cgi?IssueCAT IssueCAT on ECMA wiki]&amp;lt;br/&amp;gt;&lt;br /&gt;
Reference: [http://www.inf.ethz.ch/~meyer/ongoing/covariance/recast.pdf Article about recast]&lt;br /&gt;
&lt;br /&gt;
=== Exceptions ===&lt;br /&gt;
&lt;br /&gt;
Another way of handling catcalls at runtime is to raise exceptions. It can be required or not to provide a rescue clause which handles the case of the catcall.&lt;br /&gt;
&lt;br /&gt;
== Combinations ==&lt;br /&gt;
&lt;br /&gt;
It is also possible to combine different proposals:&lt;br /&gt;
&lt;br /&gt;
* Novariance for non-generic features and usage-site variance for generics .&lt;br /&gt;
* Forget / keep for non-generic features and definition-site variance for generics.&lt;br /&gt;
* DOG proposal for non-generic features and wildcard generics.&lt;br /&gt;
* ...&lt;br /&gt;
&lt;br /&gt;
== Results ==&lt;br /&gt;
&lt;br /&gt;
The following table summarizes the support of the various solutions to the criteria described above which can be used to judge a catcall solution.&lt;br /&gt;
&lt;br /&gt;
This results can be differently interpreted, so the colors may not be totally accurate. See the [[Comparison of catcall solutions#Table_explained|explanation at the end of the table]] for more information&lt;br /&gt;
&lt;br /&gt;
=== General solutions ===&lt;br /&gt;
&lt;br /&gt;
{| border=1 cellpadding=2&lt;br /&gt;
&lt;br /&gt;
|- style=&amp;quot;visibility: hidden&amp;quot;&lt;br /&gt;
| style=&amp;quot;width:25%&amp;quot; |&lt;br /&gt;
| style=&amp;quot;width:25%&amp;quot; |&lt;br /&gt;
| style=&amp;quot;width:25%&amp;quot; |&lt;br /&gt;
| style=&amp;quot;width:25%&amp;quot; |&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
&lt;br /&gt;
! Criteria&lt;br /&gt;
! [[Novariance]]&lt;br /&gt;
! [[Forget / keep]]&lt;br /&gt;
! Dynamic typeset algorithm&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
&lt;br /&gt;
! Syntax overhead&lt;br /&gt;
| {{Green|No}}&lt;br /&gt;
| {{Red|Big}}: forget/keep clauses per type&lt;br /&gt;
| {{Green|No}}&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
&lt;br /&gt;
! Covariance on non-generic types &lt;br /&gt;
| {{Red|Not allowed}}&lt;br /&gt;
| {{Green|Allowed}}&lt;br /&gt;
| {{Green|Allowed}}&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
&lt;br /&gt;
! Export status restrictions&lt;br /&gt;
| {{Red|Not allowed}}&lt;br /&gt;
| {{Green|Allowed}}&lt;br /&gt;
| {{Green|Allowed}}&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
&lt;br /&gt;
! Use of generic types&lt;br /&gt;
| {{Red|Very limited}}: Only invariant conformance&lt;br /&gt;
| {{Orange|Limited}}: Conformance restricted (''keep all'' as default)&amp;lt;br/&amp;gt;{{Orange|Limited}}: Use restricted (''forget all'' as default)&lt;br /&gt;
| {{Green|As it is now}}&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
&lt;br /&gt;
! Agents&lt;br /&gt;
| {{Orange|Limited}}&amp;lt;br/&amp;gt;{{Green|Safe}}&lt;br /&gt;
| {{Orange|Limited}}&amp;lt;br/&amp;gt;{{Green|Safe}}&lt;br /&gt;
| {{Red|As it is now}}&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
&lt;br /&gt;
! Comparator&lt;br /&gt;
| {{Red|Not supported}}&lt;br /&gt;
| {{Red|Not supported}}&lt;br /&gt;
| {{Red|Not supported}}&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
&lt;br /&gt;
! Complexity of compiler check&lt;br /&gt;
| {{Green|Small}}&lt;br /&gt;
| {{Orange|Medium}}: Check of feature call for all descendants; Conformance check on forget/keep clauses&lt;br /&gt;
| {{Red|Big}}: Iterative abstract system execution&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
&lt;br /&gt;
! Complexity of runtime&lt;br /&gt;
| {{Green|Small}}: As it is now&lt;br /&gt;
| {{Orange|Medium}}: Need to know cat features for object tests&lt;br /&gt;
| {{Green|Small}}: As it is now&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
&lt;br /&gt;
! Whole-system analysis&lt;br /&gt;
| {{Green|No}}&lt;br /&gt;
| {{Red|Yes}}: use of ''forget all'' depends on system&lt;br /&gt;
| {{Red|Yes}}&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
&lt;br /&gt;
! Dynamic class and type loading&lt;br /&gt;
| {{Green|Yes}}&lt;br /&gt;
| {{Red|No}}&lt;br /&gt;
| {{Red|No}}&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
&lt;br /&gt;
! Backward compatibility&lt;br /&gt;
| {{Red|Very limited}}&lt;br /&gt;
| {{Orange|Limited}}&lt;br /&gt;
| {{Green|Full}}&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
&lt;br /&gt;
! Support of IDE (Source changes)&lt;br /&gt;
| {{Green|Not needed}}&lt;br /&gt;
| {{Orange|Possible}}: Can propose forget/keep clauses&lt;br /&gt;
| {{Green|Not needed}}&lt;br /&gt;
&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Solutions for non-generics ===&lt;br /&gt;
&lt;br /&gt;
{| border=1 cellpadding=2&lt;br /&gt;
&lt;br /&gt;
|- style=&amp;quot;visibility: hidden&amp;quot;&lt;br /&gt;
| style=&amp;quot;width:25%&amp;quot; |&lt;br /&gt;
| style=&amp;quot;width:25%&amp;quot; |&lt;br /&gt;
| style=&amp;quot;width:25%&amp;quot; |&lt;br /&gt;
| style=&amp;quot;width:25%&amp;quot; |&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
&lt;br /&gt;
! Criteria&lt;br /&gt;
! [[Restrict types]]&lt;br /&gt;
! [[DOG proposal]]&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
&lt;br /&gt;
! Syntax overhead&lt;br /&gt;
| {{Red|Big}}: Restrict clause per type declaration&lt;br /&gt;
| {{Orange|Medium}}: ''cat'' on features and on type declarations&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
&lt;br /&gt;
! Covariance on non-generic types &lt;br /&gt;
| {{Green|Allowed}}&lt;br /&gt;
| {{Green|Allowed}}&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
&lt;br /&gt;
! Export status restrictions&lt;br /&gt;
| {{Green|Allowed}}&lt;br /&gt;
| {{Green|Allowed}}&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
&lt;br /&gt;
! Use of generic types&lt;br /&gt;
| Not addressed&lt;br /&gt;
| Not addressed&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
&lt;br /&gt;
! Agents&lt;br /&gt;
| Not addressed&lt;br /&gt;
| Not addressed&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
&lt;br /&gt;
! Comparator&lt;br /&gt;
| Not addressed&lt;br /&gt;
| Not addressed&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
&lt;br /&gt;
! Complexity of compiler check&lt;br /&gt;
| {{Orange|Medium}}: Check of feature call for all descendants; Conformance check on restrict clauses&lt;br /&gt;
| {{Green|Small}}: Check of ''cat'' on conformance&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
&lt;br /&gt;
! Complexity of runtime&lt;br /&gt;
| not yet considered&lt;br /&gt;
| {{Green|Small}}&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
&lt;br /&gt;
! Whole-system analysis&lt;br /&gt;
| {{Orange|Partial}}&lt;br /&gt;
| {{Green|No}}&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
&lt;br /&gt;
! Dynamic class and type loading&lt;br /&gt;
| {{Orange|Limited}}&lt;br /&gt;
| {{Green|Yes}}&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
&lt;br /&gt;
! Backward compatibility&lt;br /&gt;
| {{Red|Very limited}}&lt;br /&gt;
| {{Red|Very limited}}&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
&lt;br /&gt;
! Support of IDE (Source changes)&lt;br /&gt;
| {{Orange|Possible}}: Can propose restrict clauses&lt;br /&gt;
| {{Orange|Possible}}: Can propose ''cat'' marks&lt;br /&gt;
&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Solutions for generics ===&lt;br /&gt;
&lt;br /&gt;
{| border=1 cellpadding=2&lt;br /&gt;
&lt;br /&gt;
|- style=&amp;quot;visibility: hidden&amp;quot;&lt;br /&gt;
| style=&amp;quot;width:25%&amp;quot; |&lt;br /&gt;
| style=&amp;quot;width:25%&amp;quot; |&lt;br /&gt;
| style=&amp;quot;width:25%&amp;quot; |&lt;br /&gt;
| style=&amp;quot;width:25%&amp;quot; |&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
&lt;br /&gt;
! Criteria&lt;br /&gt;
! [[Usage-site variance]]&lt;br /&gt;
! [[Definition-site variance]]&lt;br /&gt;
! Wildcard generics&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
&lt;br /&gt;
! Syntax overhead&lt;br /&gt;
| {{Orange|Medium}}: Variance marks per generic type&lt;br /&gt;
| {{Green|Small}}: Variance marks per generic class definition&lt;br /&gt;
| {{Orange|Medium}}: Variance marks per generic type&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
&lt;br /&gt;
! Covariance on non-generic types &lt;br /&gt;
| Not addressed&lt;br /&gt;
| Not addressed&lt;br /&gt;
| Not addressed&lt;br /&gt;
|-&lt;br /&gt;
&lt;br /&gt;
! Export status restrictions&lt;br /&gt;
| Not addressed&lt;br /&gt;
| Not addressed&lt;br /&gt;
| Not addressed&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
&lt;br /&gt;
! Use of generic types&lt;br /&gt;
| {{Orange|Limited}}: Conformance is limited&amp;lt;br/&amp;gt;{{Green|Safe}}&lt;br /&gt;
| {{Orange|Limited}}: Conformance is limited&amp;lt;br/&amp;gt;{{Green|Safe}}&lt;br /&gt;
| {{Orange|Limited}}: Conformance is limited&amp;lt;br/&amp;gt;{{Green|Safe}}&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
&lt;br /&gt;
! Agents&lt;br /&gt;
| {{Green|Fully supported}}&amp;lt;br/&amp;gt;{{Green|Safe}}&lt;br /&gt;
| {{Green|Fully supported}}: If tuples can be specified covariantly&amp;lt;br/&amp;gt;{{Green|Safe}}&lt;br /&gt;
| {{Green|Fully supported}}&amp;lt;br/&amp;gt;{{Green|Safe}}&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
&lt;br /&gt;
! Comparator&lt;br /&gt;
| {{Green|Supported}}&lt;br /&gt;
| {{Green|Supported}}&lt;br /&gt;
| {{Green|Supported}}&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
&lt;br /&gt;
! Complexity of compiler check&lt;br /&gt;
| {{Green|Small}}: Consider variance in conformance check&lt;br /&gt;
| {{Green|Small}}: Consider variance in conformance check&lt;br /&gt;
| {{Green|Small}}: Consider variance in conformance check&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
&lt;br /&gt;
! Complexity of runtime&lt;br /&gt;
| {{Green|Small}}: Consider variance in object test&lt;br /&gt;
| {{Green|Small}}: Consider variance in object test&lt;br /&gt;
| {{Green|Small}}: Consider variance in object test&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
&lt;br /&gt;
! Whole-system analysis&lt;br /&gt;
| {{Green|No}}&lt;br /&gt;
| {{Green|No}}&lt;br /&gt;
| {{Green|No}}&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
&lt;br /&gt;
! Dynamic class and type loading&lt;br /&gt;
| {{Green|Yes}}&lt;br /&gt;
| {{Green|Yes}}&lt;br /&gt;
| {{Green|Yes}}&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
&lt;br /&gt;
! Backward compatibility&lt;br /&gt;
| {{Orange|Limited}}: Use of generics changed due to conformance&lt;br /&gt;
| {{Red|Very limited}}: Libraries need redesign&lt;br /&gt;
| {{Orange|Limited}}: Use of generics changed due to conformance&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
&lt;br /&gt;
! Support of IDE (Source changes)&lt;br /&gt;
| {{Orange|Possible}}: Can propose variance marks&lt;br /&gt;
| {{Red|Not possible}}: Libraries need redesign&lt;br /&gt;
| {{Orange|Possible}}: Can propose variance marks/wildcards&lt;br /&gt;
&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Dynamic solutions ===&lt;br /&gt;
&lt;br /&gt;
{| border=1 cellpadding=2&lt;br /&gt;
&lt;br /&gt;
|- style=&amp;quot;visibility: hidden&amp;quot;&lt;br /&gt;
| style=&amp;quot;width:25%&amp;quot; |&lt;br /&gt;
| style=&amp;quot;width:25%&amp;quot; |&lt;br /&gt;
| style=&amp;quot;width:25%&amp;quot; |&lt;br /&gt;
| style=&amp;quot;width:25%&amp;quot; |&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
&lt;br /&gt;
! Criteria&lt;br /&gt;
! [[Detachable types]]&lt;br /&gt;
! Recast&lt;br /&gt;
! Exceptions&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
&lt;br /&gt;
! Syntax overhead&lt;br /&gt;
| {{Green|Small}}: Detachment marks&lt;br /&gt;
| {{Red|Big}}: Recast clauses, recast features&lt;br /&gt;
| {{Orange|Medium}}: If rescue clause mandatory&amp;lt;br/&amp;gt;{{Green|No}}: If rescue clause not needed&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
&lt;br /&gt;
! Covariance on non-generic types &lt;br /&gt;
| {{Red|Very limited}}: Only detached arguments, no expanded arguments&lt;br /&gt;
| {{Green|Allowed}}&lt;br /&gt;
| {{Green|Allowed}}&lt;br /&gt;
|-&lt;br /&gt;
&lt;br /&gt;
! Export status restrictions&lt;br /&gt;
| Not addressed&lt;br /&gt;
| Not addressed&lt;br /&gt;
| Not addressed&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
&lt;br /&gt;
! Use of generics&lt;br /&gt;
| {{Red|Very limited}}: Only detachable formal arguments&lt;br /&gt;
| {{Red|Very limited}}: Recast clause for all features with formal generics&lt;br /&gt;
| {{Green|As it is now}}&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
&lt;br /&gt;
! Agents&lt;br /&gt;
| {{Red|As it is now}} &lt;br /&gt;
| {{Red|As it is now}} &lt;br /&gt;
| {{Red|As it is now}} &lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
&lt;br /&gt;
! Comparator&lt;br /&gt;
| {{Red|Not supported}}&lt;br /&gt;
| {{Red|Not supported}}&lt;br /&gt;
| {{Red|Not supported}}&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
&lt;br /&gt;
! Complexity of compiler check&lt;br /&gt;
| {{Green|Small}}: As it is now&lt;br /&gt;
| {{Green|Small}}: As it is now&lt;br /&gt;
| {{Green|Small}}: As it is now&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
&lt;br /&gt;
! Complexity of runtime&lt;br /&gt;
| {{Green|Small}}: As it is now&lt;br /&gt;
| {{Orange|Medium}}: Check for catcalls and do recast&lt;br /&gt;
| {{Orange|Medium}}: Check for catcalls and raise exception&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
&lt;br /&gt;
! Whole-system analysis&lt;br /&gt;
| {{Green|No}}&lt;br /&gt;
| {{Green|No}}&lt;br /&gt;
| {{Green|No}}&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
&lt;br /&gt;
! Dynamic class and type loading&lt;br /&gt;
| {{Green|Yes}}&lt;br /&gt;
| {{Green|Yes}}&lt;br /&gt;
| {{Green|Yes}}&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
&lt;br /&gt;
! Backward compatibility&lt;br /&gt;
| {{Red|Very limited}}: All covariant and generic features become detached&lt;br /&gt;
| {{Red|Very limited}}: All covariant and generic features need recast clause&lt;br /&gt;
| {{Orange|Limited}}: If rescue clause is mandatory&amp;lt;br/&amp;gt;{{Green|Full}}: If rescue clause not needed&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
&lt;br /&gt;
! Support of IDE (Source changes)&lt;br /&gt;
| {{Orange|Possible}}: Can propose detachment marks&lt;br /&gt;
| {{Red|Not possible}}: Programmer must provide recast clause&lt;br /&gt;
| {{Red|Not possible}}: If rescue clause mandatory&amp;lt;br/&amp;gt;{{Green|Not needed}}: If rescue clause not needed&lt;br /&gt;
&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Table explained ===&lt;br /&gt;
&lt;br /&gt;
; Syntax overhead : {{Green|Small}} if a keyword/mark is needed per class/feature declaration; {{Orange|Medium}} if a keyword/mark is neede per type declaration; {{Red|Big}} if a clause is needed per type declaration.&lt;br /&gt;
; Use of generics : {{Green|As it is now}} if assignments are possible if generic parameters conform; {{Orange|Limited}} is some restrictions in the use or the conformance between generics exist; {{Red|Very limited}} a lot of restrictions in the use or the conformance between generics exist.&lt;br /&gt;
; Agents : {{Green|Fully supported}} if all safe assignments are allowed; {{Orange|Limited}} if not all safe assignments are allowed; {{Red|As it is now}} if unsafe assignments are still possible.&lt;br /&gt;
; Comparator : {{Green|Supported}} if for a comparator all safe assignments are permitted (i.e. contravariant assignments); {{Red|Not supported}} if only exact type or even (unsafe) subtypes can be assigned.&lt;br /&gt;
; Support of IDE (Source changes) : {{Green|Not needed}} if everything still works the same; {{Orange|Possible}} if the compiler can suggest clauses or marks; {{Red|Not possible}} if the programmer has to specify additional features/instructions.&lt;br /&gt;
&lt;br /&gt;
== Personal opinions ==&lt;br /&gt;
&lt;br /&gt;
[[Personal view about catcall solution]]&lt;/div&gt;</summary>
		<author><name>Juliant</name></author>	</entry>

	<entry>
		<id>https://dev.eiffel.com/index.php?title=Interval_types_and_usage-site_variance&amp;diff=8945</id>
		<title>Interval types and usage-site variance</title>
		<link rel="alternate" type="text/html" href="https://dev.eiffel.com/index.php?title=Interval_types_and_usage-site_variance&amp;diff=8945"/>
				<updated>2007-07-06T02:52:19Z</updated>
		
		<summary type="html">&lt;p&gt;Juliant: /* Default behaviour */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Category:ECMA]]&lt;br /&gt;
[[Category:Catcall]]&lt;br /&gt;
{{Research}}&lt;br /&gt;
== Introduction ==&lt;br /&gt;
&lt;br /&gt;
This is a proposition to combine two mechanisms to prevent catcalls, the [[interval types]] for non-generics and the [[usage-site variance]] for generics.&lt;br /&gt;
&lt;br /&gt;
The reason for this is that up to now all approaches failed to deliver an easy and concise solution to solve the problem of catcalls in general. &lt;br /&gt;
&lt;br /&gt;
Interval types work well for non-generic types and the overhead for the type declaration is minimal with a sensitive default behaviour, but for generics it does not really work.&lt;br /&gt;
&lt;br /&gt;
Usage-site variance is a promising solution for generics with just the small addition of a flag for the kind of variance needed on a generic derivation. And again, the default behaviour will allow most uses of a generic type as the programmer expects it to work.&lt;br /&gt;
&lt;br /&gt;
== Syntax ==&lt;br /&gt;
&lt;br /&gt;
Types can be specified as an interval:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;e&amp;gt;LOWER..UPPER&amp;lt;/e&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Generic parameters can be marked to select the variance:&lt;br /&gt;
&lt;br /&gt;
* To specify a novariant generic, the normal syntax can be used: &amp;lt;e&amp;gt;LIST [ANY]&amp;lt;/e&amp;gt;&lt;br /&gt;
* To specify a covariant generic, we use a plus sign: &amp;lt;e&amp;gt;LIST [+ANY]&amp;lt;/e&amp;gt;&lt;br /&gt;
* To specify a contravariant generic, we use a minus sign: &amp;lt;e&amp;gt;LIST [-ANY]&amp;lt;/e&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Semantics ==&lt;br /&gt;
&lt;br /&gt;
Each interval type describes the set of types which belong to the interval. A type belongs to the inverval if it conforms to the lower bound (&amp;lt;e&amp;gt;LOWER&amp;lt;/e&amp;gt;) and if the upper bound (&amp;lt;e&amp;gt;UPPER&amp;lt;/e&amp;gt;) conforms to it. All feature calls will be subject to whole-system validity and by restricting the dynamic type set to the types in the interval this check can be influenced.&lt;br /&gt;
&lt;br /&gt;
For generics the applicable features depend on the variance mark used:&lt;br /&gt;
&lt;br /&gt;
* On a novariant generic, all features can be used.&lt;br /&gt;
* On a covariant generic, only features which have the formal generic as a result type can be used. If the formal generic appears in an argument this feature is invalid.&lt;br /&gt;
* On a contravariant generic, only feature which have the formal generc as an argument type can be used. If the formal generic appears as a result type this feature is invalid.&lt;br /&gt;
&lt;br /&gt;
The two mechanisms can also be combined. A generic parameter can be an interval type and can also have a variance modifier. The normal generic substituion applies to every formal generic by replacing the generic with the interval type. The variance marks are only used for conformance checks and don't affect the generic substitution.&lt;br /&gt;
&lt;br /&gt;
=== Conformance rules ===&lt;br /&gt;
&lt;br /&gt;
A type &amp;lt;e&amp;gt;b: C..D&amp;lt;/e&amp;gt; conforms to the type &amp;lt;e&amp;gt;a: A..B&amp;lt;/e&amp;gt; if &amp;lt;e&amp;gt;C&amp;lt;/e&amp;gt; conforms to &amp;lt;e&amp;gt;A&amp;lt;/e&amp;gt; and &amp;lt;e&amp;gt;B&amp;lt;/e&amp;gt; conforms to &amp;lt;e&amp;gt;D&amp;lt;/e&amp;gt;. The conformance rules for generics differ depending on the variance mark:&lt;br /&gt;
&lt;br /&gt;
* A generic conforms to a novariant generic if it has the exact same generic parameter. Thus &amp;lt;e&amp;gt;LIST [T]&amp;lt;/e&amp;gt; only conforms to &amp;lt;e&amp;gt;LIST [T]&amp;lt;/e&amp;gt;.&lt;br /&gt;
* A generic conforms to a covariant generic if its generic parameter conforms to the generic parameter of the covariant generic. Thus &amp;lt;e&amp;gt;LIST [U]&amp;lt;/e&amp;gt; conforms to &amp;lt;e&amp;gt;LIST [+T]&amp;lt;/e&amp;gt;.&lt;br /&gt;
* A generic conforms to a contravariant generic if its generic parameter is a parent of the generic parameter of the contravariant generic. Thus &amp;lt;e&amp;gt;LIST [T]&amp;lt;/e&amp;gt; conforms to &amp;lt;e&amp;gt;LIST [-U]&amp;lt;/e&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Default behaviour ===&lt;br /&gt;
&lt;br /&gt;
The default for a type declaration is that the interval contains the type up to &amp;lt;e&amp;gt;NONE&amp;lt;/e&amp;gt; (note that it is assumed that &amp;lt;e&amp;gt;NONE&amp;lt;/e&amp;gt; also conforms to expanded types. See the [[Interval_types#Conclusion|conclusion of interval types]] for more information.):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;e&amp;gt;&lt;br /&gt;
a: ANY  -- means ANY..NONE&lt;br /&gt;
&amp;lt;/e&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This allows that in the default case all descendants of a type can be assigned.&lt;br /&gt;
&lt;br /&gt;
The default for generic arguments is novariance. This allows that all features can be called on a generic without restrictions.&lt;br /&gt;
&lt;br /&gt;
By choosing these defaults, most code which does not rely on covariant generic conformance should work as before:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;e&amp;gt;&lt;br /&gt;
local&lt;br /&gt;
  any: ANY                  -- means ANY..NONE&lt;br /&gt;
  list: LIST [ANY]          -- means LIST [ANY..NONE] .. NONE&lt;br /&gt;
  l_list: LINKED_LIST [ANY] -- means LINKED_LIST [ANY..NONE] .. NONE&lt;br /&gt;
do&lt;br /&gt;
  any := &amp;quot;abc&amp;quot;&lt;br /&gt;
  any := 8&lt;br /&gt;
  list := l_list&lt;br /&gt;
  list.put (any)&lt;br /&gt;
  list.put (&amp;quot;abc&amp;quot;)&lt;br /&gt;
  any := list.item.out&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/e&amp;gt;&lt;br /&gt;
&lt;br /&gt;
What won't work as before is conformance of generics. The generic parameter of the target type will have to be marked as covariant, thus the features which have formal arguments cannot be called anymore.&lt;br /&gt;
&lt;br /&gt;
== Examples ==&lt;br /&gt;
&lt;br /&gt;
See the [[introduction to examples]] for information about the classes used.&lt;br /&gt;
&lt;br /&gt;
=== Combining the mechanisms ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;e&amp;gt;&lt;br /&gt;
local&lt;br /&gt;
  dog: DOG        -- means DOG..NONE&lt;br /&gt;
  cat: CAT        -- means CAT..NONE&lt;br /&gt;
  animal: ANIMAL  -- means ANIMAL..NONE&lt;br /&gt;
  animal_list: LIST [ANIMAL]  -- means LIST [ANIMAL..NONE] .. NONE&lt;br /&gt;
  animal_dog_list: LIST [ANIMAL..DOG]&lt;br /&gt;
  read_any_list: LIST [+ANY]  -- means LIST [+ ANY..NONE] .. NONE&lt;br /&gt;
do&lt;br /&gt;
    -- valid&lt;br /&gt;
  dog.eat (food)&lt;br /&gt;
  cat.eat (cat_food)&lt;br /&gt;
  animal.eat (cat_food)&lt;br /&gt;
&lt;br /&gt;
    -- invalid&lt;br /&gt;
  animal.eat (food) -- could be a CAT&lt;br /&gt;
&lt;br /&gt;
    -- valid&lt;br /&gt;
  animal_list.put (dog)&lt;br /&gt;
  animal_list.put (cat)&lt;br /&gt;
  animal_list.eat (cat_food)&lt;br /&gt;
  animal_dog_list.eat (food)&lt;br /&gt;
  read_any_list := animal_list&lt;br /&gt;
&lt;br /&gt;
    -- invalid&lt;br /&gt;
  read_any_list.put (&amp;quot;abc&amp;quot;)&lt;br /&gt;
  animal_list.eat (food) -- could be a CAT&lt;br /&gt;
&lt;br /&gt;
    -- types&lt;br /&gt;
  animal_list.item = {ANIMAL..NONE}&lt;br /&gt;
  animal_dog_list.item = {ANIMAL..DOG}&lt;br /&gt;
  read_any_list.item = {ANY..NONE}&lt;br /&gt;
&lt;br /&gt;
  animal_dog_list.put ({ANIMAL..DOG})  &lt;br /&gt;
  animal_list.put ({ANIMAL..NONE})&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/e&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Cats and dogs ===&lt;br /&gt;
&lt;br /&gt;
See the [[Interval_types#Cats_and_dogs|interval types]] example.&lt;br /&gt;
&lt;br /&gt;
=== A simple generic algorithm ===&lt;br /&gt;
&lt;br /&gt;
See the [[Usage-site_variance#A_simple_generic_algorithm|usage-site variance]] example.&lt;/div&gt;</summary>
		<author><name>Juliant</name></author>	</entry>

	<entry>
		<id>https://dev.eiffel.com/index.php?title=Interval_types&amp;diff=8944</id>
		<title>Interval types</title>
		<link rel="alternate" type="text/html" href="https://dev.eiffel.com/index.php?title=Interval_types&amp;diff=8944"/>
				<updated>2007-07-06T02:45:12Z</updated>
		
		<summary type="html">&lt;p&gt;Juliant: /* Conclusion */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Category:ECMA]]&lt;br /&gt;
[[Category:Catcall]]&lt;br /&gt;
{{Research}}&lt;br /&gt;
== Introduction ==&lt;br /&gt;
&lt;br /&gt;
With interval types, the programmer can restrict the conforming types for an entity. This way, the type set which needs to be checked for system validity of a feature call is restricted to a smaller set of types. In addition, certain rules for generic types will prohibit the unsafe use of generics.&lt;br /&gt;
&lt;br /&gt;
== Syntax ==&lt;br /&gt;
&lt;br /&gt;
At every location where a normal type is expected, an interval type can be specified by adding an upper bound for each type:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;e&amp;gt;&lt;br /&gt;
LOWER..UPPER&lt;br /&gt;
&amp;lt;/e&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This specifies an interval of all types between the types &amp;lt;e&amp;gt;LOWER&amp;lt;/e&amp;gt; and &amp;lt;e&amp;gt;UPPER&amp;lt;/e&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== Semantics ==&lt;br /&gt;
&lt;br /&gt;
The intention of an interval type is to specify that an entity can only be attached to a type which lies inside the interval. Thus a type declared as &amp;lt;e&amp;gt;ANY..STRING&amp;lt;/e&amp;gt; can be attached to an object of dynamic type &amp;lt;e&amp;gt;ANY&amp;lt;/e&amp;gt; or dynamic type &amp;lt;e&amp;gt;STRING&amp;lt;/e&amp;gt;. It cannot be attached to an object of a type which lies outside this interval, for example &amp;lt;e&amp;gt;INTEGER&amp;lt;/e&amp;gt; or &amp;lt;e&amp;gt;PATH_NAME&amp;lt;/e&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Each interval type describes the set of types which belong to the interval. A type belongs to the inverval if it conforms to the lower bound (&amp;lt;e&amp;gt;LOWER&amp;lt;/e&amp;gt;) and if the upper bound (&amp;lt;e&amp;gt;UPPER&amp;lt;/e&amp;gt;) conforms to it.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;e&amp;gt;&lt;br /&gt;
a: A .. C &amp;lt;=&amp;gt; {A, B, C}&lt;br /&gt;
b: A .. B &amp;lt;=&amp;gt; {A, B}&lt;br /&gt;
c: A .. NONE &amp;lt;=&amp;gt; {A, B, C, ...}&lt;br /&gt;
&amp;lt;/e&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Conformance rules ===&lt;br /&gt;
&lt;br /&gt;
An interval type ''b'' conforms to an interval type ''a'' if it is a sub-interval of ''a''. So if ''a'' fully encloses the interval ''b'', ''b'' conforms to ''a''.&lt;br /&gt;
&lt;br /&gt;
The conformance rules can also be explained by differently:&lt;br /&gt;
&lt;br /&gt;
* An interval type ''b'' conforms to an interval type ''a'' if the set of types described by the interval of ''b'' is a subset of the set described by the interval of ''a''.&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;e&amp;gt;&lt;br /&gt;
a := b -- Is valid as {A, B} is a subset of {A, B, C}&lt;br /&gt;
&amp;lt;/e&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* A type &amp;lt;e&amp;gt;b: C..D&amp;lt;/e&amp;gt; conforms to the type &amp;lt;e&amp;gt;a: A..B&amp;lt;/e&amp;gt; if &amp;lt;e&amp;gt;C&amp;lt;/e&amp;gt; conforms to &amp;lt;e&amp;gt;A&amp;lt;/e&amp;gt; and &amp;lt;e&amp;gt;B&amp;lt;/e&amp;gt; conforms to &amp;lt;e&amp;gt;D&amp;lt;/e&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Generic conformance is the same as it is now: A generic type ''b'' conforms to a generic type ''a'' if the base class of ''b'' conforms to ''a'' and all generic parameters conform as well.&lt;br /&gt;
&lt;br /&gt;
=== Generic features ===&lt;br /&gt;
&lt;br /&gt;
For features with formal arguments, another rule exists: A call on a feature wich contains a formal argument is only valid if the generic substitution is monomorphic.&lt;br /&gt;
&lt;br /&gt;
This means that a call on a feature &amp;lt;e&amp;gt;f (g: G)&amp;lt;/e&amp;gt; of a class &amp;lt;e&amp;gt;X [G]&amp;lt;/e&amp;gt; is only valid if &amp;lt;e&amp;gt;G&amp;lt;/e&amp;gt; is monomorphic. Thus the type has to be instantitated with &amp;lt;e&amp;gt;X [Y..Y]&amp;lt;/e&amp;gt;. So a call to &amp;lt;e&amp;gt;f&amp;lt;/e&amp;gt; on a type &amp;lt;e&amp;gt;X [Y..NONE]&amp;lt;/e&amp;gt; is not allowed.&lt;br /&gt;
&lt;br /&gt;
=== Default behaviour ===&lt;br /&gt;
&lt;br /&gt;
As a shorthand for interval definition, we define the following default behaviour which is different for ordinary types and for actual generic type parameters. Ordinary types are per default polymorphic and actual formal parameters monomorphic:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;e&amp;gt;&lt;br /&gt;
x: T &amp;lt;=&amp;gt; T .. NONE&lt;br /&gt;
y: A [T] &amp;lt;=&amp;gt; A [T .. T] .. NONE&lt;br /&gt;
&amp;lt;/e&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Examples ==&lt;br /&gt;
&lt;br /&gt;
See the [[introduction to examples]] for information about the classes used.&lt;br /&gt;
&lt;br /&gt;
=== Cats and dogs ===&lt;br /&gt;
&lt;br /&gt;
A feature call on a target ''t'' is only valid if it is valid for all polymorphic types which can possibly be assigned to ''t''. With interval types the set of conforming types can be restriced in order to be able to perform calls to features which are covariantly redefined in descendands by excluding such descendants from the dynamic type set. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;e&amp;gt;&lt;br /&gt;
a_none: ANIMAL &amp;lt;=&amp;gt; ANIMAL .. NONE&lt;br /&gt;
c_none: CAT &amp;lt;=&amp;gt; ANIMAL .. NONE&lt;br /&gt;
d_none: DOG &amp;lt;=&amp;gt; ANIMAL .. NONE&lt;br /&gt;
a_a: ANIMAL .. ANIMAL&lt;br /&gt;
c_c: CAT .. CAT&lt;br /&gt;
d_d: DOG .. DOG&lt;br /&gt;
a_c: ANIMAL .. CAT&lt;br /&gt;
a_d: ANIMAL .. DOG&lt;br /&gt;
&amp;lt;/e&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Valid assignments:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;e&amp;gt;&lt;br /&gt;
a_none := c_none&lt;br /&gt;
a_none := d_none&lt;br /&gt;
a_none := a_a&lt;br /&gt;
a_none := c_c&lt;br /&gt;
a_none := d_d&lt;br /&gt;
c_none := c_c&lt;br /&gt;
d_none := d_d&lt;br /&gt;
&lt;br /&gt;
a_c := a_a&lt;br /&gt;
a_c := c_c&lt;br /&gt;
a_d := a_a&lt;br /&gt;
a_d := d_d&lt;br /&gt;
&amp;lt;/e&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Invalid assignments:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;e&amp;gt;&lt;br /&gt;
-- Invalid: a_a := a_none&lt;br /&gt;
-- Invalid: c_c := c_none&lt;br /&gt;
-- Invalid: d_d := d_none&lt;br /&gt;
-- Invalid: a_c := c_none&lt;br /&gt;
-- Invalid: a_d := d_none&lt;br /&gt;
&amp;lt;/e&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Valid calls:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;e&amp;gt;&lt;br /&gt;
a_none.eat (cat_food)&lt;br /&gt;
a_a.eat (food)&lt;br /&gt;
a_d.eat (food)&lt;br /&gt;
&amp;lt;/e&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Invalid calls:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;e&amp;gt;&lt;br /&gt;
a_none.eat (food)&lt;br /&gt;
&amp;lt;/e&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== A simple generic algorithm ===&lt;br /&gt;
&lt;br /&gt;
It is easy to declare an algorithm which needs only read-access on a list:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;e&amp;gt;&lt;br /&gt;
class PERSON_PRINTER&lt;br /&gt;
feature&lt;br /&gt;
  print_all (a_list: LIST [PERSON..NONE])&lt;br /&gt;
      -- Print all attributes of each person in the list.&lt;br /&gt;
    do&lt;br /&gt;
      from&lt;br /&gt;
        a_list.start&lt;br /&gt;
      until&lt;br /&gt;
        a_list.after&lt;br /&gt;
      do &lt;br /&gt;
          -- Reading is valid on a covariant list&lt;br /&gt;
        a_list.item.print&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
end&lt;br /&gt;
 &lt;br /&gt;
class EXAMPLE&lt;br /&gt;
feature&lt;br /&gt;
  make&lt;br /&gt;
    local&lt;br /&gt;
      l_students: LIST [STUDENT]       &amp;lt;=&amp;gt; LIST [STUDENT..STUDENT]&lt;br /&gt;
      l_professors: LIST [PROFESSOR]   &amp;lt;=&amp;gt; LIST [PROFESSOR..PROFESSOR]&lt;br /&gt;
      l_person_printer: PERSON_PRINTER&lt;br /&gt;
    do&lt;br /&gt;
      create l_person_printer&lt;br /&gt;
        -- LIST [STUDENT..STUDENT] conforms to LIST [PERSON..NONE]&lt;br /&gt;
      l_person_printer.print_all (l_students)&lt;br /&gt;
        -- LIST [PROFESSOR..PROFESSOR] conforms to LIST [PERSON..NONE]&lt;br /&gt;
      l_person_printer.print_all (l_professor)&lt;br /&gt;
    end&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/e&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Issues ==&lt;br /&gt;
&lt;br /&gt;
=== Generic features ===&lt;br /&gt;
&lt;br /&gt;
The rule about calling features with formal parameters is too restrictive. Let's look at the following code:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;e&amp;gt;&lt;br /&gt;
deferred class COMPONENT&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
class COMPOSITE&lt;br /&gt;
inherit COMPONENT&lt;br /&gt;
feature&lt;br /&gt;
  components: LIST [COMPONENT]&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/e&amp;gt;&lt;br /&gt;
&lt;br /&gt;
What should the type of feature &amp;lt;e&amp;gt;components&amp;lt;/e&amp;gt; be? In order to be able to call &amp;lt;e&amp;gt;extend&amp;lt;/e&amp;gt; on the list, it has to be monomorphic, thus &amp;lt;e&amp;gt;LIST [COMPONENT..COMPONENT]&amp;lt;/e&amp;gt;. But since the argument type is now &amp;lt;e&amp;gt;COMPONENT..COMPONENT&amp;lt;/e&amp;gt; we actually cannot add anything to the list as no descendant of &amp;lt;e&amp;gt;COMPONENT&amp;lt;/e&amp;gt; is in the interval. Actually, since &amp;lt;e&amp;gt;COMPONENT&amp;lt;/e&amp;gt; is deferred nothing can be added to the list at all.&lt;br /&gt;
&lt;br /&gt;
But if we define the list as &amp;lt;e&amp;gt;LIST [COMPONENT..NONE]&amp;lt;/e&amp;gt; - thus allowing descendants of &amp;lt;e&amp;gt;COMPONENT&amp;lt;/e&amp;gt; in the list - then the rule about features with formal arguments disallows any calls to feature &amp;lt;e&amp;gt;extend&amp;lt;/e&amp;gt; as the argument is not monomorphic anymore.&lt;br /&gt;
&lt;br /&gt;
=== Expanded and Void ===&lt;br /&gt;
&lt;br /&gt;
Look at the following code snippet:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;e&amp;gt;&lt;br /&gt;
local&lt;br /&gt;
  any_none: ANY..NONE&lt;br /&gt;
  any_string: ANY..STRING&lt;br /&gt;
do&lt;br /&gt;
    -- invalid as NONE does not conform to INTEGER&lt;br /&gt;
  any_none := 5&lt;br /&gt;
    -- invalid as NONE is not in the interval ANY..STRING&lt;br /&gt;
  any_string := Void&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/e&amp;gt;&lt;br /&gt;
&lt;br /&gt;
It illustrates two problems in conjunction with &amp;lt;e&amp;gt;NONE&amp;lt;/e&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
* The first is that &amp;lt;e&amp;gt;NONE&amp;lt;/e&amp;gt; does not conform to expanded types. This makes it impossible to declare a type interval which includes all types in the system, reference or expanded. This prevents the programmer to write code which works with reference types and expanded types, say a generic print algorithm.&lt;br /&gt;
* The second one is that &amp;lt;e&amp;gt;Void&amp;lt;/e&amp;gt; is of type &amp;lt;e&amp;gt;NONE&amp;lt;/e&amp;gt;. This raises the question how &amp;lt;e&amp;gt;Void&amp;lt;/e&amp;gt; should be assigned to an interval type of references, or how such a type is initialized in the first place.&lt;br /&gt;
&lt;br /&gt;
== Conclusion ==&lt;br /&gt;
&lt;br /&gt;
The rule about features with formal parameters must be changed to make this solution usable as otherwise the use of generics is restricted too much.&lt;br /&gt;
&lt;br /&gt;
The problem with &amp;lt;e&amp;gt;Void&amp;lt;/e&amp;gt; and &amp;lt;e&amp;gt;NONE&amp;lt;/e&amp;gt; can easily be solved by declaring that &amp;lt;e&amp;gt;NONE&amp;lt;/e&amp;gt; inherits from all types regardless of reference or expanded status. To solve the problem of assigning &amp;lt;e&amp;gt;Void&amp;lt;/e&amp;gt; to an interval type it can be defined that &amp;lt;e&amp;gt;Void&amp;lt;/e&amp;gt; is of any (detached) reference type. You could for example say that &amp;lt;e&amp;gt;Void&amp;lt;/e&amp;gt; always has the type of the lower bound of the target interval if this type is a (detached) reference type. That way it can be assigned to any interval of a refernce type, even a monomorphic one, and it is still disallowed to assign it to expanded types.&lt;/div&gt;</summary>
		<author><name>Juliant</name></author>	</entry>

	<entry>
		<id>https://dev.eiffel.com/index.php?title=Interval_types_and_usage-site_variance&amp;diff=8943</id>
		<title>Interval types and usage-site variance</title>
		<link rel="alternate" type="text/html" href="https://dev.eiffel.com/index.php?title=Interval_types_and_usage-site_variance&amp;diff=8943"/>
				<updated>2007-07-06T02:41:25Z</updated>
		
		<summary type="html">&lt;p&gt;Juliant: /* Semantics */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Category:ECMA]]&lt;br /&gt;
[[Category:Catcall]]&lt;br /&gt;
{{Research}}&lt;br /&gt;
== Introduction ==&lt;br /&gt;
&lt;br /&gt;
This is a proposition to combine two mechanisms to prevent catcalls, the [[interval types]] for non-generics and the [[usage-site variance]] for generics.&lt;br /&gt;
&lt;br /&gt;
The reason for this is that up to now all approaches failed to deliver an easy and concise solution to solve the problem of catcalls in general. &lt;br /&gt;
&lt;br /&gt;
Interval types work well for non-generic types and the overhead for the type declaration is minimal with a sensitive default behaviour, but for generics it does not really work.&lt;br /&gt;
&lt;br /&gt;
Usage-site variance is a promising solution for generics with just the small addition of a flag for the kind of variance needed on a generic derivation. And again, the default behaviour will allow most uses of a generic type as the programmer expects it to work.&lt;br /&gt;
&lt;br /&gt;
== Syntax ==&lt;br /&gt;
&lt;br /&gt;
Types can be specified as an interval:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;e&amp;gt;LOWER..UPPER&amp;lt;/e&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Generic parameters can be marked to select the variance:&lt;br /&gt;
&lt;br /&gt;
* To specify a novariant generic, the normal syntax can be used: &amp;lt;e&amp;gt;LIST [ANY]&amp;lt;/e&amp;gt;&lt;br /&gt;
* To specify a covariant generic, we use a plus sign: &amp;lt;e&amp;gt;LIST [+ANY]&amp;lt;/e&amp;gt;&lt;br /&gt;
* To specify a contravariant generic, we use a minus sign: &amp;lt;e&amp;gt;LIST [-ANY]&amp;lt;/e&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Semantics ==&lt;br /&gt;
&lt;br /&gt;
Each interval type describes the set of types which belong to the interval. A type belongs to the inverval if it conforms to the lower bound (&amp;lt;e&amp;gt;LOWER&amp;lt;/e&amp;gt;) and if the upper bound (&amp;lt;e&amp;gt;UPPER&amp;lt;/e&amp;gt;) conforms to it. All feature calls will be subject to whole-system validity and by restricting the dynamic type set to the types in the interval this check can be influenced.&lt;br /&gt;
&lt;br /&gt;
For generics the applicable features depend on the variance mark used:&lt;br /&gt;
&lt;br /&gt;
* On a novariant generic, all features can be used.&lt;br /&gt;
* On a covariant generic, only features which have the formal generic as a result type can be used. If the formal generic appears in an argument this feature is invalid.&lt;br /&gt;
* On a contravariant generic, only feature which have the formal generc as an argument type can be used. If the formal generic appears as a result type this feature is invalid.&lt;br /&gt;
&lt;br /&gt;
The two mechanisms can also be combined. A generic parameter can be an interval type and can also have a variance modifier. The normal generic substituion applies to every formal generic by replacing the generic with the interval type. The variance marks are only used for conformance checks and don't affect the generic substitution.&lt;br /&gt;
&lt;br /&gt;
=== Conformance rules ===&lt;br /&gt;
&lt;br /&gt;
A type &amp;lt;e&amp;gt;b: C..D&amp;lt;/e&amp;gt; conforms to the type &amp;lt;e&amp;gt;a: A..B&amp;lt;/e&amp;gt; if &amp;lt;e&amp;gt;C&amp;lt;/e&amp;gt; conforms to &amp;lt;e&amp;gt;A&amp;lt;/e&amp;gt; and &amp;lt;e&amp;gt;B&amp;lt;/e&amp;gt; conforms to &amp;lt;e&amp;gt;D&amp;lt;/e&amp;gt;. The conformance rules for generics differ depending on the variance mark:&lt;br /&gt;
&lt;br /&gt;
* A generic conforms to a novariant generic if it has the exact same generic parameter. Thus &amp;lt;e&amp;gt;LIST [T]&amp;lt;/e&amp;gt; only conforms to &amp;lt;e&amp;gt;LIST [T]&amp;lt;/e&amp;gt;.&lt;br /&gt;
* A generic conforms to a covariant generic if its generic parameter conforms to the generic parameter of the covariant generic. Thus &amp;lt;e&amp;gt;LIST [U]&amp;lt;/e&amp;gt; conforms to &amp;lt;e&amp;gt;LIST [+T]&amp;lt;/e&amp;gt;.&lt;br /&gt;
* A generic conforms to a contravariant generic if its generic parameter is a parent of the generic parameter of the contravariant generic. Thus &amp;lt;e&amp;gt;LIST [T]&amp;lt;/e&amp;gt; conforms to &amp;lt;e&amp;gt;LIST [-U]&amp;lt;/e&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Default behaviour ===&lt;br /&gt;
&lt;br /&gt;
The default for a type declaration is that the interval contains the type up to &amp;lt;e&amp;gt;NONE&amp;lt;/e&amp;gt; (note that it is assumed that &amp;lt;e&amp;gt;NONE&amp;lt;/e&amp;gt; also conforms to expanded types):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;e&amp;gt;&lt;br /&gt;
a: ANY  -- means ANY..NONE&lt;br /&gt;
&amp;lt;/e&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This allows that in the default case all descendants of a type can be assigned.&lt;br /&gt;
&lt;br /&gt;
The default for generic arguments is novariance. This allows that all features can be called on a generic without restrictions.&lt;br /&gt;
&lt;br /&gt;
By choosing these defaults, most code which does not rely on covariant generic conformance should work as before:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;e&amp;gt;&lt;br /&gt;
local&lt;br /&gt;
  any: ANY                  -- means ANY..NONE&lt;br /&gt;
  list: LIST [ANY]          -- means LIST [ANY..NONE] .. NONE&lt;br /&gt;
  l_list: LINKED_LIST [ANY] -- means LINKED_LIST [ANY..NONE] .. NONE&lt;br /&gt;
do&lt;br /&gt;
  any := &amp;quot;abc&amp;quot;&lt;br /&gt;
  any := 8&lt;br /&gt;
  list := l_list&lt;br /&gt;
  list.put (any)&lt;br /&gt;
  list.put (&amp;quot;abc&amp;quot;)&lt;br /&gt;
  any := list.item.out&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/e&amp;gt;&lt;br /&gt;
&lt;br /&gt;
What won't work as before is conformance of generics. The generic parameter of the target type will have to be marked as covariant, thus the features which have formal arguments cannot be called anymore.&lt;br /&gt;
&lt;br /&gt;
== Examples ==&lt;br /&gt;
&lt;br /&gt;
See the [[introduction to examples]] for information about the classes used.&lt;br /&gt;
&lt;br /&gt;
=== Combining the mechanisms ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;e&amp;gt;&lt;br /&gt;
local&lt;br /&gt;
  dog: DOG        -- means DOG..NONE&lt;br /&gt;
  cat: CAT        -- means CAT..NONE&lt;br /&gt;
  animal: ANIMAL  -- means ANIMAL..NONE&lt;br /&gt;
  animal_list: LIST [ANIMAL]  -- means LIST [ANIMAL..NONE] .. NONE&lt;br /&gt;
  animal_dog_list: LIST [ANIMAL..DOG]&lt;br /&gt;
  read_any_list: LIST [+ANY]  -- means LIST [+ ANY..NONE] .. NONE&lt;br /&gt;
do&lt;br /&gt;
    -- valid&lt;br /&gt;
  dog.eat (food)&lt;br /&gt;
  cat.eat (cat_food)&lt;br /&gt;
  animal.eat (cat_food)&lt;br /&gt;
&lt;br /&gt;
    -- invalid&lt;br /&gt;
  animal.eat (food) -- could be a CAT&lt;br /&gt;
&lt;br /&gt;
    -- valid&lt;br /&gt;
  animal_list.put (dog)&lt;br /&gt;
  animal_list.put (cat)&lt;br /&gt;
  animal_list.eat (cat_food)&lt;br /&gt;
  animal_dog_list.eat (food)&lt;br /&gt;
  read_any_list := animal_list&lt;br /&gt;
&lt;br /&gt;
    -- invalid&lt;br /&gt;
  read_any_list.put (&amp;quot;abc&amp;quot;)&lt;br /&gt;
  animal_list.eat (food) -- could be a CAT&lt;br /&gt;
&lt;br /&gt;
    -- types&lt;br /&gt;
  animal_list.item = {ANIMAL..NONE}&lt;br /&gt;
  animal_dog_list.item = {ANIMAL..DOG}&lt;br /&gt;
  read_any_list.item = {ANY..NONE}&lt;br /&gt;
&lt;br /&gt;
  animal_dog_list.put ({ANIMAL..DOG})  &lt;br /&gt;
  animal_list.put ({ANIMAL..NONE})&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/e&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Cats and dogs ===&lt;br /&gt;
&lt;br /&gt;
See the [[Interval_types#Cats_and_dogs|interval types]] example.&lt;br /&gt;
&lt;br /&gt;
=== A simple generic algorithm ===&lt;br /&gt;
&lt;br /&gt;
See the [[Usage-site_variance#A_simple_generic_algorithm|usage-site variance]] example.&lt;/div&gt;</summary>
		<author><name>Juliant</name></author>	</entry>

	<entry>
		<id>https://dev.eiffel.com/index.php?title=Interval_types_and_usage-site_variance&amp;diff=8942</id>
		<title>Interval types and usage-site variance</title>
		<link rel="alternate" type="text/html" href="https://dev.eiffel.com/index.php?title=Interval_types_and_usage-site_variance&amp;diff=8942"/>
				<updated>2007-07-06T02:31:02Z</updated>
		
		<summary type="html">&lt;p&gt;Juliant: /* Default behaviour */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Category:ECMA]]&lt;br /&gt;
[[Category:Catcall]]&lt;br /&gt;
{{Research}}&lt;br /&gt;
== Introduction ==&lt;br /&gt;
&lt;br /&gt;
This is a proposition to combine two mechanisms to prevent catcalls, the [[interval types]] for non-generics and the [[usage-site variance]] for generics.&lt;br /&gt;
&lt;br /&gt;
The reason for this is that up to now all approaches failed to deliver an easy and concise solution to solve the problem of catcalls in general. &lt;br /&gt;
&lt;br /&gt;
Interval types work well for non-generic types and the overhead for the type declaration is minimal with a sensitive default behaviour, but for generics it does not really work.&lt;br /&gt;
&lt;br /&gt;
Usage-site variance is a promising solution for generics with just the small addition of a flag for the kind of variance needed on a generic derivation. And again, the default behaviour will allow most uses of a generic type as the programmer expects it to work.&lt;br /&gt;
&lt;br /&gt;
== Syntax ==&lt;br /&gt;
&lt;br /&gt;
Types can be specified as an interval:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;e&amp;gt;LOWER..UPPER&amp;lt;/e&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Generic parameters can be marked to select the variance:&lt;br /&gt;
&lt;br /&gt;
* To specify a novariant generic, the normal syntax can be used: &amp;lt;e&amp;gt;LIST [ANY]&amp;lt;/e&amp;gt;&lt;br /&gt;
* To specify a covariant generic, we use a plus sign: &amp;lt;e&amp;gt;LIST [+ANY]&amp;lt;/e&amp;gt;&lt;br /&gt;
* To specify a contravariant generic, we use a minus sign: &amp;lt;e&amp;gt;LIST [-ANY]&amp;lt;/e&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Semantics ==&lt;br /&gt;
&lt;br /&gt;
Each interval type describes the set of types which belong to the interval. A type belongs to the inverval if it conforms to the lower bound (&amp;lt;e&amp;gt;LOWER&amp;lt;/e&amp;gt;) and if the upper bound (&amp;lt;e&amp;gt;UPPER&amp;lt;/e&amp;gt;) conforms to it. All feature calls will be subject to whole-system validity and by restricting the dynamic type set to the types in the interval this check can be influenced.&lt;br /&gt;
&lt;br /&gt;
For generics the applicable features depend on the variance mark used:&lt;br /&gt;
&lt;br /&gt;
* On a novariant generic, all features can be used.&lt;br /&gt;
* On a covariant generic, only features which have the formal generic as a result type can be used. If the formal generic appears in an argument this feature is invalid.&lt;br /&gt;
* On a contravariant generic, only feature which have the formal generc as an argument type can be used. If the formal generic appears as a result type this feature is invalid.&lt;br /&gt;
&lt;br /&gt;
=== Conformance rules ===&lt;br /&gt;
&lt;br /&gt;
A type &amp;lt;e&amp;gt;b: C..D&amp;lt;/e&amp;gt; conforms to the type &amp;lt;e&amp;gt;a: A..B&amp;lt;/e&amp;gt; if &amp;lt;e&amp;gt;C&amp;lt;/e&amp;gt; conforms to &amp;lt;e&amp;gt;A&amp;lt;/e&amp;gt; and &amp;lt;e&amp;gt;B&amp;lt;/e&amp;gt; conforms to &amp;lt;e&amp;gt;D&amp;lt;/e&amp;gt;. The conformance rules for generics differ depending on the variance mark:&lt;br /&gt;
&lt;br /&gt;
* A generic conforms to a novariant generic if it has the exact same generic parameter. Thus &amp;lt;e&amp;gt;LIST [T]&amp;lt;/e&amp;gt; only conforms to &amp;lt;e&amp;gt;LIST [T]&amp;lt;/e&amp;gt;.&lt;br /&gt;
* A generic conforms to a covariant generic if its generic parameter conforms to the generic parameter of the covariant generic. Thus &amp;lt;e&amp;gt;LIST [U]&amp;lt;/e&amp;gt; conforms to &amp;lt;e&amp;gt;LIST [+T]&amp;lt;/e&amp;gt;.&lt;br /&gt;
* A generic conforms to a contravariant generic if its generic parameter is a parent of the generic parameter of the contravariant generic. Thus &amp;lt;e&amp;gt;LIST [T]&amp;lt;/e&amp;gt; conforms to &amp;lt;e&amp;gt;LIST [-U]&amp;lt;/e&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Default behaviour ===&lt;br /&gt;
&lt;br /&gt;
The default for a type declaration is that the interval contains the type up to &amp;lt;e&amp;gt;NONE&amp;lt;/e&amp;gt; (note that it is assumed that &amp;lt;e&amp;gt;NONE&amp;lt;/e&amp;gt; also conforms to expanded types):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;e&amp;gt;&lt;br /&gt;
a: ANY  -- means ANY..NONE&lt;br /&gt;
&amp;lt;/e&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This allows that in the default case all descendants of a type can be assigned.&lt;br /&gt;
&lt;br /&gt;
The default for generic arguments is novariance. This allows that all features can be called on a generic without restrictions.&lt;br /&gt;
&lt;br /&gt;
By choosing these defaults, most code which does not rely on covariant generic conformance should work as before:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;e&amp;gt;&lt;br /&gt;
local&lt;br /&gt;
  any: ANY                  -- means ANY..NONE&lt;br /&gt;
  list: LIST [ANY]          -- means LIST [ANY..NONE] .. NONE&lt;br /&gt;
  l_list: LINKED_LIST [ANY] -- means LINKED_LIST [ANY..NONE] .. NONE&lt;br /&gt;
do&lt;br /&gt;
  any := &amp;quot;abc&amp;quot;&lt;br /&gt;
  any := 8&lt;br /&gt;
  list := l_list&lt;br /&gt;
  list.put (any)&lt;br /&gt;
  list.put (&amp;quot;abc&amp;quot;)&lt;br /&gt;
  any := list.item.out&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/e&amp;gt;&lt;br /&gt;
&lt;br /&gt;
What won't work as before is conformance of generics. The generic parameter of the target type will have to be marked as covariant, thus the features which have formal arguments cannot be called anymore.&lt;br /&gt;
&lt;br /&gt;
== Examples ==&lt;br /&gt;
&lt;br /&gt;
See the [[introduction to examples]] for information about the classes used.&lt;br /&gt;
&lt;br /&gt;
=== Combining the mechanisms ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;e&amp;gt;&lt;br /&gt;
local&lt;br /&gt;
  dog: DOG        -- means DOG..NONE&lt;br /&gt;
  cat: CAT        -- means CAT..NONE&lt;br /&gt;
  animal: ANIMAL  -- means ANIMAL..NONE&lt;br /&gt;
  animal_list: LIST [ANIMAL]  -- means LIST [ANIMAL..NONE] .. NONE&lt;br /&gt;
  animal_dog_list: LIST [ANIMAL..DOG]&lt;br /&gt;
  read_any_list: LIST [+ANY]  -- means LIST [+ ANY..NONE] .. NONE&lt;br /&gt;
do&lt;br /&gt;
    -- valid&lt;br /&gt;
  dog.eat (food)&lt;br /&gt;
  cat.eat (cat_food)&lt;br /&gt;
  animal.eat (cat_food)&lt;br /&gt;
&lt;br /&gt;
    -- invalid&lt;br /&gt;
  animal.eat (food) -- could be a CAT&lt;br /&gt;
&lt;br /&gt;
    -- valid&lt;br /&gt;
  animal_list.put (dog)&lt;br /&gt;
  animal_list.put (cat)&lt;br /&gt;
  animal_list.eat (cat_food)&lt;br /&gt;
  animal_dog_list.eat (food)&lt;br /&gt;
  read_any_list := animal_list&lt;br /&gt;
&lt;br /&gt;
    -- invalid&lt;br /&gt;
  read_any_list.put (&amp;quot;abc&amp;quot;)&lt;br /&gt;
  animal_list.eat (food) -- could be a CAT&lt;br /&gt;
&lt;br /&gt;
    -- types&lt;br /&gt;
  animal_list.item = {ANIMAL..NONE}&lt;br /&gt;
  animal_dog_list.item = {ANIMAL..DOG}&lt;br /&gt;
  read_any_list.item = {ANY..NONE}&lt;br /&gt;
&lt;br /&gt;
  animal_dog_list.put ({ANIMAL..DOG})  &lt;br /&gt;
  animal_list.put ({ANIMAL..NONE})&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/e&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Cats and dogs ===&lt;br /&gt;
&lt;br /&gt;
See the [[Interval_types#Cats_and_dogs|interval types]] example.&lt;br /&gt;
&lt;br /&gt;
=== A simple generic algorithm ===&lt;br /&gt;
&lt;br /&gt;
See the [[Usage-site_variance#A_simple_generic_algorithm|usage-site variance]] example.&lt;/div&gt;</summary>
		<author><name>Juliant</name></author>	</entry>

	<entry>
		<id>https://dev.eiffel.com/index.php?title=Interval_types_and_usage-site_variance&amp;diff=8941</id>
		<title>Interval types and usage-site variance</title>
		<link rel="alternate" type="text/html" href="https://dev.eiffel.com/index.php?title=Interval_types_and_usage-site_variance&amp;diff=8941"/>
				<updated>2007-07-06T02:29:40Z</updated>
		
		<summary type="html">&lt;p&gt;Juliant: /* Default behaviour */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Category:ECMA]]&lt;br /&gt;
[[Category:Catcall]]&lt;br /&gt;
{{Research}}&lt;br /&gt;
== Introduction ==&lt;br /&gt;
&lt;br /&gt;
This is a proposition to combine two mechanisms to prevent catcalls, the [[interval types]] for non-generics and the [[usage-site variance]] for generics.&lt;br /&gt;
&lt;br /&gt;
The reason for this is that up to now all approaches failed to deliver an easy and concise solution to solve the problem of catcalls in general. &lt;br /&gt;
&lt;br /&gt;
Interval types work well for non-generic types and the overhead for the type declaration is minimal with a sensitive default behaviour, but for generics it does not really work.&lt;br /&gt;
&lt;br /&gt;
Usage-site variance is a promising solution for generics with just the small addition of a flag for the kind of variance needed on a generic derivation. And again, the default behaviour will allow most uses of a generic type as the programmer expects it to work.&lt;br /&gt;
&lt;br /&gt;
== Syntax ==&lt;br /&gt;
&lt;br /&gt;
Types can be specified as an interval:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;e&amp;gt;LOWER..UPPER&amp;lt;/e&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Generic parameters can be marked to select the variance:&lt;br /&gt;
&lt;br /&gt;
* To specify a novariant generic, the normal syntax can be used: &amp;lt;e&amp;gt;LIST [ANY]&amp;lt;/e&amp;gt;&lt;br /&gt;
* To specify a covariant generic, we use a plus sign: &amp;lt;e&amp;gt;LIST [+ANY]&amp;lt;/e&amp;gt;&lt;br /&gt;
* To specify a contravariant generic, we use a minus sign: &amp;lt;e&amp;gt;LIST [-ANY]&amp;lt;/e&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Semantics ==&lt;br /&gt;
&lt;br /&gt;
Each interval type describes the set of types which belong to the interval. A type belongs to the inverval if it conforms to the lower bound (&amp;lt;e&amp;gt;LOWER&amp;lt;/e&amp;gt;) and if the upper bound (&amp;lt;e&amp;gt;UPPER&amp;lt;/e&amp;gt;) conforms to it. All feature calls will be subject to whole-system validity and by restricting the dynamic type set to the types in the interval this check can be influenced.&lt;br /&gt;
&lt;br /&gt;
For generics the applicable features depend on the variance mark used:&lt;br /&gt;
&lt;br /&gt;
* On a novariant generic, all features can be used.&lt;br /&gt;
* On a covariant generic, only features which have the formal generic as a result type can be used. If the formal generic appears in an argument this feature is invalid.&lt;br /&gt;
* On a contravariant generic, only feature which have the formal generc as an argument type can be used. If the formal generic appears as a result type this feature is invalid.&lt;br /&gt;
&lt;br /&gt;
=== Conformance rules ===&lt;br /&gt;
&lt;br /&gt;
A type &amp;lt;e&amp;gt;b: C..D&amp;lt;/e&amp;gt; conforms to the type &amp;lt;e&amp;gt;a: A..B&amp;lt;/e&amp;gt; if &amp;lt;e&amp;gt;C&amp;lt;/e&amp;gt; conforms to &amp;lt;e&amp;gt;A&amp;lt;/e&amp;gt; and &amp;lt;e&amp;gt;B&amp;lt;/e&amp;gt; conforms to &amp;lt;e&amp;gt;D&amp;lt;/e&amp;gt;. The conformance rules for generics differ depending on the variance mark:&lt;br /&gt;
&lt;br /&gt;
* A generic conforms to a novariant generic if it has the exact same generic parameter. Thus &amp;lt;e&amp;gt;LIST [T]&amp;lt;/e&amp;gt; only conforms to &amp;lt;e&amp;gt;LIST [T]&amp;lt;/e&amp;gt;.&lt;br /&gt;
* A generic conforms to a covariant generic if its generic parameter conforms to the generic parameter of the covariant generic. Thus &amp;lt;e&amp;gt;LIST [U]&amp;lt;/e&amp;gt; conforms to &amp;lt;e&amp;gt;LIST [+T]&amp;lt;/e&amp;gt;.&lt;br /&gt;
* A generic conforms to a contravariant generic if its generic parameter is a parent of the generic parameter of the contravariant generic. Thus &amp;lt;e&amp;gt;LIST [T]&amp;lt;/e&amp;gt; conforms to &amp;lt;e&amp;gt;LIST [-U]&amp;lt;/e&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Default behaviour ===&lt;br /&gt;
&lt;br /&gt;
The default for a type declaration is that the interval contains the type up to &amp;lt;e&amp;gt;NONE&amp;lt;/e&amp;gt; (note that it is assumed that &amp;lt;e&amp;gt;NONE&amp;lt;/e&amp;gt; also conforms to expanded types):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;e&amp;gt;&lt;br /&gt;
a: ANY  -- means ANY..NONE&lt;br /&gt;
&amp;lt;/e&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This allows that in the default case all descendants of a type can be assigned.&lt;br /&gt;
&lt;br /&gt;
The default for generic arguments is novariance. This allows that all features can be called on a generic without restrictions.&lt;br /&gt;
&lt;br /&gt;
By choosing these defaults, most code which does not rely on covariant generic conformance should work as before:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;e&amp;gt;&lt;br /&gt;
local&lt;br /&gt;
  any: ANY                  -- mean ANY..NONE&lt;br /&gt;
  list: LIST [ANY]          -- mean LIST [ANY..NONE] .. NONE&lt;br /&gt;
  l_list: LINKED_LIST [ANY] -- means LINKED_LIST [ANY..NONE] .. NONE&lt;br /&gt;
do&lt;br /&gt;
  any := &amp;quot;abc&amp;quot;&lt;br /&gt;
  any := 8&lt;br /&gt;
  list := l_list&lt;br /&gt;
  list.put (any)&lt;br /&gt;
  list.put (&amp;quot;abc&amp;quot;)&lt;br /&gt;
  any := list.item.out&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/e&amp;gt;&lt;br /&gt;
&lt;br /&gt;
What won't work as before is conformance of generics. The generic parameter of the target type will have to be marked as covariant, thus the features which have formal arguments cannot be called anymore.&lt;br /&gt;
&lt;br /&gt;
== Examples ==&lt;br /&gt;
&lt;br /&gt;
See the [[introduction to examples]] for information about the classes used.&lt;br /&gt;
&lt;br /&gt;
=== Combining the mechanisms ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;e&amp;gt;&lt;br /&gt;
local&lt;br /&gt;
  dog: DOG        -- means DOG..NONE&lt;br /&gt;
  cat: CAT        -- means CAT..NONE&lt;br /&gt;
  animal: ANIMAL  -- means ANIMAL..NONE&lt;br /&gt;
  animal_list: LIST [ANIMAL]  -- means LIST [ANIMAL..NONE] .. NONE&lt;br /&gt;
  animal_dog_list: LIST [ANIMAL..DOG]&lt;br /&gt;
  read_any_list: LIST [+ANY]  -- means LIST [+ ANY..NONE] .. NONE&lt;br /&gt;
do&lt;br /&gt;
    -- valid&lt;br /&gt;
  dog.eat (food)&lt;br /&gt;
  cat.eat (cat_food)&lt;br /&gt;
  animal.eat (cat_food)&lt;br /&gt;
&lt;br /&gt;
    -- invalid&lt;br /&gt;
  animal.eat (food) -- could be a CAT&lt;br /&gt;
&lt;br /&gt;
    -- valid&lt;br /&gt;
  animal_list.put (dog)&lt;br /&gt;
  animal_list.put (cat)&lt;br /&gt;
  animal_list.eat (cat_food)&lt;br /&gt;
  animal_dog_list.eat (food)&lt;br /&gt;
  read_any_list := animal_list&lt;br /&gt;
&lt;br /&gt;
    -- invalid&lt;br /&gt;
  read_any_list.put (&amp;quot;abc&amp;quot;)&lt;br /&gt;
  animal_list.eat (food) -- could be a CAT&lt;br /&gt;
&lt;br /&gt;
    -- types&lt;br /&gt;
  animal_list.item = {ANIMAL..NONE}&lt;br /&gt;
  animal_dog_list.item = {ANIMAL..DOG}&lt;br /&gt;
  read_any_list.item = {ANY..NONE}&lt;br /&gt;
&lt;br /&gt;
  animal_dog_list.put ({ANIMAL..DOG})  &lt;br /&gt;
  animal_list.put ({ANIMAL..NONE})&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/e&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Cats and dogs ===&lt;br /&gt;
&lt;br /&gt;
See the [[Interval_types#Cats_and_dogs|interval types]] example.&lt;br /&gt;
&lt;br /&gt;
=== A simple generic algorithm ===&lt;br /&gt;
&lt;br /&gt;
See the [[Usage-site_variance#A_simple_generic_algorithm|usage-site variance]] example.&lt;/div&gt;</summary>
		<author><name>Juliant</name></author>	</entry>

	<entry>
		<id>https://dev.eiffel.com/index.php?title=Interval_types_and_usage-site_variance&amp;diff=8940</id>
		<title>Interval types and usage-site variance</title>
		<link rel="alternate" type="text/html" href="https://dev.eiffel.com/index.php?title=Interval_types_and_usage-site_variance&amp;diff=8940"/>
				<updated>2007-07-06T02:27:37Z</updated>
		
		<summary type="html">&lt;p&gt;Juliant: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Category:ECMA]]&lt;br /&gt;
[[Category:Catcall]]&lt;br /&gt;
{{Research}}&lt;br /&gt;
== Introduction ==&lt;br /&gt;
&lt;br /&gt;
This is a proposition to combine two mechanisms to prevent catcalls, the [[interval types]] for non-generics and the [[usage-site variance]] for generics.&lt;br /&gt;
&lt;br /&gt;
The reason for this is that up to now all approaches failed to deliver an easy and concise solution to solve the problem of catcalls in general. &lt;br /&gt;
&lt;br /&gt;
Interval types work well for non-generic types and the overhead for the type declaration is minimal with a sensitive default behaviour, but for generics it does not really work.&lt;br /&gt;
&lt;br /&gt;
Usage-site variance is a promising solution for generics with just the small addition of a flag for the kind of variance needed on a generic derivation. And again, the default behaviour will allow most uses of a generic type as the programmer expects it to work.&lt;br /&gt;
&lt;br /&gt;
== Syntax ==&lt;br /&gt;
&lt;br /&gt;
Types can be specified as an interval:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;e&amp;gt;LOWER..UPPER&amp;lt;/e&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Generic parameters can be marked to select the variance:&lt;br /&gt;
&lt;br /&gt;
* To specify a novariant generic, the normal syntax can be used: &amp;lt;e&amp;gt;LIST [ANY]&amp;lt;/e&amp;gt;&lt;br /&gt;
* To specify a covariant generic, we use a plus sign: &amp;lt;e&amp;gt;LIST [+ANY]&amp;lt;/e&amp;gt;&lt;br /&gt;
* To specify a contravariant generic, we use a minus sign: &amp;lt;e&amp;gt;LIST [-ANY]&amp;lt;/e&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Semantics ==&lt;br /&gt;
&lt;br /&gt;
Each interval type describes the set of types which belong to the interval. A type belongs to the inverval if it conforms to the lower bound (&amp;lt;e&amp;gt;LOWER&amp;lt;/e&amp;gt;) and if the upper bound (&amp;lt;e&amp;gt;UPPER&amp;lt;/e&amp;gt;) conforms to it. All feature calls will be subject to whole-system validity and by restricting the dynamic type set to the types in the interval this check can be influenced.&lt;br /&gt;
&lt;br /&gt;
For generics the applicable features depend on the variance mark used:&lt;br /&gt;
&lt;br /&gt;
* On a novariant generic, all features can be used.&lt;br /&gt;
* On a covariant generic, only features which have the formal generic as a result type can be used. If the formal generic appears in an argument this feature is invalid.&lt;br /&gt;
* On a contravariant generic, only feature which have the formal generc as an argument type can be used. If the formal generic appears as a result type this feature is invalid.&lt;br /&gt;
&lt;br /&gt;
=== Conformance rules ===&lt;br /&gt;
&lt;br /&gt;
A type &amp;lt;e&amp;gt;b: C..D&amp;lt;/e&amp;gt; conforms to the type &amp;lt;e&amp;gt;a: A..B&amp;lt;/e&amp;gt; if &amp;lt;e&amp;gt;C&amp;lt;/e&amp;gt; conforms to &amp;lt;e&amp;gt;A&amp;lt;/e&amp;gt; and &amp;lt;e&amp;gt;B&amp;lt;/e&amp;gt; conforms to &amp;lt;e&amp;gt;D&amp;lt;/e&amp;gt;. The conformance rules for generics differ depending on the variance mark:&lt;br /&gt;
&lt;br /&gt;
* A generic conforms to a novariant generic if it has the exact same generic parameter. Thus &amp;lt;e&amp;gt;LIST [T]&amp;lt;/e&amp;gt; only conforms to &amp;lt;e&amp;gt;LIST [T]&amp;lt;/e&amp;gt;.&lt;br /&gt;
* A generic conforms to a covariant generic if its generic parameter conforms to the generic parameter of the covariant generic. Thus &amp;lt;e&amp;gt;LIST [U]&amp;lt;/e&amp;gt; conforms to &amp;lt;e&amp;gt;LIST [+T]&amp;lt;/e&amp;gt;.&lt;br /&gt;
* A generic conforms to a contravariant generic if its generic parameter is a parent of the generic parameter of the contravariant generic. Thus &amp;lt;e&amp;gt;LIST [T]&amp;lt;/e&amp;gt; conforms to &amp;lt;e&amp;gt;LIST [-U]&amp;lt;/e&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Default behaviour ===&lt;br /&gt;
&lt;br /&gt;
The default for a type declaration is that the interval contains the type up to &amp;lt;e&amp;gt;NONE&amp;lt;/e&amp;gt; (note that it is assumed that &amp;lt;e&amp;gt;NONE&amp;lt;/e&amp;gt; also conforms to expanded types):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;e&amp;gt;&lt;br /&gt;
a: ANY  -- means ANY..NONE&lt;br /&gt;
&amp;lt;/e&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This allows that in the default case all descendants of a type can be assigned.&lt;br /&gt;
&lt;br /&gt;
The default for generic arguments is novariance. This allows that all features can be called on a generic without restrictions.&lt;br /&gt;
&lt;br /&gt;
By choosing these defaults, most code which does not rely on covariant generic conformance should work as before:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;e&amp;gt;&lt;br /&gt;
local&lt;br /&gt;
  any: ANY                  -- mean ANY..NONE&lt;br /&gt;
  list: LIST [ANY]          -- mean LIST [ANY..NONE] .. NONE&lt;br /&gt;
  l_list: LINKED_LIST [ANY] -- means LINKED_LIST [ANY..NONE] .. NONE&lt;br /&gt;
do&lt;br /&gt;
  any := &amp;quot;abc&amp;quot;&lt;br /&gt;
  any := 8&lt;br /&gt;
  list := l_list&lt;br /&gt;
  list.put (any)&lt;br /&gt;
  list.put (&amp;quot;abc&amp;quot;)&lt;br /&gt;
  any := list.item.out&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/e&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The only things which don't work as before is conformance of generics and calls on covariantly redefined features. For the former the generic parameters of the target type have to be marked as covariant (using ''+'') and the latter will be subject to whole-system validity of feature calls.&lt;br /&gt;
&lt;br /&gt;
== Examples ==&lt;br /&gt;
&lt;br /&gt;
See the [[introduction to examples]] for information about the classes used.&lt;br /&gt;
&lt;br /&gt;
=== Combining the mechanisms ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;e&amp;gt;&lt;br /&gt;
local&lt;br /&gt;
  dog: DOG        -- means DOG..NONE&lt;br /&gt;
  cat: CAT        -- means CAT..NONE&lt;br /&gt;
  animal: ANIMAL  -- means ANIMAL..NONE&lt;br /&gt;
  animal_list: LIST [ANIMAL]  -- means LIST [ANIMAL..NONE] .. NONE&lt;br /&gt;
  animal_dog_list: LIST [ANIMAL..DOG]&lt;br /&gt;
  read_any_list: LIST [+ANY]  -- means LIST [+ ANY..NONE] .. NONE&lt;br /&gt;
do&lt;br /&gt;
    -- valid&lt;br /&gt;
  dog.eat (food)&lt;br /&gt;
  cat.eat (cat_food)&lt;br /&gt;
  animal.eat (cat_food)&lt;br /&gt;
&lt;br /&gt;
    -- invalid&lt;br /&gt;
  animal.eat (food) -- could be a CAT&lt;br /&gt;
&lt;br /&gt;
    -- valid&lt;br /&gt;
  animal_list.put (dog)&lt;br /&gt;
  animal_list.put (cat)&lt;br /&gt;
  animal_list.eat (cat_food)&lt;br /&gt;
  animal_dog_list.eat (food)&lt;br /&gt;
  read_any_list := animal_list&lt;br /&gt;
&lt;br /&gt;
    -- invalid&lt;br /&gt;
  read_any_list.put (&amp;quot;abc&amp;quot;)&lt;br /&gt;
  animal_list.eat (food) -- could be a CAT&lt;br /&gt;
&lt;br /&gt;
    -- types&lt;br /&gt;
  animal_list.item = {ANIMAL..NONE}&lt;br /&gt;
  animal_dog_list.item = {ANIMAL..DOG}&lt;br /&gt;
  read_any_list.item = {ANY..NONE}&lt;br /&gt;
&lt;br /&gt;
  animal_dog_list.put ({ANIMAL..DOG})  &lt;br /&gt;
  animal_list.put ({ANIMAL..NONE})&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/e&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Cats and dogs ===&lt;br /&gt;
&lt;br /&gt;
See the [[Interval_types#Cats_and_dogs|interval types]] example.&lt;br /&gt;
&lt;br /&gt;
=== A simple generic algorithm ===&lt;br /&gt;
&lt;br /&gt;
See the [[Usage-site_variance#A_simple_generic_algorithm|usage-site variance]] example.&lt;/div&gt;</summary>
		<author><name>Juliant</name></author>	</entry>

	<entry>
		<id>https://dev.eiffel.com/index.php?title=Interval_types&amp;diff=8939</id>
		<title>Interval types</title>
		<link rel="alternate" type="text/html" href="https://dev.eiffel.com/index.php?title=Interval_types&amp;diff=8939"/>
				<updated>2007-07-06T02:16:41Z</updated>
		
		<summary type="html">&lt;p&gt;Juliant: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Category:ECMA]]&lt;br /&gt;
[[Category:Catcall]]&lt;br /&gt;
{{Research}}&lt;br /&gt;
== Introduction ==&lt;br /&gt;
&lt;br /&gt;
With interval types, the programmer can restrict the conforming types for an entity. This way, the type set which needs to be checked for system validity of a feature call is restricted to a smaller set of types. In addition, certain rules for generic types will prohibit the unsafe use of generics.&lt;br /&gt;
&lt;br /&gt;
== Syntax ==&lt;br /&gt;
&lt;br /&gt;
At every location where a normal type is expected, an interval type can be specified by adding an upper bound for each type:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;e&amp;gt;&lt;br /&gt;
LOWER..UPPER&lt;br /&gt;
&amp;lt;/e&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This specifies an interval of all types between the types &amp;lt;e&amp;gt;LOWER&amp;lt;/e&amp;gt; and &amp;lt;e&amp;gt;UPPER&amp;lt;/e&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== Semantics ==&lt;br /&gt;
&lt;br /&gt;
The intention of an interval type is to specify that an entity can only be attached to a type which lies inside the interval. Thus a type declared as &amp;lt;e&amp;gt;ANY..STRING&amp;lt;/e&amp;gt; can be attached to an object of dynamic type &amp;lt;e&amp;gt;ANY&amp;lt;/e&amp;gt; or dynamic type &amp;lt;e&amp;gt;STRING&amp;lt;/e&amp;gt;. It cannot be attached to an object of a type which lies outside this interval, for example &amp;lt;e&amp;gt;INTEGER&amp;lt;/e&amp;gt; or &amp;lt;e&amp;gt;PATH_NAME&amp;lt;/e&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Each interval type describes the set of types which belong to the interval. A type belongs to the inverval if it conforms to the lower bound (&amp;lt;e&amp;gt;LOWER&amp;lt;/e&amp;gt;) and if the upper bound (&amp;lt;e&amp;gt;UPPER&amp;lt;/e&amp;gt;) conforms to it.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;e&amp;gt;&lt;br /&gt;
a: A .. C &amp;lt;=&amp;gt; {A, B, C}&lt;br /&gt;
b: A .. B &amp;lt;=&amp;gt; {A, B}&lt;br /&gt;
c: A .. NONE &amp;lt;=&amp;gt; {A, B, C, ...}&lt;br /&gt;
&amp;lt;/e&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Conformance rules ===&lt;br /&gt;
&lt;br /&gt;
An interval type ''b'' conforms to an interval type ''a'' if it is a sub-interval of ''a''. So if ''a'' fully encloses the interval ''b'', ''b'' conforms to ''a''.&lt;br /&gt;
&lt;br /&gt;
The conformance rules can also be explained by differently:&lt;br /&gt;
&lt;br /&gt;
* An interval type ''b'' conforms to an interval type ''a'' if the set of types described by the interval of ''b'' is a subset of the set described by the interval of ''a''.&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;e&amp;gt;&lt;br /&gt;
a := b -- Is valid as {A, B} is a subset of {A, B, C}&lt;br /&gt;
&amp;lt;/e&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* A type &amp;lt;e&amp;gt;b: C..D&amp;lt;/e&amp;gt; conforms to the type &amp;lt;e&amp;gt;a: A..B&amp;lt;/e&amp;gt; if &amp;lt;e&amp;gt;C&amp;lt;/e&amp;gt; conforms to &amp;lt;e&amp;gt;A&amp;lt;/e&amp;gt; and &amp;lt;e&amp;gt;B&amp;lt;/e&amp;gt; conforms to &amp;lt;e&amp;gt;D&amp;lt;/e&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Generic conformance is the same as it is now: A generic type ''b'' conforms to a generic type ''a'' if the base class of ''b'' conforms to ''a'' and all generic parameters conform as well.&lt;br /&gt;
&lt;br /&gt;
=== Generic features ===&lt;br /&gt;
&lt;br /&gt;
For features with formal arguments, another rule exists: A call on a feature wich contains a formal argument is only valid if the generic substitution is monomorphic.&lt;br /&gt;
&lt;br /&gt;
This means that a call on a feature &amp;lt;e&amp;gt;f (g: G)&amp;lt;/e&amp;gt; of a class &amp;lt;e&amp;gt;X [G]&amp;lt;/e&amp;gt; is only valid if &amp;lt;e&amp;gt;G&amp;lt;/e&amp;gt; is monomorphic. Thus the type has to be instantitated with &amp;lt;e&amp;gt;X [Y..Y]&amp;lt;/e&amp;gt;. So a call to &amp;lt;e&amp;gt;f&amp;lt;/e&amp;gt; on a type &amp;lt;e&amp;gt;X [Y..NONE]&amp;lt;/e&amp;gt; is not allowed.&lt;br /&gt;
&lt;br /&gt;
=== Default behaviour ===&lt;br /&gt;
&lt;br /&gt;
As a shorthand for interval definition, we define the following default behaviour which is different for ordinary types and for actual generic type parameters. Ordinary types are per default polymorphic and actual formal parameters monomorphic:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;e&amp;gt;&lt;br /&gt;
x: T &amp;lt;=&amp;gt; T .. NONE&lt;br /&gt;
y: A [T] &amp;lt;=&amp;gt; A [T .. T] .. NONE&lt;br /&gt;
&amp;lt;/e&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Examples ==&lt;br /&gt;
&lt;br /&gt;
See the [[introduction to examples]] for information about the classes used.&lt;br /&gt;
&lt;br /&gt;
=== Cats and dogs ===&lt;br /&gt;
&lt;br /&gt;
A feature call on a target ''t'' is only valid if it is valid for all polymorphic types which can possibly be assigned to ''t''. With interval types the set of conforming types can be restriced in order to be able to perform calls to features which are covariantly redefined in descendands by excluding such descendants from the dynamic type set. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;e&amp;gt;&lt;br /&gt;
a_none: ANIMAL &amp;lt;=&amp;gt; ANIMAL .. NONE&lt;br /&gt;
c_none: CAT &amp;lt;=&amp;gt; ANIMAL .. NONE&lt;br /&gt;
d_none: DOG &amp;lt;=&amp;gt; ANIMAL .. NONE&lt;br /&gt;
a_a: ANIMAL .. ANIMAL&lt;br /&gt;
c_c: CAT .. CAT&lt;br /&gt;
d_d: DOG .. DOG&lt;br /&gt;
a_c: ANIMAL .. CAT&lt;br /&gt;
a_d: ANIMAL .. DOG&lt;br /&gt;
&amp;lt;/e&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Valid assignments:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;e&amp;gt;&lt;br /&gt;
a_none := c_none&lt;br /&gt;
a_none := d_none&lt;br /&gt;
a_none := a_a&lt;br /&gt;
a_none := c_c&lt;br /&gt;
a_none := d_d&lt;br /&gt;
c_none := c_c&lt;br /&gt;
d_none := d_d&lt;br /&gt;
&lt;br /&gt;
a_c := a_a&lt;br /&gt;
a_c := c_c&lt;br /&gt;
a_d := a_a&lt;br /&gt;
a_d := d_d&lt;br /&gt;
&amp;lt;/e&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Invalid assignments:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;e&amp;gt;&lt;br /&gt;
-- Invalid: a_a := a_none&lt;br /&gt;
-- Invalid: c_c := c_none&lt;br /&gt;
-- Invalid: d_d := d_none&lt;br /&gt;
-- Invalid: a_c := c_none&lt;br /&gt;
-- Invalid: a_d := d_none&lt;br /&gt;
&amp;lt;/e&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Valid calls:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;e&amp;gt;&lt;br /&gt;
a_none.eat (cat_food)&lt;br /&gt;
a_a.eat (food)&lt;br /&gt;
a_d.eat (food)&lt;br /&gt;
&amp;lt;/e&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Invalid calls:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;e&amp;gt;&lt;br /&gt;
a_none.eat (food)&lt;br /&gt;
&amp;lt;/e&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== A simple generic algorithm ===&lt;br /&gt;
&lt;br /&gt;
It is easy to declare an algorithm which needs only read-access on a list:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;e&amp;gt;&lt;br /&gt;
class PERSON_PRINTER&lt;br /&gt;
feature&lt;br /&gt;
  print_all (a_list: LIST [PERSON..NONE])&lt;br /&gt;
      -- Print all attributes of each person in the list.&lt;br /&gt;
    do&lt;br /&gt;
      from&lt;br /&gt;
        a_list.start&lt;br /&gt;
      until&lt;br /&gt;
        a_list.after&lt;br /&gt;
      do &lt;br /&gt;
          -- Reading is valid on a covariant list&lt;br /&gt;
        a_list.item.print&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
end&lt;br /&gt;
 &lt;br /&gt;
class EXAMPLE&lt;br /&gt;
feature&lt;br /&gt;
  make&lt;br /&gt;
    local&lt;br /&gt;
      l_students: LIST [STUDENT]       &amp;lt;=&amp;gt; LIST [STUDENT..STUDENT]&lt;br /&gt;
      l_professors: LIST [PROFESSOR]   &amp;lt;=&amp;gt; LIST [PROFESSOR..PROFESSOR]&lt;br /&gt;
      l_person_printer: PERSON_PRINTER&lt;br /&gt;
    do&lt;br /&gt;
      create l_person_printer&lt;br /&gt;
        -- LIST [STUDENT..STUDENT] conforms to LIST [PERSON..NONE]&lt;br /&gt;
      l_person_printer.print_all (l_students)&lt;br /&gt;
        -- LIST [PROFESSOR..PROFESSOR] conforms to LIST [PERSON..NONE]&lt;br /&gt;
      l_person_printer.print_all (l_professor)&lt;br /&gt;
    end&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/e&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Issues ==&lt;br /&gt;
&lt;br /&gt;
=== Generic features ===&lt;br /&gt;
&lt;br /&gt;
The rule about calling features with formal parameters is too restrictive. Let's look at the following code:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;e&amp;gt;&lt;br /&gt;
deferred class COMPONENT&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
class COMPOSITE&lt;br /&gt;
inherit COMPONENT&lt;br /&gt;
feature&lt;br /&gt;
  components: LIST [COMPONENT]&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/e&amp;gt;&lt;br /&gt;
&lt;br /&gt;
What should the type of feature &amp;lt;e&amp;gt;components&amp;lt;/e&amp;gt; be? In order to be able to call &amp;lt;e&amp;gt;extend&amp;lt;/e&amp;gt; on the list, it has to be monomorphic, thus &amp;lt;e&amp;gt;LIST [COMPONENT..COMPONENT]&amp;lt;/e&amp;gt;. But since the argument type is now &amp;lt;e&amp;gt;COMPONENT..COMPONENT&amp;lt;/e&amp;gt; we actually cannot add anything to the list as no descendant of &amp;lt;e&amp;gt;COMPONENT&amp;lt;/e&amp;gt; is in the interval. Actually, since &amp;lt;e&amp;gt;COMPONENT&amp;lt;/e&amp;gt; is deferred nothing can be added to the list at all.&lt;br /&gt;
&lt;br /&gt;
But if we define the list as &amp;lt;e&amp;gt;LIST [COMPONENT..NONE]&amp;lt;/e&amp;gt; - thus allowing descendants of &amp;lt;e&amp;gt;COMPONENT&amp;lt;/e&amp;gt; in the list - then the rule about features with formal arguments disallows any calls to feature &amp;lt;e&amp;gt;extend&amp;lt;/e&amp;gt; as the argument is not monomorphic anymore.&lt;br /&gt;
&lt;br /&gt;
=== Expanded and Void ===&lt;br /&gt;
&lt;br /&gt;
Look at the following code snippet:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;e&amp;gt;&lt;br /&gt;
local&lt;br /&gt;
  any_none: ANY..NONE&lt;br /&gt;
  any_string: ANY..STRING&lt;br /&gt;
do&lt;br /&gt;
    -- invalid as NONE does not conform to INTEGER&lt;br /&gt;
  any_none := 5&lt;br /&gt;
    -- invalid as NONE is not in the interval ANY..STRING&lt;br /&gt;
  any_string := Void&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/e&amp;gt;&lt;br /&gt;
&lt;br /&gt;
It illustrates two problems in conjunction with &amp;lt;e&amp;gt;NONE&amp;lt;/e&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
* The first is that &amp;lt;e&amp;gt;NONE&amp;lt;/e&amp;gt; does not conform to expanded types. This makes it impossible to declare a type interval which includes all types in the system, reference or expanded. This prevents the programmer to write code which works with reference types and expanded types, say a generic print algorithm.&lt;br /&gt;
* The second one is that &amp;lt;e&amp;gt;Void&amp;lt;/e&amp;gt; is of type &amp;lt;e&amp;gt;NONE&amp;lt;/e&amp;gt;. This raises the question how &amp;lt;e&amp;gt;Void&amp;lt;/e&amp;gt; should be assigned to an interval type of references, or how such a type is initialized in the first place.&lt;br /&gt;
&lt;br /&gt;
== Conclusion ==&lt;br /&gt;
&lt;br /&gt;
The rule about features with formal parameters must be changed to make this solution usable as otherwise the use of generics is restricted too much.&lt;br /&gt;
&lt;br /&gt;
The problem with &amp;lt;e&amp;gt;Void&amp;lt;/e&amp;gt; and &amp;lt;e&amp;gt;NONE&amp;lt;/e&amp;gt; can easily be solved by declaring that &amp;lt;e&amp;gt;NONE&amp;lt;/e&amp;gt; inherits from all types regardless of reference or expanded status. To solve the problem of assigning &amp;lt;e&amp;gt;Void&amp;lt;/e&amp;gt; to an interval type it can be defined that &amp;lt;e&amp;gt;Void&amp;lt;/e&amp;gt; is of any (detached) reference type. That way it can be assigned to any interval of a refernce type, even a monomorphic one, and it is still disallowed to assign it to expanded types.&lt;/div&gt;</summary>
		<author><name>Juliant</name></author>	</entry>

	<entry>
		<id>https://dev.eiffel.com/index.php?title=Talk:Catcall_checkpoints&amp;diff=8938</id>
		<title>Talk:Catcall checkpoints</title>
		<link rel="alternate" type="text/html" href="https://dev.eiffel.com/index.php?title=Talk:Catcall_checkpoints&amp;diff=8938"/>
				<updated>2007-07-03T22:32:55Z</updated>
		
		<summary type="html">&lt;p&gt;Juliant: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;--[[User:Peter gummer|Peter gummer]] 10:54, 3 July 2007 (CEST) It is annoying that, in order to solve the catcall problem, we have to forbid polymorphic assignments like &amp;lt;e&amp;gt;list_of_any := list_of_string&amp;lt;/e&amp;gt;. Yes, we don't want integers poked into &amp;lt;e&amp;gt;list_of_any&amp;lt;/e&amp;gt; when it's attached to a list of strings; but usually when we perform such assignments it's so that we can use the list in a read-only fashion. I would prefer to allow such assignments, if and only if the entity on the left is declared '''read-only'''. ''Uh oh'', now I've gone and raised the old question, &amp;quot;C++ has ''const'' so why doesn't Eiffel?&amp;quot;&lt;br /&gt;
&lt;br /&gt;
'''--[[User:Juliant|Juliant]] 00:32, 4 July 2007 (CEST)''':&lt;br /&gt;
The assignment has to be disallowed with ''default semantics''. A good solution will allow exactly what you say, an easy way to declare a read-only list. For example the [[usage-site variance]] would allow to declare a list as &amp;lt;e&amp;gt;LIST [+ANY]&amp;lt;/e&amp;gt; to mark it read-only.&lt;br /&gt;
&lt;br /&gt;
The last ECMA meeting proposed a new solution but we didn't get the validity rules yet, so we don't have a wiki-page for this at the moment. We will add this when we get them and then we can see how it works there.&lt;/div&gt;</summary>
		<author><name>Juliant</name></author>	</entry>

	<entry>
		<id>https://dev.eiffel.com/index.php?title=Catcall_checkpoints&amp;diff=8935</id>
		<title>Catcall checkpoints</title>
		<link rel="alternate" type="text/html" href="https://dev.eiffel.com/index.php?title=Catcall_checkpoints&amp;diff=8935"/>
				<updated>2007-07-02T16:29:51Z</updated>
		
		<summary type="html">&lt;p&gt;Juliant: /* Generic lists */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Category:Catcall]]&lt;br /&gt;
These examples should be considered for all catcall solutions:&lt;br /&gt;
&lt;br /&gt;
== Generic lists ==&lt;br /&gt;
&lt;br /&gt;
The default semantics of the catcall solution should work for generics like the following:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;e&amp;gt;&lt;br /&gt;
local&lt;br /&gt;
  any_list: LIST [ANY]&lt;br /&gt;
  string_list: LIST [STRING]&lt;br /&gt;
  any_linked_list: LINKED_LIST [ANY]&lt;br /&gt;
do&lt;br /&gt;
    -- Should be allowed with default semantics&lt;br /&gt;
  any_list := any_linked_list&lt;br /&gt;
  any_list.put (&amp;quot;abc&amp;quot;)&lt;br /&gt;
  any_linked_list.put (5)&lt;br /&gt;
&lt;br /&gt;
    -- Has to be forbidden with default semantics&lt;br /&gt;
  any_list := string_list&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/e&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Faces of covariance ==&lt;br /&gt;
&lt;br /&gt;
The following example shows the difference between generic covariance and non-generic covariance. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;e&amp;gt;&lt;br /&gt;
class A [G]&lt;br /&gt;
feature&lt;br /&gt;
  f (t: T) do end&lt;br /&gt;
  put (g: G) do end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
class B [G]&lt;br /&gt;
inherit A [G] redefine f end&lt;br /&gt;
feature&lt;br /&gt;
  f (u: U) do end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
local&lt;br /&gt;
  a_any: A [ANY]&lt;br /&gt;
  a_string: A [STRING]&lt;br /&gt;
  b_any: B [ANY]&lt;br /&gt;
  b_string: B [STRING]&lt;br /&gt;
  t: T&lt;br /&gt;
do&lt;br /&gt;
  a_any := a_string&lt;br /&gt;
  a_any.put (5) -- catcall for generic feature&lt;br /&gt;
  a_any.f (t) -- no catcall&lt;br /&gt;
&lt;br /&gt;
  a_any := b_any&lt;br /&gt;
  a_any.put (5) -- no catcall&lt;br /&gt;
  a_any.f (t) -- catcall for non-generic feature&lt;br /&gt;
&lt;br /&gt;
  a_any := b_string&lt;br /&gt;
  a_any.put (5) -- catcall for generic feature&lt;br /&gt;
  a_any.f (t) -- catcall for non-generic feature&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/e&amp;gt;&lt;br /&gt;
&lt;br /&gt;
A safe and expressive solution should have a way to allow all valid cases and prohibit the invalid ones. This needs a way to address the generic and non-generic features indiviually.&lt;br /&gt;
&lt;br /&gt;
== Contravariance ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;e&amp;gt;&lt;br /&gt;
class SORTER [G]&lt;br /&gt;
feature&lt;br /&gt;
  sort (a_list: LIST [G]; a_comparator: COMPARATOR [G])&lt;br /&gt;
    do&lt;br /&gt;
        -- Somewhere in the loop:&lt;br /&gt;
      a_comparator.compare (l_string_1, l_string_2)&lt;br /&gt;
    end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
class EXAMPLE&lt;br /&gt;
feature&lt;br /&gt;
  make&lt;br /&gt;
    local&lt;br /&gt;
      l_list: LIST [STRING]&lt;br /&gt;
      l_string_sorter: SORTER [STRING]&lt;br /&gt;
      l_any_comparator: COMPARATOR [ANY]&lt;br /&gt;
    do&lt;br /&gt;
        -- Should be allowed to sort the string list with an&lt;br /&gt;
        -- ANY comparator&lt;br /&gt;
      l_string_sorter.sort (l_list, l_any_comparator)&lt;br /&gt;
    end&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/e&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Solutions which pass this test are likely to be expressive for agents as well.&lt;br /&gt;
&lt;br /&gt;
== Agents ==&lt;br /&gt;
&lt;br /&gt;
For agents, we will look at an example with the type &amp;lt;e&amp;gt;T&amp;lt;/e&amp;gt; and a subtype &amp;lt;e&amp;gt;U&amp;lt;/e&amp;gt;. We will see an agent declaration and then check which arguments that are allowed:&lt;br /&gt;
&lt;br /&gt;
=== Calling agents ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;e&amp;gt;&lt;br /&gt;
local&lt;br /&gt;
  an_agent: PROCEDURE [ANY, TUPLE [T]]&lt;br /&gt;
    -- An agent which takes an argument of type T.&lt;br /&gt;
do&lt;br /&gt;
    -- The following calls are currently valid and should remain valid.&lt;br /&gt;
  an_agent.call ([T])&lt;br /&gt;
  an_agent.call ([U])&lt;br /&gt;
&lt;br /&gt;
  an_agent.call ([T, ...])&lt;br /&gt;
  an_agent.call ([U, ...])&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/e&amp;gt;&lt;br /&gt;
These basic cases mostly rely on the tuple conformance rules to work properly.&lt;br /&gt;
&lt;br /&gt;
=== Assigning agents ===&lt;br /&gt;
To allow anything that is safe is more tricky. It requires the ability to model contravariance.&lt;br /&gt;
&amp;lt;e&amp;gt;&lt;br /&gt;
local&lt;br /&gt;
  an_agent: PROCEDURE [ANY, TUPLE [T]]&lt;br /&gt;
    -- An agent which takes an argument of type T.&lt;br /&gt;
do&lt;br /&gt;
  agent_empty := agent () do end --&amp;gt; PROCEDURE [ANY, TUPLE []]&lt;br /&gt;
  agent_any := agent (a: ANY) do end --&amp;gt; PROCEDURE [ANY, TUPLE [ANY]]&lt;br /&gt;
  agent_t := agent (t: T) do end --&amp;gt; PROCEDURE [ANY, TUPLE [T]]&lt;br /&gt;
  agent_u := agent (u: U) do end --&amp;gt; PROCEDURE [ANY, TUPLE [U]]&lt;br /&gt;
  agent_tt := agent (t: T; t2: T) do end --&amp;gt; PROCEDURE [ANY, TUPLE [T, T]]&lt;br /&gt;
&lt;br /&gt;
    -- This assignment is naturally allowed as they are the same type.&lt;br /&gt;
  an_agent := agent_t&lt;br /&gt;
&lt;br /&gt;
    -- The following assignments are save but prohibited by the current implementation.&lt;br /&gt;
    -- If they were allowed it would benefit event driven programming in Eiffel a lot.&lt;br /&gt;
    -- As agents currently are modeled over the generic mechanism any solution which&lt;br /&gt;
    -- solves the &amp;quot;comparator problem&amp;quot; is likely to pass here too.&lt;br /&gt;
  an_agent := agent_empty&lt;br /&gt;
  an_agent := agent_any&lt;br /&gt;
&lt;br /&gt;
    -- The following assignments are currently permitted. This is not the correct&lt;br /&gt;
    -- behavior  as you could either create a catcall by passing a T argument to the &lt;br /&gt;
    -- `agent_u' or pass the wrong number of arguments by passing a [T] tuple to the &lt;br /&gt;
    -- `agent_tt'.&lt;br /&gt;
  an_agent := agent_u&lt;br /&gt;
  an_agent := agent_tt&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/e&amp;gt;&lt;/div&gt;</summary>
		<author><name>Juliant</name></author>	</entry>

	<entry>
		<id>https://dev.eiffel.com/index.php?title=Catcall_checkpoints&amp;diff=8934</id>
		<title>Catcall checkpoints</title>
		<link rel="alternate" type="text/html" href="https://dev.eiffel.com/index.php?title=Catcall_checkpoints&amp;diff=8934"/>
				<updated>2007-07-02T16:28:13Z</updated>
		
		<summary type="html">&lt;p&gt;Juliant: /* Lists */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Category:Catcall]]&lt;br /&gt;
These examples should be considered for all catcall solutions:&lt;br /&gt;
&lt;br /&gt;
== Generic lists ==&lt;br /&gt;
&lt;br /&gt;
The default semantics of the catcall solution should work for generics like the following:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;e&amp;gt;&lt;br /&gt;
local&lt;br /&gt;
  any_list: LIST [ANY]&lt;br /&gt;
  string_list: LIST [STRING]&lt;br /&gt;
  any_linked_list: LINKED_LIST [ANY]&lt;br /&gt;
do&lt;br /&gt;
    -- Should be allowed with default semantics&lt;br /&gt;
  any_list := any_linked_list&lt;br /&gt;
  any_list.put (&amp;quot;abc&amp;quot;)&lt;br /&gt;
  any_linked_list.put (5)&lt;br /&gt;
    -- Has to be forbidden with default semantics&lt;br /&gt;
  any_list := string_list&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/e&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Faces of covariance ==&lt;br /&gt;
&lt;br /&gt;
The following example shows the difference between generic covariance and non-generic covariance. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;e&amp;gt;&lt;br /&gt;
class A [G]&lt;br /&gt;
feature&lt;br /&gt;
  f (t: T) do end&lt;br /&gt;
  put (g: G) do end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
class B [G]&lt;br /&gt;
inherit A [G] redefine f end&lt;br /&gt;
feature&lt;br /&gt;
  f (u: U) do end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
local&lt;br /&gt;
  a_any: A [ANY]&lt;br /&gt;
  a_string: A [STRING]&lt;br /&gt;
  b_any: B [ANY]&lt;br /&gt;
  b_string: B [STRING]&lt;br /&gt;
  t: T&lt;br /&gt;
do&lt;br /&gt;
  a_any := a_string&lt;br /&gt;
  a_any.put (5) -- catcall for generic feature&lt;br /&gt;
  a_any.f (t) -- no catcall&lt;br /&gt;
&lt;br /&gt;
  a_any := b_any&lt;br /&gt;
  a_any.put (5) -- no catcall&lt;br /&gt;
  a_any.f (t) -- catcall for non-generic feature&lt;br /&gt;
&lt;br /&gt;
  a_any := b_string&lt;br /&gt;
  a_any.put (5) -- catcall for generic feature&lt;br /&gt;
  a_any.f (t) -- catcall for non-generic feature&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/e&amp;gt;&lt;br /&gt;
&lt;br /&gt;
A safe and expressive solution should have a way to allow all valid cases and prohibit the invalid ones. This needs a way to address the generic and non-generic features indiviually.&lt;br /&gt;
&lt;br /&gt;
== Contravariance ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;e&amp;gt;&lt;br /&gt;
class SORTER [G]&lt;br /&gt;
feature&lt;br /&gt;
  sort (a_list: LIST [G]; a_comparator: COMPARATOR [G])&lt;br /&gt;
    do&lt;br /&gt;
        -- Somewhere in the loop:&lt;br /&gt;
      a_comparator.compare (l_string_1, l_string_2)&lt;br /&gt;
    end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
class EXAMPLE&lt;br /&gt;
feature&lt;br /&gt;
  make&lt;br /&gt;
    local&lt;br /&gt;
      l_list: LIST [STRING]&lt;br /&gt;
      l_string_sorter: SORTER [STRING]&lt;br /&gt;
      l_any_comparator: COMPARATOR [ANY]&lt;br /&gt;
    do&lt;br /&gt;
        -- Should be allowed to sort the string list with an&lt;br /&gt;
        -- ANY comparator&lt;br /&gt;
      l_string_sorter.sort (l_list, l_any_comparator)&lt;br /&gt;
    end&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/e&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Solutions which pass this test are likely to be expressive for agents as well.&lt;br /&gt;
&lt;br /&gt;
== Agents ==&lt;br /&gt;
&lt;br /&gt;
For agents, we will look at an example with the type &amp;lt;e&amp;gt;T&amp;lt;/e&amp;gt; and a subtype &amp;lt;e&amp;gt;U&amp;lt;/e&amp;gt;. We will see an agent declaration and then check which arguments that are allowed:&lt;br /&gt;
&lt;br /&gt;
=== Calling agents ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;e&amp;gt;&lt;br /&gt;
local&lt;br /&gt;
  an_agent: PROCEDURE [ANY, TUPLE [T]]&lt;br /&gt;
    -- An agent which takes an argument of type T.&lt;br /&gt;
do&lt;br /&gt;
    -- The following calls are currently valid and should remain valid.&lt;br /&gt;
  an_agent.call ([T])&lt;br /&gt;
  an_agent.call ([U])&lt;br /&gt;
&lt;br /&gt;
  an_agent.call ([T, ...])&lt;br /&gt;
  an_agent.call ([U, ...])&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/e&amp;gt;&lt;br /&gt;
These basic cases mostly rely on the tuple conformance rules to work properly.&lt;br /&gt;
&lt;br /&gt;
=== Assigning agents ===&lt;br /&gt;
To allow anything that is safe is more tricky. It requires the ability to model contravariance.&lt;br /&gt;
&amp;lt;e&amp;gt;&lt;br /&gt;
local&lt;br /&gt;
  an_agent: PROCEDURE [ANY, TUPLE [T]]&lt;br /&gt;
    -- An agent which takes an argument of type T.&lt;br /&gt;
do&lt;br /&gt;
  agent_empty := agent () do end --&amp;gt; PROCEDURE [ANY, TUPLE []]&lt;br /&gt;
  agent_any := agent (a: ANY) do end --&amp;gt; PROCEDURE [ANY, TUPLE [ANY]]&lt;br /&gt;
  agent_t := agent (t: T) do end --&amp;gt; PROCEDURE [ANY, TUPLE [T]]&lt;br /&gt;
  agent_u := agent (u: U) do end --&amp;gt; PROCEDURE [ANY, TUPLE [U]]&lt;br /&gt;
  agent_tt := agent (t: T; t2: T) do end --&amp;gt; PROCEDURE [ANY, TUPLE [T, T]]&lt;br /&gt;
&lt;br /&gt;
    -- This assignment is naturally allowed as they are the same type.&lt;br /&gt;
  an_agent := agent_t&lt;br /&gt;
&lt;br /&gt;
    -- The following assignments are save but prohibited by the current implementation.&lt;br /&gt;
    -- If they were allowed it would benefit event driven programming in Eiffel a lot.&lt;br /&gt;
    -- As agents currently are modeled over the generic mechanism any solution which&lt;br /&gt;
    -- solves the &amp;quot;comparator problem&amp;quot; is likely to pass here too.&lt;br /&gt;
  an_agent := agent_empty&lt;br /&gt;
  an_agent := agent_any&lt;br /&gt;
&lt;br /&gt;
    -- The following assignments are currently permitted. This is not the correct&lt;br /&gt;
    -- behavior  as you could either create a catcall by passing a T argument to the &lt;br /&gt;
    -- `agent_u' or pass the wrong number of arguments by passing a [T] tuple to the &lt;br /&gt;
    -- `agent_tt'.&lt;br /&gt;
  an_agent := agent_u&lt;br /&gt;
  an_agent := agent_tt&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/e&amp;gt;&lt;/div&gt;</summary>
		<author><name>Juliant</name></author>	</entry>

	<entry>
		<id>https://dev.eiffel.com/index.php?title=Catcall_checkpoints&amp;diff=8933</id>
		<title>Catcall checkpoints</title>
		<link rel="alternate" type="text/html" href="https://dev.eiffel.com/index.php?title=Catcall_checkpoints&amp;diff=8933"/>
				<updated>2007-07-02T16:25:10Z</updated>
		
		<summary type="html">&lt;p&gt;Juliant: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Category:Catcall]]&lt;br /&gt;
These examples should be considered for all catcall solutions:&lt;br /&gt;
&lt;br /&gt;
== Lists ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Faces of covariance ==&lt;br /&gt;
&lt;br /&gt;
The following example shows the difference between generic covariance and non-generic covariance. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;e&amp;gt;&lt;br /&gt;
class A [G]&lt;br /&gt;
feature&lt;br /&gt;
  f (t: T) do end&lt;br /&gt;
  put (g: G) do end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
class B [G]&lt;br /&gt;
inherit A [G] redefine f end&lt;br /&gt;
feature&lt;br /&gt;
  f (u: U) do end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
local&lt;br /&gt;
  a_any: A [ANY]&lt;br /&gt;
  a_string: A [STRING]&lt;br /&gt;
  b_any: B [ANY]&lt;br /&gt;
  b_string: B [STRING]&lt;br /&gt;
  t: T&lt;br /&gt;
do&lt;br /&gt;
  a_any := a_string&lt;br /&gt;
  a_any.put (5) -- catcall for generic feature&lt;br /&gt;
  a_any.f (t) -- no catcall&lt;br /&gt;
&lt;br /&gt;
  a_any := b_any&lt;br /&gt;
  a_any.put (5) -- no catcall&lt;br /&gt;
  a_any.f (t) -- catcall for non-generic feature&lt;br /&gt;
&lt;br /&gt;
  a_any := b_string&lt;br /&gt;
  a_any.put (5) -- catcall for generic feature&lt;br /&gt;
  a_any.f (t) -- catcall for non-generic feature&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/e&amp;gt;&lt;br /&gt;
&lt;br /&gt;
A safe and expressive solution should have a way to allow all valid cases and prohibit the invalid ones. This needs a way to address the generic and non-generic features indiviually.&lt;br /&gt;
&lt;br /&gt;
== Contravariance ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;e&amp;gt;&lt;br /&gt;
class SORTER [G]&lt;br /&gt;
feature&lt;br /&gt;
  sort (a_list: LIST [G]; a_comparator: COMPARATOR [G])&lt;br /&gt;
    do&lt;br /&gt;
        -- Somewhere in the loop:&lt;br /&gt;
      a_comparator.compare (l_string_1, l_string_2)&lt;br /&gt;
    end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
class EXAMPLE&lt;br /&gt;
feature&lt;br /&gt;
  make&lt;br /&gt;
    local&lt;br /&gt;
      l_list: LIST [STRING]&lt;br /&gt;
      l_string_sorter: SORTER [STRING]&lt;br /&gt;
      l_any_comparator: COMPARATOR [ANY]&lt;br /&gt;
    do&lt;br /&gt;
        -- Should be allowed to sort the string list with an&lt;br /&gt;
        -- ANY comparator&lt;br /&gt;
      l_string_sorter.sort (l_list, l_any_comparator)&lt;br /&gt;
    end&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/e&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Solutions which pass this test are likely to be expressive for agents as well.&lt;br /&gt;
&lt;br /&gt;
== Agents ==&lt;br /&gt;
&lt;br /&gt;
For agents, we will look at an example with the type &amp;lt;e&amp;gt;T&amp;lt;/e&amp;gt; and a subtype &amp;lt;e&amp;gt;U&amp;lt;/e&amp;gt;. We will see an agent declaration and then check which arguments that are allowed:&lt;br /&gt;
&lt;br /&gt;
=== Calling agents ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;e&amp;gt;&lt;br /&gt;
local&lt;br /&gt;
  an_agent: PROCEDURE [ANY, TUPLE [T]]&lt;br /&gt;
    -- An agent which takes an argument of type T.&lt;br /&gt;
do&lt;br /&gt;
    -- The following calls are currently valid and should remain valid.&lt;br /&gt;
  an_agent.call ([T])&lt;br /&gt;
  an_agent.call ([U])&lt;br /&gt;
&lt;br /&gt;
  an_agent.call ([T, ...])&lt;br /&gt;
  an_agent.call ([U, ...])&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/e&amp;gt;&lt;br /&gt;
These basic cases mostly rely on the tuple conformance rules to work properly.&lt;br /&gt;
&lt;br /&gt;
=== Assigning agents ===&lt;br /&gt;
To allow anything that is safe is more tricky. It requires the ability to model contravariance.&lt;br /&gt;
&amp;lt;e&amp;gt;&lt;br /&gt;
local&lt;br /&gt;
  an_agent: PROCEDURE [ANY, TUPLE [T]]&lt;br /&gt;
    -- An agent which takes an argument of type T.&lt;br /&gt;
do&lt;br /&gt;
  agent_empty := agent () do end --&amp;gt; PROCEDURE [ANY, TUPLE []]&lt;br /&gt;
  agent_any := agent (a: ANY) do end --&amp;gt; PROCEDURE [ANY, TUPLE [ANY]]&lt;br /&gt;
  agent_t := agent (t: T) do end --&amp;gt; PROCEDURE [ANY, TUPLE [T]]&lt;br /&gt;
  agent_u := agent (u: U) do end --&amp;gt; PROCEDURE [ANY, TUPLE [U]]&lt;br /&gt;
  agent_tt := agent (t: T; t2: T) do end --&amp;gt; PROCEDURE [ANY, TUPLE [T, T]]&lt;br /&gt;
&lt;br /&gt;
    -- This assignment is naturally allowed as they are the same type.&lt;br /&gt;
  an_agent := agent_t&lt;br /&gt;
&lt;br /&gt;
    -- The following assignments are save but prohibited by the current implementation.&lt;br /&gt;
    -- If they were allowed it would benefit event driven programming in Eiffel a lot.&lt;br /&gt;
    -- As agents currently are modeled over the generic mechanism any solution which&lt;br /&gt;
    -- solves the &amp;quot;comparator problem&amp;quot; is likely to pass here too.&lt;br /&gt;
  an_agent := agent_empty&lt;br /&gt;
  an_agent := agent_any&lt;br /&gt;
&lt;br /&gt;
    -- The following assignments are currently permitted. This is not the correct&lt;br /&gt;
    -- behavior  as you could either create a catcall by passing a T argument to the &lt;br /&gt;
    -- `agent_u' or pass the wrong number of arguments by passing a [T] tuple to the &lt;br /&gt;
    -- `agent_tt'.&lt;br /&gt;
  an_agent := agent_u&lt;br /&gt;
  an_agent := agent_tt&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/e&amp;gt;&lt;/div&gt;</summary>
		<author><name>Juliant</name></author>	</entry>

	<entry>
		<id>https://dev.eiffel.com/index.php?title=Comparison_of_catcall_solutions&amp;diff=8917</id>
		<title>Comparison of catcall solutions</title>
		<link rel="alternate" type="text/html" href="https://dev.eiffel.com/index.php?title=Comparison_of_catcall_solutions&amp;diff=8917"/>
				<updated>2007-06-24T19:09:06Z</updated>
		
		<summary type="html">&lt;p&gt;Juliant: /* Solutions for generics */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Category:ECMA]]&lt;br /&gt;
[[Category:Catcall]]&lt;br /&gt;
== Motivation ==&lt;br /&gt;
&lt;br /&gt;
By allowing covariant feature redefinition and hiding of features, the Eiffel language introduces the problem of catcalls (Changed Availability or Type). Currently the ECMA Eiffel standard does not specify how the occurrence of catcalls should be statically rejected.&lt;br /&gt;
&lt;br /&gt;
The purpose of this document is to show a comparison between different proposals on how to handle the issue of preventing catcalls.&lt;br /&gt;
&lt;br /&gt;
== Criteria for a solution ==&lt;br /&gt;
&lt;br /&gt;
To be able to judge a solution we use the following criteria which we consider as important:&lt;br /&gt;
&lt;br /&gt;
; Syntax overhead : How much syntax will be added to the language in order to express safe covariance and generics?&lt;br /&gt;
; Covariance on non-generic types : Are covariant argument redefinitions addressed in the solution? How does the programmer express it?&lt;br /&gt;
; Export status restrictions : Is restriction of export status addressed in the solution? How does the programmer express it?&lt;br /&gt;
; Use of generic types : How is conformance of generics? Are catcalls for generics addressed in the solution? How does the programmer express it? Can generics be used as now or are there restrictions?&lt;br /&gt;
:; Agents : Can agents be modeled with the solution while being type safe and expressive?&lt;br /&gt;
:; Comparator : Can comparator types be modeled with the solution while being type safe and expressive?&lt;br /&gt;
; Complexity of the compiler check : Is it just a matter of doing one check or several?&lt;br /&gt;
; Complexity of the runtime : Does the runtime need more information to do assignment attempts or object tests?&lt;br /&gt;
; Whole-system analysis : Is a whole-system analysis necessary?&lt;br /&gt;
; Dynamic class and type loading : Is it safe to dynamically load new classes at runtime and instantiate new types?&lt;br /&gt;
; Backward compatibility : Is the solution backward compatible to existing source code?&lt;br /&gt;
:; Applicable per cluster : Can the solution be applied on a per cluster basis?&lt;br /&gt;
; Support of compiler/IDE : Can the compiler/IDE help in updating existing source code? How?&lt;br /&gt;
&lt;br /&gt;
== General remarks ==&lt;br /&gt;
&lt;br /&gt;
=== Checking feature calls ===&lt;br /&gt;
&lt;br /&gt;
As the ''Single-level Call rule'' (8.25.3, VUSC) describes, a feature call is only valid if it is valid for every type in the dynamic type set. A simple solution would be that every feature call has to be checked for all possible descendants of the static target type. If this check is performed on a system, it will catch all catcalls - but also report false positives.&lt;br /&gt;
&lt;br /&gt;
Some of the proposed solutions try to address this problem by finding a better approximation to the dynamic type set so that the false positives can be ruled out.&lt;br /&gt;
&lt;br /&gt;
In general this is problematic as it requires a whole-system analysis, thus preventing the dynamic loading of new classes at run-time. The reason for this is that it is not known at compile time which features will be covariantly redefined by dynamically loaded classes.&lt;br /&gt;
&lt;br /&gt;
This is only the case with non-generic types. For generics, it is known at compile time that all features containing a formal in the parameter list can be treated as covariantly redefined and corresponding precautions can be implemented via the type system and conformance rules which allow to load even generic types at run-time.&lt;br /&gt;
&lt;br /&gt;
By the way, Eiffel Software has started to [[Single level call rule implementation|implement the basis of the ''single-level call rule'']] in it's Eiffel compiler. It is work in progress which revealed some implementation problems.&lt;br /&gt;
&lt;br /&gt;
=== Generic vs. non-generic covariance ===&lt;br /&gt;
&lt;br /&gt;
We can distinguish two different kinds of covariant argument redefinition:&lt;br /&gt;
&lt;br /&gt;
* When a generic type is derived, the formal generic parameters will be replaced by the actual generic parameters. Given the current conformance rules for generics, this can be seen as a covariant redefinition for all features which contain a formal generic as an argument. A simple example is the change from &amp;lt;e&amp;gt;LIST [ANY]&amp;lt;/e&amp;gt; to &amp;lt;e&amp;gt;LIST [INTEGER]&amp;lt;/e&amp;gt; where the feature &amp;lt;e&amp;gt;put&amp;lt;/e&amp;gt; changes signature from &amp;lt;e&amp;gt;ANY&amp;lt;/e&amp;gt; to &amp;lt;e&amp;gt;INTEGER&amp;lt;/e&amp;gt;.&lt;br /&gt;
* In the non-generic case, covariance happens for certain anchored type declarations and in the case of explicitly changing an argument type to a descendant. This happens in general only on a small subset of the features.&lt;br /&gt;
&lt;br /&gt;
The main difference is that in the generic case, all features which have a formal generic parameter automatically change the signature in different derivations whereas the non-generic case only specific features are covariantly redefined (if any at all). Also, in the generic case it is known for all possible descendants which features are redefined covariantly.&lt;br /&gt;
&lt;br /&gt;
This observation helps to understand the various proposals and to see their strengths and weaknesses:&lt;br /&gt;
* A proposal which operates on the feature level can be good for non-generic classes as you generally have a small number of features covariantly redefined and you only have to specify these features. In the case of generics this can become cumbersome as all features with formal generic parameters are always considered as covariantly redefined and thus for generics they always have to be considered.&lt;br /&gt;
* A proposal which operates on the type level is better suited for generics as you don't have to specify every single feature which has a formal generic parameter as argument. But they run into problems in the non-generic case if you look at anchored types - for example &amp;lt;e&amp;gt;like Current&amp;lt;/e&amp;gt;. Due to the fact that you have a covariant redeclaration in every descendant with such a feature, operating on the type level means that you have to handle every descendant specifically whereas if you operated on the feature level you could just handle this single feature.&lt;br /&gt;
* You see that there are two families of features: Features with formal arguments and ordinary features which are covariantly redefined. The fundamental difference between these two families is that they can change their signature independently. From &amp;lt;e&amp;gt;LIST [ANY]&amp;lt;/e&amp;gt; to &amp;lt;e&amp;gt;LIST [INTEGER]&amp;lt;/e&amp;gt; only the features based on the formal change their signature while they don't change from &amp;lt;e&amp;gt;LIST [ANY]&amp;lt;/e&amp;gt; to &amp;lt;e&amp;gt;LINKED_LIST [ANY]&amp;lt;/e&amp;gt; where the ordinary ones do. If you don't want to restrict the programmers expressiveness these feature families have to be addressed separately and a ''one fits all'' solution does not exist.&lt;br /&gt;
&lt;br /&gt;
=== Contravariant generics ===&lt;br /&gt;
&lt;br /&gt;
The modeling of certain problems involving generics requires contravariance. The two examples which will be used are comparator objects and agents:&lt;br /&gt;
&lt;br /&gt;
* If you want to compare objects using a comparator, it either needs to be able to compare objects of the exact type, or an ancestor. Thus if you want to compare strings, either a comparator for &amp;lt;e&amp;gt;STRING&amp;lt;/e&amp;gt; or one for &amp;lt;e&amp;gt;ANY&amp;lt;/e&amp;gt; is suitable. &lt;br /&gt;
* If you want to pass an argument of type &amp;lt;e&amp;gt;STRING&amp;lt;/e&amp;gt; to an agent, the agent either has to accept a &amp;lt;e&amp;gt;STRING&amp;lt;/e&amp;gt; or &amp;lt;e&amp;gt;ANY&amp;lt;/e&amp;gt; argument (or no argument at all).&lt;br /&gt;
&lt;br /&gt;
These problems can only be modeled if there is a way to express contravariant conformance for generics. This means that all proposed solutions which don't offer this possibility can't be used to model agents or comparator correctly and safely.&lt;br /&gt;
&lt;br /&gt;
=== Catcall benchmark ===&lt;br /&gt;
&lt;br /&gt;
[[Catcall checkpoints]]&lt;br /&gt;
&lt;br /&gt;
== Overview of general solutions ==&lt;br /&gt;
&lt;br /&gt;
The following proposals handle the case of covariance on non-generic and generic types.&lt;br /&gt;
&lt;br /&gt;
=== [[Novariance]] ===&lt;br /&gt;
&lt;br /&gt;
In the novariance proposal, covariant redefinition for arguments is prohibited. If covariance is needed for modeling purposes it can be [http://dev.eiffel.com/Covariance_through_renaming simulated by renaming].&lt;br /&gt;
&lt;br /&gt;
The conformance between generics with different formal parameters is removed.&lt;br /&gt;
&lt;br /&gt;
=== [[Forget / keep]] ===&lt;br /&gt;
&lt;br /&gt;
With the forget and keep mechanisms you specify per type on the feature level which features need not to be called - these features can safely be redefined covariantly - or which features have to be available - these features have to be typesafe for all possible values of a caller object.&lt;br /&gt;
&lt;br /&gt;
Reference: [http://dev.eiffel.com/Forget_/_Keep_Mechanism Article on dev.eiffel.com]&lt;br /&gt;
&lt;br /&gt;
=== Dynamic typeset algorithm ===&lt;br /&gt;
&lt;br /&gt;
The dynamic typeset algorithm does not change any semantics of the types or the conformance as it is in Eiffel already, it only does an abstract execution of the system to limit the possibilities per feature call which have to be checked if they are safe.&lt;br /&gt;
== Overview of solutions for non-generics ==&lt;br /&gt;
&lt;br /&gt;
These proposal only address the case for non-generics. For generic catcalls another solution (e.g. wildcard generics) can be used.&lt;br /&gt;
&lt;br /&gt;
=== [[Restrict types]] ===&lt;br /&gt;
&lt;br /&gt;
With restrict types you specify per type on the type level which descendant types that are allowed. Only these types can be assigned to such a variable, and all feature calls on these variables have to be valid for all possible types in this list.&lt;br /&gt;
&lt;br /&gt;
Reference: [http://se.inf.ethz.ch/cgi-bin/ecma/index.cgi?IssueFLEX_CATCALL IssueFLEX_CATCALL on ECMA wiki]&amp;lt;br/&amp;gt;&lt;br /&gt;
Reference: Discussion in ECMA mailinglist named ''Catcall removal: another proposal'', [[Restrict types mail|available in parts]]&lt;br /&gt;
&lt;br /&gt;
=== [[DOG proposal]] ===&lt;br /&gt;
&lt;br /&gt;
With the DOG proposal, features which can be covariantly redefined have to be marked as such. These features can only be called on specially marked entities which have a restricted conformance, thus preventing assignments from descendants with potential covariantly redefined arguments.&lt;br /&gt;
&lt;br /&gt;
Reference: [http://se.inf.ethz.ch/cgi-bin/ecma/index.cgi?IssueDOG IssueDOG on ECMA wiki]&lt;br /&gt;
&lt;br /&gt;
== Overview of solutions for generics ==&lt;br /&gt;
&lt;br /&gt;
These proposal only address the case for generics. For non-generic catcalls another solution (e.g. novariance) can be used.&lt;br /&gt;
&lt;br /&gt;
=== [[Usage-site variance]] ===&lt;br /&gt;
&lt;br /&gt;
This solution lets the programmer decide on the instantiation of a generic if the generic parameter should be covariant, contravariant or invariant. Depending on the variance, the applicable features of the type and the conformance rules to other generic types are changed.&lt;br /&gt;
&lt;br /&gt;
Reference: [http://pag.csail.mit.edu/reading-group/variance-ECOOP02.pdf On variance-based subtyping for parametric types]&lt;br /&gt;
&lt;br /&gt;
=== [[Definition-site variance]] ===&lt;br /&gt;
&lt;br /&gt;
This solution lets the programmer decide in the definition of a generic class if the generic parameter should be covariant, contravariant or invariant. Depending on the variance, the formal generic can only appear at the argument, only appear as a result type or appear in both places. Also the conformance is adapted depending on the variance of the generic parameter.&lt;br /&gt;
&lt;br /&gt;
This is the solution which is implemented in the CLR, although not supported by generics in C# which are novariant.&lt;br /&gt;
&lt;br /&gt;
Reference: [http://blogs.msdn.com/rmbyers/archive/2006/06/01/613690.aspx Article about generics in CLR]&lt;br /&gt;
&lt;br /&gt;
Note: There is also a [http://fams.de/text/type-safe-eiffel.html proposal by Bernd Schoeller] about ''variant and invariant'' generics which is a subset of this one and thus not explained in detail.&lt;br /&gt;
&lt;br /&gt;
=== Wildcard generics ===&lt;br /&gt;
&lt;br /&gt;
This mechanism extends the [[usage-site variance]] by adding a wildcard to the generic derivation. This wildcard denotes unspecified types and limits the use of features with generic parameters or result types over conformance to the wildcard types.&lt;br /&gt;
&lt;br /&gt;
Since the mechanism is almost identical to the usage-site variance, it will not be looked at in more detail. Please refer to the reference article for more information.&lt;br /&gt;
&lt;br /&gt;
Reference: [http://www.jot.fm/issues/issue_2004_12/article5 Adding Wildcards to the Java Programming Language]&lt;br /&gt;
&lt;br /&gt;
== Overview of dynamic solutions ==&lt;br /&gt;
&lt;br /&gt;
These proposals do not prevent catcalls at compile-time but introduce means to handle catcalls at runtime.&lt;br /&gt;
&lt;br /&gt;
=== [[Detachable types]] ===&lt;br /&gt;
&lt;br /&gt;
This solution allows covariantly redefined features only to use detachable types. Through this mechanism, an object test is necessary before an argument can be used. This forces the programmer to test arguments for validity.&lt;br /&gt;
&lt;br /&gt;
Reference: [http://se.ethz.ch/~meyer/publications/lncs/attached.pdf Article about ''attached types'' by Bertrand Meyer]&amp;lt;br/&amp;gt;&lt;br /&gt;
Reference: [http://www.ecma-international.org/publications/standards/Ecma-367.htm ECMA Eiffel standard 2nd edition of June 2006]&lt;br /&gt;
&lt;br /&gt;
=== Recast ===&lt;br /&gt;
&lt;br /&gt;
In the recast proposal, the programmer has to specify a transformation function when covariantly redefining a feature which can transform the old argument types to the new ones.&lt;br /&gt;
&lt;br /&gt;
Reference: [http://se.inf.ethz.ch/cgi-bin/ecma/index.cgi?IssueCAT IssueCAT on ECMA wiki]&amp;lt;br/&amp;gt;&lt;br /&gt;
Reference: [http://www.inf.ethz.ch/~meyer/ongoing/covariance/recast.pdf Article about recast]&lt;br /&gt;
&lt;br /&gt;
=== Exceptions ===&lt;br /&gt;
&lt;br /&gt;
Another way of handling catcalls at runtime is to raise exceptions. It can be required or not to provide a rescue clause which handles the case of the catcall.&lt;br /&gt;
&lt;br /&gt;
== Combinations ==&lt;br /&gt;
&lt;br /&gt;
It is also possible to combine different proposals:&lt;br /&gt;
&lt;br /&gt;
* Novariance for non-generic features and usage-site variance for generics .&lt;br /&gt;
* Forget / keep for non-generic features and definition-site variance for generics.&lt;br /&gt;
* DOG proposal for non-generic features and wildcard generics.&lt;br /&gt;
* ...&lt;br /&gt;
&lt;br /&gt;
== Results ==&lt;br /&gt;
&lt;br /&gt;
The following table summarizes the support of the various solutions to the criteria described above which can be used to judge a catcall solution.&lt;br /&gt;
&lt;br /&gt;
This results can be differently interpreted, so the colors may not be totally accurate. See the [[Comparison of catcall solutions#Table_explained|explanation at the end of the table]] for more information&lt;br /&gt;
&lt;br /&gt;
=== General solutions ===&lt;br /&gt;
&lt;br /&gt;
{| border=1 cellpadding=2&lt;br /&gt;
&lt;br /&gt;
|- style=&amp;quot;visibility: hidden&amp;quot;&lt;br /&gt;
| style=&amp;quot;width:25%&amp;quot; |&lt;br /&gt;
| style=&amp;quot;width:25%&amp;quot; |&lt;br /&gt;
| style=&amp;quot;width:25%&amp;quot; |&lt;br /&gt;
| style=&amp;quot;width:25%&amp;quot; |&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
&lt;br /&gt;
! Criteria&lt;br /&gt;
! [[Novariance]]&lt;br /&gt;
! [[Forget / keep]]&lt;br /&gt;
! Dynamic typeset algorithm&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
&lt;br /&gt;
! Syntax overhead&lt;br /&gt;
| {{Green|No}}&lt;br /&gt;
| {{Red|Big}}: forget/keep clauses per type&lt;br /&gt;
| {{Green|No}}&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
&lt;br /&gt;
! Covariance on non-generic types &lt;br /&gt;
| {{Red|Not allowed}}&lt;br /&gt;
| {{Green|Allowed}}&lt;br /&gt;
| {{Green|Allowed}}&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
&lt;br /&gt;
! Export status restrictions&lt;br /&gt;
| {{Red|Not allowed}}&lt;br /&gt;
| {{Green|Allowed}}&lt;br /&gt;
| {{Green|Allowed}}&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
&lt;br /&gt;
! Use of generic types&lt;br /&gt;
| {{Red|Very limited}}: Only invariant conformance&lt;br /&gt;
| {{Orange|Limited}}: Conformance restricted (''keep all'' as default)&amp;lt;br/&amp;gt;{{Orange|Limited}}: Use restricted (''forget all'' as default)&lt;br /&gt;
| {{Green|As it is now}}&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
&lt;br /&gt;
! Agents&lt;br /&gt;
| {{Orange|Limited}}&amp;lt;br/&amp;gt;{{Green|Safe}}&lt;br /&gt;
| {{Orange|Limited}}&amp;lt;br/&amp;gt;{{Green|Safe}}&lt;br /&gt;
| {{Red|As it is now}}&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
&lt;br /&gt;
! Comparator&lt;br /&gt;
| {{Red|Not supported}}&lt;br /&gt;
| {{Red|Not supported}}&lt;br /&gt;
| {{Red|Not supported}}&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
&lt;br /&gt;
! Complexity of compiler check&lt;br /&gt;
| {{Green|Small}}&lt;br /&gt;
| {{Orange|Medium}}: Check of feature call for all descendants; Conformance check on forget/keep clauses&lt;br /&gt;
| {{Red|Big}}: Iterative abstract system execution&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
&lt;br /&gt;
! Complexity of runtime&lt;br /&gt;
| {{Green|Small}}: As it is now&lt;br /&gt;
| {{Orange|Medium}}: Need to know cat features for object tests&lt;br /&gt;
| {{Green|Small}}: As it is now&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
&lt;br /&gt;
! Whole-system analysis&lt;br /&gt;
| {{Green|No}}&lt;br /&gt;
| {{Red|Yes}}: use of ''forget all'' depends on system&lt;br /&gt;
| {{Red|Yes}}&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
&lt;br /&gt;
! Dynamic class and type loading&lt;br /&gt;
| {{Green|Yes}}&lt;br /&gt;
| {{Red|No}}&lt;br /&gt;
| {{Red|No}}&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
&lt;br /&gt;
! Backward compatibility&lt;br /&gt;
| {{Red|Very limited}}&lt;br /&gt;
| {{Orange|Limited}}&lt;br /&gt;
| {{Green|Full}}&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
&lt;br /&gt;
! Support of IDE (Source changes)&lt;br /&gt;
| {{Green|Not needed}}&lt;br /&gt;
| {{Orange|Possible}}: Can propose forget/keep clauses&lt;br /&gt;
| {{Green|Not needed}}&lt;br /&gt;
&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Solutions for non-generics ===&lt;br /&gt;
&lt;br /&gt;
{| border=1 cellpadding=2&lt;br /&gt;
&lt;br /&gt;
|- style=&amp;quot;visibility: hidden&amp;quot;&lt;br /&gt;
| style=&amp;quot;width:25%&amp;quot; |&lt;br /&gt;
| style=&amp;quot;width:25%&amp;quot; |&lt;br /&gt;
| style=&amp;quot;width:25%&amp;quot; |&lt;br /&gt;
| style=&amp;quot;width:25%&amp;quot; |&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
&lt;br /&gt;
! Criteria&lt;br /&gt;
! [[Restrict types]]&lt;br /&gt;
! [[DOG proposal]]&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
&lt;br /&gt;
! Syntax overhead&lt;br /&gt;
| {{Red|Big}}: Restrict clause per type declaration&lt;br /&gt;
| {{Orange|Medium}}: ''cat'' on features and on type declarations&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
&lt;br /&gt;
! Covariance on non-generic types &lt;br /&gt;
| {{Green|Allowed}}&lt;br /&gt;
| {{Green|Allowed}}&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
&lt;br /&gt;
! Export status restrictions&lt;br /&gt;
| {{Green|Allowed}}&lt;br /&gt;
| {{Green|Allowed}}&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
&lt;br /&gt;
! Use of generic types&lt;br /&gt;
| Not addressed&lt;br /&gt;
| Not addressed&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
&lt;br /&gt;
! Agents&lt;br /&gt;
| Not addressed&lt;br /&gt;
| Not addressed&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
&lt;br /&gt;
! Comparator&lt;br /&gt;
| Not addressed&lt;br /&gt;
| Not addressed&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
&lt;br /&gt;
! Complexity of compiler check&lt;br /&gt;
| {{Orange|Medium}}: Check of feature call for all descendants; Conformance check on restrict clauses&lt;br /&gt;
| {{Green|Small}}: Check of ''cat'' on conformance&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
&lt;br /&gt;
! Complexity of runtime&lt;br /&gt;
| not yet considered&lt;br /&gt;
| {{Green|Small}}&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
&lt;br /&gt;
! Whole-system analysis&lt;br /&gt;
| {{Orange|Partial}}&lt;br /&gt;
| {{Green|No}}&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
&lt;br /&gt;
! Dynamic class and type loading&lt;br /&gt;
| {{Orange|Limited}}&lt;br /&gt;
| {{Green|Yes}}&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
&lt;br /&gt;
! Backward compatibility&lt;br /&gt;
| {{Red|Very limited}}&lt;br /&gt;
| {{Red|Very limited}}&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
&lt;br /&gt;
! Support of IDE (Source changes)&lt;br /&gt;
| {{Orange|Possible}}: Can propose restrict clauses&lt;br /&gt;
| {{Orange|Possible}}: Can propose ''cat'' marks&lt;br /&gt;
&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Solutions for generics ===&lt;br /&gt;
&lt;br /&gt;
{| border=1 cellpadding=2&lt;br /&gt;
&lt;br /&gt;
|- style=&amp;quot;visibility: hidden&amp;quot;&lt;br /&gt;
| style=&amp;quot;width:25%&amp;quot; |&lt;br /&gt;
| style=&amp;quot;width:25%&amp;quot; |&lt;br /&gt;
| style=&amp;quot;width:25%&amp;quot; |&lt;br /&gt;
| style=&amp;quot;width:25%&amp;quot; |&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
&lt;br /&gt;
! Criteria&lt;br /&gt;
! [[Usage-site variance]]&lt;br /&gt;
! [[Definition-site variance]]&lt;br /&gt;
! Wildcard generics&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
&lt;br /&gt;
! Syntax overhead&lt;br /&gt;
| {{Orange|Medium}}: Variance marks per generic type&lt;br /&gt;
| {{Green|Small}}: Variance marks per generic class definition&lt;br /&gt;
| {{Orange|Medium}}: Variance marks per generic type&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
&lt;br /&gt;
! Covariance on non-generic types &lt;br /&gt;
| Not addressed&lt;br /&gt;
| Not addressed&lt;br /&gt;
| Not addressed&lt;br /&gt;
|-&lt;br /&gt;
&lt;br /&gt;
! Export status restrictions&lt;br /&gt;
| Not addressed&lt;br /&gt;
| Not addressed&lt;br /&gt;
| Not addressed&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
&lt;br /&gt;
! Use of generic types&lt;br /&gt;
| {{Orange|Limited}}: Conformance is limited&amp;lt;br/&amp;gt;{{Green|Safe}}&lt;br /&gt;
| {{Orange|Limited}}: Conformance is limited&amp;lt;br/&amp;gt;{{Green|Safe}}&lt;br /&gt;
| {{Orange|Limited}}: Conformance is limited&amp;lt;br/&amp;gt;{{Green|Safe}}&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
&lt;br /&gt;
! Agents&lt;br /&gt;
| {{Green|Fully supported}}&amp;lt;br/&amp;gt;{{Green|Safe}}&lt;br /&gt;
| {{Green|Fully supported}}: If tuples can be specified covariantly&amp;lt;br/&amp;gt;{{Green|Safe}}&lt;br /&gt;
| {{Green|Fully supported}}&amp;lt;br/&amp;gt;{{Green|Safe}}&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
&lt;br /&gt;
! Comparator&lt;br /&gt;
| {{Green|Supported}}&lt;br /&gt;
| {{Green|Supported}}&lt;br /&gt;
| {{Green|Supported}}&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
&lt;br /&gt;
! Complexity of compiler check&lt;br /&gt;
| {{Green|Small}}: Consider variance in conformance check&lt;br /&gt;
| {{Green|Small}}: Consider variance in conformance check&lt;br /&gt;
| {{Green|Small}}: Consider variance in conformance check&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
&lt;br /&gt;
! Complexity of runtime&lt;br /&gt;
| {{Green|Small}}: Consider variance in object test&lt;br /&gt;
| {{Green|Small}}: Consider variance in object test&lt;br /&gt;
| {{Green|Small}}: Consider variance in object test&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
&lt;br /&gt;
! Whole-system analysis&lt;br /&gt;
| {{Green|No}}&lt;br /&gt;
| {{Green|No}}&lt;br /&gt;
| {{Green|No}}&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
&lt;br /&gt;
! Dynamic class and type loading&lt;br /&gt;
| {{Green|Yes}}&lt;br /&gt;
| {{Green|Yes}}&lt;br /&gt;
| {{Green|Yes}}&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
&lt;br /&gt;
! Backward compatibility&lt;br /&gt;
| {{Orange|Limited}}: Use of generics changed due to conformance&lt;br /&gt;
| {{Red|Very limited}}: Libraries need redesign&lt;br /&gt;
| {{Orange|Limited}}: Use of generics changed due to conformance&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
&lt;br /&gt;
! Support of IDE (Source changes)&lt;br /&gt;
| {{Orange|Possible}}: Can propose variance marks&lt;br /&gt;
| {{Red|Not possible}}: Libraries need redesign&lt;br /&gt;
| {{Orange|Possible}}: Can propose variance marks/wildcards&lt;br /&gt;
&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Dynamic solutions ===&lt;br /&gt;
&lt;br /&gt;
{| border=1 cellpadding=2&lt;br /&gt;
&lt;br /&gt;
|- style=&amp;quot;visibility: hidden&amp;quot;&lt;br /&gt;
| style=&amp;quot;width:25%&amp;quot; |&lt;br /&gt;
| style=&amp;quot;width:25%&amp;quot; |&lt;br /&gt;
| style=&amp;quot;width:25%&amp;quot; |&lt;br /&gt;
| style=&amp;quot;width:25%&amp;quot; |&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
&lt;br /&gt;
! Criteria&lt;br /&gt;
! [[Detachable types]]&lt;br /&gt;
! Recast&lt;br /&gt;
! Exceptions&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
&lt;br /&gt;
! Syntax overhead&lt;br /&gt;
| {{Green|Small}}: Detachment marks&lt;br /&gt;
| {{Red|Big}}: Recast clauses, recast features&lt;br /&gt;
| {{Orange|Medium}}: If rescue clause mandatory&amp;lt;br/&amp;gt;{{Green|No}}: If rescue clause not needed&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
&lt;br /&gt;
! Covariance on non-generic types &lt;br /&gt;
| {{Red|Very limited}}: Only detached arguments, no expanded arguments&lt;br /&gt;
| {{Green|Allowed}}&lt;br /&gt;
| {{Green|Allowed}}&lt;br /&gt;
|-&lt;br /&gt;
&lt;br /&gt;
! Export status restrictions&lt;br /&gt;
| Not addressed&lt;br /&gt;
| Not addressed&lt;br /&gt;
| Not addressed&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
&lt;br /&gt;
! Use of generics&lt;br /&gt;
| {{Red|Very limited}}: Only detachable formal arguments&lt;br /&gt;
| {{Red|Very limited}}: Recast clause for all features with formal generics&lt;br /&gt;
| {{Green|As it is now}}&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
&lt;br /&gt;
! Agents&lt;br /&gt;
| {{Red|As it is now}} &lt;br /&gt;
| {{Red|As it is now}} &lt;br /&gt;
| {{Red|As it is now}} &lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
&lt;br /&gt;
! Comparator&lt;br /&gt;
| {{Red|Not supported}}&lt;br /&gt;
| {{Red|Not supported}}&lt;br /&gt;
| {{Red|Not supported}}&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
&lt;br /&gt;
! Complexity of compiler check&lt;br /&gt;
| {{Green|Small}}: As it is now&lt;br /&gt;
| {{Green|Small}}: As it is now&lt;br /&gt;
| {{Green|Small}}: As it is now&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
&lt;br /&gt;
! Complexity of runtime&lt;br /&gt;
| {{Green|Small}}: As it is now&lt;br /&gt;
| {{Orange|Medium}}: Check for catcalls and do recast&lt;br /&gt;
| {{Orange|Medium}}: Check for catcalls and raise exception&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
&lt;br /&gt;
! Whole-system analysis&lt;br /&gt;
| {{Green|No}}&lt;br /&gt;
| {{Green|No}}&lt;br /&gt;
| {{Green|No}}&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
&lt;br /&gt;
! Dynamic class and type loading&lt;br /&gt;
| {{Green|Yes}}&lt;br /&gt;
| {{Green|Yes}}&lt;br /&gt;
| {{Green|Yes}}&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
&lt;br /&gt;
! Backward compatibility&lt;br /&gt;
| {{Red|Very limited}}: All covariant and generic features become detached&lt;br /&gt;
| {{Red|Very limited}}: All covariant and generic features need recast clause&lt;br /&gt;
| {{Orange|Limited}}: If rescue clause is mandatory&amp;lt;br/&amp;gt;{{Green|Full}}: If rescue clause not needed&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
&lt;br /&gt;
! Support of IDE (Source changes)&lt;br /&gt;
| {{Orange|Possible}}: Can propose detachment marks&lt;br /&gt;
| {{Red|Not possible}}: Programmer must provide recast clause&lt;br /&gt;
| {{Red|Not possible}}: If rescue clause mandatory&amp;lt;br/&amp;gt;{{Green|Not needed}}: If rescue clause not needed&lt;br /&gt;
&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Table explained ===&lt;br /&gt;
&lt;br /&gt;
; Syntax overhead : {{Green|Small}} if a keyword/mark is needed per class/feature declaration; {{Orange|Medium}} if a keyword/mark is neede per type declaration; {{Red|Big}} if a clause is needed per type declaration.&lt;br /&gt;
; Use of generics : {{Green|As it is now}} if assignments are possible if generic parameters conform; {{Orange|Limited}} is some restrictions in the use or the conformance between generics exist; {{Red|Very limited}} a lot of restrictions in the use or the conformance between generics exist.&lt;br /&gt;
; Agents : {{Green|Fully supported}} if all safe assignments are allowed; {{Orange|Limited}} if not all safe assignments are allowed; {{Red|As it is now}} if unsafe assignments are still possible.&lt;br /&gt;
; Comparator : {{Green|Supported}} if for a comparator all safe assignments are permitted (i.e. contravariant assignments); {{Red|Not supported}} if only exact type or even (unsafe) subtypes can be assigned.&lt;br /&gt;
; Support of IDE (Source changes) : {{Green|Not needed}} if everything still works the same; {{Orange|Possible}} if the compiler can suggest clauses or marks; {{Red|Not possible}} if the programmer has to specify additional features/instructions.&lt;br /&gt;
&lt;br /&gt;
== Personal opinions ==&lt;br /&gt;
&lt;br /&gt;
[[Personal view about catcall solution]]&lt;/div&gt;</summary>
		<author><name>Juliant</name></author>	</entry>

	<entry>
		<id>https://dev.eiffel.com/index.php?title=Comparison_of_catcall_solutions&amp;diff=8916</id>
		<title>Comparison of catcall solutions</title>
		<link rel="alternate" type="text/html" href="https://dev.eiffel.com/index.php?title=Comparison_of_catcall_solutions&amp;diff=8916"/>
				<updated>2007-06-24T19:08:48Z</updated>
		
		<summary type="html">&lt;p&gt;Juliant: /* Solutions for generics */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Category:ECMA]]&lt;br /&gt;
[[Category:Catcall]]&lt;br /&gt;
== Motivation ==&lt;br /&gt;
&lt;br /&gt;
By allowing covariant feature redefinition and hiding of features, the Eiffel language introduces the problem of catcalls (Changed Availability or Type). Currently the ECMA Eiffel standard does not specify how the occurrence of catcalls should be statically rejected.&lt;br /&gt;
&lt;br /&gt;
The purpose of this document is to show a comparison between different proposals on how to handle the issue of preventing catcalls.&lt;br /&gt;
&lt;br /&gt;
== Criteria for a solution ==&lt;br /&gt;
&lt;br /&gt;
To be able to judge a solution we use the following criteria which we consider as important:&lt;br /&gt;
&lt;br /&gt;
; Syntax overhead : How much syntax will be added to the language in order to express safe covariance and generics?&lt;br /&gt;
; Covariance on non-generic types : Are covariant argument redefinitions addressed in the solution? How does the programmer express it?&lt;br /&gt;
; Export status restrictions : Is restriction of export status addressed in the solution? How does the programmer express it?&lt;br /&gt;
; Use of generic types : How is conformance of generics? Are catcalls for generics addressed in the solution? How does the programmer express it? Can generics be used as now or are there restrictions?&lt;br /&gt;
:; Agents : Can agents be modeled with the solution while being type safe and expressive?&lt;br /&gt;
:; Comparator : Can comparator types be modeled with the solution while being type safe and expressive?&lt;br /&gt;
; Complexity of the compiler check : Is it just a matter of doing one check or several?&lt;br /&gt;
; Complexity of the runtime : Does the runtime need more information to do assignment attempts or object tests?&lt;br /&gt;
; Whole-system analysis : Is a whole-system analysis necessary?&lt;br /&gt;
; Dynamic class and type loading : Is it safe to dynamically load new classes at runtime and instantiate new types?&lt;br /&gt;
; Backward compatibility : Is the solution backward compatible to existing source code?&lt;br /&gt;
:; Applicable per cluster : Can the solution be applied on a per cluster basis?&lt;br /&gt;
; Support of compiler/IDE : Can the compiler/IDE help in updating existing source code? How?&lt;br /&gt;
&lt;br /&gt;
== General remarks ==&lt;br /&gt;
&lt;br /&gt;
=== Checking feature calls ===&lt;br /&gt;
&lt;br /&gt;
As the ''Single-level Call rule'' (8.25.3, VUSC) describes, a feature call is only valid if it is valid for every type in the dynamic type set. A simple solution would be that every feature call has to be checked for all possible descendants of the static target type. If this check is performed on a system, it will catch all catcalls - but also report false positives.&lt;br /&gt;
&lt;br /&gt;
Some of the proposed solutions try to address this problem by finding a better approximation to the dynamic type set so that the false positives can be ruled out.&lt;br /&gt;
&lt;br /&gt;
In general this is problematic as it requires a whole-system analysis, thus preventing the dynamic loading of new classes at run-time. The reason for this is that it is not known at compile time which features will be covariantly redefined by dynamically loaded classes.&lt;br /&gt;
&lt;br /&gt;
This is only the case with non-generic types. For generics, it is known at compile time that all features containing a formal in the parameter list can be treated as covariantly redefined and corresponding precautions can be implemented via the type system and conformance rules which allow to load even generic types at run-time.&lt;br /&gt;
&lt;br /&gt;
By the way, Eiffel Software has started to [[Single level call rule implementation|implement the basis of the ''single-level call rule'']] in it's Eiffel compiler. It is work in progress which revealed some implementation problems.&lt;br /&gt;
&lt;br /&gt;
=== Generic vs. non-generic covariance ===&lt;br /&gt;
&lt;br /&gt;
We can distinguish two different kinds of covariant argument redefinition:&lt;br /&gt;
&lt;br /&gt;
* When a generic type is derived, the formal generic parameters will be replaced by the actual generic parameters. Given the current conformance rules for generics, this can be seen as a covariant redefinition for all features which contain a formal generic as an argument. A simple example is the change from &amp;lt;e&amp;gt;LIST [ANY]&amp;lt;/e&amp;gt; to &amp;lt;e&amp;gt;LIST [INTEGER]&amp;lt;/e&amp;gt; where the feature &amp;lt;e&amp;gt;put&amp;lt;/e&amp;gt; changes signature from &amp;lt;e&amp;gt;ANY&amp;lt;/e&amp;gt; to &amp;lt;e&amp;gt;INTEGER&amp;lt;/e&amp;gt;.&lt;br /&gt;
* In the non-generic case, covariance happens for certain anchored type declarations and in the case of explicitly changing an argument type to a descendant. This happens in general only on a small subset of the features.&lt;br /&gt;
&lt;br /&gt;
The main difference is that in the generic case, all features which have a formal generic parameter automatically change the signature in different derivations whereas the non-generic case only specific features are covariantly redefined (if any at all). Also, in the generic case it is known for all possible descendants which features are redefined covariantly.&lt;br /&gt;
&lt;br /&gt;
This observation helps to understand the various proposals and to see their strengths and weaknesses:&lt;br /&gt;
* A proposal which operates on the feature level can be good for non-generic classes as you generally have a small number of features covariantly redefined and you only have to specify these features. In the case of generics this can become cumbersome as all features with formal generic parameters are always considered as covariantly redefined and thus for generics they always have to be considered.&lt;br /&gt;
* A proposal which operates on the type level is better suited for generics as you don't have to specify every single feature which has a formal generic parameter as argument. But they run into problems in the non-generic case if you look at anchored types - for example &amp;lt;e&amp;gt;like Current&amp;lt;/e&amp;gt;. Due to the fact that you have a covariant redeclaration in every descendant with such a feature, operating on the type level means that you have to handle every descendant specifically whereas if you operated on the feature level you could just handle this single feature.&lt;br /&gt;
* You see that there are two families of features: Features with formal arguments and ordinary features which are covariantly redefined. The fundamental difference between these two families is that they can change their signature independently. From &amp;lt;e&amp;gt;LIST [ANY]&amp;lt;/e&amp;gt; to &amp;lt;e&amp;gt;LIST [INTEGER]&amp;lt;/e&amp;gt; only the features based on the formal change their signature while they don't change from &amp;lt;e&amp;gt;LIST [ANY]&amp;lt;/e&amp;gt; to &amp;lt;e&amp;gt;LINKED_LIST [ANY]&amp;lt;/e&amp;gt; where the ordinary ones do. If you don't want to restrict the programmers expressiveness these feature families have to be addressed separately and a ''one fits all'' solution does not exist.&lt;br /&gt;
&lt;br /&gt;
=== Contravariant generics ===&lt;br /&gt;
&lt;br /&gt;
The modeling of certain problems involving generics requires contravariance. The two examples which will be used are comparator objects and agents:&lt;br /&gt;
&lt;br /&gt;
* If you want to compare objects using a comparator, it either needs to be able to compare objects of the exact type, or an ancestor. Thus if you want to compare strings, either a comparator for &amp;lt;e&amp;gt;STRING&amp;lt;/e&amp;gt; or one for &amp;lt;e&amp;gt;ANY&amp;lt;/e&amp;gt; is suitable. &lt;br /&gt;
* If you want to pass an argument of type &amp;lt;e&amp;gt;STRING&amp;lt;/e&amp;gt; to an agent, the agent either has to accept a &amp;lt;e&amp;gt;STRING&amp;lt;/e&amp;gt; or &amp;lt;e&amp;gt;ANY&amp;lt;/e&amp;gt; argument (or no argument at all).&lt;br /&gt;
&lt;br /&gt;
These problems can only be modeled if there is a way to express contravariant conformance for generics. This means that all proposed solutions which don't offer this possibility can't be used to model agents or comparator correctly and safely.&lt;br /&gt;
&lt;br /&gt;
=== Catcall benchmark ===&lt;br /&gt;
&lt;br /&gt;
[[Catcall checkpoints]]&lt;br /&gt;
&lt;br /&gt;
== Overview of general solutions ==&lt;br /&gt;
&lt;br /&gt;
The following proposals handle the case of covariance on non-generic and generic types.&lt;br /&gt;
&lt;br /&gt;
=== [[Novariance]] ===&lt;br /&gt;
&lt;br /&gt;
In the novariance proposal, covariant redefinition for arguments is prohibited. If covariance is needed for modeling purposes it can be [http://dev.eiffel.com/Covariance_through_renaming simulated by renaming].&lt;br /&gt;
&lt;br /&gt;
The conformance between generics with different formal parameters is removed.&lt;br /&gt;
&lt;br /&gt;
=== [[Forget / keep]] ===&lt;br /&gt;
&lt;br /&gt;
With the forget and keep mechanisms you specify per type on the feature level which features need not to be called - these features can safely be redefined covariantly - or which features have to be available - these features have to be typesafe for all possible values of a caller object.&lt;br /&gt;
&lt;br /&gt;
Reference: [http://dev.eiffel.com/Forget_/_Keep_Mechanism Article on dev.eiffel.com]&lt;br /&gt;
&lt;br /&gt;
=== Dynamic typeset algorithm ===&lt;br /&gt;
&lt;br /&gt;
The dynamic typeset algorithm does not change any semantics of the types or the conformance as it is in Eiffel already, it only does an abstract execution of the system to limit the possibilities per feature call which have to be checked if they are safe.&lt;br /&gt;
== Overview of solutions for non-generics ==&lt;br /&gt;
&lt;br /&gt;
These proposal only address the case for non-generics. For generic catcalls another solution (e.g. wildcard generics) can be used.&lt;br /&gt;
&lt;br /&gt;
=== [[Restrict types]] ===&lt;br /&gt;
&lt;br /&gt;
With restrict types you specify per type on the type level which descendant types that are allowed. Only these types can be assigned to such a variable, and all feature calls on these variables have to be valid for all possible types in this list.&lt;br /&gt;
&lt;br /&gt;
Reference: [http://se.inf.ethz.ch/cgi-bin/ecma/index.cgi?IssueFLEX_CATCALL IssueFLEX_CATCALL on ECMA wiki]&amp;lt;br/&amp;gt;&lt;br /&gt;
Reference: Discussion in ECMA mailinglist named ''Catcall removal: another proposal'', [[Restrict types mail|available in parts]]&lt;br /&gt;
&lt;br /&gt;
=== [[DOG proposal]] ===&lt;br /&gt;
&lt;br /&gt;
With the DOG proposal, features which can be covariantly redefined have to be marked as such. These features can only be called on specially marked entities which have a restricted conformance, thus preventing assignments from descendants with potential covariantly redefined arguments.&lt;br /&gt;
&lt;br /&gt;
Reference: [http://se.inf.ethz.ch/cgi-bin/ecma/index.cgi?IssueDOG IssueDOG on ECMA wiki]&lt;br /&gt;
&lt;br /&gt;
== Overview of solutions for generics ==&lt;br /&gt;
&lt;br /&gt;
These proposal only address the case for generics. For non-generic catcalls another solution (e.g. novariance) can be used.&lt;br /&gt;
&lt;br /&gt;
=== [[Usage-site variance]] ===&lt;br /&gt;
&lt;br /&gt;
This solution lets the programmer decide on the instantiation of a generic if the generic parameter should be covariant, contravariant or invariant. Depending on the variance, the applicable features of the type and the conformance rules to other generic types are changed.&lt;br /&gt;
&lt;br /&gt;
Reference: [http://pag.csail.mit.edu/reading-group/variance-ECOOP02.pdf On variance-based subtyping for parametric types]&lt;br /&gt;
&lt;br /&gt;
=== [[Definition-site variance]] ===&lt;br /&gt;
&lt;br /&gt;
This solution lets the programmer decide in the definition of a generic class if the generic parameter should be covariant, contravariant or invariant. Depending on the variance, the formal generic can only appear at the argument, only appear as a result type or appear in both places. Also the conformance is adapted depending on the variance of the generic parameter.&lt;br /&gt;
&lt;br /&gt;
This is the solution which is implemented in the CLR, although not supported by generics in C# which are novariant.&lt;br /&gt;
&lt;br /&gt;
Reference: [http://blogs.msdn.com/rmbyers/archive/2006/06/01/613690.aspx Article about generics in CLR]&lt;br /&gt;
&lt;br /&gt;
Note: There is also a [http://fams.de/text/type-safe-eiffel.html proposal by Bernd Schoeller] about ''variant and invariant'' generics which is a subset of this one and thus not explained in detail.&lt;br /&gt;
&lt;br /&gt;
=== Wildcard generics ===&lt;br /&gt;
&lt;br /&gt;
This mechanism extends the [[usage-site variance]] by adding a wildcard to the generic derivation. This wildcard denotes unspecified types and limits the use of features with generic parameters or result types over conformance to the wildcard types.&lt;br /&gt;
&lt;br /&gt;
Since the mechanism is almost identical to the usage-site variance, it will not be looked at in more detail. Please refer to the reference article for more information.&lt;br /&gt;
&lt;br /&gt;
Reference: [http://www.jot.fm/issues/issue_2004_12/article5 Adding Wildcards to the Java Programming Language]&lt;br /&gt;
&lt;br /&gt;
== Overview of dynamic solutions ==&lt;br /&gt;
&lt;br /&gt;
These proposals do not prevent catcalls at compile-time but introduce means to handle catcalls at runtime.&lt;br /&gt;
&lt;br /&gt;
=== [[Detachable types]] ===&lt;br /&gt;
&lt;br /&gt;
This solution allows covariantly redefined features only to use detachable types. Through this mechanism, an object test is necessary before an argument can be used. This forces the programmer to test arguments for validity.&lt;br /&gt;
&lt;br /&gt;
Reference: [http://se.ethz.ch/~meyer/publications/lncs/attached.pdf Article about ''attached types'' by Bertrand Meyer]&amp;lt;br/&amp;gt;&lt;br /&gt;
Reference: [http://www.ecma-international.org/publications/standards/Ecma-367.htm ECMA Eiffel standard 2nd edition of June 2006]&lt;br /&gt;
&lt;br /&gt;
=== Recast ===&lt;br /&gt;
&lt;br /&gt;
In the recast proposal, the programmer has to specify a transformation function when covariantly redefining a feature which can transform the old argument types to the new ones.&lt;br /&gt;
&lt;br /&gt;
Reference: [http://se.inf.ethz.ch/cgi-bin/ecma/index.cgi?IssueCAT IssueCAT on ECMA wiki]&amp;lt;br/&amp;gt;&lt;br /&gt;
Reference: [http://www.inf.ethz.ch/~meyer/ongoing/covariance/recast.pdf Article about recast]&lt;br /&gt;
&lt;br /&gt;
=== Exceptions ===&lt;br /&gt;
&lt;br /&gt;
Another way of handling catcalls at runtime is to raise exceptions. It can be required or not to provide a rescue clause which handles the case of the catcall.&lt;br /&gt;
&lt;br /&gt;
== Combinations ==&lt;br /&gt;
&lt;br /&gt;
It is also possible to combine different proposals:&lt;br /&gt;
&lt;br /&gt;
* Novariance for non-generic features and usage-site variance for generics .&lt;br /&gt;
* Forget / keep for non-generic features and definition-site variance for generics.&lt;br /&gt;
* DOG proposal for non-generic features and wildcard generics.&lt;br /&gt;
* ...&lt;br /&gt;
&lt;br /&gt;
== Results ==&lt;br /&gt;
&lt;br /&gt;
The following table summarizes the support of the various solutions to the criteria described above which can be used to judge a catcall solution.&lt;br /&gt;
&lt;br /&gt;
This results can be differently interpreted, so the colors may not be totally accurate. See the [[Comparison of catcall solutions#Table_explained|explanation at the end of the table]] for more information&lt;br /&gt;
&lt;br /&gt;
=== General solutions ===&lt;br /&gt;
&lt;br /&gt;
{| border=1 cellpadding=2&lt;br /&gt;
&lt;br /&gt;
|- style=&amp;quot;visibility: hidden&amp;quot;&lt;br /&gt;
| style=&amp;quot;width:25%&amp;quot; |&lt;br /&gt;
| style=&amp;quot;width:25%&amp;quot; |&lt;br /&gt;
| style=&amp;quot;width:25%&amp;quot; |&lt;br /&gt;
| style=&amp;quot;width:25%&amp;quot; |&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
&lt;br /&gt;
! Criteria&lt;br /&gt;
! [[Novariance]]&lt;br /&gt;
! [[Forget / keep]]&lt;br /&gt;
! Dynamic typeset algorithm&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
&lt;br /&gt;
! Syntax overhead&lt;br /&gt;
| {{Green|No}}&lt;br /&gt;
| {{Red|Big}}: forget/keep clauses per type&lt;br /&gt;
| {{Green|No}}&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
&lt;br /&gt;
! Covariance on non-generic types &lt;br /&gt;
| {{Red|Not allowed}}&lt;br /&gt;
| {{Green|Allowed}}&lt;br /&gt;
| {{Green|Allowed}}&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
&lt;br /&gt;
! Export status restrictions&lt;br /&gt;
| {{Red|Not allowed}}&lt;br /&gt;
| {{Green|Allowed}}&lt;br /&gt;
| {{Green|Allowed}}&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
&lt;br /&gt;
! Use of generic types&lt;br /&gt;
| {{Red|Very limited}}: Only invariant conformance&lt;br /&gt;
| {{Orange|Limited}}: Conformance restricted (''keep all'' as default)&amp;lt;br/&amp;gt;{{Orange|Limited}}: Use restricted (''forget all'' as default)&lt;br /&gt;
| {{Green|As it is now}}&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
&lt;br /&gt;
! Agents&lt;br /&gt;
| {{Orange|Limited}}&amp;lt;br/&amp;gt;{{Green|Safe}}&lt;br /&gt;
| {{Orange|Limited}}&amp;lt;br/&amp;gt;{{Green|Safe}}&lt;br /&gt;
| {{Red|As it is now}}&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
&lt;br /&gt;
! Comparator&lt;br /&gt;
| {{Red|Not supported}}&lt;br /&gt;
| {{Red|Not supported}}&lt;br /&gt;
| {{Red|Not supported}}&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
&lt;br /&gt;
! Complexity of compiler check&lt;br /&gt;
| {{Green|Small}}&lt;br /&gt;
| {{Orange|Medium}}: Check of feature call for all descendants; Conformance check on forget/keep clauses&lt;br /&gt;
| {{Red|Big}}: Iterative abstract system execution&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
&lt;br /&gt;
! Complexity of runtime&lt;br /&gt;
| {{Green|Small}}: As it is now&lt;br /&gt;
| {{Orange|Medium}}: Need to know cat features for object tests&lt;br /&gt;
| {{Green|Small}}: As it is now&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
&lt;br /&gt;
! Whole-system analysis&lt;br /&gt;
| {{Green|No}}&lt;br /&gt;
| {{Red|Yes}}: use of ''forget all'' depends on system&lt;br /&gt;
| {{Red|Yes}}&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
&lt;br /&gt;
! Dynamic class and type loading&lt;br /&gt;
| {{Green|Yes}}&lt;br /&gt;
| {{Red|No}}&lt;br /&gt;
| {{Red|No}}&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
&lt;br /&gt;
! Backward compatibility&lt;br /&gt;
| {{Red|Very limited}}&lt;br /&gt;
| {{Orange|Limited}}&lt;br /&gt;
| {{Green|Full}}&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
&lt;br /&gt;
! Support of IDE (Source changes)&lt;br /&gt;
| {{Green|Not needed}}&lt;br /&gt;
| {{Orange|Possible}}: Can propose forget/keep clauses&lt;br /&gt;
| {{Green|Not needed}}&lt;br /&gt;
&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Solutions for non-generics ===&lt;br /&gt;
&lt;br /&gt;
{| border=1 cellpadding=2&lt;br /&gt;
&lt;br /&gt;
|- style=&amp;quot;visibility: hidden&amp;quot;&lt;br /&gt;
| style=&amp;quot;width:25%&amp;quot; |&lt;br /&gt;
| style=&amp;quot;width:25%&amp;quot; |&lt;br /&gt;
| style=&amp;quot;width:25%&amp;quot; |&lt;br /&gt;
| style=&amp;quot;width:25%&amp;quot; |&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
&lt;br /&gt;
! Criteria&lt;br /&gt;
! [[Restrict types]]&lt;br /&gt;
! [[DOG proposal]]&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
&lt;br /&gt;
! Syntax overhead&lt;br /&gt;
| {{Red|Big}}: Restrict clause per type declaration&lt;br /&gt;
| {{Orange|Medium}}: ''cat'' on features and on type declarations&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
&lt;br /&gt;
! Covariance on non-generic types &lt;br /&gt;
| {{Green|Allowed}}&lt;br /&gt;
| {{Green|Allowed}}&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
&lt;br /&gt;
! Export status restrictions&lt;br /&gt;
| {{Green|Allowed}}&lt;br /&gt;
| {{Green|Allowed}}&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
&lt;br /&gt;
! Use of generic types&lt;br /&gt;
| Not addressed&lt;br /&gt;
| Not addressed&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
&lt;br /&gt;
! Agents&lt;br /&gt;
| Not addressed&lt;br /&gt;
| Not addressed&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
&lt;br /&gt;
! Comparator&lt;br /&gt;
| Not addressed&lt;br /&gt;
| Not addressed&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
&lt;br /&gt;
! Complexity of compiler check&lt;br /&gt;
| {{Orange|Medium}}: Check of feature call for all descendants; Conformance check on restrict clauses&lt;br /&gt;
| {{Green|Small}}: Check of ''cat'' on conformance&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
&lt;br /&gt;
! Complexity of runtime&lt;br /&gt;
| not yet considered&lt;br /&gt;
| {{Green|Small}}&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
&lt;br /&gt;
! Whole-system analysis&lt;br /&gt;
| {{Orange|Partial}}&lt;br /&gt;
| {{Green|No}}&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
&lt;br /&gt;
! Dynamic class and type loading&lt;br /&gt;
| {{Orange|Limited}}&lt;br /&gt;
| {{Green|Yes}}&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
&lt;br /&gt;
! Backward compatibility&lt;br /&gt;
| {{Red|Very limited}}&lt;br /&gt;
| {{Red|Very limited}}&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
&lt;br /&gt;
! Support of IDE (Source changes)&lt;br /&gt;
| {{Orange|Possible}}: Can propose restrict clauses&lt;br /&gt;
| {{Orange|Possible}}: Can propose ''cat'' marks&lt;br /&gt;
&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Solutions for generics ===&lt;br /&gt;
&lt;br /&gt;
{| border=1 cellpadding=2&lt;br /&gt;
&lt;br /&gt;
|- style=&amp;quot;visibility: hidden&amp;quot;&lt;br /&gt;
| style=&amp;quot;width:25%&amp;quot; |&lt;br /&gt;
| style=&amp;quot;width:25%&amp;quot; |&lt;br /&gt;
| style=&amp;quot;width:25%&amp;quot; |&lt;br /&gt;
| style=&amp;quot;width:25%&amp;quot; |&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
&lt;br /&gt;
! Criteria&lt;br /&gt;
! [[Usage-site variance]]&lt;br /&gt;
! [[Definition-site variance]]&lt;br /&gt;
! Wildcard generics&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
&lt;br /&gt;
! Syntax overhead&lt;br /&gt;
| {{Orange|Medium}}: Variance marks per generic type&lt;br /&gt;
| {{Green|Small}}: Variance marks per generic class definition&lt;br /&gt;
| {{Orange|Medium}}: Variance marks per generic type&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
&lt;br /&gt;
! Covariance on non-generic types &lt;br /&gt;
| Not addressed&lt;br /&gt;
| Not addressed&lt;br /&gt;
| Not addressed&lt;br /&gt;
|-&lt;br /&gt;
&lt;br /&gt;
! Export status restrictions&lt;br /&gt;
| Not addressed&lt;br /&gt;
| Not addressed&lt;br /&gt;
| Not addressed&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
&lt;br /&gt;
! Use of generic types&lt;br /&gt;
| {{Orange|Limited}}: Conformance is limited&amp;lt;br/&amp;gt;{{Green|Safe}}&lt;br /&gt;
| {{Orange|Limited}}: Conformance is limited&amp;lt;br/&amp;gt;{{Green|Safe}}&lt;br /&gt;
| {{Orange|Limited}}: Conformance is limited&amp;lt;br/&amp;gt;{{Green|Safe}}&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
&lt;br /&gt;
! Agents&lt;br /&gt;
| {{Green|Fully supported}}&amp;lt;br/&amp;gt;{{Green|Safe}}&lt;br /&gt;
| {{Orange|Fully supported}}&amp;lt;br/&amp;gt;{{Green|Safe}}: If tuples can be specified covariantly&lt;br /&gt;
| {{Green|Fully supported}}&amp;lt;br/&amp;gt;{{Green|Safe}}&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
&lt;br /&gt;
! Comparator&lt;br /&gt;
| {{Green|Supported}}&lt;br /&gt;
| {{Green|Supported}}&lt;br /&gt;
| {{Green|Supported}}&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
&lt;br /&gt;
! Complexity of compiler check&lt;br /&gt;
| {{Green|Small}}: Consider variance in conformance check&lt;br /&gt;
| {{Green|Small}}: Consider variance in conformance check&lt;br /&gt;
| {{Green|Small}}: Consider variance in conformance check&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
&lt;br /&gt;
! Complexity of runtime&lt;br /&gt;
| {{Green|Small}}: Consider variance in object test&lt;br /&gt;
| {{Green|Small}}: Consider variance in object test&lt;br /&gt;
| {{Green|Small}}: Consider variance in object test&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
&lt;br /&gt;
! Whole-system analysis&lt;br /&gt;
| {{Green|No}}&lt;br /&gt;
| {{Green|No}}&lt;br /&gt;
| {{Green|No}}&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
&lt;br /&gt;
! Dynamic class and type loading&lt;br /&gt;
| {{Green|Yes}}&lt;br /&gt;
| {{Green|Yes}}&lt;br /&gt;
| {{Green|Yes}}&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
&lt;br /&gt;
! Backward compatibility&lt;br /&gt;
| {{Orange|Limited}}: Use of generics changed due to conformance&lt;br /&gt;
| {{Red|Very limited}}: Libraries need redesign&lt;br /&gt;
| {{Orange|Limited}}: Use of generics changed due to conformance&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
&lt;br /&gt;
! Support of IDE (Source changes)&lt;br /&gt;
| {{Orange|Possible}}: Can propose variance marks&lt;br /&gt;
| {{Red|Not possible}}: Libraries need redesign&lt;br /&gt;
| {{Orange|Possible}}: Can propose variance marks/wildcards&lt;br /&gt;
&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Dynamic solutions ===&lt;br /&gt;
&lt;br /&gt;
{| border=1 cellpadding=2&lt;br /&gt;
&lt;br /&gt;
|- style=&amp;quot;visibility: hidden&amp;quot;&lt;br /&gt;
| style=&amp;quot;width:25%&amp;quot; |&lt;br /&gt;
| style=&amp;quot;width:25%&amp;quot; |&lt;br /&gt;
| style=&amp;quot;width:25%&amp;quot; |&lt;br /&gt;
| style=&amp;quot;width:25%&amp;quot; |&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
&lt;br /&gt;
! Criteria&lt;br /&gt;
! [[Detachable types]]&lt;br /&gt;
! Recast&lt;br /&gt;
! Exceptions&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
&lt;br /&gt;
! Syntax overhead&lt;br /&gt;
| {{Green|Small}}: Detachment marks&lt;br /&gt;
| {{Red|Big}}: Recast clauses, recast features&lt;br /&gt;
| {{Orange|Medium}}: If rescue clause mandatory&amp;lt;br/&amp;gt;{{Green|No}}: If rescue clause not needed&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
&lt;br /&gt;
! Covariance on non-generic types &lt;br /&gt;
| {{Red|Very limited}}: Only detached arguments, no expanded arguments&lt;br /&gt;
| {{Green|Allowed}}&lt;br /&gt;
| {{Green|Allowed}}&lt;br /&gt;
|-&lt;br /&gt;
&lt;br /&gt;
! Export status restrictions&lt;br /&gt;
| Not addressed&lt;br /&gt;
| Not addressed&lt;br /&gt;
| Not addressed&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
&lt;br /&gt;
! Use of generics&lt;br /&gt;
| {{Red|Very limited}}: Only detachable formal arguments&lt;br /&gt;
| {{Red|Very limited}}: Recast clause for all features with formal generics&lt;br /&gt;
| {{Green|As it is now}}&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
&lt;br /&gt;
! Agents&lt;br /&gt;
| {{Red|As it is now}} &lt;br /&gt;
| {{Red|As it is now}} &lt;br /&gt;
| {{Red|As it is now}} &lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
&lt;br /&gt;
! Comparator&lt;br /&gt;
| {{Red|Not supported}}&lt;br /&gt;
| {{Red|Not supported}}&lt;br /&gt;
| {{Red|Not supported}}&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
&lt;br /&gt;
! Complexity of compiler check&lt;br /&gt;
| {{Green|Small}}: As it is now&lt;br /&gt;
| {{Green|Small}}: As it is now&lt;br /&gt;
| {{Green|Small}}: As it is now&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
&lt;br /&gt;
! Complexity of runtime&lt;br /&gt;
| {{Green|Small}}: As it is now&lt;br /&gt;
| {{Orange|Medium}}: Check for catcalls and do recast&lt;br /&gt;
| {{Orange|Medium}}: Check for catcalls and raise exception&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
&lt;br /&gt;
! Whole-system analysis&lt;br /&gt;
| {{Green|No}}&lt;br /&gt;
| {{Green|No}}&lt;br /&gt;
| {{Green|No}}&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
&lt;br /&gt;
! Dynamic class and type loading&lt;br /&gt;
| {{Green|Yes}}&lt;br /&gt;
| {{Green|Yes}}&lt;br /&gt;
| {{Green|Yes}}&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
&lt;br /&gt;
! Backward compatibility&lt;br /&gt;
| {{Red|Very limited}}: All covariant and generic features become detached&lt;br /&gt;
| {{Red|Very limited}}: All covariant and generic features need recast clause&lt;br /&gt;
| {{Orange|Limited}}: If rescue clause is mandatory&amp;lt;br/&amp;gt;{{Green|Full}}: If rescue clause not needed&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
&lt;br /&gt;
! Support of IDE (Source changes)&lt;br /&gt;
| {{Orange|Possible}}: Can propose detachment marks&lt;br /&gt;
| {{Red|Not possible}}: Programmer must provide recast clause&lt;br /&gt;
| {{Red|Not possible}}: If rescue clause mandatory&amp;lt;br/&amp;gt;{{Green|Not needed}}: If rescue clause not needed&lt;br /&gt;
&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Table explained ===&lt;br /&gt;
&lt;br /&gt;
; Syntax overhead : {{Green|Small}} if a keyword/mark is needed per class/feature declaration; {{Orange|Medium}} if a keyword/mark is neede per type declaration; {{Red|Big}} if a clause is needed per type declaration.&lt;br /&gt;
; Use of generics : {{Green|As it is now}} if assignments are possible if generic parameters conform; {{Orange|Limited}} is some restrictions in the use or the conformance between generics exist; {{Red|Very limited}} a lot of restrictions in the use or the conformance between generics exist.&lt;br /&gt;
; Agents : {{Green|Fully supported}} if all safe assignments are allowed; {{Orange|Limited}} if not all safe assignments are allowed; {{Red|As it is now}} if unsafe assignments are still possible.&lt;br /&gt;
; Comparator : {{Green|Supported}} if for a comparator all safe assignments are permitted (i.e. contravariant assignments); {{Red|Not supported}} if only exact type or even (unsafe) subtypes can be assigned.&lt;br /&gt;
; Support of IDE (Source changes) : {{Green|Not needed}} if everything still works the same; {{Orange|Possible}} if the compiler can suggest clauses or marks; {{Red|Not possible}} if the programmer has to specify additional features/instructions.&lt;br /&gt;
&lt;br /&gt;
== Personal opinions ==&lt;br /&gt;
&lt;br /&gt;
[[Personal view about catcall solution]]&lt;/div&gt;</summary>
		<author><name>Juliant</name></author>	</entry>

	<entry>
		<id>https://dev.eiffel.com/index.php?title=Usage-site_variance&amp;diff=8915</id>
		<title>Usage-site variance</title>
		<link rel="alternate" type="text/html" href="https://dev.eiffel.com/index.php?title=Usage-site_variance&amp;diff=8915"/>
				<updated>2007-06-24T19:08:03Z</updated>
		
		<summary type="html">&lt;p&gt;Juliant: /* Vision 2 Example */ Thanks for the correction Peter&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Category:ECMA]]&lt;br /&gt;
[[Category:Catcall]]&lt;br /&gt;
{{Research}}&lt;br /&gt;
== Introduction ==&lt;br /&gt;
&lt;br /&gt;
The usage-site variance allows the programmer to choose which kind of variance he wants to use when a generic derivation is declared. This allows to use every generic as novariant, covariant or contravariant in contrast to the [[definition-site variance]] where it is set in the class definition.&lt;br /&gt;
&lt;br /&gt;
== Syntax ==&lt;br /&gt;
&lt;br /&gt;
The syntax used here to specify the variance of a generic is simple and may be changed to something more verbose but also clearer:&lt;br /&gt;
&lt;br /&gt;
* To specify a novariant generic, the normal syntax can be used: &amp;lt;e&amp;gt;LIST [ANY]&amp;lt;/e&amp;gt;&lt;br /&gt;
* To specify a covariant generic, we use a plus sign: &amp;lt;e&amp;gt;LIST [+ANY]&amp;lt;/e&amp;gt;&lt;br /&gt;
* To specify a contravariant generic, we use a minus sign: &amp;lt;e&amp;gt;LIST [-ANY]&amp;lt;/e&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Semantics ==&lt;br /&gt;
&lt;br /&gt;
See the [[introduction to examples]] for information about the classes used.&lt;br /&gt;
&lt;br /&gt;
=== Conformance rules ===&lt;br /&gt;
&lt;br /&gt;
Depending on the variance of the generic, the conformance rules differ:&lt;br /&gt;
&lt;br /&gt;
* A generic conforms to a novariant generic if it has the exact same generic parameter. Thus &amp;lt;e&amp;gt;LIST [T]&amp;lt;/e&amp;gt; only conforms to &amp;lt;e&amp;gt;LIST [T]&amp;lt;/e&amp;gt;. Note that &amp;lt;e&amp;gt;LINKED_LIST [T]&amp;lt;/e&amp;gt; also conforms to &amp;lt;e&amp;gt;LIST [T]&amp;lt;/e&amp;gt; as long as the generic parameter matches.&lt;br /&gt;
* A generic conforms to a covariant generic if its generic parameter conforms to the generic parameter of the covariant generic. Thus &amp;lt;e&amp;gt;LIST [U]&amp;lt;/e&amp;gt; conforms to &amp;lt;e&amp;gt;LIST [+T]&amp;lt;/e&amp;gt;.&lt;br /&gt;
* A generic conforms to a contravariant generic if its generic parameter is a parent of the generic parameter of the contravariant generic. Thus &amp;lt;e&amp;gt;LIST [T]&amp;lt;/e&amp;gt; conforms to &amp;lt;e&amp;gt;LIST [-U]&amp;lt;/e&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
For the conformance of tuples, we keep that a tuple with more elements conforms to a tuple with less elements as long as the common elements conform:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;e&amp;gt;TUPLE [T, U]&amp;lt;/e&amp;gt; conforms to &amp;lt;e&amp;gt;TUPLE [T]&amp;lt;/e&amp;gt;&lt;br /&gt;
* &amp;lt;e&amp;gt;TUPLE [U, U]&amp;lt;/e&amp;gt; conforms to &amp;lt;e&amp;gt;TUPLE [+T]&amp;lt;/e&amp;gt;&lt;br /&gt;
* &amp;lt;e&amp;gt;TUPLE [T, U]&amp;lt;/e&amp;gt; conforms to &amp;lt;e&amp;gt;TUPLE [-U]&amp;lt;/e&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Applicable features ===&lt;br /&gt;
&lt;br /&gt;
Depending on the variance of the generic, the applicable features differ:&lt;br /&gt;
&lt;br /&gt;
* On a novariant generic, all features can be used.&lt;br /&gt;
* On a covariant generic, only features which have the formal generic as a result type can be used. If the formal generic appears in an argument this feature is invalid.&lt;br /&gt;
* On a contravariant generic, only feature which have the formal generc as an argument type can be used. If the formal generic appears as a result type this feature is invalid.&lt;br /&gt;
&lt;br /&gt;
== Examples ==&lt;br /&gt;
&lt;br /&gt;
See the [[introduction to examples]] for information about the classes used.&lt;br /&gt;
&lt;br /&gt;
=== A simple generic algorithm ===&lt;br /&gt;
&lt;br /&gt;
It is easy to declare an algorithm over generics as long as only read-access is needed. Just declare input to the algorithm as covariant list.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;e&amp;gt;&lt;br /&gt;
class PERSON_PRINTER&lt;br /&gt;
feature&lt;br /&gt;
  print_all (a_list: LIST [+PERSON])&lt;br /&gt;
      -- Print all attributes of each person in the list.&lt;br /&gt;
    do&lt;br /&gt;
      from&lt;br /&gt;
        a_list.start&lt;br /&gt;
      until&lt;br /&gt;
        a_list.after&lt;br /&gt;
      do &lt;br /&gt;
          -- Reading is valid on a covariant list&lt;br /&gt;
        a_list.item.print&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
end&lt;br /&gt;
 &lt;br /&gt;
class EXAMPLE&lt;br /&gt;
feature&lt;br /&gt;
  make&lt;br /&gt;
    local&lt;br /&gt;
      l_students: LIST [STUDENT]&lt;br /&gt;
      l_professors: LIST [PROFESSOR]&lt;br /&gt;
      l_person_printer: PERSON_PRINTER&lt;br /&gt;
    do&lt;br /&gt;
      create l_person_printer&lt;br /&gt;
        -- LIST [STUDENT] conforms to LIST [+PERSON]&lt;br /&gt;
      l_person_printer.print_all (l_students)&lt;br /&gt;
        -- LIST [PROFESSPR] conforms to LIST [+PERSON]&lt;br /&gt;
      l_person_printer.print_all (l_professor)&lt;br /&gt;
    end&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/e&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Comparator ===&lt;br /&gt;
&lt;br /&gt;
In the example of sorting a list with a comparator, contravariant generics can be used. Due to the use of &amp;lt;e&amp;gt;COMPARATOR [-G]&amp;lt;/e&amp;gt; when sorting a &amp;lt;e&amp;gt;LIST [G]&amp;lt;/e&amp;gt;, we allow to use a comparator which can sort more generally than just objects of type &amp;lt;e&amp;gt;G&amp;lt;/e&amp;gt;. This allows to use a comparator for &amp;lt;e&amp;gt;ANY&amp;lt;/e&amp;gt; objects to sort a list of strings.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;e&amp;gt;&lt;br /&gt;
class SORTER [G]&lt;br /&gt;
feature&lt;br /&gt;
  sort (a_list: LIST [G]; a_comparator: COMPARATOR [-G])&lt;br /&gt;
    do&lt;br /&gt;
        -- Somewhere in the loop:&lt;br /&gt;
      a_comparator.compare (l_string_1, l_string_2)&lt;br /&gt;
    end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
class EXAMPLE&lt;br /&gt;
feature&lt;br /&gt;
  make&lt;br /&gt;
    local&lt;br /&gt;
      l_list: LIST [STRING]&lt;br /&gt;
      l_string_sorter: SORTER [STRING]&lt;br /&gt;
      l_string_comparator: COMPARATOR [STRING]&lt;br /&gt;
      l_any_comparator: COMPARATOR [ANY]&lt;br /&gt;
    do&lt;br /&gt;
        -- COMPARATOR [STRING] conforms to COMPARATOR [-STRING]&lt;br /&gt;
      l_string_sorter.sort (l_list, l_string_comparator)&lt;br /&gt;
        -- COMPARATOR [ANY] conforms to COMPARATOR [-STRING]&lt;br /&gt;
      l_string_sorter.sort (l_list, l_any_comparator)&lt;br /&gt;
    end&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/e&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Agents ===&lt;br /&gt;
&lt;br /&gt;
For agents, we will look at an example with the type &amp;lt;e&amp;gt;T&amp;lt;/e&amp;gt; and a subtype &amp;lt;e&amp;gt;U&amp;lt;/e&amp;gt;. We will see an agent declaration and then check which arguments that are allowed:&lt;br /&gt;
&lt;br /&gt;
==== Calling agents ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;e&amp;gt;&lt;br /&gt;
local&lt;br /&gt;
  an_agent: PROCEDURE [+ANY, -TUPLE [+T]]&lt;br /&gt;
    -- An agent which takes an argument of type T.&lt;br /&gt;
do&lt;br /&gt;
    -- The following calls are surely permitted (and also correct) since&lt;br /&gt;
    -- the tuple generic inside the tuple is covariant and thus allows&lt;br /&gt;
    -- the tuple of type U to be passed.&lt;br /&gt;
  an_agent.call ([T])&lt;br /&gt;
  an_agent.call ([U])&lt;br /&gt;
&lt;br /&gt;
    -- Due to the tuple conformance, the following calls are also&lt;br /&gt;
    -- permitted. Note that they are both correct.&lt;br /&gt;
  an_agent.call ([T, ...])&lt;br /&gt;
  an_agent.call ([U, ...])&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/e&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We see that this solution allows the full range of applicable arguments for calling agents.&lt;br /&gt;
&lt;br /&gt;
==== Assigning agents ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;e&amp;gt;&lt;br /&gt;
local&lt;br /&gt;
  an_agent: PROCEDURE [+ANY, -TUPLE [+T]]&lt;br /&gt;
    -- An agent which takes an argument of type T.&lt;br /&gt;
do&lt;br /&gt;
  agent_empty := agent () do end --&amp;gt; PROCEDURE [ANY, TUPLE []]&lt;br /&gt;
  agent_any := agent (a: ANY) do end --&amp;gt; PROCEDURE [ANY, TUPLE [+ANY]]&lt;br /&gt;
  agent_t := agent (t: T) do end --&amp;gt; PROCEDURE [ANY, TUPLE [+T]]&lt;br /&gt;
  agent_u := agent (u: U) do end --&amp;gt; PROCEDURE [ANY, TUPLE [+U]]&lt;br /&gt;
  agent_tt := agent (t: T; t2: T) do end --&amp;gt; PROCEDURE [ANY, TUPLE [+T, +T]]&lt;br /&gt;
&lt;br /&gt;
    -- This assignment is naturally allowed.&lt;br /&gt;
  an_agent := agent_t&lt;br /&gt;
&lt;br /&gt;
    -- This assignment is allowed since the tuple is declared contravariant&lt;br /&gt;
    -- and the empty tuple is an ancestor of TUPLE [+T]&lt;br /&gt;
  an_agent := agent_empty&lt;br /&gt;
&lt;br /&gt;
    -- This assignment is allowed and correct. The reason is that TUPLE [+ANY]&lt;br /&gt;
    -- is an ancestor of TUPLE [+T].&lt;br /&gt;
  an_agent := agent_any&lt;br /&gt;
&lt;br /&gt;
    -- The following assignments are not permitted by the solution. This is the correct&lt;br /&gt;
    -- behaviour  as you could either create a catcall by passing a T argument to the &lt;br /&gt;
    -- `agent_u' or pass the wrong number of arguments by passing a [T] tuple to the &lt;br /&gt;
    -- `agent_tt'.&lt;br /&gt;
  an_agent := agent_u&lt;br /&gt;
  an_agent := agent_tt&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/e&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We see that this solution allows all possible agents to be assigned.&lt;br /&gt;
&lt;br /&gt;
Since declaring an agent can be difficult (where did I need to put the &amp;quot;+&amp;quot; and the &amp;quot;-&amp;quot;?), an alternate [[Agent syntax|syntax for agents]] could be useful where the compiler can derive the correct type for an agent.&lt;br /&gt;
&lt;br /&gt;
==== Vision 2 Example ====&lt;br /&gt;
A field which makes heavy use of agents and benefits a lot of them is ''event driven programming''. With the current agent mechanism the programmer is sometimes forced to use a hack to circumvent the type checker in order to gain flexibility.&lt;br /&gt;
&lt;br /&gt;
The following code is taken from &amp;lt;e&amp;gt;EV_PND_MOTION_ACTION_SEQUENCE&amp;lt;/e&amp;gt;. Here we gain the flexibility that an agent which listens to the event does not have to be a feature which takes all the data provided if the event occurs. Maybe the programmer is just interested in the fact that an actual event occurred and not in the data about it.&lt;br /&gt;
&amp;lt;e&amp;gt;&lt;br /&gt;
  force_extend (action: PROCEDURE [ANY, TUPLE]) is&lt;br /&gt;
      -- Extend without type checking. Not type save! Use on your own risk!&lt;br /&gt;
    do&lt;br /&gt;
      extend (agent wrapper (?, ?, ?, action))&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
  wrapper (an_x, a_y: INTEGER; a_pick_and_dropable: EV_ABSTRACT_PICK_AND_DROPABLE;&lt;br /&gt;
        action: PROCEDURE [ANY, TUPLE])&lt;br /&gt;
        -- Use this to circumvent tuple type checking. (at your own risk!)&lt;br /&gt;
        -- Calls `action' passing all other arguments.&lt;br /&gt;
    do&lt;br /&gt;
      action.call ([an_x, a_y, a_pick_and_dropable])&lt;br /&gt;
    end&lt;br /&gt;
&amp;lt;/e&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If this solution is built into Eiffel the designer of Vision2 would do a small change in &amp;lt;e&amp;gt;ACTION_SEQUENCE&amp;lt;/e&amp;gt;. The changes makes sure that we can accept agents to features defined in descendants of &amp;lt;e&amp;gt;ANY&amp;lt;/e&amp;gt; (therefore the &amp;lt;e&amp;gt;+ANY&amp;lt;/e&amp;gt;) and that we accept agents which are not interested in all data but just (possibly) take parts of it (therefore &amp;lt;e&amp;gt;-EVENT_DATA&amp;lt;/e&amp;gt;).&lt;br /&gt;
&amp;lt;e&amp;gt;&lt;br /&gt;
class&lt;br /&gt;
  ACTION_SEQUENCE [EVENT_DATA -&amp;gt; TUPLE create default_create end]&lt;br /&gt;
inherit&lt;br /&gt;
  ARRAYED_LIST [PROCEDURE [+ANY, -EVENT_DATA]]&lt;br /&gt;
  -- old ARRAYED_LIST [PROCEDURE [ANY, EVENT_DATA]]&lt;br /&gt;
&amp;lt;/e&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The wrapper code can be removed from &amp;lt;e&amp;gt;EV_PND_MOTION_ACTION_SEQUENCE&amp;lt;/e&amp;gt; and we also change one line. This change empowers the system to accept descendants of &amp;lt;e&amp;gt;EV_ABSTRACT_PICK_AND_DROPABLE&amp;lt;/e&amp;gt; as event data. The two integers do not need be marked covariantly as they are frozen and no descendants exist for them.&lt;br /&gt;
&amp;lt;e&amp;gt;&lt;br /&gt;
class&lt;br /&gt;
  EV_PND_MOTION_ACTION_SEQUENCE&lt;br /&gt;
&lt;br /&gt;
inherit&lt;br /&gt;
    -- old EV_ACTION_SEQUENCE [TUPLE [x: INTEGER; y: INTEGER; pick_and_dropable: EV_ABSTRACT_PICK_AND_DROPABLE]]&lt;br /&gt;
  EV_ACTION_SEQUENCE [TUPLE [x: INTEGER; y: INTEGER; pick_and_dropable: +EV_ABSTRACT_PICK_AND_DROPABLE]]&lt;br /&gt;
&amp;lt;/e&amp;gt;&lt;br /&gt;
Now with this the actual signature of &amp;lt;e&amp;gt;{EV_PND_MOTION_ACTION_SEQUENCE}.extend&amp;lt;/e&amp;gt; looks like this:&lt;br /&gt;
&amp;lt;e&amp;gt;&lt;br /&gt;
  extend (v: PROCEDURE [ANY, -TUPLE [x: INTEGER_32; y: INTEGER_32; +pick_and_dropable: EV_ABSTRACT_PICK_AND_DROPABLE]]&lt;br /&gt;
&amp;lt;/e&amp;gt;&lt;br /&gt;
&lt;br /&gt;
For the sake of completeness the signature of &amp;lt;e&amp;gt;{EV_PND_MOTION_ACTION_SEQUENCE}.call&amp;lt;/e&amp;gt;. Note again that the the field `pick_and_dropable' is covariant allowing to call the event with tuples containing descendants of &amp;lt;e&amp;gt;EV_ABSTRACT_PICK_AND_DROPABLE&amp;lt;/e&amp;gt;.&lt;br /&gt;
&amp;lt;e&amp;gt;&lt;br /&gt;
  call (event_data: TUPLE [x: INTEGER_32; y: INTEGER_32; pick_and_dropable: +EV_ABSTRACT_PICK_AND_DROPABLE])&lt;br /&gt;
&amp;lt;/e&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Conclusion ==&lt;br /&gt;
&lt;br /&gt;
The usage-site variance is a mechanism which allows both expressive and type-safe generics. It can model agents and comparator types correctly.&lt;/div&gt;</summary>
		<author><name>Juliant</name></author>	</entry>

	<entry>
		<id>https://dev.eiffel.com/index.php?title=Definition-site_variance&amp;diff=8914</id>
		<title>Definition-site variance</title>
		<link rel="alternate" type="text/html" href="https://dev.eiffel.com/index.php?title=Definition-site_variance&amp;diff=8914"/>
				<updated>2007-06-24T19:05:03Z</updated>
		
		<summary type="html">&lt;p&gt;Juliant: /* Agents */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Category:ECMA]]&lt;br /&gt;
[[Category:Catcall]]&lt;br /&gt;
{{Research}}&lt;br /&gt;
== Introduction ==&lt;br /&gt;
&lt;br /&gt;
The defintion-site variance allows the programmer to choose which kind of variance he wants to use in the defintion of a generic class. Unlike the [[usage-site variance]], this fixes a specific class to the kind of variance which it supports.&lt;br /&gt;
&lt;br /&gt;
== Syntax ==&lt;br /&gt;
&lt;br /&gt;
The syntax used here to specify the variance of a generic is simple and may be changed to something more verbose but also clearer:&lt;br /&gt;
&lt;br /&gt;
* To specify a novariant generic, the normal syntax can be used: &amp;lt;e&amp;gt;class LIST [G] end&amp;lt;/e&amp;gt;&lt;br /&gt;
* To specify a covariant generic, we use a plus sign: &amp;lt;e&amp;gt;class READ_LIST [+G] end&amp;lt;/e&amp;gt;&lt;br /&gt;
* To specify a contravariant generic, we use a minus sign: &amp;lt;e&amp;gt;class WRITE_LIST [-G] end&amp;lt;/e&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Semantics ==&lt;br /&gt;
&lt;br /&gt;
See the [[introduction to examples]] for information about the classes used.&lt;br /&gt;
&lt;br /&gt;
=== Conformance rules ===&lt;br /&gt;
&lt;br /&gt;
Depending on the variance of the generic, the conformance rules differ:&lt;br /&gt;
&lt;br /&gt;
* If a generic class is declared novariant, two generics conform if their base class conforms and the generic parameters match exactly. Thus &amp;lt;e&amp;gt;LIST [T]&amp;lt;/e&amp;gt; only conforms to &amp;lt;e&amp;gt;LIST [T]&amp;lt;/e&amp;gt;.&lt;br /&gt;
* If a generic class is declared covariant, a generic conforms to another if its base class conforms and the generic parameter conforms to the other. Thus &amp;lt;e&amp;gt;READ_LIST [U]&amp;lt;/e&amp;gt; conforms to &amp;lt;e&amp;gt;READ_LIST [T]&amp;lt;/e&amp;gt;.&lt;br /&gt;
* If a generic class is declared contravariant, a generic conforms to another if its base class conforms and the generic parameter is an ancestor of the other. Thus &amp;lt;e&amp;gt;WRITE_LIST [U]&amp;lt;/e&amp;gt; conforms to &amp;lt;e&amp;gt;WRITE_LIST [T]&amp;lt;/e&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Tuples are problematic in this solution as have to declare the generic tuple parameters as invariant. For the conformance of tuples, we keep that a tuple with more elements conforms to a tuple with less elements. The common elements have to match exactly due to their invariance:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;e&amp;gt;TUPLE [T, U]&amp;lt;/e&amp;gt; conforms to &amp;lt;e&amp;gt;TUPLE [T]&amp;lt;/e&amp;gt;&lt;br /&gt;
* &amp;lt;e&amp;gt;TUPLE [U]&amp;lt;/e&amp;gt; does not conform to &amp;lt;e&amp;gt;TUPLE [T]&amp;lt;/e&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Applicable features ===&lt;br /&gt;
&lt;br /&gt;
Depending on the variance of a generic, it can only occur in certain places:&lt;br /&gt;
&lt;br /&gt;
* A novariant generic can be used as argument or result type.&lt;br /&gt;
* A covariant generic can only be used as a result type.&lt;br /&gt;
* A contravariant generic can only be used as an argument type.&lt;br /&gt;
&lt;br /&gt;
== Examples ==&lt;br /&gt;
&lt;br /&gt;
See the [[introduction to examples]] for information about the classes used.&lt;br /&gt;
&lt;br /&gt;
=== A simple generic algorithm ===&lt;br /&gt;
&lt;br /&gt;
In order to use lists as read-only lists, the library design has to be adapted. &amp;lt;e&amp;gt;LIST [G]&amp;lt;/e&amp;gt; needs to inherit from &amp;lt;e&amp;gt;READ_LIST [+G]&amp;lt;/e&amp;gt;. That way you can assign a &amp;lt;e&amp;gt;LIST [STRING]&amp;lt;/e&amp;gt; to a &amp;lt;e&amp;gt;READ_LIST [STRING]&amp;lt;/e&amp;gt; and, through transitivity of conformance, to a &amp;lt;e&amp;gt;READ_LIST [ANY]&amp;lt;/e&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;e&amp;gt;&lt;br /&gt;
class PERSON_PRINTER&lt;br /&gt;
feature&lt;br /&gt;
  print_all (a_list: READ_LIST [PERSON])&lt;br /&gt;
      -- Print all attributes of each person in the list.&lt;br /&gt;
    do&lt;br /&gt;
      from&lt;br /&gt;
        a_list.start&lt;br /&gt;
      until&lt;br /&gt;
        a_list.after&lt;br /&gt;
      do &lt;br /&gt;
          -- Reading is valid on a covariant list&lt;br /&gt;
        a_list.item.print&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
end&lt;br /&gt;
 &lt;br /&gt;
class EXAMPLE&lt;br /&gt;
feature&lt;br /&gt;
  make&lt;br /&gt;
    local&lt;br /&gt;
      l_students: LIST [STUDENT]&lt;br /&gt;
      l_professors: LIST [PROFESSOR]&lt;br /&gt;
      l_person_printer: PERSON_PRINTER&lt;br /&gt;
    do&lt;br /&gt;
      create l_person_printer&lt;br /&gt;
        -- LIST [STUDENT] conforms to READ_LIST [PERSON]&lt;br /&gt;
      l_person_printer.print_all (l_students)&lt;br /&gt;
        -- LIST [PROFESSOR] conforms to READ_LIST [PERSON]&lt;br /&gt;
      l_person_printer.print_all (l_professor)&lt;br /&gt;
    end&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/e&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Comparator ===&lt;br /&gt;
&lt;br /&gt;
For the comparator example to work, the comparator class has to be declared as contravariant generic: &amp;lt;e&amp;gt;class COMPARATOR [-G]&amp;lt;/e&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;e&amp;gt;&lt;br /&gt;
class SORTER [G]&lt;br /&gt;
feature&lt;br /&gt;
  sort (a_list: LIST [G]; a_comparator: COMPARATOR [G])&lt;br /&gt;
    do&lt;br /&gt;
        -- Somewhere in the loop:&lt;br /&gt;
      a_comparator.compare (l_string_1, l_string_2)&lt;br /&gt;
    end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
class EXAMPLE&lt;br /&gt;
feature&lt;br /&gt;
  make&lt;br /&gt;
    local&lt;br /&gt;
      l_list: LIST [STRING]&lt;br /&gt;
      l_string_sorter: SORTER [STRING]&lt;br /&gt;
      l_string_comparator: COMPARATOR [STRING]&lt;br /&gt;
      l_any_comparator: COMPARATOR [ANY]&lt;br /&gt;
    do&lt;br /&gt;
        -- COMPARATOR [STRING] conforms to COMPARATOR [STRING]&lt;br /&gt;
      l_string_sorter.sort (l_list, l_string_comparator)&lt;br /&gt;
        -- COMPARATOR [ANY] conforms to COMPARATOR [STRING]&lt;br /&gt;
      l_string_sorter.sort (l_list, l_any_comparator)&lt;br /&gt;
    end&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/e&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Agents ===&lt;br /&gt;
&lt;br /&gt;
Again, to use definition-site variance you have to adapt the library design. The procedure class has to be defined as follows:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;e&amp;gt;&lt;br /&gt;
class PROCEDURE [+BASE_TYPE, -OPEN_ARGS -&amp;gt; TUPLE]&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/e&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Calling agents ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;e&amp;gt;&lt;br /&gt;
local&lt;br /&gt;
  an_agent: PROCEDURE [ANY, TUPLE [T]]&lt;br /&gt;
    -- An agent which takes an argument of type T.&lt;br /&gt;
do&lt;br /&gt;
    -- The following calls are surely permitted as the generic &lt;br /&gt;
    -- parameter in the tuple is novariant since it is not specified&lt;br /&gt;
    -- further in the procedure class.&lt;br /&gt;
  an_agent.call ([T])&lt;br /&gt;
  an_agent.call ([T, ...])&lt;br /&gt;
&lt;br /&gt;
    -- Because the tuple is novariant, the following calls are&lt;br /&gt;
    -- illegal although they would be safe.&lt;br /&gt;
  an_agent.call ([U])&lt;br /&gt;
  an_agent.call ([U, ...])&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/e&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In contrast to [[usage-site variance#Agents|usage-site variance]] you cannot express that the generic parameters of the tuple are covariant. Because of that, the call with a subtype of the actual parameter is not permitted by the type system.&lt;br /&gt;
&lt;br /&gt;
==== Assigning agents ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;e&amp;gt;&lt;br /&gt;
local&lt;br /&gt;
  an_agent: PROCEDURE [ANY, TUPLE [T]]&lt;br /&gt;
    -- An agent which takes an argument of type T.&lt;br /&gt;
do&lt;br /&gt;
  agent_empty := agent () do end --&amp;gt; PROCEDURE [ANY, TUPLE []]&lt;br /&gt;
  agent_any := agent (a: ANY) do end --&amp;gt; PROCEDURE [ANY, TUPLE [ANY]]&lt;br /&gt;
  agent_t := agent (t: T) do end --&amp;gt; PROCEDURE [ANY, TUPLE [T]]&lt;br /&gt;
  agent_u := agent (u: U) do end --&amp;gt; PROCEDURE [ANY, TUPLE [U]]&lt;br /&gt;
  agent_tt := agent (t: T; t2: T) do end --&amp;gt; PROCEDURE [ANY, TUPLE [T, T]]&lt;br /&gt;
&lt;br /&gt;
    -- This assignment is naturally allowed.&lt;br /&gt;
  an_agent := agent_t&lt;br /&gt;
&lt;br /&gt;
    -- This assignment is allowed since the tuple is declared contravariant&lt;br /&gt;
    -- and the empty tuple is an ancestor of TUPLE [T]&lt;br /&gt;
  an_agent := agent_empty&lt;br /&gt;
&lt;br /&gt;
    -- This assignment is not allowed although it would be correct. The reason &lt;br /&gt;
    -- is that TUPLE [ANY] is not an ancestor of TUPEL [T].&lt;br /&gt;
  an_agent := agent_any&lt;br /&gt;
&lt;br /&gt;
    -- The following assignments are not permitted by the solution. This is the correct&lt;br /&gt;
    -- behaviour  as you could either create a catcall by passing a T argument to the &lt;br /&gt;
    -- `agent_u' or pass the wrong number of arguments by passing a [T] tuple to the &lt;br /&gt;
    -- `agent_tt'.&lt;br /&gt;
  an_agent := agent_u&lt;br /&gt;
  an_agent := agent_tt&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/e&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Again, the fact that the generic tuple parameters are novariant causes that a safe assignment is prohibited.&lt;br /&gt;
&lt;br /&gt;
==== Covariant tuples ====&lt;br /&gt;
&lt;br /&gt;
The agent mechanism in definition-site variance is not as expressive as it can be because the generic &amp;lt;e&amp;gt;TUPLE&amp;lt;/e&amp;gt; parameters cannot be specified as covariant in the class definition of &amp;lt;e&amp;gt;PROCEDURE&amp;lt;/e&amp;gt;. Since &amp;lt;e&amp;gt;TUPLE&amp;lt;/e&amp;gt; is a special case, you could think about allowing a special notation to denote totally covariant tuples. If this would be available, the mechanism would allow all possible assignments and calls for the agents.&lt;br /&gt;
&lt;br /&gt;
A possible syntax to designate that the generic tuple arguments will be contravariant would be:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;e&amp;gt;&lt;br /&gt;
class PROCEDURE [+BASE_TYPE, -OPEN_ARGS -&amp;gt; TUPLE[+]]&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/e&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Conclusion ==&lt;br /&gt;
&lt;br /&gt;
This solution requires that the libraries are designed in a way which separates reading and writing to generic datastructes. It allows full use of comparator objects but does not fully support agents.&lt;br /&gt;
&lt;br /&gt;
On the plus side, the client of a library does not need to put variance markers as in the [[usage-site variance]] proposal which makes the use of the solution easier for the normal programmer.&lt;/div&gt;</summary>
		<author><name>Juliant</name></author>	</entry>

	<entry>
		<id>https://dev.eiffel.com/index.php?title=Catcall_checkpoints&amp;diff=8912</id>
		<title>Catcall checkpoints</title>
		<link rel="alternate" type="text/html" href="https://dev.eiffel.com/index.php?title=Catcall_checkpoints&amp;diff=8912"/>
				<updated>2007-06-24T18:54:05Z</updated>
		
		<summary type="html">&lt;p&gt;Juliant: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Category:Catcall]]&lt;br /&gt;
These examples should be considered for all catcall solutions:&lt;br /&gt;
&lt;br /&gt;
== Faces of covariance ==&lt;br /&gt;
&lt;br /&gt;
The following example shows the difference between generic covariance and non-generic covariance. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;e&amp;gt;&lt;br /&gt;
class A [G]&lt;br /&gt;
feature&lt;br /&gt;
  f (t: T) do end&lt;br /&gt;
  put (g: G) do end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
class B [G]&lt;br /&gt;
inherit A [G] redefine f end&lt;br /&gt;
feature&lt;br /&gt;
  f (u: U) do end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
local&lt;br /&gt;
  a_any: A [ANY]&lt;br /&gt;
  a_string: A [STRING]&lt;br /&gt;
  b_any: B [ANY]&lt;br /&gt;
  b_string: B [STRING]&lt;br /&gt;
  t: T&lt;br /&gt;
do&lt;br /&gt;
  a_any := a_string&lt;br /&gt;
  a_any.put (5) -- catcall for generic feature&lt;br /&gt;
  a_any.f (t) -- no catcall&lt;br /&gt;
&lt;br /&gt;
  a_any := b_any&lt;br /&gt;
  a_any.put (5) -- no catcall&lt;br /&gt;
  a_any.f (t) -- catcall for non-generic feature&lt;br /&gt;
&lt;br /&gt;
  a_any := b_string&lt;br /&gt;
  a_any.put (5) -- catcall for generic feature&lt;br /&gt;
  a_any.f (t) -- catcall for non-generic feature&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/e&amp;gt;&lt;br /&gt;
&lt;br /&gt;
A safe and expressive solution should have a way to allow all valid cases and prohibit the invalid ones. This needs a way to address the generic and non-generic features indiviually.&lt;br /&gt;
&lt;br /&gt;
== Contravariance ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;e&amp;gt;&lt;br /&gt;
class SORTER [G]&lt;br /&gt;
feature&lt;br /&gt;
  sort (a_list: LIST [G]; a_comparator: COMPARATOR [G])&lt;br /&gt;
    do&lt;br /&gt;
        -- Somewhere in the loop:&lt;br /&gt;
      a_comparator.compare (l_string_1, l_string_2)&lt;br /&gt;
    end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
class EXAMPLE&lt;br /&gt;
feature&lt;br /&gt;
  make&lt;br /&gt;
    local&lt;br /&gt;
      l_list: LIST [STRING]&lt;br /&gt;
      l_string_sorter: SORTER [STRING]&lt;br /&gt;
      l_any_comparator: COMPARATOR [ANY]&lt;br /&gt;
    do&lt;br /&gt;
        -- Should be allowed to sort the string list with an&lt;br /&gt;
        -- ANY comparator&lt;br /&gt;
      l_string_sorter.sort (l_list, l_any_comparator)&lt;br /&gt;
    end&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/e&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Solutions which pass this test are likely to be expressive for agents as well.&lt;br /&gt;
&lt;br /&gt;
== Agents ==&lt;br /&gt;
&lt;br /&gt;
For agents, we will look at an example with the type &amp;lt;e&amp;gt;T&amp;lt;/e&amp;gt; and a subtype &amp;lt;e&amp;gt;U&amp;lt;/e&amp;gt;. We will see an agent declaration and then check which arguments that are allowed:&lt;br /&gt;
&lt;br /&gt;
=== Calling agents ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;e&amp;gt;&lt;br /&gt;
local&lt;br /&gt;
  an_agent: PROCEDURE [ANY, TUPLE [T]]&lt;br /&gt;
    -- An agent which takes an argument of type T.&lt;br /&gt;
do&lt;br /&gt;
    -- The following calls are currently valid and should remain valid.&lt;br /&gt;
  an_agent.call ([T])&lt;br /&gt;
  an_agent.call ([U])&lt;br /&gt;
&lt;br /&gt;
  an_agent.call ([T, ...])&lt;br /&gt;
  an_agent.call ([U, ...])&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/e&amp;gt;&lt;br /&gt;
These basic cases mostly rely on the tuple conformance rules to work properly.&lt;br /&gt;
&lt;br /&gt;
=== Assigning agents ===&lt;br /&gt;
To allow anything that is safe is more tricky. It requires the ability to model contravariance.&lt;br /&gt;
&amp;lt;e&amp;gt;&lt;br /&gt;
local&lt;br /&gt;
  an_agent: PROCEDURE [ANY, TUPLE [T]]&lt;br /&gt;
    -- An agent which takes an argument of type T.&lt;br /&gt;
do&lt;br /&gt;
  agent_empty := agent () do end --&amp;gt; PROCEDURE [ANY, TUPLE []]&lt;br /&gt;
  agent_any := agent (a: ANY) do end --&amp;gt; PROCEDURE [ANY, TUPLE [ANY]]&lt;br /&gt;
  agent_t := agent (t: T) do end --&amp;gt; PROCEDURE [ANY, TUPLE [T]]&lt;br /&gt;
  agent_u := agent (u: U) do end --&amp;gt; PROCEDURE [ANY, TUPLE [U]]&lt;br /&gt;
  agent_tt := agent (t: T; t2: T) do end --&amp;gt; PROCEDURE [ANY, TUPLE [T, T]]&lt;br /&gt;
&lt;br /&gt;
    -- This assignment is naturally allowed as they are the same type.&lt;br /&gt;
  an_agent := agent_t&lt;br /&gt;
&lt;br /&gt;
    -- The following assignments are save but prohibited by the current implementation.&lt;br /&gt;
    -- If they were allowed it would benefit event driven programming in Eiffel a lot.&lt;br /&gt;
    -- As agents currently are modeled over the generic mechanism any solution which&lt;br /&gt;
    -- solves the &amp;quot;comparator problem&amp;quot; is likely to pass here too.&lt;br /&gt;
  an_agent := agent_empty&lt;br /&gt;
  an_agent := agent_any&lt;br /&gt;
&lt;br /&gt;
    -- The following assignments are currently permitted. This is not the correct&lt;br /&gt;
    -- behavior  as you could either create a catcall by passing a T argument to the &lt;br /&gt;
    -- `agent_u' or pass the wrong number of arguments by passing a [T] tuple to the &lt;br /&gt;
    -- `agent_tt'.&lt;br /&gt;
  an_agent := agent_u&lt;br /&gt;
  an_agent := agent_tt&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/e&amp;gt;&lt;/div&gt;</summary>
		<author><name>Juliant</name></author>	</entry>

	<entry>
		<id>https://dev.eiffel.com/index.php?title=Catcall_checkpoints&amp;diff=8911</id>
		<title>Catcall checkpoints</title>
		<link rel="alternate" type="text/html" href="https://dev.eiffel.com/index.php?title=Catcall_checkpoints&amp;diff=8911"/>
				<updated>2007-06-24T18:52:35Z</updated>
		
		<summary type="html">&lt;p&gt;Juliant: /* faces of covariance */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Category:Catcall]]&lt;br /&gt;
These examples should be considered for all catcall solutions:&lt;br /&gt;
&lt;br /&gt;
== faces of covariance ==&lt;br /&gt;
&lt;br /&gt;
The following example shows the difference between generic covariance and non-generic covariance. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;e&amp;gt;&lt;br /&gt;
class A [G]&lt;br /&gt;
feature&lt;br /&gt;
  f (t: T) do end&lt;br /&gt;
  put (g: G) do end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
class B [G]&lt;br /&gt;
inherit A [G] redefine f end&lt;br /&gt;
feature&lt;br /&gt;
  f (u: U) do end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
local&lt;br /&gt;
  a_any: A [ANY]&lt;br /&gt;
  a_string: A [STRING]&lt;br /&gt;
  b_any: B [ANY]&lt;br /&gt;
  b_string: B [STRING]&lt;br /&gt;
  t: T&lt;br /&gt;
do&lt;br /&gt;
  a_any := a_string&lt;br /&gt;
  a_any.put (5) -- catcall for generic feature&lt;br /&gt;
  a_any.f (t) -- no catcall&lt;br /&gt;
&lt;br /&gt;
  a_any := b_any&lt;br /&gt;
  a_any.put (5) -- no catcall&lt;br /&gt;
  a_any.f (t) -- catcall for non-generic feature&lt;br /&gt;
&lt;br /&gt;
  a_any := b_string&lt;br /&gt;
  a_any.put (5) -- catcall for generic feature&lt;br /&gt;
  a_any.f (t) -- catcall for non-generic feature&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/e&amp;gt;&lt;br /&gt;
&lt;br /&gt;
A safe and expressive solution should have a way to allow all valid cases and prohibit the invalid ones. This needs a way to address the generic and non-generic features indiviually.&lt;br /&gt;
&lt;br /&gt;
== contravariance ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;e&amp;gt;&lt;br /&gt;
class SORTER [G]&lt;br /&gt;
feature&lt;br /&gt;
  sort (a_list: LIST [G]; a_comparator: COMPARATOR [G])&lt;br /&gt;
    do&lt;br /&gt;
        -- Somewhere in the loop:&lt;br /&gt;
      a_comparator.compare (l_string_1, l_string_2)&lt;br /&gt;
    end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
class EXAMPLE&lt;br /&gt;
feature&lt;br /&gt;
  make&lt;br /&gt;
    local&lt;br /&gt;
      l_list: LIST [STRING]&lt;br /&gt;
      l_string_sorter: SORTER [STRING]&lt;br /&gt;
      l_any_comparator: COMPARATOR [ANY]&lt;br /&gt;
    do&lt;br /&gt;
        -- Should be allowed to sort the string list with an&lt;br /&gt;
        -- ANY comparator&lt;br /&gt;
      l_string_sorter.sort (l_list, l_any_comparator)&lt;br /&gt;
    end&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/e&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Solutions which pass this test are likely to be expressive for agents as well.&lt;br /&gt;
&lt;br /&gt;
== Agents ==&lt;br /&gt;
&lt;br /&gt;
For agents, we will look at an example with the type &amp;lt;e&amp;gt;T&amp;lt;/e&amp;gt; and a subtype &amp;lt;e&amp;gt;U&amp;lt;/e&amp;gt;. We will see an agent declaration and then check which arguments that are allowed:&lt;br /&gt;
&lt;br /&gt;
=== Calling agents ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;e&amp;gt;&lt;br /&gt;
local&lt;br /&gt;
  an_agent: PROCEDURE [ANY, TUPLE [T]]&lt;br /&gt;
    -- An agent which takes an argument of type T.&lt;br /&gt;
do&lt;br /&gt;
    -- The following calls are currently valid and should remain valid.&lt;br /&gt;
  an_agent.call ([T])&lt;br /&gt;
  an_agent.call ([U])&lt;br /&gt;
&lt;br /&gt;
  an_agent.call ([T, ...])&lt;br /&gt;
  an_agent.call ([U, ...])&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/e&amp;gt;&lt;br /&gt;
These basic cases mostly rely on the tuple conformance rules to work properly.&lt;br /&gt;
&lt;br /&gt;
=== Assigning agents ===&lt;br /&gt;
To allow anything that is safe is more tricky. It requires the ability to model contravariance.&lt;br /&gt;
&amp;lt;e&amp;gt;&lt;br /&gt;
local&lt;br /&gt;
  an_agent: PROCEDURE [ANY, TUPLE [T]]&lt;br /&gt;
    -- An agent which takes an argument of type T.&lt;br /&gt;
do&lt;br /&gt;
  agent_empty := agent () do end --&amp;gt; PROCEDURE [ANY, TUPLE []]&lt;br /&gt;
  agent_any := agent (a: ANY) do end --&amp;gt; PROCEDURE [ANY, TUPLE [ANY]]&lt;br /&gt;
  agent_t := agent (t: T) do end --&amp;gt; PROCEDURE [ANY, TUPLE [T]]&lt;br /&gt;
  agent_u := agent (u: U) do end --&amp;gt; PROCEDURE [ANY, TUPLE [U]]&lt;br /&gt;
  agent_tt := agent (t: T; t2: T) do end --&amp;gt; PROCEDURE [ANY, TUPLE [T, T]]&lt;br /&gt;
&lt;br /&gt;
    -- This assignment is naturally allowed as they are the same type.&lt;br /&gt;
  an_agent := agent_t&lt;br /&gt;
&lt;br /&gt;
    -- The following assignments are save but prohibited by the current implementation.&lt;br /&gt;
    -- If they were allowed it would benefit event driven programming in Eiffel a lot.&lt;br /&gt;
    -- As agents currently are modeled over the generic mechanism any solution which&lt;br /&gt;
    -- solves the &amp;quot;comparator problem&amp;quot; is likely to pass here too.&lt;br /&gt;
  an_agent := agent_empty&lt;br /&gt;
  an_agent := agent_any&lt;br /&gt;
&lt;br /&gt;
    -- The following assignments are currently permitted. This is not the correct&lt;br /&gt;
    -- behavior  as you could either create a catcall by passing a T argument to the &lt;br /&gt;
    -- `agent_u' or pass the wrong number of arguments by passing a [T] tuple to the &lt;br /&gt;
    -- `agent_tt'.&lt;br /&gt;
  an_agent := agent_u&lt;br /&gt;
  an_agent := agent_tt&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/e&amp;gt;&lt;/div&gt;</summary>
		<author><name>Juliant</name></author>	</entry>

	<entry>
		<id>https://dev.eiffel.com/index.php?title=Talk:Usage-site_variance&amp;diff=8910</id>
		<title>Talk:Usage-site variance</title>
		<link rel="alternate" type="text/html" href="https://dev.eiffel.com/index.php?title=Talk:Usage-site_variance&amp;diff=8910"/>
				<updated>2007-06-24T18:48:56Z</updated>
		
		<summary type="html">&lt;p&gt;Juliant: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;--[[User:Peter gummer|Peter gummer]] 20:11, 24 June 2007 (CEST) I think that pages such as this should be clearly marked as research. They could be misleading to someone new to Eiffel, who might stumble upon them and think that they describe the existing Eiffel compiler.&lt;br /&gt;
&lt;br /&gt;
--[[User:Juliant|Juliant]] 20:48, 24 June 2007 (CEST) We added the ''Research'' template to make it clear.&lt;/div&gt;</summary>
		<author><name>Juliant</name></author>	</entry>

	<entry>
		<id>https://dev.eiffel.com/index.php?title=Forget_/_keep&amp;diff=8909</id>
		<title>Forget / keep</title>
		<link rel="alternate" type="text/html" href="https://dev.eiffel.com/index.php?title=Forget_/_keep&amp;diff=8909"/>
				<updated>2007-06-24T18:45:44Z</updated>
		
		<summary type="html">&lt;p&gt;Juliant: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Category:ECMA]]&lt;br /&gt;
[[Category:Catcall]]&lt;br /&gt;
{{Research}}&lt;br /&gt;
== Introduction ==&lt;br /&gt;
&lt;br /&gt;
The forget / keep mechanism enhances the type system. It allows to change types on the feature level by ''forgetting'' specific features (especially features which are covariantly redefined) so that these features can't be called anymore. It also allows to specifically ''keep'' certain features so that they are surely available which in turn changes the conformance rules to only allow types which have this feature with the exact same signature.&lt;br /&gt;
&lt;br /&gt;
== Syntax ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;e&amp;gt;&lt;br /&gt;
-- forget types&lt;br /&gt;
&lt;br /&gt;
  -- A type which forgets all covariantly redefined features, thus all &lt;br /&gt;
  -- subtypes conform to this type.&lt;br /&gt;
a: ANIMAL forget all end&lt;br /&gt;
&lt;br /&gt;
  -- A type which only forgets the features `eat' and `sleep' but not other&lt;br /&gt;
  -- covarianlty redefined features or features whose export status is&lt;br /&gt;
  -- restricted. All subtypes which only redefine or restrict export status &lt;br /&gt;
  -- of `eat' or `sleep' will conform to this type.&lt;br /&gt;
a: ANIMAL forget eat, sleep end&lt;br /&gt;
&lt;br /&gt;
-- keep types&lt;br /&gt;
&lt;br /&gt;
  -- A type which keeps all features and looses conformance from subtypes which&lt;br /&gt;
  -- covariantly redefine features or restrict export status.&lt;br /&gt;
b: ANIMAL keep all end&lt;br /&gt;
 &lt;br /&gt;
  -- A type where all subtypes conform except those who covariantly redefine&lt;br /&gt;
  -- feature `eat'.&lt;br /&gt;
b: ANIMAL keep eat end&lt;br /&gt;
&amp;lt;/e&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Semantics ==&lt;br /&gt;
&lt;br /&gt;
The meaning of a ''forget'' clause is that the actual type which is used does not have the features listed in the forget clause. &amp;lt;e&amp;gt;forget all&amp;lt;/e&amp;gt; is a bit misleading as it does not forget all features, but only features which are covariantly redefined or have the export status changed to be more restrictive later in the inheritance hierarchy. A better naming would be something along the lines of &amp;lt;e&amp;gt;forget covariance&amp;lt;/e&amp;gt; but this does not address the export status change.&lt;br /&gt;
&lt;br /&gt;
The meaning of a ''keep'' clause is the reverse. If a feature is listed in a ''keep'' clause it can be called on that type with the arguments listed in that type. This means in turn that all subclasses which change the signature of those features covariantly don't conform anymore as a call would not be safe anymore.&lt;br /&gt;
&lt;br /&gt;
=== Default behavior ===&lt;br /&gt;
&lt;br /&gt;
The mechanism has two possible default behaviors. If a type is declared without specifying which features to keep or to forget, it can either mean a type which keeps all features or a type which forgets all features. The default behavior has a big impact on the language:&lt;br /&gt;
* In the ''keep all'' case, all subclasses which have a covariantly redefined feature don't conform to the parent type anymore as it ''keeps'' this feature.&lt;br /&gt;
* In the ''forget all'' case, all subclasses conform to the parent per default, but all features which are covariantly redefined (even much later in the inheritance hierarchy) are not callable since they are ''forgotten''.&lt;br /&gt;
&lt;br /&gt;
=== Conformance rules ===&lt;br /&gt;
&lt;br /&gt;
Conformance is best explained on the feature level. A type &amp;lt;e&amp;gt;SUB&amp;lt;/e&amp;gt; conforms to a type &amp;lt;e&amp;gt;PARENT&amp;lt;/e&amp;gt; if all features which are available in &amp;lt;e&amp;gt;PARENT&amp;lt;/e&amp;gt; are also available in &amp;lt;e&amp;gt;SUB&amp;lt;/e&amp;gt;. You have to keep in mind that the type &amp;lt;e&amp;gt;PARENT&amp;lt;/e&amp;gt; can forget certain features. Thus &amp;lt;e&amp;gt;SUB&amp;lt;/e&amp;gt; only conforms to the type &amp;lt;e&amp;gt;PARENT forget x&amp;lt;/e&amp;gt; if SUB also has a &amp;lt;e&amp;gt;forget x&amp;lt;/e&amp;gt; clause. For the keep clause it is a little bit different: A type &amp;lt;e&amp;gt;SUB&amp;lt;/e&amp;gt; only conforms to the type &amp;lt;e&amp;gt;PARENT keep x&amp;lt;/e&amp;gt; if &amp;lt;e&amp;gt;SUB&amp;lt;/e&amp;gt; does not restrict the export status of &amp;lt;e&amp;gt;x&amp;lt;/e&amp;gt; or changes the arguments covariantly, thus it has the same interface regarding feature &amp;lt;e&amp;gt;x&amp;lt;/e&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== Examples ==&lt;br /&gt;
&lt;br /&gt;
See the [[introduction to examples]] for information about the classes used.&lt;br /&gt;
&lt;br /&gt;
=== Cats and Dogs ===&lt;br /&gt;
&lt;br /&gt;
The examples are taken from the [http://dev.eiffel.com/Forget_/_Keep_Mechanism#Covariant_feature_redefinition reference article]&lt;br /&gt;
&lt;br /&gt;
==== forget mechanism ====&lt;br /&gt;
&lt;br /&gt;
The example regarding covariance on the feature level with the forget mechanism looks as follows:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;e&amp;gt;&lt;br /&gt;
local&lt;br /&gt;
  a: ANIMAL -- means ANIMAL keep all&lt;br /&gt;
  c: CAT&lt;br /&gt;
do&lt;br /&gt;
    -- illegal assignment, ANIMAL and CAT don't conform&lt;br /&gt;
    -- since CAT does not have the same signature for `eat'&lt;br /&gt;
  a := c&lt;br /&gt;
  a.eat (food)&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/e&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;e&amp;gt;&lt;br /&gt;
local&lt;br /&gt;
  a: ANIMAL forget all end&lt;br /&gt;
  c: CAT&lt;br /&gt;
do&lt;br /&gt;
    -- legal, CAT conforms to ANIMAL forget all&lt;br /&gt;
  a := c&lt;br /&gt;
&lt;br /&gt;
    -- illegal, ANIMAL forget all doesn't have a feature eat&lt;br /&gt;
  a.eat (food)&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/e&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== keep mechanism ====&lt;br /&gt;
&lt;br /&gt;
The example regarding covariance on the feature level with the keep mechanism looks as follows:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;e&amp;gt;&lt;br /&gt;
local&lt;br /&gt;
  a: ANIMAL -- means ANIMAL forget all&lt;br /&gt;
  c: CAT&lt;br /&gt;
do&lt;br /&gt;
  a := c&lt;br /&gt;
    -- illegal call since the type ANIMAL does not have a feature `eat' anymore&lt;br /&gt;
  a.eat (food)&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/e&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;e&amp;gt;&lt;br /&gt;
local&lt;br /&gt;
  a: ANIMAL keep all end&lt;br /&gt;
  c: CAT&lt;br /&gt;
do&lt;br /&gt;
    -- illegal, CAT does not conform to ANIMAL keep all&lt;br /&gt;
  a := c&lt;br /&gt;
&lt;br /&gt;
    -- legal, ANIMAL keep all still has the feature `eat'&lt;br /&gt;
  a.eat (food)&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/e&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== A Simple Generic Algorithm ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;e&amp;gt;&lt;br /&gt;
deferred class PERSON_PRINTER&lt;br /&gt;
feature&lt;br /&gt;
&lt;br /&gt;
  print_attributes (a_list: LIST [PERSON] forget all)&lt;br /&gt;
      -- Print all attributes of each person in the list.&lt;br /&gt;
    deferred&lt;br /&gt;
    end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
deferred class EXAMPLE&lt;br /&gt;
feature&lt;br /&gt;
  example&lt;br /&gt;
      -- Shows example usage of PERSON_PRINTER.&lt;br /&gt;
    local&lt;br /&gt;
      l_students: LINKED_LIST [STUDENT]&lt;br /&gt;
      l_professors: LINKED_LIST [PROFESSOR]&lt;br /&gt;
      l_person_printer: PERSON_PRINTER&lt;br /&gt;
    do&lt;br /&gt;
      create l_person_printer&lt;br /&gt;
      l_person_printer.print_attributes (l_students)&lt;br /&gt;
      l_person_printer.print_attributes (l_professor)&lt;br /&gt;
    end&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/e&amp;gt;&lt;br /&gt;
&lt;br /&gt;
By forgetting all covariantly redefined features the generics conform and we can reuse this algorithm for all implementations of &amp;lt;e&amp;gt;LIST&amp;lt;/e&amp;gt; of descendants of &amp;lt;e&amp;gt;PERSON&amp;lt;/e&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Agents ===&lt;br /&gt;
&lt;br /&gt;
For agents, we will look at an example with the type &amp;lt;e&amp;gt;T&amp;lt;/e&amp;gt; and a subtype &amp;lt;e&amp;gt;U&amp;lt;/e&amp;gt;. We will see an agent declaration and then check which arguments that are allowed:&lt;br /&gt;
&lt;br /&gt;
==== Calling agents ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;e&amp;gt;&lt;br /&gt;
local&lt;br /&gt;
  an_agent: PROCEDURE [ANY, TUPLE [T] forget all]&lt;br /&gt;
    -- An agent which takes an argument of type T.&lt;br /&gt;
do&lt;br /&gt;
    -- The following calls are surely permitted (and also correct) since&lt;br /&gt;
    -- the tuple generic inside the tuple has a 'forget all' clause and&lt;br /&gt;
    -- thus allows the tuple of type U to be passed.&lt;br /&gt;
  an_agent.call ([T])&lt;br /&gt;
  an_agent.call ([U])&lt;br /&gt;
&lt;br /&gt;
    -- Due to the tuple conformance, the following calls are also&lt;br /&gt;
    -- permitted. Note that they are both correct.&lt;br /&gt;
  an_agent.call ([T, ...])&lt;br /&gt;
  an_agent.call ([U, ...])&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/e&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We see that this solution allows the full range of applicable arguments for calling agents.&lt;br /&gt;
&lt;br /&gt;
==== Assigning agents ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;e&amp;gt;&lt;br /&gt;
local&lt;br /&gt;
  an_agent: PROCEDURE [ANY, TUPLE [T] forget all]&lt;br /&gt;
    -- An agent which takes an argument of type T.&lt;br /&gt;
do&lt;br /&gt;
  agent_empty := agent () do end --&amp;gt; PROCEDURE [ANY, TUPLE [] forget all]&lt;br /&gt;
  agent_any := agent (a: ANY) do end --&amp;gt; PROCEDURE [ANY, TUPLE [ANY] forget all]&lt;br /&gt;
  agent_t := agent (t: T) do end --&amp;gt; PROCEDURE [ANY, TUPLE [T] forget all]&lt;br /&gt;
  agent_u := agent (u: U) do end --&amp;gt; PROCEDURE [ANY, TUPLE [U] forget all]&lt;br /&gt;
  agent_tt := agent (t: T; t2: T) do end --&amp;gt; PROCEDURE [ANY, TUPLE [T, T] forget all]&lt;br /&gt;
&lt;br /&gt;
    -- This assignment is naturally allowed.&lt;br /&gt;
  an_agent := agent_t&lt;br /&gt;
&lt;br /&gt;
    -- Although it would be safe, the following assignments are not permitted by &lt;br /&gt;
    -- the solution as it does not allow contravariance.&lt;br /&gt;
  an_agent := agent_empty&lt;br /&gt;
  an_agent := agent_any&lt;br /&gt;
&lt;br /&gt;
    -- The following assignments are not permitted by the solution. This is the correct&lt;br /&gt;
    -- behaviour  as you could either create a catcall by passing a T argument to the &lt;br /&gt;
    -- `agent_u' or pass the wrong number of arguments by passing a [T] tuple to the &lt;br /&gt;
    -- `agent_tt'.&lt;br /&gt;
    -- The reason that they are not permitted is that the signature of 'call' changes&lt;br /&gt;
    -- and thus don't conform anymore (with 'keep all' as default)&lt;br /&gt;
  an_agent := agent_u&lt;br /&gt;
  an_agent := agent_tt&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/e&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Due to the lack of support for contravariance, not all safe assignments are possible with this solution.&lt;br /&gt;
&lt;br /&gt;
Since declaring an agent can be difficult (there needs to be a &amp;quot;forget all&amp;quot; somewhere?), an alternate [[Agent syntax|syntax for agents]] could be useful where the compiler can derive the correct type for an agent.&lt;br /&gt;
&lt;br /&gt;
== Issues ==&lt;br /&gt;
&lt;br /&gt;
=== Whole-system analysis ===&lt;br /&gt;
&lt;br /&gt;
Consider the following code fragment which shows an object test:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;e&amp;gt;&lt;br /&gt;
local&lt;br /&gt;
  a: ANIMAL&lt;br /&gt;
do&lt;br /&gt;
  if {x: ANIMAL forget all} a then&lt;br /&gt;
    x.sleep&lt;br /&gt;
  end&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/e&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Now if the system is extended with a reference to the class CAT, the code becomes invalid as now &amp;lt;e&amp;gt;ANIMAL forget all&amp;lt;/e&amp;gt; does not have a feature &amp;lt;e&amp;gt;sleep&amp;lt;/e&amp;gt; anymore. This prevents loading of classes at runtime.&lt;br /&gt;
&lt;br /&gt;
=== Object test ===&lt;br /&gt;
&lt;br /&gt;
Consider the following code fragment which shows an object test:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;e&amp;gt;&lt;br /&gt;
local&lt;br /&gt;
  a: ANIMAL forget all&lt;br /&gt;
  c: CAT -- cat features 'eat' and 'sleep'&lt;br /&gt;
do&lt;br /&gt;
    -- Valid&lt;br /&gt;
  a := c &lt;br /&gt;
  if {x: ANIMAL forget eat} a then&lt;br /&gt;
    x.sleep&lt;br /&gt;
  end&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/e&amp;gt;&lt;br /&gt;
&lt;br /&gt;
For this to work, the runtime must have information about the covariantly redefined features of each class. This adds a considerable amount of work to the object test as you need to check if all features which are covariantly redefined between the test type (&amp;lt;e&amp;gt;ANIMAL&amp;lt;/e&amp;gt;) and the dynamic type (&amp;lt;e&amp;gt;CAT&amp;lt;/e&amp;gt;) are listed in the forget clause.&lt;br /&gt;
&lt;br /&gt;
== Conclusion ==&lt;br /&gt;
&lt;br /&gt;
This proposal solves catcalls as a whole. This include catcalls which are introduced by covariant argument redefinition through formal arguments in generic classes.&lt;br /&gt;
It is not as expressive as other solutions (not fully applicable to agents, comparator example) and it is likely that it adds a lot of syntax to the code.&lt;/div&gt;</summary>
		<author><name>Juliant</name></author>	</entry>

	<entry>
		<id>https://dev.eiffel.com/index.php?title=Agent_syntax&amp;diff=8908</id>
		<title>Agent syntax</title>
		<link rel="alternate" type="text/html" href="https://dev.eiffel.com/index.php?title=Agent_syntax&amp;diff=8908"/>
				<updated>2007-06-24T18:43:49Z</updated>
		
		<summary type="html">&lt;p&gt;Juliant: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Category:ECMA]]&lt;br /&gt;
{{Research}}&lt;br /&gt;
==Agent syntax==&lt;br /&gt;
&lt;br /&gt;
 Idea: Use the '''like''' keyword followed by an agent signature definition to define agent types.&lt;br /&gt;
&lt;br /&gt;
The good thing is that in Eiffel the &amp;quot;like&amp;quot; mechanism is already in place and well understood. In order to define an agent type something like&lt;br /&gt;
&amp;lt;e&amp;gt;&lt;br /&gt;
an_agent: like agent (a_x, a_y: INTEGER): BOOLEAN&lt;br /&gt;
&amp;lt;/e&amp;gt;&lt;br /&gt;
would be very handy. Note that it is very similar to the definition of an inline agent. Of course the argument names could be omitted. But by allowing it we can even provide a named tuple as the argument signature for the call feature.&lt;br /&gt;
&amp;lt;e&amp;gt;&lt;br /&gt;
an_agent: like agent (INTEGER; INTEGER): BOOLEAN&lt;br /&gt;
&amp;lt;/e&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The reason to introduce a syntax like this is to let the compiler handle the correct type of the agent. Depending if the type system is enhanced on a per-declaration syntax - like the [[restrict types]] or the [[usage-site variance]] propose - then the definition of an agent can be very cumbersome. By giving the programmer a shorthand he does not need to specify the exact agent type himself.&lt;/div&gt;</summary>
		<author><name>Juliant</name></author>	</entry>

	<entry>
		<id>https://dev.eiffel.com/index.php?title=Comparison_of_catcall_solutions&amp;diff=8907</id>
		<title>Comparison of catcall solutions</title>
		<link rel="alternate" type="text/html" href="https://dev.eiffel.com/index.php?title=Comparison_of_catcall_solutions&amp;diff=8907"/>
				<updated>2007-06-24T18:42:35Z</updated>
		
		<summary type="html">&lt;p&gt;Juliant: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Category:ECMA]]&lt;br /&gt;
[[Category:Catcall]]&lt;br /&gt;
== Motivation ==&lt;br /&gt;
&lt;br /&gt;
By allowing covariant feature redefinition and hiding of features, the Eiffel language introduces the problem of catcalls (Changed Availability or Type). Currently the ECMA Eiffel standard does not specify how the occurrence of catcalls should be statically rejected.&lt;br /&gt;
&lt;br /&gt;
The purpose of this document is to show a comparison between different proposals on how to handle the issue of preventing catcalls.&lt;br /&gt;
&lt;br /&gt;
== Criteria for a solution ==&lt;br /&gt;
&lt;br /&gt;
To be able to judge a solution we use the following criteria which we consider as important:&lt;br /&gt;
&lt;br /&gt;
; Syntax overhead : How much syntax will be added to the language in order to express safe covariance and generics?&lt;br /&gt;
; Covariance on non-generic types : Are covariant argument redefinitions addressed in the solution? How does the programmer express it?&lt;br /&gt;
; Export status restrictions : Is restriction of export status addressed in the solution? How does the programmer express it?&lt;br /&gt;
; Use of generic types : How is conformance of generics? Are catcalls for generics addressed in the solution? How does the programmer express it? Can generics be used as now or are there restrictions?&lt;br /&gt;
:; Agents : Can agents be modeled with the solution while being type safe and expressive?&lt;br /&gt;
:; Comparator : Can comparator types be modeled with the solution while being type safe and expressive?&lt;br /&gt;
; Complexity of the compiler check : Is it just a matter of doing one check or several?&lt;br /&gt;
; Complexity of the runtime : Does the runtime need more information to do assignment attempts or object tests?&lt;br /&gt;
; Whole-system analysis : Is a whole-system analysis necessary?&lt;br /&gt;
; Dynamic class and type loading : Is it safe to dynamically load new classes at runtime and instantiate new types?&lt;br /&gt;
; Backward compatibility : Is the solution backward compatible to existing source code?&lt;br /&gt;
:; Applicable per cluster : Can the solution be applied on a per cluster basis?&lt;br /&gt;
; Support of compiler/IDE : Can the compiler/IDE help in updating existing source code? How?&lt;br /&gt;
&lt;br /&gt;
== General remarks ==&lt;br /&gt;
&lt;br /&gt;
=== Checking feature calls ===&lt;br /&gt;
&lt;br /&gt;
As the ''Single-level Call rule'' (8.25.3, VUSC) describes, a feature call is only valid if it is valid for every type in the dynamic type set. A simple solution would be that every feature call has to be checked for all possible descendants of the static target type. If this check is performed on a system, it will catch all catcalls - but also report false positives.&lt;br /&gt;
&lt;br /&gt;
Some of the proposed solutions try to address this problem by finding a better approximation to the dynamic type set so that the false positives can be ruled out.&lt;br /&gt;
&lt;br /&gt;
In general this is problematic as it requires a whole-system analysis, thus preventing the dynamic loading of new classes at run-time. The reason for this is that it is not known at compile time which features will be covariantly redefined by dynamically loaded classes.&lt;br /&gt;
&lt;br /&gt;
This is only the case with non-generic types. For generics, it is known at compile time that all features containing a formal in the parameter list can be treated as covariantly redefined and corresponding precautions can be implemented via the type system and conformance rules which allow to load even generic types at run-time.&lt;br /&gt;
&lt;br /&gt;
By the way, Eiffel Software has started to [[Single level call rule implementation|implement the basis of the ''single-level call rule'']] in it's Eiffel compiler. It is work in progress which revealed some implementation problems.&lt;br /&gt;
&lt;br /&gt;
=== Generic vs. non-generic covariance ===&lt;br /&gt;
&lt;br /&gt;
We can distinguish two different kinds of covariant argument redefinition:&lt;br /&gt;
&lt;br /&gt;
* When a generic type is derived, the formal generic parameters will be replaced by the actual generic parameters. Given the current conformance rules for generics, this can be seen as a covariant redefinition for all features which contain a formal generic as an argument. A simple example is the change from &amp;lt;e&amp;gt;LIST [ANY]&amp;lt;/e&amp;gt; to &amp;lt;e&amp;gt;LIST [INTEGER]&amp;lt;/e&amp;gt; where the feature &amp;lt;e&amp;gt;put&amp;lt;/e&amp;gt; changes signature from &amp;lt;e&amp;gt;ANY&amp;lt;/e&amp;gt; to &amp;lt;e&amp;gt;INTEGER&amp;lt;/e&amp;gt;.&lt;br /&gt;
* In the non-generic case, covariance happens for certain anchored type declarations and in the case of explicitly changing an argument type to a descendant. This happens in general only on a small subset of the features.&lt;br /&gt;
&lt;br /&gt;
The main difference is that in the generic case, all features which have a formal generic parameter automatically change the signature in different derivations whereas the non-generic case only specific features are covariantly redefined (if any at all). Also, in the generic case it is known for all possible descendants which features are redefined covariantly.&lt;br /&gt;
&lt;br /&gt;
This observation helps to understand the various proposals and to see their strengths and weaknesses:&lt;br /&gt;
* A proposal which operates on the feature level can be good for non-generic classes as you generally have a small number of features covariantly redefined and you only have to specify these features. In the case of generics this can become cumbersome as all features with formal generic parameters are always considered as covariantly redefined and thus for generics they always have to be considered.&lt;br /&gt;
* A proposal which operates on the type level is better suited for generics as you don't have to specify every single feature which has a formal generic parameter as argument. But they run into problems in the non-generic case if you look at anchored types - for example &amp;lt;e&amp;gt;like Current&amp;lt;/e&amp;gt;. Due to the fact that you have a covariant redeclaration in every descendant with such a feature, operating on the type level means that you have to handle every descendant specifically whereas if you operated on the feature level you could just handle this single feature.&lt;br /&gt;
* You see that there are two families of features: Features with formal arguments and ordinary features which are covariantly redefined. The fundamental difference between these two families is that they can change their signature independently. From &amp;lt;e&amp;gt;LIST [ANY]&amp;lt;/e&amp;gt; to &amp;lt;e&amp;gt;LIST [INTEGER]&amp;lt;/e&amp;gt; only the features based on the formal change their signature while they don't change from &amp;lt;e&amp;gt;LIST [ANY]&amp;lt;/e&amp;gt; to &amp;lt;e&amp;gt;LINKED_LIST [ANY]&amp;lt;/e&amp;gt; where the ordinary ones do. If you don't want to restrict the programmers expressiveness these feature families have to be addressed separately and a ''one fits all'' solution does not exist.&lt;br /&gt;
&lt;br /&gt;
=== Contravariant generics ===&lt;br /&gt;
&lt;br /&gt;
The modeling of certain problems involving generics requires contravariance. The two examples which will be used are comparator objects and agents:&lt;br /&gt;
&lt;br /&gt;
* If you want to compare objects using a comparator, it either needs to be able to compare objects of the exact type, or an ancestor. Thus if you want to compare strings, either a comparator for &amp;lt;e&amp;gt;STRING&amp;lt;/e&amp;gt; or one for &amp;lt;e&amp;gt;ANY&amp;lt;/e&amp;gt; is suitable. &lt;br /&gt;
* If you want to pass an argument of type &amp;lt;e&amp;gt;STRING&amp;lt;/e&amp;gt; to an agent, the agent either has to accept a &amp;lt;e&amp;gt;STRING&amp;lt;/e&amp;gt; or &amp;lt;e&amp;gt;ANY&amp;lt;/e&amp;gt; argument (or no argument at all).&lt;br /&gt;
&lt;br /&gt;
These problems can only be modeled if there is a way to express contravariant conformance for generics. This means that all proposed solutions which don't offer this possibility can't be used to model agents or comparator correctly and safely.&lt;br /&gt;
&lt;br /&gt;
=== Catcall benchmark ===&lt;br /&gt;
&lt;br /&gt;
[[Catcall checkpoints]]&lt;br /&gt;
&lt;br /&gt;
== Overview of general solutions ==&lt;br /&gt;
&lt;br /&gt;
The following proposals handle the case of covariance on non-generic and generic types.&lt;br /&gt;
&lt;br /&gt;
=== [[Novariance]] ===&lt;br /&gt;
&lt;br /&gt;
In the novariance proposal, covariant redefinition for arguments is prohibited. If covariance is needed for modeling purposes it can be [http://dev.eiffel.com/Covariance_through_renaming simulated by renaming].&lt;br /&gt;
&lt;br /&gt;
The conformance between generics with different formal parameters is removed.&lt;br /&gt;
&lt;br /&gt;
=== [[Forget / keep]] ===&lt;br /&gt;
&lt;br /&gt;
With the forget and keep mechanisms you specify per type on the feature level which features need not to be called - these features can safely be redefined covariantly - or which features have to be available - these features have to be typesafe for all possible values of a caller object.&lt;br /&gt;
&lt;br /&gt;
Reference: [http://dev.eiffel.com/Forget_/_Keep_Mechanism Article on dev.eiffel.com]&lt;br /&gt;
&lt;br /&gt;
=== Dynamic typeset algorithm ===&lt;br /&gt;
&lt;br /&gt;
The dynamic typeset algorithm does not change any semantics of the types or the conformance as it is in Eiffel already, it only does an abstract execution of the system to limit the possibilities per feature call which have to be checked if they are safe.&lt;br /&gt;
== Overview of solutions for non-generics ==&lt;br /&gt;
&lt;br /&gt;
These proposal only address the case for non-generics. For generic catcalls another solution (e.g. wildcard generics) can be used.&lt;br /&gt;
&lt;br /&gt;
=== [[Restrict types]] ===&lt;br /&gt;
&lt;br /&gt;
With restrict types you specify per type on the type level which descendant types that are allowed. Only these types can be assigned to such a variable, and all feature calls on these variables have to be valid for all possible types in this list.&lt;br /&gt;
&lt;br /&gt;
Reference: [http://se.inf.ethz.ch/cgi-bin/ecma/index.cgi?IssueFLEX_CATCALL IssueFLEX_CATCALL on ECMA wiki]&amp;lt;br/&amp;gt;&lt;br /&gt;
Reference: Discussion in ECMA mailinglist named ''Catcall removal: another proposal'', [[Restrict types mail|available in parts]]&lt;br /&gt;
&lt;br /&gt;
=== [[DOG proposal]] ===&lt;br /&gt;
&lt;br /&gt;
With the DOG proposal, features which can be covariantly redefined have to be marked as such. These features can only be called on specially marked entities which have a restricted conformance, thus preventing assignments from descendants with potential covariantly redefined arguments.&lt;br /&gt;
&lt;br /&gt;
Reference: [http://se.inf.ethz.ch/cgi-bin/ecma/index.cgi?IssueDOG IssueDOG on ECMA wiki]&lt;br /&gt;
&lt;br /&gt;
== Overview of solutions for generics ==&lt;br /&gt;
&lt;br /&gt;
These proposal only address the case for generics. For non-generic catcalls another solution (e.g. novariance) can be used.&lt;br /&gt;
&lt;br /&gt;
=== [[Usage-site variance]] ===&lt;br /&gt;
&lt;br /&gt;
This solution lets the programmer decide on the instantiation of a generic if the generic parameter should be covariant, contravariant or invariant. Depending on the variance, the applicable features of the type and the conformance rules to other generic types are changed.&lt;br /&gt;
&lt;br /&gt;
Reference: [http://pag.csail.mit.edu/reading-group/variance-ECOOP02.pdf On variance-based subtyping for parametric types]&lt;br /&gt;
&lt;br /&gt;
=== [[Definition-site variance]] ===&lt;br /&gt;
&lt;br /&gt;
This solution lets the programmer decide in the definition of a generic class if the generic parameter should be covariant, contravariant or invariant. Depending on the variance, the formal generic can only appear at the argument, only appear as a result type or appear in both places. Also the conformance is adapted depending on the variance of the generic parameter.&lt;br /&gt;
&lt;br /&gt;
This is the solution which is implemented in the CLR, although not supported by generics in C# which are novariant.&lt;br /&gt;
&lt;br /&gt;
Reference: [http://blogs.msdn.com/rmbyers/archive/2006/06/01/613690.aspx Article about generics in CLR]&lt;br /&gt;
&lt;br /&gt;
Note: There is also a [http://fams.de/text/type-safe-eiffel.html proposal by Bernd Schoeller] about ''variant and invariant'' generics which is a subset of this one and thus not explained in detail.&lt;br /&gt;
&lt;br /&gt;
=== Wildcard generics ===&lt;br /&gt;
&lt;br /&gt;
This mechanism extends the [[usage-site variance]] by adding a wildcard to the generic derivation. This wildcard denotes unspecified types and limits the use of features with generic parameters or result types over conformance to the wildcard types.&lt;br /&gt;
&lt;br /&gt;
Since the mechanism is almost identical to the usage-site variance, it will not be looked at in more detail. Please refer to the reference article for more information.&lt;br /&gt;
&lt;br /&gt;
Reference: [http://www.jot.fm/issues/issue_2004_12/article5 Adding Wildcards to the Java Programming Language]&lt;br /&gt;
&lt;br /&gt;
== Overview of dynamic solutions ==&lt;br /&gt;
&lt;br /&gt;
These proposals do not prevent catcalls at compile-time but introduce means to handle catcalls at runtime.&lt;br /&gt;
&lt;br /&gt;
=== [[Detachable types]] ===&lt;br /&gt;
&lt;br /&gt;
This solution allows covariantly redefined features only to use detachable types. Through this mechanism, an object test is necessary before an argument can be used. This forces the programmer to test arguments for validity.&lt;br /&gt;
&lt;br /&gt;
Reference: [http://se.ethz.ch/~meyer/publications/lncs/attached.pdf Article about ''attached types'' by Bertrand Meyer]&amp;lt;br/&amp;gt;&lt;br /&gt;
Reference: [http://www.ecma-international.org/publications/standards/Ecma-367.htm ECMA Eiffel standard 2nd edition of June 2006]&lt;br /&gt;
&lt;br /&gt;
=== Recast ===&lt;br /&gt;
&lt;br /&gt;
In the recast proposal, the programmer has to specify a transformation function when covariantly redefining a feature which can transform the old argument types to the new ones.&lt;br /&gt;
&lt;br /&gt;
Reference: [http://se.inf.ethz.ch/cgi-bin/ecma/index.cgi?IssueCAT IssueCAT on ECMA wiki]&amp;lt;br/&amp;gt;&lt;br /&gt;
Reference: [http://www.inf.ethz.ch/~meyer/ongoing/covariance/recast.pdf Article about recast]&lt;br /&gt;
&lt;br /&gt;
=== Exceptions ===&lt;br /&gt;
&lt;br /&gt;
Another way of handling catcalls at runtime is to raise exceptions. It can be required or not to provide a rescue clause which handles the case of the catcall.&lt;br /&gt;
&lt;br /&gt;
== Combinations ==&lt;br /&gt;
&lt;br /&gt;
It is also possible to combine different proposals:&lt;br /&gt;
&lt;br /&gt;
* Novariance for non-generic features and usage-site variance for generics .&lt;br /&gt;
* Forget / keep for non-generic features and definition-site variance for generics.&lt;br /&gt;
* DOG proposal for non-generic features and wildcard generics.&lt;br /&gt;
* ...&lt;br /&gt;
&lt;br /&gt;
== Results ==&lt;br /&gt;
&lt;br /&gt;
The following table summarizes the support of the various solutions to the criteria described above which can be used to judge a catcall solution.&lt;br /&gt;
&lt;br /&gt;
This results can be differently interpreted, so the colors may not be totally accurate. See the [[Comparison of catcall solutions#Table_explained|explanation at the end of the table]] for more information&lt;br /&gt;
&lt;br /&gt;
=== General solutions ===&lt;br /&gt;
&lt;br /&gt;
{| border=1 cellpadding=2&lt;br /&gt;
&lt;br /&gt;
|- style=&amp;quot;visibility: hidden&amp;quot;&lt;br /&gt;
| style=&amp;quot;width:25%&amp;quot; |&lt;br /&gt;
| style=&amp;quot;width:25%&amp;quot; |&lt;br /&gt;
| style=&amp;quot;width:25%&amp;quot; |&lt;br /&gt;
| style=&amp;quot;width:25%&amp;quot; |&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
&lt;br /&gt;
! Criteria&lt;br /&gt;
! [[Novariance]]&lt;br /&gt;
! [[Forget / keep]]&lt;br /&gt;
! Dynamic typeset algorithm&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
&lt;br /&gt;
! Syntax overhead&lt;br /&gt;
| {{Green|No}}&lt;br /&gt;
| {{Red|Big}}: forget/keep clauses per type&lt;br /&gt;
| {{Green|No}}&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
&lt;br /&gt;
! Covariance on non-generic types &lt;br /&gt;
| {{Red|Not allowed}}&lt;br /&gt;
| {{Green|Allowed}}&lt;br /&gt;
| {{Green|Allowed}}&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
&lt;br /&gt;
! Export status restrictions&lt;br /&gt;
| {{Red|Not allowed}}&lt;br /&gt;
| {{Green|Allowed}}&lt;br /&gt;
| {{Green|Allowed}}&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
&lt;br /&gt;
! Use of generic types&lt;br /&gt;
| {{Red|Very limited}}: Only invariant conformance&lt;br /&gt;
| {{Orange|Limited}}: Conformance restricted (''keep all'' as default)&amp;lt;br/&amp;gt;{{Orange|Limited}}: Use restricted (''forget all'' as default)&lt;br /&gt;
| {{Green|As it is now}}&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
&lt;br /&gt;
! Agents&lt;br /&gt;
| {{Orange|Limited}}&amp;lt;br/&amp;gt;{{Green|Safe}}&lt;br /&gt;
| {{Orange|Limited}}&amp;lt;br/&amp;gt;{{Green|Safe}}&lt;br /&gt;
| {{Red|As it is now}}&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
&lt;br /&gt;
! Comparator&lt;br /&gt;
| {{Red|Not supported}}&lt;br /&gt;
| {{Red|Not supported}}&lt;br /&gt;
| {{Red|Not supported}}&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
&lt;br /&gt;
! Complexity of compiler check&lt;br /&gt;
| {{Green|Small}}&lt;br /&gt;
| {{Orange|Medium}}: Check of feature call for all descendants; Conformance check on forget/keep clauses&lt;br /&gt;
| {{Red|Big}}: Iterative abstract system execution&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
&lt;br /&gt;
! Complexity of runtime&lt;br /&gt;
| {{Green|Small}}: As it is now&lt;br /&gt;
| {{Orange|Medium}}: Need to know cat features for object tests&lt;br /&gt;
| {{Green|Small}}: As it is now&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
&lt;br /&gt;
! Whole-system analysis&lt;br /&gt;
| {{Green|No}}&lt;br /&gt;
| {{Red|Yes}}: use of ''forget all'' depends on system&lt;br /&gt;
| {{Red|Yes}}&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
&lt;br /&gt;
! Dynamic class and type loading&lt;br /&gt;
| {{Green|Yes}}&lt;br /&gt;
| {{Red|No}}&lt;br /&gt;
| {{Red|No}}&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
&lt;br /&gt;
! Backward compatibility&lt;br /&gt;
| {{Red|Very limited}}&lt;br /&gt;
| {{Orange|Limited}}&lt;br /&gt;
| {{Green|Full}}&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
&lt;br /&gt;
! Support of IDE (Source changes)&lt;br /&gt;
| {{Green|Not needed}}&lt;br /&gt;
| {{Orange|Possible}}: Can propose forget/keep clauses&lt;br /&gt;
| {{Green|Not needed}}&lt;br /&gt;
&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Solutions for non-generics ===&lt;br /&gt;
&lt;br /&gt;
{| border=1 cellpadding=2&lt;br /&gt;
&lt;br /&gt;
|- style=&amp;quot;visibility: hidden&amp;quot;&lt;br /&gt;
| style=&amp;quot;width:25%&amp;quot; |&lt;br /&gt;
| style=&amp;quot;width:25%&amp;quot; |&lt;br /&gt;
| style=&amp;quot;width:25%&amp;quot; |&lt;br /&gt;
| style=&amp;quot;width:25%&amp;quot; |&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
&lt;br /&gt;
! Criteria&lt;br /&gt;
! [[Restrict types]]&lt;br /&gt;
! [[DOG proposal]]&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
&lt;br /&gt;
! Syntax overhead&lt;br /&gt;
| {{Red|Big}}: Restrict clause per type declaration&lt;br /&gt;
| {{Orange|Medium}}: ''cat'' on features and on type declarations&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
&lt;br /&gt;
! Covariance on non-generic types &lt;br /&gt;
| {{Green|Allowed}}&lt;br /&gt;
| {{Green|Allowed}}&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
&lt;br /&gt;
! Export status restrictions&lt;br /&gt;
| {{Green|Allowed}}&lt;br /&gt;
| {{Green|Allowed}}&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
&lt;br /&gt;
! Use of generic types&lt;br /&gt;
| Not addressed&lt;br /&gt;
| Not addressed&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
&lt;br /&gt;
! Agents&lt;br /&gt;
| Not addressed&lt;br /&gt;
| Not addressed&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
&lt;br /&gt;
! Comparator&lt;br /&gt;
| Not addressed&lt;br /&gt;
| Not addressed&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
&lt;br /&gt;
! Complexity of compiler check&lt;br /&gt;
| {{Orange|Medium}}: Check of feature call for all descendants; Conformance check on restrict clauses&lt;br /&gt;
| {{Green|Small}}: Check of ''cat'' on conformance&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
&lt;br /&gt;
! Complexity of runtime&lt;br /&gt;
| not yet considered&lt;br /&gt;
| {{Green|Small}}&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
&lt;br /&gt;
! Whole-system analysis&lt;br /&gt;
| {{Orange|Partial}}&lt;br /&gt;
| {{Green|No}}&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
&lt;br /&gt;
! Dynamic class and type loading&lt;br /&gt;
| {{Orange|Limited}}&lt;br /&gt;
| {{Green|Yes}}&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
&lt;br /&gt;
! Backward compatibility&lt;br /&gt;
| {{Red|Very limited}}&lt;br /&gt;
| {{Red|Very limited}}&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
&lt;br /&gt;
! Support of IDE (Source changes)&lt;br /&gt;
| {{Orange|Possible}}: Can propose restrict clauses&lt;br /&gt;
| {{Orange|Possible}}: Can propose ''cat'' marks&lt;br /&gt;
&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Solutions for generics ===&lt;br /&gt;
&lt;br /&gt;
{| border=1 cellpadding=2&lt;br /&gt;
&lt;br /&gt;
|- style=&amp;quot;visibility: hidden&amp;quot;&lt;br /&gt;
| style=&amp;quot;width:25%&amp;quot; |&lt;br /&gt;
| style=&amp;quot;width:25%&amp;quot; |&lt;br /&gt;
| style=&amp;quot;width:25%&amp;quot; |&lt;br /&gt;
| style=&amp;quot;width:25%&amp;quot; |&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
&lt;br /&gt;
! Criteria&lt;br /&gt;
! [[Usage-site variance]]&lt;br /&gt;
! [[Definition-site variance]]&lt;br /&gt;
! Wildcard generics&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
&lt;br /&gt;
! Syntax overhead&lt;br /&gt;
| {{Orange|Medium}}: Variance marks per generic type&lt;br /&gt;
| {{Green|Small}}: Variance marks per generic class definition&lt;br /&gt;
| {{Orange|Medium}}: Variance marks per generic type&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
&lt;br /&gt;
! Covariance on non-generic types &lt;br /&gt;
| Not addressed&lt;br /&gt;
| Not addressed&lt;br /&gt;
| Not addressed&lt;br /&gt;
|-&lt;br /&gt;
&lt;br /&gt;
! Export status restrictions&lt;br /&gt;
| Not addressed&lt;br /&gt;
| Not addressed&lt;br /&gt;
| Not addressed&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
&lt;br /&gt;
! Use of generic types&lt;br /&gt;
| {{Orange|Limited}}: Conformance is limited&amp;lt;br/&amp;gt;{{Green|Safe}}&lt;br /&gt;
| {{Orange|Limited}}: Conformance is limited&amp;lt;br/&amp;gt;{{Green|Safe}}&lt;br /&gt;
| {{Orange|Limited}}: Conformance is limited&amp;lt;br/&amp;gt;{{Green|Safe}}&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
&lt;br /&gt;
! Agents&lt;br /&gt;
| {{Green|Fully supported}}&amp;lt;br/&amp;gt;{{Green|Safe}}&lt;br /&gt;
| {{Orange|Almost fully supported}}&amp;lt;br/&amp;gt;{{Green|Safe}}&lt;br /&gt;
| {{Green|Fully supported}}&amp;lt;br/&amp;gt;{{Green|Safe}}&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
&lt;br /&gt;
! Comparator&lt;br /&gt;
| {{Green|Supported}}&lt;br /&gt;
| {{Green|Supported}}&lt;br /&gt;
| {{Green|Supported}}&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
&lt;br /&gt;
! Complexity of compiler check&lt;br /&gt;
| {{Green|Small}}: Consider variance in conformance check&lt;br /&gt;
| {{Green|Small}}: Consider variance in conformance check&lt;br /&gt;
| {{Green|Small}}: Consider variance in conformance check&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
&lt;br /&gt;
! Complexity of runtime&lt;br /&gt;
| {{Green|Small}}: Consider variance in object test&lt;br /&gt;
| {{Green|Small}}: Consider variance in object test&lt;br /&gt;
| {{Green|Small}}: Consider variance in object test&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
&lt;br /&gt;
! Whole-system analysis&lt;br /&gt;
| {{Green|No}}&lt;br /&gt;
| {{Green|No}}&lt;br /&gt;
| {{Green|No}}&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
&lt;br /&gt;
! Dynamic class and type loading&lt;br /&gt;
| {{Green|Yes}}&lt;br /&gt;
| {{Green|Yes}}&lt;br /&gt;
| {{Green|Yes}}&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
&lt;br /&gt;
! Backward compatibility&lt;br /&gt;
| {{Orange|Limited}}: Use of generics changed due to conformance&lt;br /&gt;
| {{Red|Very limited}}: Libraries need redesign&lt;br /&gt;
| {{Orange|Limited}}: Use of generics changed due to conformance&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
&lt;br /&gt;
! Support of IDE (Source changes)&lt;br /&gt;
| {{Orange|Possible}}: Can propose variance marks&lt;br /&gt;
| {{Red|Not possible}}: Libraries need redesign&lt;br /&gt;
| {{Orange|Possible}}: Can propose variance marks/wildcards&lt;br /&gt;
&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Dynamic solutions ===&lt;br /&gt;
&lt;br /&gt;
{| border=1 cellpadding=2&lt;br /&gt;
&lt;br /&gt;
|- style=&amp;quot;visibility: hidden&amp;quot;&lt;br /&gt;
| style=&amp;quot;width:25%&amp;quot; |&lt;br /&gt;
| style=&amp;quot;width:25%&amp;quot; |&lt;br /&gt;
| style=&amp;quot;width:25%&amp;quot; |&lt;br /&gt;
| style=&amp;quot;width:25%&amp;quot; |&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
&lt;br /&gt;
! Criteria&lt;br /&gt;
! [[Detachable types]]&lt;br /&gt;
! Recast&lt;br /&gt;
! Exceptions&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
&lt;br /&gt;
! Syntax overhead&lt;br /&gt;
| {{Green|Small}}: Detachment marks&lt;br /&gt;
| {{Red|Big}}: Recast clauses, recast features&lt;br /&gt;
| {{Orange|Medium}}: If rescue clause mandatory&amp;lt;br/&amp;gt;{{Green|No}}: If rescue clause not needed&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
&lt;br /&gt;
! Covariance on non-generic types &lt;br /&gt;
| {{Red|Very limited}}: Only detached arguments, no expanded arguments&lt;br /&gt;
| {{Green|Allowed}}&lt;br /&gt;
| {{Green|Allowed}}&lt;br /&gt;
|-&lt;br /&gt;
&lt;br /&gt;
! Export status restrictions&lt;br /&gt;
| Not addressed&lt;br /&gt;
| Not addressed&lt;br /&gt;
| Not addressed&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
&lt;br /&gt;
! Use of generics&lt;br /&gt;
| {{Red|Very limited}}: Only detachable formal arguments&lt;br /&gt;
| {{Red|Very limited}}: Recast clause for all features with formal generics&lt;br /&gt;
| {{Green|As it is now}}&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
&lt;br /&gt;
! Agents&lt;br /&gt;
| {{Red|As it is now}} &lt;br /&gt;
| {{Red|As it is now}} &lt;br /&gt;
| {{Red|As it is now}} &lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
&lt;br /&gt;
! Comparator&lt;br /&gt;
| {{Red|Not supported}}&lt;br /&gt;
| {{Red|Not supported}}&lt;br /&gt;
| {{Red|Not supported}}&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
&lt;br /&gt;
! Complexity of compiler check&lt;br /&gt;
| {{Green|Small}}: As it is now&lt;br /&gt;
| {{Green|Small}}: As it is now&lt;br /&gt;
| {{Green|Small}}: As it is now&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
&lt;br /&gt;
! Complexity of runtime&lt;br /&gt;
| {{Green|Small}}: As it is now&lt;br /&gt;
| {{Orange|Medium}}: Check for catcalls and do recast&lt;br /&gt;
| {{Orange|Medium}}: Check for catcalls and raise exception&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
&lt;br /&gt;
! Whole-system analysis&lt;br /&gt;
| {{Green|No}}&lt;br /&gt;
| {{Green|No}}&lt;br /&gt;
| {{Green|No}}&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
&lt;br /&gt;
! Dynamic class and type loading&lt;br /&gt;
| {{Green|Yes}}&lt;br /&gt;
| {{Green|Yes}}&lt;br /&gt;
| {{Green|Yes}}&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
&lt;br /&gt;
! Backward compatibility&lt;br /&gt;
| {{Red|Very limited}}: All covariant and generic features become detached&lt;br /&gt;
| {{Red|Very limited}}: All covariant and generic features need recast clause&lt;br /&gt;
| {{Orange|Limited}}: If rescue clause is mandatory&amp;lt;br/&amp;gt;{{Green|Full}}: If rescue clause not needed&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
&lt;br /&gt;
! Support of IDE (Source changes)&lt;br /&gt;
| {{Orange|Possible}}: Can propose detachment marks&lt;br /&gt;
| {{Red|Not possible}}: Programmer must provide recast clause&lt;br /&gt;
| {{Red|Not possible}}: If rescue clause mandatory&amp;lt;br/&amp;gt;{{Green|Not needed}}: If rescue clause not needed&lt;br /&gt;
&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Table explained ===&lt;br /&gt;
&lt;br /&gt;
; Syntax overhead : {{Green|Small}} if a keyword/mark is needed per class/feature declaration; {{Orange|Medium}} if a keyword/mark is neede per type declaration; {{Red|Big}} if a clause is needed per type declaration.&lt;br /&gt;
; Use of generics : {{Green|As it is now}} if assignments are possible if generic parameters conform; {{Orange|Limited}} is some restrictions in the use or the conformance between generics exist; {{Red|Very limited}} a lot of restrictions in the use or the conformance between generics exist.&lt;br /&gt;
; Agents : {{Green|Fully supported}} if all safe assignments are allowed; {{Orange|Limited}} if not all safe assignments are allowed; {{Red|As it is now}} if unsafe assignments are still possible.&lt;br /&gt;
; Comparator : {{Green|Supported}} if for a comparator all safe assignments are permitted (i.e. contravariant assignments); {{Red|Not supported}} if only exact type or even (unsafe) subtypes can be assigned.&lt;br /&gt;
; Support of IDE (Source changes) : {{Green|Not needed}} if everything still works the same; {{Orange|Possible}} if the compiler can suggest clauses or marks; {{Red|Not possible}} if the programmer has to specify additional features/instructions.&lt;br /&gt;
&lt;br /&gt;
== Personal opinions ==&lt;br /&gt;
&lt;br /&gt;
[[Personal view about catcall solution]]&lt;/div&gt;</summary>
		<author><name>Juliant</name></author>	</entry>

	<entry>
		<id>https://dev.eiffel.com/index.php?title=Detachable_types&amp;diff=8906</id>
		<title>Detachable types</title>
		<link rel="alternate" type="text/html" href="https://dev.eiffel.com/index.php?title=Detachable_types&amp;diff=8906"/>
				<updated>2007-06-24T18:42:07Z</updated>
		
		<summary type="html">&lt;p&gt;Juliant: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Category:ECMA]]&lt;br /&gt;
[[Category:Catcall]]&lt;br /&gt;
{{Research}}&lt;br /&gt;
== Introduction ==&lt;br /&gt;
&lt;br /&gt;
This solution allows covariantly redefined features only to use detachable types. Through this mechanism, an object test is necessary before an argument can be used. This forces the programmer to test arguments for validity.&lt;br /&gt;
&lt;br /&gt;
This is specified in the [http://www.ecma-international.org/publications/standards/Ecma-367.htm ECMA Eiffel standard 2nd edition of June 2006].&lt;br /&gt;
&lt;br /&gt;
== Syntax ==&lt;br /&gt;
&lt;br /&gt;
No new syntax is necessary.&lt;br /&gt;
&lt;br /&gt;
== Semantics ==&lt;br /&gt;
&lt;br /&gt;
In this solution, it is only allowed to covariantly redefine arguments to detachable types. This ensures that an object test is done before the use of an argument. If now a catcall happens, the object test will fail. Since the argument is of detachable type, the programmer has to handle the case where Void is passed anyway and this also handles the catcall.&lt;br /&gt;
&lt;br /&gt;
== Examples ==&lt;br /&gt;
&lt;br /&gt;
See the [[introduction to examples]] for information about the classes used.&lt;br /&gt;
&lt;br /&gt;
=== Cats and dogs ===&lt;br /&gt;
&lt;br /&gt;
The definition of the CAT class changes as follows:&lt;br /&gt;
&amp;lt;e&amp;gt;&lt;br /&gt;
class CAT &lt;br /&gt;
inherit ANIMAL redefine eat end&lt;br /&gt;
feature&lt;br /&gt;
  eat (food: ? CAT_FOOD)&lt;br /&gt;
    do&lt;br /&gt;
      if {cat_food: CAT_FOOD} food then&lt;br /&gt;
        -- Use `cat_food'&lt;br /&gt;
      else&lt;br /&gt;
        -- either Void or an argument of type FOOD passed&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/e&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Issues ==&lt;br /&gt;
&lt;br /&gt;
=== Weak covariance support ===&lt;br /&gt;
&lt;br /&gt;
See [http://dev.eiffel.com/New_CAT_call article on dev.eiffel.com].&lt;br /&gt;
&lt;br /&gt;
=== Generics ===&lt;br /&gt;
&lt;br /&gt;
With the current conformance of generics, different generic derivations can be seen as if they covariantly redefined the features with formal generic parameters. For example feature &amp;lt;e&amp;gt;put&amp;lt;/e&amp;gt; from the class &amp;lt;e&amp;gt;LIST&amp;lt;/e&amp;gt; if you look at the signature of &amp;lt;e&amp;gt;LIST [ANY]&amp;lt;/e&amp;gt; compared to &amp;lt;e&amp;gt;LIST [STRING]&amp;lt;/e&amp;gt;. As with anchored types as parameters, you would also have to specify that all formal generic parameters need to be detached. This would mean that all classes which use generic parameters always have to use object tests to use the generic parameters, and Void-safety cannot be expressed on the type system level which would remove the main benefit of attached types in the context of generics.&lt;br /&gt;
&lt;br /&gt;
=== Expanded types ===&lt;br /&gt;
&lt;br /&gt;
The type rule specified by ECMA (VTCT, 8.11.8) defines that an expanded type cannot have an attachment mark since Void is not a valid value for it. Given that covariant feature redeclaration, especially anchored types for arguments, can only occur with detached types, this means that arguments cannot be covariantly redefined into expanded types.&lt;br /&gt;
&lt;br /&gt;
The base classes like &amp;lt;e&amp;gt;INTEGER&amp;lt;/e&amp;gt; which currently inherit from &amp;lt;e&amp;gt;NUMERIC&amp;lt;/e&amp;gt; which only defines it's arguments as &amp;lt;e&amp;gt;like Current&amp;lt;/e&amp;gt; would be invalid in their current form. Also if formal generic parameters need to be detached as explained above, generic derivations would not be allowed for expanded types if the formal generic occurs as a parameter of a feature. Especially &amp;lt;e&amp;gt;LIST [INTEGER]&amp;lt;/e&amp;gt; would not be possible.&lt;br /&gt;
&lt;br /&gt;
== Conclusion ==&lt;br /&gt;
&lt;br /&gt;
The problems arise partially due to the fact that two concepts are mixed:&lt;br /&gt;
* Attachable/detachable types: A type &amp;lt;e&amp;gt;? T&amp;lt;/e&amp;gt; can be attached to an object of type T or not attached at all (i.e. Void)&lt;br /&gt;
* Catcall arguments: In a catcall, the type of the argument can either be the expected type or the type of an ancestor version of the feature.&lt;br /&gt;
&lt;br /&gt;
By using detachable types to solve catcalls, the notion of a detachable type is expanded to be able to hold types of all ancestors as well.&lt;br /&gt;
&lt;br /&gt;
In addition to this, the problems with generics and expanded types show that this solution does severely limit the usefulness of covariance.&lt;/div&gt;</summary>
		<author><name>Juliant</name></author>	</entry>

	<entry>
		<id>https://dev.eiffel.com/index.php?title=Definition-site_variance&amp;diff=8905</id>
		<title>Definition-site variance</title>
		<link rel="alternate" type="text/html" href="https://dev.eiffel.com/index.php?title=Definition-site_variance&amp;diff=8905"/>
				<updated>2007-06-24T18:41:53Z</updated>
		
		<summary type="html">&lt;p&gt;Juliant: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Category:ECMA]]&lt;br /&gt;
[[Category:Catcall]]&lt;br /&gt;
{{Research}}&lt;br /&gt;
== Introduction ==&lt;br /&gt;
&lt;br /&gt;
The defintion-site variance allows the programmer to choose which kind of variance he wants to use in the defintion of a generic class. Unlike the [[usage-site variance]], this fixes a specific class to the kind of variance which it supports.&lt;br /&gt;
&lt;br /&gt;
== Syntax ==&lt;br /&gt;
&lt;br /&gt;
The syntax used here to specify the variance of a generic is simple and may be changed to something more verbose but also clearer:&lt;br /&gt;
&lt;br /&gt;
* To specify a novariant generic, the normal syntax can be used: &amp;lt;e&amp;gt;class LIST [G] end&amp;lt;/e&amp;gt;&lt;br /&gt;
* To specify a covariant generic, we use a plus sign: &amp;lt;e&amp;gt;class READ_LIST [+G] end&amp;lt;/e&amp;gt;&lt;br /&gt;
* To specify a contravariant generic, we use a minus sign: &amp;lt;e&amp;gt;class WRITE_LIST [-G] end&amp;lt;/e&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Semantics ==&lt;br /&gt;
&lt;br /&gt;
See the [[introduction to examples]] for information about the classes used.&lt;br /&gt;
&lt;br /&gt;
=== Conformance rules ===&lt;br /&gt;
&lt;br /&gt;
Depending on the variance of the generic, the conformance rules differ:&lt;br /&gt;
&lt;br /&gt;
* If a generic class is declared novariant, two generics conform if their base class conforms and the generic parameters match exactly. Thus &amp;lt;e&amp;gt;LIST [T]&amp;lt;/e&amp;gt; only conforms to &amp;lt;e&amp;gt;LIST [T]&amp;lt;/e&amp;gt;.&lt;br /&gt;
* If a generic class is declared covariant, a generic conforms to another if its base class conforms and the generic parameter conforms to the other. Thus &amp;lt;e&amp;gt;READ_LIST [U]&amp;lt;/e&amp;gt; conforms to &amp;lt;e&amp;gt;READ_LIST [T]&amp;lt;/e&amp;gt;.&lt;br /&gt;
* If a generic class is declared contravariant, a generic conforms to another if its base class conforms and the generic parameter is an ancestor of the other. Thus &amp;lt;e&amp;gt;WRITE_LIST [U]&amp;lt;/e&amp;gt; conforms to &amp;lt;e&amp;gt;WRITE_LIST [T]&amp;lt;/e&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Tuples are problematic in this solution as have to declare the generic tuple parameters as invariant. For the conformance of tuples, we keep that a tuple with more elements conforms to a tuple with less elements. The common elements have to match exactly due to their invariance:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;e&amp;gt;TUPLE [T, U]&amp;lt;/e&amp;gt; conforms to &amp;lt;e&amp;gt;TUPLE [T]&amp;lt;/e&amp;gt;&lt;br /&gt;
* &amp;lt;e&amp;gt;TUPLE [U]&amp;lt;/e&amp;gt; does not conform to &amp;lt;e&amp;gt;TUPLE [T]&amp;lt;/e&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Applicable features ===&lt;br /&gt;
&lt;br /&gt;
Depending on the variance of a generic, it can only occur in certain places:&lt;br /&gt;
&lt;br /&gt;
* A novariant generic can be used as argument or result type.&lt;br /&gt;
* A covariant generic can only be used as a result type.&lt;br /&gt;
* A contravariant generic can only be used as an argument type.&lt;br /&gt;
&lt;br /&gt;
== Examples ==&lt;br /&gt;
&lt;br /&gt;
See the [[introduction to examples]] for information about the classes used.&lt;br /&gt;
&lt;br /&gt;
=== A simple generic algorithm ===&lt;br /&gt;
&lt;br /&gt;
In order to use lists as read-only lists, the library design has to be adapted. &amp;lt;e&amp;gt;LIST [G]&amp;lt;/e&amp;gt; needs to inherit from &amp;lt;e&amp;gt;READ_LIST [+G]&amp;lt;/e&amp;gt;. That way you can assign a &amp;lt;e&amp;gt;LIST [STRING]&amp;lt;/e&amp;gt; to a &amp;lt;e&amp;gt;READ_LIST [STRING]&amp;lt;/e&amp;gt; and, through transitivity of conformance, to a &amp;lt;e&amp;gt;READ_LIST [ANY]&amp;lt;/e&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;e&amp;gt;&lt;br /&gt;
class PERSON_PRINTER&lt;br /&gt;
feature&lt;br /&gt;
  print_all (a_list: READ_LIST [PERSON])&lt;br /&gt;
      -- Print all attributes of each person in the list.&lt;br /&gt;
    do&lt;br /&gt;
      from&lt;br /&gt;
        a_list.start&lt;br /&gt;
      until&lt;br /&gt;
        a_list.after&lt;br /&gt;
      do &lt;br /&gt;
          -- Reading is valid on a covariant list&lt;br /&gt;
        a_list.item.print&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
end&lt;br /&gt;
 &lt;br /&gt;
class EXAMPLE&lt;br /&gt;
feature&lt;br /&gt;
  make&lt;br /&gt;
    local&lt;br /&gt;
      l_students: LIST [STUDENT]&lt;br /&gt;
      l_professors: LIST [PROFESSOR]&lt;br /&gt;
      l_person_printer: PERSON_PRINTER&lt;br /&gt;
    do&lt;br /&gt;
      create l_person_printer&lt;br /&gt;
        -- LIST [STUDENT] conforms to READ_LIST [PERSON]&lt;br /&gt;
      l_person_printer.print_all (l_students)&lt;br /&gt;
        -- LIST [PROFESSOR] conforms to READ_LIST [PERSON]&lt;br /&gt;
      l_person_printer.print_all (l_professor)&lt;br /&gt;
    end&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/e&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Comparator ===&lt;br /&gt;
&lt;br /&gt;
For the comparator example to work, the comparator class has to be declared as contravariant generic: &amp;lt;e&amp;gt;class COMPARATOR [-G]&amp;lt;/e&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;e&amp;gt;&lt;br /&gt;
class SORTER [G]&lt;br /&gt;
feature&lt;br /&gt;
  sort (a_list: LIST [G]; a_comparator: COMPARATOR [G])&lt;br /&gt;
    do&lt;br /&gt;
        -- Somewhere in the loop:&lt;br /&gt;
      a_comparator.compare (l_string_1, l_string_2)&lt;br /&gt;
    end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
class EXAMPLE&lt;br /&gt;
feature&lt;br /&gt;
  make&lt;br /&gt;
    local&lt;br /&gt;
      l_list: LIST [STRING]&lt;br /&gt;
      l_string_sorter: SORTER [STRING]&lt;br /&gt;
      l_string_comparator: COMPARATOR [STRING]&lt;br /&gt;
      l_any_comparator: COMPARATOR [ANY]&lt;br /&gt;
    do&lt;br /&gt;
        -- COMPARATOR [STRING] conforms to COMPARATOR [STRING]&lt;br /&gt;
      l_string_sorter.sort (l_list, l_string_comparator)&lt;br /&gt;
        -- COMPARATOR [ANY] conforms to COMPARATOR [STRING]&lt;br /&gt;
      l_string_sorter.sort (l_list, l_any_comparator)&lt;br /&gt;
    end&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/e&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Agents ===&lt;br /&gt;
&lt;br /&gt;
Again, to use definition-site variance you have to adapt the library design. The procedure class has to be defined as follows:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;e&amp;gt;&lt;br /&gt;
class PROCEDURE [+BASE_TYPE, -OPEN_ARGS -&amp;gt; TUPLE]&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/e&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Calling agents ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;e&amp;gt;&lt;br /&gt;
local&lt;br /&gt;
  an_agent: PROCEDURE [ANY, TUPLE [T]]&lt;br /&gt;
    -- An agent which takes an argument of type T.&lt;br /&gt;
do&lt;br /&gt;
    -- The following calls are surely permitted as the generic &lt;br /&gt;
    -- parameter in the tuple is novariant since it is not specified&lt;br /&gt;
    -- further in the procedure class.&lt;br /&gt;
  an_agent.call ([T])&lt;br /&gt;
  an_agent.call ([T, ...])&lt;br /&gt;
&lt;br /&gt;
    -- Because the tuple is novariant, the following calls are&lt;br /&gt;
    -- illegal although they would be safe.&lt;br /&gt;
  an_agent.call ([U])&lt;br /&gt;
  an_agent.call ([U, ...])&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/e&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In contrast to [[usage-site variance#Agents|usage-site variance]] you cannot express that the generic parameters of the tuple are covariant. Because of that, the call with a subtype of the actual parameter is not permitted by the type system.&lt;br /&gt;
&lt;br /&gt;
==== Assigning agents ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;e&amp;gt;&lt;br /&gt;
local&lt;br /&gt;
  an_agent: PROCEDURE [ANY, TUPLE [T]]&lt;br /&gt;
    -- An agent which takes an argument of type T.&lt;br /&gt;
do&lt;br /&gt;
  agent_empty := agent () do end --&amp;gt; PROCEDURE [ANY, TUPLE []]&lt;br /&gt;
  agent_any := agent (a: ANY) do end --&amp;gt; PROCEDURE [ANY, TUPLE [ANY]]&lt;br /&gt;
  agent_t := agent (t: T) do end --&amp;gt; PROCEDURE [ANY, TUPLE [T]]&lt;br /&gt;
  agent_u := agent (u: U) do end --&amp;gt; PROCEDURE [ANY, TUPLE [U]]&lt;br /&gt;
  agent_tt := agent (t: T; t2: T) do end --&amp;gt; PROCEDURE [ANY, TUPLE [T, T]]&lt;br /&gt;
&lt;br /&gt;
    -- This assignment is naturally allowed.&lt;br /&gt;
  an_agent := agent_t&lt;br /&gt;
&lt;br /&gt;
    -- This assignment is allowed since the tuple is declared contravariant&lt;br /&gt;
    -- and the empty tuple is an ancestor of TUPLE [T]&lt;br /&gt;
  an_agent := agent_empty&lt;br /&gt;
&lt;br /&gt;
    -- This assignment is not allowed although it would be correct. The reason &lt;br /&gt;
    -- is that TUPLE [ANY] is not an ancestor of TUPEL [T].&lt;br /&gt;
  an_agent := agent_any&lt;br /&gt;
&lt;br /&gt;
    -- The following assignments are not permitted by the solution. This is the correct&lt;br /&gt;
    -- behaviour  as you could either create a catcall by passing a T argument to the &lt;br /&gt;
    -- `agent_u' or pass the wrong number of arguments by passing a [T] tuple to the &lt;br /&gt;
    -- `agent_tt'.&lt;br /&gt;
  an_agent := agent_u&lt;br /&gt;
  an_agent := agent_tt&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/e&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Again, the fact that the generic tuple parameters are novariant causes that a safe assignment is prohibited.&lt;br /&gt;
&lt;br /&gt;
== Conclusion ==&lt;br /&gt;
&lt;br /&gt;
This solution requires that the libraries are designed in a way which separates reading and writing to generic datastructes. It allows full use of comparator objects but does not fully support agents.&lt;br /&gt;
&lt;br /&gt;
On the plus side, the client of a library does not need to put variance markers as in the [[usage-site variance]] proposal which makes the use of the solution easier for the normal programmer.&lt;/div&gt;</summary>
		<author><name>Juliant</name></author>	</entry>

	<entry>
		<id>https://dev.eiffel.com/index.php?title=DOG_proposal&amp;diff=8904</id>
		<title>DOG proposal</title>
		<link rel="alternate" type="text/html" href="https://dev.eiffel.com/index.php?title=DOG_proposal&amp;diff=8904"/>
				<updated>2007-06-24T18:41:41Z</updated>
		
		<summary type="html">&lt;p&gt;Juliant: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Category:ECMA]]&lt;br /&gt;
[[Category:Catcall]]&lt;br /&gt;
{{Research}}&lt;br /&gt;
== Introduction ==&lt;br /&gt;
&lt;br /&gt;
This solution prevents catcalls by prohibiting polymorphic calls to features which are the source of potential catcalls.&lt;br /&gt;
&lt;br /&gt;
== Syntax ==&lt;br /&gt;
&lt;br /&gt;
A new keyword &amp;quot;cat&amp;quot; (subject to change) is introduced. It can be applied in front of features and type declarations.&lt;br /&gt;
&amp;lt;e&amp;gt;&lt;br /&gt;
feature&lt;br /&gt;
  cat f (a: ANY)&lt;br /&gt;
      -- Such a feature is called a cat-feature&lt;br /&gt;
    local&lt;br /&gt;
      l: cat DOG -- Such a type is called a cat-type&lt;br /&gt;
    do&lt;br /&gt;
    end&lt;br /&gt;
&amp;lt;/e&amp;gt;&lt;br /&gt;
Features and types with the &amp;quot;cat&amp;quot; keyword will be referred to from now on as cat-features and cat-types.&lt;br /&gt;
&lt;br /&gt;
== Semantics ==&lt;br /&gt;
&lt;br /&gt;
In order to be able to redefine argument types of features covariantly and restrict the export status a feature has to be marked with the &amp;quot;cat&amp;quot; keyword. Such features can only be called on types which are declared with the &amp;quot;cat&amp;quot; keyword as well. The semantics of the &amp;quot;cat&amp;quot; keyword is that it is a monomorphic type. This is contrary to ordinary declarations which remain polymorphic. By allowing calls to &amp;quot;cat&amp;quot; features only on monomorphic types the compiler knows exactly which signature to check against. As the type cannot possibly change at runtime because of monomorphism of a cat-type the problem is avoided.&lt;br /&gt;
&lt;br /&gt;
=== Conformance rules ===&lt;br /&gt;
&lt;br /&gt;
The conformance stays the same but has one special case more: No type conforms to a cat-type except the same cat-type.&lt;br /&gt;
&amp;lt;e&amp;gt;&lt;br /&gt;
a: A&lt;br /&gt;
b: B&lt;br /&gt;
ca: cat A&lt;br /&gt;
cb: cat B&lt;br /&gt;
  -- Conform and therefore valid&lt;br /&gt;
a := a&lt;br /&gt;
a := b&lt;br /&gt;
a := ca&lt;br /&gt;
a := cb&lt;br /&gt;
b := b&lt;br /&gt;
b := cb&lt;br /&gt;
ca := ca&lt;br /&gt;
cb := cb&lt;br /&gt;
  -- Invalid (not all mentioned)&lt;br /&gt;
ca := a  -- `a' could be attached to an object of type `B'&lt;br /&gt;
ca := b  -- `ca' is monomorphic&lt;br /&gt;
&amp;lt;/e&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Examples ==&lt;br /&gt;
&lt;br /&gt;
See the [[introduction to examples]] for information about the classes used but we give enhanced versions for some classes:&lt;br /&gt;
&amp;lt;e&amp;gt;&lt;br /&gt;
class ANIMAL&lt;br /&gt;
feature&lt;br /&gt;
  cat eat (f: FOOD) do end&lt;br /&gt;
  cat sleep do end&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/e&amp;gt;&lt;br /&gt;
This is needed so that the (covariant) redefinition of the argument types of these features or the restriction of the export status is valid.&lt;br /&gt;
&lt;br /&gt;
=== Cats and dogs ===&lt;br /&gt;
&lt;br /&gt;
local&lt;br /&gt;
  a: ANIMAL&lt;br /&gt;
  ca: cat ANIMAL&lt;br /&gt;
  c: CAT&lt;br /&gt;
  cc: cat CAT&lt;br /&gt;
  d: DOG&lt;br /&gt;
  cd: cat DOG&lt;br /&gt;
  f: FOOD&lt;br /&gt;
  cf: CAT_FOOD&lt;br /&gt;
do&lt;br /&gt;
    -- Invalid calls, both features are marked as cat.&lt;br /&gt;
  a.eat (f)&lt;br /&gt;
  a.sleep&lt;br /&gt;
  c.eat (cf)&lt;br /&gt;
    -- In order to be valid their target has to be of cat-type.&lt;br /&gt;
  ca.eat (f)&lt;br /&gt;
  ca.eat (cf)&lt;br /&gt;
  ca.sleep&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
=== Generics ===&lt;br /&gt;
&lt;br /&gt;
Generics are not that obvious and clear defined in the article. However there is always one save solution.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;e&amp;gt;&lt;br /&gt;
local&lt;br /&gt;
  a: ANIMAL&lt;br /&gt;
  ca: cat ANIMAL&lt;br /&gt;
  la: LIST [ANIMAL]&lt;br /&gt;
  lca: LIST [cat ANIMAL]&lt;br /&gt;
  cla: cat LIST [ANIMAL]&lt;br /&gt;
  clca: cat LIST [cat ANIMAL]&lt;br /&gt;
  cllca: LINKED_LIST [cat ANIMAL]&lt;br /&gt;
do&lt;br /&gt;
    -- Invalid:&lt;br /&gt;
  lca := la  -- ANIMAL is not cat: The list could contain polymorphic animals&lt;br /&gt;
  lca := cla -- This is again because ANIMAL is not cat: Same reason as above.&lt;br /&gt;
  clca := lca -- This time it is because we assign to a cat LIST.&lt;br /&gt;
  clca := cla -- Here it is again because ANIMAL is not cat.&lt;br /&gt;
  clca := llca -- LINKED_LIST is not of cat-type.&lt;br /&gt;
    -- Invalid: Attachment to cat-type&lt;br /&gt;
  ca := la.item (1) -- The result is not cat-type while the target of the assignment is.&lt;br /&gt;
&lt;br /&gt;
    -- Valid:&lt;br /&gt;
  la := lca&lt;br /&gt;
  la := cla&lt;br /&gt;
  la := clca&lt;br /&gt;
  lca := clca&lt;br /&gt;
  cla := clca&lt;br /&gt;
  lca := llca -- The list can still be used polymorphic&lt;br /&gt;
    -- Valid: Attachement to non cat-type&lt;br /&gt;
  a := la.item (1)&lt;br /&gt;
  a := lca.item (1)&lt;br /&gt;
  a := cla.item (1)&lt;br /&gt;
  a := clca.item (1)&lt;br /&gt;
    -- Valid: Attachement to cat-type&lt;br /&gt;
  ca := lca.item (1)&lt;br /&gt;
  ca := clca.item (1)&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/e&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Issues ==&lt;br /&gt;
&lt;br /&gt;
=== Lacks support for generics ===&lt;br /&gt;
&lt;br /&gt;
The solution is not suited to prohibit catcalls occurring in the context of generics.&lt;br /&gt;
If you assumes that each feature of a generic containing the formal as an argument is implicit ''cat'' you can only call them on cat lists:&lt;br /&gt;
&amp;lt;e&amp;gt;&lt;br /&gt;
feature&lt;br /&gt;
  list: LIST [ANY]&lt;br /&gt;
    local&lt;br /&gt;
      ll: cat LINKED_LIST [DOG]&lt;br /&gt;
    do&lt;br /&gt;
      create ll&lt;br /&gt;
      ll.extend (create {DOG})&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
  not_so_nice&lt;br /&gt;
    local&lt;br /&gt;
      l: cat LIST [DOG]&lt;br /&gt;
      ll: cat LINKED_LIST [DOG]&lt;br /&gt;
    do&lt;br /&gt;
        -- You cannot write algorithms which fill lists implementation independent.&lt;br /&gt;
      -- INVALID: l := ll&lt;br /&gt;
        l.extend (create {DOG})&lt;br /&gt;
    end&lt;br /&gt;
&amp;lt;/e&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This is because the base type of a generic has two kind of generic features: The ordinary ones like `is_equal' or other special features and then the ones who carry the formal as an argument. The difference is that a feature like `is_equal' changes its signature from LIST [A] to LINKED_LIST [A] but `put' does not.&lt;br /&gt;
&lt;br /&gt;
=== Programmer needs foresight ===&lt;br /&gt;
&lt;br /&gt;
This solution requires the programmer to think ahead. If a feature of a library is not marked as &amp;quot;cat&amp;quot; it becomes really difficult to change it later. This is not only because the owner of library is somebody else but also because it would invalidate probably a lot of existing code.&lt;br /&gt;
&lt;br /&gt;
== Conclusion ==&lt;br /&gt;
&lt;br /&gt;
This solution is targeted to ordinary types. However, it can easily be paired with another solution [[Comparison_of_catcall_solutions#Overview_of_solutions_for_generics|specific for generics]]. They might even look the same or use partly the same keywords and form a good solution in symbiosis.&lt;/div&gt;</summary>
		<author><name>Juliant</name></author>	</entry>

	<entry>
		<id>https://dev.eiffel.com/index.php?title=Restrict_types&amp;diff=8903</id>
		<title>Restrict types</title>
		<link rel="alternate" type="text/html" href="https://dev.eiffel.com/index.php?title=Restrict_types&amp;diff=8903"/>
				<updated>2007-06-24T18:41:28Z</updated>
		
		<summary type="html">&lt;p&gt;Juliant: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Category:ECMA]]&lt;br /&gt;
[[Category:Catcall]]&lt;br /&gt;
{{Research}}&lt;br /&gt;
== Introduction ==&lt;br /&gt;
This solution uses enhancements to the type system to ensure CAT call freeness. It tackles the problem on the type basis for each entity declaration (which includes variables and generic parameters). The programmer declares a set of types and depending on the type declaration of a target of a qualified call all problematic features regarding CAT are disabled.&lt;br /&gt;
&lt;br /&gt;
A call on a target is only valid if it cannot become possibly invalid at run-time due to polymorphism and covariantly redefined features or changed export status.&lt;br /&gt;
This is achieved as the compiler checks that for all types which could be attached to a variable that all calls are valid.&lt;br /&gt;
To help the compiler the programmer '''restricts''' the set of possible types.&lt;br /&gt;
&lt;br /&gt;
== Syntax and semantic==&lt;br /&gt;
There were various proposals for syntax. They all express sets of types. Some include set operations and simplified construction by using construct to describe intervals.&lt;br /&gt;
In the end it all comes down to the fact that the notion of a type in Eiffel is enhanced to a set of types.&lt;br /&gt;
&lt;br /&gt;
The last proposal on the ECMA mailinglist is introduced here in a simplified, less formal manner:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;e&amp;gt;&lt;br /&gt;
a_type: TYPE restrict TYPE_SET&lt;br /&gt;
&amp;lt;/e&amp;gt;&lt;br /&gt;
&lt;br /&gt;
An actual type set for &amp;lt;e&amp;gt;TYPE_SET&amp;lt;/e&amp;gt; can be constructed in many different ways. This proposal includes syntactic sugar to create sets out of given intervals and includes the set operations ''union'', ''intersection'' and ''subtraction''.&lt;br /&gt;
&amp;lt;e&amp;gt;&lt;br /&gt;
ANY .. NONE             -- Fits all types&lt;br /&gt;
ANY &amp;gt;			-- Means the same&lt;br /&gt;
&amp;gt; NONE                  -- Means the same&lt;br /&gt;
T &amp;gt;                     -- T and conforming types&lt;br /&gt;
&amp;gt; T                     -- Types to which T conforms to&lt;br /&gt;
T .. U                  -- Types conforming to T and to which U conforms&lt;br /&gt;
X .. Y                  -- Types conforming to X and to which Y conforms&lt;br /&gt;
{T .. U} + {X .. Y}     -- Types that satisfy any of the preceding two conditions&lt;br /&gt;
{T .. U} - {X .. Y}     -- Types that satisfy the first of those but not the second&lt;br /&gt;
{T .. U} * {X .. Y}     -- Types that satisfy both&lt;br /&gt;
&amp;lt;/e&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Once the compiler has a set of types it computes all features which are CAT free. This relies on the fact that all types are known at compile time.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
A call on a target is only valid if it cannot become possibly invalid at run-time due to polymorphism and covariantly redefined features or changed export status.&lt;br /&gt;
This is achieved as the compiler checks that for all types which could be attached to a variable that all calls are valid.&lt;br /&gt;
To help the compiler the programmer '''restricts''' the set of possible types.&lt;br /&gt;
&lt;br /&gt;
=== Conformance rules ===&lt;br /&gt;
The conformance rule for the new introduced entity ''type-set'' is given by the subset relation:&lt;br /&gt;
&lt;br /&gt;
 T restrict S conforms to T restrict S' only if S is a subset of S'&lt;br /&gt;
&lt;br /&gt;
A few examples for some type sets help one to get started:&lt;br /&gt;
&amp;lt;e&amp;gt;&lt;br /&gt;
{ANIMAL} := {CAT} -- Does NOT conform. There is just an ANIMAL in the set!&lt;br /&gt;
&amp;lt;/e&amp;gt;&lt;br /&gt;
&amp;lt;e&amp;gt;ANIMAL .. NONE&amp;lt;/e&amp;gt; creates the set &amp;lt;e&amp;gt;{ANIMAL, CAT, DOG, ..., NONE}&amp;lt;/e&amp;gt;&lt;br /&gt;
&lt;br /&gt;
One can see now that the {CAT} is a subset of it and per definition the two sets conform:&lt;br /&gt;
&amp;lt;e&amp;gt;&lt;br /&gt;
{ANIMAL, CAT, DOG, ..., NONE} := {CAT}&lt;br /&gt;
&amp;lt;/e&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Default behavior ===&lt;br /&gt;
An important decision to be made is what the default behavior is for:&lt;br /&gt;
&amp;lt;e&amp;gt;&lt;br /&gt;
a_type: TYPE&lt;br /&gt;
&amp;lt;/e&amp;gt;&lt;br /&gt;
There are a couple of trade offs here. The possibilities are as follows:&lt;br /&gt;
* &amp;lt;e&amp;gt;TYPE .. TYPE -- monomorphic&amp;lt;/e&amp;gt;&lt;br /&gt;
* &amp;lt;e&amp;gt;TYPE .. NONE -- polymorphic&amp;lt;/e&amp;gt; &lt;br /&gt;
The choice made [[Restrict types mail|here]] is the second one: polymorphic&lt;br /&gt;
The article does not explain how exactly generic types are handled. Are generic parameters monomorphic? What are the conformance rules for generics?&lt;br /&gt;
&lt;br /&gt;
== Examples ==&lt;br /&gt;
See the [[introduction to examples]] for information about the classes used.&lt;br /&gt;
&lt;br /&gt;
=== Cats and dogs ===&lt;br /&gt;
Here is a list of valid and invalid assignments. A valid assignment in this context means that the right type conforms to the left type of the assignment.&lt;br /&gt;
&amp;lt;e&amp;gt;&lt;br /&gt;
local&lt;br /&gt;
  zoo_member: ANIMAL  -- Polymorph is default: The type set contains any descendant of ANIMAL.&lt;br /&gt;
  animal: ANIMAL restrict ANIMAL&lt;br /&gt;
  cat: CAT restrict CAT&lt;br /&gt;
  dog: DOG restrict DOG&lt;br /&gt;
  animal_not_hungry: ANIMAL restrict ANIMAL .. NONE  -- One cannot call `eat' as it is covariantly redefined in CAT&lt;br /&gt;
  animal_only_eating_cat_food: ANIMAL restrict ANIMAL .. CAT  -- They can eat, but only cat food.&lt;br /&gt;
&lt;br /&gt;
  food: FOOD restrict FOOD&lt;br /&gt;
        -- Food&lt;br /&gt;
  cat_food: CAT_FOOD restrict CAT_FOOD&lt;br /&gt;
        -- Cat food&lt;br /&gt;
do&lt;br /&gt;
  animal := zoo_member -- Invalid! Default for ANIMAL is ANIMAL .. NONE, this is not a subset of {ANIMAL}&lt;br /&gt;
  animal := cat -- Invalid! {CAT} is not a subset of {ANIMAL}&lt;br /&gt;
  animal := dog -- Invalid! Rejected out of the same reason as the cat,&lt;br /&gt;
                -- but to assign the dog would be save.&lt;br /&gt;
  animal_not_hungry := cat -- Valid&lt;br /&gt;
  animal_not_hungry := dog -- Valid&lt;br /&gt;
  animal_only_eating_cat_food := cat -- Valid&lt;br /&gt;
  animal_only_eating_cat_food := dog -- Invalid, but would be save for this example.&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/e&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Generics ===&lt;br /&gt;
This mechanism partly describes the handling of generic types. The only major difference between the version presented here and the one in the wiki is that &amp;lt;e&amp;gt;la := lc&amp;lt;/e&amp;gt; was moved to the invalid cases.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;e&amp;gt;&lt;br /&gt;
  lc: LIST [CAT]; lo: LIST [OCTOPUS]&lt;br /&gt;
  la: LIST [ANIMAL]&lt;br /&gt;
  lac: LIST [ANIMAL restrict {CAT}]&lt;br /&gt;
  laa: LIST [ANIMAL restrict] -- Monomorphic list&lt;br /&gt;
&lt;br /&gt;
    -- All OK.&lt;br /&gt;
  lac := lc ; la := lo&lt;br /&gt;
&lt;br /&gt;
  -- INVALD: la := lc ; laa := la ; laa := lac ; laa := lc ; laa := lo ; lac := lo&lt;br /&gt;
    &lt;br /&gt;
&amp;lt;/e&amp;gt;&lt;br /&gt;
&amp;lt;e&amp;gt;&lt;br /&gt;
    -- OK&lt;br /&gt;
  lac.item.eat (cf) &lt;br /&gt;
&lt;br /&gt;
-- INVALID:	lac.item.eat (f)&lt;br /&gt;
-- INVALID:	la.item.eat (f)&lt;br /&gt;
-- INVALID:	la.item.eat (cf)	-- Becomes valid if OCTOPUS is removed from system&lt;br /&gt;
&amp;lt;/e&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Issues ==&lt;br /&gt;
=== Void and NONE ===&lt;br /&gt;
Note that the fact that ''Void'' is of type &amp;lt;e&amp;gt;NONE&amp;lt;/e&amp;gt; does not fit into the conformance rules.&amp;lt;br/&amp;gt;&lt;br /&gt;
If we check this code with the currently given rules it would be rejected:&lt;br /&gt;
&amp;lt;e&amp;gt;&lt;br /&gt;
a_t: T .. T&lt;br /&gt;
a_t := Void&lt;br /&gt;
&amp;lt;/e&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;e&amp;gt;{NONE}&amp;lt;/e&amp;gt; is no subset of &amp;lt;e&amp;gt;{T}&amp;lt;/e&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Lists ===&lt;br /&gt;
There are some interesting cases:&lt;br /&gt;
&amp;lt;e&amp;gt;&lt;br /&gt;
lla: LIST [LIST [ANIMAL]] restrict {LIST [LIST [ANIMAL]] .. LIST [LIST [CAT]]}&lt;br /&gt;
&amp;lt;/e&amp;gt;  &lt;br /&gt;
Now we apply the definition of the interval using the current conformance rules for types given by the ECMA standard.&lt;br /&gt;
&amp;lt;e&amp;gt;&lt;br /&gt;
T .. U                  -- Types conforming to T and to which U conforms&lt;br /&gt;
&amp;lt;/e&amp;gt;&lt;br /&gt;
The following set is described by the interval above:&lt;br /&gt;
&amp;lt;e&amp;gt;&lt;br /&gt;
{LIST [LIST [ANIMAL]], LIST [LIST [CAT]]}&lt;br /&gt;
&amp;lt;/e&amp;gt;&lt;br /&gt;
So we are allowed to assign a &amp;lt;e&amp;gt;LIST [LIST [CAT]]&amp;lt;/e&amp;gt; to `l'.&amp;lt;br/&amp;gt;&lt;br /&gt;
Now the result type of item is &amp;lt;e&amp;gt;LIST [ANIMAL]&amp;lt;/e&amp;gt;:&lt;br /&gt;
&amp;lt;e&amp;gt;&lt;br /&gt;
lla.item (1) -- LIST [ANIMAL]&lt;br /&gt;
&amp;lt;/e&amp;gt;&lt;br /&gt;
But then one could produce a CAT call like this:&lt;br /&gt;
&amp;lt;e&amp;gt;&lt;br /&gt;
lla.item (1).put (create {DOG})&lt;br /&gt;
&amp;lt;/e&amp;gt;&lt;br /&gt;
Here the whole code:&lt;br /&gt;
&amp;lt;e&amp;gt;&lt;br /&gt;
local&lt;br /&gt;
  lla: LIST [LIST [ANIMAL]] restrict {LIST [LIST [ANIMAL]] .. LIST [LIST [CAT]]}&lt;br /&gt;
  llc: LIST [LIST [CAT]]&lt;br /&gt;
  la: LIST [ANIMAL]&lt;br /&gt;
do&lt;br /&gt;
  create llc...&lt;br /&gt;
  lla := llc -- Type of `llc' is in type set of `lla'&lt;br /&gt;
  la := lla.item (1) -- Dynamic type of la is LIST [CAT]&lt;br /&gt;
  la.put (create {DOG}) -- Now there is an instance of DOG in LIST [CAT]&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/e&amp;gt;&lt;br /&gt;
This is indeed bad because cats can have features which dogs do not have, calling them would lead to system failure.&lt;br /&gt;
We might try to fix this by changing the conformance for generics and the rule how intervals are generated.&lt;br /&gt;
&lt;br /&gt;
== Conclusion ==&lt;br /&gt;
The solution in its current state solves CAT calls only for ordinary types. But it might be possible to enhance it to solve generic types as well.&lt;/div&gt;</summary>
		<author><name>Juliant</name></author>	</entry>

	<entry>
		<id>https://dev.eiffel.com/index.php?title=Usage-site_variance&amp;diff=8902</id>
		<title>Usage-site variance</title>
		<link rel="alternate" type="text/html" href="https://dev.eiffel.com/index.php?title=Usage-site_variance&amp;diff=8902"/>
				<updated>2007-06-24T18:40:45Z</updated>
		
		<summary type="html">&lt;p&gt;Juliant: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Category:ECMA]]&lt;br /&gt;
[[Category:Catcall]]&lt;br /&gt;
{{Research}}&lt;br /&gt;
== Introduction ==&lt;br /&gt;
&lt;br /&gt;
The usage-site variance allows the programmer to choose which kind of variance he wants to use when a generic derivation is declared. This allows to use every generic as novariant, covariant or contravariant in contrast to the [[definition-site variance]] where it is set in the class definition.&lt;br /&gt;
&lt;br /&gt;
== Syntax ==&lt;br /&gt;
&lt;br /&gt;
The syntax used here to specify the variance of a generic is simple and may be changed to something more verbose but also clearer:&lt;br /&gt;
&lt;br /&gt;
* To specify a novariant generic, the normal syntax can be used: &amp;lt;e&amp;gt;LIST [ANY]&amp;lt;/e&amp;gt;&lt;br /&gt;
* To specify a covariant generic, we use a plus sign: &amp;lt;e&amp;gt;LIST [+ANY]&amp;lt;/e&amp;gt;&lt;br /&gt;
* To specify a contravariant generic, we use a minus sign: &amp;lt;e&amp;gt;LIST [-ANY]&amp;lt;/e&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Semantics ==&lt;br /&gt;
&lt;br /&gt;
See the [[introduction to examples]] for information about the classes used.&lt;br /&gt;
&lt;br /&gt;
=== Conformance rules ===&lt;br /&gt;
&lt;br /&gt;
Depending on the variance of the generic, the conformance rules differ:&lt;br /&gt;
&lt;br /&gt;
* A generic conforms to a novariant generic if it has the exact same generic parameter. Thus &amp;lt;e&amp;gt;LIST [T]&amp;lt;/e&amp;gt; only conforms to &amp;lt;e&amp;gt;LIST [T]&amp;lt;/e&amp;gt;. Note that &amp;lt;e&amp;gt;LINKED_LIST [T]&amp;lt;/e&amp;gt; also conforms to &amp;lt;e&amp;gt;LIST [T]&amp;lt;/e&amp;gt; as long as the generic parameter matches.&lt;br /&gt;
* A generic conforms to a covariant generic if its generic parameter conforms to the generic parameter of the covariant generic. Thus &amp;lt;e&amp;gt;LIST [U]&amp;lt;/e&amp;gt; conforms to &amp;lt;e&amp;gt;LIST [+T]&amp;lt;/e&amp;gt;.&lt;br /&gt;
* A generic conforms to a contravariant generic if its generic parameter is a parent of the generic parameter of the contravariant generic. Thus &amp;lt;e&amp;gt;LIST [T]&amp;lt;/e&amp;gt; conforms to &amp;lt;e&amp;gt;LIST [-U]&amp;lt;/e&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
For the conformance of tuples, we keep that a tuple with more elements conforms to a tuple with less elements as long as the common elements conform:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;e&amp;gt;TUPLE [T, U]&amp;lt;/e&amp;gt; conforms to &amp;lt;e&amp;gt;TUPLE [T]&amp;lt;/e&amp;gt;&lt;br /&gt;
* &amp;lt;e&amp;gt;TUPLE [U, U]&amp;lt;/e&amp;gt; conforms to &amp;lt;e&amp;gt;TUPLE [+T]&amp;lt;/e&amp;gt;&lt;br /&gt;
* &amp;lt;e&amp;gt;TUPLE [T, U]&amp;lt;/e&amp;gt; conforms to &amp;lt;e&amp;gt;TUPLE [-U]&amp;lt;/e&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Applicable features ===&lt;br /&gt;
&lt;br /&gt;
Depending on the variance of the generic, the applicable features differ:&lt;br /&gt;
&lt;br /&gt;
* On a novariant generic, all features can be used.&lt;br /&gt;
* On a covariant generic, only features which have the formal generic as a result type can be used. If the formal generic appears in an argument this feature is invalid.&lt;br /&gt;
* On a contravariant generic, only feature which have the formal generc as an argument type can be used. If the formal generic appears as a result type this feature is invalid.&lt;br /&gt;
&lt;br /&gt;
== Examples ==&lt;br /&gt;
&lt;br /&gt;
See the [[introduction to examples]] for information about the classes used.&lt;br /&gt;
&lt;br /&gt;
=== A simple generic algorithm ===&lt;br /&gt;
&lt;br /&gt;
It is easy to declare an algorithm over generics as long as only read-access is needed. Just declare input to the algorithm as covariant list.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;e&amp;gt;&lt;br /&gt;
class PERSON_PRINTER&lt;br /&gt;
feature&lt;br /&gt;
  print_all (a_list: LIST [+PERSON])&lt;br /&gt;
      -- Print all attributes of each person in the list.&lt;br /&gt;
    do&lt;br /&gt;
      from&lt;br /&gt;
        a_list.start&lt;br /&gt;
      until&lt;br /&gt;
        a_list.after&lt;br /&gt;
      do &lt;br /&gt;
          -- Reading is valid on a covariant list&lt;br /&gt;
        a_list.item.print&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
end&lt;br /&gt;
 &lt;br /&gt;
class EXAMPLE&lt;br /&gt;
feature&lt;br /&gt;
  make&lt;br /&gt;
    local&lt;br /&gt;
      l_students: LIST [STUDENT]&lt;br /&gt;
      l_professors: LIST [PROFESSOR]&lt;br /&gt;
      l_person_printer: PERSON_PRINTER&lt;br /&gt;
    do&lt;br /&gt;
      create l_person_printer&lt;br /&gt;
        -- LIST [STUDENT] conforms to LIST [+PERSON]&lt;br /&gt;
      l_person_printer.print_all (l_students)&lt;br /&gt;
        -- LIST [PROFESSPR] conforms to LIST [+PERSON]&lt;br /&gt;
      l_person_printer.print_all (l_professor)&lt;br /&gt;
    end&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/e&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Comparator ===&lt;br /&gt;
&lt;br /&gt;
In the example of sorting a list with a comparator, contravariant generics can be used. Due to the use of &amp;lt;e&amp;gt;COMPARATOR [-G]&amp;lt;/e&amp;gt; when sorting a &amp;lt;e&amp;gt;LIST [G]&amp;lt;/e&amp;gt;, we allow to use a comparator which can sort more generally than just objects of type &amp;lt;e&amp;gt;G&amp;lt;/e&amp;gt;. This allows to use a comparator for &amp;lt;e&amp;gt;ANY&amp;lt;/e&amp;gt; objects to sort a list of strings.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;e&amp;gt;&lt;br /&gt;
class SORTER [G]&lt;br /&gt;
feature&lt;br /&gt;
  sort (a_list: LIST [G]; a_comparator: COMPARATOR [-G])&lt;br /&gt;
    do&lt;br /&gt;
        -- Somewhere in the loop:&lt;br /&gt;
      a_comparator.compare (l_string_1, l_string_2)&lt;br /&gt;
    end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
class EXAMPLE&lt;br /&gt;
feature&lt;br /&gt;
  make&lt;br /&gt;
    local&lt;br /&gt;
      l_list: LIST [STRING]&lt;br /&gt;
      l_string_sorter: SORTER [STRING]&lt;br /&gt;
      l_string_comparator: COMPARATOR [STRING]&lt;br /&gt;
      l_any_comparator: COMPARATOR [ANY]&lt;br /&gt;
    do&lt;br /&gt;
        -- COMPARATOR [STRING] conforms to COMPARATOR [-STRING]&lt;br /&gt;
      l_string_sorter.sort (l_list, l_string_comparator)&lt;br /&gt;
        -- COMPARATOR [ANY] conforms to COMPARATOR [-STRING]&lt;br /&gt;
      l_string_sorter.sort (l_list, l_any_comparator)&lt;br /&gt;
    end&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/e&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Agents ===&lt;br /&gt;
&lt;br /&gt;
For agents, we will look at an example with the type &amp;lt;e&amp;gt;T&amp;lt;/e&amp;gt; and a subtype &amp;lt;e&amp;gt;U&amp;lt;/e&amp;gt;. We will see an agent declaration and then check which arguments that are allowed:&lt;br /&gt;
&lt;br /&gt;
==== Calling agents ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;e&amp;gt;&lt;br /&gt;
local&lt;br /&gt;
  an_agent: PROCEDURE [+ANY, -TUPLE [+T]]&lt;br /&gt;
    -- An agent which takes an argument of type T.&lt;br /&gt;
do&lt;br /&gt;
    -- The following calls are surely permitted (and also correct) since&lt;br /&gt;
    -- the tuple generic inside the tuple is covariant and thus allows&lt;br /&gt;
    -- the tuple of type U to be passed.&lt;br /&gt;
  an_agent.call ([T])&lt;br /&gt;
  an_agent.call ([U])&lt;br /&gt;
&lt;br /&gt;
    -- Due to the tuple conformance, the following calls are also&lt;br /&gt;
    -- permitted. Note that they are both correct.&lt;br /&gt;
  an_agent.call ([T, ...])&lt;br /&gt;
  an_agent.call ([U, ...])&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/e&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We see that this solution allows the full range of applicable arguments for calling agents.&lt;br /&gt;
&lt;br /&gt;
==== Assigning agents ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;e&amp;gt;&lt;br /&gt;
local&lt;br /&gt;
  an_agent: PROCEDURE [+ANY, -TUPLE [+T]]&lt;br /&gt;
    -- An agent which takes an argument of type T.&lt;br /&gt;
do&lt;br /&gt;
  agent_empty := agent () do end --&amp;gt; PROCEDURE [ANY, TUPLE []]&lt;br /&gt;
  agent_any := agent (a: ANY) do end --&amp;gt; PROCEDURE [ANY, TUPLE [+ANY]]&lt;br /&gt;
  agent_t := agent (t: T) do end --&amp;gt; PROCEDURE [ANY, TUPLE [+T]]&lt;br /&gt;
  agent_u := agent (u: U) do end --&amp;gt; PROCEDURE [ANY, TUPLE [+U]]&lt;br /&gt;
  agent_tt := agent (t: T; t2: T) do end --&amp;gt; PROCEDURE [ANY, TUPLE [+T, +T]]&lt;br /&gt;
&lt;br /&gt;
    -- This assignment is naturally allowed.&lt;br /&gt;
  an_agent := agent_t&lt;br /&gt;
&lt;br /&gt;
    -- This assignment is allowed since the tuple is declared contravariant&lt;br /&gt;
    -- and the empty tuple is an ancestor of TUPLE [+T]&lt;br /&gt;
  an_agent := agent_empty&lt;br /&gt;
&lt;br /&gt;
    -- This assignment is allowed and correct. The reason is that TUPLE [+ANY]&lt;br /&gt;
    -- is an ancestor of TUPLE [+T].&lt;br /&gt;
  an_agent := agent_any&lt;br /&gt;
&lt;br /&gt;
    -- The following assignments are not permitted by the solution. This is the correct&lt;br /&gt;
    -- behaviour  as you could either create a catcall by passing a T argument to the &lt;br /&gt;
    -- `agent_u' or pass the wrong number of arguments by passing a [T] tuple to the &lt;br /&gt;
    -- `agent_tt'.&lt;br /&gt;
  an_agent := agent_u&lt;br /&gt;
  an_agent := agent_tt&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/e&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We see that this solution allows all possible agents to be assigned.&lt;br /&gt;
&lt;br /&gt;
Since declaring an agent can be difficult (where did I need to put the &amp;quot;+&amp;quot; and the &amp;quot;-&amp;quot;?), an alternate [[Agent syntax|syntax for agents]] could be useful where the compiler can derive the correct type for an agent.&lt;br /&gt;
&lt;br /&gt;
==== Vision 2 Example ====&lt;br /&gt;
A field which makes heavy use of agents and benefits a lot of them is ''event driven programming''. With the current agent mechanism the programmer is sometimes forced to use a hack to circumvent the type checker in order to gain flexibility.&lt;br /&gt;
&lt;br /&gt;
The following code is taken from &amp;lt;e&amp;gt;EV_PND_MOTION_ACTION_SEQUENCE&amp;lt;/e&amp;gt;. Here we gain the flexibility that an agent which listens to the event does not have to be a feature which takes all the data provided if the event occurs. Maybe the programmer is just interested in the fact that an actual event occurred and not in the data about it.&lt;br /&gt;
&amp;lt;e&amp;gt;&lt;br /&gt;
  force_extend (action: PROCEDURE [ANY, TUPLE]) is&lt;br /&gt;
      -- Extend without type checking. Not type save! Use on your own risk!&lt;br /&gt;
    do&lt;br /&gt;
      extend (agent wrapper (?, ?, ?, action))&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
  wrapper (an_x, a_y: INTEGER; a_pick_and_dropable: EV_ABSTRACT_PICK_AND_DROPABLE;&lt;br /&gt;
        action: PROCEDURE [ANY, TUPLE])&lt;br /&gt;
        -- Use this to circumvent tuple type checking. (at your own risk!)&lt;br /&gt;
        -- Calls `action' passing all other arguments.&lt;br /&gt;
    do&lt;br /&gt;
      action.call ([an_x, a_y, a_pick_and_dropable])&lt;br /&gt;
    end&lt;br /&gt;
&amp;lt;/e&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If this solution is built into Eiffel the designer of Vision2 would do a small change in &amp;lt;e&amp;gt;ACTION_SEQUENCE&amp;lt;/e&amp;gt;. The changes makes sure that we can accept agents to features defined in ancestors of &amp;lt;e&amp;gt;ANY&amp;lt;/e&amp;gt; (therefore the &amp;lt;e&amp;gt;+ANY&amp;lt;/e&amp;gt;) and that we accept agents which are not interested in all data but just (possibly) take parts of it (therefore &amp;lt;e&amp;gt;-EVENT_DATA&amp;lt;/e&amp;gt;).&lt;br /&gt;
&amp;lt;e&amp;gt;&lt;br /&gt;
class&lt;br /&gt;
  ACTION_SEQUENCE [EVENT_DATA -&amp;gt; TUPLE create default_create end]&lt;br /&gt;
inherit&lt;br /&gt;
  ARRAYED_LIST [PROCEDURE [+ANY, -EVENT_DATA]]&lt;br /&gt;
  -- old ARRAYED_LIST [PROCEDURE [ANY, EVENT_DATA]]&lt;br /&gt;
&amp;lt;/e&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The wrapper code can be removed from &amp;lt;e&amp;gt;EV_PND_MOTION_ACTION_SEQUENCE&amp;lt;/e&amp;gt; and we also change one line. This change empowers the system to accept descendants of &amp;lt;e&amp;gt;EV_ABSTRACT_PICK_AND_DROPABLE&amp;lt;/e&amp;gt; as event data. The two integers do not need be marked covariantly as they are frozen and no descendants exist for them.&lt;br /&gt;
&amp;lt;e&amp;gt;&lt;br /&gt;
class&lt;br /&gt;
  EV_PND_MOTION_ACTION_SEQUENCE&lt;br /&gt;
&lt;br /&gt;
inherit&lt;br /&gt;
    -- old EV_ACTION_SEQUENCE [TUPLE [x: INTEGER; y: INTEGER; pick_and_dropable: EV_ABSTRACT_PICK_AND_DROPABLE]]&lt;br /&gt;
  EV_ACTION_SEQUENCE [TUPLE [x: INTEGER; y: INTEGER; pick_and_dropable: +EV_ABSTRACT_PICK_AND_DROPABLE]]&lt;br /&gt;
&amp;lt;/e&amp;gt;&lt;br /&gt;
Now with this the actual signature of &amp;lt;e&amp;gt;{EV_PND_MOTION_ACTION_SEQUENCE}.extend&amp;lt;/e&amp;gt; looks like this:&lt;br /&gt;
&amp;lt;e&amp;gt;&lt;br /&gt;
  extend (v: PROCEDURE [ANY, -TUPLE [x: INTEGER_32; y: INTEGER_32; +pick_and_dropable: EV_ABSTRACT_PICK_AND_DROPABLE]]&lt;br /&gt;
&amp;lt;/e&amp;gt;&lt;br /&gt;
&lt;br /&gt;
For the sake of completeness the signature of &amp;lt;e&amp;gt;{EV_PND_MOTION_ACTION_SEQUENCE}.call&amp;lt;/e&amp;gt;. Note again that the the field `pick_and_dropable' is covariant allowing to call the event with tuples containing descendants of &amp;lt;e&amp;gt;EV_ABSTRACT_PICK_AND_DROPABLE&amp;lt;/e&amp;gt;.&lt;br /&gt;
&amp;lt;e&amp;gt;&lt;br /&gt;
  call (event_data: TUPLE [x: INTEGER_32; y: INTEGER_32; pick_and_dropable: +EV_ABSTRACT_PICK_AND_DROPABLE])&lt;br /&gt;
&amp;lt;/e&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Conclusion ==&lt;br /&gt;
&lt;br /&gt;
The usage-site variance is a mechanism which allows both expressive and type-safe generics. It can model agents and comparator types correctly.&lt;/div&gt;</summary>
		<author><name>Juliant</name></author>	</entry>

	<entry>
		<id>https://dev.eiffel.com/index.php?title=Novariance&amp;diff=8901</id>
		<title>Novariance</title>
		<link rel="alternate" type="text/html" href="https://dev.eiffel.com/index.php?title=Novariance&amp;diff=8901"/>
				<updated>2007-06-24T18:40:20Z</updated>
		
		<summary type="html">&lt;p&gt;Juliant: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Category:ECMA]]&lt;br /&gt;
[[Category:Catcall]]&lt;br /&gt;
{{Research}}&lt;br /&gt;
== Introduction ==&lt;br /&gt;
&lt;br /&gt;
Novariance can be looked at for non-generics and generics:&lt;br /&gt;
&lt;br /&gt;
* For non-generics, it just disallows covariant redeclaration of feature arguments. Since a covariant feature redeclaration is actually a strengthening of the precondition - strengthening of the type - the safest way is to disallow it. Also it is not really consistent in allowing strengthening of the precondition on the type system level but not on normal preconditions.&lt;br /&gt;
&lt;br /&gt;
* For generics, you know from the beginning that for two different generic derivations of the same type, the generic arguments of features will differ. This is an inherent property of generics and you cannot disallow the change of type in the arguments. But again, since this is in general a strengthening of the precondition (from LIST [ANY] to LIST [STRING]) the direct solution is to disallow assignments between these types and thus removing conformance between generic derivations based on the conformance of the generic parameter. Conformance is only available on the base type if the generic parameters match exactly.&lt;br /&gt;
&lt;br /&gt;
== Syntax ==&lt;br /&gt;
&lt;br /&gt;
No new syntax is necessary.&lt;br /&gt;
&lt;br /&gt;
== Semantics ==&lt;br /&gt;
&lt;br /&gt;
The change in semantics as described above is:&lt;br /&gt;
&lt;br /&gt;
* Covariant redefinition of feature arguments is not allowed.&lt;br /&gt;
* Generics only conform if the base types conform and the generic parameters are exactly the same.&lt;br /&gt;
&lt;br /&gt;
== Examples ==&lt;br /&gt;
&lt;br /&gt;
See the [[introduction to examples]] for information about the classes used.&lt;br /&gt;
&lt;br /&gt;
=== Cat ===&lt;br /&gt;
&lt;br /&gt;
To see how the ''CAT'' example can be modeled without covariance, see the article about [http://dev.eiffel.com/Covariance_through_renaming covariance through renaming].&lt;br /&gt;
&lt;br /&gt;
=== Agents ===&lt;br /&gt;
&lt;br /&gt;
For agents, we will look at an example with the type &amp;lt;e&amp;gt;T&amp;lt;/e&amp;gt; and a subtype &amp;lt;e&amp;gt;U&amp;lt;/e&amp;gt;. We will see an agent declaration and then check which arguments that are allowed:&lt;br /&gt;
&lt;br /&gt;
==== Calling agents ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;e&amp;gt;&lt;br /&gt;
local&lt;br /&gt;
  an_agent: PROCEDURE [ANY, TUPLE [T]]&lt;br /&gt;
    -- An agent which takes an argument of type T.&lt;br /&gt;
do&lt;br /&gt;
&lt;br /&gt;
    -- In the case of novariant generics, the only permitted call is&lt;br /&gt;
  an_agent.call ([T])&lt;br /&gt;
&lt;br /&gt;
    -- None of the follwing calls is permitted, although it would be safe to &lt;br /&gt;
    -- pass a tuple with more arguments or a tuple which consists of subtypes&lt;br /&gt;
    -- of the required argument.&lt;br /&gt;
  an_agent.call ([T, ...])&lt;br /&gt;
  an_agent.call ([U])&lt;br /&gt;
  an_agent.call ([U, ...])&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/e&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The observations made are that it is not possible to pass an argument which has a different type than the exact required argument. This means that if you want to pass an argument of type &amp;lt;e&amp;gt;U&amp;lt;/e&amp;gt; to an agent which requires an argument &amp;lt;e&amp;gt;T&amp;lt;/e&amp;gt; you have to do an assignment to a variable of type &amp;lt;e&amp;gt;T&amp;lt;/e&amp;gt; first and then pass this variable instead or use the adapt routine of the TYPE class, ie {T} [U].&lt;br /&gt;
&lt;br /&gt;
==== Assigning agents ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;e&amp;gt;&lt;br /&gt;
local&lt;br /&gt;
  an_agent: PROCEDURE [ANY, TUPLE [T]]&lt;br /&gt;
    -- An agent which takes an argument of type T.&lt;br /&gt;
do&lt;br /&gt;
  agent_empty := agent () do end --&amp;gt; PROCEDURE [ANY, TUPLE []]&lt;br /&gt;
  agent_any := agent (a: ANY) do end --&amp;gt; PROCEDURE [ANY, TUPLE [ANY]]&lt;br /&gt;
  agent_t := agent (t: T) do end --&amp;gt; PROCEDURE [ANY, TUPLE [T]]&lt;br /&gt;
  agent_u := agent (u: U) do end --&amp;gt; PROCEDURE [ANY, TUPLE [U]]&lt;br /&gt;
  agent_tt := agent (t: T; t: T) do end --&amp;gt; PROCEDURE [ANY, TUPLE [T, T]]&lt;br /&gt;
&lt;br /&gt;
    -- The only legal assignment is an agent with the exact same generic parameters.&lt;br /&gt;
  an_agent := agent_t&lt;br /&gt;
&lt;br /&gt;
    -- None of the follwing assignments is permitted, although it would be safe&lt;br /&gt;
    -- to do so. The `empty_agent' would just discard the T argument passed, and the&lt;br /&gt;
    -- `any_agent' also works if a T is passed.&lt;br /&gt;
  an_agent := agent_empty&lt;br /&gt;
  an_agent := agent_any&lt;br /&gt;
&lt;br /&gt;
    -- The following assignments are not permitted by the solution. This is the correct&lt;br /&gt;
    -- behaviour  as you could either create a catcall by passing a T argument to the &lt;br /&gt;
    -- `agent_u' or pass the wrong number of arguments by passing a [T] tuple to the &lt;br /&gt;
    -- `agent_tt'.&lt;br /&gt;
  an_agent := agent_u&lt;br /&gt;
  an_agent := agent_tt&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/e&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Again, not all assignments which would be safe are allowed by the type system.&lt;br /&gt;
&lt;br /&gt;
== Conclusion ==&lt;br /&gt;
&lt;br /&gt;
In the non-generic case this solution limits the direct modeling ability as you cannot express covariant changes in the arguments. Since covariant redefinition is a precondition strengthening this can be justified on a mathematical basis, especially since covariant argument redefinition can be simulated through renaming.&lt;br /&gt;
&lt;br /&gt;
In the generic case the possibilities are severely limited. It is not possible to use a list with a more general type even for reading (e.g. LIST [ANY]) without copying all elements over from a more specialized list (e.g. LIST [STRING]).&lt;/div&gt;</summary>
		<author><name>Juliant</name></author>	</entry>

	<entry>
		<id>https://dev.eiffel.com/index.php?title=Template:Research&amp;diff=8900</id>
		<title>Template:Research</title>
		<link rel="alternate" type="text/html" href="https://dev.eiffel.com/index.php?title=Template:Research&amp;diff=8900"/>
				<updated>2007-06-24T18:40:01Z</updated>
		
		<summary type="html">&lt;p&gt;Juliant: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;p style=&amp;quot;margin-left: 30px; margin-right: 30px; border: 1px solid #000; padding: 5px; background-color: #ffe; color: black;&amp;quot;&amp;gt;'''Research:''' This page describes research about Eiffel, not the actual language specification.&amp;lt;/p&amp;gt;&lt;/div&gt;</summary>
		<author><name>Juliant</name></author>	</entry>

	<entry>
		<id>https://dev.eiffel.com/index.php?title=Comparison_of_catcall_solutions&amp;diff=8891</id>
		<title>Comparison of catcall solutions</title>
		<link rel="alternate" type="text/html" href="https://dev.eiffel.com/index.php?title=Comparison_of_catcall_solutions&amp;diff=8891"/>
				<updated>2007-06-24T02:18:12Z</updated>
		
		<summary type="html">&lt;p&gt;Juliant: /* General remarks */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Category:ECMA]]&lt;br /&gt;
[[Category:Catcall]]&lt;br /&gt;
== Motivation ==&lt;br /&gt;
&lt;br /&gt;
By allowing covariant feature redefinition and hiding of features, the Eiffel language introduces the problem of catcalls (Changed Availability or Type). Currently the ECMA Eiffel standard does not specify how the occurrence of catcalls should be statically rejected.&lt;br /&gt;
&lt;br /&gt;
The purpose of this document is to show a comparison between different proposals on how to handle the issue of statically preventing catcalls.&lt;br /&gt;
&lt;br /&gt;
== Criteria for a solution ==&lt;br /&gt;
&lt;br /&gt;
To be able to judge a solution we use the following criteria which we consider as important:&lt;br /&gt;
&lt;br /&gt;
; Syntax overhead : How much syntax will be added to the language in order to express safe covariance and generics?&lt;br /&gt;
; Covariance on non-generic types : Are covariant argument redefinitions addressed in the solution? How does the programmer express it?&lt;br /&gt;
; Export status restrictions : Is restriction of export status addressed in the solution? How does the programmer express it?&lt;br /&gt;
; Use of generic types : How is conformance of generics? Are catcalls for generics addressed in the solution? How does the programmer express it? Can generics be used as now or are there restrictions?&lt;br /&gt;
:; Agents : Can agents be modeled with the solution while being type safe and expressive?&lt;br /&gt;
:; Comparator : Can comparator types be modeled with the solution while being type safe and expressive?&lt;br /&gt;
; Complexity of the compiler check : Is it just a matter of doing one check or several?&lt;br /&gt;
; Complexity of the runtime : Does the runtime need more information to do assignment attempts or object tests?&lt;br /&gt;
; Whole-system analysis : Is a whole-system analysis necessary?&lt;br /&gt;
; Dynamic class and type loading : Is it safe to dynamically load new classes at runtime and instantiate new types?&lt;br /&gt;
; Backward compatibility : Is the solution backward compatible to existing source code?&lt;br /&gt;
:; Applicable per cluster : Can the solution be applied on a per cluster basis?&lt;br /&gt;
; Support of compiler/IDE : Can the compiler/IDE help in updating existing source code? How?&lt;br /&gt;
&lt;br /&gt;
== General remarks ==&lt;br /&gt;
&lt;br /&gt;
=== Checking feature calls ===&lt;br /&gt;
&lt;br /&gt;
As the ''Single-level Call rule'' (8.25.3, VUSC) describes, a feature call is only valid if it is valid for every type in the dynamic type set. A simple solution would be that every feature call has to be checked for all possible descendants of the static target type. If this check is performed on a system, it will catch all catcalls - but also report false positives.&lt;br /&gt;
&lt;br /&gt;
Some of the proposed solutions try to address this problem by finding a better approximation to the dynamic type set so that the false positives can be ruled out.&lt;br /&gt;
&lt;br /&gt;
In general this is problematic as it requires a whole-system analysis, thus preventing the dynamic loading of new classes at run-time. The reason for this is that it is not known at compile time which features will be covariantly redefined by dynamically loaded classes.&lt;br /&gt;
&lt;br /&gt;
This is only the case with non-generic types. For generics, it is known at compile time that all features containing a formal in the parameter list can be treated as covariantly redefined and corresponding precautions can be implemented via the type system and conformance rules which allow to load even generic types at run-time.&lt;br /&gt;
&lt;br /&gt;
By the way, Eiffel Software has started to [[Single level call rule implementation|implement the basis of the ''single-level call rule'']] in it's Eiffel compiler. It is work in progress which revealed some implementation problems.&lt;br /&gt;
&lt;br /&gt;
=== Generic vs. non-generic covariance ===&lt;br /&gt;
&lt;br /&gt;
We can distinguish two different kinds of covariant argument redefinition:&lt;br /&gt;
&lt;br /&gt;
* When a generic type is derived, the formal generic parameters will be replaced by the actual generic parameters. Given the current conformance rules for generics, this can be seen as a covariant redefinition for all features which contain a formal generic as an argument. A simple example is the change from &amp;lt;e&amp;gt;LIST [ANY]&amp;lt;/e&amp;gt; to &amp;lt;e&amp;gt;LIST [INTEGER]&amp;lt;/e&amp;gt; where the feature &amp;lt;e&amp;gt;put&amp;lt;/e&amp;gt; changes signature from &amp;lt;e&amp;gt;ANY&amp;lt;/e&amp;gt; to &amp;lt;e&amp;gt;INTEGER&amp;lt;/e&amp;gt;.&lt;br /&gt;
* In the non-generic case, covariance happens for certain anchored type declarations and in the case of explicitly changing an argument type to a descendant. This happens in general only on a small subset of the features.&lt;br /&gt;
&lt;br /&gt;
The main difference is that in the generic case, all features which have a formal generic parameter automatically change the signature in different derivations whereas the non-generic case only specific features are covariantly redefined (if any at all). Also, in the generic case it is known for all possible descendants which features are redefined covariantly.&lt;br /&gt;
&lt;br /&gt;
This observation helps to understand the various proposals and to see their strengths and weaknesses:&lt;br /&gt;
* A proposal which operates on the feature level can be good for non-generic classes as you generally have a small number of features covariantly redefined and you only have to specify these features. In the case of generics this can become cumbersome as all features with formal generic parameters are always considered as covariantly redefined and thus for generics they always have to be considered.&lt;br /&gt;
* A proposal which operates on the type level is better suited for generics as you don't have to specify every single feature which has a formal generic parameter as argument. But they run into problems in the non-generic case if you look at anchored types - for example &amp;lt;e&amp;gt;like Current&amp;lt;/e&amp;gt;. Due to the fact that you have a covariant redeclaration in every descendant with such a feature, operating on the type level means that you have to handle every descendant specifically whereas if you operated on the feature level you could just handle this single feature.&lt;br /&gt;
* You see that there are two families of features: Features with formal arguments and ordinary features which are covariantly redefined. The fundamental difference between these two families is that they can change their signature independently. From &amp;lt;e&amp;gt;LIST [ANY]&amp;lt;/e&amp;gt; to &amp;lt;e&amp;gt;LIST [INTEGER]&amp;lt;/e&amp;gt; only the features based on the formal change their signature while they don't change from &amp;lt;e&amp;gt;LIST [ANY]&amp;lt;/e&amp;gt; to &amp;lt;e&amp;gt;LINKED_LIST [ANY]&amp;lt;/e&amp;gt; where the ordinary ones do. If you don't want to restrict the programmers expressiveness these feature families have to be addressed separately and a ''one fits all'' solution does not exist.&lt;br /&gt;
&lt;br /&gt;
=== Contravariant generics ===&lt;br /&gt;
&lt;br /&gt;
The modeling of certain problems involving generics requires contravariance. The two examples which will be used are comparator objects and agents:&lt;br /&gt;
&lt;br /&gt;
* If you want to compare objects using a comparator, it either needs to be able to compare objects of the exact type, or an ancestor. Thus if you want to compare strings, either a comparator for &amp;lt;e&amp;gt;STRING&amp;lt;/e&amp;gt; or one for &amp;lt;e&amp;gt;ANY&amp;lt;/e&amp;gt; is suitable. &lt;br /&gt;
* If you want to pass an argument of type &amp;lt;e&amp;gt;STRING&amp;lt;/e&amp;gt; to an agent, the agent either has to accept a &amp;lt;e&amp;gt;STRING&amp;lt;/e&amp;gt; or &amp;lt;e&amp;gt;ANY&amp;lt;/e&amp;gt; argument (or no argument at all).&lt;br /&gt;
&lt;br /&gt;
These problems can only be modeled if there is a way to express contravariant conformance for generics. This means that all proposed solutions which don't offer this possibility can't be used to model agents or comparator correctly and safely.&lt;br /&gt;
&lt;br /&gt;
=== Catcall benchmark ===&lt;br /&gt;
&lt;br /&gt;
[[Catcall checkpoints]]&lt;br /&gt;
&lt;br /&gt;
== Overview of general solutions ==&lt;br /&gt;
&lt;br /&gt;
The following proposals handle the case of covariance on non-generic and generic types.&lt;br /&gt;
&lt;br /&gt;
=== [[Novariance]] ===&lt;br /&gt;
&lt;br /&gt;
In the novariance proposal, covariant redefinition for arguments is prohibited. If covariance is needed for modeling purposes it can be [http://dev.eiffel.com/Covariance_through_renaming simulated by renaming].&lt;br /&gt;
&lt;br /&gt;
The conformance between generics with different formal parameters is removed.&lt;br /&gt;
&lt;br /&gt;
=== [[Forget / keep]] ===&lt;br /&gt;
&lt;br /&gt;
With the forget and keep mechanisms you specify per type on the feature level which features need not to be called - these features can safely be redefined covariantly - or which features have to be available - these features have to be typesafe for all possible values of a caller object.&lt;br /&gt;
&lt;br /&gt;
Reference: [http://dev.eiffel.com/Forget_/_Keep_Mechanism Article on dev.eiffel.com]&lt;br /&gt;
&lt;br /&gt;
=== Dynamic typeset algorithm ===&lt;br /&gt;
&lt;br /&gt;
The dynamic typeset algorithm does not change any semantics of the types or the conformance as it is in Eiffel already, it only does an abstract execution of the system to limit the possibilities per feature call which have to be checked if they are safe.&lt;br /&gt;
== Overview of solutions for non-generics ==&lt;br /&gt;
&lt;br /&gt;
These proposal only address the case for non-generics. For generic catcalls another solution (e.g. wildcard generics) can be used.&lt;br /&gt;
&lt;br /&gt;
=== [[Restrict types]] ===&lt;br /&gt;
&lt;br /&gt;
With restrict types you specify per type on the type level which descendant types that are allowed. Only these types can be assigned to such a variable, and all feature calls on these variables have to be valid for all possible types in this list.&lt;br /&gt;
&lt;br /&gt;
Reference: [http://se.inf.ethz.ch/cgi-bin/ecma/index.cgi?IssueFLEX_CATCALL IssueFLEX_CATCALL on ECMA wiki]&amp;lt;br/&amp;gt;&lt;br /&gt;
Reference: Discussion in ECMA mailinglist named ''Catcall removal: another proposal'', [[Restrict types mail|available in parts]]&lt;br /&gt;
&lt;br /&gt;
=== [[DOG proposal]] ===&lt;br /&gt;
&lt;br /&gt;
With the DOG proposal, features which can be covariantly redefined have to be marked as such. These features can only be called on specially marked entities which have a restricted conformance, thus preventing assignments from descendants with potential covariantly redefined arguments.&lt;br /&gt;
&lt;br /&gt;
Reference: [http://se.inf.ethz.ch/cgi-bin/ecma/index.cgi?IssueDOG IssueDOG on ECMA wiki]&lt;br /&gt;
&lt;br /&gt;
== Overview of solutions for generics ==&lt;br /&gt;
&lt;br /&gt;
These proposal only address the case for generics. For non-generic catcalls another solution (e.g. novariance) can be used.&lt;br /&gt;
&lt;br /&gt;
=== [[Usage-site variance]] ===&lt;br /&gt;
&lt;br /&gt;
This solution lets the programmer decide on the instantiation of a generic if the generic parameter should be covariant, contravariant or invariant. Depending on the variance, the applicable features of the type and the conformance rules to other generic types are changed.&lt;br /&gt;
&lt;br /&gt;
Reference: [http://pag.csail.mit.edu/reading-group/variance-ECOOP02.pdf On variance-based subtyping for parametric types]&lt;br /&gt;
&lt;br /&gt;
=== [[Definition-site variance]] ===&lt;br /&gt;
&lt;br /&gt;
This solution lets the programmer decide in the definition of a generic class if the generic parameter should be covariant, contravariant or invariant. Depending on the variance, the formal generic can only appear at the argument, only appear as a result type or appear in both places. Also the conformance is adapted depending on the variance of the generic parameter.&lt;br /&gt;
&lt;br /&gt;
This is the solution which is implemented in the CLR, although not supported by generics in C# which are novariant.&lt;br /&gt;
&lt;br /&gt;
Reference: [http://blogs.msdn.com/rmbyers/archive/2006/06/01/613690.aspx Article about generics in CLR]&lt;br /&gt;
&lt;br /&gt;
Note: There is also a [http://fams.de/text/type-safe-eiffel.html proposal by Bernd Schoeller] about ''variant and invariant'' generics which is a subset of this one and thus not explained in detail.&lt;br /&gt;
&lt;br /&gt;
=== Wildcard generics ===&lt;br /&gt;
&lt;br /&gt;
This mechanism extends the [[usage-site variance]] by adding a wildcard to the generic derivation. This wildcard denotes unspecified types and limits the use of features with generic parameters or result types over conformance to the wildcard types.&lt;br /&gt;
&lt;br /&gt;
Since the mechanism is almost identical to the usage-site variance, it will not be looked at in more detail. Please refer to the reference article for more information.&lt;br /&gt;
&lt;br /&gt;
Reference: [http://www.jot.fm/issues/issue_2004_12/article5 Adding Wildcards to the Java Programming Language]&lt;br /&gt;
&lt;br /&gt;
== Overview of dynamic solutions ==&lt;br /&gt;
&lt;br /&gt;
These proposals do not prevent catcalls at compile-time but introduce means to handle catcalls at runtime.&lt;br /&gt;
&lt;br /&gt;
=== [[Detachable types]] ===&lt;br /&gt;
&lt;br /&gt;
This solution allows covariantly redefined features only to use detachable types. Through this mechanism, an object test is necessary before an argument can be used. This forces the programmer to test arguments for validity.&lt;br /&gt;
&lt;br /&gt;
Reference: [http://se.ethz.ch/~meyer/publications/lncs/attached.pdf Article about ''attached types'' by Bertrand Meyer]&amp;lt;br/&amp;gt;&lt;br /&gt;
Reference: [http://www.ecma-international.org/publications/standards/Ecma-367.htm ECMA Eiffel standard 2nd edition of June 2006]&lt;br /&gt;
&lt;br /&gt;
=== Recast ===&lt;br /&gt;
&lt;br /&gt;
In the recast proposal, the programmer has to specify a transformation function when covariantly redefining a feature which can transform the old argument types to the new ones.&lt;br /&gt;
&lt;br /&gt;
Reference: [http://se.inf.ethz.ch/cgi-bin/ecma/index.cgi?IssueCAT IssueCAT on ECMA wiki]&amp;lt;br/&amp;gt;&lt;br /&gt;
Reference: [http://www.inf.ethz.ch/~meyer/ongoing/covariance/recast.pdf Article about recast]&lt;br /&gt;
&lt;br /&gt;
=== Exceptions ===&lt;br /&gt;
&lt;br /&gt;
Another way of handling catcalls at runtime is to raise exceptions. It can be required or not to provide a rescue clause which handles the case of the catcall.&lt;br /&gt;
&lt;br /&gt;
== Combinations ==&lt;br /&gt;
&lt;br /&gt;
It is also possible to combine different proposals:&lt;br /&gt;
&lt;br /&gt;
* Novariance for non-generic features and usage-site variance for generics .&lt;br /&gt;
* Forget / keep for non-generic features and definition-site variance for generics.&lt;br /&gt;
* DOG proposal for non-generic features and wildcard generics.&lt;br /&gt;
* ...&lt;br /&gt;
&lt;br /&gt;
== Results ==&lt;br /&gt;
&lt;br /&gt;
The following table summarizes the support of the various solutions to the criteria described above which can be used to judge a catcall solution.&lt;br /&gt;
&lt;br /&gt;
This results can be differently interpreted, so the colors may not be totally accurate. See the [[Comparison of catcall solutions#Table_explained|explanation at the end of the table]] for more information&lt;br /&gt;
&lt;br /&gt;
=== General solutions ===&lt;br /&gt;
&lt;br /&gt;
{| border=1 cellpadding=2&lt;br /&gt;
&lt;br /&gt;
|- style=&amp;quot;visibility: hidden&amp;quot;&lt;br /&gt;
| style=&amp;quot;width:25%&amp;quot; |&lt;br /&gt;
| style=&amp;quot;width:25%&amp;quot; |&lt;br /&gt;
| style=&amp;quot;width:25%&amp;quot; |&lt;br /&gt;
| style=&amp;quot;width:25%&amp;quot; |&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
&lt;br /&gt;
! Criteria&lt;br /&gt;
! [[Novariance]]&lt;br /&gt;
! [[Forget / keep]]&lt;br /&gt;
! Dynamic typeset algorithm&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
&lt;br /&gt;
! Syntax overhead&lt;br /&gt;
| {{Green|No}}&lt;br /&gt;
| {{Red|Big}}: forget/keep clauses per type&lt;br /&gt;
| {{Green|No}}&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
&lt;br /&gt;
! Covariance on non-generic types &lt;br /&gt;
| {{Red|Not allowed}}&lt;br /&gt;
| {{Green|Allowed}}&lt;br /&gt;
| {{Green|Allowed}}&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
&lt;br /&gt;
! Export status restrictions&lt;br /&gt;
| {{Red|Not allowed}}&lt;br /&gt;
| {{Green|Allowed}}&lt;br /&gt;
| {{Green|Allowed}}&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
&lt;br /&gt;
! Use of generic types&lt;br /&gt;
| {{Red|Very limited}}: Only invariant conformance&lt;br /&gt;
| {{Orange|Limited}}: Conformance restricted (''keep all'' as default)&amp;lt;br/&amp;gt;{{Orange|Limited}}: Use restricted (''forget all'' as default)&lt;br /&gt;
| {{Green|As it is now}}&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
&lt;br /&gt;
! Agents&lt;br /&gt;
| {{Orange|Limited}}&amp;lt;br/&amp;gt;{{Green|Safe}}&lt;br /&gt;
| {{Orange|Limited}}&amp;lt;br/&amp;gt;{{Green|Safe}}&lt;br /&gt;
| {{Red|As it is now}}&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
&lt;br /&gt;
! Comparator&lt;br /&gt;
| {{Red|Not supported}}&lt;br /&gt;
| {{Red|Not supported}}&lt;br /&gt;
| {{Red|Not supported}}&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
&lt;br /&gt;
! Complexity of compiler check&lt;br /&gt;
| {{Green|Small}}&lt;br /&gt;
| {{Orange|Medium}}: Check of feature call for all descendants; Conformance check on forget/keep clauses&lt;br /&gt;
| {{Red|Big}}: Iterative abstract system execution&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
&lt;br /&gt;
! Complexity of runtime&lt;br /&gt;
| {{Green|Small}}: As it is now&lt;br /&gt;
| {{Orange|Medium}}: Need to know cat features for object tests&lt;br /&gt;
| {{Green|Small}}: As it is now&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
&lt;br /&gt;
! Whole-system analysis&lt;br /&gt;
| {{Green|No}}&lt;br /&gt;
| {{Red|Yes}}: use of ''forget all'' depends on system&lt;br /&gt;
| {{Red|Yes}}&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
&lt;br /&gt;
! Dynamic class and type loading&lt;br /&gt;
| {{Green|Yes}}&lt;br /&gt;
| {{Red|No}}&lt;br /&gt;
| {{Red|No}}&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
&lt;br /&gt;
! Backward compatibility&lt;br /&gt;
| {{Red|Very limited}}&lt;br /&gt;
| {{Orange|Limited}}&lt;br /&gt;
| {{Green|Full}}&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
&lt;br /&gt;
! Support of IDE (Source changes)&lt;br /&gt;
| {{Green|Not needed}}&lt;br /&gt;
| {{Orange|Possible}}: Can propose forget/keep clauses&lt;br /&gt;
| {{Green|Not needed}}&lt;br /&gt;
&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Solutions for non-generics ===&lt;br /&gt;
&lt;br /&gt;
{| border=1 cellpadding=2&lt;br /&gt;
&lt;br /&gt;
|- style=&amp;quot;visibility: hidden&amp;quot;&lt;br /&gt;
| style=&amp;quot;width:25%&amp;quot; |&lt;br /&gt;
| style=&amp;quot;width:25%&amp;quot; |&lt;br /&gt;
| style=&amp;quot;width:25%&amp;quot; |&lt;br /&gt;
| style=&amp;quot;width:25%&amp;quot; |&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
&lt;br /&gt;
! Criteria&lt;br /&gt;
! [[Restrict types]]&lt;br /&gt;
! [[DOG proposal]]&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
&lt;br /&gt;
! Syntax overhead&lt;br /&gt;
| {{Red|Big}}: Restrict clause per type declaration&lt;br /&gt;
| {{Orange|Medium}}: ''cat'' on features and on type declarations&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
&lt;br /&gt;
! Covariance on non-generic types &lt;br /&gt;
| {{Green|Allowed}}&lt;br /&gt;
| {{Green|Allowed}}&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
&lt;br /&gt;
! Export status restrictions&lt;br /&gt;
| {{Green|Allowed}}&lt;br /&gt;
| {{Green|Allowed}}&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
&lt;br /&gt;
! Use of generic types&lt;br /&gt;
| Not addressed&lt;br /&gt;
| Not addressed&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
&lt;br /&gt;
! Agents&lt;br /&gt;
| Not addressed&lt;br /&gt;
| Not addressed&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
&lt;br /&gt;
! Comparator&lt;br /&gt;
| Not addressed&lt;br /&gt;
| Not addressed&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
&lt;br /&gt;
! Complexity of compiler check&lt;br /&gt;
| {{Orange|Medium}}: Check of feature call for all descendants; Conformance check on restrict clauses&lt;br /&gt;
| {{Green|Small}}: Check of ''cat'' on conformance&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
&lt;br /&gt;
! Complexity of runtime&lt;br /&gt;
| not yet considered&lt;br /&gt;
| {{Green|Small}}&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
&lt;br /&gt;
! Whole-system analysis&lt;br /&gt;
| {{Orange|Partial}}&lt;br /&gt;
| {{Green|No}}&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
&lt;br /&gt;
! Dynamic class and type loading&lt;br /&gt;
| {{Orange|Limited}}&lt;br /&gt;
| {{Green|Yes}}&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
&lt;br /&gt;
! Backward compatibility&lt;br /&gt;
| {{Red|Very limited}}&lt;br /&gt;
| {{Red|Very limited}}&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
&lt;br /&gt;
! Support of IDE (Source changes)&lt;br /&gt;
| {{Orange|Possible}}: Can propose restrict clauses&lt;br /&gt;
| {{Orange|Possible}}: Can propose ''cat'' marks&lt;br /&gt;
&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Solutions for generics ===&lt;br /&gt;
&lt;br /&gt;
{| border=1 cellpadding=2&lt;br /&gt;
&lt;br /&gt;
|- style=&amp;quot;visibility: hidden&amp;quot;&lt;br /&gt;
| style=&amp;quot;width:25%&amp;quot; |&lt;br /&gt;
| style=&amp;quot;width:25%&amp;quot; |&lt;br /&gt;
| style=&amp;quot;width:25%&amp;quot; |&lt;br /&gt;
| style=&amp;quot;width:25%&amp;quot; |&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
&lt;br /&gt;
! Criteria&lt;br /&gt;
! [[Usage-site variance]]&lt;br /&gt;
! [[Definition-site variance]]&lt;br /&gt;
! Wildcard generics&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
&lt;br /&gt;
! Syntax overhead&lt;br /&gt;
| {{Orange|Medium}}: Variance marks per generic type&lt;br /&gt;
| {{Green|Small}}: Variance marks per generic class definition&lt;br /&gt;
| {{Orange|Medium}}: Variance marks per generic type&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
&lt;br /&gt;
! Covariance on non-generic types &lt;br /&gt;
| Not addressed&lt;br /&gt;
| Not addressed&lt;br /&gt;
| Not addressed&lt;br /&gt;
|-&lt;br /&gt;
&lt;br /&gt;
! Export status restrictions&lt;br /&gt;
| Not addressed&lt;br /&gt;
| Not addressed&lt;br /&gt;
| Not addressed&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
&lt;br /&gt;
! Use of generic types&lt;br /&gt;
| {{Orange|Limited}}: Conformance is limited&amp;lt;br/&amp;gt;{{Green|Safe}}&lt;br /&gt;
| {{Orange|Limited}}: Conformance is limited&amp;lt;br/&amp;gt;{{Green|Safe}}&lt;br /&gt;
| {{Orange|Limited}}: Conformance is limited&amp;lt;br/&amp;gt;{{Green|Safe}}&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
&lt;br /&gt;
! Agents&lt;br /&gt;
| {{Green|Fully supported}}&amp;lt;br/&amp;gt;{{Green|Safe}}&lt;br /&gt;
| {{Orange|Almost fully supported}}&amp;lt;br/&amp;gt;{{Green|Safe}}&lt;br /&gt;
| {{Green|Fully supported}}&amp;lt;br/&amp;gt;{{Green|Safe}}&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
&lt;br /&gt;
! Comparator&lt;br /&gt;
| {{Green|Supported}}&lt;br /&gt;
| {{Green|Supported}}&lt;br /&gt;
| {{Green|Supported}}&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
&lt;br /&gt;
! Complexity of compiler check&lt;br /&gt;
| {{Green|Small}}: Consider variance in conformance check&lt;br /&gt;
| {{Green|Small}}: Consider variance in conformance check&lt;br /&gt;
| {{Green|Small}}: Consider variance in conformance check&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
&lt;br /&gt;
! Complexity of runtime&lt;br /&gt;
| {{Green|Small}}: Consider variance in object test&lt;br /&gt;
| {{Green|Small}}: Consider variance in object test&lt;br /&gt;
| {{Green|Small}}: Consider variance in object test&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
&lt;br /&gt;
! Whole-system analysis&lt;br /&gt;
| {{Green|No}}&lt;br /&gt;
| {{Green|No}}&lt;br /&gt;
| {{Green|No}}&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
&lt;br /&gt;
! Dynamic class and type loading&lt;br /&gt;
| {{Green|Yes}}&lt;br /&gt;
| {{Green|Yes}}&lt;br /&gt;
| {{Green|Yes}}&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
&lt;br /&gt;
! Backward compatibility&lt;br /&gt;
| {{Orange|Limited}}: Use of generics changed due to conformance&lt;br /&gt;
| {{Red|Very limited}}: Libraries need redesign&lt;br /&gt;
| {{Orange|Limited}}: Use of generics changed due to conformance&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
&lt;br /&gt;
! Support of IDE (Source changes)&lt;br /&gt;
| {{Orange|Possible}}: Can propose variance marks&lt;br /&gt;
| {{Red|Not possible}}: Libraries need redesign&lt;br /&gt;
| {{Orange|Possible}}: Can propose variance marks/wildcards&lt;br /&gt;
&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Dynamic solutions ===&lt;br /&gt;
&lt;br /&gt;
{| border=1 cellpadding=2&lt;br /&gt;
&lt;br /&gt;
|- style=&amp;quot;visibility: hidden&amp;quot;&lt;br /&gt;
| style=&amp;quot;width:25%&amp;quot; |&lt;br /&gt;
| style=&amp;quot;width:25%&amp;quot; |&lt;br /&gt;
| style=&amp;quot;width:25%&amp;quot; |&lt;br /&gt;
| style=&amp;quot;width:25%&amp;quot; |&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
&lt;br /&gt;
! Criteria&lt;br /&gt;
! [[Detachable types]]&lt;br /&gt;
! Recast&lt;br /&gt;
! Exceptions&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
&lt;br /&gt;
! Syntax overhead&lt;br /&gt;
| {{Green|Small}}: Detachment marks&lt;br /&gt;
| {{Red|Big}}: Recast clauses, recast features&lt;br /&gt;
| {{Orange|Medium}}: If rescue clause mandatory&amp;lt;br/&amp;gt;{{Green|No}}: If rescue clause not needed&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
&lt;br /&gt;
! Covariance on non-generic types &lt;br /&gt;
| {{Red|Very limited}}: Only detached arguments, no expanded arguments&lt;br /&gt;
| {{Green|Allowed}}&lt;br /&gt;
| {{Green|Allowed}}&lt;br /&gt;
|-&lt;br /&gt;
&lt;br /&gt;
! Export status restrictions&lt;br /&gt;
| Not addressed&lt;br /&gt;
| Not addressed&lt;br /&gt;
| Not addressed&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
&lt;br /&gt;
! Use of generics&lt;br /&gt;
| {{Red|Very limited}}: Only detachable formal arguments&lt;br /&gt;
| {{Red|Very limited}}: Recast clause for all features with formal generics&lt;br /&gt;
| {{Green|As it is now}}&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
&lt;br /&gt;
! Agents&lt;br /&gt;
| {{Red|As it is now}} &lt;br /&gt;
| {{Red|As it is now}} &lt;br /&gt;
| {{Red|As it is now}} &lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
&lt;br /&gt;
! Comparator&lt;br /&gt;
| {{Red|Not supported}}&lt;br /&gt;
| {{Red|Not supported}}&lt;br /&gt;
| {{Red|Not supported}}&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
&lt;br /&gt;
! Complexity of compiler check&lt;br /&gt;
| {{Green|Small}}: As it is now&lt;br /&gt;
| {{Green|Small}}: As it is now&lt;br /&gt;
| {{Green|Small}}: As it is now&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
&lt;br /&gt;
! Complexity of runtime&lt;br /&gt;
| {{Green|Small}}: As it is now&lt;br /&gt;
| {{Orange|Medium}}: Check for catcalls and do recast&lt;br /&gt;
| {{Orange|Medium}}: Check for catcalls and raise exception&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
&lt;br /&gt;
! Whole-system analysis&lt;br /&gt;
| {{Green|No}}&lt;br /&gt;
| {{Green|No}}&lt;br /&gt;
| {{Green|No}}&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
&lt;br /&gt;
! Dynamic class and type loading&lt;br /&gt;
| {{Green|Yes}}&lt;br /&gt;
| {{Green|Yes}}&lt;br /&gt;
| {{Green|Yes}}&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
&lt;br /&gt;
! Backward compatibility&lt;br /&gt;
| {{Red|Very limited}}: All covariant and generic features become detached&lt;br /&gt;
| {{Red|Very limited}}: All covariant and generic features need recast clause&lt;br /&gt;
| {{Orange|Limited}}: If rescue clause is mandatory&amp;lt;br/&amp;gt;{{Green|Full}}: If rescue clause not needed&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
&lt;br /&gt;
! Support of IDE (Source changes)&lt;br /&gt;
| {{Orange|Possible}}: Can propose detachment marks&lt;br /&gt;
| {{Red|Not possible}}: Programmer must provide recast clause&lt;br /&gt;
| {{Red|Not possible}}: If rescue clause mandatory&amp;lt;br/&amp;gt;{{Green|Not needed}}: If rescue clause not needed&lt;br /&gt;
&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Table explained ===&lt;br /&gt;
&lt;br /&gt;
; Syntax overhead : {{Green|Small}} if a keyword/mark is needed per class/feature declaration; {{Orange|Medium}} if a keyword/mark is neede per type declaration; {{Red|Big}} if a clause is needed per type declaration.&lt;br /&gt;
; Use of generics : {{Green|As it is now}} if assignments are possible if generic parameters conform; {{Orange|Limited}} is some restrictions in the use or the conformance between generics exist; {{Red|Very limited}} a lot of restrictions in the use or the conformance between generics exist.&lt;br /&gt;
; Agents : {{Green|Fully supported}} if all safe assignments are allowed; {{Orange|Limited}} if not all safe assignments are allowed; {{Red|As it is now}} if unsafe assignments are still possible.&lt;br /&gt;
; Comparator : {{Green|Supported}} if for a comparator all safe assignments are permitted (i.e. contravariant assignments); {{Red|Not supported}} if only exact type or even (unsafe) subtypes can be assigned.&lt;br /&gt;
; Support of IDE (Source changes) : {{Green|Not needed}} if everything still works the same; {{Orange|Possible}} if the compiler can suggest clauses or marks; {{Red|Not possible}} if the programmer has to specify additional features/instructions.&lt;br /&gt;
&lt;br /&gt;
== Personal opinions ==&lt;br /&gt;
&lt;br /&gt;
[[Personal view about catcall solution]]&lt;/div&gt;</summary>
		<author><name>Juliant</name></author>	</entry>

	<entry>
		<id>https://dev.eiffel.com/index.php?title=Catcall_checkpoints&amp;diff=8890</id>
		<title>Catcall checkpoints</title>
		<link rel="alternate" type="text/html" href="https://dev.eiffel.com/index.php?title=Catcall_checkpoints&amp;diff=8890"/>
				<updated>2007-06-24T01:59:41Z</updated>
		
		<summary type="html">&lt;p&gt;Juliant: /* faces of covariance */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Category:Catcall]]&lt;br /&gt;
These examples should be considered for all catcall solutions:&lt;br /&gt;
&lt;br /&gt;
== faces of covariance ==&lt;br /&gt;
&lt;br /&gt;
The following example shows the difference between generic covariance and non-generic covariance. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;e&amp;gt;&lt;br /&gt;
class A [G]&lt;br /&gt;
feature&lt;br /&gt;
	f (t: T) do end&lt;br /&gt;
	put (g: G) do end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
class B [G]&lt;br /&gt;
inherit A [G] redefine f end&lt;br /&gt;
feature&lt;br /&gt;
	f (u: U) do end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
local&lt;br /&gt;
  a_any: A [ANY]&lt;br /&gt;
  a_string: A [STRING]&lt;br /&gt;
  b_any: B [ANY]&lt;br /&gt;
  b_string: B [STRING]&lt;br /&gt;
  t: T&lt;br /&gt;
do&lt;br /&gt;
  a_any := a_string&lt;br /&gt;
  a_any.put (5) -- catcall for generic feature&lt;br /&gt;
  a_any.f (t) -- no catcall&lt;br /&gt;
&lt;br /&gt;
  a_any := b_any&lt;br /&gt;
  a_any.put (5) -- no catcall&lt;br /&gt;
  a_any.f (t) -- catcall for non-generic feature&lt;br /&gt;
&lt;br /&gt;
  a_any := b_string&lt;br /&gt;
  a_any.put (5) -- catcall for generic feature&lt;br /&gt;
  a_any.f (t) -- catcall for non-generic feature&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/e&amp;gt;&lt;br /&gt;
&lt;br /&gt;
A safe and expressive solution should have a way to allow all valid cases and prohibit the invalid ones. This needs a way to address the generic and non-generic features indiviually.&lt;br /&gt;
&lt;br /&gt;
== contravariance ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;e&amp;gt;&lt;br /&gt;
class SORTER [G]&lt;br /&gt;
feature&lt;br /&gt;
  sort (a_list: LIST [G]; a_comparator: COMPARATOR [G])&lt;br /&gt;
    do&lt;br /&gt;
        -- Somewhere in the loop:&lt;br /&gt;
      a_comparator.compare (l_string_1, l_string_2)&lt;br /&gt;
    end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
class EXAMPLE&lt;br /&gt;
feature&lt;br /&gt;
  make&lt;br /&gt;
    local&lt;br /&gt;
      l_list: LIST [STRING]&lt;br /&gt;
      l_string_sorter: SORTER [STRING]&lt;br /&gt;
      l_any_comparator: COMPARATOR [ANY]&lt;br /&gt;
    do&lt;br /&gt;
        -- Should be allowed to sort the string list with an&lt;br /&gt;
        -- ANY comparator&lt;br /&gt;
      l_string_sorter.sort (l_list, l_any_comparator)&lt;br /&gt;
    end&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/e&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Solutions which pass this test are likely to be expressive for agents as well.&lt;/div&gt;</summary>
		<author><name>Juliant</name></author>	</entry>

	<entry>
		<id>https://dev.eiffel.com/index.php?title=Catcall_checkpoints&amp;diff=8889</id>
		<title>Catcall checkpoints</title>
		<link rel="alternate" type="text/html" href="https://dev.eiffel.com/index.php?title=Catcall_checkpoints&amp;diff=8889"/>
				<updated>2007-06-24T01:59:08Z</updated>
		
		<summary type="html">&lt;p&gt;Juliant: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Category:Catcall]]&lt;br /&gt;
These examples should be considered for all catcall solutions:&lt;br /&gt;
&lt;br /&gt;
== faces of covariance ==&lt;br /&gt;
&lt;br /&gt;
The following example shows the difference between generic covariance and non-generic covariance. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;e&amp;gt;&lt;br /&gt;
class A [G]&lt;br /&gt;
feature&lt;br /&gt;
	f (t: T) do end&lt;br /&gt;
	put (g: G) do end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
class B [G]&lt;br /&gt;
inherit A [G]&lt;br /&gt;
	redefine f end&lt;br /&gt;
feature&lt;br /&gt;
	f (u: U) do end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
local&lt;br /&gt;
  a_any: A [ANY]&lt;br /&gt;
  a_string: A [STRING]&lt;br /&gt;
  b_any: B [ANY]&lt;br /&gt;
  b_string: B [STRING]&lt;br /&gt;
  t: T&lt;br /&gt;
do&lt;br /&gt;
  a_any := a_string&lt;br /&gt;
  a_any.put (5) -- catcall for generic feature&lt;br /&gt;
  a_any.f (t) -- no catcall&lt;br /&gt;
&lt;br /&gt;
  a_any := b_any&lt;br /&gt;
  a_any.put (5) -- no catcall&lt;br /&gt;
  a_any.f (t) -- catcall for non-generic feature&lt;br /&gt;
&lt;br /&gt;
  a_any := b_string&lt;br /&gt;
  a_any.put (5) -- catcall for generic feature&lt;br /&gt;
  a_any.f (t) -- catcall for non-generic feature&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/e&amp;gt;&lt;br /&gt;
&lt;br /&gt;
A safe and expressive solution should have a way to allow all valid cases and prohibit the invalid ones. This needs a way to address the generic and non-generic features indiviually.&lt;br /&gt;
&lt;br /&gt;
== contravariance ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;e&amp;gt;&lt;br /&gt;
class SORTER [G]&lt;br /&gt;
feature&lt;br /&gt;
  sort (a_list: LIST [G]; a_comparator: COMPARATOR [G])&lt;br /&gt;
    do&lt;br /&gt;
        -- Somewhere in the loop:&lt;br /&gt;
      a_comparator.compare (l_string_1, l_string_2)&lt;br /&gt;
    end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
class EXAMPLE&lt;br /&gt;
feature&lt;br /&gt;
  make&lt;br /&gt;
    local&lt;br /&gt;
      l_list: LIST [STRING]&lt;br /&gt;
      l_string_sorter: SORTER [STRING]&lt;br /&gt;
      l_any_comparator: COMPARATOR [ANY]&lt;br /&gt;
    do&lt;br /&gt;
        -- Should be allowed to sort the string list with an&lt;br /&gt;
        -- ANY comparator&lt;br /&gt;
      l_string_sorter.sort (l_list, l_any_comparator)&lt;br /&gt;
    end&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/e&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Solutions which pass this test are likely to be expressive for agents as well.&lt;/div&gt;</summary>
		<author><name>Juliant</name></author>	</entry>

	</feed>