<?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=Seilerm</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=Seilerm"/>
		<link rel="alternate" type="text/html" href="https://dev.eiffel.com/Special:Contributions/Seilerm"/>
		<updated>2026-04-27T11:21:57Z</updated>
		<subtitle>User contributions</subtitle>
		<generator>MediaWiki 1.24.1</generator>

	<entry>
		<id>https://dev.eiffel.com/index.php?title=Multiple_constraints&amp;diff=9984</id>
		<title>Multiple constraints</title>
		<link rel="alternate" type="text/html" href="https://dev.eiffel.com/index.php?title=Multiple_constraints&amp;diff=9984"/>
				<updated>2007-11-06T22:03:45Z</updated>
		
		<summary type="html">&lt;p&gt;Seilerm: /* Using whats there */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Category:ECMA]]&lt;br /&gt;
==Description==&lt;br /&gt;
This article discusses issues which arise with multiple constrained type parameters.&lt;br /&gt;
==Formal generic type parameters with multiple constraints==&lt;br /&gt;
&lt;br /&gt;
The new [http://www.ecma-international.org/publications/standards/Ecma-367.htm ECMA standard] for Eiffel introduces multi-constraint formal generic type parameters.&lt;br /&gt;
&lt;br /&gt;
{|border=&amp;quot;0&amp;quot; cellpadding=&amp;quot;2&amp;quot; cellspacing=&amp;quot;0&amp;quot; align=&amp;quot;center&amp;quot;&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot; -halign=&amp;quot;center&amp;quot;&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
Example:&lt;br /&gt;
&amp;lt;code&amp;gt;[eiffel,N]&lt;br /&gt;
class C [G -&amp;gt; {A, B}]&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Class C expects a type parameter that conforms to A and B.&lt;br /&gt;
To make the text a bit easier to read I sometimes abbreviate the term 'formal generic type parameter' simply as 'formal'.&lt;br /&gt;
So &amp;quot;G is the only formal of class C&amp;quot; means that G is the only formal generic type parameter of class C.&lt;br /&gt;
&lt;br /&gt;
==Qualified calls==&lt;br /&gt;
====Explanation of the issue====&lt;br /&gt;
Consider this example inheritance hierarchy together with the following code:&lt;br /&gt;
&lt;br /&gt;
{|border=&amp;quot;0&amp;quot; cellpadding=&amp;quot;2&amp;quot; cellspacing=&amp;quot;0&amp;quot; align=&amp;quot;center&amp;quot;&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot; -halign=&amp;quot;center&amp;quot;&lt;br /&gt;
|[[Image:Class_diagram_for_multiple_constraints_explanation.png|173px]]&lt;br /&gt;
|&lt;br /&gt;
Example:&lt;br /&gt;
&amp;lt;e&amp;gt;&lt;br /&gt;
class GENERIC_CLASS [G -&amp;gt; {B, C}]&lt;br /&gt;
&lt;br /&gt;
feature&lt;br /&gt;
&lt;br /&gt;
   g: G&lt;br /&gt;
&lt;br /&gt;
   example is&lt;br /&gt;
      do       &lt;br /&gt;
         g.f      -- qualified feature call&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;
Our interest is focused on the qualified feature call ''g.f'' of the example feature. With the dynamic binding semantics defined in section ''8.16.11'' of the ECMA standard, it makes a difference whether the static type of ''g'' is ''A'', ''B'' or ''C''. An illustration of the differences can be found in the [[Transposition]] article.&lt;br /&gt;
&lt;br /&gt;
The standard defines in section ''8.12.23'' what the base type of such a multiple constrained formal type parameter is. It is a fictitious class (denoted as a dashed class ''FICT'' in the diagram) which inherits from all constraint classes and to which a possible renaming is applied. Dynamic binding requires a clear notion of what the static type of a target (here g) is. To obtain the correct feature, one needs the static and dynamic type of the target at runtime. Normally the base type of the target is taken as the static type. But we cannot take this fictitious base type as our static type, because, as can be seen in the diagram, it is outside of the conformance paths to X and therefore not usable with the current definition of dynamic binding.&lt;br /&gt;
&lt;br /&gt;
The definition of this fictitious type ''FICT'' can only be used to clearly define the set of available features to instances of type G. It can not be used to define the semantic of a qualified feature call (like f.a).&lt;br /&gt;
&lt;br /&gt;
To be able to use the type G one must provide a clear definition which static type is to use for a qualified feature call.&lt;br /&gt;
An ambiguous feature, regarding the dynamic binding problematic, is a feature which is inherited through multiple constraining types. In our example this is the case for the feature ''f''. It occurs in ''B'' and in ''C''.&lt;br /&gt;
&lt;br /&gt;
====Solution proposal: Common Ancestor====&lt;br /&gt;
&lt;br /&gt;
If we have a multi-constraint formal type parameter and a qualified feature call on a target of that type, we define the static type to be the type of the class which introduced the current version of the called feature body. This must be a common ancestor of the constraining class types which contain the feature ''f'' (in our case ''B'' and ''C'').&lt;br /&gt;
&lt;br /&gt;
In our example we would set the static type of ''f'' to ''A'' and then execute the qualified feature call.&lt;br /&gt;
&lt;br /&gt;
'''Properties of this solution:'''&lt;br /&gt;
&lt;br /&gt;
* All features can be directly called on a target of type ''G''.&lt;br /&gt;
&lt;br /&gt;
* The static type of ''g'' may change depending on which feature is called.&lt;br /&gt;
&lt;br /&gt;
====Solution proposal: Manual Static Type Selection====&lt;br /&gt;
&lt;br /&gt;
The basic idea is to disallow ambiguous qualified calls on targets of type ''G'' at all.&lt;br /&gt;
In our example it would '''not''' be valid to do the call ''g.f'' because the feature ''f'' is ambiguous as it is inherited over multiple paths (once through B and once through C).&lt;br /&gt;
&lt;br /&gt;
As a consequence the programmer needs to resolve ambiguities manually. He does that by using either &lt;br /&gt;
&lt;br /&gt;
* explicit renaming&lt;br /&gt;
* local variables&lt;br /&gt;
* object test&lt;br /&gt;
&lt;br /&gt;
'''Using explicit renaming:'''&lt;br /&gt;
&amp;lt;e&amp;gt;&lt;br /&gt;
class GENERIC_CLASS [G -&amp;gt; {B rename f as f_b end, C rename f as f_c end}]&lt;br /&gt;
&lt;br /&gt;
feature&lt;br /&gt;
&lt;br /&gt;
   g: G&lt;br /&gt;
&lt;br /&gt;
   example is&lt;br /&gt;
      do       &lt;br /&gt;
         g.f_b   -- qualified feature call with static type B&lt;br /&gt;
         g.f_c   -- qualified feature call with static type C&lt;br /&gt;
      end&lt;br /&gt;
&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/e&amp;gt;&lt;br /&gt;
The programmer resolves the issue by renaming in the first place.&lt;br /&gt;
&lt;br /&gt;
'''Using a local variable:'''&lt;br /&gt;
&amp;lt;code&amp;gt;[eiffel,N]&lt;br /&gt;
   example is&lt;br /&gt;
      local&lt;br /&gt;
         b: B&lt;br /&gt;
      do &lt;br /&gt;
         b := g&lt;br /&gt;
         b.f      -- qualified feature call with static type B&lt;br /&gt;
      end&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The programmer explicitly choses static type ''B'' by assigning ''g'' to the local variable ''b''.&lt;br /&gt;
&lt;br /&gt;
'''Using the object test:'''&lt;br /&gt;
&amp;lt;e&amp;gt;&lt;br /&gt;
   example is&lt;br /&gt;
      do &lt;br /&gt;
         check {bg: B | g } end&lt;br /&gt;
         bg.f  -- qualified feature call with static type B&lt;br /&gt;
      end&lt;br /&gt;
&amp;lt;/e&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In this version the static type is chosen due to an object test.&lt;br /&gt;
&lt;br /&gt;
'''Properties of this solution:'''&lt;br /&gt;
&lt;br /&gt;
* Not all feature calls can be applied to a target whose type is a multi-constraint generic.&lt;br /&gt;
&lt;br /&gt;
* The definition of the static type of every call remains straight forward.&lt;br /&gt;
&lt;br /&gt;
'''Option'''&lt;br /&gt;
&lt;br /&gt;
The renaming clause for multi-constraint types could be removed and name clashes could be regarded as ambiguous cases too. The user resolves it as shown above by choosing a static type explicitly over locals and object tests only.&lt;br /&gt;
&lt;br /&gt;
==Abstract creation==&lt;br /&gt;
It is not perfectly clear by reading the standard what the semantics of&lt;br /&gt;
&amp;lt;e&amp;gt;&lt;br /&gt;
create g&lt;br /&gt;
&amp;lt;/e&amp;gt;&lt;br /&gt;
Where the type of ''g'' is a multi-constraint formal.&lt;br /&gt;
&lt;br /&gt;
===By name===&lt;br /&gt;
Require a feature with name ''default_create'' in creation constraint clause and use that for the creation. But remember the routine id and the type as an actual generic derivation may use different renaming.&lt;br /&gt;
&lt;br /&gt;
* New semantic&lt;br /&gt;
* Programmer can always use an instruction of the form &amp;lt;e&amp;gt;create g&amp;lt;/e&amp;gt; as soon as he as a creation constraint with the name ''default_create''.&lt;br /&gt;
&lt;br /&gt;
===By version===&lt;br /&gt;
Require exactly one version of ''default_create'' from ''ANY'' in creation constraint clause to make a call like &amp;lt;e&amp;gt;create g&amp;lt;/e&amp;gt; valid.&lt;br /&gt;
&lt;br /&gt;
* No new semantic&lt;br /&gt;
* Programmer cannot always use an instruction of the form &amp;lt;e&amp;gt;create g&amp;lt;/e&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The following code illustrates a case where it is not possible to use &amp;lt;e&amp;gt;create g&amp;lt;/e&amp;gt;.&lt;br /&gt;
&amp;lt;e&amp;gt;&lt;br /&gt;
class MULTI [G -&amp;gt; {X rename default_create as dc_x,&lt;br /&gt;
                   Y rename default_create as dc_y end} create dc_x, dc_y end]&lt;br /&gt;
feature&lt;br /&gt;
    g: G&lt;br /&gt;
&lt;br /&gt;
    some_feature&lt;br /&gt;
            -- Some feature&lt;br /&gt;
        do&lt;br /&gt;
            create g.dc_x -- 1&lt;br /&gt;
            create g.dc_y -- 2&lt;br /&gt;
            create g      -- 3&lt;br /&gt;
        end&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/e&amp;gt;&lt;br /&gt;
* 1 and 2: The creation of ''g'' is ok as we have an explicit invocation of the creation feature.&lt;br /&gt;
* 3: The abstract creation is not ok as ''dc_x'' and ''dc_y'' are both versions of ''default_create'' from ''ANY''.&lt;br /&gt;
&lt;br /&gt;
==Formal generic type parameters in constraints==&lt;br /&gt;
&lt;br /&gt;
===Introduction===&lt;br /&gt;
As a special case of a constraint a formal is allowed:&lt;br /&gt;
&amp;lt;e&amp;gt;&lt;br /&gt;
class C [G -&amp;gt; {H, A}, H -&amp;gt; {A, B}]&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/e&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Recursive definitions are allowed too and explicitly mentioned in the standard:&lt;br /&gt;
&amp;lt;e&amp;gt;&lt;br /&gt;
class C [G -&amp;gt; {H, A}, H -&amp;gt; {A, B, G}]&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/e&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Renaming Issues===&lt;br /&gt;
The question is now, how the renaming is handled for formal generic types.&lt;br /&gt;
&lt;br /&gt;
* [[#By using the base type|One could use the base type and]] apply a further renaming to it.&lt;br /&gt;
* One [[#By disallowing renaming on formals|disallows renaming on formals]].&lt;br /&gt;
&lt;br /&gt;
====Solution proposal: Base Type====&lt;br /&gt;
As [[#Explanation of the issue|previously stated]] the base type of a multi-constraint formal is defined in section ''8.12.23: Base type of a multi-constraint formal generic type'' and it can be used to define which features are available to the formal.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;e&amp;gt;&lt;br /&gt;
class C [G -&amp;gt; {H rename is_eq_a as is_eq_h_a end,&lt;br /&gt;
               A rename is_eq as is_eq_a},&lt;br /&gt;
         H -&amp;gt; {A rename is_eq as is_eq_a end,&lt;br /&gt;
               B}]&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/e&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This approach however can become more complex if you consider it in the context of a set of formals which include a recursion in their definition:&lt;br /&gt;
&amp;lt;e&amp;gt;&lt;br /&gt;
class C [G -&amp;gt; H rename is_equal as is_equal_of_h end,&lt;br /&gt;
         H -&amp;gt; G rename is_equal_of_h as is_equal end]&lt;br /&gt;
feature&lt;br /&gt;
   f&lt;br /&gt;
      local&lt;br /&gt;
         l_g: G&lt;br /&gt;
         l_h: H&lt;br /&gt;
      do&lt;br /&gt;
         l_g.is_equal_of_h (l_h)&lt;br /&gt;
         l_h.is_equal (l_g)&lt;br /&gt;
      end&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/e&amp;gt;&lt;br /&gt;
The base types of G and H look according to the definition something like this:&lt;br /&gt;
&amp;lt;e&amp;gt;&lt;br /&gt;
class FICT_BASE_TYPE_OF_G&lt;br /&gt;
inherit&lt;br /&gt;
   H&lt;br /&gt;
      rename is_equal as is_equal_of_h end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
class FICT_BASE_TYPE_OF_H&lt;br /&gt;
inherit&lt;br /&gt;
   G&lt;br /&gt;
      rename is_equal_of_h as is_equal end&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/e&amp;gt;&lt;br /&gt;
All the other conflicts (feature name clashes) which occur are resolved through renaming as well according to the definition. This renaming is however not accessible by the developer and omitted in the example.&lt;br /&gt;
&lt;br /&gt;
What is noteworthy for this example is:&lt;br /&gt;
* A formal occurs directly in the inheritance part.&lt;br /&gt;
* There is a cycle in the inheritance hierarchy.&lt;br /&gt;
&lt;br /&gt;
Both of them are not allowed in proper Eiffel code.&lt;br /&gt;
&lt;br /&gt;
====Solution proposal: No Renaming on Formals====&lt;br /&gt;
This forces the developer to rename each feature he wants to use once properly to it's final name.&lt;br /&gt;
&amp;lt;e&amp;gt;&lt;br /&gt;
class C [G -&amp;gt; {H,&lt;br /&gt;
               A rename is_eq as is_eq_g_a end},&lt;br /&gt;
         H -&amp;gt; {A rename is_eq as is_eq_h_a end,&lt;br /&gt;
               B rename is_eq as is_eq_b_a end}]&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/e&amp;gt;&lt;br /&gt;
== A second look on multi constraints ==&lt;br /&gt;
&lt;br /&gt;
=== Why multi constraint generics? ===&lt;br /&gt;
One could actually &amp;quot;simulate&amp;quot; it by introducing a new class which inherits from the constraints and using this new class as the actual constraint.&lt;br /&gt;
This is not possible as soon as one uses a predefined library which one cannot change easily.&lt;br /&gt;
That is really a reason why we need multi-constraint formals besides the syntactical sugar.&lt;br /&gt;
For example one cannot introduce a class COMPARABLE_NUMERIC and then use it as a constraint.&lt;br /&gt;
&lt;br /&gt;
=== Using what's there ===&lt;br /&gt;
&lt;br /&gt;
Issues which arise in the context of multi constraint formal generics are in many ways similar to the ones which have already been solved for multiple inheritance: &lt;br /&gt;
&lt;br /&gt;
* Inheritance cycles are not valid&lt;br /&gt;
* Select clauses are necessary to select a particular version of a feature&lt;br /&gt;
* Rename clauses are there to resolve name clashes&lt;br /&gt;
&lt;br /&gt;
=== Disallow recursion ===&lt;br /&gt;
As we've already seen in the section about renaming-issues recursive formals can add quite a lot of complexity to the language.&lt;br /&gt;
&lt;br /&gt;
Let's again have a look at this simple example:&lt;br /&gt;
&amp;lt;e&amp;gt;&lt;br /&gt;
class TEST[G -&amp;gt; H, H -&amp;gt; G]&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/e&amp;gt;&lt;br /&gt;
A valid generic derivation for this example has the property, that both formals have to be '''exactly the same type'''. Otherwise it's impossible to meet the constraints.&lt;br /&gt;
The conclusion is, that recursion has no practical benefit for the developer.&lt;br /&gt;
One can however define certain things more general and maybe mathematically more consistent. But as constraints are to a formal, what inheritance is to a class, it seems also consistent to disallow cycles for formals as well. As a cycle in the inheritance hierarchy is indeed invalid.&lt;br /&gt;
&lt;br /&gt;
=== Introduce a select clause with new semantics ===&lt;br /&gt;
According to the standard only the ''rename clause'' can be used. The ''select'' and the ''redefine'' clause cannot be used.&lt;br /&gt;
&amp;lt;e&amp;gt;&lt;br /&gt;
class MULTI [G -&amp;gt; {X select is_equal end,&lt;br /&gt;
                   Y select default_create end} create default_create end]&lt;br /&gt;
&lt;br /&gt;
feature&lt;br /&gt;
    g: G&lt;br /&gt;
&lt;br /&gt;
    some_feature&lt;br /&gt;
        do&lt;br /&gt;
            create g&lt;br /&gt;
            if g.is_equal (g) then&lt;br /&gt;
            end&lt;br /&gt;
        end&lt;br /&gt;
&amp;lt;/e&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If the programmer wants to access the versions of is_equal from X and Y he simply renames at least one of them to a different name.&lt;br /&gt;
&lt;br /&gt;
One has to emphasize that the usage of ''select'' has '''not''' the same semantic as in the multi-inheritance case: It does only mean that we select the type of the selected feature as static type for the call. The ''select clause'' in the multi-constraint case has no effect on any dynamic binding table.&lt;br /&gt;
&lt;br /&gt;
The ''select clause'' used in the multi constraint case has the following semantic:&lt;br /&gt;
* As soon as there is a name clash for a particular feature (regardless whether they are different features or not) the one which is selected will be used.&lt;br /&gt;
&lt;br /&gt;
This can be done like that because a multi constraint formal is always somehow the last virtual type of an inheritance path and one knows exactly which features should be available and which ones are not used. If the requirements change, one simply changes locally the rename and select clauses which has no effect on any client using this particular class.&lt;br /&gt;
&lt;br /&gt;
This would have the following benefits:&lt;br /&gt;
* Avoid renaming if not necessary&lt;br /&gt;
* Empower abstract creation again as one can use select in ambiguous cases&lt;br /&gt;
&lt;br /&gt;
and the following drawbacks:&lt;br /&gt;
* New semantic for select, possibly confusing&lt;/div&gt;</summary>
		<author><name>Seilerm</name></author>	</entry>

	<entry>
		<id>https://dev.eiffel.com/index.php?title=Multiple_constraints&amp;diff=9983</id>
		<title>Multiple constraints</title>
		<link rel="alternate" type="text/html" href="https://dev.eiffel.com/index.php?title=Multiple_constraints&amp;diff=9983"/>
				<updated>2007-11-06T22:03:34Z</updated>
		
		<summary type="html">&lt;p&gt;Seilerm: /* Using whats there */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Category:ECMA]]&lt;br /&gt;
==Description==&lt;br /&gt;
This article discusses issues which arise with multiple constrained type parameters.&lt;br /&gt;
==Formal generic type parameters with multiple constraints==&lt;br /&gt;
&lt;br /&gt;
The new [http://www.ecma-international.org/publications/standards/Ecma-367.htm ECMA standard] for Eiffel introduces multi-constraint formal generic type parameters.&lt;br /&gt;
&lt;br /&gt;
{|border=&amp;quot;0&amp;quot; cellpadding=&amp;quot;2&amp;quot; cellspacing=&amp;quot;0&amp;quot; align=&amp;quot;center&amp;quot;&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot; -halign=&amp;quot;center&amp;quot;&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
Example:&lt;br /&gt;
&amp;lt;code&amp;gt;[eiffel,N]&lt;br /&gt;
class C [G -&amp;gt; {A, B}]&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Class C expects a type parameter that conforms to A and B.&lt;br /&gt;
To make the text a bit easier to read I sometimes abbreviate the term 'formal generic type parameter' simply as 'formal'.&lt;br /&gt;
So &amp;quot;G is the only formal of class C&amp;quot; means that G is the only formal generic type parameter of class C.&lt;br /&gt;
&lt;br /&gt;
==Qualified calls==&lt;br /&gt;
====Explanation of the issue====&lt;br /&gt;
Consider this example inheritance hierarchy together with the following code:&lt;br /&gt;
&lt;br /&gt;
{|border=&amp;quot;0&amp;quot; cellpadding=&amp;quot;2&amp;quot; cellspacing=&amp;quot;0&amp;quot; align=&amp;quot;center&amp;quot;&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot; -halign=&amp;quot;center&amp;quot;&lt;br /&gt;
|[[Image:Class_diagram_for_multiple_constraints_explanation.png|173px]]&lt;br /&gt;
|&lt;br /&gt;
Example:&lt;br /&gt;
&amp;lt;e&amp;gt;&lt;br /&gt;
class GENERIC_CLASS [G -&amp;gt; {B, C}]&lt;br /&gt;
&lt;br /&gt;
feature&lt;br /&gt;
&lt;br /&gt;
   g: G&lt;br /&gt;
&lt;br /&gt;
   example is&lt;br /&gt;
      do       &lt;br /&gt;
         g.f      -- qualified feature call&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;
Our interest is focused on the qualified feature call ''g.f'' of the example feature. With the dynamic binding semantics defined in section ''8.16.11'' of the ECMA standard, it makes a difference whether the static type of ''g'' is ''A'', ''B'' or ''C''. An illustration of the differences can be found in the [[Transposition]] article.&lt;br /&gt;
&lt;br /&gt;
The standard defines in section ''8.12.23'' what the base type of such a multiple constrained formal type parameter is. It is a fictitious class (denoted as a dashed class ''FICT'' in the diagram) which inherits from all constraint classes and to which a possible renaming is applied. Dynamic binding requires a clear notion of what the static type of a target (here g) is. To obtain the correct feature, one needs the static and dynamic type of the target at runtime. Normally the base type of the target is taken as the static type. But we cannot take this fictitious base type as our static type, because, as can be seen in the diagram, it is outside of the conformance paths to X and therefore not usable with the current definition of dynamic binding.&lt;br /&gt;
&lt;br /&gt;
The definition of this fictitious type ''FICT'' can only be used to clearly define the set of available features to instances of type G. It can not be used to define the semantic of a qualified feature call (like f.a).&lt;br /&gt;
&lt;br /&gt;
To be able to use the type G one must provide a clear definition which static type is to use for a qualified feature call.&lt;br /&gt;
An ambiguous feature, regarding the dynamic binding problematic, is a feature which is inherited through multiple constraining types. In our example this is the case for the feature ''f''. It occurs in ''B'' and in ''C''.&lt;br /&gt;
&lt;br /&gt;
====Solution proposal: Common Ancestor====&lt;br /&gt;
&lt;br /&gt;
If we have a multi-constraint formal type parameter and a qualified feature call on a target of that type, we define the static type to be the type of the class which introduced the current version of the called feature body. This must be a common ancestor of the constraining class types which contain the feature ''f'' (in our case ''B'' and ''C'').&lt;br /&gt;
&lt;br /&gt;
In our example we would set the static type of ''f'' to ''A'' and then execute the qualified feature call.&lt;br /&gt;
&lt;br /&gt;
'''Properties of this solution:'''&lt;br /&gt;
&lt;br /&gt;
* All features can be directly called on a target of type ''G''.&lt;br /&gt;
&lt;br /&gt;
* The static type of ''g'' may change depending on which feature is called.&lt;br /&gt;
&lt;br /&gt;
====Solution proposal: Manual Static Type Selection====&lt;br /&gt;
&lt;br /&gt;
The basic idea is to disallow ambiguous qualified calls on targets of type ''G'' at all.&lt;br /&gt;
In our example it would '''not''' be valid to do the call ''g.f'' because the feature ''f'' is ambiguous as it is inherited over multiple paths (once through B and once through C).&lt;br /&gt;
&lt;br /&gt;
As a consequence the programmer needs to resolve ambiguities manually. He does that by using either &lt;br /&gt;
&lt;br /&gt;
* explicit renaming&lt;br /&gt;
* local variables&lt;br /&gt;
* object test&lt;br /&gt;
&lt;br /&gt;
'''Using explicit renaming:'''&lt;br /&gt;
&amp;lt;e&amp;gt;&lt;br /&gt;
class GENERIC_CLASS [G -&amp;gt; {B rename f as f_b end, C rename f as f_c end}]&lt;br /&gt;
&lt;br /&gt;
feature&lt;br /&gt;
&lt;br /&gt;
   g: G&lt;br /&gt;
&lt;br /&gt;
   example is&lt;br /&gt;
      do       &lt;br /&gt;
         g.f_b   -- qualified feature call with static type B&lt;br /&gt;
         g.f_c   -- qualified feature call with static type C&lt;br /&gt;
      end&lt;br /&gt;
&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/e&amp;gt;&lt;br /&gt;
The programmer resolves the issue by renaming in the first place.&lt;br /&gt;
&lt;br /&gt;
'''Using a local variable:'''&lt;br /&gt;
&amp;lt;code&amp;gt;[eiffel,N]&lt;br /&gt;
   example is&lt;br /&gt;
      local&lt;br /&gt;
         b: B&lt;br /&gt;
      do &lt;br /&gt;
         b := g&lt;br /&gt;
         b.f      -- qualified feature call with static type B&lt;br /&gt;
      end&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The programmer explicitly choses static type ''B'' by assigning ''g'' to the local variable ''b''.&lt;br /&gt;
&lt;br /&gt;
'''Using the object test:'''&lt;br /&gt;
&amp;lt;e&amp;gt;&lt;br /&gt;
   example is&lt;br /&gt;
      do &lt;br /&gt;
         check {bg: B | g } end&lt;br /&gt;
         bg.f  -- qualified feature call with static type B&lt;br /&gt;
      end&lt;br /&gt;
&amp;lt;/e&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In this version the static type is chosen due to an object test.&lt;br /&gt;
&lt;br /&gt;
'''Properties of this solution:'''&lt;br /&gt;
&lt;br /&gt;
* Not all feature calls can be applied to a target whose type is a multi-constraint generic.&lt;br /&gt;
&lt;br /&gt;
* The definition of the static type of every call remains straight forward.&lt;br /&gt;
&lt;br /&gt;
'''Option'''&lt;br /&gt;
&lt;br /&gt;
The renaming clause for multi-constraint types could be removed and name clashes could be regarded as ambiguous cases too. The user resolves it as shown above by choosing a static type explicitly over locals and object tests only.&lt;br /&gt;
&lt;br /&gt;
==Abstract creation==&lt;br /&gt;
It is not perfectly clear by reading the standard what the semantics of&lt;br /&gt;
&amp;lt;e&amp;gt;&lt;br /&gt;
create g&lt;br /&gt;
&amp;lt;/e&amp;gt;&lt;br /&gt;
Where the type of ''g'' is a multi-constraint formal.&lt;br /&gt;
&lt;br /&gt;
===By name===&lt;br /&gt;
Require a feature with name ''default_create'' in creation constraint clause and use that for the creation. But remember the routine id and the type as an actual generic derivation may use different renaming.&lt;br /&gt;
&lt;br /&gt;
* New semantic&lt;br /&gt;
* Programmer can always use an instruction of the form &amp;lt;e&amp;gt;create g&amp;lt;/e&amp;gt; as soon as he as a creation constraint with the name ''default_create''.&lt;br /&gt;
&lt;br /&gt;
===By version===&lt;br /&gt;
Require exactly one version of ''default_create'' from ''ANY'' in creation constraint clause to make a call like &amp;lt;e&amp;gt;create g&amp;lt;/e&amp;gt; valid.&lt;br /&gt;
&lt;br /&gt;
* No new semantic&lt;br /&gt;
* Programmer cannot always use an instruction of the form &amp;lt;e&amp;gt;create g&amp;lt;/e&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The following code illustrates a case where it is not possible to use &amp;lt;e&amp;gt;create g&amp;lt;/e&amp;gt;.&lt;br /&gt;
&amp;lt;e&amp;gt;&lt;br /&gt;
class MULTI [G -&amp;gt; {X rename default_create as dc_x,&lt;br /&gt;
                   Y rename default_create as dc_y end} create dc_x, dc_y end]&lt;br /&gt;
feature&lt;br /&gt;
    g: G&lt;br /&gt;
&lt;br /&gt;
    some_feature&lt;br /&gt;
            -- Some feature&lt;br /&gt;
        do&lt;br /&gt;
            create g.dc_x -- 1&lt;br /&gt;
            create g.dc_y -- 2&lt;br /&gt;
            create g      -- 3&lt;br /&gt;
        end&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/e&amp;gt;&lt;br /&gt;
* 1 and 2: The creation of ''g'' is ok as we have an explicit invocation of the creation feature.&lt;br /&gt;
* 3: The abstract creation is not ok as ''dc_x'' and ''dc_y'' are both versions of ''default_create'' from ''ANY''.&lt;br /&gt;
&lt;br /&gt;
==Formal generic type parameters in constraints==&lt;br /&gt;
&lt;br /&gt;
===Introduction===&lt;br /&gt;
As a special case of a constraint a formal is allowed:&lt;br /&gt;
&amp;lt;e&amp;gt;&lt;br /&gt;
class C [G -&amp;gt; {H, A}, H -&amp;gt; {A, B}]&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/e&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Recursive definitions are allowed too and explicitly mentioned in the standard:&lt;br /&gt;
&amp;lt;e&amp;gt;&lt;br /&gt;
class C [G -&amp;gt; {H, A}, H -&amp;gt; {A, B, G}]&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/e&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Renaming Issues===&lt;br /&gt;
The question is now, how the renaming is handled for formal generic types.&lt;br /&gt;
&lt;br /&gt;
* [[#By using the base type|One could use the base type and]] apply a further renaming to it.&lt;br /&gt;
* One [[#By disallowing renaming on formals|disallows renaming on formals]].&lt;br /&gt;
&lt;br /&gt;
====Solution proposal: Base Type====&lt;br /&gt;
As [[#Explanation of the issue|previously stated]] the base type of a multi-constraint formal is defined in section ''8.12.23: Base type of a multi-constraint formal generic type'' and it can be used to define which features are available to the formal.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;e&amp;gt;&lt;br /&gt;
class C [G -&amp;gt; {H rename is_eq_a as is_eq_h_a end,&lt;br /&gt;
               A rename is_eq as is_eq_a},&lt;br /&gt;
         H -&amp;gt; {A rename is_eq as is_eq_a end,&lt;br /&gt;
               B}]&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/e&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This approach however can become more complex if you consider it in the context of a set of formals which include a recursion in their definition:&lt;br /&gt;
&amp;lt;e&amp;gt;&lt;br /&gt;
class C [G -&amp;gt; H rename is_equal as is_equal_of_h end,&lt;br /&gt;
         H -&amp;gt; G rename is_equal_of_h as is_equal end]&lt;br /&gt;
feature&lt;br /&gt;
   f&lt;br /&gt;
      local&lt;br /&gt;
         l_g: G&lt;br /&gt;
         l_h: H&lt;br /&gt;
      do&lt;br /&gt;
         l_g.is_equal_of_h (l_h)&lt;br /&gt;
         l_h.is_equal (l_g)&lt;br /&gt;
      end&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/e&amp;gt;&lt;br /&gt;
The base types of G and H look according to the definition something like this:&lt;br /&gt;
&amp;lt;e&amp;gt;&lt;br /&gt;
class FICT_BASE_TYPE_OF_G&lt;br /&gt;
inherit&lt;br /&gt;
   H&lt;br /&gt;
      rename is_equal as is_equal_of_h end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
class FICT_BASE_TYPE_OF_H&lt;br /&gt;
inherit&lt;br /&gt;
   G&lt;br /&gt;
      rename is_equal_of_h as is_equal end&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/e&amp;gt;&lt;br /&gt;
All the other conflicts (feature name clashes) which occur are resolved through renaming as well according to the definition. This renaming is however not accessible by the developer and omitted in the example.&lt;br /&gt;
&lt;br /&gt;
What is noteworthy for this example is:&lt;br /&gt;
* A formal occurs directly in the inheritance part.&lt;br /&gt;
* There is a cycle in the inheritance hierarchy.&lt;br /&gt;
&lt;br /&gt;
Both of them are not allowed in proper Eiffel code.&lt;br /&gt;
&lt;br /&gt;
====Solution proposal: No Renaming on Formals====&lt;br /&gt;
This forces the developer to rename each feature he wants to use once properly to it's final name.&lt;br /&gt;
&amp;lt;e&amp;gt;&lt;br /&gt;
class C [G -&amp;gt; {H,&lt;br /&gt;
               A rename is_eq as is_eq_g_a end},&lt;br /&gt;
         H -&amp;gt; {A rename is_eq as is_eq_h_a end,&lt;br /&gt;
               B rename is_eq as is_eq_b_a end}]&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/e&amp;gt;&lt;br /&gt;
== A second look on multi constraints ==&lt;br /&gt;
&lt;br /&gt;
=== Why multi constraint generics? ===&lt;br /&gt;
One could actually &amp;quot;simulate&amp;quot; it by introducing a new class which inherits from the constraints and using this new class as the actual constraint.&lt;br /&gt;
This is not possible as soon as one uses a predefined library which one cannot change easily.&lt;br /&gt;
That is really a reason why we need multi-constraint formals besides the syntactical sugar.&lt;br /&gt;
For example one cannot introduce a class COMPARABLE_NUMERIC and then use it as a constraint.&lt;br /&gt;
&lt;br /&gt;
=== Using whats there ===&lt;br /&gt;
&lt;br /&gt;
Issues which arise in the context of multi constraint formal generics are in many ways similar to the ones which have already been solved for multiple inheritance: &lt;br /&gt;
&lt;br /&gt;
* Inheritance cycles are not valid&lt;br /&gt;
* Select clauses are necessary to select a particular version of a feature&lt;br /&gt;
* Rename clauses are there to resolve name clashes&lt;br /&gt;
&lt;br /&gt;
=== Disallow recursion ===&lt;br /&gt;
As we've already seen in the section about renaming-issues recursive formals can add quite a lot of complexity to the language.&lt;br /&gt;
&lt;br /&gt;
Let's again have a look at this simple example:&lt;br /&gt;
&amp;lt;e&amp;gt;&lt;br /&gt;
class TEST[G -&amp;gt; H, H -&amp;gt; G]&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/e&amp;gt;&lt;br /&gt;
A valid generic derivation for this example has the property, that both formals have to be '''exactly the same type'''. Otherwise it's impossible to meet the constraints.&lt;br /&gt;
The conclusion is, that recursion has no practical benefit for the developer.&lt;br /&gt;
One can however define certain things more general and maybe mathematically more consistent. But as constraints are to a formal, what inheritance is to a class, it seems also consistent to disallow cycles for formals as well. As a cycle in the inheritance hierarchy is indeed invalid.&lt;br /&gt;
&lt;br /&gt;
=== Introduce a select clause with new semantics ===&lt;br /&gt;
According to the standard only the ''rename clause'' can be used. The ''select'' and the ''redefine'' clause cannot be used.&lt;br /&gt;
&amp;lt;e&amp;gt;&lt;br /&gt;
class MULTI [G -&amp;gt; {X select is_equal end,&lt;br /&gt;
                   Y select default_create end} create default_create end]&lt;br /&gt;
&lt;br /&gt;
feature&lt;br /&gt;
    g: G&lt;br /&gt;
&lt;br /&gt;
    some_feature&lt;br /&gt;
        do&lt;br /&gt;
            create g&lt;br /&gt;
            if g.is_equal (g) then&lt;br /&gt;
            end&lt;br /&gt;
        end&lt;br /&gt;
&amp;lt;/e&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If the programmer wants to access the versions of is_equal from X and Y he simply renames at least one of them to a different name.&lt;br /&gt;
&lt;br /&gt;
One has to emphasize that the usage of ''select'' has '''not''' the same semantic as in the multi-inheritance case: It does only mean that we select the type of the selected feature as static type for the call. The ''select clause'' in the multi-constraint case has no effect on any dynamic binding table.&lt;br /&gt;
&lt;br /&gt;
The ''select clause'' used in the multi constraint case has the following semantic:&lt;br /&gt;
* As soon as there is a name clash for a particular feature (regardless whether they are different features or not) the one which is selected will be used.&lt;br /&gt;
&lt;br /&gt;
This can be done like that because a multi constraint formal is always somehow the last virtual type of an inheritance path and one knows exactly which features should be available and which ones are not used. If the requirements change, one simply changes locally the rename and select clauses which has no effect on any client using this particular class.&lt;br /&gt;
&lt;br /&gt;
This would have the following benefits:&lt;br /&gt;
* Avoid renaming if not necessary&lt;br /&gt;
* Empower abstract creation again as one can use select in ambiguous cases&lt;br /&gt;
&lt;br /&gt;
and the following drawbacks:&lt;br /&gt;
* New semantic for select, possibly confusing&lt;/div&gt;</summary>
		<author><name>Seilerm</name></author>	</entry>

	<entry>
		<id>https://dev.eiffel.com/index.php?title=Talk:Interval_types&amp;diff=8983</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=8983"/>
				<updated>2007-07-10T18:33:19Z</updated>
		
		<summary type="html">&lt;p&gt;Seilerm: &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;/div&gt;</summary>
		<author><name>Seilerm</name></author>	</entry>

	<entry>
		<id>https://dev.eiffel.com/index.php?title=Restrict_types&amp;diff=8923</id>
		<title>Restrict types</title>
		<link rel="alternate" type="text/html" href="https://dev.eiffel.com/index.php?title=Restrict_types&amp;diff=8923"/>
				<updated>2007-06-24T23:27:20Z</updated>
		
		<summary type="html">&lt;p&gt;Seilerm: enhanced Void/NONE example&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; prohibits some assignments.&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 restrict 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;
So if the programmer wants to do this he has to declare `a_t' differently:&lt;br /&gt;
&amp;lt;e&amp;gt;&lt;br /&gt;
a_t: T restrict {T, NONE}&lt;br /&gt;
a_t := Void&lt;br /&gt;
&amp;lt;/e&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Now &amp;lt;e&amp;gt;{NONE}&amp;lt;/e&amp;gt;is a 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>Seilerm</name></author>	</entry>

	<entry>
		<id>https://dev.eiffel.com/index.php?title=Forget_/_keep&amp;diff=8899</id>
		<title>Forget / keep</title>
		<link rel="alternate" type="text/html" href="https://dev.eiffel.com/index.php?title=Forget_/_keep&amp;diff=8899"/>
				<updated>2007-06-24T18:38:22Z</updated>
		
		<summary type="html">&lt;p&gt;Seilerm: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Category:ECMA]]&lt;br /&gt;
[[Category:Catcall]]&lt;br /&gt;
{{Warning|Research article}}&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>Seilerm</name></author>	</entry>

	<entry>
		<id>https://dev.eiffel.com/index.php?title=Forget_/_keep&amp;diff=8898</id>
		<title>Forget / keep</title>
		<link rel="alternate" type="text/html" href="https://dev.eiffel.com/index.php?title=Forget_/_keep&amp;diff=8898"/>
				<updated>2007-06-24T18:37:46Z</updated>
		
		<summary type="html">&lt;p&gt;Seilerm: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Category:ECMA]]&lt;br /&gt;
[[Category:Catcall]]&lt;br /&gt;
{{Warning|Research Article}}&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>Seilerm</name></author>	</entry>

	<entry>
		<id>https://dev.eiffel.com/index.php?title=Novariance&amp;diff=8897</id>
		<title>Novariance</title>
		<link rel="alternate" type="text/html" href="https://dev.eiffel.com/index.php?title=Novariance&amp;diff=8897"/>
				<updated>2007-06-24T18:36:40Z</updated>
		
		<summary type="html">&lt;p&gt;Seilerm: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Category:ECMA]]&lt;br /&gt;
[[Category:Catcall]]&lt;br /&gt;
{{Warning|Research Article}}&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>Seilerm</name></author>	</entry>

	<entry>
		<id>https://dev.eiffel.com/index.php?title=Novariance&amp;diff=8896</id>
		<title>Novariance</title>
		<link rel="alternate" type="text/html" href="https://dev.eiffel.com/index.php?title=Novariance&amp;diff=8896"/>
				<updated>2007-06-24T18:36:00Z</updated>
		
		<summary type="html">&lt;p&gt;Seilerm: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Category:ECMA]]&lt;br /&gt;
[[Category:Catcall]]&lt;br /&gt;
{{Warning: Research Article}}&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>Seilerm</name></author>	</entry>

	<entry>
		<id>https://dev.eiffel.com/index.php?title=Catcall_checkpoints&amp;diff=8893</id>
		<title>Catcall checkpoints</title>
		<link rel="alternate" type="text/html" href="https://dev.eiffel.com/index.php?title=Catcall_checkpoints&amp;diff=8893"/>
				<updated>2007-06-24T06:43:01Z</updated>
		
		<summary type="html">&lt;p&gt;Seilerm: /* Agents */&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>Seilerm</name></author>	</entry>

	<entry>
		<id>https://dev.eiffel.com/index.php?title=Catcall_checkpoints&amp;diff=8892</id>
		<title>Catcall checkpoints</title>
		<link rel="alternate" type="text/html" href="https://dev.eiffel.com/index.php?title=Catcall_checkpoints&amp;diff=8892"/>
				<updated>2007-06-24T06:42:39Z</updated>
		
		<summary type="html">&lt;p&gt;Seilerm: added agent example&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>Seilerm</name></author>	</entry>

	<entry>
		<id>https://dev.eiffel.com/index.php?title=Usage-site_variance&amp;diff=8879</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=8879"/>
				<updated>2007-06-23T23:01:06Z</updated>
		
		<summary type="html">&lt;p&gt;Seilerm: /* Vision 2 Example */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Category:ECMA]]&lt;br /&gt;
[[Category:Catcall]]&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; action: PROCEDURE [ANY, TUPLE]) is&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>Seilerm</name></author>	</entry>

	<entry>
		<id>https://dev.eiffel.com/index.php?title=Usage-site_variance&amp;diff=8878</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=8878"/>
				<updated>2007-06-23T22:52:00Z</updated>
		
		<summary type="html">&lt;p&gt;Seilerm: /* Vision 2 Example */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Category:ECMA]]&lt;br /&gt;
[[Category:Catcall]]&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;
 &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; action: PROCEDURE [ANY, TUPLE]) is&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;
    -- Note `+' in front of `TUPLE' as it is indeed covariant: We accept all kind&lt;br /&gt;
    --  of EVENT_DATA as long it is a descendant of `TUPLE', like `TUPLE [ANY, INTEGER]'.&lt;br /&gt;
&lt;br /&gt;
inherit&lt;br /&gt;
  -- old ARRAYED_LIST [PROCEDURE [ANY, EVENT_DATA]]&lt;br /&gt;
  ARRAYED_LIST [PROCEDURE [+ANY, -EVENT_DATA]]&lt;br /&gt;
    rename&lt;br /&gt;
      -- ...&lt;br /&gt;
    end&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;
   ...&lt;br /&gt;
end&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>Seilerm</name></author>	</entry>

	<entry>
		<id>https://dev.eiffel.com/index.php?title=Usage-site_variance&amp;diff=8875</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=8875"/>
				<updated>2007-06-23T22:48:14Z</updated>
		
		<summary type="html">&lt;p&gt;Seilerm: /* Vision 2 Example */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Category:ECMA]]&lt;br /&gt;
[[Category:Catcall]]&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;
 &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; action: PROCEDURE [ANY, TUPLE]) is&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;
            -- Note `+' in front of `TUPLE' as it is indeed covariant: We accept all kind&lt;br /&gt;
            --  of EVENT_DATA as long it is a descendant of `TUPLE', like `TUPLE [ANY, INTEGER]'.&lt;br /&gt;
&lt;br /&gt;
inherit&lt;br /&gt;
	-- old ARRAYED_LIST [PROCEDURE [ANY, EVENT_DATA]]&lt;br /&gt;
        ARRAYED_LIST [PROCEDURE [+ANY, -EVENT_DATA]]&lt;br /&gt;
		rename&lt;br /&gt;
		  -- ...&lt;br /&gt;
		end&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;
   ...&lt;br /&gt;
end&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>Seilerm</name></author>	</entry>

	<entry>
		<id>https://dev.eiffel.com/index.php?title=Usage-site_variance&amp;diff=8874</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=8874"/>
				<updated>2007-06-23T22:46:30Z</updated>
		
		<summary type="html">&lt;p&gt;Seilerm: /* Vision 2 Example */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Category:ECMA]]&lt;br /&gt;
[[Category:Catcall]]&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;
 &lt;br /&gt;
  force_extend (action: PROCEDURE [ANY, TUPLE]) is&lt;br /&gt;
      -- Extend without type checking.&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; action: PROCEDURE [ANY, TUPLE]) is&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;
            -- Note `+' in front of `TUPLE' as it is indeed covariant: We accept all kind&lt;br /&gt;
            --  of EVENT_DATA as long it is a descendant of `TUPLE', like `TUPLE [ANY, INTEGER]'.&lt;br /&gt;
&lt;br /&gt;
inherit&lt;br /&gt;
	-- old ARRAYED_LIST [PROCEDURE [ANY, EVENT_DATA]]&lt;br /&gt;
        ARRAYED_LIST [PROCEDURE [+ANY, -EVENT_DATA]]&lt;br /&gt;
		rename&lt;br /&gt;
			make as arrayed_list_make&lt;br /&gt;
		export&lt;br /&gt;
			{ACTION_SEQUENCE} same_items, subarray&lt;br /&gt;
		redefine&lt;br /&gt;
			default_create,&lt;br /&gt;
			set_count&lt;br /&gt;
		end&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;
   ...&lt;br /&gt;
end&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>Seilerm</name></author>	</entry>

	<entry>
		<id>https://dev.eiffel.com/index.php?title=Usage-site_variance&amp;diff=8873</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=8873"/>
				<updated>2007-06-23T22:46:02Z</updated>
		
		<summary type="html">&lt;p&gt;Seilerm: /* Vision 2 Example */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Category:ECMA]]&lt;br /&gt;
[[Category:Catcall]]&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 intrested 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;
 &lt;br /&gt;
  force_extend (action: PROCEDURE [ANY, TUPLE]) is&lt;br /&gt;
      -- Extend without type checking.&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; action: PROCEDURE [ANY, TUPLE]) is&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;
            -- Note `+' in front of `TUPLE' as it is indeed covariant: We accept all kind&lt;br /&gt;
            --  of EVENT_DATA as long it is a descendant of `TUPLE', like `TUPLE [ANY, INTEGER]'.&lt;br /&gt;
&lt;br /&gt;
inherit&lt;br /&gt;
	-- old ARRAYED_LIST [PROCEDURE [ANY, EVENT_DATA]]&lt;br /&gt;
        ARRAYED_LIST [PROCEDURE [+ANY, -EVENT_DATA]]&lt;br /&gt;
		rename&lt;br /&gt;
			make as arrayed_list_make&lt;br /&gt;
		export&lt;br /&gt;
			{ACTION_SEQUENCE} same_items, subarray&lt;br /&gt;
		redefine&lt;br /&gt;
			default_create,&lt;br /&gt;
			set_count&lt;br /&gt;
		end&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;
   ...&lt;br /&gt;
end&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>Seilerm</name></author>	</entry>

	<entry>
		<id>https://dev.eiffel.com/index.php?title=Usage-site_variance&amp;diff=8871</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=8871"/>
				<updated>2007-06-23T22:44:47Z</updated>
		
		<summary type="html">&lt;p&gt;Seilerm: /* Vision 2 Example */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Category:ECMA]]&lt;br /&gt;
[[Category:Catcall]]&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.&lt;br /&gt;
&amp;lt;e&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
  force_extend (action: PROCEDURE [ANY, TUPLE]) is&lt;br /&gt;
      -- Extend without type checking.&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; action: PROCEDURE [ANY, TUPLE]) is&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;
            -- Note `+' in front of `TUPLE' as it is indeed covariant: We accept all kind&lt;br /&gt;
            --  of EVENT_DATA as long it is a descendant of `TUPLE', like `TUPLE [ANY, INTEGER]'.&lt;br /&gt;
&lt;br /&gt;
inherit&lt;br /&gt;
	-- old ARRAYED_LIST [PROCEDURE [ANY, EVENT_DATA]]&lt;br /&gt;
        ARRAYED_LIST [PROCEDURE [+ANY, -EVENT_DATA]]&lt;br /&gt;
		rename&lt;br /&gt;
			make as arrayed_list_make&lt;br /&gt;
		export&lt;br /&gt;
			{ACTION_SEQUENCE} same_items, subarray&lt;br /&gt;
		redefine&lt;br /&gt;
			default_create,&lt;br /&gt;
			set_count&lt;br /&gt;
		end&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;
   ...&lt;br /&gt;
end&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>Seilerm</name></author>	</entry>

	<entry>
		<id>https://dev.eiffel.com/index.php?title=Usage-site_variance&amp;diff=8870</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=8870"/>
				<updated>2007-06-23T22:43:09Z</updated>
		
		<summary type="html">&lt;p&gt;Seilerm: /* Vision 2 Example */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Category:ECMA]]&lt;br /&gt;
[[Category:Catcall]]&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.&lt;br /&gt;
&amp;lt;e&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
  force_extend (action: PROCEDURE [ANY, TUPLE]) is&lt;br /&gt;
      -- Extend without type checking.&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; action: PROCEDURE [ANY, TUPLE]) is&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 -EVENT_DATA).&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;
            -- Note `+' in front of `TUPLE' as it is indeed covariant: We accept all kind&lt;br /&gt;
            --  of EVENT_DATA as long it is a descendant of `TUPLE', like `TUPLE [ANY, INTEGER]'.&lt;br /&gt;
&lt;br /&gt;
inherit&lt;br /&gt;
	-- old ARRAYED_LIST [PROCEDURE [ANY, EVENT_DATA]]&lt;br /&gt;
        ARRAYED_LIST [PROCEDURE [+ANY, -EVENT_DATA]]&lt;br /&gt;
		rename&lt;br /&gt;
			make as arrayed_list_make&lt;br /&gt;
		export&lt;br /&gt;
			{ACTION_SEQUENCE} same_items, subarray&lt;br /&gt;
		redefine&lt;br /&gt;
			default_create,&lt;br /&gt;
			set_count&lt;br /&gt;
		end&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;
   ...&lt;br /&gt;
end&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>Seilerm</name></author>	</entry>

	<entry>
		<id>https://dev.eiffel.com/index.php?title=Usage-site_variance&amp;diff=8869</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=8869"/>
				<updated>2007-06-23T22:39:14Z</updated>
		
		<summary type="html">&lt;p&gt;Seilerm: /* Vision 2 Example */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Category:ECMA]]&lt;br /&gt;
[[Category:Catcall]]&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.&lt;br /&gt;
&amp;lt;e&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
  force_extend (action: PROCEDURE [ANY, TUPLE]) is&lt;br /&gt;
      -- Extend without type checking.&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; action: PROCEDURE [ANY, TUPLE]) is&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 -EVENT_DATA).&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;
            -- Note `+' in front of `TUPLE' as it is covariant, we accept all kind of EVENT_DATA&lt;br /&gt;
            -- which is some subtype of `TUPLE'.&lt;br /&gt;
&lt;br /&gt;
inherit&lt;br /&gt;
	-- old ARRAYED_LIST [PROCEDURE [ANY, EVENT_DATA]]&lt;br /&gt;
        ARRAYED_LIST [PROCEDURE [+ANY, -EVENT_DATA]]&lt;br /&gt;
		rename&lt;br /&gt;
			make as arrayed_list_make&lt;br /&gt;
		export&lt;br /&gt;
			{ACTION_SEQUENCE} same_items, subarray&lt;br /&gt;
		redefine&lt;br /&gt;
			default_create,&lt;br /&gt;
			set_count&lt;br /&gt;
		end&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;
   ...&lt;br /&gt;
end&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>Seilerm</name></author>	</entry>

	<entry>
		<id>https://dev.eiffel.com/index.php?title=Usage-site_variance&amp;diff=8865</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=8865"/>
				<updated>2007-06-23T22:35:12Z</updated>
		
		<summary type="html">&lt;p&gt;Seilerm: /* Vision 2 Example */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Category:ECMA]]&lt;br /&gt;
[[Category:Catcall]]&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.&lt;br /&gt;
&amp;lt;e&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
  force_extend (action: PROCEDURE [ANY, TUPLE]) is&lt;br /&gt;
      -- Extend without type checking.&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; action: PROCEDURE [ANY, TUPLE]) is&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.&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;
&lt;br /&gt;
inherit&lt;br /&gt;
	-- old ARRAYED_LIST [PROCEDURE [ANY, EVENT_DATA]]&lt;br /&gt;
        ARRAYED_LIST [PROCEDURE [+ANY, -EVENT_DATA]]&lt;br /&gt;
		rename&lt;br /&gt;
			make as arrayed_list_make&lt;br /&gt;
		export&lt;br /&gt;
			{ACTION_SEQUENCE} same_items, subarray&lt;br /&gt;
		redefine&lt;br /&gt;
			default_create,&lt;br /&gt;
			set_count&lt;br /&gt;
		end&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;
   ...&lt;br /&gt;
end&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>Seilerm</name></author>	</entry>

	<entry>
		<id>https://dev.eiffel.com/index.php?title=Usage-site_variance&amp;diff=8853</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=8853"/>
				<updated>2007-06-23T21:24:06Z</updated>
		
		<summary type="html">&lt;p&gt;Seilerm: /* Agents */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Category:ECMA]]&lt;br /&gt;
[[Category:Catcall]]&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;
&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>Seilerm</name></author>	</entry>

	<entry>
		<id>https://dev.eiffel.com/index.php?title=Forget_/_keep&amp;diff=8848</id>
		<title>Forget / keep</title>
		<link rel="alternate" type="text/html" href="https://dev.eiffel.com/index.php?title=Forget_/_keep&amp;diff=8848"/>
				<updated>2007-06-23T19:09:40Z</updated>
		
		<summary type="html">&lt;p&gt;Seilerm: /* A Simple Generic Algorithm */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Category:ECMA]]&lt;br /&gt;
[[Category:Catcall]]&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;
== Conclusion ==&lt;br /&gt;
This proposal solves CAT calls as a whole. This include CAT calls 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 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>Seilerm</name></author>	</entry>

	<entry>
		<id>https://dev.eiffel.com/index.php?title=Comparison_of_catcall_solutions&amp;diff=8834</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=8834"/>
				<updated>2007-06-23T02:28:59Z</updated>
		
		<summary type="html">&lt;p&gt;Seilerm: /* Generic vs. non-generic covariance */&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;
; 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;
; 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, ISE 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;
== 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.&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;
|colspan=4 |&lt;br /&gt;
=== General solutions ===&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}}&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;
| {{Red|Very limited}}&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;
! Whole-system analysis&lt;br /&gt;
| {{Green|No}}&lt;br /&gt;
| {{Orange|Partial}}&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;
| {{Orange|Limited}}&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;
| {{Red|Difficult}}&lt;br /&gt;
| {{Green|Not needed}}&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
&lt;br /&gt;
|colspan=4 |&lt;br /&gt;
&lt;br /&gt;
=== Solutions for non-generics ===&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;
! 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;
|colspan=4 |&lt;br /&gt;
&lt;br /&gt;
=== Solutions for generics ===&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|Save}}&lt;br /&gt;
| {{Orange|Almost fully supported}}&amp;lt;br/&amp;gt;{{Green|Save}}&lt;br /&gt;
| {{Green|Fully supported}}&amp;lt;br/&amp;gt;{{Green|Save}}&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;
! 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;
|colspan=4 |&lt;br /&gt;
&lt;br /&gt;
=== Dynamic solutions ===&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|As it is now}}&lt;br /&gt;
| {{Green|As it is now}}&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;
! 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;
== Personal opinions ==&lt;br /&gt;
&lt;br /&gt;
[[Personal view about catcall solution]]&lt;/div&gt;</summary>
		<author><name>Seilerm</name></author>	</entry>

	<entry>
		<id>https://dev.eiffel.com/index.php?title=Comparison_of_catcall_solutions&amp;diff=8833</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=8833"/>
				<updated>2007-06-23T02:28:21Z</updated>
		
		<summary type="html">&lt;p&gt;Seilerm: /* Generic vs. non-generic covariance */&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;
; 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;
; 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, ISE 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 LIST [ANY] to LINKED_LIST [ANY] 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;
== 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.&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;
|colspan=4 |&lt;br /&gt;
=== General solutions ===&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}}&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;
| {{Red|Very limited}}&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;
! Whole-system analysis&lt;br /&gt;
| {{Green|No}}&lt;br /&gt;
| {{Orange|Partial}}&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;
| {{Orange|Limited}}&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;
| {{Red|Difficult}}&lt;br /&gt;
| {{Green|Not needed}}&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
&lt;br /&gt;
|colspan=4 |&lt;br /&gt;
&lt;br /&gt;
=== Solutions for non-generics ===&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;
! 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;
|colspan=4 |&lt;br /&gt;
&lt;br /&gt;
=== Solutions for generics ===&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|Save}}&lt;br /&gt;
| {{Orange|Almost fully supported}}&amp;lt;br/&amp;gt;{{Green|Save}}&lt;br /&gt;
| {{Green|Fully supported}}&amp;lt;br/&amp;gt;{{Green|Save}}&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;
! 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;
|colspan=4 |&lt;br /&gt;
&lt;br /&gt;
=== Dynamic solutions ===&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|As it is now}}&lt;br /&gt;
| {{Green|As it is now}}&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;
! 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;
== Personal opinions ==&lt;br /&gt;
&lt;br /&gt;
[[Personal view about catcall solution]]&lt;/div&gt;</summary>
		<author><name>Seilerm</name></author>	</entry>

	<entry>
		<id>https://dev.eiffel.com/index.php?title=Agent_syntax&amp;diff=8824</id>
		<title>Agent syntax</title>
		<link rel="alternate" type="text/html" href="https://dev.eiffel.com/index.php?title=Agent_syntax&amp;diff=8824"/>
				<updated>2007-06-23T01:56:17Z</updated>
		
		<summary type="html">&lt;p&gt;Seilerm: initial copy from internal wiki&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Category:ECMA]]&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>Seilerm</name></author>	</entry>

	<entry>
		<id>https://dev.eiffel.com/index.php?title=Definition-site_variance&amp;diff=8821</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=8821"/>
				<updated>2007-06-23T01:55:09Z</updated>
		
		<summary type="html">&lt;p&gt;Seilerm: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Category:ECMA]]&lt;br /&gt;
[[Category:Catcall]]&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>Seilerm</name></author>	</entry>

	<entry>
		<id>https://dev.eiffel.com/index.php?title=Detachable_types&amp;diff=8818</id>
		<title>Detachable types</title>
		<link rel="alternate" type="text/html" href="https://dev.eiffel.com/index.php?title=Detachable_types&amp;diff=8818"/>
				<updated>2007-06-23T01:54:00Z</updated>
		
		<summary type="html">&lt;p&gt;Seilerm: copy from internal wiki&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Category:ECMA]]&lt;br /&gt;
[[Category:Catcall]]&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;
=== 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 expaned 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 expaned 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 expaned 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 expaned 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 severly limit the usefulness of covariance.&lt;/div&gt;</summary>
		<author><name>Seilerm</name></author>	</entry>

	<entry>
		<id>https://dev.eiffel.com/index.php?title=EiffelStudio_6.0_Features&amp;diff=8243</id>
		<title>EiffelStudio 6.0 Features</title>
		<link rel="alternate" type="text/html" href="https://dev.eiffel.com/index.php?title=EiffelStudio_6.0_Features&amp;diff=8243"/>
				<updated>2007-04-24T17:41:11Z</updated>
		
		<summary type="html">&lt;p&gt;Seilerm: /* Eiffel Language/Compiler */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Category:Releases]]&lt;br /&gt;
&lt;br /&gt;
This page highlights some of the major feature changes between versions 5.7 and the forthcoming 6.0 release of EiffelStudio. &lt;br /&gt;
&lt;br /&gt;
For the 6.0 change log see [[EiffelStudio Releases]].&lt;br /&gt;
&lt;br /&gt;
== EiffelStudio (General) ==&lt;br /&gt;
&lt;br /&gt;
* New docking manager graphical interface&lt;br /&gt;
&lt;br /&gt;
== New Tools ==&lt;br /&gt;
&lt;br /&gt;
== Debugger ==&lt;br /&gt;
&lt;br /&gt;
== Eiffel Language/Compiler ==&lt;br /&gt;
&lt;br /&gt;
* [[Compilation Without Configuration]]&lt;br /&gt;
* Multi constraint formal generic type parameters&lt;br /&gt;
&lt;br /&gt;
== Libraries ==&lt;/div&gt;</summary>
		<author><name>Seilerm</name></author>	</entry>

	<entry>
		<id>https://dev.eiffel.com/index.php?title=Current_implementation_of_multi_constraint_formals&amp;diff=8242</id>
		<title>Current implementation of multi constraint formals</title>
		<link rel="alternate" type="text/html" href="https://dev.eiffel.com/index.php?title=Current_implementation_of_multi_constraint_formals&amp;diff=8242"/>
				<updated>2007-04-24T17:39:22Z</updated>
		
		<summary type="html">&lt;p&gt;Seilerm: /* Creation without call to explicit creation feature */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Category:Compiler]]&lt;br /&gt;
{{UnderConstruction}}&lt;br /&gt;
&lt;br /&gt;
==Introduction==&lt;br /&gt;
The first implementation of multi constraints is done and this article describes its current implementation status.&lt;br /&gt;
&lt;br /&gt;
Let's take this example&lt;br /&gt;
&amp;lt;e&amp;gt;&lt;br /&gt;
MULTI [G -&amp;gt; {H, COMPARABLE rename is_equal as is_equal_cmp end},&lt;br /&gt;
      H -&amp;gt; {NUMERIC rename default_create as default_create_num end, G}]&lt;br /&gt;
&amp;lt;/e&amp;gt;&lt;br /&gt;
A type satisfying the constraint of ''G'' has the following properties:&lt;br /&gt;
* It conforms to whatever ''H'' is and therefore&lt;br /&gt;
** to &amp;lt;e&amp;gt;NUMERIC&amp;lt;/e&amp;gt; and &lt;br /&gt;
** by recursion to itself (''G'')&lt;br /&gt;
* It conforms to its second constraint which is &amp;lt;e&amp;gt;COMPARABLE&amp;lt;/e&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
A type satisfying the constraint of ''H'' has the following properties:&lt;br /&gt;
* It conforms to &amp;lt;e&amp;gt;NUMERIC&amp;lt;/e&amp;gt;.&lt;br /&gt;
* It conforms to ''G'' and therefore&lt;br /&gt;
** by recursion to itself (''H'') and&lt;br /&gt;
** to &amp;lt;e&amp;gt;COMPARABLE&amp;lt;/e&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
As ''G'' and ''H'' both have to conform to each other the only possibility to satisfy this is that ''G'' and ''H'' must be the same in the generic derivation. It does not make much sense to program something like that but it is part of the current implementation.&lt;br /&gt;
&lt;br /&gt;
=== Feature calls ===&lt;br /&gt;
&lt;br /&gt;
Let's have a look at the following feature written in class ''MULTI'':&lt;br /&gt;
&amp;lt;e&amp;gt;&lt;br /&gt;
feature&lt;br /&gt;
    g: G&lt;br /&gt;
&lt;br /&gt;
    f: BOOLEAN&lt;br /&gt;
            -- Sample feature&lt;br /&gt;
        do&lt;br /&gt;
            create g -- 1&lt;br /&gt;
            Result := g.is_equal(g) -- 2&lt;br /&gt;
        end&lt;br /&gt;
&amp;lt;/e&amp;gt;&lt;br /&gt;
The following rules have to hold for each call on a multi constraint formal:&lt;br /&gt;
* Every feature which is called has exactly one class which is used as the static type for the call.&lt;br /&gt;
&lt;br /&gt;
This is a major difference to the ECMA standard which allows a call to features which are available through different classes as long as it is the same feature. A definition of what the ''same feature'' means can be found [[Replication|here]].&lt;br /&gt;
&lt;br /&gt;
In order to achieve that goal if a feature occurs with the same name in  different classes one uses a rename clause and renames that feature. If there are name clashes between features and one does not want to call that feature a renaming is '''not''' needed.&lt;br /&gt;
&lt;br /&gt;
As we perform calls to &amp;lt;e&amp;gt;default_create&amp;lt;/e&amp;gt; (line 1 of &amp;lt;e&amp;gt;f&amp;lt;/e&amp;gt;) and &amp;lt;e&amp;gt;is_equal&amp;lt;/e&amp;gt; (line 2 of &amp;lt;e&amp;gt;f&amp;lt;/e&amp;gt;, which are both features from &amp;lt;e&amp;gt;ANY&amp;lt;/e&amp;gt; and each occurs as the same feature once in &amp;lt;e&amp;gt;COMPARABLE&amp;lt;/e&amp;gt; and once in &amp;lt;e&amp;gt;NUMERIC&amp;lt;/e&amp;gt;. We do this despite the fact that it is actually the same feature. The reason for this can be found in the new semantics of the dynamic binding described in the [http://www.ecma-international.org/publications/standards/Ecma-367.htm standard]. You may also want to have a look at the following [[Multiple_constraints|article]] which discusses the issue.&lt;br /&gt;
&lt;br /&gt;
=== Renaming on formals ===&lt;br /&gt;
&lt;br /&gt;
The current implementation rejects a rename clause which is applied to a formal. The following code is therefore currently rejected as H is a formal and we don't allow a renaming on it.&lt;br /&gt;
&amp;lt;e&amp;gt;&lt;br /&gt;
class MULTI[G -&amp;gt; {H rename is_equal as is_equal_prime end, ANY}, H -&amp;gt; ANY]&lt;br /&gt;
&amp;lt;/e&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The rules implemented are chosen so that they are the most restrictive. This is to ensure that written code is likely to compile in the future where the rules might be more relaxed.&lt;br /&gt;
&lt;br /&gt;
=== Creation without call to explicit creation feature ===&lt;br /&gt;
{{Note|This is not implemented in interim release 6.0.6.7358 or older.}}&lt;br /&gt;
&amp;lt;e&amp;gt;&lt;br /&gt;
class MULTI [G -&amp;gt; {COMPARABLE rename default_craete as default_create2 end,&lt;br /&gt;
                   NUMERIC} create default_create, default_create2 end]&lt;br /&gt;
&amp;lt;/e&amp;gt;&lt;br /&gt;
&lt;br /&gt;
A creation like &amp;lt;e&amp;gt;create g&amp;lt;/e&amp;gt; where ''g'' is of type ''G'' yields an error as&lt;br /&gt;
there are two versions of ''default_create'' available.&lt;br /&gt;
&lt;br /&gt;
==Implementation details==&lt;br /&gt;
&lt;br /&gt;
The current implementation is pretty straightforward and tries to be as non-intrusive as possible. Most things rely on computation rather than on memory. For example there's no list which contains all features properly renamed but only a relatively small instance of &amp;lt;e&amp;gt;RENAMING_A&amp;lt;/e&amp;gt; which contains a mapping of the name-ids.&lt;br /&gt;
&lt;br /&gt;
The central classes to the current implementation are:&lt;br /&gt;
* &amp;lt;e&amp;gt;TYPE_SET_A&amp;lt;/e&amp;gt;&lt;br /&gt;
* &amp;lt;e&amp;gt;RENAMED_TYPE_A&amp;lt;/e&amp;gt;&lt;br /&gt;
* &amp;lt;e&amp;gt;RENAMING_A&amp;lt;/e&amp;gt;&lt;br /&gt;
* &amp;lt;e&amp;gt;CONSTRAINING_TYPE_AS&amp;lt;/e&amp;gt;&lt;br /&gt;
* and some changes to &amp;lt;e&amp;gt;CLASS_C&amp;lt;/e&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The main tasks which have to be performed are:&lt;br /&gt;
* Type checking in particular type conformance.&lt;br /&gt;
* Feature lookup&lt;br /&gt;
&lt;br /&gt;
Both tasks are provided by &amp;lt;e&amp;gt;TYPE_SET_A&amp;lt;/e&amp;gt;.&lt;br /&gt;
===TYPE_SET_A===&lt;br /&gt;
====Conformance====&lt;br /&gt;
The feature &amp;lt;e&amp;gt;conform_to&amp;lt;/e&amp;gt; inherited from &amp;lt;e&amp;gt;TYPE_A&amp;lt;/e&amp;gt; can be used to check whether a type set conforms to another type which is possibly a type set as well. &lt;br /&gt;
&lt;br /&gt;
* A type set conforms to another type if at least one type in the type &lt;br /&gt;
set conforms to the type.&lt;br /&gt;
* Another type conforms to a type set if it conforms to all types in the type set.&lt;br /&gt;
* A type set ''ts1'' conforms to a type set ''ts2'' if for each type ''t'' in ''ts2'' there is at least one type in ''ts1'' which conforms to ''t''.&lt;br /&gt;
&lt;br /&gt;
If every type is regarded as a type set with one element one can simply  always use the last rule.&lt;br /&gt;
&lt;br /&gt;
====Feature lookup====&lt;br /&gt;
There are various features which provide this functionality. Their differences are mostly in the amount of information they provide. Of course the computation gets more expensive if the feature returns more information.&lt;br /&gt;
Currently the API is pretty much targeted to what the compiler needs.&lt;br /&gt;
There's a bunch of features of the family ''e_feature_state_*''/''feature_i_state_*'' which are used when most likely only one feature occurs.&lt;br /&gt;
As soon as you need more information the features of the family ''info_about_feature_*'' can help you to get all information about a certain feature for a given type set.&lt;br /&gt;
&lt;br /&gt;
Now there is one more thing to add: As a type set which you obtain over &amp;lt;e&amp;gt;{CLASS_C}.constraints (a_formal_position)&amp;lt;/e&amp;gt; can contain formals, which themselves can have constraints and therefore add more available features, one needs to compute somehow a &amp;quot;flat&amp;quot; version of the type set. This version cannot be used anymore for meaning full type checking but is perfectly suited to do feature queries.&lt;br /&gt;
&amp;lt;e&amp;gt;&lt;br /&gt;
class MULTI [G -&amp;gt; {H, I}, H -&amp;gt; COMPARABLE, I -&amp;gt; NUMERIC]&lt;br /&gt;
&amp;lt;/e&amp;gt;&lt;br /&gt;
Consider now the following code which works on the &amp;lt;e&amp;gt;CLASS_C&amp;lt;/e&amp;gt; object of class &amp;lt;e&amp;gt;MULTI&amp;lt;/e&amp;gt; called &amp;lt;e&amp;gt;multi_class&amp;lt;/e&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;e&amp;gt;&lt;br /&gt;
a_type_set_with_formals := multi_class.constraints (1)&lt;br /&gt;
-- a_type_set_with_formals: {H, I}&lt;br /&gt;
a_type_set_without_formals := a_type_set_with_formals.constraining_types (multi_class)&lt;br /&gt;
-- a_type_set_without_formals: {COMPARABLE, NUMERIC}&lt;br /&gt;
&amp;lt;/e&amp;gt;&lt;br /&gt;
&lt;br /&gt;
It basically gets rid of all formals (even recursive cases are handled correctly) and puts together a new type set which can be used for example to show all classes which provide features to a formal or to do feature lookup. The fact that there's no good reason to use it for conformance suggests that one refactors this class into two classes: One for type checking and one for feature lookup.&lt;br /&gt;
&lt;br /&gt;
====Associated class====&lt;br /&gt;
This feature is no longer available and therefore exported to NONE. This is simply because there is no single associated class but many.&lt;br /&gt;
You can use the feature ''associated_classes'' instead and get a list of all associated classes.&lt;br /&gt;
However, the features applicable to the type set is not the same set as the features provided by each element of the ''associated_classes''. This is because one loses the renaming (class &amp;lt;e&amp;gt;RENAMING_A&amp;lt;/e&amp;gt;) which is stored inside the &amp;lt;e&amp;gt;TYPE_SET_A&amp;lt;/e&amp;gt; in each &amp;lt;e&amp;gt;RENAMED_TYPE_A&amp;lt;/e&amp;gt; instance. This is why there are some places in the code where going from a &amp;lt;e&amp;gt;CLASS_C&amp;lt;/e&amp;gt; instance to one of type &amp;lt;e&amp;gt;LIST [CLASS_C]&amp;lt;/e&amp;gt; is not enough.&lt;br /&gt;
&lt;br /&gt;
===RENAMED_TYPE_A===&lt;br /&gt;
The &amp;lt;e&amp;gt;RENAMED_TYPE_A&amp;lt;/e&amp;gt; class basically encapsulates a &amp;lt;e&amp;gt;TYPE_A&amp;lt;/e&amp;gt; object and a &amp;lt;e&amp;gt;RENAMING_A&amp;lt;/e&amp;gt; object.&lt;br /&gt;
The fact that it is conform to TYPE_A opens the door for mistakes: Make sure that you use &amp;lt;e&amp;gt;{RENAMED_TYPE_A}.type&amp;lt;/e&amp;gt; or &amp;lt;e&amp;gt;{RENAMED_TYPE_A}.actual_type&amp;lt;/e&amp;gt; if your code makes assignment attempts, it is pretty much the same as with the family of the &amp;quot;like&amp;quot; types.&lt;br /&gt;
&lt;br /&gt;
===RENAMING_A===&lt;br /&gt;
This is the class which provides features to handle the renaming which is applied to the features of the constraint type.&lt;br /&gt;
&lt;br /&gt;
It's current implementation is based on a hash table and therefore only one way is efficient.&lt;br /&gt;
&lt;br /&gt;
You can find out whether a specific feature is renamed by calling &amp;lt;e&amp;gt;is_feature_renamed&amp;lt;/e&amp;gt;. There's also a predefined feature &amp;lt;e&amp;gt;renamed&amp;lt;/e&amp;gt; which takes an integer argument and returns another one. The integer returned is either&lt;br /&gt;
* unchanged, if the feature is not renamed&lt;br /&gt;
* some other positive integer if the feature is renamed under the renaming&lt;br /&gt;
* -1 if the feature was renamed into something else (therefore it is not accessible)&lt;br /&gt;
&lt;br /&gt;
However, this is only relative to the renaming and is not in the context of a specific class. It means that if the feature ''f'' does not occur in  the class you don't get an error (-1), as &amp;lt;e&amp;gt;RENAMING_A&amp;lt;/e&amp;gt; does not consult a context class for its operations.&lt;br /&gt;
&lt;br /&gt;
===CLASS_C===&lt;br /&gt;
&lt;br /&gt;
A major change here affects the feature &amp;lt;e&amp;gt;constraint (i: INTEGER): TYPE_A&amp;lt;/e&amp;gt;.&lt;br /&gt;
It is used to get the constraint of the formal at position ''i''. A new precondition has been added which states that it is only ok to call that feature if the formal has only one constraint. This is also the reason why currently it is not allowed to apply a renaming to a single constraint.&lt;br /&gt;
For the multi constraint case the feature &amp;lt;e&amp;gt;constraints (i: INTEGER): TYPE_SET_A&amp;lt;/e&amp;gt; should be used instead. It returns a TYPE_SET_A instance which can possibly contain other formals.&lt;br /&gt;
==List of changes done==&lt;br /&gt;
This is an incomplete list of changes I've done which might need to be undone in the future.&lt;br /&gt;
&lt;br /&gt;
* VGCC1 has a slightly adapted error message (which was wrong before) but is now also used for the case where one has two versions default_create in the creation constraint list.&lt;/div&gt;</summary>
		<author><name>Seilerm</name></author>	</entry>

	<entry>
		<id>https://dev.eiffel.com/index.php?title=Current_implementation_of_multi_constraint_formals&amp;diff=8236</id>
		<title>Current implementation of multi constraint formals</title>
		<link rel="alternate" type="text/html" href="https://dev.eiffel.com/index.php?title=Current_implementation_of_multi_constraint_formals&amp;diff=8236"/>
				<updated>2007-04-23T16:39:14Z</updated>
		
		<summary type="html">&lt;p&gt;Seilerm: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Category:Compiler]]&lt;br /&gt;
{{UnderConstruction}}&lt;br /&gt;
&lt;br /&gt;
==Introduction==&lt;br /&gt;
The first implementation of multi constraints is done and this article describes its current implementation status.&lt;br /&gt;
&lt;br /&gt;
Let's take this example&lt;br /&gt;
&amp;lt;e&amp;gt;&lt;br /&gt;
MULTI [G -&amp;gt; {H, COMPARABLE rename is_equal as is_equal_cmp end},&lt;br /&gt;
      H -&amp;gt; {NUMERIC rename default_create as default_create_num end, G}]&lt;br /&gt;
&amp;lt;/e&amp;gt;&lt;br /&gt;
A type satisfying the constraint of ''G'' has the following properties:&lt;br /&gt;
* It conforms to whatever ''H'' is and therefore&lt;br /&gt;
** to &amp;lt;e&amp;gt;NUMERIC&amp;lt;/e&amp;gt; and &lt;br /&gt;
** by recursion to itself (''G'')&lt;br /&gt;
* It conforms to its second constraint which is &amp;lt;e&amp;gt;COMPARABLE&amp;lt;/e&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
A type satisfying the constraint of ''H'' has the following properties:&lt;br /&gt;
* It conforms to &amp;lt;e&amp;gt;NUMERIC&amp;lt;/e&amp;gt;.&lt;br /&gt;
* It conforms to ''G'' and therefore&lt;br /&gt;
** by recursion to itself (''H'') and&lt;br /&gt;
** to &amp;lt;e&amp;gt;COMPARABLE&amp;lt;/e&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
As ''G'' and ''H'' both have to conform to each other the only possibility to satisfy this is that ''G'' and ''H'' must be the same in the generic derivation. It does not make much sense to program something like that but it is part of the current implementation.&lt;br /&gt;
&lt;br /&gt;
=== Feature calls ===&lt;br /&gt;
&lt;br /&gt;
Let's have a look at the following feature written in class ''MULTI'':&lt;br /&gt;
&amp;lt;e&amp;gt;&lt;br /&gt;
feature&lt;br /&gt;
    g: G&lt;br /&gt;
&lt;br /&gt;
    f: BOOLEAN&lt;br /&gt;
            -- Sample feature&lt;br /&gt;
        do&lt;br /&gt;
            create g -- 1&lt;br /&gt;
            Result := g.is_equal(g) -- 2&lt;br /&gt;
        end&lt;br /&gt;
&amp;lt;/e&amp;gt;&lt;br /&gt;
The following rules have to hold for each call on a multi constraint formal:&lt;br /&gt;
* Every feature which is called has exactly one class which is used as the static type for the call.&lt;br /&gt;
&lt;br /&gt;
This is a major difference to the ECMA standard which allows a call to features which are available through different classes as long as it is the same feature. A definition of what the ''same feature'' means can be found [[Replication|here]].&lt;br /&gt;
&lt;br /&gt;
In order to achieve that goal if a feature occurs with the same name in  different classes one uses a rename clause and renames that feature. If there are name clashes between features and one does not want to call that feature a renaming is '''not''' needed.&lt;br /&gt;
&lt;br /&gt;
As we perform calls to &amp;lt;e&amp;gt;default_create&amp;lt;/e&amp;gt; (line 1 of &amp;lt;e&amp;gt;f&amp;lt;/e&amp;gt;) and &amp;lt;e&amp;gt;is_equal&amp;lt;/e&amp;gt; (line 2 of &amp;lt;e&amp;gt;f&amp;lt;/e&amp;gt;, which are both features from &amp;lt;e&amp;gt;ANY&amp;lt;/e&amp;gt; and each occurs as the same feature once in &amp;lt;e&amp;gt;COMPARABLE&amp;lt;/e&amp;gt; and once in &amp;lt;e&amp;gt;NUMERIC&amp;lt;/e&amp;gt;. We do this despite the fact that it is actually the same feature. The reason for this can be found in the new semantics of the dynamic binding described in the [http://www.ecma-international.org/publications/standards/Ecma-367.htm standard]. You may also want to have a look at the following [[Multiple_constraints|article]] which discusses the issue.&lt;br /&gt;
&lt;br /&gt;
=== Renaming on formals ===&lt;br /&gt;
&lt;br /&gt;
The current implementation rejects a rename clause which is applied to a formal. The following code is therefore currently rejected as H is a formal and we don't allow a renaming on it.&lt;br /&gt;
&amp;lt;e&amp;gt;&lt;br /&gt;
class MULTI[G -&amp;gt; {H rename is_equal as is_equal_prime end, ANY}, H -&amp;gt; ANY]&lt;br /&gt;
&amp;lt;/e&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The rules implemented are chosen so that they are the most restrictive. This is to ensure that written code is likely to compile in the future where the rules might be more relaxed.&lt;br /&gt;
&lt;br /&gt;
=== Creation without call to explicit creation feature ===&lt;br /&gt;
{{Note|This is not implemented in interim release 6.0.6.7358 or older.}}&lt;br /&gt;
&amp;lt;e&amp;gt;&lt;br /&gt;
class MULTI [G -&amp;gt; {COMPARABLE rename default_craete as default_create2 end,&lt;br /&gt;
                   NUMERIC} create default_create, default_create2 end]&lt;br /&gt;
&amp;lt;/e&amp;gt;&lt;br /&gt;
&lt;br /&gt;
An creation like &amp;lt;e&amp;gt;create g&amp;lt;/e&amp;gt; where ''g'' is of type ''G'' yields an error as&lt;br /&gt;
there are two versions of ''default_create'' available.&lt;br /&gt;
&lt;br /&gt;
==Implementation details==&lt;br /&gt;
&lt;br /&gt;
The current implementation is pretty straightforward and tries to be as non-intrusive as possible. Most things rely on computation rather than on memory. For example there's no list which contains all features properly renamed but only a relatively small instance of &amp;lt;e&amp;gt;RENAMING_A&amp;lt;/e&amp;gt; which contains a mapping of the name-ids.&lt;br /&gt;
&lt;br /&gt;
The central classes to the current implementation are:&lt;br /&gt;
* &amp;lt;e&amp;gt;TYPE_SET_A&amp;lt;/e&amp;gt;&lt;br /&gt;
* &amp;lt;e&amp;gt;RENAMED_TYPE_A&amp;lt;/e&amp;gt;&lt;br /&gt;
* &amp;lt;e&amp;gt;RENAMING_A&amp;lt;/e&amp;gt;&lt;br /&gt;
* &amp;lt;e&amp;gt;CONSTRAINING_TYPE_AS&amp;lt;/e&amp;gt;&lt;br /&gt;
* and some changes to &amp;lt;e&amp;gt;CLASS_C&amp;lt;/e&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The main tasks which have to be performed are:&lt;br /&gt;
* Type checking in particular type conformance.&lt;br /&gt;
* Feature lookup&lt;br /&gt;
&lt;br /&gt;
Both tasks are provided by &amp;lt;e&amp;gt;TYPE_SET_A&amp;lt;/e&amp;gt;.&lt;br /&gt;
===TYPE_SET_A===&lt;br /&gt;
====Conformance====&lt;br /&gt;
The feature &amp;lt;e&amp;gt;conform_to&amp;lt;/e&amp;gt; inherited from &amp;lt;e&amp;gt;TYPE_A&amp;lt;/e&amp;gt; can be used to check whether a type set conforms to another type which is possibly a type set as well. &lt;br /&gt;
&lt;br /&gt;
* A type set conforms to another type if at least one type in the type &lt;br /&gt;
set conforms to the type.&lt;br /&gt;
* Another type conforms to a type set if it conforms to all types in the type set.&lt;br /&gt;
* A type set ''ts1'' conforms to a type set ''ts2'' if for each type ''t'' in ''ts2'' there is at least one type in ''ts1'' which conforms to ''t''.&lt;br /&gt;
&lt;br /&gt;
If every type is regarded as a type set with one element one can simply  always use the last rule.&lt;br /&gt;
&lt;br /&gt;
====Feature lookup====&lt;br /&gt;
There are various features which provide this functionality. Their differences are mostly in the amount of information they provide. Of course the computation gets more expensive if the feature returns more information.&lt;br /&gt;
Currently the API is pretty much targeted to what the compiler needs.&lt;br /&gt;
There's a bunch of features of the family ''e_feature_state_*''/''feature_i_state_*'' which are used when most likely only one feature occurs.&lt;br /&gt;
As soon as you need more information the features of the family ''info_about_feature_*'' can help you to get all information about a certain feature for a given type set.&lt;br /&gt;
&lt;br /&gt;
Now there is one more thing to add: As a type set which you obtain over &amp;lt;e&amp;gt;{CLASS_C}.constraints (a_formal_position)&amp;lt;/e&amp;gt; can contain formals, which themselves can have constraints and therefore add more available features, one needs to compute somehow a &amp;quot;flat&amp;quot; version of the type set. This version cannot be used anymore for meaning full type checking but is perfectly suited to do feature queries.&lt;br /&gt;
&amp;lt;e&amp;gt;&lt;br /&gt;
class MULTI [G -&amp;gt; {H, I}, H -&amp;gt; COMPARABLE, I -&amp;gt; NUMERIC]&lt;br /&gt;
&amp;lt;/e&amp;gt;&lt;br /&gt;
Consider now the following code which works on the &amp;lt;e&amp;gt;CLASS_C&amp;lt;/e&amp;gt; object of class &amp;lt;e&amp;gt;MULTI&amp;lt;/e&amp;gt; called &amp;lt;e&amp;gt;multi_class&amp;lt;/e&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;e&amp;gt;&lt;br /&gt;
a_type_set_with_formals := multi_class.constraints (1)&lt;br /&gt;
-- a_type_set_with_formals: {H, I}&lt;br /&gt;
a_type_set_without_formals := a_type_set_with_formals.constraining_types (multi_class)&lt;br /&gt;
-- a_type_set_without_formals: {COMPARABLE, NUMERIC}&lt;br /&gt;
&amp;lt;/e&amp;gt;&lt;br /&gt;
&lt;br /&gt;
It basically gets rid of all formals (even recursive cases are handled correctly) and puts together a new type set which can be used for example to show all classes which provide features to a formal or to do feature lookup. The fact that there's no good reason to use it for conformance suggests that one refactors this class into two classes: One for type checking and one for feature lookup.&lt;br /&gt;
&lt;br /&gt;
====Associated class====&lt;br /&gt;
This feature is no longer available and therefore exported to NONE. This is simply because there is no single associated class but many.&lt;br /&gt;
You can use the feature ''associated_classes'' instead and get a list of all associated classes.&lt;br /&gt;
However, the features applicable to the type set is not the same set as the features provided by each element of the ''associated_classes''. This is because one loses the renaming (class &amp;lt;e&amp;gt;RENAMING_A&amp;lt;/e&amp;gt;) which is stored inside the &amp;lt;e&amp;gt;TYPE_SET_A&amp;lt;/e&amp;gt; in each &amp;lt;e&amp;gt;RENAMED_TYPE_A&amp;lt;/e&amp;gt; instance. This is why there are some places in the code where going from a &amp;lt;e&amp;gt;CLASS_C&amp;lt;/e&amp;gt; instance to one of type &amp;lt;e&amp;gt;LIST [CLASS_C]&amp;lt;/e&amp;gt; is not enough.&lt;br /&gt;
&lt;br /&gt;
===RENAMED_TYPE_A===&lt;br /&gt;
The &amp;lt;e&amp;gt;RENAMED_TYPE_A&amp;lt;/e&amp;gt; class basically encapsulates a &amp;lt;e&amp;gt;TYPE_A&amp;lt;/e&amp;gt; object and a &amp;lt;e&amp;gt;RENAMING_A&amp;lt;/e&amp;gt; object.&lt;br /&gt;
The fact that it is conform to TYPE_A opens the door for mistakes: Make sure that you use &amp;lt;e&amp;gt;{RENAMED_TYPE_A}.type&amp;lt;/e&amp;gt; or &amp;lt;e&amp;gt;{RENAMED_TYPE_A}.actual_type&amp;lt;/e&amp;gt; if your code makes assignment attempts, it is pretty much the same as with the family of the &amp;quot;like&amp;quot; types.&lt;br /&gt;
&lt;br /&gt;
===RENAMING_A===&lt;br /&gt;
This is the class which provides features to handle the renaming which is applied to the features of the constraint type.&lt;br /&gt;
&lt;br /&gt;
It's current implementation is based on a hash table and therefore only one way is efficient.&lt;br /&gt;
&lt;br /&gt;
You can find out whether a specific feature is renamed by calling &amp;lt;e&amp;gt;is_feature_renamed&amp;lt;/e&amp;gt;. There's also a predefined feature &amp;lt;e&amp;gt;renamed&amp;lt;/e&amp;gt; which takes an integer argument and returns another one. The integer returned is either&lt;br /&gt;
* unchanged, if the feature is not renamed&lt;br /&gt;
* some other positive integer if the feature is renamed under the renaming&lt;br /&gt;
* -1 if the feature was renamed into something else (therefore it is not accessible)&lt;br /&gt;
&lt;br /&gt;
However, this is only relative to the renaming and is not in the context of a specific class. It means that if the feature ''f'' does not occur in  the class you don't get an error (-1), as &amp;lt;e&amp;gt;RENAMING_A&amp;lt;/e&amp;gt; does not consult a context class for its operations.&lt;br /&gt;
&lt;br /&gt;
===CLASS_C===&lt;br /&gt;
&lt;br /&gt;
A major change here affects the feature &amp;lt;e&amp;gt;constraint (i: INTEGER): TYPE_A&amp;lt;/e&amp;gt;.&lt;br /&gt;
It is used to get the constraint of the formal at position ''i''. A new precondition has been added which states that it is only ok to call that feature if the formal has only one constraint. This is also the reason why currently it is not allowed to apply a renaming to a single constraint.&lt;br /&gt;
For the multi constraint case the feature &amp;lt;e&amp;gt;constraints (i: INTEGER): TYPE_SET_A&amp;lt;/e&amp;gt; should be used instead. It returns a TYPE_SET_A instance which can possibly contain other formals.&lt;br /&gt;
==List of changes done==&lt;br /&gt;
This is an incomplete list of changes I've done which might need to be undone in the future.&lt;br /&gt;
&lt;br /&gt;
* VGCC1 has a slightly adapted error message (which was wrong before) but is now also used for the case where one has two versions default_create in the creation constraint list.&lt;/div&gt;</summary>
		<author><name>Seilerm</name></author>	</entry>

	<entry>
		<id>https://dev.eiffel.com/index.php?title=Covariance-aware_assertions&amp;diff=8220</id>
		<title>Covariance-aware assertions</title>
		<link rel="alternate" type="text/html" href="https://dev.eiffel.com/index.php?title=Covariance-aware_assertions&amp;diff=8220"/>
				<updated>2007-04-22T19:04:21Z</updated>
		
		<summary type="html">&lt;p&gt;Seilerm: /* Unsatisfiable postcondition on catcalls */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;ECMA Eiffel introduces covariance-aware assertions (section 8.10.4)). This is a change in assertions when covariant redefinition of feature argument occurs.&lt;br /&gt;
&lt;br /&gt;
== Why do we need this? ==&lt;br /&gt;
&lt;br /&gt;
When covariant argument redefinition occurs, some assertions may be invalidated through the change of an attached to a detached type. For example an assertion &amp;lt;e&amp;gt;x.is_empty&amp;lt;/e&amp;gt; is not valid anymore after x is covariantly redefined since it is of a detachable type and could be Void.&lt;br /&gt;
&lt;br /&gt;
{{Todo|Add other examples}}&lt;br /&gt;
&lt;br /&gt;
== Problems with the mechanism ==&lt;br /&gt;
&lt;br /&gt;
Let's look at an example:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;e&amp;gt;&lt;br /&gt;
class A&lt;br /&gt;
&lt;br /&gt;
feature&lt;br /&gt;
&lt;br /&gt;
  f (x: ? ANY)&lt;br /&gt;
    do&lt;br /&gt;
    ensure&lt;br /&gt;
      True&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
class B&lt;br /&gt;
&lt;br /&gt;
inherit&lt;br /&gt;
  A&lt;br /&gt;
    redefine f end&lt;br /&gt;
&lt;br /&gt;
feature&lt;br /&gt;
&lt;br /&gt;
  f (x: ? STRING)&lt;br /&gt;
    do&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;
Since the feature is covariantly redefined, the postcondition will go through the process described in section 8.10.4. The consequences are that each assertion will be changed to check for potential catcalls in the following way:&lt;br /&gt;
&lt;br /&gt;
* Normal assertion: &amp;lt;e&amp;gt;True&amp;lt;/e&amp;gt;&lt;br /&gt;
* Covariant-aware assertion: &amp;lt;e&amp;gt;({y: STRING} x) and then (True)&amp;lt;/e&amp;gt;&lt;br /&gt;
&lt;br /&gt;
So the full interface of the inherited feature is:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;e&amp;gt;&lt;br /&gt;
f (x: ? STRING)&lt;br /&gt;
  ensure -- From A&lt;br /&gt;
    ({y: STRING} x) and then (True)&lt;br /&gt;
&amp;lt;/e&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{{Note|The postcondition &amp;lt;e&amp;gt;True&amp;lt;/e&amp;gt; could be replaced by any other postcondition. This just illustrates that the problem occurs on any feature since all features have an implicit postcondition ''True''.}}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Unsatisfiable postcondition on Void arguments ===&lt;br /&gt;
&lt;br /&gt;
Now consider the following code block:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;e&amp;gt;&lt;br /&gt;
local&lt;br /&gt;
  a: A&lt;br /&gt;
  b: B&lt;br /&gt;
do&lt;br /&gt;
  a := b&lt;br /&gt;
  a.f (Void)&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/e&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The caller of feature f in class A makes a valid call by passing Void as an argument. But the postcondition of the redefined feature f in class B will evaulate to false since the object test on the argument will evaluate to false.&lt;br /&gt;
&lt;br /&gt;
In general, every covariance-aware assertion on an argument where Void would have been allowed (namely detached arguments) will invalidate the postcondition for a Void argument.&lt;br /&gt;
&lt;br /&gt;
The problem is that the object test which actually should check for invalid arguments through cat calls will fail for Void even if it would be legal as an argument. Thus the covariance-aware assertion rule has to be changed to take Void into account if the argument which gets covariantly redefined is not an attached type and allows Void values.&lt;br /&gt;
&lt;br /&gt;
For this the rule should make an object test for arguments which get redefined covariantly, but additionally allow Void values for detachable argument types. Thus the covariance-aware assertion has to look like:&lt;br /&gt;
&lt;br /&gt;
* Normal assertion: &amp;lt;e&amp;gt;True&amp;lt;/e&amp;gt;&lt;br /&gt;
* Covariant-aware assertion: &amp;lt;e&amp;gt;({y: STRING} x or x = Void) and then (True)&amp;lt;/e&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Unsatisfiable postcondition on catcalls ===&lt;br /&gt;
&lt;br /&gt;
Consider a second example where the argument type is attached in the parent feature:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;e&amp;gt;&lt;br /&gt;
class A&lt;br /&gt;
&lt;br /&gt;
feature&lt;br /&gt;
&lt;br /&gt;
  g (x: ANY)&lt;br /&gt;
    do&lt;br /&gt;
    ensure&lt;br /&gt;
      True&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
class B&lt;br /&gt;
&lt;br /&gt;
inherit&lt;br /&gt;
  A&lt;br /&gt;
&lt;br /&gt;
feature&lt;br /&gt;
&lt;br /&gt;
  g (x: ? STRING)&lt;br /&gt;
    do&lt;br /&gt;
      if {y: STRING} x then&lt;br /&gt;
        -- Do something with y&lt;br /&gt;
      else&lt;br /&gt;
        -- We had a catcall or a Void argument.&lt;br /&gt;
        -- There is nothing to do here since&lt;br /&gt;
        -- the inherited postcondition is 'True'&lt;br /&gt;
      end&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 argument get's detached, and any meaningful code in the redefined feature has to check for the type of the argument.&lt;br /&gt;
&lt;br /&gt;
But again, the inherited assertion goes through the process to become covariance-aware:&lt;br /&gt;
&lt;br /&gt;
* Normal assertion: &amp;lt;e&amp;gt;True&amp;lt;/e&amp;gt;&lt;br /&gt;
* Covariant-aware assertion: &amp;lt;e&amp;gt;({y: STRING} x) and then (True)&amp;lt;/e&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Now consider the following code block with a catcall:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;e&amp;gt;&lt;br /&gt;
local&lt;br /&gt;
  a: A&lt;br /&gt;
  b: B&lt;br /&gt;
do&lt;br /&gt;
  a := b&lt;br /&gt;
  a.g (5)&lt;br /&gt;
  b.g (Void)&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/e&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The covariance-aware postcondition again evaluates to &amp;lt;e&amp;gt;False&amp;lt;/e&amp;gt;, no matter what the feature does. Thus in case of a cat-call the postcondition is violated in every case. Even in the case where &amp;lt;e&amp;gt;Void&amp;lt;/e&amp;gt; is passed legally, the postcondition is violated (as described in the previous section).&lt;br /&gt;
&lt;br /&gt;
The question here is, if we want to allow catcalls at all. Should they go trough then the programmer has to check them with an object test (which does not work if Void is passed), or should an exception be triggered by the runtime system. In the second case it surely should not be a postcondition violation.&lt;br /&gt;
&lt;br /&gt;
== Possible solutions ==&lt;br /&gt;
&lt;br /&gt;
To solve the first problem shown - when a valid Void argument is passed the covariance-aware assertion fails - the rules to create covariance-aware assertions have to be changed to take detachable arguments into account and allow the valid use of Void arguments.&lt;br /&gt;
&lt;br /&gt;
To solve the second problem shown - on a catcall the postcondition is violated in every case - the rules also have to be changed ... (Todo: changed to what?)&lt;br /&gt;
&lt;br /&gt;
== Catcalls in general ==&lt;br /&gt;
&lt;br /&gt;
{{Todo|This part probably should get it's own page}}&lt;br /&gt;
&lt;br /&gt;
The question remains what the system is supposed to do in a catcall at all:&lt;br /&gt;
* If catcalls have to be detected statically, the whole mechanism of redefining detachable is not necessary anyway and covariance-aware assertions have to be revised.&lt;br /&gt;
* If catcalls should be handled dynamically, there are two ways to do so:&lt;br /&gt;
** The program does not raise an exception on a catcall. In this case the programmer has to do an object-test to use covariantly redefined features (See also [[New CAT call|this]] page for an argument against this). Problems are raised with the covariance-aware assertions and their rules have to be changed not to invalidate postconditions in all cases.&lt;br /&gt;
** The program raises an exception on a catcall. If an exception should be raised, this better be the case on the entry to the call and not in the postcondition. So a runtime check could be introduced on any problematic feature call and raise an exception. This would also imply that the mechanism of redefining covariant features detachable is not necessary anymore since the runtime guarantees that all arguments are valid.&lt;/div&gt;</summary>
		<author><name>Seilerm</name></author>	</entry>

	<entry>
		<id>https://dev.eiffel.com/index.php?title=Preventing_CAT_calls_in_Generics&amp;diff=8208</id>
		<title>Preventing CAT calls in Generics</title>
		<link rel="alternate" type="text/html" href="https://dev.eiffel.com/index.php?title=Preventing_CAT_calls_in_Generics&amp;diff=8208"/>
				<updated>2007-04-20T04:27:00Z</updated>
		
		<summary type="html">&lt;p&gt;Seilerm: /* How to generate the call signature for a given agent type */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Category:ECMA]]&lt;br /&gt;
{{UnderConstruction}}&lt;br /&gt;
&lt;br /&gt;
==Introduction==&lt;br /&gt;
&lt;br /&gt;
The problem with the way generics are implemented in Eiffel right now is that CAT calls can occur.&lt;br /&gt;
&amp;lt;e&amp;gt;&lt;br /&gt;
class PERSON&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
class STUDENT&lt;br /&gt;
inherit&lt;br /&gt;
 PERSON&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
class EMPLOYEE&lt;br /&gt;
inherit&lt;br /&gt;
 PERSON&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
class EMPLOYED_STUDENT&lt;br /&gt;
inherit&lt;br /&gt;
 EMPLOYEE&lt;br /&gt;
 STUDENT&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;
  l_person: PERSON&lt;br /&gt;
  l_student: STUDENT&lt;br /&gt;
  l_any_stack: STACK [PERSON]&lt;br /&gt;
  l_student_stack: STACK [STUDENT]&lt;br /&gt;
do&lt;br /&gt;
  l_person_stack := l_student_stack -- line 1&lt;br /&gt;
  l_person_stack.put (l_person) -- line 2&lt;br /&gt;
  l_student := l_student_stack.item -- line 3&lt;br /&gt;
&amp;lt;/e&amp;gt;&lt;br /&gt;
Currently no static check will prohibit you from writing things like this. At runtime on ''line 2'' the first CAT call occurs, which most likely wont do any harm to a list. But the object returned by &amp;lt;e&amp;gt;item&amp;lt;/e&amp;gt; on ''line 3'' is not of type &amp;lt;e&amp;gt;STUDENT&amp;lt;/e&amp;gt; but of type &amp;lt;e&amp;gt;PERSON&amp;lt;/e&amp;gt; and at least now we have a serious problem if one invokes features specific to a student on &amp;lt;e&amp;gt;l_student&amp;lt;/e&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
The issue is that the &amp;lt;e&amp;gt;put&amp;lt;/e&amp;gt; feature of &amp;lt;e&amp;gt;l_person_stack&amp;lt;/e&amp;gt; allows you to put objects of type &amp;lt;e&amp;gt;PERSON&amp;lt;/e&amp;gt; on the stack even though the actual type of the attached object is &amp;lt;e&amp;gt;STACK [STUDENT]&amp;lt;/e&amp;gt; and is referenced by &amp;lt;e&amp;gt;l_student_stack&amp;lt;/e&amp;gt; whose &amp;lt;e&amp;gt;item&amp;lt;/e&amp;gt; feature guarantees, that the returned object will be of type &amp;lt;e&amp;gt;STUDENT&amp;lt;/e&amp;gt;.&lt;br /&gt;
This solution will now extend the type system and the generic derivation of Eiffel in such away, that the type of a formal occurring as an argument in a feature declaration and the type of a formal occurring as a result type can be set independently. The type system will be extended with rules which allow only assignments between generic types if it cannot possibly lead to problems like the one mentioned above.&lt;br /&gt;
&lt;br /&gt;
== Syntax ==&lt;br /&gt;
&lt;br /&gt;
LIST [G] can be declared in the following way:&lt;br /&gt;
&amp;lt;e&amp;gt;&lt;br /&gt;
l_list: LIST [PERSON..EXMLPOYED_STUDENT]&lt;br /&gt;
&amp;lt;/e&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;e&amp;gt;LIST[A]&amp;lt;/e&amp;gt; is a shorthand for &amp;lt;e&amp;gt;LIST[A..A]&amp;lt;/e&amp;gt;.&lt;br /&gt;
&amp;lt;e&amp;gt;LIST[A..]&amp;lt;/e&amp;gt; is also a possible syntax.&lt;br /&gt;
&lt;br /&gt;
Another syntax could look as follows:&lt;br /&gt;
&amp;lt;e&amp;gt;&lt;br /&gt;
&amp;lt;type_for_arguments&amp;gt;:&amp;lt;type_for_return_types&amp;gt;&lt;br /&gt;
&amp;lt;/e&amp;gt;&lt;br /&gt;
This would more resemble an actual generated signature of a feature which looks initially like&lt;br /&gt;
&amp;lt;e&amp;gt;&lt;br /&gt;
class EXAMPLE [G]&lt;br /&gt;
feature&lt;br /&gt;
  example (a_g: G): G&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/e&amp;gt;&lt;br /&gt;
&lt;br /&gt;
A type declaration with this syntax would look like:&lt;br /&gt;
&amp;lt;e&amp;gt;&lt;br /&gt;
local&lt;br /&gt;
 l_example: EXAMPLE [EMLPOYED_STYDENT: STUDENT]&lt;br /&gt;
 l_employed_student: EMPLOYED_STUDENT&lt;br /&gt;
 l_person: PERSON&lt;br /&gt;
do&lt;br /&gt;
 -- l_example.example (a_g: EMPLOYED_STUDENT): STUDENT &lt;br /&gt;
  l_person := l_example.example (l_employed_student) -- valid&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/e&amp;gt;&lt;br /&gt;
&amp;lt;e&amp;gt;LIST[:A]&amp;lt;/e&amp;gt; is the equivalent to &amp;lt;e&amp;gt;LIST[A..]&amp;lt;/e&amp;gt;.&lt;br /&gt;
&amp;lt;e&amp;gt;LIST[A]&amp;lt;/e&amp;gt; is a shorthand for &amp;lt;e&amp;gt;LIST[A: A]&amp;lt;/e&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
But let's stick with the initial syntax for now.&lt;br /&gt;
&lt;br /&gt;
== Semantics ==&lt;br /&gt;
&lt;br /&gt;
As we already pointed out, this solution is an extension to the type system. It helps you to proper derive an interface of a generic type.&lt;br /&gt;
For example an actual type parameter for G in &amp;lt;e&amp;gt;LIST [G]&amp;lt;/e&amp;gt; is PERSON..EMPLOYED_STUDENT.&lt;br /&gt;
The interface generated by this derivation is simply that the first type (PERSON) is taken wherever G occurs as a return type.&lt;br /&gt;
The second type (EMPLOYED_STUDENT) is taken wherever G occurs as an argument type.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;e&amp;gt;&lt;br /&gt;
(generic derived) class LIST[PERSON..EMPLOYED_STUDENT]&lt;br /&gt;
&lt;br /&gt;
  put (v: EMPLOYED_STUDENT)&lt;br /&gt;
  &lt;br /&gt;
  item: PERSON&lt;br /&gt;
&amp;lt;/e&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If we encounter a form like LIST [A..] it simply means that no feature which has the formal in the argument can be called.&lt;br /&gt;
&lt;br /&gt;
{{Note| Why do we need that?&lt;br /&gt;
We want to ensure that one has a read only list. One cannot use a &amp;lt;e&amp;gt;LIST [ANY..NONE]&amp;lt;/e&amp;gt; because one would not be allowed to assign a &amp;lt;e&amp;gt;LIST [INTEGER]&amp;lt;/e&amp;gt; to it. This is because one can put Void into a list of type &amp;lt;e&amp;gt;LIST [ANY..NONE]&amp;lt;/e&amp;gt;, which is invalid for a list of integer as &amp;lt;e&amp;gt;INTEGER&amp;lt;/e&amp;gt; is expanded.}}&lt;br /&gt;
&lt;br /&gt;
== Validity ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;e&amp;gt;LIST[&amp;lt;first_type&amp;gt;..&amp;lt;second_type&amp;gt;]&amp;lt;/e&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Such a generic derivation is valid if:&lt;br /&gt;
* 1: the second type conforms to the constraint of the formal.&lt;br /&gt;
* 2: the second type conforms to the first type&lt;br /&gt;
&lt;br /&gt;
==Conformance Rules==&lt;br /&gt;
&lt;br /&gt;
We make another more abstract example to illustrate the conformance rules. They can easily be derived by applying the fact that its save for argument types to be contra-variant and for result types to be covariant. This is actually a very important as it is the basis where the conformance is based uppon.&lt;br /&gt;
&lt;br /&gt;
Interface conformance rule:&lt;br /&gt;
 An interface B is conform to an interface A if for every feature f_a in A &lt;br /&gt;
 there is a corresponding feature f_b available from B and for each feature &lt;br /&gt;
 the arguments of f_a conform to those of f_b and the result type of f_b is &lt;br /&gt;
 conform to the one of f_a.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;e&amp;gt;&lt;br /&gt;
local&lt;br /&gt;
  l_a: A&lt;br /&gt;
  l_b: B&lt;br /&gt;
do&lt;br /&gt;
    -- is legal if the interface conformance rule holds&lt;br /&gt;
  l_a := l_b&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/e&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Example of an actual generic conformance table===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;e&amp;gt;&lt;br /&gt;
class T &lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
class U &lt;br /&gt;
inherit T &lt;br /&gt;
  -- no covariant feature redefinition&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/e&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
| conforms to&lt;br /&gt;
! LIST [ANY]&lt;br /&gt;
! LIST [T]&lt;br /&gt;
! LIST [T..NONE]&lt;br /&gt;
! LIST [ANY..T]&lt;br /&gt;
! LIST [U]&lt;br /&gt;
|-&lt;br /&gt;
! LIST [ANY]&lt;br /&gt;
| true&lt;br /&gt;
| false&lt;br /&gt;
| false&lt;br /&gt;
| true&lt;br /&gt;
| false&lt;br /&gt;
|-&lt;br /&gt;
! LIST [T]&lt;br /&gt;
| false&lt;br /&gt;
| true&lt;br /&gt;
| true&lt;br /&gt;
| true&lt;br /&gt;
| false&lt;br /&gt;
|-&lt;br /&gt;
! LIST [T..NONE]&lt;br /&gt;
| false&lt;br /&gt;
| false&lt;br /&gt;
| true&lt;br /&gt;
| false&lt;br /&gt;
| false&lt;br /&gt;
|-&lt;br /&gt;
! LIST [ANY..T]&lt;br /&gt;
| false&lt;br /&gt;
| false &lt;br /&gt;
| false &lt;br /&gt;
| true&lt;br /&gt;
| false&lt;br /&gt;
|-&lt;br /&gt;
! LIST [U]&lt;br /&gt;
| false&lt;br /&gt;
| '''false'''&lt;br /&gt;
| true&lt;br /&gt;
| false&lt;br /&gt;
| true&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;e&amp;gt;&lt;br /&gt;
  -- legal&lt;br /&gt;
T := LIST [T..NONE] .item&lt;br /&gt;
LIST [T..NONE] .put (Void)&lt;br /&gt;
&lt;br /&gt;
  -- illegal&lt;br /&gt;
U := LIST [T..NONE] .item&lt;br /&gt;
LIST [T..NONE] .put (T)&lt;br /&gt;
&lt;br /&gt;
  -- legal&lt;br /&gt;
LIST [ANY..T] .put (T)&lt;br /&gt;
LIST [ANY..T] .put (U)&lt;br /&gt;
ANY := LIST [ANY..T] .item&lt;br /&gt;
&lt;br /&gt;
  -- illegal&lt;br /&gt;
LIST [ANY..T] .put (ANY)&lt;br /&gt;
T := LIST [ANY..T] .item&lt;br /&gt;
&amp;lt;/e&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Agents==&lt;br /&gt;
&lt;br /&gt;
The neat thing about this extension is, that there is no need to cut down the expressiveness of the agent mechanism to make them perfectly save to use with full support for all legal situations. &lt;br /&gt;
&lt;br /&gt;
Procedure class:&lt;br /&gt;
&amp;lt;e&amp;gt;&lt;br /&gt;
class PROCEDURE [BASE_TYPE, OPEN_ARGS -&amp;gt; TUPLE []]&lt;br /&gt;
    -- Signature of call is generated by the compiler. To visualize this we add _reflected to the argument tuple.&lt;br /&gt;
  call (args: OPEN_ARGS_reflected)&lt;br /&gt;
    do end&lt;br /&gt;
&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/e&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Agent example ===&lt;br /&gt;
&lt;br /&gt;
Type declaration:&lt;br /&gt;
&amp;lt;e&amp;gt;&lt;br /&gt;
an_agent: PROCEDURE [ANY..NONE, TUPLE..TUPLE [ANY..T]]  --&amp;gt; like agent (T)&lt;br /&gt;
  -- This signature promises that the caller is going to give at least one argument which conforms to T.&lt;br /&gt;
  -- Note: The signature for the call routine has to be reflected by the compiler into : TUPLE [T..]..NONE&lt;br /&gt;
  --       This is because we can give a tuple containing more than one element and it element type has to conform to T.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
  -- legal&lt;br /&gt;
an_agent.call ([T])&lt;br /&gt;
an_agent.call ([T, ...])&lt;br /&gt;
an_agent.call ([U, ...])&lt;br /&gt;
&lt;br /&gt;
  -- illegal&lt;br /&gt;
an_agent.call ([])&lt;br /&gt;
&amp;lt;/e&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Instantiation:&lt;br /&gt;
&amp;lt;e&amp;gt;&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;
&lt;br /&gt;
  -- legal&lt;br /&gt;
an_agent := agent_empty&lt;br /&gt;
an_agent := agent_any&lt;br /&gt;
an_agent := agent_t&lt;br /&gt;
&lt;br /&gt;
  -- illegal&lt;br /&gt;
an_agent := agent_u&lt;br /&gt;
&amp;lt;/e&amp;gt;&lt;br /&gt;
&lt;br /&gt;
There might be a concern about the fact that the compiler generates the signature of the call method. But I think that its not wrong to have compiler support for agents, as they are such a fundamental core concept that is simply important that one could sacrifice expressive power or type safety just to avoid explicit support from the compiler.&lt;br /&gt;
&lt;br /&gt;
=== How to generate the call signature for a given agent type ===&lt;br /&gt;
&lt;br /&gt;
To build the signature of the call routine one simply takes he second parameter and puts it as the first. As the second parameter we put nothing.&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&amp;lt;e&amp;gt;&lt;br /&gt;
TUPLE [ANY..T, ANY..U, ANY..V]&lt;br /&gt;
&amp;lt;/e&amp;gt;&lt;br /&gt;
&lt;br /&gt;
leads to&lt;br /&gt;
&amp;lt;e&amp;gt;&lt;br /&gt;
TUPLE [T..,U..,V..]&lt;br /&gt;
&amp;lt;/e&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This basically states that all I want is to be able to read an object of at least type T, U, V and that I'm not going to put anything into this tuple.&lt;/div&gt;</summary>
		<author><name>Seilerm</name></author>	</entry>

	<entry>
		<id>https://dev.eiffel.com/index.php?title=Class_checking&amp;diff=8194</id>
		<title>Class checking</title>
		<link rel="alternate" type="text/html" href="https://dev.eiffel.com/index.php?title=Class_checking&amp;diff=8194"/>
				<updated>2007-04-19T17:11:29Z</updated>
		
		<summary type="html">&lt;p&gt;Seilerm: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Introduction==&lt;br /&gt;
&lt;br /&gt;
This page is intended to find consensus over something called differently in EiffelStudio and gec/gelint.&lt;br /&gt;
&lt;br /&gt;
The subject for which a name is needed is the checking of all inherited features in the context of each descendant.&lt;br /&gt;
&lt;br /&gt;
==Proposals==&lt;br /&gt;
&lt;br /&gt;
===Proposal template===&lt;br /&gt;
====Pro====&lt;br /&gt;
====Contra====&lt;/div&gt;</summary>
		<author><name>Seilerm</name></author>	</entry>

	<entry>
		<id>https://dev.eiffel.com/index.php?title=Immutable_Strings&amp;diff=8164</id>
		<title>Immutable Strings</title>
		<link rel="alternate" type="text/html" href="https://dev.eiffel.com/index.php?title=Immutable_Strings&amp;diff=8164"/>
				<updated>2007-04-18T00:24:03Z</updated>
		
		<summary type="html">&lt;p&gt;Seilerm: /* Issues with ANY.is_equal */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{warning|This article under development and is not ready for any form of review.}}&lt;br /&gt;
&lt;br /&gt;
Author: Paul Bates&lt;br /&gt;
&lt;br /&gt;
[[Category:EiffelBase]]&lt;br /&gt;
&lt;br /&gt;
==Introduction==&lt;br /&gt;
On the heals of a point raised on [http://www.eiffelroom.com/blog/colin_adams/read_only_strings eiffelroom] regarding read-only variants of an Eiffel &amp;lt;code&amp;gt;[eiffel, n]STRING&amp;lt;/code&amp;gt;, this page has come about to discuss the possible options for introducing such new types.&lt;br /&gt;
&lt;br /&gt;
The term read-only is not a fitting name so this page documents such string variants as being immutable with it's already implemented cousins &amp;lt;code&amp;gt;[eiffel, n]STRING_8&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;[eiffel, n]STRING_32&amp;lt;/code&amp;gt; coined mutable.&lt;br /&gt;
&lt;br /&gt;
==Rational==&lt;br /&gt;
There are a number of reason why Eiffel needs an immutable representation of a string, which no matter what should be able to be altered. Below explains the rationale for why immutable strings are required in a language, as for those reasons why they are there.&lt;br /&gt;
&lt;br /&gt;
===EMCA STRING_8 and STRING_32 Are Not Constants===&lt;br /&gt;
Section 8.29 of the Eiffel ECMA specification details the declaration and use of constants in Eiffel. In section 8.29 the three Eiffel string forms are detailed as being constants. To be pedantic about the matter I extracted a dictional reference for the the word ''constant''.&lt;br /&gt;
&lt;br /&gt;
 ''con·stant'' /ˈkɒnstənt/&lt;br /&gt;
 &lt;br /&gt;
   –adjective&lt;br /&gt;
     1. Not changing or varying; uniform; regular; invariable.&lt;br /&gt;
 &lt;br /&gt;
   –noun&lt;br /&gt;
     7. Something that does not or cannot change or vary.&lt;br /&gt;
&lt;br /&gt;
ECMA details the use of the three &amp;lt;code&amp;gt;[eiffel, n]STRING&amp;lt;/code&amp;gt; declaration variants as constants but in reality this is contracting to the definition, and misleading in true semantics. &amp;lt;code&amp;gt;[eiffel, n]STRING&amp;lt;/code&amp;gt;s are mutable, &amp;quot;constants&amp;quot; are not. As a simple case example, take the following code snippet.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;[eiffel, n]&lt;br /&gt;
full_path: STRING_8&lt;br /&gt;
  once&lt;br /&gt;
    Result := template_path&lt;br /&gt;
    Result.replace_sub_string_all (&amp;quot;$1&amp;quot;, root_path)&lt;br /&gt;
  ensure&lt;br /&gt;
    result_attached: Result /= Void&lt;br /&gt;
    not_result_is_empty: not Result.is_empty&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
template_path: STRING_8 = &amp;quot;$1\data\default.cfg&amp;quot;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The code demonstrates an all too common scenario. Once &amp;lt;code&amp;gt;[eiffel, n]full_path&amp;lt;/code&amp;gt; has been called the contents of template_path are modified. Any other use of &amp;lt;code&amp;gt;[eiffel, n]template_path&amp;lt;/code&amp;gt; will yield a &amp;quot;constant&amp;quot; value that differs from that declared. The EMCA specification indicates that declaration of &amp;lt;code&amp;gt;[eiffel, n]template_path&amp;lt;/code&amp;gt; pertains to the specification of a constant attribute (8.29.2 and 8.29.3.)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;[eiffel, n]full_path&amp;lt;/code&amp;gt;, with once function semantics, is never a constant but is evaluated on a single as-needed basis. full_path actually demonstrates yet another rationale for introducing immutable strings into Eiffel.&lt;br /&gt;
&lt;br /&gt;
===Immutable Interfaces===&lt;br /&gt;
&lt;br /&gt;
A second rationale is through good design of a class' exported interface. A good design will yield immutable exported members as not to seemingly violate such principles of object orientation. I note &amp;quot;seemly&amp;quot; violated because by technical reference such principles are not violated. The principle in reference is one that states - a class, and it's descendants, should be the only entities to modify a respective runtime instantiation internal state. No client should be permitted to perform such modifications - Technically STRING is a reference type so a qualified call, like append, made on a STRING object, is modifying the internal state of that STRING object. However STRING has special reverence that binds it with the likes of INTEGER, NATURAL and CHARACTER. It's an inbuilt rudimentary type that is seen to be &amp;quot;a value&amp;quot;. Almost all other reference types are just objects and runtime with no real discernible value.&lt;br /&gt;
&lt;br /&gt;
Current EiffelBase abstraction enabled authoring of immutable exported client interfaces, yet allow resident routines to manipulate the internals of an object's state.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;[eiffel, n]&lt;br /&gt;
feature -- Access&lt;br /&gt;
 &lt;br /&gt;
  selected_indexes: BILINEAR [NATURAL]&lt;br /&gt;
      -- Select item indexes&lt;br /&gt;
    do&lt;br /&gt;
      Result := internal_selected_indexes&lt;br /&gt;
    ensure&lt;br /&gt;
      result_attached: Result /= Void&lt;br /&gt;
    end&lt;br /&gt;
 &lt;br /&gt;
feature {NONE} -- Implementation&lt;br /&gt;
&lt;br /&gt;
  internal_selected_indexes: ARRAYED_LIST [NATURAL]&lt;br /&gt;
      -- Mutable version of `internal_selected_indexes'&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
selected_indexes permits clients to access a list of index positions but never allows any extending or removal of items from that structure. &amp;lt;code&amp;gt;[eiffel, n]internal_selected_indexes&amp;lt;/code&amp;gt; is used internally to add or extend items based on some peripheral interaction. If the author wanted client to modified the result of selected_indexes then additional routines can be implemented on a fully or partially exported part of the class' interface. Such routines as &amp;lt;code&amp;gt;[eiffel, n]set_selected_indexes&amp;lt;/code&amp;gt; could be implemented or &amp;lt;code&amp;gt;[eiffel, n]add_index&amp;lt;/code&amp;gt; and the conversely &amp;lt;code&amp;gt;[eiffel, n]remove_index&amp;lt;/code&amp;gt; could be implemented as a Delegate pattern implementation.&lt;br /&gt;
&lt;br /&gt;
As it stands today, with only mutable strings, it is not possible to author such classes. A class attribute, or a once function, is open for modification by an unruly client, where it be accidental through a missing clone of a &amp;lt;code&amp;gt;[eiffel, n]STRING&amp;lt;/code&amp;gt;, using twin, or through naivety. Either way, it's dangerous!&lt;br /&gt;
&lt;br /&gt;
==Suggestions to Implementation==&lt;br /&gt;
&lt;br /&gt;
There are a number of factors to consider before deciding on a implementation choice for immutable string. First and probably most importantly is compatibility. Compatibility raises concerns regarding the assignment of a mutable string to an immutable string, vice-versa and even back again.&lt;br /&gt;
&lt;br /&gt;
==Compatibility==&lt;br /&gt;
Before any indicate of how mutable and immutable strings interacte there's needs to be a brief rundown of the possible ways they can interact. There's two schools of thought; Conformance or Conversion.&lt;br /&gt;
&lt;br /&gt;
===Conformance or Conversion===&lt;br /&gt;
It has been mentioned that maybe an immutable string should conform to a mutable string, for optimization purposes. Respecting the possible choice for conformance it does not seem coherent that a mutable string is actually a specialized immutable string?! In addition, with conformance it would be entirely possible to reverse assign an immutable string to a mutable string, rendering any immutable client interface ineffective at preventing external modification.&lt;br /&gt;
&lt;br /&gt;
The alternative to conformance would be to use an implicit conversion routine to convert the mutable string to an immutable one, on assignment or a pass through to a routine argument typed to an immutable string. Conversion, personally, seems the most correct route to follow.&lt;br /&gt;
&lt;br /&gt;
===Examples===&lt;br /&gt;
&lt;br /&gt;
For the purpose of illustration the following declarations will be used. &amp;lt;code&amp;gt;[eiffel, n]IMMUTABLE_STRING_8&amp;lt;/code&amp;gt; is being introduced as a place holder for a immutable variant of the current mutable &amp;lt;code&amp;gt;[eiffel, n]IMMUTABLE_STRING_8&amp;lt;/code&amp;gt; class.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;[eiffel]&lt;br /&gt;
ms1: STRING_8&lt;br /&gt;
ms2: STRING_8&lt;br /&gt;
is1: IMMUTABLE_STRING_8&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The first topic is to determine how manifest string constants comply with mutable strings. The following lists all syntax valid operations based on the ECMA specification. The assignments are made using the types manifest constant specification in section 8.29.6.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;[eiffel]&lt;br /&gt;
1. ms1 := &amp;quot;Hello World&amp;quot;&lt;br /&gt;
2. ms1 := {STRING_8} &amp;quot;Hello World&amp;quot;&lt;br /&gt;
3. ms1 := {IMMUTABLE_STRING_8} &amp;quot;Hello World&amp;quot;&lt;br /&gt;
4. ms1 := once &amp;quot;Hello World&amp;quot;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In case '''1''' the compiler should recognize the assignment and create a &amp;lt;code&amp;gt;[eiffel]STRING_8&amp;lt;/code&amp;gt; using the manifest string. No immutable string should be created. Case '''2''' is effectively the same as case '''1''', just more explicit. Case '''3''' introduces the immutable string. In this case the compiler should reject the call. Immutable strings cannot become mutable. If the conforming option for implement were to be chose then &amp;lt;code&amp;gt;[eiffel]ms1&amp;lt;/code&amp;gt; would be set to &amp;lt;code&amp;gt;[eiffel]Void&amp;lt;/code&amp;gt;. An immutable string has been created and it does not conform to &amp;lt;code&amp;gt;[eiffel]STRING_8&amp;lt;/code&amp;gt;. Finally case '''4''' leaves room for explanation. In a world of Eiffel immutable strings a once string should behave in the same manner as case '''3'''. Currently it behaves like cases '''1''' and '''2'''.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;[eiffel]&lt;br /&gt;
1. is1 := &amp;quot;Hello Immutable World&amp;quot;&lt;br /&gt;
2. is1 := {STRING_8} &amp;quot;Hello Immutable World&amp;quot;&lt;br /&gt;
3. is1 := {IMMUTABLE_STRING_8} &amp;quot;Hello Immutable World&amp;quot;&lt;br /&gt;
4. is1 := once &amp;quot;Hello Immutable World&amp;quot;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In case '''1''' the compiler should recognize the assignment and create a &amp;lt;code&amp;gt;[eiffel]IMMUTABLE_STRING_8&amp;lt;/code&amp;gt; using the manifest string. No mutable string should be created. Case '''2''' uses the mutable string. In this case the developer has explicitly requested that the manifest string be of an immutable type. The course of action is dictated by a choice between conformance or conversion. Case '''3''' is effectively the same as case '''1''', just more explicit. Finally case '''4''' leaves room for explanation. In a world of Eiffel immutable strings a once string should behave in the same manner as cases '''1''' and '''3'''. Currently there is no defined behavior for this.&lt;br /&gt;
&lt;br /&gt;
===Using Conversion===&lt;br /&gt;
As stated conversion seems to be the winner. In discussing this with others at Eiffel Software it seems the vote is unanimous that conversion is the best option after all things considered. The road to using conversion as a mean to interop between strings is not a clear one. There are problems that need to be overcome.&lt;br /&gt;
&lt;br /&gt;
====Fetching a Mutable String====&lt;br /&gt;
First and most rudimentary is the ability to fetch a mutable version of an immutable string. All that is needed is function to make the explicit conversion; &amp;lt;code&amp;gt;[eiffel, n]as_string_8&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;[eiffel, n]as_string_32&amp;lt;/code&amp;gt; functions will have to be added to the immutable string class or be defined in a more abstract version of the class.&lt;br /&gt;
&lt;br /&gt;
====Issues with ANY.is_equal====&lt;br /&gt;
With a non-conforming implementation of mutable and immutable strings &amp;lt;code&amp;gt;[eiffel, n]ANY.is_equal&amp;lt;/code&amp;gt; as defined in ECMA will be broken.&lt;br /&gt;
&lt;br /&gt;
ECMA's &amp;lt;code&amp;gt;[eiffel, n]is_equal&amp;lt;/code&amp;gt; loosens the binds when it comes to comparing objects for equality. &amp;lt;code&amp;gt;[eiffel, n]is_equal&amp;lt;/code&amp;gt;'s argument &amp;lt;code&amp;gt;[eiffel, n]other&amp;lt;/code&amp;gt; is now of type &amp;lt;code&amp;gt;[eiffel, n]ANY&amp;lt;/code&amp;gt; and not a CAT-call prone &amp;lt;code&amp;gt;[eiffel, n]like Current&amp;lt;/code&amp;gt; anchored type. It's not desirable to compare immutable string with only immutable string, and the same is true for mutable strings and mutable strings. Functionality must be provided to compare either or for equality and &amp;lt;code&amp;gt;[eiffel, n]True&amp;lt;/code&amp;gt; returned as a result when both strings contain the same chain of characters. To support this crucial scenario a common base for '''all''' string variants needs to be introduced. For the sake of clarity with names, this shall be referenced as &amp;lt;code&amp;gt;[eiffel, n]ABSTRACT_STRING&amp;lt;/code&amp;gt; (see A Common Ancestor). &amp;lt;code&amp;gt;[eiffel, n]ABSTRACT_STRING&amp;lt;/code&amp;gt; should covariantly redefine &amp;lt;code&amp;gt;[eiffel, n]ANY.is_equal&amp;lt;/code&amp;gt; so it's &amp;lt;code&amp;gt;[eiffel, n]other&amp;lt;/code&amp;gt; argument is of type &amp;lt;code&amp;gt;[eiffel, n]ABSTRACT_STRING&amp;lt;/code&amp;gt;. This way strings can be compared without any need for conversion with more concrete versions of &amp;lt;code&amp;gt;[eiffel, n]STRING_8&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;[eiffel, n]IMMUTABLE_STRING_8&amp;lt;/code&amp;gt;. More importantly, no risk of CAT-calls.&lt;br /&gt;
&lt;br /&gt;
The second and more dispelling problem is with the postconditions. &amp;lt;code&amp;gt;[eiffel, n]same_type&amp;lt;/code&amp;gt; will fail! It's possible for immutable and mutable strings to be declared as being equal, after all most of the time it's the content a program wants to compare and not the object reference. It is an argumentative point if two related but different objects can be equal, with accordance to the EMCA informative text.&lt;br /&gt;
&lt;br /&gt;
''&amp;quot;..default_is_equal is frozen, always returning the value of field-by-field identity comparison (for not-void other); any class may, on the other hand, redefine is_equal, in accordance with the pre- and postconditions, to reflect a more specific notion of equality.&amp;quot;''&lt;br /&gt;
&lt;br /&gt;
Should it really matter then that the objects being compared actually be of the same type, when the result of &amp;lt;code&amp;gt;[eiffel, n]is_equal&amp;lt;/code&amp;gt; yields &amp;lt;code&amp;gt;[eiffel, n]True&amp;lt;/code&amp;gt;? The post-conditions are too strong, forbidding two disparate from being compared in valid domain context.&lt;br /&gt;
&lt;br /&gt;
====Optimizations====&lt;br /&gt;
The mutable versions of the string class should convert to, and cache, an immutable variant of a string upon an initial request. Once the mutable string's content is modified the cached immutable string is to invalidated. The next request to convert the mutable string to an immutable variant would yield a new immutable string reference.&lt;br /&gt;
&lt;br /&gt;
====A Common Ancestor====&lt;br /&gt;
Just as &amp;lt;code&amp;gt;[eiffel, n]STRING_GENERAL&amp;lt;/code&amp;gt; is available now, a more abstract implementation is required to implement the features available for all string variants. That is; mutable, immutable and 8 and 32 bit versions of each. In the interest of backwards compatibility the use of &amp;lt;code&amp;gt;[eiffel, n]STRING_GENERAL&amp;lt;/code&amp;gt; is not a viable solution. A proposed &amp;lt;code&amp;gt;[eiffel, n]ABSTRACT_STRING&amp;lt;/code&amp;gt; will instead be put forth for the real general purpose string class.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;[eiffel, n]ABSTRACT_STRING&amp;lt;/code&amp;gt; should contain a number of the routines moved up &amp;lt;code&amp;gt;[eiffel, n]STRING_GENERAL&amp;lt;/code&amp;gt; and STRING_GENERAL&amp;lt;/code&amp;gt; will hence forth derived &amp;lt;code&amp;gt;[eiffel, n]ABSTRACT_STRING&amp;lt;/code&amp;gt;. The routines that will not be resident in &amp;lt;code&amp;gt;[eiffel, n]ABSTRACT_STRING&amp;lt;/code&amp;gt; will be anything pertaining to mutating the internal representation.&lt;br /&gt;
&lt;br /&gt;
==Is There a Need to STRING_8 and STRING_32==&lt;br /&gt;
Of course in outlining such a proposal you have to ask the relevance of augments/patching (it depends on your views) Eiffel with immutable strings. Should Eiffel just have immutable strings? It's been discussed that there should be mutable and immutable variants of &amp;lt;code&amp;gt;[eiffel, n]STRING&amp;lt;/code&amp;gt;. Deviating from this a moment and looking at the best possible scenario for implementing immutable strings - make mutable strings a thing of the past!&lt;br /&gt;
&lt;br /&gt;
So many other languages have chosen to use a immutable string as their fundamental string type. For optimization in creating new strings or piecing parts of strings together a string builder is used. Under .NET there is the immutable &amp;lt;code&amp;gt;[csharp, n]System.String&amp;lt;/code&amp;gt; and optimized builder &amp;lt;code&amp;gt;[csharp, n]System.Text.StringBuilder&amp;lt;/code&amp;gt;. In Java the exact same story; &amp;lt;code&amp;gt;[java, n]String&amp;lt;/code&amp;gt; is an immutable string and &amp;lt;code&amp;gt;[java, n]StringBuffer&amp;lt;/code&amp;gt; is used to optimally create immutable strings.&lt;br /&gt;
&lt;br /&gt;
Yes, choosing such a option would break existing code. But we have to respect that trying to patch rather than change, often causes more problems that breaking code. With code breaking changes there should always be assistants available to help user migrate.&lt;br /&gt;
&lt;br /&gt;
As simple first step is to change all &amp;lt;code&amp;gt;[eiffel, n]STRING_8&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;[eiffel, n]STRING_32&amp;lt;/code&amp;gt; into &amp;lt;code&amp;gt;[eiffel, n]STRING_BUILDER_8&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;[eiffel, n]STRING_BUILDER_32&amp;lt;/code&amp;gt;, or indeed a unified &amp;lt;code&amp;gt;[eiffel, n]STRING_BUILDER&amp;lt;/code&amp;gt; for manipulating any sized string. The breaking changes can be minimized and all future use of &amp;lt;code&amp;gt;[eiffel, n]STRING_8&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;[eiffel, n]STRING_32&amp;lt;/code&amp;gt; are known to be immutable.&lt;br /&gt;
&lt;br /&gt;
Should Eiffel follow suit and depreciate the existing implementation of &amp;lt;code&amp;gt;[eiffel, n]STRING_8&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;[eiffel, n]STRING_32&amp;lt;/code&amp;gt;, in order to favor immutable strings and string builder(s)?&lt;/div&gt;</summary>
		<author><name>Seilerm</name></author>	</entry>

	<entry>
		<id>https://dev.eiffel.com/index.php?title=Immutable_Strings&amp;diff=8162</id>
		<title>Immutable Strings</title>
		<link rel="alternate" type="text/html" href="https://dev.eiffel.com/index.php?title=Immutable_Strings&amp;diff=8162"/>
				<updated>2007-04-18T00:16:11Z</updated>
		
		<summary type="html">&lt;p&gt;Seilerm: /* Conformance or Conversion */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{warning|This article under development and is not ready for any form of review.}}&lt;br /&gt;
&lt;br /&gt;
Author: Paul Bates&lt;br /&gt;
&lt;br /&gt;
[[Category:EiffelBase]]&lt;br /&gt;
&lt;br /&gt;
==Introduction==&lt;br /&gt;
On the heals of a point raised on [http://www.eiffelroom.com/blog/colin_adams/read_only_strings eiffelroom] regarding read-only variants of an Eiffel &amp;lt;code&amp;gt;[eiffel, n]STRING&amp;lt;/code&amp;gt;, this page has come about to discuss the possible options for introducing such new types.&lt;br /&gt;
&lt;br /&gt;
The term read-only is not a fitting name so this page documents such string variants as being immutable with it's already implemented cousins &amp;lt;code&amp;gt;[eiffel, n]STRING_8&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;[eiffel, n]STRING_32&amp;lt;/code&amp;gt; coined mutable.&lt;br /&gt;
&lt;br /&gt;
==Rational==&lt;br /&gt;
There are a number of reason why Eiffel needs an immutable representation of a string, which no matter what should be able to be altered. Below explains the rationale for why immutable strings are required in a language, as for those reasons why they are there.&lt;br /&gt;
&lt;br /&gt;
===EMCA STRING_8 and STRING_32 Are Not Constants===&lt;br /&gt;
Section 8.29 of the Eiffel ECMA specification details the declaration and use of constants in Eiffel. In section 8.29 the three Eiffel string forms are detailed as being constants. To be pedantic about the matter I extracted a dictional reference for the the word ''constant''.&lt;br /&gt;
&lt;br /&gt;
 ''con·stant'' /ˈkɒnstənt/&lt;br /&gt;
 &lt;br /&gt;
   –adjective&lt;br /&gt;
     1. Not changing or varying; uniform; regular; invariable.&lt;br /&gt;
 &lt;br /&gt;
   –noun&lt;br /&gt;
     7. Something that does not or cannot change or vary.&lt;br /&gt;
&lt;br /&gt;
ECMA details the use of the three &amp;lt;code&amp;gt;[eiffel, n]STRING&amp;lt;/code&amp;gt; declaration variants as constants but in reality this is contracting to the definition, and misleading in true semantics. &amp;lt;code&amp;gt;[eiffel, n]STRING&amp;lt;/code&amp;gt;s are mutable, &amp;quot;constants&amp;quot; are not. As a simple case example, take the following code snippet.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;[eiffel, n]&lt;br /&gt;
full_path: STRING_8&lt;br /&gt;
  once&lt;br /&gt;
    Result := template_path&lt;br /&gt;
    Result.replace_sub_string_all (&amp;quot;$1&amp;quot;, root_path)&lt;br /&gt;
  ensure&lt;br /&gt;
    result_attached: Result /= Void&lt;br /&gt;
    not_result_is_empty: not Result.is_empty&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
template_path: STRING_8 = &amp;quot;$1\data\default.cfg&amp;quot;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The code demonstrates an all too common scenario. Once &amp;lt;code&amp;gt;[eiffel, n]full_path&amp;lt;/code&amp;gt; has been called the contents of template_path are modified. Any other use of &amp;lt;code&amp;gt;[eiffel, n]template_path&amp;lt;/code&amp;gt; will yield a &amp;quot;constant&amp;quot; value that differs from that declared. The EMCA specification indicates that declaration of &amp;lt;code&amp;gt;[eiffel, n]template_path&amp;lt;/code&amp;gt; pertains to the specification of a constant attribute (8.29.2 and 8.29.3.)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;[eiffel, n]full_path&amp;lt;/code&amp;gt;, with once function semantics, is never a constant but is evaluated on a single as-needed basis. full_path actually demonstrates yet another rationale for introducing immutable strings into Eiffel.&lt;br /&gt;
&lt;br /&gt;
===Immutable Interfaces===&lt;br /&gt;
&lt;br /&gt;
A second rationale is through good design of a class' exported interface. A good design will yield immutable exported members as not to seemingly violate such principles of object orientation. I note &amp;quot;seemly&amp;quot; violated because by technical reference such principles are not violated. The principle in reference is one that states - a class, and it's descendants, should be the only entities to modify a respective runtime instantiation internal state. No client should be permitted to perform such modifications - Technically STRING is a reference type so a qualified call, like append, made on a STRING object, is modifying the internal state of that STRING object. However STRING has special reverence that binds it with the likes of INTEGER, NATURAL and CHARACTER. It's an inbuilt rudimentary type that is seen to be &amp;quot;a value&amp;quot;. Almost all other reference types are just objects and runtime with no real discernible value.&lt;br /&gt;
&lt;br /&gt;
Current EiffelBase abstraction enabled authoring of immutable exported client interfaces, yet allow resident routines to manipulate the internals of an object's state.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;[eiffel, n]&lt;br /&gt;
feature -- Access&lt;br /&gt;
 &lt;br /&gt;
  selected_indexes: BILINEAR [NATURAL]&lt;br /&gt;
      -- Select item indexes&lt;br /&gt;
    do&lt;br /&gt;
      Result := internal_selected_indexes&lt;br /&gt;
    ensure&lt;br /&gt;
      result_attached: Result /= Void&lt;br /&gt;
    end&lt;br /&gt;
 &lt;br /&gt;
feature {NONE} -- Implementation&lt;br /&gt;
&lt;br /&gt;
  internal_selected_indexes: ARRAYED_LIST [NATURAL]&lt;br /&gt;
      -- Mutable version of `internal_selected_indexes'&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
selected_indexes permits clients to access a list of index positions but never allows any extending or removal of items from that structure. &amp;lt;code&amp;gt;[eiffel, n]internal_selected_indexes&amp;lt;/code&amp;gt; is used internally to add or extend items based on some peripheral interaction. If the author wanted client to modified the result of selected_indexes then additional routines can be implemented on a fully or partially exported part of the class' interface. Such routines as &amp;lt;code&amp;gt;[eiffel, n]set_selected_indexes&amp;lt;/code&amp;gt; could be implemented or &amp;lt;code&amp;gt;[eiffel, n]add_index&amp;lt;/code&amp;gt; and the conversely &amp;lt;code&amp;gt;[eiffel, n]remove_index&amp;lt;/code&amp;gt; could be implemented as a Delegate pattern implementation.&lt;br /&gt;
&lt;br /&gt;
As it stands today, with only mutable strings, it is not possible to author such classes. A class attribute, or a once function, is open for modification by an unruly client, where it be accidental through a missing clone of a &amp;lt;code&amp;gt;[eiffel, n]STRING&amp;lt;/code&amp;gt;, using twin, or through naivety. Either way, it's dangerous!&lt;br /&gt;
&lt;br /&gt;
==Suggestions to Implementation==&lt;br /&gt;
&lt;br /&gt;
There are a number of factors to consider before deciding on a implementation choice for immutable string. First and probably most importantly is compatibility. Compatibility raises concerns regarding the assignment of a mutable string to an immutable string, vice-versa and even back again.&lt;br /&gt;
&lt;br /&gt;
==Compatibility==&lt;br /&gt;
Before any indicate of how mutable and immutable strings interacte there's needs to be a brief rundown of the possible ways they can interact. There's two schools of thought; Conformance or Conversion.&lt;br /&gt;
&lt;br /&gt;
===Conformance or Conversion===&lt;br /&gt;
It has been mentioned that maybe an immutable string should conform to a mutable string, for optimization purposes. Respecting the possible choice for conformance it does not seem coherent that a mutable string is actually a specialized immutable string?! In addition, with conformance it would be entirely possible to reverse assign an immutable string to a mutable string, rendering any immutable client interface ineffective at preventing external modification.&lt;br /&gt;
&lt;br /&gt;
The alternative to conformance would be to use an implicit conversion routine to convert the mutable string to an immutable one, on assignment or a pass through to a routine argument typed to an immutable string. Conversion, personally, seems the most correct route to follow.&lt;br /&gt;
&lt;br /&gt;
===Examples===&lt;br /&gt;
&lt;br /&gt;
For the purpose of illustration the following declarations will be used. &amp;lt;code&amp;gt;[eiffel, n]IMMUTABLE_STRING_8&amp;lt;/code&amp;gt; is being introduced as a place holder for a immutable variant of the current mutable &amp;lt;code&amp;gt;[eiffel, n]IMMUTABLE_STRING_8&amp;lt;/code&amp;gt; class.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;[eiffel]&lt;br /&gt;
ms1: STRING_8&lt;br /&gt;
ms2: STRING_8&lt;br /&gt;
is1: IMMUTABLE_STRING_8&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The first topic is to determine how manifest string constants comply with mutable strings. The following lists all syntax valid operations based on the ECMA specification. The assignments are made using the types manifest constant specification in section 8.29.6.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;[eiffel]&lt;br /&gt;
1. ms1 := &amp;quot;Hello World&amp;quot;&lt;br /&gt;
2. ms1 := {STRING_8} &amp;quot;Hello World&amp;quot;&lt;br /&gt;
3. ms1 := {IMMUTABLE_STRING_8} &amp;quot;Hello World&amp;quot;&lt;br /&gt;
4. ms1 := once &amp;quot;Hello World&amp;quot;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In case '''1''' the compiler should recognize the assignment and create a &amp;lt;code&amp;gt;[eiffel]STRING_8&amp;lt;/code&amp;gt; using the manifest string. No immutable string should be created. Case '''2''' is effectively the same as case '''1''', just more explicit. Case '''3''' introduces the immutable string. In this case the compiler should reject the call. Immutable strings cannot become mutable. If the conforming option for implement were to be chose then &amp;lt;code&amp;gt;[eiffel]ms1&amp;lt;/code&amp;gt; would be set to &amp;lt;code&amp;gt;[eiffel]Void&amp;lt;/code&amp;gt;. An immutable string has been created and it does not conform to &amp;lt;code&amp;gt;[eiffel]STRING_8&amp;lt;/code&amp;gt;. Finally case '''4''' leaves room for explanation. In a world of Eiffel immutable strings a once string should behave in the same manner as case '''3'''. Currently it behaves like cases '''1''' and '''2'''.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;[eiffel]&lt;br /&gt;
1. is1 := &amp;quot;Hello Immutable World&amp;quot;&lt;br /&gt;
2. is1 := {STRING_8} &amp;quot;Hello Immutable World&amp;quot;&lt;br /&gt;
3. is1 := {IMMUTABLE_STRING_8} &amp;quot;Hello Immutable World&amp;quot;&lt;br /&gt;
4. is1 := once &amp;quot;Hello Immutable World&amp;quot;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In case '''1''' the compiler should recognize the assignment and create a &amp;lt;code&amp;gt;[eiffel]IMMUTABLE_STRING_8&amp;lt;/code&amp;gt; using the manifest string. No mutable string should be created. Case '''2''' uses the mutable string. In this case the developer has explicitly requested that the manifest string be of an immutable type. The course of action is dictated by a choice between conformance or conversion. Case '''3''' is effectively the same as case '''1''', just more explicit. Finally case '''4''' leaves room for explanation. In a world of Eiffel immutable strings a once string should behave in the same manner as cases '''1''' and '''3'''. Currently there is no defined behavior for this.&lt;br /&gt;
&lt;br /&gt;
===Using Conversion===&lt;br /&gt;
As stated conversion seems to be the winner. In discussing this with others at Eiffel Software it seems the vote is unanimous that conversion is the best option after all things considered. The road to using conversion as a mean to interop between strings is not a clear one. There are problems that need to be overcome.&lt;br /&gt;
&lt;br /&gt;
====Fetching a Mutable String====&lt;br /&gt;
First and most rudimentary is the ability to fetch a mutable version of an immutable string. All that is needed is function to make the explicit conversion; &amp;lt;code&amp;gt;[eiffel, n]as_string_8&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;[eiffel, n]as_string_32&amp;lt;/code&amp;gt; functions will have to be added to the immutable string class or be defined in a more abstract version of the class.&lt;br /&gt;
&lt;br /&gt;
====Issues with ANY.is_equal====&lt;br /&gt;
With a non-conforming implementation of mutable and immutable strings &amp;lt;code&amp;gt;[eiffel, n]ANY.is_equal&amp;lt;/code&amp;gt; as defined in ECMA will be broken.&lt;br /&gt;
&lt;br /&gt;
ECMA's &amp;lt;code&amp;gt;[eiffel, n]is_equal&amp;lt;/code&amp;gt; loosens the binds when it comes to comparing objects for equality. &amp;lt;code&amp;gt;[eiffel, n]is_equal&amp;lt;/code&amp;gt;'s argument &amp;lt;code&amp;gt;[eiffel, n]other&amp;lt;/code&amp;gt; is now of type &amp;lt;code&amp;gt;[eiffel, n]ANY&amp;lt;/code&amp;gt; and not a CAT-call prone &amp;lt;code&amp;gt;[eiffel, n]like Current&amp;lt;/code&amp;gt; anchored type. It's not desirable to compare immutable string with only immutable string, and the same is true for mutable strings and mutable strings. Functionality must be provided to compare either or for equality and &amp;lt;code&amp;gt;[eiffel, n]True&amp;lt;/code&amp;gt; returned as a result when both strings contain the same chain of characters. To support this crucial scenario a common base for '''all''' string variants needs to be introduced. For the sake of clarity with names, this shall be referenced as &amp;lt;code&amp;gt;[eiffel, n]ABSTRACT_STRING&amp;lt;/code&amp;gt; (see A Common Ancestor). &amp;lt;code&amp;gt;[eiffel, n]ABSTRACT_STRING&amp;lt;/code&amp;gt; should convariantly redefine &amp;lt;code&amp;gt;[eiffel, n]ANY.is_equal&amp;lt;/code&amp;gt; so it's &amp;lt;code&amp;gt;[eiffel, n]other&amp;lt;/code&amp;gt; argument is of type &amp;lt;code&amp;gt;[eiffel, n]ABSTRACT_STRING&amp;lt;/code&amp;gt;. This way strings can be compared without any need for conversion with more concrete versions of &amp;lt;code&amp;gt;[eiffel, n]STRING_8&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;[eiffel, n]IMMUTABLE_STRING_8&amp;lt;/code&amp;gt;. More importantly, no risk of CAT-calls.&lt;br /&gt;
&lt;br /&gt;
The second and more dispelling problem is with the postconditions. &amp;lt;code&amp;gt;[eiffel, n]same_type&amp;lt;/code&amp;gt; will fail! It's possible for immutable and mutable strings to be declared as being equal, after all most of the time it's the content a program wants to compare and not the object reference. It is an argumentative point if two related but different objects can be equal, with accordance to the EMCA informative text.&lt;br /&gt;
&lt;br /&gt;
''&amp;quot;..default_is_equal is frozen, always returning the value of field-by-field identity comparison (for not-void other); any class may, on the other hand, redefine is_equal, in accordance with the pre- and postconditions, to reflect a more specific notion of equality.&amp;quot;''&lt;br /&gt;
&lt;br /&gt;
Should it really matter then that the objects being compared actually be of the same type, when the result of &amp;lt;code&amp;gt;[eiffel, n]is_equal&amp;lt;/code&amp;gt; yields &amp;lt;code&amp;gt;[eiffel, n]True&amp;lt;/code&amp;gt;? The post-conditions are too strong, forbidding two disparate from being compared in valid domain context.&lt;br /&gt;
&lt;br /&gt;
====Optimizations====&lt;br /&gt;
The mutable versions of the string class should convert to, and cache, an immutable variant of a string upon an initial request. Once the mutable string's content is modified the cached immutable string is to invalidated. The next request to convert the mutable string to an immutable variant would yield a new immutable string reference.&lt;br /&gt;
&lt;br /&gt;
====A Common Ancestor====&lt;br /&gt;
Just as &amp;lt;code&amp;gt;[eiffel, n]STRING_GENERAL&amp;lt;/code&amp;gt; is available now, a more abstract implementation is required to implement the features available for all string variants. That is; mutable, immutable and 8 and 32 bit versions of each. In the interest of backwards compatibility the use of &amp;lt;code&amp;gt;[eiffel, n]STRING_GENERAL&amp;lt;/code&amp;gt; is not a viable solution. A proposed &amp;lt;code&amp;gt;[eiffel, n]ABSTRACT_STRING&amp;lt;/code&amp;gt; will instead be put forth for the real general purpose string class.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;[eiffel, n]ABSTRACT_STRING&amp;lt;/code&amp;gt; should contain a number of the routines moved up &amp;lt;code&amp;gt;[eiffel, n]STRING_GENERAL&amp;lt;/code&amp;gt; and STRING_GENERAL&amp;lt;/code&amp;gt; will hence forth derived &amp;lt;code&amp;gt;[eiffel, n]ABSTRACT_STRING&amp;lt;/code&amp;gt;. The routines that will not be resident in &amp;lt;code&amp;gt;[eiffel, n]ABSTRACT_STRING&amp;lt;/code&amp;gt; will be anything pertaining to mutating the internal representation.&lt;br /&gt;
&lt;br /&gt;
==Is There a Need to STRING_8 and STRING_32==&lt;br /&gt;
Of course in outlining such a proposal you have to ask the relevance of augments/patching (it depends on your views) Eiffel with immutable strings. Should Eiffel just have immutable strings? It's been discussed that there should be mutable and immutable variants of &amp;lt;code&amp;gt;[eiffel, n]STRING&amp;lt;/code&amp;gt;. Deviating from this a moment and looking at the best possible scenario for implementing immutable strings - make mutable strings a thing of the past!&lt;br /&gt;
&lt;br /&gt;
So many other languages have chosen to use a immutable string as their fundamental string type. For optimization in creating new strings or piecing parts of strings together a string builder is used. Under .NET there is the immutable &amp;lt;code&amp;gt;[csharp, n]System.String&amp;lt;/code&amp;gt; and optimized builder &amp;lt;code&amp;gt;[csharp, n]System.Text.StringBuilder&amp;lt;/code&amp;gt;. In Java the exact same story; &amp;lt;code&amp;gt;[java, n]String&amp;lt;/code&amp;gt; is an immutable string and &amp;lt;code&amp;gt;[java, n]StringBuffer&amp;lt;/code&amp;gt; is used to optimally create immutable strings.&lt;br /&gt;
&lt;br /&gt;
Yes, choosing such a option would break existing code. But we have to respect that trying to patch rather than change, often causes more problems that breaking code. With code breaking changes there should always be assistants available to help user migrate.&lt;br /&gt;
&lt;br /&gt;
As simple first step is to change all &amp;lt;code&amp;gt;[eiffel, n]STRING_8&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;[eiffel, n]STRING_32&amp;lt;/code&amp;gt; into &amp;lt;code&amp;gt;[eiffel, n]STRING_BUILDER_8&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;[eiffel, n]STRING_BUILDER_32&amp;lt;/code&amp;gt;, or indeed a unified &amp;lt;code&amp;gt;[eiffel, n]STRING_BUILDER&amp;lt;/code&amp;gt; for manipulating any sized string. The breaking changes can be minimized and all future use of &amp;lt;code&amp;gt;[eiffel, n]STRING_8&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;[eiffel, n]STRING_32&amp;lt;/code&amp;gt; are known to be immutable.&lt;br /&gt;
&lt;br /&gt;
Should Eiffel follow suit and depreciate the existing implementation of &amp;lt;code&amp;gt;[eiffel, n]STRING_8&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;[eiffel, n]STRING_32&amp;lt;/code&amp;gt;, in order to favor immutable strings and string builder(s)?&lt;/div&gt;</summary>
		<author><name>Seilerm</name></author>	</entry>

	<entry>
		<id>https://dev.eiffel.com/index.php?title=Immutable_Strings&amp;diff=8161</id>
		<title>Immutable Strings</title>
		<link rel="alternate" type="text/html" href="https://dev.eiffel.com/index.php?title=Immutable_Strings&amp;diff=8161"/>
				<updated>2007-04-18T00:14:18Z</updated>
		
		<summary type="html">&lt;p&gt;Seilerm: /* Conformance or Conversion */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{warning|This article under development and is not ready for any form of review.}}&lt;br /&gt;
&lt;br /&gt;
Author: Paul Bates&lt;br /&gt;
&lt;br /&gt;
[[Category:EiffelBase]]&lt;br /&gt;
&lt;br /&gt;
==Introduction==&lt;br /&gt;
On the heals of a point raised on [http://www.eiffelroom.com/blog/colin_adams/read_only_strings eiffelroom] regarding read-only variants of an Eiffel &amp;lt;code&amp;gt;[eiffel, n]STRING&amp;lt;/code&amp;gt;, this page has come about to discuss the possible options for introducing such new types.&lt;br /&gt;
&lt;br /&gt;
The term read-only is not a fitting name so this page documents such string variants as being immutable with it's already implemented cousins &amp;lt;code&amp;gt;[eiffel, n]STRING_8&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;[eiffel, n]STRING_32&amp;lt;/code&amp;gt; coined mutable.&lt;br /&gt;
&lt;br /&gt;
==Rational==&lt;br /&gt;
There are a number of reason why Eiffel needs an immutable representation of a string, which no matter what should be able to be altered. Below explains the rationale for why immutable strings are required in a language, as for those reasons why they are there.&lt;br /&gt;
&lt;br /&gt;
===EMCA STRING_8 and STRING_32 Are Not Constants===&lt;br /&gt;
Section 8.29 of the Eiffel ECMA specification details the declaration and use of constants in Eiffel. In section 8.29 the three Eiffel string forms are detailed as being constants. To be pedantic about the matter I extracted a dictional reference for the the word ''constant''.&lt;br /&gt;
&lt;br /&gt;
 ''con·stant'' /ˈkɒnstənt/&lt;br /&gt;
 &lt;br /&gt;
   –adjective&lt;br /&gt;
     1. Not changing or varying; uniform; regular; invariable.&lt;br /&gt;
 &lt;br /&gt;
   –noun&lt;br /&gt;
     7. Something that does not or cannot change or vary.&lt;br /&gt;
&lt;br /&gt;
ECMA details the use of the three &amp;lt;code&amp;gt;[eiffel, n]STRING&amp;lt;/code&amp;gt; declaration variants as constants but in reality this is contracting to the definition, and misleading in true semantics. &amp;lt;code&amp;gt;[eiffel, n]STRING&amp;lt;/code&amp;gt;s are mutable, &amp;quot;constants&amp;quot; are not. As a simple case example, take the following code snippet.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;[eiffel, n]&lt;br /&gt;
full_path: STRING_8&lt;br /&gt;
  once&lt;br /&gt;
    Result := template_path&lt;br /&gt;
    Result.replace_sub_string_all (&amp;quot;$1&amp;quot;, root_path)&lt;br /&gt;
  ensure&lt;br /&gt;
    result_attached: Result /= Void&lt;br /&gt;
    not_result_is_empty: not Result.is_empty&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
template_path: STRING_8 = &amp;quot;$1\data\default.cfg&amp;quot;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The code demonstrates an all too common scenario. Once &amp;lt;code&amp;gt;[eiffel, n]full_path&amp;lt;/code&amp;gt; has been called the contents of template_path are modified. Any other use of &amp;lt;code&amp;gt;[eiffel, n]template_path&amp;lt;/code&amp;gt; will yield a &amp;quot;constant&amp;quot; value that differs from that declared. The EMCA specification indicates that declaration of &amp;lt;code&amp;gt;[eiffel, n]template_path&amp;lt;/code&amp;gt; pertains to the specification of a constant attribute (8.29.2 and 8.29.3.)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;[eiffel, n]full_path&amp;lt;/code&amp;gt;, with once function semantics, is never a constant but is evaluated on a single as-needed basis. full_path actually demonstrates yet another rationale for introducing immutable strings into Eiffel.&lt;br /&gt;
&lt;br /&gt;
===Immutable Interfaces===&lt;br /&gt;
&lt;br /&gt;
A second rationale is through good design of a class' exported interface. A good design will yield immutable exported members as not to seemingly violate such principles of object orientation. I note &amp;quot;seemly&amp;quot; violated because by technical reference such principles are not violated. The principle in reference is one that states - a class, and it's descendants, should be the only entities to modify a respective runtime instantiation internal state. No client should be permitted to perform such modifications - Technically STRING is a reference type so a qualified call, like append, made on a STRING object, is modifying the internal state of that STRING object. However STRING has special reverence that binds it with the likes of INTEGER, NATURAL and CHARACTER. It's an inbuilt rudimentary type that is seen to be &amp;quot;a value&amp;quot;. Almost all other reference types are just objects and runtime with no real discernible value.&lt;br /&gt;
&lt;br /&gt;
Current EiffelBase abstraction enabled authoring of immutable exported client interfaces, yet allow resident routines to manipulate the internals of an object's state.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;[eiffel, n]&lt;br /&gt;
feature -- Access&lt;br /&gt;
 &lt;br /&gt;
  selected_indexes: BILINEAR [NATURAL]&lt;br /&gt;
      -- Select item indexes&lt;br /&gt;
    do&lt;br /&gt;
      Result := internal_selected_indexes&lt;br /&gt;
    ensure&lt;br /&gt;
      result_attached: Result /= Void&lt;br /&gt;
    end&lt;br /&gt;
 &lt;br /&gt;
feature {NONE} -- Implementation&lt;br /&gt;
&lt;br /&gt;
  internal_selected_indexes: ARRAYED_LIST [NATURAL]&lt;br /&gt;
      -- Mutable version of `internal_selected_indexes'&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
selected_indexes permits clients to access a list of index positions but never allows any extending or removal of items from that structure. &amp;lt;code&amp;gt;[eiffel, n]internal_selected_indexes&amp;lt;/code&amp;gt; is used internally to add or extend items based on some peripheral interaction. If the author wanted client to modified the result of selected_indexes then additional routines can be implemented on a fully or partially exported part of the class' interface. Such routines as &amp;lt;code&amp;gt;[eiffel, n]set_selected_indexes&amp;lt;/code&amp;gt; could be implemented or &amp;lt;code&amp;gt;[eiffel, n]add_index&amp;lt;/code&amp;gt; and the conversely &amp;lt;code&amp;gt;[eiffel, n]remove_index&amp;lt;/code&amp;gt; could be implemented as a Delegate pattern implementation.&lt;br /&gt;
&lt;br /&gt;
As it stands today, with only mutable strings, it is not possible to author such classes. A class attribute, or a once function, is open for modification by an unruly client, where it be accidental through a missing clone of a &amp;lt;code&amp;gt;[eiffel, n]STRING&amp;lt;/code&amp;gt;, using twin, or through naivety. Either way, it's dangerous!&lt;br /&gt;
&lt;br /&gt;
==Suggestions to Implementation==&lt;br /&gt;
&lt;br /&gt;
There are a number of factors to consider before deciding on a implementation choice for immutable string. First and probably most importantly is compatibility. Compatibility raises concerns regarding the assignment of a mutable string to an immutable string, vice-versa and even back again.&lt;br /&gt;
&lt;br /&gt;
==Compatibility==&lt;br /&gt;
Before any indicate of how mutable and immutable strings interacte there's needs to be a brief rundown of the possible ways they can interact. There's two schools of thought; Conformance or Conversion.&lt;br /&gt;
&lt;br /&gt;
===Conformance or Conversion===&lt;br /&gt;
It has been mentioned that maybe an immutable string should conform to a mutable string, for optimization purposes. Respecting the possible choice for conformance it does not seem coherent that a mutable string is actually a specialize immutable string?! In addition, with conformance it would be entirely possible to reverse assign a immutable string to a mutable string, rendering any immutable client interface ineffective at preventing external modification.&lt;br /&gt;
&lt;br /&gt;
The alternative to conformance would be to use an implicit conversion routines to convert the mutable string to an immutable one, on assignment or a pass through to a routine argument typed to an immutable string. Conversion, personally, seems the most correct route to follow.&lt;br /&gt;
&lt;br /&gt;
===Examples===&lt;br /&gt;
&lt;br /&gt;
For the purpose of illustration the following declarations will be used. &amp;lt;code&amp;gt;[eiffel, n]IMMUTABLE_STRING_8&amp;lt;/code&amp;gt; is being introduced as a place holder for a immutable variant of the current mutable &amp;lt;code&amp;gt;[eiffel, n]IMMUTABLE_STRING_8&amp;lt;/code&amp;gt; class.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;[eiffel]&lt;br /&gt;
ms1: STRING_8&lt;br /&gt;
ms2: STRING_8&lt;br /&gt;
is1: IMMUTABLE_STRING_8&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The first topic is to determine how manifest string constants comply with mutable strings. The following lists all syntax valid operations based on the ECMA specification. The assignments are made using the types manifest constant specification in section 8.29.6.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;[eiffel]&lt;br /&gt;
1. ms1 := &amp;quot;Hello World&amp;quot;&lt;br /&gt;
2. ms1 := {STRING_8} &amp;quot;Hello World&amp;quot;&lt;br /&gt;
3. ms1 := {IMMUTABLE_STRING_8} &amp;quot;Hello World&amp;quot;&lt;br /&gt;
4. ms1 := once &amp;quot;Hello World&amp;quot;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In case '''1''' the compiler should recognize the assignment and create a &amp;lt;code&amp;gt;[eiffel]STRING_8&amp;lt;/code&amp;gt; using the manifest string. No immutable string should be created. Case '''2''' is effectively the same as case '''1''', just more explicit. Case '''3''' introduces the immutable string. In this case the compiler should reject the call. Immutable strings cannot become mutable. If the conforming option for implement were to be chose then &amp;lt;code&amp;gt;[eiffel]ms1&amp;lt;/code&amp;gt; would be set to &amp;lt;code&amp;gt;[eiffel]Void&amp;lt;/code&amp;gt;. An immutable string has been created and it does not conform to &amp;lt;code&amp;gt;[eiffel]STRING_8&amp;lt;/code&amp;gt;. Finally case '''4''' leaves room for explanation. In a world of Eiffel immutable strings a once string should behave in the same manner as case '''3'''. Currently it behaves like cases '''1''' and '''2'''.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;[eiffel]&lt;br /&gt;
1. is1 := &amp;quot;Hello Immutable World&amp;quot;&lt;br /&gt;
2. is1 := {STRING_8} &amp;quot;Hello Immutable World&amp;quot;&lt;br /&gt;
3. is1 := {IMMUTABLE_STRING_8} &amp;quot;Hello Immutable World&amp;quot;&lt;br /&gt;
4. is1 := once &amp;quot;Hello Immutable World&amp;quot;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In case '''1''' the compiler should recognize the assignment and create a &amp;lt;code&amp;gt;[eiffel]IMMUTABLE_STRING_8&amp;lt;/code&amp;gt; using the manifest string. No mutable string should be created. Case '''2''' uses the mutable string. In this case the developer has explicitly requested that the manifest string be of an immutable type. The course of action is dictated by a choice between conformance or conversion. Case '''3''' is effectively the same as case '''1''', just more explicit. Finally case '''4''' leaves room for explanation. In a world of Eiffel immutable strings a once string should behave in the same manner as cases '''1''' and '''3'''. Currently there is no defined behavior for this.&lt;br /&gt;
&lt;br /&gt;
===Using Conversion===&lt;br /&gt;
As stated conversion seems to be the winner. In discussing this with others at Eiffel Software it seems the vote is unanimous that conversion is the best option after all things considered. The road to using conversion as a mean to interop between strings is not a clear one. There are problems that need to be overcome.&lt;br /&gt;
&lt;br /&gt;
====Fetching a Mutable String====&lt;br /&gt;
First and most rudimentary is the ability to fetch a mutable version of an immutable string. All that is needed is function to make the explicit conversion; &amp;lt;code&amp;gt;[eiffel, n]as_string_8&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;[eiffel, n]as_string_32&amp;lt;/code&amp;gt; functions will have to be added to the immutable string class or be defined in a more abstract version of the class.&lt;br /&gt;
&lt;br /&gt;
====Issues with ANY.is_equal====&lt;br /&gt;
With a non-conforming implementation of mutable and immutable strings &amp;lt;code&amp;gt;[eiffel, n]ANY.is_equal&amp;lt;/code&amp;gt; as defined in ECMA will be broken.&lt;br /&gt;
&lt;br /&gt;
ECMA's &amp;lt;code&amp;gt;[eiffel, n]is_equal&amp;lt;/code&amp;gt; loosens the binds when it comes to comparing objects for equality. &amp;lt;code&amp;gt;[eiffel, n]is_equal&amp;lt;/code&amp;gt;'s argument &amp;lt;code&amp;gt;[eiffel, n]other&amp;lt;/code&amp;gt; is now of type &amp;lt;code&amp;gt;[eiffel, n]ANY&amp;lt;/code&amp;gt; and not a CAT-call prone &amp;lt;code&amp;gt;[eiffel, n]like Current&amp;lt;/code&amp;gt; anchored type. It's not desirable to compare immutable string with only immutable string, and the same is true for mutable strings and mutable strings. Functionality must be provided to compare either or for equality and &amp;lt;code&amp;gt;[eiffel, n]True&amp;lt;/code&amp;gt; returned as a result when both strings contain the same chain of characters. To support this crucial scenario a common base for '''all''' string variants needs to be introduced. For the sake of clarity with names, this shall be referenced as &amp;lt;code&amp;gt;[eiffel, n]ABSTRACT_STRING&amp;lt;/code&amp;gt; (see A Common Ancestor). &amp;lt;code&amp;gt;[eiffel, n]ABSTRACT_STRING&amp;lt;/code&amp;gt; should convariantly redefine &amp;lt;code&amp;gt;[eiffel, n]ANY.is_equal&amp;lt;/code&amp;gt; so it's &amp;lt;code&amp;gt;[eiffel, n]other&amp;lt;/code&amp;gt; argument is of type &amp;lt;code&amp;gt;[eiffel, n]ABSTRACT_STRING&amp;lt;/code&amp;gt;. This way strings can be compared without any need for conversion with more concrete versions of &amp;lt;code&amp;gt;[eiffel, n]STRING_8&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;[eiffel, n]IMMUTABLE_STRING_8&amp;lt;/code&amp;gt;. More importantly, no risk of CAT-calls.&lt;br /&gt;
&lt;br /&gt;
The second and more dispelling problem is with the postconditions. &amp;lt;code&amp;gt;[eiffel, n]same_type&amp;lt;/code&amp;gt; will fail! It's possible for immutable and mutable strings to be declared as being equal, after all most of the time it's the content a program wants to compare and not the object reference. It is an argumentative point if two related but different objects can be equal, with accordance to the EMCA informative text.&lt;br /&gt;
&lt;br /&gt;
''&amp;quot;..default_is_equal is frozen, always returning the value of field-by-field identity comparison (for not-void other); any class may, on the other hand, redefine is_equal, in accordance with the pre- and postconditions, to reflect a more specific notion of equality.&amp;quot;''&lt;br /&gt;
&lt;br /&gt;
Should it really matter then that the objects being compared actually be of the same type, when the result of &amp;lt;code&amp;gt;[eiffel, n]is_equal&amp;lt;/code&amp;gt; yields &amp;lt;code&amp;gt;[eiffel, n]True&amp;lt;/code&amp;gt;? The post-conditions are too strong, forbidding two disparate from being compared in valid domain context.&lt;br /&gt;
&lt;br /&gt;
====Optimizations====&lt;br /&gt;
The mutable versions of the string class should convert to, and cache, an immutable variant of a string upon an initial request. Once the mutable string's content is modified the cached immutable string is to invalidated. The next request to convert the mutable string to an immutable variant would yield a new immutable string reference.&lt;br /&gt;
&lt;br /&gt;
====A Common Ancestor====&lt;br /&gt;
Just as &amp;lt;code&amp;gt;[eiffel, n]STRING_GENERAL&amp;lt;/code&amp;gt; is available now, a more abstract implementation is required to implement the features available for all string variants. That is; mutable, immutable and 8 and 32 bit versions of each. In the interest of backwards compatibility the use of &amp;lt;code&amp;gt;[eiffel, n]STRING_GENERAL&amp;lt;/code&amp;gt; is not a viable solution. A proposed &amp;lt;code&amp;gt;[eiffel, n]ABSTRACT_STRING&amp;lt;/code&amp;gt; will instead be put forth for the real general purpose string class.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;[eiffel, n]ABSTRACT_STRING&amp;lt;/code&amp;gt; should contain a number of the routines moved up &amp;lt;code&amp;gt;[eiffel, n]STRING_GENERAL&amp;lt;/code&amp;gt; and STRING_GENERAL&amp;lt;/code&amp;gt; will hence forth derived &amp;lt;code&amp;gt;[eiffel, n]ABSTRACT_STRING&amp;lt;/code&amp;gt;. The routines that will not be resident in &amp;lt;code&amp;gt;[eiffel, n]ABSTRACT_STRING&amp;lt;/code&amp;gt; will be anything pertaining to mutating the internal representation.&lt;br /&gt;
&lt;br /&gt;
==Is There a Need to STRING_8 and STRING_32==&lt;br /&gt;
Of course in outlining such a proposal you have to ask the relevance of augments/patching (it depends on your views) Eiffel with immutable strings. Should Eiffel just have immutable strings? It's been discussed that there should be mutable and immutable variants of &amp;lt;code&amp;gt;[eiffel, n]STRING&amp;lt;/code&amp;gt;. Deviating from this a moment and looking at the best possible scenario for implementing immutable strings - make mutable strings a thing of the past!&lt;br /&gt;
&lt;br /&gt;
So many other languages have chosen to use a immutable string as their fundamental string type. For optimization in creating new strings or piecing parts of strings together a string builder is used. Under .NET there is the immutable &amp;lt;code&amp;gt;[csharp, n]System.String&amp;lt;/code&amp;gt; and optimized builder &amp;lt;code&amp;gt;[csharp, n]System.Text.StringBuilder&amp;lt;/code&amp;gt;. In Java the exact same story; &amp;lt;code&amp;gt;[java, n]String&amp;lt;/code&amp;gt; is an immutable string and &amp;lt;code&amp;gt;[java, n]StringBuffer&amp;lt;/code&amp;gt; is used to optimally create immutable strings.&lt;br /&gt;
&lt;br /&gt;
Yes, choosing such a option would break existing code. But we have to respect that trying to patch rather than change, often causes more problems that breaking code. With code breaking changes there should always be assistants available to help user migrate.&lt;br /&gt;
&lt;br /&gt;
As simple first step is to change all &amp;lt;code&amp;gt;[eiffel, n]STRING_8&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;[eiffel, n]STRING_32&amp;lt;/code&amp;gt; into &amp;lt;code&amp;gt;[eiffel, n]STRING_BUILDER_8&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;[eiffel, n]STRING_BUILDER_32&amp;lt;/code&amp;gt;, or indeed a unified &amp;lt;code&amp;gt;[eiffel, n]STRING_BUILDER&amp;lt;/code&amp;gt; for manipulating any sized string. The breaking changes can be minimized and all future use of &amp;lt;code&amp;gt;[eiffel, n]STRING_8&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;[eiffel, n]STRING_32&amp;lt;/code&amp;gt; are known to be immutable.&lt;br /&gt;
&lt;br /&gt;
Should Eiffel follow suit and depreciate the existing implementation of &amp;lt;code&amp;gt;[eiffel, n]STRING_8&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;[eiffel, n]STRING_32&amp;lt;/code&amp;gt;, in order to favor immutable strings and string builder(s)?&lt;/div&gt;</summary>
		<author><name>Seilerm</name></author>	</entry>

	<entry>
		<id>https://dev.eiffel.com/index.php?title=Immutable_Strings&amp;diff=8160</id>
		<title>Immutable Strings</title>
		<link rel="alternate" type="text/html" href="https://dev.eiffel.com/index.php?title=Immutable_Strings&amp;diff=8160"/>
				<updated>2007-04-18T00:13:26Z</updated>
		
		<summary type="html">&lt;p&gt;Seilerm: /* Conformance or Conversion */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{warning|This article under development and is not ready for any form of review.}}&lt;br /&gt;
&lt;br /&gt;
Author: Paul Bates&lt;br /&gt;
&lt;br /&gt;
[[Category:EiffelBase]]&lt;br /&gt;
&lt;br /&gt;
==Introduction==&lt;br /&gt;
On the heals of a point raised on [http://www.eiffelroom.com/blog/colin_adams/read_only_strings eiffelroom] regarding read-only variants of an Eiffel &amp;lt;code&amp;gt;[eiffel, n]STRING&amp;lt;/code&amp;gt;, this page has come about to discuss the possible options for introducing such new types.&lt;br /&gt;
&lt;br /&gt;
The term read-only is not a fitting name so this page documents such string variants as being immutable with it's already implemented cousins &amp;lt;code&amp;gt;[eiffel, n]STRING_8&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;[eiffel, n]STRING_32&amp;lt;/code&amp;gt; coined mutable.&lt;br /&gt;
&lt;br /&gt;
==Rational==&lt;br /&gt;
There are a number of reason why Eiffel needs an immutable representation of a string, which no matter what should be able to be altered. Below explains the rationale for why immutable strings are required in a language, as for those reasons why they are there.&lt;br /&gt;
&lt;br /&gt;
===EMCA STRING_8 and STRING_32 Are Not Constants===&lt;br /&gt;
Section 8.29 of the Eiffel ECMA specification details the declaration and use of constants in Eiffel. In section 8.29 the three Eiffel string forms are detailed as being constants. To be pedantic about the matter I extracted a dictional reference for the the word ''constant''.&lt;br /&gt;
&lt;br /&gt;
 ''con·stant'' /ˈkɒnstənt/&lt;br /&gt;
 &lt;br /&gt;
   –adjective&lt;br /&gt;
     1. Not changing or varying; uniform; regular; invariable.&lt;br /&gt;
 &lt;br /&gt;
   –noun&lt;br /&gt;
     7. Something that does not or cannot change or vary.&lt;br /&gt;
&lt;br /&gt;
ECMA details the use of the three &amp;lt;code&amp;gt;[eiffel, n]STRING&amp;lt;/code&amp;gt; declaration variants as constants but in reality this is contracting to the definition, and misleading in true semantics. &amp;lt;code&amp;gt;[eiffel, n]STRING&amp;lt;/code&amp;gt;s are mutable, &amp;quot;constants&amp;quot; are not. As a simple case example, take the following code snippet.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;[eiffel, n]&lt;br /&gt;
full_path: STRING_8&lt;br /&gt;
  once&lt;br /&gt;
    Result := template_path&lt;br /&gt;
    Result.replace_sub_string_all (&amp;quot;$1&amp;quot;, root_path)&lt;br /&gt;
  ensure&lt;br /&gt;
    result_attached: Result /= Void&lt;br /&gt;
    not_result_is_empty: not Result.is_empty&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
template_path: STRING_8 = &amp;quot;$1\data\default.cfg&amp;quot;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The code demonstrates an all too common scenario. Once &amp;lt;code&amp;gt;[eiffel, n]full_path&amp;lt;/code&amp;gt; has been called the contents of template_path are modified. Any other use of &amp;lt;code&amp;gt;[eiffel, n]template_path&amp;lt;/code&amp;gt; will yield a &amp;quot;constant&amp;quot; value that differs from that declared. The EMCA specification indicates that declaration of &amp;lt;code&amp;gt;[eiffel, n]template_path&amp;lt;/code&amp;gt; pertains to the specification of a constant attribute (8.29.2 and 8.29.3.)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;[eiffel, n]full_path&amp;lt;/code&amp;gt;, with once function semantics, is never a constant but is evaluated on a single as-needed basis. full_path actually demonstrates yet another rationale for introducing immutable strings into Eiffel.&lt;br /&gt;
&lt;br /&gt;
===Immutable Interfaces===&lt;br /&gt;
&lt;br /&gt;
A second rationale is through good design of a class' exported interface. A good design will yield immutable exported members as not to seemingly violate such principles of object orientation. I note &amp;quot;seemly&amp;quot; violated because by technical reference such principles are not violated. The principle in reference is one that states - a class, and it's descendants, should be the only entities to modify a respective runtime instantiation internal state. No client should be permitted to perform such modifications - Technically STRING is a reference type so a qualified call, like append, made on a STRING object, is modifying the internal state of that STRING object. However STRING has special reverence that binds it with the likes of INTEGER, NATURAL and CHARACTER. It's an inbuilt rudimentary type that is seen to be &amp;quot;a value&amp;quot;. Almost all other reference types are just objects and runtime with no real discernible value.&lt;br /&gt;
&lt;br /&gt;
Current EiffelBase abstraction enabled authoring of immutable exported client interfaces, yet allow resident routines to manipulate the internals of an object's state.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;[eiffel, n]&lt;br /&gt;
feature -- Access&lt;br /&gt;
 &lt;br /&gt;
  selected_indexes: BILINEAR [NATURAL]&lt;br /&gt;
      -- Select item indexes&lt;br /&gt;
    do&lt;br /&gt;
      Result := internal_selected_indexes&lt;br /&gt;
    ensure&lt;br /&gt;
      result_attached: Result /= Void&lt;br /&gt;
    end&lt;br /&gt;
 &lt;br /&gt;
feature {NONE} -- Implementation&lt;br /&gt;
&lt;br /&gt;
  internal_selected_indexes: ARRAYED_LIST [NATURAL]&lt;br /&gt;
      -- Mutable version of `internal_selected_indexes'&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
selected_indexes permits clients to access a list of index positions but never allows any extending or removal of items from that structure. &amp;lt;code&amp;gt;[eiffel, n]internal_selected_indexes&amp;lt;/code&amp;gt; is used internally to add or extend items based on some peripheral interaction. If the author wanted client to modified the result of selected_indexes then additional routines can be implemented on a fully or partially exported part of the class' interface. Such routines as &amp;lt;code&amp;gt;[eiffel, n]set_selected_indexes&amp;lt;/code&amp;gt; could be implemented or &amp;lt;code&amp;gt;[eiffel, n]add_index&amp;lt;/code&amp;gt; and the conversely &amp;lt;code&amp;gt;[eiffel, n]remove_index&amp;lt;/code&amp;gt; could be implemented as a Delegate pattern implementation.&lt;br /&gt;
&lt;br /&gt;
As it stands today, with only mutable strings, it is not possible to author such classes. A class attribute, or a once function, is open for modification by an unruly client, where it be accidental through a missing clone of a &amp;lt;code&amp;gt;[eiffel, n]STRING&amp;lt;/code&amp;gt;, using twin, or through naivety. Either way, it's dangerous!&lt;br /&gt;
&lt;br /&gt;
==Suggestions to Implementation==&lt;br /&gt;
&lt;br /&gt;
There are a number of factors to consider before deciding on a implementation choice for immutable string. First and probably most importantly is compatibility. Compatibility raises concerns regarding the assignment of a mutable string to an immutable string, vice-versa and even back again.&lt;br /&gt;
&lt;br /&gt;
==Compatibility==&lt;br /&gt;
Before any indicate of how mutable and immutable strings interacte there's needs to be a brief rundown of the possible ways they can interact. There's two schools of thought; Conformance or Conversion.&lt;br /&gt;
&lt;br /&gt;
===Conformance or Conversion===&lt;br /&gt;
It has been mentioned that maybe an immutable string should conform to a mutable string, for optimization purposes. Respecting the possible choice for conformance it does not seem coherent that a mutable string is actually a specialize immutable string?! In addition, with conformance it would be entirely possible to to reverse assign a immutable string to a mutable string, rendering any immutable client interface ineffective at preventing external modification.&lt;br /&gt;
&lt;br /&gt;
The alternative to conformance would be to use an implicit conversion routines to convert the mutable string to an immutable one, on assignment or a pass through to a routine argument typed to an immutable string. Conversion, personally, seems the most correct route to follow.&lt;br /&gt;
&lt;br /&gt;
===Examples===&lt;br /&gt;
&lt;br /&gt;
For the purpose of illustration the following declarations will be used. &amp;lt;code&amp;gt;[eiffel, n]IMMUTABLE_STRING_8&amp;lt;/code&amp;gt; is being introduced as a place holder for a immutable variant of the current mutable &amp;lt;code&amp;gt;[eiffel, n]IMMUTABLE_STRING_8&amp;lt;/code&amp;gt; class.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;[eiffel]&lt;br /&gt;
ms1: STRING_8&lt;br /&gt;
ms2: STRING_8&lt;br /&gt;
is1: IMMUTABLE_STRING_8&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The first topic is to determine how manifest string constants comply with mutable strings. The following lists all syntax valid operations based on the ECMA specification. The assignments are made using the types manifest constant specification in section 8.29.6.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;[eiffel]&lt;br /&gt;
1. ms1 := &amp;quot;Hello World&amp;quot;&lt;br /&gt;
2. ms1 := {STRING_8} &amp;quot;Hello World&amp;quot;&lt;br /&gt;
3. ms1 := {IMMUTABLE_STRING_8} &amp;quot;Hello World&amp;quot;&lt;br /&gt;
4. ms1 := once &amp;quot;Hello World&amp;quot;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In case '''1''' the compiler should recognize the assignment and create a &amp;lt;code&amp;gt;[eiffel]STRING_8&amp;lt;/code&amp;gt; using the manifest string. No immutable string should be created. Case '''2''' is effectively the same as case '''1''', just more explicit. Case '''3''' introduces the immutable string. In this case the compiler should reject the call. Immutable strings cannot become mutable. If the conforming option for implement were to be chose then &amp;lt;code&amp;gt;[eiffel]ms1&amp;lt;/code&amp;gt; would be set to &amp;lt;code&amp;gt;[eiffel]Void&amp;lt;/code&amp;gt;. An immutable string has been created and it does not conform to &amp;lt;code&amp;gt;[eiffel]STRING_8&amp;lt;/code&amp;gt;. Finally case '''4''' leaves room for explanation. In a world of Eiffel immutable strings a once string should behave in the same manner as case '''3'''. Currently it behaves like cases '''1''' and '''2'''.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;[eiffel]&lt;br /&gt;
1. is1 := &amp;quot;Hello Immutable World&amp;quot;&lt;br /&gt;
2. is1 := {STRING_8} &amp;quot;Hello Immutable World&amp;quot;&lt;br /&gt;
3. is1 := {IMMUTABLE_STRING_8} &amp;quot;Hello Immutable World&amp;quot;&lt;br /&gt;
4. is1 := once &amp;quot;Hello Immutable World&amp;quot;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In case '''1''' the compiler should recognize the assignment and create a &amp;lt;code&amp;gt;[eiffel]IMMUTABLE_STRING_8&amp;lt;/code&amp;gt; using the manifest string. No mutable string should be created. Case '''2''' uses the mutable string. In this case the developer has explicitly requested that the manifest string be of an immutable type. The course of action is dictated by a choice between conformance or conversion. Case '''3''' is effectively the same as case '''1''', just more explicit. Finally case '''4''' leaves room for explanation. In a world of Eiffel immutable strings a once string should behave in the same manner as cases '''1''' and '''3'''. Currently there is no defined behavior for this.&lt;br /&gt;
&lt;br /&gt;
===Using Conversion===&lt;br /&gt;
As stated conversion seems to be the winner. In discussing this with others at Eiffel Software it seems the vote is unanimous that conversion is the best option after all things considered. The road to using conversion as a mean to interop between strings is not a clear one. There are problems that need to be overcome.&lt;br /&gt;
&lt;br /&gt;
====Fetching a Mutable String====&lt;br /&gt;
First and most rudimentary is the ability to fetch a mutable version of an immutable string. All that is needed is function to make the explicit conversion; &amp;lt;code&amp;gt;[eiffel, n]as_string_8&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;[eiffel, n]as_string_32&amp;lt;/code&amp;gt; functions will have to be added to the immutable string class or be defined in a more abstract version of the class.&lt;br /&gt;
&lt;br /&gt;
====Issues with ANY.is_equal====&lt;br /&gt;
With a non-conforming implementation of mutable and immutable strings &amp;lt;code&amp;gt;[eiffel, n]ANY.is_equal&amp;lt;/code&amp;gt; as defined in ECMA will be broken.&lt;br /&gt;
&lt;br /&gt;
ECMA's &amp;lt;code&amp;gt;[eiffel, n]is_equal&amp;lt;/code&amp;gt; loosens the binds when it comes to comparing objects for equality. &amp;lt;code&amp;gt;[eiffel, n]is_equal&amp;lt;/code&amp;gt;'s argument &amp;lt;code&amp;gt;[eiffel, n]other&amp;lt;/code&amp;gt; is now of type &amp;lt;code&amp;gt;[eiffel, n]ANY&amp;lt;/code&amp;gt; and not a CAT-call prone &amp;lt;code&amp;gt;[eiffel, n]like Current&amp;lt;/code&amp;gt; anchored type. It's not desirable to compare immutable string with only immutable string, and the same is true for mutable strings and mutable strings. Functionality must be provided to compare either or for equality and &amp;lt;code&amp;gt;[eiffel, n]True&amp;lt;/code&amp;gt; returned as a result when both strings contain the same chain of characters. To support this crucial scenario a common base for '''all''' string variants needs to be introduced. For the sake of clarity with names, this shall be referenced as &amp;lt;code&amp;gt;[eiffel, n]ABSTRACT_STRING&amp;lt;/code&amp;gt; (see A Common Ancestor). &amp;lt;code&amp;gt;[eiffel, n]ABSTRACT_STRING&amp;lt;/code&amp;gt; should convariantly redefine &amp;lt;code&amp;gt;[eiffel, n]ANY.is_equal&amp;lt;/code&amp;gt; so it's &amp;lt;code&amp;gt;[eiffel, n]other&amp;lt;/code&amp;gt; argument is of type &amp;lt;code&amp;gt;[eiffel, n]ABSTRACT_STRING&amp;lt;/code&amp;gt;. This way strings can be compared without any need for conversion with more concrete versions of &amp;lt;code&amp;gt;[eiffel, n]STRING_8&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;[eiffel, n]IMMUTABLE_STRING_8&amp;lt;/code&amp;gt;. More importantly, no risk of CAT-calls.&lt;br /&gt;
&lt;br /&gt;
The second and more dispelling problem is with the postconditions. &amp;lt;code&amp;gt;[eiffel, n]same_type&amp;lt;/code&amp;gt; will fail! It's possible for immutable and mutable strings to be declared as being equal, after all most of the time it's the content a program wants to compare and not the object reference. It is an argumentative point if two related but different objects can be equal, with accordance to the EMCA informative text.&lt;br /&gt;
&lt;br /&gt;
''&amp;quot;..default_is_equal is frozen, always returning the value of field-by-field identity comparison (for not-void other); any class may, on the other hand, redefine is_equal, in accordance with the pre- and postconditions, to reflect a more specific notion of equality.&amp;quot;''&lt;br /&gt;
&lt;br /&gt;
Should it really matter then that the objects being compared actually be of the same type, when the result of &amp;lt;code&amp;gt;[eiffel, n]is_equal&amp;lt;/code&amp;gt; yields &amp;lt;code&amp;gt;[eiffel, n]True&amp;lt;/code&amp;gt;? The post-conditions are too strong, forbidding two disparate from being compared in valid domain context.&lt;br /&gt;
&lt;br /&gt;
====Optimizations====&lt;br /&gt;
The mutable versions of the string class should convert to, and cache, an immutable variant of a string upon an initial request. Once the mutable string's content is modified the cached immutable string is to invalidated. The next request to convert the mutable string to an immutable variant would yield a new immutable string reference.&lt;br /&gt;
&lt;br /&gt;
====A Common Ancestor====&lt;br /&gt;
Just as &amp;lt;code&amp;gt;[eiffel, n]STRING_GENERAL&amp;lt;/code&amp;gt; is available now, a more abstract implementation is required to implement the features available for all string variants. That is; mutable, immutable and 8 and 32 bit versions of each. In the interest of backwards compatibility the use of &amp;lt;code&amp;gt;[eiffel, n]STRING_GENERAL&amp;lt;/code&amp;gt; is not a viable solution. A proposed &amp;lt;code&amp;gt;[eiffel, n]ABSTRACT_STRING&amp;lt;/code&amp;gt; will instead be put forth for the real general purpose string class.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;[eiffel, n]ABSTRACT_STRING&amp;lt;/code&amp;gt; should contain a number of the routines moved up &amp;lt;code&amp;gt;[eiffel, n]STRING_GENERAL&amp;lt;/code&amp;gt; and STRING_GENERAL&amp;lt;/code&amp;gt; will hence forth derived &amp;lt;code&amp;gt;[eiffel, n]ABSTRACT_STRING&amp;lt;/code&amp;gt;. The routines that will not be resident in &amp;lt;code&amp;gt;[eiffel, n]ABSTRACT_STRING&amp;lt;/code&amp;gt; will be anything pertaining to mutating the internal representation.&lt;br /&gt;
&lt;br /&gt;
==Is There a Need to STRING_8 and STRING_32==&lt;br /&gt;
Of course in outlining such a proposal you have to ask the relevance of augments/patching (it depends on your views) Eiffel with immutable strings. Should Eiffel just have immutable strings? It's been discussed that there should be mutable and immutable variants of &amp;lt;code&amp;gt;[eiffel, n]STRING&amp;lt;/code&amp;gt;. Deviating from this a moment and looking at the best possible scenario for implementing immutable strings - make mutable strings a thing of the past!&lt;br /&gt;
&lt;br /&gt;
So many other languages have chosen to use a immutable string as their fundamental string type. For optimization in creating new strings or piecing parts of strings together a string builder is used. Under .NET there is the immutable &amp;lt;code&amp;gt;[csharp, n]System.String&amp;lt;/code&amp;gt; and optimized builder &amp;lt;code&amp;gt;[csharp, n]System.Text.StringBuilder&amp;lt;/code&amp;gt;. In Java the exact same story; &amp;lt;code&amp;gt;[java, n]String&amp;lt;/code&amp;gt; is an immutable string and &amp;lt;code&amp;gt;[java, n]StringBuffer&amp;lt;/code&amp;gt; is used to optimally create immutable strings.&lt;br /&gt;
&lt;br /&gt;
Yes, choosing such a option would break existing code. But we have to respect that trying to patch rather than change, often causes more problems that breaking code. With code breaking changes there should always be assistants available to help user migrate.&lt;br /&gt;
&lt;br /&gt;
As simple first step is to change all &amp;lt;code&amp;gt;[eiffel, n]STRING_8&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;[eiffel, n]STRING_32&amp;lt;/code&amp;gt; into &amp;lt;code&amp;gt;[eiffel, n]STRING_BUILDER_8&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;[eiffel, n]STRING_BUILDER_32&amp;lt;/code&amp;gt;, or indeed a unified &amp;lt;code&amp;gt;[eiffel, n]STRING_BUILDER&amp;lt;/code&amp;gt; for manipulating any sized string. The breaking changes can be minimized and all future use of &amp;lt;code&amp;gt;[eiffel, n]STRING_8&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;[eiffel, n]STRING_32&amp;lt;/code&amp;gt; are known to be immutable.&lt;br /&gt;
&lt;br /&gt;
Should Eiffel follow suit and depreciate the existing implementation of &amp;lt;code&amp;gt;[eiffel, n]STRING_8&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;[eiffel, n]STRING_32&amp;lt;/code&amp;gt;, in order to favor immutable strings and string builder(s)?&lt;/div&gt;</summary>
		<author><name>Seilerm</name></author>	</entry>

	<entry>
		<id>https://dev.eiffel.com/index.php?title=EiffelStudio_6.0_Releases&amp;diff=8104</id>
		<title>EiffelStudio 6.0 Releases</title>
		<link rel="alternate" type="text/html" href="https://dev.eiffel.com/index.php?title=EiffelStudio_6.0_Releases&amp;diff=8104"/>
				<updated>2007-04-16T21:07:48Z</updated>
		
		<summary type="html">&lt;p&gt;Seilerm: /* 6.0.x */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Category:Releases]]__NOTOC__{{ReleaseHistoryHeader}}&lt;br /&gt;
&lt;br /&gt;
= EiffelStudio 6.0.x Releases=&lt;br /&gt;
&lt;br /&gt;
==6.0.x==&lt;br /&gt;
Placeholder for new stuff since last intermediate release.&lt;br /&gt;
===New features===&lt;br /&gt;
* estudio: {{Red|Replaced all native tool bars (EV_TOOL_BAR) with Smart Docking library tool bars (SD_TOOL_BAR).}}&lt;br /&gt;
&lt;br /&gt;
===Feature removed===&lt;br /&gt;
===Bug fixes===&lt;br /&gt;
* EiffelStore: Fixed bug#12478: SQL_SCAN is made generic to overcome a creation readiness problem. This is a breaking change and you might need to update your code.&lt;br /&gt;
* docking: Fixed bug#12389: &amp;quot;Reset tools layout&amp;quot; in debug mode does not do what I am expecting&lt;br /&gt;
===User changes===&lt;br /&gt;
===Developer changes===&lt;br /&gt;
&lt;br /&gt;
==6.0.6.7849 (April 15th 2007)==&lt;br /&gt;
===New features===&lt;br /&gt;
* compiler: The notion of creation readiness according to ECMA Eiffel standard (2nd edition, chapter 8.12.12) is implemented.&lt;br /&gt;
===Feature removed===&lt;br /&gt;
===Bug fixes===&lt;br /&gt;
* compiler: Fixed bug#12464: If a generic derivation in a deferred class uses `like Current' as generic parameter the creation constraints are not enforced on that particular formal.&lt;br /&gt;
* debugger: Completed implementation for dotnet system: bug#12435: Evaluating an expression still checks for invariant.&lt;br /&gt;
* debugger: Fixed bug#12435: Evaluating an expression still checks for invariant&lt;br /&gt;
* debugger: Now it is possible to disable/restore assertion checking during debugging in classic AND dotnet system.&lt;br /&gt;
* debugger: Fixed bug#12461: &amp;quot;Run Workbench&amp;quot; fails if no environment variable had been added.&lt;br /&gt;
* debugger: Fixed bug#12442: Selecting Debug/Exception handling for uncompiled project causes crash&lt;br /&gt;
* debugger: Fixed bug#12443: Run Workbench button in Debugging Options window does not work when app melted&lt;br /&gt;
* studio: Improved memory management.&lt;br /&gt;
&lt;br /&gt;
===User changes===&lt;br /&gt;
===Developer changes===&lt;br /&gt;
&lt;br /&gt;
==6.0.6.7775 (April 9th 2007)==&lt;br /&gt;
===New feature===&lt;br /&gt;
* vision2: ability to save an EV_PIXEL_BUFFER or to convert it to EV_PIXMAP.&lt;br /&gt;
* wel: {{Red|Added ability to convert image formats among all image formats on Windows (using WEL_GDIP_BITMAP).}}&lt;br /&gt;
&lt;br /&gt;
===Bug fixes===&lt;br /&gt;
* debugger: Fixed bug#12435: Evaluating an expression still checks for invariant (classic only)&lt;br /&gt;
* debugger: Fixed bug#12443: Run Workbench button in Debugging Options window does not work when app melted&lt;br /&gt;
* vision2: Fixed bug bug#12113: I'd like to be able to save an EV_PIXEL_BUFFER into a file&lt;br /&gt;
* estudio: Fixed bug bug#12437: Previous docking layout are not valid&lt;br /&gt;
&lt;br /&gt;
===Developer changes===&lt;br /&gt;
* Set .NET namespaces on all ISE libraries to be as terse and coherent as possible.&lt;br /&gt;
* .NET precompiled libraries binary names have been changed to fit present naming for .NET assemblies.&lt;br /&gt;
&lt;br /&gt;
==6.0.6.7670 (April 1st 2007)==&lt;br /&gt;
===New features===&lt;br /&gt;
* studio: {{Red|Added ability to add new classes/clusters/assemblies early on in the compilation phase instead of waiting for a successful compilation.}}&lt;br /&gt;
&lt;br /&gt;
===Bug fixes===&lt;br /&gt;
* dotnet: {{Red|Implemented suggestion from [[.NET_Namespace_Generation]].}}&lt;br /&gt;
* dotnet: Fixed bug#12433 where editing a class in EiffelStudio would change its generated namespace and thus invalidating the generated assembly (recompilation from scratch was necessary).&lt;br /&gt;
* Vision2: {{Red|Made sure that Windows and Unix behave the same way regarding widget navigation when one has set the ''default_key_processing_handler''. The behavior is that if it is set, then the tab processing will be disabled if it returns True.}}&lt;br /&gt;
*debugger: Fixed (again) bug#12371: Feature Relation window not scrolled to current line in debugger&lt;br /&gt;
*debugger: Implemented suggestion bug#12395 :No splitter by default&lt;br /&gt;
*debugger: Added start workbench and finalized system on Debugging option dialogs&lt;br /&gt;
*debugger: Fixed bug#11688: Compiling all classes under .NET with EXE generation hangs debugger&lt;br /&gt;
*estudio: Fixed bug#12203: Open Layout window disappears first time View/Open Layout is selected&lt;br /&gt;
*estudio: Fixed bug#12164: Large Fonts not respected in all widgets&lt;br /&gt;
*estudio: Fixed bug#12121: Wrong cursor if undock window operation in progress when compile ends&lt;br /&gt;
*estudio: Fixed bug#12036: Enter on a category in the Features tool does not focus the Editor&lt;br /&gt;
*estudio: Fixed bug#12104: Docked tracking preference ignored&lt;br /&gt;
*estudio: Fixed bug#12134: Auto Hide button should have different tooltips for enable/disable&lt;br /&gt;
*estudio: Fixed bug#12327: Closing Editor tab makes Clickable, Flat etc buttons insensitive&lt;br /&gt;
*docking: Fixed bug#12103: Estudio doesn't remember layout correctly if force debugger mode or maximize a tool&lt;br /&gt;
*docking: Fixed bug#12241: Hiding Address tool bar and reshowing it causes it to appear on Project tool bar row&lt;br /&gt;
*docking: Fixed bug#12260: Hiding toolbars leaves vacant space at bottom&lt;br /&gt;
*docking: Fixed bug#12114: Bringing up undocked window via View/Tools unmaximizes other too&lt;br /&gt;
&lt;br /&gt;
===User changes===&lt;br /&gt;
&lt;br /&gt;
===Developer changes===&lt;br /&gt;
*visioon2: Added new class EV_BEEP which can make system default beeps.&lt;br /&gt;
&lt;br /&gt;
==6.0.6.7522 (March 25th 2007)==&lt;br /&gt;
===New features===&lt;br /&gt;
* studio: Add assembly dialog assembly entires are now placed in columns. Added columns for the assembly path and processor architecture.&lt;br /&gt;
* studio: {{Red| Added support for multi constraint code completion.}}&lt;br /&gt;
&lt;br /&gt;
===Bug fixes===&lt;br /&gt;
* debugger: Fixed bug#11558 about evaluation of expressions involving NATURAL_XY values&lt;br /&gt;
* installer: (Windows) Fixed bitmap scaling issue for large fonts.&lt;br /&gt;
* Fixed the problem that Precursor {CLASS}.* only showed once routines.&lt;br /&gt;
* Fixed the problem that Result [i].* didn't work.&lt;br /&gt;
* Fixed the problem that Precursor {NEW_CLASS_3} [1].* didn't work.&lt;br /&gt;
* Fixed the problem that {INTEGER}.max_value.* didn't work.&lt;br /&gt;
* Fixed bug#12323 changing class name and then canceling Class Rename crashes estudio.&lt;br /&gt;
* Fixed bug#12331 Windows window showed two windows instead of one after exit and restart.&lt;br /&gt;
* Fixed bug#12347 that deleting a class displayed in an editor tab caused crash. &lt;br /&gt;
* Fixed a bug that initial dropping a cluster to diagram tool did nothing.&lt;br /&gt;
* Fixed bug#12299 that compiling lost diagram tool when targeted to a cluster.&lt;br /&gt;
* Fixed bug#12355 that selecting homonyms format for feature caused crash.&lt;br /&gt;
* Fixed the bug that shortcut for an initial or edited external command did not work.&lt;br /&gt;
* Fixed bug#11879 that show all docking indicators preference only respected when setting it.&lt;br /&gt;
* Fixed bug#12324 that main window resizes after loading project.&lt;br /&gt;
* Fixed bug#12118 that closing auto hidden tools during debugging leads to estudio crash.&lt;br /&gt;
* Fixed bug#12120 that particular docking layout causes crash in {SD_STATE_VOID}.move_to_docking_zone.&lt;br /&gt;
* Fixed bug#12339 that crash when rearranging editor tabs using mouse.&lt;br /&gt;
* Fixed bug#12235 that toolbar text blurs when exposed on linux.&lt;br /&gt;
* Fixed Eiffel Studio starting flicker problem, there is only 1 time flicker during the whole Eiffel Studio starting process now.&lt;br /&gt;
&lt;br /&gt;
==6.0.6.7358 (March 18th 2007)==&lt;br /&gt;
===New features===&lt;br /&gt;
* studio: Added configurable shortcuts for history back and forth.&lt;br /&gt;
* studio: Added ability to remember show/hide formatting marks status.&lt;br /&gt;
* studio: Made Eiffel Studio can open into debug mode directly.&lt;br /&gt;
* studio: Disable fading effects for Eiffel Studio splash screen and disabled auto hide animations on remote desktop.&lt;br /&gt;
* debugger: new object viewer tool. (to replace the pretty or expanded display dialog)&lt;br /&gt;
* compiler: {{Red|Added support for multiple constraints in formal generic parameters.}}&lt;br /&gt;
* docking: Made docking library title bar drawing text position care about font size.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Bug fixes===&lt;br /&gt;
* compiler: Fixed issue with incorrect labeled tuples which were not detected in signature of features (see eweasel test#tuple008).&lt;br /&gt;
* compiler: Fixed crash when checking an incorrect labeled tuple (e.g. TUPLE [a, a: INTEGER]) (see eweasel test#tuple009).&lt;br /&gt;
* studio: {{Red|Fixed bug#12083 where classes in override clusters would not get recompiled properly when automatically saved by EiffelStudio when requesting a compilation.}}&lt;br /&gt;
* studio: Fixed display of public key token on add assembly dialog.&lt;br /&gt;
* studio: Improved show/hide formatting marks command. This command only functioned on current editor and when current editor switched the name was not displayed correctly. Now it functions on all editors of current window.&lt;br /&gt;
* studio: Fixed bug#12256 that dependency tool could not close.&lt;br /&gt;
* studio: Fixed bug#12261 that find was broken, and added Home/End actions to the report grid.&lt;br /&gt;
* studio: Fixed bug#12264 that first column of preference grid was too narrow.&lt;br /&gt;
* studio: Fixed a bug that Alt+Left/Alt+Right didn't function on diagram tool and dependency tool.&lt;br /&gt;
* studio: Fixed a bug that address history forth command was always disabled in diagram tool.&lt;br /&gt;
* studio: Fixed bug#12258 that completion window was brought up by dot after a number. &lt;br /&gt;
* studio: Fixed the bug that shortcut for class completion triggered feature completion window in completable text fields (i.e. Watch tool, conditional breakpoint dialog).&lt;br /&gt;
* studio: Fixed bug#12037: Post condition violation at {EB_SMART_EDITOR}.refresh_line_number_display&lt;br /&gt;
* studio: Fixed bug#12013: View | Toolbars indicates wrong state for hidden toolbars&lt;br /&gt;
* studio: Fixed bug#12102: Search tool Options section cut off and mostly not visible&lt;br /&gt;
* pref: fixed bug#12183: Filter in preferences window is case-sensitive but should not be&lt;br /&gt;
* pref: fixed bug#12184 : Changing value of boolean preference when filter in effect causes crash&lt;br /&gt;
* debugger: Fixed bug#12195: Trying to save exception dialog when in Force Debugger mode causes crash&lt;br /&gt;
* debugger: Fixed bug#12194: Copying call stack to clipboard in Force Debugger mode causes crash&lt;br /&gt;
* debugger: Fixed bug#12265 : Ctrl+Alt+W used by the Debug - Show object viewer tool&lt;br /&gt;
* debugger: Fixed bug#12267: Multiple problems with Object Browser window (except for the width of the &amp;quot;Select Viewer&amp;quot; button, it seems a vision2 issue)&lt;br /&gt;
* debugger: Fixed bug#12283: Confirmation improvement and wrong preference category&lt;br /&gt;
* debugger: Fixed upper slice value for string display box.&lt;br /&gt;
* debugger: Fixed bug#12246: continue on cond breakpoint failure does not seem to work with Not Yet Called once&lt;br /&gt;
* debugger: Fixed bug#12170: Run to This Point doesn't stop unless hit count matches&lt;br /&gt;
* debugger: Fixed bug#12251: Saving exception message from debugger gives no error when permission problem&lt;br /&gt;
* debugger: Fixed suggestion bug#12230: Switch arguments and working directory in Debugging Options dialog&lt;br /&gt;
* debugger: Allow to save a file without the extension; fixed bug#12293: Estudio insists on adding &amp;quot;.txt&amp;quot; when save exception message from debugger&lt;br /&gt;
* debugger: Fixed issue with data associated with debugger grid line. A few internal data were not reseted when the expression's text was changed in the watch tool.&lt;br /&gt;
* debugger: Fixed bug#12257 : Watch expression that is constant real expression evaluates to 0&lt;br /&gt;
* vision2: Fixed bug#12210 where a pixmap will not be copied when assigned to a menu, and therefore you would get the same pixmap for all menu items instead of different ones.&lt;br /&gt;
* docking: Fixed bug#11870: Default layout for toolbar is not properly left aligned.&lt;br /&gt;
* docking: Fixed bug#11941: Dockable toolbars can have their handle placed so it cannot be accessed&lt;br /&gt;
* docking: Fixed bug#11944: Dragging tabs to re-order is not stable&lt;br /&gt;
* docking: Fixed bug#11829 CTRL+TAB selector item spacing/clipping&lt;br /&gt;
* docking: Fixed bug#11962: Postcondition violation in `make' of SD_NOTEBOOK_HIDE_TAB_DIALOG&lt;br /&gt;
* docking: Fixed bug#11970 Please add a tooltip to the Editor's class name tab&lt;br /&gt;
* docking: Fixed bug#11974: Address Toolbar customisations are lost&lt;br /&gt;
* docking: Fixed bug#12031: Another Internal Error on typing Ctrl+Tab&lt;br /&gt;
* docking: Fixed bug#12078: Internal Error halting debugger&lt;br /&gt;
* docking: Fixed bug#12090: Minor problems with resizing undocked windows&lt;br /&gt;
* docking: Fixed bug#12307: Window below editor doesn't return to original size after running application.(same as bug#12312)&lt;br /&gt;
* docking: Fixed bug#12091: Clicking &amp;quot;X&amp;quot; to close Editor tab often has no effect&lt;br /&gt;
* docking: Fixed bug#12117: Auto hiding tools then stepping to start debugger crashes estudio&lt;br /&gt;
* docking: Fixed Eiffel Studio on Linux hanging after just started undock a Window which is caused by a previous bug fixing.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Developer changes===&lt;br /&gt;
* configuration: Changed STRING_PROPERTY and STRING_CHOICE_PROPERTY to drop the generic parameter and use a value of STRING_32 all the time.&lt;br /&gt;
&lt;br /&gt;
==6.0.6.7183 (March 11th 2007)==&lt;br /&gt;
===New features===&lt;br /&gt;
* studio: {{Red| Added ability to configure shortcuts}}&lt;br /&gt;
* studio: {{Red|Auto-completion after bracketed expression. i.e. arr [i].*}}&lt;br /&gt;
* studio: Set editors’ description and details in Ctrl + Tab dialog.&lt;br /&gt;
* studio: When no class are edited, dropping a class or feature stone in the empty grey box of the editors will open a new editor related with the stone&lt;br /&gt;
* compiler: {{Red|Supported reattachment of generic derivations with expanded parameters to generic derivations with reference parameters on .NET.}}&lt;br /&gt;
* compiler: {{Red|Added option for full class checking. It can be enabled at the system, cluster or class level. However not all our code has been compiled with this option so don't be surprised if you get errors in our libraries.}} The next release should fix all the remaining issues.&lt;br /&gt;
* compiler: {{Red|Added [[Compilation Without Configuration]] for simple projects.}}&lt;br /&gt;
* docking: {{Red | Implemented lock toolbars and lock tools docking mechanism feature, and added related two new menu items under View menu.}}&lt;br /&gt;
* docking: Draw an extra floating title bar baseline to make it beautiful.&lt;br /&gt;
&lt;br /&gt;
===Bug fixes===&lt;br /&gt;
* studio: Fixed a bug that Ctrl + f4 didn't close debugger tools (call stack, object, watch and thread)&lt;br /&gt;
* studio: Fixed bug#12216 that %B from editing text was taken as an instruction.&lt;br /&gt;
* studio: Fixed bug#12208 of search report display issue. Improved its mouse/keyboard behaviors and interface a little bit.&lt;br /&gt;
* studio: Fixed bug#12202 that linked tools did not update when auto hiding.&lt;br /&gt;
* studio: Fixed bug#12185: Crash with old docking layout files&lt;br /&gt;
* studio: Fixed bug#12212: Refactoring menu is missing&lt;br /&gt;
* docking: Fixed bug#12164: Large Fonts not respected in all widgets&lt;br /&gt;
* docking: Fixed bug#12158: Text labels disappear on panes docked to the side&lt;br /&gt;
* docking: Fixed bug#12197: issue with maximized editor&lt;br /&gt;
* docking: Fixed bug#12189: Undocked window comes back very small when shown again.&lt;br /&gt;
* docking: Fixed bug#12228: Breakpoints window toolbar truncated&lt;br /&gt;
* docking: Fixed bug#12225: Windows key messes docking indicators.&lt;br /&gt;
* docking: Made double click to maximize feature works fine on Linux.&lt;br /&gt;
&lt;br /&gt;
==6.0.6.7079 (March 5th 2007)==&lt;br /&gt;
===Bug fixes===&lt;br /&gt;
* studio: Fixed issues with the way we launched '''finish_freezing.exe''' on Windows, we were not protecting the path to the executable against white spaces.&lt;br /&gt;
* debugger: Fixed issue which would prevent debugging if ISE_EIFFEL has spaces in it.&lt;br /&gt;
* install: Fixed incorrect shortcuts on Windows.&lt;br /&gt;
&lt;br /&gt;
==6.0.6.7057 (March 3rd 2007)==&lt;br /&gt;
===New features===&lt;br /&gt;
* compiler: we are now using FreeELKS as a replacement for EiffelBase&lt;br /&gt;
* estudio: Made Window Eiffel Studio splash screen beautiful.&lt;br /&gt;
&lt;br /&gt;
===Bug fixes===&lt;br /&gt;
* install: (Windows) fixed fatal error bug#12146 when attempting to browse for a folder.&lt;br /&gt;
* install: (Windows) fixed radio button background color different as best possible given the limitations of MSI.&lt;br /&gt;
* install: (Windows) pressing Back on the installed when on the Precompilation Choice page goes to the correct parent page instead of the Configure C/C++ Compiler page.&lt;br /&gt;
* compiler: Fix bug in .NET resx =&amp;gt; resource generation by the compiler when using resx files with relative paths.&lt;br /&gt;
* compiler: Adapted the compiler so that ISE_EIFFEL does not need to be defined with a short path name on Windows, since some file systems can disable support for short path &lt;br /&gt;
names.&lt;br /&gt;
* studio: various bug fixes with the docking.&lt;br /&gt;
* vision2: Fixed issue where hiding a widget in an EV_FIXED and changing its position would not be reflected when showing the widget later.&lt;br /&gt;
* base: {{Red| Fixed issue with LINKED_QUEUE.twin which would violate its invariant.}}&lt;br /&gt;
* base: {{Red| Revisited contracts of LINEAR_ITERATOR.}}&lt;br /&gt;
* docking: bug#11981: Cannot put window from another application in front of undocked window&lt;br /&gt;
* estudio: bug#12076: Refresh issue on Start/Continue button&lt;br /&gt;
* docking: bug#12096: Sliding panel tools cause an unsightly redraw when revealed when on the right side on gtk&lt;br /&gt;
* docking: bug#12098: Disable text in docking toolbar on linux doesn't look disabled&lt;br /&gt;
* docking: bug#12099: Particular docking layout crashes estudio on exit&lt;br /&gt;
* docking: bug#12111: Toolbars disappear after running debugger&lt;br /&gt;
* docking: bug#12067: Estudio crash in {SD_TAB_STATE}.make called from move_to_zone_internal&lt;br /&gt;
* docking: bug#12126: Maximizing tool then closing it closes other tools and makes them unavailable&lt;br /&gt;
* docking: bug#12132: Estudio doesn't restore normal/debug layouts within same session&lt;br /&gt;
* docking: bug#12138: Sequence of saving, opening and resetting tools layout causes crash&lt;br /&gt;
* docking: bug#11984: Text on many buttons in estudio main window cut off at bottom&lt;br /&gt;
* vision2: bug#11989: Unintuitive behavior when trying to move an undocked window&lt;br /&gt;
* vision2: bug#12071: Auto Hide of window before pick ends hangs estudio, then F7 crashes it&lt;br /&gt;
* vision2: bug#12143: Window titles in title bar not visible when window has focus&lt;br /&gt;
&lt;br /&gt;
===User changes===&lt;br /&gt;
* install: (Windows) removed information, on the welcome page, about setting up a C/C++ compiler if a compiler is detected.&lt;br /&gt;
* estudio: Improved background color of Linux editor place holder zone.&lt;br /&gt;
&lt;br /&gt;
===Developer changes===&lt;br /&gt;
* docking: Added proprogate accelerator in SD_DOCKING_MANAGER.&lt;br /&gt;
* docking: Added SD_CONTENT.update_mini_tool_bar_size.&lt;br /&gt;
&lt;br /&gt;
==6.0.6.6895 (February 25th 2007)==&lt;br /&gt;
===New features===&lt;br /&gt;
* Added the feature requested at bug#12046 that Ctrl+F3 searches current word if no text is selected.&lt;br /&gt;
* Internationalized choices in interface.development_window.ctrl_right_click_receiver and tools.search_tool.init_scope.&lt;br /&gt;
* debugger: Added &amp;quot;rescue&amp;quot; indicator in call stack tool's grid.&lt;br /&gt;
* debugger: {{Red|Added the possibility to evaluate an instruction with the debugger (i.e: procedure call).}}&lt;br /&gt;
* compiler: {{Red|Support for FreeELKS as a replacement for EiffelBase}}.&lt;br /&gt;
* studio: Now we can exit directly from debugging mode, no changing to normal mode needed.&lt;br /&gt;
* docking: SD_TOOL_BAR_CONTENT has new feature &amp;quot;unique_title&amp;quot; for store data, and using feature &amp;quot;title&amp;quot; for display.&lt;br /&gt;
* install: (Windows) Installer detects and configures a resident VC/VC++ compiler and provides/hides options based on what it found.&lt;br /&gt;
* install: (Windows) Precompilation is disabled if a VC/VC++ could not be configured to prevent creation of bad precompiled libraries.&lt;br /&gt;
* install: (Windows) x64 version no longer displays the option for installing the Borland C compiler because it's for x86 compilations only.&lt;br /&gt;
* install: (Windows) In the event of no C/C++ compiler found help is now link-provided to obtain a the free Windows SDK.&lt;br /&gt;
* install: (Windows) new installers with compact look and feel and better auto-configuration.&lt;br /&gt;
&lt;br /&gt;
===Bug fixes===&lt;br /&gt;
* studio: Fixed bug#5437 that Shift+End selects too much text.&lt;br /&gt;
* studio: Fixed the bug that menu commands like Cut, Copy, Paste and Select All and sub commands of &amp;quot;Search&amp;quot; didn't work consistently as their shortcuts did. i.e. &amp;quot;Select All&amp;quot; always selected texts in main editor, but Ctrl+A did correct thing that was select all texts in the editor where focus was.&lt;br /&gt;
* studio: Fixed a bug that when dropping a stone to the editor, confirmation on saving a read only class didn't prevent the stone from loading, which means that the modified class got lost in this case.&lt;br /&gt;
* studio: Fixed bug#12050 that EiffelStudio crashed when trying to save a file that you didn't have write access to. Open a Save As dialog if .swp file is not creatable.&lt;br /&gt;
* studio: Fixed bug#12053 that Toggle Line Numbers and Go to didn't show correct sensitivity.&lt;br /&gt;
* studio: Fixed bug#12029 that es crashed when reopening ES with general.locale changed from English to Chinese.&lt;br /&gt;
* studio: Fixed bug#12061 that synchronization button not showing the proper tool. Now we try to synchronize the feature displayed in the combo box. (We only synchronized the stone.)&lt;br /&gt;
* studio: Fixed a crash when updating viewpoints. &lt;br /&gt;
* studio: Fixed bug#12068 and bug#12069, crashes when there was no editor.&lt;br /&gt;
* debugger: fixed issue with native_array unable to be resized with slices tool. (dotnet debugger)&lt;br /&gt;
* compiler: Fixed bug#11936 where namespace names included the cluster name when a cluster defined a namespace.&lt;br /&gt;
* studio: Fixed bug#11987 that Closing Class tab crashes estudio after move to Clusters&lt;br /&gt;
* studio: Fixed bug#12054 that Crash when select Editor window after exiting debugger&lt;br /&gt;
* studio: Fixed bug#12000 that Particular docking layout causes estudio to crash at startup&lt;br /&gt;
* studio: Fixed bug#11998 that Wrong tooltips on many Project tool bar buttons - say Show/Hide&lt;br /&gt;
* studio: Fixed bug#11873 Breakpoint tool content not refreshed when switching to debug mode&lt;br /&gt;
* docking: Fixed bug#11960 Alignment issues&lt;br /&gt;
* studio: Set docking window title bar height, tool bar height a little bit bigger for Linux specially.&lt;br /&gt;
* docking: Make hide tab indicator correct and tool bar drawing style correct for Linux implementation.&lt;br /&gt;
* studio: Fixed bug that hidden tab dialog position not correct on Linux.&lt;br /&gt;
* studio: Fixed bug that minimum height of docking (not tabbed) editor not correct on Linux.&lt;br /&gt;
* docking: Fixed bug that select a tab from hidden item drop down menu, SD_CONTENT.focus_in_actions not been called.&lt;br /&gt;
* docking: Fixed bug that close button of editor tab position not correct if not enough space.&lt;br /&gt;
* docking: Fixed bug that close button of editor tab state not updated correctly sometimes.&lt;br /&gt;
&lt;br /&gt;
===User changes===&lt;br /&gt;
* debugger: the call stack tool now display a special icon when on feature with rescue cause.&lt;br /&gt;
* studio: Changed shortcut for Cluster tool to Ctrl+Alt+U.&lt;br /&gt;
* studio: Fixed bug#11998: Wrong tooltips on many Project tool bar buttons - say Show/Hide&lt;br /&gt;
* studio: Fixed bug#12048: Please improve the Debug | Tools menu&lt;br /&gt;
===Developer changes===&lt;br /&gt;
* studio: Improved the way of saving context session data. We save ids of the feature/class targeted in tools.&lt;br /&gt;
&lt;br /&gt;
==6.0.6.6595 (February 11th 2007)==&lt;br /&gt;
===New features===&lt;br /&gt;
* compiler: (windows) finish_freezing.exe now looks for the installed Windows SDK recently released from Microsoft. If installed, there is no need to perform any manual C-compiler configuration.&lt;br /&gt;
* studio: Dependency tool tab receives stones.&lt;br /&gt;
* build: {{Red|Code generation will includes the facility of closing the application when last window is closed.}}&lt;br /&gt;
&lt;br /&gt;
===Bug fixes===&lt;br /&gt;
* studio: Fixed bug#12016 where EiffelStudio would crash when trying to debug an application after cancelling a finalization.&lt;br /&gt;
* debugger: fixed &amp;quot;restart&amp;quot; feature which was broken in last release.&lt;br /&gt;
* debugger: fixed &amp;quot;DEBUG_OUTPUT&amp;quot; processing in debugger for dotnet system.&lt;br /&gt;
* debugger: fixed issue with &amp;quot;do not close ecdbgd&amp;quot; when the user decides to reuse the same &amp;quot;ecdbgd&amp;quot; process, be sure to reuse it.&lt;br /&gt;
* debugger: fixed bug#11928 and more general issue with exception on framework .NET 3&lt;br /&gt;
* studio: Fixed bug#11969 that diagram tool did not link to the editor (Neither dependency tool).&lt;br /&gt;
* studio: Fixed bug#12003 that Pick and drop of a parent class in the feature tool targeted to class view instead of showing ancestor.&lt;br /&gt;
* studio: Fixed bug#12018 that changing shortcut preference of external commands crashed es.&lt;br /&gt;
* studio: Improved history behaviors mostly according to [[History behavior]] except the preference.&lt;br /&gt;
* studio: Fixed a crash that opening ES with a group opened last time closing.&lt;br /&gt;
* studio: Fixed the bug#11959 that after refactoring a class with file name changed was not correctly reloaded.&lt;br /&gt;
* studio: Fixed bug#12002: Boolean Preferences cannot be edited via the keyboard&lt;br /&gt;
* studio: Fixed bug#12006: Shortcut Preferences cannot be edited via the keyboard&lt;br /&gt;
* studio: Fixed bug#11827: Extra padding on right for &amp;quot;Customize&amp;quot; toolbar menu&lt;br /&gt;
* studio: Fixed bug#12005: Moving tabs around issue with metric&lt;br /&gt;
* studio: Fixed bug#11814: Persistent redraw issue&lt;br /&gt;
* studio: Fixed the bug that first time tool bar floating, the width is not correct.&lt;br /&gt;
* studio: Fixed bug that favorite tool only can show in normal mode or debug mode.&lt;br /&gt;
* build: Fixed crash when generating code which included a combo box in read-only mode.&lt;br /&gt;
&lt;br /&gt;
===User changes===&lt;br /&gt;
* studio: Changed shortcut of showing Diagram tool to Ctrl+Alt+I.&lt;br /&gt;
* debugger: add possibility to continue on conditional breakpoint evaluation failure&lt;br /&gt;
* debugger: Get rid of useless &amp;quot;Attributes&amp;quot; row in debugger's objects grids (This makes display less lighter).&lt;br /&gt;
* debugger: now the &amp;quot;Once routines&amp;quot; also show states of &amp;quot;once procedures&amp;quot; and not only &amp;quot;once functions&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
===Developer changes===&lt;br /&gt;
* studio: Now we store in session data class/group IDs from EB_SHARED_ID_SOLUTION instead of class 'file_name's or group names which could cause a problem that moving a project lead to class missing and a problem wrong group returned (many groups with the same name).&lt;br /&gt;
* studio: Made fake editors for clusters if hidden when opening.&lt;br /&gt;
&lt;br /&gt;
==6.0.6.6451 (February 4th 2007)==&lt;br /&gt;
===New features===&lt;br /&gt;
* debugger: now it is possible to force the environment to stay in debugger mode.&lt;br /&gt;
===Bug fixes===&lt;br /&gt;
* runtime: {{Red|Fixed a memory corruption which could occur when performing a deep_twin on an object whose graph contains a TUPLE object. See test#tuple006.}}&lt;br /&gt;
* runtime: {{Red|Fixed issue when retrieving 64-bit storables on 32-bit machines. It requires a regeneration of the 64-bit storables if one wants to retrieve them on 32-bit machines. Fixed bug#11744.}}&lt;br /&gt;
* studio: Fixed bug#11848 and bug#11939 related to the `Debugging Options' dialog which could randomly crash (related to test#tuple006 issue).&lt;br /&gt;
* studio: Fixed `on_text_fully_loaded' crash (bug#11943, bug#11938 and bug#11937).&lt;br /&gt;
* EiffelStore: Fixed ODBC on Linux.&lt;br /&gt;
* debugger: SPECIAL[SPECIAL[..]] is fully supported now by the debugger.&lt;br /&gt;
* studio: Fixed bug#11761, bug#11865 and bug#11866, general.locale didn't initialize properly. &amp;quot;Unselected&amp;quot; entry was added.&lt;br /&gt;
* studio: Corrected current output codepage/charset for command line ES.&lt;br /&gt;
&lt;br /&gt;
==6.0.6.6309 (January 27th 2007)==&lt;br /&gt;
===New features===&lt;br /&gt;
* studio: Finished internationalizing starting dialog, wizards.&lt;br /&gt;
* studio: {{red|Integrated Smart Docking library.}}&lt;br /&gt;
* studio: {{red|Integrated tab editor mechanism.}}&lt;br /&gt;
* studio: Added preference &amp;quot;Maximum processor usage&amp;quot; to dictate the maximum number of processors/cores to use when compile c-code.&lt;br /&gt;
* EiffelWizard: Introduced i18n library to make it possible to display in different languages.&lt;br /&gt;
* compiler: .NET Enums are can be automatically converted to INTEGERs&lt;br /&gt;
* compiler: indexing tags ''interface_metadata'' and ''class_metadata'' are supported on feature level like this is done on class level and allow to specify custom attributes for associated methods only in interface type or only in implementation type.&lt;br /&gt;
* compiler: Static access on external routines is allowed even if not marked frozen (this simply applies a relaxed rule that was adopted by ECMA).&lt;br /&gt;
* debugger: dropping feature or class stones on breakpoints tool to add related breakpoint&lt;br /&gt;
* debugger: enhanced breakpoint mechanism by adding print message, hit count (condition), and provide &amp;quot;Is True&amp;quot; and &amp;quot;Has Changed&amp;quot; condition.&lt;br /&gt;
* studio: Integrated encoding library and internationalized part of batch compiler.&lt;br /&gt;
* base: Added facilities to read/write REAL_32 and REAL_64 values in big and little endian format in MANAGED_POINTER&lt;br /&gt;
* net: {{red|Updated reading routines of EiffelNet so that for all basic types they would read all the required bytes, not just stop after the first reading. This is important as in some very bad network situation or if you have some signals you could mess up the reading by only reading half of the expected bytes.}}&lt;br /&gt;
&lt;br /&gt;
===Bug fixes===&lt;br /&gt;
* studio: Fixed bug#11760 that replacing on empty result crashed es.&lt;br /&gt;
* studio: Auto-complete members for open target agents have been corrected. bug#11767.&lt;br /&gt;
* studio: Fixed bug#11772 that a crash occurred while renaming clusters in property tool.&lt;br /&gt;
* compiler: Fixed bug causing test#dotnet046 to fail, now functions that are .NET properties can be called and executed from client code.&lt;br /&gt;
&lt;br /&gt;
===User changes===&lt;br /&gt;
* studio: Added new docking feedback indicators.&lt;br /&gt;
* compiler: added conversion of TYPED_POINTER to POINTER before reattachment to reference entity so that the behaviour is the same in classic and .NET modes&lt;br /&gt;
* compiler: All versioned COM import interfaces now have versioned interface member names based on the trailing version number of the interface name, as this meta information is not available in any other way. This greatly improves the versioned names and makes implementing interfaces much easier.&lt;br /&gt;
* compiler: The unique keyword will yield a syntax warning if enabled.&lt;br /&gt;
* debugger: improved cosmetic of debugger's exception handling dialog&lt;br /&gt;
* base: Changed INTERNAL so that it does not have the `is_pre_ecma_mapping_disabled' attribute. If you were setting it to True, you should instead create an instance of ECMA_INTERNAL (fixes bug#11792).&lt;br /&gt;
&lt;br /&gt;
===Developer changes===&lt;br /&gt;
*debugger: refactored breakpoints and exceptions processing for easier integration of other projects on debugger.&lt;br /&gt;
*compiler: updated compiler to compile FreeELKS library, however it cannot yet be executed.&lt;br /&gt;
&lt;br /&gt;
==6.0.65740 (December 25th 2006)==&lt;br /&gt;
===New features===&lt;br /&gt;
* debugger: console based debugger is now working for classic, dotnet, on windows and unices (-debug or via -loop : still experimental)&lt;br /&gt;
&lt;br /&gt;
===Feature removed===&lt;br /&gt;
===Bug fixes===&lt;br /&gt;
* compiler: fixed a bug in .NET consumer that can cause some assemblies to be consume infinitely.&lt;br /&gt;
* compiler: fixed a .NET bug that prevents System.Windows.Forms.Panel from being compiled correct and subsequently causing a compilation to fail, due to incorrect an mapped inherit property and assigner. This addresses test#dotnet043.&lt;br /&gt;
* compiler: Fixed bug#11758 for eweasel test#incr279, where the compiler would crash when generating the call to '''Precursor''' when both the current class and the parent class had their number of formal generics changed.&lt;br /&gt;
* compiler: Fixed bug#11766 for eweasel test#term146 and test#incr129 where the compiler would crash at degree 4 when checking the conformance of a feature, and the signature involves a type which have an incorrect parent hierarchy (i.e. one parent does not have the right number of actual generic parameters).&lt;br /&gt;
* store: {{Red| Fixed bug#10523: if you create a DB_REPOSITORY before being connected to the database, some of the queries made on the database are not returning the proper result in ODBC(e.g. odbc_sensitive_mixed will return 0 instead of 3 for an ORACLE database). By adding the precondition we nicely solve the problem by forcing client to connect first before creating an instance of DB_REPOSITORY.}}&lt;br /&gt;
* store: {{Red| Fixed some issues related to the new implementation of expanded semantics which would break some introspection part of EiffelStore.}}&lt;br /&gt;
* favorites: fixed bug#11745 &amp;quot;feature item&amp;quot; favorites were being lost on restarting EiffelStudio&lt;br /&gt;
* gui: fixed bug#11749 with debugger's grid being empty.&lt;br /&gt;
* debugger: fixed bug#11755: empty string with huge capacity were slow to be displayed.&lt;br /&gt;
* debugger: improved display of objects tool header bar. (minor)&lt;br /&gt;
&lt;br /&gt;
===User changes===&lt;br /&gt;
* base: sped up {SPECIAL}.copy_data which was not inlined.&lt;br /&gt;
&lt;br /&gt;
===Developer changes===&lt;br /&gt;
&lt;br /&gt;
==6.0.65604 (December 17th 2006)==&lt;br /&gt;
===New features===&lt;br /&gt;
* compiler: improved backup mechanism so that overridden classes are copied in the library where they are defined (they were previously copied in the library where the override cluster was defined).&lt;br /&gt;
* studio: {{red|Integrated the internationalization library. Added a preference named &amp;quot;general.locale&amp;quot; to switch among languages. English and Chinese are available for the moment}}&lt;br /&gt;
* debugger: added auto expressions on watch tools&lt;br /&gt;
* studio: Added metric history support. Calculated metrics with their inputs can be sent into history so they can be recalculated afterwards.&lt;br /&gt;
* general: Revision number of EiffelStudio has changed because we reached the limit set by most OS for the revision (65535). So now it is split into revision.build, that is to say rev 65570 will read 6.5570.&lt;br /&gt;
* debugger: added an experimental console based debugger.&lt;br /&gt;
&lt;br /&gt;
===Bug fixes===&lt;br /&gt;
* compiler: {{Red|Fixed issue with inline agents where if you have one and during a compilation from scratch you have a compiler error, then fixing this error and recompiling, it would crash when melting or freezing (test#incr277).}}&lt;br /&gt;
* compiler: Fixed issue with C compilation linking error when a generic class which have an invariant clause has its formal generics changed (test#incr278).&lt;br /&gt;
* compiler: Fixed C compilation error on Windows for trying to compile empties Cxxx directories (test#ccomp061).&lt;br /&gt;
* compiler: Fixed incorrect code generation of agents on attribute when target is open (test#exec264).&lt;br /&gt;
* compiler: Fixed incremental bug when an agent creation based on a feature whose signature changes for less arguments (test#incr276).&lt;br /&gt;
* compiler: Fixed a backup creation bug when two classes from the same cluster/library have the same original file name, the backup would only contain one or the other because we use the original file name. Now we use the original class name.&lt;br /&gt;
&lt;br /&gt;
===User changes===&lt;br /&gt;
* base: Sped up HASH_TABLE iteration and lookup by about 8% or more.&lt;br /&gt;
* base: TUPLE can now compare items using reference equality (=) or object comparison (is_equal).&lt;br /&gt;
* vision2: Changed behavior of {EV_TITLED_WINDOW}.raise to always make sure the window is visible on screen (show if hidden, restore if minimized).&lt;br /&gt;
* vision2: Fixed behavior of is_show_requested and is_displayed for EV_GRID and its items so that it conforms to the widget behavior in Vision2.&lt;br /&gt;
* wel/vision2: {{Red|Raised compatibility bar to Windows 2000 or greater. No more support for Windows 98 or NT 4.0}}&lt;br /&gt;
* dotnet: {{Red|Renamed SYSTEM_ATTRIBUTE into NATIVE_ATTRIBUTE for consistency reasons.}}&lt;br /&gt;
&lt;br /&gt;
===Developer changes===&lt;br /&gt;
* debugger: deep refactoring (reduce the number of onces, renamed and moved some debugger related data)&lt;br /&gt;
* studio: to help track incremental compilation bugs, we build a replay backup window that given a backup directory will go through each compilation and perform them the way it was done by the end user.&lt;br /&gt;
&lt;br /&gt;
==6.0.65344 (December 3rd 2006)==&lt;br /&gt;
===New features===&lt;br /&gt;
* compiler: {{Red|A root type can now be a generic derivation.}}&lt;br /&gt;
* studio: {{Red|Project settings such as arguments/working directory/location are now stored in a user specific location that does not depend on the UUID of the project, but on its path.}}&lt;br /&gt;
* compiler: {{Red|Integers can now also be specified with binary and octal representation}}&lt;br /&gt;
* compiler: {{Red|Manifest characters can now also be specified with binary, octal and hexadecimal representation. Manifest characters can be specified up to 32 Bit.}}&lt;br /&gt;
* compiler: {{Red|Possibility for &amp;quot;hidden/implementation&amp;quot; clusters in libraries, clusters that are not accessible if the library is used (like libraries in libraries are not accessible).}}&lt;br /&gt;
* compiler: {{Red|Added supplier_precondition assertion level that enables to only check preconditions of trusted libraries.}}&lt;br /&gt;
* debugger: {{Red|New Debugging options dialog (to set the arguments and other)}}&lt;br /&gt;
* compiler: Don't do an expensive degree 6 when we freeze or finalize.&lt;br /&gt;
* compiler: Newly added clusters are recursive by default.&lt;br /&gt;
* studio: Favorites are now stored in the user settings.&lt;br /&gt;
* compiler: Warning if an environment variable has changed and opportunity to (temporarily) use the old, stored value&lt;br /&gt;
* compiler: Trigger a full configuration rebuild if environment variables have changed&lt;br /&gt;
* compiler: Added configurable (project to class-level) optimization for .NET project that will mark all classes frozen if they are not descended by another.&lt;br /&gt;
* studio: Add assemblies dialog shows more assembly information.&lt;br /&gt;
* studio: Some diagram generation for assemblies&lt;br /&gt;
* studio:Display documentation for .NET Framework assemblies on .NET 2.0&lt;br /&gt;
* studio: Display features tree for .NET classes.&lt;br /&gt;
* studio: Display uncompiled .NET classes.&lt;br /&gt;
* debugger: Now we can pass modified environment variables to the debuggee application.&lt;br /&gt;
* compiler: Externals (includes, objects, resources, ...) can now be relative to the ecf file by using the new replacement $ECF_CONFIG_PATH.&lt;br /&gt;
* compiler: UUID is not needed for non library systems. If no uuid is specified a random one will be generated. (Startup dialog may not work correct if the config has not been saved with the random generated uuid)&lt;br /&gt;
* debugger: New contextual menu on breakpoints tool for multiple action on class (enable first bp on all features ...)&lt;br /&gt;
* studio: Only expand the currently used target in the project settings.&lt;br /&gt;
* compiler: Changed version of configuration format to 1.1.0&lt;br /&gt;
* compiler: Only print warnings for unknown attributes and tags if we detect an unknown version (try to be upward compatible).&lt;br /&gt;
* compiler: Speed up consumer cache synchronization so working with large .NET caches or large assembly sets is much faster.&lt;br /&gt;
* debugger: now it is possible to restart the debuggee without unraising and raising again the debugger's interface&lt;br /&gt;
* debugger: now we keep the layout for each watch tool in preferences.&lt;br /&gt;
* compiler: Custom conditions now also take environment variables into account.&lt;br /&gt;
* compiler: Display unsubstitued path to cluster/assembly/library if a file/directory open error occurs.&lt;br /&gt;
* studio: Added a cancel button in the dialog of the automatic precompilation to cancel the precompilation.&lt;br /&gt;
* COM Wizard: EiffelStudio button is enabled also if the Eiffel compilation fails.&lt;br /&gt;
* compiler: Generate an error if a configuration file used in a precompile has structurally been changed as the precompile is not usable in this case anymore.&lt;br /&gt;
* base: The HASH_TABLE in base has two new possibilities to detect/prevent catcalls, they can be enabled by enabling assertion checking and enabling the debug clauses prevent_hash_table_catcall and detect_hash_table_catcall.&lt;br /&gt;
* studio: {{Red|Added dependency view so supplier/client dependency of a group/folder/class can be investigated. Feature calls are included in dependency view.}}&lt;br /&gt;
* studio: Added syntactical supplier/client support in class view.&lt;br /&gt;
&lt;br /&gt;
===Bug fixes===&lt;br /&gt;
* COM wizard: {{Red|Time library was not included which lead to problems if a COM component used the DATE_TIME data type.}}&lt;br /&gt;
* compiler: {{Red|Fixed incrementality bug with agents where finalizing and then freezing would cause some unresolved externals.}}&lt;br /&gt;
* compiler: Don't do an expensive degree 6 if assertion level or similar project settings have changed.&lt;br /&gt;
* studio: Decreased amount of created GDI objects on windows in some grids.&lt;br /&gt;
* studio: Fixed a problem with externals in the project settings.&lt;br /&gt;
* studio: Fixed viewpoint handling for assemblies&lt;br /&gt;
* studio: Fixed output to file redirection in the process library on windows.&lt;br /&gt;
* studio: Fixed samples that would not compile.&lt;br /&gt;
* compiler: Fixed a crash if a library without an UUID is used.&lt;br /&gt;
* compiler: Fixed a problem that classes that were not visible before did not get compiled when they were made visible.&lt;br /&gt;
* compiler: Fixed CECIL name if there is a renaming specified in the visible clause.&lt;br /&gt;
* compiler: Fixed VTCT error was not detected if a prefix/renaming changed on an assembly or library.&lt;br /&gt;
* vision2: Fixed bug when setting a pixmap on a menu entry which has a submenu, the submenu would disappear.&lt;br /&gt;
* compiler: Fixed a bug in the check if local assemblies are present.&lt;br /&gt;
* compiler: Fixed some problems with sub clusters of overrides.&lt;br /&gt;
* compiler: Interpolate environment variables also in metadata cache path specified on the command line.&lt;br /&gt;
* compiler: Fixed some bugs in the documentation generation related to sub clusters.&lt;br /&gt;
* compiler: Option changes always led to an expensive degree 6 even if a fast degree 6 would have been enough.&lt;br /&gt;
&lt;br /&gt;
===User changes===&lt;br /&gt;
* base: {{Red|EXECUTION_ENVIRONMENT.get will only retrieve environment variable. It won't retrieve a value from the registry key on Windows (from HKLM\Software\ISE\Eiffelxx\app_name). This also means that MELT_PATH on Windows cannot be set in registry; this is not really a problem since now you do not need to set it since the W_code knows where to find it.}}&lt;br /&gt;
&lt;br /&gt;
===Developer changes===&lt;br /&gt;
* cli_debugger is now under framework, and the corresponding clib has to be compiled.&lt;br /&gt;
* New delivery scripts on unix will now compress packages using bzip2 as they are about 30% smaller than the packages build with gzip.&lt;br /&gt;
* The eifinit/studio folder has now been moved into studio/eifinit&lt;br /&gt;
* build has been renamed into esbuilder&lt;br /&gt;
* vision2_tour has been renamed into vision2_demo&lt;br /&gt;
* Possibility to build a delivery which fits into the unix directory layout.&lt;br /&gt;
* Use the normal HASH_TABLE in the compiler.&lt;br /&gt;
* ID_AS does no longer inherit from STRING, instead it has a name_id and the string is stored in NAMES_HEAP&lt;br /&gt;
* Added additional applicable inspect-able types to VOMB1 error help text.&lt;br /&gt;
===Road map to ISO Eiffel===&lt;br /&gt;
[[Language_road_map|(Under construction)]]&lt;/div&gt;</summary>
		<author><name>Seilerm</name></author>	</entry>

	<entry>
		<id>https://dev.eiffel.com/index.php?title=EiffelStudio_6.0_Releases&amp;diff=8101</id>
		<title>EiffelStudio 6.0 Releases</title>
		<link rel="alternate" type="text/html" href="https://dev.eiffel.com/index.php?title=EiffelStudio_6.0_Releases&amp;diff=8101"/>
				<updated>2007-04-16T17:19:28Z</updated>
		
		<summary type="html">&lt;p&gt;Seilerm: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Category:Releases]]__NOTOC__{{ReleaseHistoryHeader}}&lt;br /&gt;
&lt;br /&gt;
= EiffelStudio 6.0.x Releases=&lt;br /&gt;
&lt;br /&gt;
==6.0.x==&lt;br /&gt;
Placeholder for new stuff since last intermediate release.&lt;br /&gt;
===New features===&lt;br /&gt;
* estudio: {{Red|Replaced all native tool bars (EV_TOOL_BAR) with Smart Docking library tool bars (SD_TOOL_BAR).}}&lt;br /&gt;
&lt;br /&gt;
===Feature removed===&lt;br /&gt;
===Bug fixes===&lt;br /&gt;
* docking: Fixed bug#12389: &amp;quot;Reset tools layout&amp;quot; in debug mode does not do what I am expecting&lt;br /&gt;
===User changes===&lt;br /&gt;
===Developer changes===&lt;br /&gt;
&lt;br /&gt;
==6.0.6.7849 (April 15th 2007)==&lt;br /&gt;
===New features===&lt;br /&gt;
* compiler: The notion of creation readiness according to ECMA Eiffel standard (2nd edition, chapter 8.12.12) is implemented.&lt;br /&gt;
===Feature removed===&lt;br /&gt;
===Bug fixes===&lt;br /&gt;
* compiler: Fixed bug#12464: If a generic derivation in a deferred class uses `like Current' as generic parameter the creation constraints are not enforced on that particular formal.&lt;br /&gt;
* debugger: Completed implementation for dotnet system: bug#12435: Evaluating an expression still checks for invariant.&lt;br /&gt;
* debugger: Fixed bug#12435: Evaluating an expression still checks for invariant&lt;br /&gt;
* debugger: Now it is possible to disable/restore assertion checking during debugging in classic AND dotnet system.&lt;br /&gt;
* debugger: Fixed bug#12461: &amp;quot;Run Workbench&amp;quot; fails if no environment variable had been added.&lt;br /&gt;
* debugger: Fixed bug#12442: Selecting Debug/Exception handling for uncompiled project causes crash&lt;br /&gt;
* debugger: Fixed bug#12443: Run Workbench button in Debugging Options window does not work when app melted&lt;br /&gt;
* studio: Improved memory management.&lt;br /&gt;
&lt;br /&gt;
===User changes===&lt;br /&gt;
===Developer changes===&lt;br /&gt;
&lt;br /&gt;
==6.0.6.7775 (April 9th 2007)==&lt;br /&gt;
===New feature===&lt;br /&gt;
* vision2: ability to save an EV_PIXEL_BUFFER or to convert it to EV_PIXMAP.&lt;br /&gt;
* wel: {{Red|Added ability to convert image formats among all image formats on Windows (using WEL_GDIP_BITMAP).}}&lt;br /&gt;
&lt;br /&gt;
===Bug fixes===&lt;br /&gt;
* debugger: Fixed bug#12435: Evaluating an expression still checks for invariant (classic only)&lt;br /&gt;
* debugger: Fixed bug#12443: Run Workbench button in Debugging Options window does not work when app melted&lt;br /&gt;
* vision2: Fixed bug bug#12113: I'd like to be able to save an EV_PIXEL_BUFFER into a file&lt;br /&gt;
* estudio: Fixed bug bug#12437: Previous docking layout are not valid&lt;br /&gt;
&lt;br /&gt;
===Developer changes===&lt;br /&gt;
* Set .NET namespaces on all ISE libraries to be as terse and coherent as possible.&lt;br /&gt;
* .NET precompiled libraries binary names have been changed to fit present naming for .NET assemblies.&lt;br /&gt;
&lt;br /&gt;
==6.0.6.7670 (April 1st 2007)==&lt;br /&gt;
===New features===&lt;br /&gt;
* studio: {{Red|Added ability to add new classes/clusters/assemblies early on in the compilation phase instead of waiting for a successful compilation.}}&lt;br /&gt;
&lt;br /&gt;
===Bug fixes===&lt;br /&gt;
* dotnet: {{Red|Implemented suggestion from [[.NET_Namespace_Generation]].}}&lt;br /&gt;
* dotnet: Fixed bug#12433 where editing a class in EiffelStudio would change its generated namespace and thus invalidating the generated assembly (recompilation from scratch was necessary).&lt;br /&gt;
* Vision2: {{Red|Made sure that Windows and Unix behave the same way regarding widget navigation when one has set the ''default_key_processing_handler''. The behavior is that if it is set, then the tab processing will be disabled if it returns True.}}&lt;br /&gt;
*debugger: Fixed (again) bug#12371: Feature Relation window not scrolled to current line in debugger&lt;br /&gt;
*debugger: Implemented suggestion bug#12395 :No splitter by default&lt;br /&gt;
*debugger: Added start workbench and finalized system on Debugging option dialogs&lt;br /&gt;
*debugger: Fixed bug#11688: Compiling all classes under .NET with EXE generation hangs debugger&lt;br /&gt;
*estudio: Fixed bug#12203: Open Layout window disappears first time View/Open Layout is selected&lt;br /&gt;
*estudio: Fixed bug#12164: Large Fonts not respected in all widgets&lt;br /&gt;
*estudio: Fixed bug#12121: Wrong cursor if undock window operation in progress when compile ends&lt;br /&gt;
*estudio: Fixed bug#12036: Enter on a category in the Features tool does not focus the Editor&lt;br /&gt;
*estudio: Fixed bug#12104: Docked tracking preference ignored&lt;br /&gt;
*estudio: Fixed bug#12134: Auto Hide button should have different tooltips for enable/disable&lt;br /&gt;
*estudio: Fixed bug#12327: Closing Editor tab makes Clickable, Flat etc buttons insensitive&lt;br /&gt;
*docking: Fixed bug#12103: Estudio doesn't remember layout correctly if force debugger mode or maximize a tool&lt;br /&gt;
*docking: Fixed bug#12241: Hiding Address tool bar and reshowing it causes it to appear on Project tool bar row&lt;br /&gt;
*docking: Fixed bug#12260: Hiding toolbars leaves vacant space at bottom&lt;br /&gt;
*docking: Fixed bug#12114: Bringing up undocked window via View/Tools unmaximizes other too&lt;br /&gt;
&lt;br /&gt;
===User changes===&lt;br /&gt;
&lt;br /&gt;
===Developer changes===&lt;br /&gt;
*visioon2: Added new class EV_BEEP which can make system default beeps.&lt;br /&gt;
&lt;br /&gt;
==6.0.6.7522 (March 25th 2007)==&lt;br /&gt;
===New features===&lt;br /&gt;
* studio: Add assembly dialog assembly entires are now placed in columns. Added columns for the assembly path and processor architecture.&lt;br /&gt;
* studio: {{Red| Added support for multi constraint code completion.}}&lt;br /&gt;
&lt;br /&gt;
===Bug fixes===&lt;br /&gt;
* debugger: Fixed bug#11558 about evaluation of expressions involving NATURAL_XY values&lt;br /&gt;
* installer: (Windows) Fixed bitmap scaling issue for large fonts.&lt;br /&gt;
* Fixed the problem that Precursor {CLASS}.* only showed once routines.&lt;br /&gt;
* Fixed the problem that Result [i].* didn't work.&lt;br /&gt;
* Fixed the problem that Precursor {NEW_CLASS_3} [1].* didn't work.&lt;br /&gt;
* Fixed the problem that {INTEGER}.max_value.* didn't work.&lt;br /&gt;
* Fixed bug#12323 changing class name and then canceling Class Rename crashes estudio.&lt;br /&gt;
* Fixed bug#12331 Windows window showed two windows instead of one after exit and restart.&lt;br /&gt;
* Fixed bug#12347 that deleting a class displayed in an editor tab caused crash. &lt;br /&gt;
* Fixed a bug that initial dropping a cluster to diagram tool did nothing.&lt;br /&gt;
* Fixed bug#12299 that compiling lost diagram tool when targeted to a cluster.&lt;br /&gt;
* Fixed bug#12355 that selecting homonyms format for feature caused crash.&lt;br /&gt;
* Fixed the bug that shortcut for an initial or edited external command did not work.&lt;br /&gt;
* Fixed bug#11879 that show all docking indicators preference only respected when setting it.&lt;br /&gt;
* Fixed bug#12324 that main window resizes after loading project.&lt;br /&gt;
* Fixed bug#12118 that closing auto hidden tools during debugging leads to estudio crash.&lt;br /&gt;
* Fixed bug#12120 that particular docking layout causes crash in {SD_STATE_VOID}.move_to_docking_zone.&lt;br /&gt;
* Fixed bug#12339 that crash when rearranging editor tabs using mouse.&lt;br /&gt;
* Fixed bug#12235 that toolbar text blurs when exposed on linux.&lt;br /&gt;
* Fixed Eiffel Studio starting flicker problem, there is only 1 time flicker during the whole Eiffel Studio starting process now.&lt;br /&gt;
&lt;br /&gt;
==6.0.6.7358 (March 18th 2007)==&lt;br /&gt;
===New features===&lt;br /&gt;
* studio: Added configurable shortcuts for history back and forth.&lt;br /&gt;
* studio: Added ability to remember show/hide formatting marks status.&lt;br /&gt;
* studio: Made Eiffel Studio can open into debug mode directly.&lt;br /&gt;
* studio: Disable fading effects for Eiffel Studio splash screen and disabled auto hide animations on remote desktop.&lt;br /&gt;
* debugger: new object viewer tool. (to replace the pretty or expanded display dialog)&lt;br /&gt;
* compiler: {{Red|Added support for multiple constraints in formal generic parameters.}}&lt;br /&gt;
* docking: Made docking library title bar drawing text position care about font size.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Bug fixes===&lt;br /&gt;
* compiler: Fixed issue with incorrect labeled tuples which were not detected in signature of features (see eweasel test#tuple008).&lt;br /&gt;
* compiler: Fixed crash when checking an incorrect labeled tuple (e.g. TUPLE [a, a: INTEGER]) (see eweasel test#tuple009).&lt;br /&gt;
* studio: {{Red|Fixed bug#12083 where classes in override clusters would not get recompiled properly when automatically saved by EiffelStudio when requesting a compilation.}}&lt;br /&gt;
* studio: Fixed display of public key token on add assembly dialog.&lt;br /&gt;
* studio: Improved show/hide formatting marks command. This command only functioned on current editor and when current editor switched the name was not displayed correctly. Now it functions on all editors of current window.&lt;br /&gt;
* studio: Fixed bug#12256 that dependency tool could not close.&lt;br /&gt;
* studio: Fixed bug#12261 that find was broken, and added Home/End actions to the report grid.&lt;br /&gt;
* studio: Fixed bug#12264 that first column of preference grid was too narrow.&lt;br /&gt;
* studio: Fixed a bug that Alt+Left/Alt+Right didn't function on diagram tool and dependency tool.&lt;br /&gt;
* studio: Fixed a bug that address history forth command was always disabled in diagram tool.&lt;br /&gt;
* studio: Fixed bug#12258 that completion window was brought up by dot after a number. &lt;br /&gt;
* studio: Fixed the bug that shortcut for class completion triggered feature completion window in completable text fields (i.e. Watch tool, conditional breakpoint dialog).&lt;br /&gt;
* studio: Fixed bug#12037: Post condition violation at {EB_SMART_EDITOR}.refresh_line_number_display&lt;br /&gt;
* studio: Fixed bug#12013: View | Toolbars indicates wrong state for hidden toolbars&lt;br /&gt;
* studio: Fixed bug#12102: Search tool Options section cut off and mostly not visible&lt;br /&gt;
* pref: fixed bug#12183: Filter in preferences window is case-sensitive but should not be&lt;br /&gt;
* pref: fixed bug#12184 : Changing value of boolean preference when filter in effect causes crash&lt;br /&gt;
* debugger: Fixed bug#12195: Trying to save exception dialog when in Force Debugger mode causes crash&lt;br /&gt;
* debugger: Fixed bug#12194: Copying call stack to clipboard in Force Debugger mode causes crash&lt;br /&gt;
* debugger: Fixed bug#12265 : Ctrl+Alt+W used by the Debug - Show object viewer tool&lt;br /&gt;
* debugger: Fixed bug#12267: Multiple problems with Object Browser window (except for the width of the &amp;quot;Select Viewer&amp;quot; button, it seems a vision2 issue)&lt;br /&gt;
* debugger: Fixed bug#12283: Confirmation improvement and wrong preference category&lt;br /&gt;
* debugger: Fixed upper slice value for string display box.&lt;br /&gt;
* debugger: Fixed bug#12246: continue on cond breakpoint failure does not seem to work with Not Yet Called once&lt;br /&gt;
* debugger: Fixed bug#12170: Run to This Point doesn't stop unless hit count matches&lt;br /&gt;
* debugger: Fixed bug#12251: Saving exception message from debugger gives no error when permission problem&lt;br /&gt;
* debugger: Fixed suggestion bug#12230: Switch arguments and working directory in Debugging Options dialog&lt;br /&gt;
* debugger: Allow to save a file without the extension; fixed bug#12293: Estudio insists on adding &amp;quot;.txt&amp;quot; when save exception message from debugger&lt;br /&gt;
* debugger: Fixed issue with data associated with debugger grid line. A few internal data were not reseted when the expression's text was changed in the watch tool.&lt;br /&gt;
* debugger: Fixed bug#12257 : Watch expression that is constant real expression evaluates to 0&lt;br /&gt;
* vision2: Fixed bug#12210 where a pixmap will not be copied when assigned to a menu, and therefore you would get the same pixmap for all menu items instead of different ones.&lt;br /&gt;
* docking: Fixed bug#11870: Default layout for toolbar is not properly left aligned.&lt;br /&gt;
* docking: Fixed bug#11941: Dockable toolbars can have their handle placed so it cannot be accessed&lt;br /&gt;
* docking: Fixed bug#11944: Dragging tabs to re-order is not stable&lt;br /&gt;
* docking: Fixed bug#11829 CTRL+TAB selector item spacing/clipping&lt;br /&gt;
* docking: Fixed bug#11962: Postcondition violation in `make' of SD_NOTEBOOK_HIDE_TAB_DIALOG&lt;br /&gt;
* docking: Fixed bug#11970 Please add a tooltip to the Editor's class name tab&lt;br /&gt;
* docking: Fixed bug#11974: Address Toolbar customisations are lost&lt;br /&gt;
* docking: Fixed bug#12031: Another Internal Error on typing Ctrl+Tab&lt;br /&gt;
* docking: Fixed bug#12078: Internal Error halting debugger&lt;br /&gt;
* docking: Fixed bug#12090: Minor problems with resizing undocked windows&lt;br /&gt;
* docking: Fixed bug#12307: Window below editor doesn't return to original size after running application.(same as bug#12312)&lt;br /&gt;
* docking: Fixed bug#12091: Clicking &amp;quot;X&amp;quot; to close Editor tab often has no effect&lt;br /&gt;
* docking: Fixed bug#12117: Auto hiding tools then stepping to start debugger crashes estudio&lt;br /&gt;
* docking: Fixed Eiffel Studio on Linux hanging after just started undock a Window which is caused by a previous bug fixing.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Developer changes===&lt;br /&gt;
* configuration: Changed STRING_PROPERTY and STRING_CHOICE_PROPERTY to drop the generic parameter and use a value of STRING_32 all the time.&lt;br /&gt;
&lt;br /&gt;
==6.0.6.7183 (March 11th 2007)==&lt;br /&gt;
===New features===&lt;br /&gt;
* studio: {{Red| Added ability to configure shortcuts}}&lt;br /&gt;
* studio: {{Red|Auto-completion after bracketed expression. i.e. arr [i].*}}&lt;br /&gt;
* studio: Set editors’ description and details in Ctrl + Tab dialog.&lt;br /&gt;
* studio: When no class are edited, dropping a class or feature stone in the empty grey box of the editors will open a new editor related with the stone&lt;br /&gt;
* compiler: {{Red|Supported reattachment of generic derivations with expanded parameters to generic derivations with reference parameters on .NET.}}&lt;br /&gt;
* compiler: {{Red|Added option for full class checking. It can be enabled at the system, cluster or class level. However not all our code has been compiled with this option so don't be surprised if you get errors in our libraries.}} The next release should fix all the remaining issues.&lt;br /&gt;
* compiler: {{Red|Added [[Compilation Without Configuration]] for simple projects.}}&lt;br /&gt;
* docking: {{Red | Implemented lock toolbars and lock tools docking mechanism feature, and added related two new menu items under View menu.}}&lt;br /&gt;
* docking: Draw an extra floating title bar baseline to make it beautiful.&lt;br /&gt;
&lt;br /&gt;
===Bug fixes===&lt;br /&gt;
* studio: Fixed a bug that Ctrl + f4 didn't close debugger tools (call stack, object, watch and thread)&lt;br /&gt;
* studio: Fixed bug#12216 that %B from editing text was taken as an instruction.&lt;br /&gt;
* studio: Fixed bug#12208 of search report display issue. Improved its mouse/keyboard behaviors and interface a little bit.&lt;br /&gt;
* studio: Fixed bug#12202 that linked tools did not update when auto hiding.&lt;br /&gt;
* studio: Fixed bug#12185: Crash with old docking layout files&lt;br /&gt;
* studio: Fixed bug#12212: Refactoring menu is missing&lt;br /&gt;
* docking: Fixed bug#12164: Large Fonts not respected in all widgets&lt;br /&gt;
* docking: Fixed bug#12158: Text labels disappear on panes docked to the side&lt;br /&gt;
* docking: Fixed bug#12197: issue with maximized editor&lt;br /&gt;
* docking: Fixed bug#12189: Undocked window comes back very small when shown again.&lt;br /&gt;
* docking: Fixed bug#12228: Breakpoints window toolbar truncated&lt;br /&gt;
* docking: Fixed bug#12225: Windows key messes docking indicators.&lt;br /&gt;
* docking: Made double click to maximize feature works fine on Linux.&lt;br /&gt;
&lt;br /&gt;
==6.0.6.7079 (March 5th 2007)==&lt;br /&gt;
===Bug fixes===&lt;br /&gt;
* studio: Fixed issues with the way we launched '''finish_freezing.exe''' on Windows, we were not protecting the path to the executable against white spaces.&lt;br /&gt;
* debugger: Fixed issue which would prevent debugging if ISE_EIFFEL has spaces in it.&lt;br /&gt;
* install: Fixed incorrect shortcuts on Windows.&lt;br /&gt;
&lt;br /&gt;
==6.0.6.7057 (March 3rd 2007)==&lt;br /&gt;
===New features===&lt;br /&gt;
* compiler: we are now using FreeELKS as a replacement for EiffelBase&lt;br /&gt;
* estudio: Made Window Eiffel Studio splash screen beautiful.&lt;br /&gt;
&lt;br /&gt;
===Bug fixes===&lt;br /&gt;
* install: (Windows) fixed fatal error bug#12146 when attempting to browse for a folder.&lt;br /&gt;
* install: (Windows) fixed radio button background color different as best possible given the limitations of MSI.&lt;br /&gt;
* install: (Windows) pressing Back on the installed when on the Precompilation Choice page goes to the correct parent page instead of the Configure C/C++ Compiler page.&lt;br /&gt;
* compiler: Fix bug in .NET resx =&amp;gt; resource generation by the compiler when using resx files with relative paths.&lt;br /&gt;
* compiler: Adapted the compiler so that ISE_EIFFEL does not need to be defined with a short path name on Windows, since some file systems can disable support for short path &lt;br /&gt;
names.&lt;br /&gt;
* studio: various bug fixes with the docking.&lt;br /&gt;
* vision2: Fixed issue where hiding a widget in an EV_FIXED and changing its position would not be reflected when showing the widget later.&lt;br /&gt;
* base: {{Red| Fixed issue with LINKED_QUEUE.twin which would violate its invariant.}}&lt;br /&gt;
* base: {{Red| Revisited contracts of LINEAR_ITERATOR.}}&lt;br /&gt;
* docking: bug#11981: Cannot put window from another application in front of undocked window&lt;br /&gt;
* estudio: bug#12076: Refresh issue on Start/Continue button&lt;br /&gt;
* docking: bug#12096: Sliding panel tools cause an unsightly redraw when revealed when on the right side on gtk&lt;br /&gt;
* docking: bug#12098: Disable text in docking toolbar on linux doesn't look disabled&lt;br /&gt;
* docking: bug#12099: Particular docking layout crashes estudio on exit&lt;br /&gt;
* docking: bug#12111: Toolbars disappear after running debugger&lt;br /&gt;
* docking: bug#12067: Estudio crash in {SD_TAB_STATE}.make called from move_to_zone_internal&lt;br /&gt;
* docking: bug#12126: Maximizing tool then closing it closes other tools and makes them unavailable&lt;br /&gt;
* docking: bug#12132: Estudio doesn't restore normal/debug layouts within same session&lt;br /&gt;
* docking: bug#12138: Sequence of saving, opening and resetting tools layout causes crash&lt;br /&gt;
* docking: bug#11984: Text on many buttons in estudio main window cut off at bottom&lt;br /&gt;
* vision2: bug#11989: Unintuitive behavior when trying to move an undocked window&lt;br /&gt;
* vision2: bug#12071: Auto Hide of window before pick ends hangs estudio, then F7 crashes it&lt;br /&gt;
* vision2: bug#12143: Window titles in title bar not visible when window has focus&lt;br /&gt;
&lt;br /&gt;
===User changes===&lt;br /&gt;
* install: (Windows) removed information, on the welcome page, about setting up a C/C++ compiler if a compiler is detected.&lt;br /&gt;
* estudio: Improved background color of Linux editor place holder zone.&lt;br /&gt;
&lt;br /&gt;
===Developer changes===&lt;br /&gt;
* docking: Added proprogate accelerator in SD_DOCKING_MANAGER.&lt;br /&gt;
* docking: Added SD_CONTENT.update_mini_tool_bar_size.&lt;br /&gt;
&lt;br /&gt;
==6.0.6.6895 (February 25th 2007)==&lt;br /&gt;
===New features===&lt;br /&gt;
* Added the feature requested at bug#12046 that Ctrl+F3 searches current word if no text is selected.&lt;br /&gt;
* Internationalized choices in interface.development_window.ctrl_right_click_receiver and tools.search_tool.init_scope.&lt;br /&gt;
* debugger: Added &amp;quot;rescue&amp;quot; indicator in call stack tool's grid.&lt;br /&gt;
* debugger: {{Red|Added the possibility to evaluate an instruction with the debugger (i.e: procedure call).}}&lt;br /&gt;
* compiler: {{Red|Support for FreeELKS as a replacement for EiffelBase}}.&lt;br /&gt;
* studio: Now we can exit directly from debugging mode, no changing to normal mode needed.&lt;br /&gt;
* docking: SD_TOOL_BAR_CONTENT has new feature &amp;quot;unique_title&amp;quot; for store data, and using feature &amp;quot;title&amp;quot; for display.&lt;br /&gt;
* install: (Windows) Installer detects and configures a resident VC/VC++ compiler and provides/hides options based on what it found.&lt;br /&gt;
* install: (Windows) Precompilation is disabled if a VC/VC++ could not be configured to prevent creation of bad precompiled libraries.&lt;br /&gt;
* install: (Windows) x64 version no longer displays the option for installing the Borland C compiler because it's for x86 compilations only.&lt;br /&gt;
* install: (Windows) In the event of no C/C++ compiler found help is now link-provided to obtain a the free Windows SDK.&lt;br /&gt;
* install: (Windows) new installers with compact look and feel and better auto-configuration.&lt;br /&gt;
&lt;br /&gt;
===Bug fixes===&lt;br /&gt;
* studio: Fixed bug#5437 that Shift+End selects too much text.&lt;br /&gt;
* studio: Fixed the bug that menu commands like Cut, Copy, Paste and Select All and sub commands of &amp;quot;Search&amp;quot; didn't work consistently as their shortcuts did. i.e. &amp;quot;Select All&amp;quot; always selected texts in main editor, but Ctrl+A did correct thing that was select all texts in the editor where focus was.&lt;br /&gt;
* studio: Fixed a bug that when dropping a stone to the editor, confirmation on saving a read only class didn't prevent the stone from loading, which means that the modified class got lost in this case.&lt;br /&gt;
* studio: Fixed bug#12050 that EiffelStudio crashed when trying to save a file that you didn't have write access to. Open a Save As dialog if .swp file is not creatable.&lt;br /&gt;
* studio: Fixed bug#12053 that Toggle Line Numbers and Go to didn't show correct sensitivity.&lt;br /&gt;
* studio: Fixed bug#12029 that es crashed when reopening ES with general.locale changed from English to Chinese.&lt;br /&gt;
* studio: Fixed bug#12061 that synchronization button not showing the proper tool. Now we try to synchronize the feature displayed in the combo box. (We only synchronized the stone.)&lt;br /&gt;
* studio: Fixed a crash when updating viewpoints. &lt;br /&gt;
* studio: Fixed bug#12068 and bug#12069, crashes when there was no editor.&lt;br /&gt;
* debugger: fixed issue with native_array unable to be resized with slices tool. (dotnet debugger)&lt;br /&gt;
* compiler: Fixed bug#11936 where namespace names included the cluster name when a cluster defined a namespace.&lt;br /&gt;
* studio: Fixed bug#11987 that Closing Class tab crashes estudio after move to Clusters&lt;br /&gt;
* studio: Fixed bug#12054 that Crash when select Editor window after exiting debugger&lt;br /&gt;
* studio: Fixed bug#12000 that Particular docking layout causes estudio to crash at startup&lt;br /&gt;
* studio: Fixed bug#11998 that Wrong tooltips on many Project tool bar buttons - say Show/Hide&lt;br /&gt;
* studio: Fixed bug#11873 Breakpoint tool content not refreshed when switching to debug mode&lt;br /&gt;
* docking: Fixed bug#11960 Alignment issues&lt;br /&gt;
* studio: Set docking window title bar height, tool bar height a little bit bigger for Linux specially.&lt;br /&gt;
* docking: Make hide tab indicator correct and tool bar drawing style correct for Linux implementation.&lt;br /&gt;
* studio: Fixed bug that hidden tab dialog position not correct on Linux.&lt;br /&gt;
* studio: Fixed bug that minimum height of docking (not tabbed) editor not correct on Linux.&lt;br /&gt;
* docking: Fixed bug that select a tab from hidden item drop down menu, SD_CONTENT.focus_in_actions not been called.&lt;br /&gt;
* docking: Fixed bug that close button of editor tab position not correct if not enough space.&lt;br /&gt;
* docking: Fixed bug that close button of editor tab state not updated correctly sometimes.&lt;br /&gt;
&lt;br /&gt;
===User changes===&lt;br /&gt;
* debugger: the call stack tool now display a special icon when on feature with rescue cause.&lt;br /&gt;
* studio: Changed shortcut for Cluster tool to Ctrl+Alt+U.&lt;br /&gt;
* studio: Fixed bug#11998: Wrong tooltips on many Project tool bar buttons - say Show/Hide&lt;br /&gt;
* studio: Fixed bug#12048: Please improve the Debug | Tools menu&lt;br /&gt;
===Developer changes===&lt;br /&gt;
* studio: Improved the way of saving context session data. We save ids of the feature/class targeted in tools.&lt;br /&gt;
&lt;br /&gt;
==6.0.6.6595 (February 11th 2007)==&lt;br /&gt;
===New features===&lt;br /&gt;
* compiler: (windows) finish_freezing.exe now looks for the installed Windows SDK recently released from Microsoft. If installed, there is no need to perform any manual C-compiler configuration.&lt;br /&gt;
* studio: Dependency tool tab receives stones.&lt;br /&gt;
* build: {{Red|Code generation will includes the facility of closing the application when last window is closed.}}&lt;br /&gt;
&lt;br /&gt;
===Bug fixes===&lt;br /&gt;
* studio: Fixed bug#12016 where EiffelStudio would crash when trying to debug an application after cancelling a finalization.&lt;br /&gt;
* debugger: fixed &amp;quot;restart&amp;quot; feature which was broken in last release.&lt;br /&gt;
* debugger: fixed &amp;quot;DEBUG_OUTPUT&amp;quot; processing in debugger for dotnet system.&lt;br /&gt;
* debugger: fixed issue with &amp;quot;do not close ecdbgd&amp;quot; when the user decides to reuse the same &amp;quot;ecdbgd&amp;quot; process, be sure to reuse it.&lt;br /&gt;
* debugger: fixed bug#11928 and more general issue with exception on framework .NET 3&lt;br /&gt;
* studio: Fixed bug#11969 that diagram tool did not link to the editor (Neither dependency tool).&lt;br /&gt;
* studio: Fixed bug#12003 that Pick and drop of a parent class in the feature tool targeted to class view instead of showing ancestor.&lt;br /&gt;
* studio: Fixed bug#12018 that changing shortcut preference of external commands crashed es.&lt;br /&gt;
* studio: Improved history behaviors mostly according to [[History behavior]] except the preference.&lt;br /&gt;
* studio: Fixed a crash that opening ES with a group opened last time closing.&lt;br /&gt;
* studio: Fixed the bug#11959 that after refactoring a class with file name changed was not correctly reloaded.&lt;br /&gt;
* studio: Fixed bug#12002: Boolean Preferences cannot be edited via the keyboard&lt;br /&gt;
* studio: Fixed bug#12006: Shortcut Preferences cannot be edited via the keyboard&lt;br /&gt;
* studio: Fixed bug#11827: Extra padding on right for &amp;quot;Customize&amp;quot; toolbar menu&lt;br /&gt;
* studio: Fixed bug#12005: Moving tabs around issue with metric&lt;br /&gt;
* studio: Fixed bug#11814: Persistent redraw issue&lt;br /&gt;
* studio: Fixed the bug that first time tool bar floating, the width is not correct.&lt;br /&gt;
* studio: Fixed bug that favorite tool only can show in normal mode or debug mode.&lt;br /&gt;
* build: Fixed crash when generating code which included a combo box in read-only mode.&lt;br /&gt;
&lt;br /&gt;
===User changes===&lt;br /&gt;
* studio: Changed shortcut of showing Diagram tool to Ctrl+Alt+I.&lt;br /&gt;
* debugger: add possibility to continue on conditional breakpoint evaluation failure&lt;br /&gt;
* debugger: Get rid of useless &amp;quot;Attributes&amp;quot; row in debugger's objects grids (This makes display less lighter).&lt;br /&gt;
* debugger: now the &amp;quot;Once routines&amp;quot; also show states of &amp;quot;once procedures&amp;quot; and not only &amp;quot;once functions&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
===Developer changes===&lt;br /&gt;
* studio: Now we store in session data class/group IDs from EB_SHARED_ID_SOLUTION instead of class 'file_name's or group names which could cause a problem that moving a project lead to class missing and a problem wrong group returned (many groups with the same name).&lt;br /&gt;
* studio: Made fake editors for clusters if hidden when opening.&lt;br /&gt;
&lt;br /&gt;
==6.0.6.6451 (February 4th 2007)==&lt;br /&gt;
===New features===&lt;br /&gt;
* debugger: now it is possible to force the environment to stay in debugger mode.&lt;br /&gt;
===Bug fixes===&lt;br /&gt;
* runtime: {{Red|Fixed a memory corruption which could occur when performing a deep_twin on an object whose graph contains a TUPLE object. See test#tuple006.}}&lt;br /&gt;
* runtime: {{Red|Fixed issue when retrieving 64-bit storables on 32-bit machines. It requires a regeneration of the 64-bit storables if one wants to retrieve them on 32-bit machines. Fixed bug#11744.}}&lt;br /&gt;
* studio: Fixed bug#11848 and bug#11939 related to the `Debugging Options' dialog which could randomly crash (related to test#tuple006 issue).&lt;br /&gt;
* studio: Fixed `on_text_fully_loaded' crash (bug#11943, bug#11938 and bug#11937).&lt;br /&gt;
* EiffelStore: Fixed ODBC on Linux.&lt;br /&gt;
* debugger: SPECIAL[SPECIAL[..]] is fully supported now by the debugger.&lt;br /&gt;
* studio: Fixed bug#11761, bug#11865 and bug#11866, general.locale didn't initialize properly. &amp;quot;Unselected&amp;quot; entry was added.&lt;br /&gt;
* studio: Corrected current output codepage/charset for command line ES.&lt;br /&gt;
&lt;br /&gt;
==6.0.6.6309 (January 27th 2007)==&lt;br /&gt;
===New features===&lt;br /&gt;
* studio: Finished internationalizing starting dialog, wizards.&lt;br /&gt;
* studio: {{red|Integrated Smart Docking library.}}&lt;br /&gt;
* studio: {{red|Integrated tab editor mechanism.}}&lt;br /&gt;
* studio: Added preference &amp;quot;Maximum processor usage&amp;quot; to dictate the maximum number of processors/cores to use when compile c-code.&lt;br /&gt;
* EiffelWizard: Introduced i18n library to make it possible to display in different languages.&lt;br /&gt;
* compiler: .NET Enums are can be automatically converted to INTEGERs&lt;br /&gt;
* compiler: indexing tags ''interface_metadata'' and ''class_metadata'' are supported on feature level like this is done on class level and allow to specify custom attributes for associated methods only in interface type or only in implementation type.&lt;br /&gt;
* compiler: Static access on external routines is allowed even if not marked frozen (this simply applies a relaxed rule that was adopted by ECMA).&lt;br /&gt;
* debugger: dropping feature or class stones on breakpoints tool to add related breakpoint&lt;br /&gt;
* debugger: enhanced breakpoint mechanism by adding print message, hit count (condition), and provide &amp;quot;Is True&amp;quot; and &amp;quot;Has Changed&amp;quot; condition.&lt;br /&gt;
* studio: Integrated encoding library and internationalized part of batch compiler.&lt;br /&gt;
* base: Added facilities to read/write REAL_32 and REAL_64 values in big and little endian format in MANAGED_POINTER&lt;br /&gt;
* net: {{red|Updated reading routines of EiffelNet so that for all basic types they would read all the required bytes, not just stop after the first reading. This is important as in some very bad network situation or if you have some signals you could mess up the reading by only reading half of the expected bytes.}}&lt;br /&gt;
&lt;br /&gt;
===Bug fixes===&lt;br /&gt;
* studio: Fixed bug#11760 that replacing on empty result crashed es.&lt;br /&gt;
* studio: Auto-complete members for open target agents have been corrected. bug#11767.&lt;br /&gt;
* studio: Fixed bug#11772 that a crash occurred while renaming clusters in property tool.&lt;br /&gt;
* compiler: Fixed bug causing test#dotnet046 to fail, now functions that are .NET properties can be called and executed from client code.&lt;br /&gt;
&lt;br /&gt;
===User changes===&lt;br /&gt;
* studio: Added new docking feedback indicators.&lt;br /&gt;
* compiler: added conversion of TYPED_POINTER to POINTER before reattachment to reference entity so that the behaviour is the same in classic and .NET modes&lt;br /&gt;
* compiler: All versioned COM import interfaces now have versioned interface member names based on the trailing version number of the interface name, as this meta information is not available in any other way. This greatly improves the versioned names and makes implementing interfaces much easier.&lt;br /&gt;
* compiler: The unique keyword will yield a syntax warning if enabled.&lt;br /&gt;
* debugger: improved cosmetic of debugger's exception handling dialog&lt;br /&gt;
* base: Changed INTERNAL so that it does not have the `is_pre_ecma_mapping_disabled' attribute. If you were setting it to True, you should instead create an instance of ECMA_INTERNAL (fixes bug#11792).&lt;br /&gt;
&lt;br /&gt;
===Developer changes===&lt;br /&gt;
*debugger: refactored breakpoints and exceptions processing for easier integration of other projects on debugger.&lt;br /&gt;
*compiler: updated compiler to compile FreeELKS library, however it cannot yet be executed.&lt;br /&gt;
&lt;br /&gt;
==6.0.65740 (December 25th 2006)==&lt;br /&gt;
===New features===&lt;br /&gt;
* debugger: console based debugger is now working for classic, dotnet, on windows and unices (-debug or via -loop : still experimental)&lt;br /&gt;
&lt;br /&gt;
===Feature removed===&lt;br /&gt;
===Bug fixes===&lt;br /&gt;
* compiler: fixed a bug in .NET consumer that can cause some assemblies to be consume infinitely.&lt;br /&gt;
* compiler: fixed a .NET bug that prevents System.Windows.Forms.Panel from being compiled correct and subsequently causing a compilation to fail, due to incorrect an mapped inherit property and assigner. This addresses test#dotnet043.&lt;br /&gt;
* compiler: Fixed bug#11758 for eweasel test#incr279, where the compiler would crash when generating the call to '''Precursor''' when both the current class and the parent class had their number of formal generics changed.&lt;br /&gt;
* compiler: Fixed bug#11766 for eweasel test#term146 and test#incr129 where the compiler would crash at degree 4 when checking the conformance of a feature, and the signature involves a type which have an incorrect parent hierarchy (i.e. one parent does not have the right number of actual generic parameters).&lt;br /&gt;
* store: {{Red| Fixed bug#10523: if you create a DB_REPOSITORY before being connected to the database, some of the queries made on the database are not returning the proper result in ODBC(e.g. odbc_sensitive_mixed will return 0 instead of 3 for an ORACLE database). By adding the precondition we nicely solve the problem by forcing client to connect first before creating an instance of DB_REPOSITORY.}}&lt;br /&gt;
* store: {{Red| Fixed some issues related to the new implementation of expanded semantics which would break some introspection part of EiffelStore.}}&lt;br /&gt;
* favorites: fixed bug#11745 &amp;quot;feature item&amp;quot; favorites were being lost on restarting EiffelStudio&lt;br /&gt;
* gui: fixed bug#11749 with debugger's grid being empty.&lt;br /&gt;
* debugger: fixed bug#11755: empty string with huge capacity were slow to be displayed.&lt;br /&gt;
* debugger: improved display of objects tool header bar. (minor)&lt;br /&gt;
&lt;br /&gt;
===User changes===&lt;br /&gt;
* base: sped up {SPECIAL}.copy_data which was not inlined.&lt;br /&gt;
&lt;br /&gt;
===Developer changes===&lt;br /&gt;
&lt;br /&gt;
==6.0.65604 (December 17th 2006)==&lt;br /&gt;
===New features===&lt;br /&gt;
* compiler: improved backup mechanism so that overridden classes are copied in the library where they are defined (they were previously copied in the library where the override cluster was defined).&lt;br /&gt;
* studio: {{red|Integrated the internationalization library. Added a preference named &amp;quot;general.locale&amp;quot; to switch among languages. English and Chinese are available for the moment}}&lt;br /&gt;
* debugger: added auto expressions on watch tools&lt;br /&gt;
* studio: Added metric history support. Calculated metrics with their inputs can be sent into history so they can be recalculated afterwards.&lt;br /&gt;
* general: Revision number of EiffelStudio has changed because we reached the limit set by most OS for the revision (65535). So now it is split into revision.build, that is to say rev 65570 will read 6.5570.&lt;br /&gt;
* debugger: added an experimental console based debugger.&lt;br /&gt;
&lt;br /&gt;
===Bug fixes===&lt;br /&gt;
* compiler: {{Red|Fixed issue with inline agents where if you have one and during a compilation from scratch you have a compiler error, then fixing this error and recompiling, it would crash when melting or freezing (test#incr277).}}&lt;br /&gt;
* compiler: Fixed issue with C compilation linking error when a generic class which have an invariant clause has its formal generics changed (test#incr278).&lt;br /&gt;
* compiler: Fixed C compilation error on Windows for trying to compile empties Cxxx directories (test#ccomp061).&lt;br /&gt;
* compiler: Fixed incorrect code generation of agents on attribute when target is open (test#exec264).&lt;br /&gt;
* compiler: Fixed incremental bug when an agent creation based on a feature whose signature changes for less arguments (test#incr276).&lt;br /&gt;
* compiler: Fixed a backup creation bug when two classes from the same cluster/library have the same original file name, the backup would only contain one or the other because we use the original file name. Now we use the original class name.&lt;br /&gt;
&lt;br /&gt;
===User changes===&lt;br /&gt;
* base: Sped up HASH_TABLE iteration and lookup by about 8% or more.&lt;br /&gt;
* base: TUPLE can now compare items using reference equality (=) or object comparison (is_equal).&lt;br /&gt;
* vision2: Changed behavior of {EV_TITLED_WINDOW}.raise to always make sure the window is visible on screen (show if hidden, restore if minimized).&lt;br /&gt;
* vision2: Fixed behavior of is_show_requested and is_displayed for EV_GRID and its items so that it conforms to the widget behavior in Vision2.&lt;br /&gt;
* wel/vision2: {{Red|Raised compatibility bar to Windows 2000 or greater. No more support for Windows 98 or NT 4.0}}&lt;br /&gt;
* dotnet: {{Red|Renamed SYSTEM_ATTRIBUTE into NATIVE_ATTRIBUTE for consistency reasons.}}&lt;br /&gt;
&lt;br /&gt;
===Developer changes===&lt;br /&gt;
* debugger: deep refactoring (reduce the number of onces, renamed and moved some debugger related data)&lt;br /&gt;
* studio: to help track incremental compilation bugs, we build a replay backup window that given a backup directory will go through each compilation and perform them the way it was done by the end user.&lt;br /&gt;
&lt;br /&gt;
==6.0.65344 (December 3rd 2006)==&lt;br /&gt;
===New features===&lt;br /&gt;
* compiler: {{Red|A root type can now be a generic derivation.}}&lt;br /&gt;
* studio: {{Red|Project settings such as arguments/working directory/location are now stored in a user specific location that does not depend on the UUID of the project, but on its path.}}&lt;br /&gt;
* compiler: {{Red|Integers can now also be specified with binary and octal representation}}&lt;br /&gt;
* compiler: {{Red|Manifest characters can now also be specified with binary, octal and hexadecimal representation. Manifest characters can be specified up to 32 Bit.}}&lt;br /&gt;
* compiler: {{Red|Possibility for &amp;quot;hidden/implementation&amp;quot; clusters in libraries, clusters that are not accessible if the library is used (like libraries in libraries are not accessible).}}&lt;br /&gt;
* compiler: {{Red|Added supplier_precondition assertion level that enables to only check preconditions of trusted libraries.}}&lt;br /&gt;
* debugger: {{Red|New Debugging options dialog (to set the arguments and other)}}&lt;br /&gt;
* compiler: Don't do an expensive degree 6 when we freeze or finalize.&lt;br /&gt;
* compiler: Newly added clusters are recursive by default.&lt;br /&gt;
* studio: Favorites are now stored in the user settings.&lt;br /&gt;
* compiler: Warning if an environment variable has changed and opportunity to (temporarily) use the old, stored value&lt;br /&gt;
* compiler: Trigger a full configuration rebuild if environment variables have changed&lt;br /&gt;
* compiler: Added configurable (project to class-level) optimization for .NET project that will mark all classes frozen if they are not descended by another.&lt;br /&gt;
* studio: Add assemblies dialog shows more assembly information.&lt;br /&gt;
* studio: Some diagram generation for assemblies&lt;br /&gt;
* studio:Display documentation for .NET Framework assemblies on .NET 2.0&lt;br /&gt;
* studio: Display features tree for .NET classes.&lt;br /&gt;
* studio: Display uncompiled .NET classes.&lt;br /&gt;
* debugger: Now we can pass modified environment variables to the debuggee application.&lt;br /&gt;
* compiler: Externals (includes, objects, resources, ...) can now be relative to the ecf file by using the new replacement $ECF_CONFIG_PATH.&lt;br /&gt;
* compiler: UUID is not needed for non library systems. If no uuid is specified a random one will be generated. (Startup dialog may not work correct if the config has not been saved with the random generated uuid)&lt;br /&gt;
* debugger: New contextual menu on breakpoints tool for multiple action on class (enable first bp on all features ...)&lt;br /&gt;
* studio: Only expand the currently used target in the project settings.&lt;br /&gt;
* compiler: Changed version of configuration format to 1.1.0&lt;br /&gt;
* compiler: Only print warnings for unknown attributes and tags if we detect an unknown version (try to be upward compatible).&lt;br /&gt;
* compiler: Speed up consumer cache synchronization so working with large .NET caches or large assembly sets is much faster.&lt;br /&gt;
* debugger: now it is possible to restart the debuggee without unraising and raising again the debugger's interface&lt;br /&gt;
* debugger: now we keep the layout for each watch tool in preferences.&lt;br /&gt;
* compiler: Custom conditions now also take environment variables into account.&lt;br /&gt;
* compiler: Display unsubstitued path to cluster/assembly/library if a file/directory open error occurs.&lt;br /&gt;
* studio: Added a cancel button in the dialog of the automatic precompilation to cancel the precompilation.&lt;br /&gt;
* COM Wizard: EiffelStudio button is enabled also if the Eiffel compilation fails.&lt;br /&gt;
* compiler: Generate an error if a configuration file used in a precompile has structurally been changed as the precompile is not usable in this case anymore.&lt;br /&gt;
* base: The HASH_TABLE in base has two new possibilities to detect/prevent catcalls, they can be enabled by enabling assertion checking and enabling the debug clauses prevent_hash_table_catcall and detect_hash_table_catcall.&lt;br /&gt;
* studio: {{Red|Added dependency view so supplier/client dependency of a group/folder/class can be investigated. Feature calls are included in dependency view.}}&lt;br /&gt;
* studio: Added syntactical supplier/client support in class view.&lt;br /&gt;
&lt;br /&gt;
===Bug fixes===&lt;br /&gt;
* COM wizard: {{Red|Time library was not included which lead to problems if a COM component used the DATE_TIME data type.}}&lt;br /&gt;
* compiler: {{Red|Fixed incrementality bug with agents where finalizing and then freezing would cause some unresolved externals.}}&lt;br /&gt;
* compiler: Don't do an expensive degree 6 if assertion level or similar project settings have changed.&lt;br /&gt;
* studio: Decreased amount of created GDI objects on windows in some grids.&lt;br /&gt;
* studio: Fixed a problem with externals in the project settings.&lt;br /&gt;
* studio: Fixed viewpoint handling for assemblies&lt;br /&gt;
* studio: Fixed output to file redirection in the process library on windows.&lt;br /&gt;
* studio: Fixed samples that would not compile.&lt;br /&gt;
* compiler: Fixed a crash if a library without an UUID is used.&lt;br /&gt;
* compiler: Fixed a problem that classes that were not visible before did not get compiled when they were made visible.&lt;br /&gt;
* compiler: Fixed CECIL name if there is a renaming specified in the visible clause.&lt;br /&gt;
* compiler: Fixed VTCT error was not detected if a prefix/renaming changed on an assembly or library.&lt;br /&gt;
* vision2: Fixed bug when setting a pixmap on a menu entry which has a submenu, the submenu would disappear.&lt;br /&gt;
* compiler: Fixed a bug in the check if local assemblies are present.&lt;br /&gt;
* compiler: Fixed some problems with sub clusters of overrides.&lt;br /&gt;
* compiler: Interpolate environment variables also in metadata cache path specified on the command line.&lt;br /&gt;
* compiler: Fixed some bugs in the documentation generation related to sub clusters.&lt;br /&gt;
* compiler: Option changes always led to an expensive degree 6 even if a fast degree 6 would have been enough.&lt;br /&gt;
&lt;br /&gt;
===User changes===&lt;br /&gt;
* base: {{Red|EXECUTION_ENVIRONMENT.get will only retrieve environment variable. It won't retrieve a value from the registry key on Windows (from HKLM\Software\ISE\Eiffelxx\app_name). This also means that MELT_PATH on Windows cannot be set in registry; this is not really a problem since now you do not need to set it since the W_code knows where to find it.}}&lt;br /&gt;
&lt;br /&gt;
===Developer changes===&lt;br /&gt;
* cli_debugger is now under framework, and the corresponding clib has to be compiled.&lt;br /&gt;
* New delivery scripts on unix will now compress packages using bzip2 as they are about 30% smaller than the packages build with gzip.&lt;br /&gt;
* The eifinit/studio folder has now been moved into studio/eifinit&lt;br /&gt;
* build has been renamed into esbuilder&lt;br /&gt;
* vision2_tour has been renamed into vision2_demo&lt;br /&gt;
* Possibility to build a delivery which fits into the unix directory layout.&lt;br /&gt;
* Use the normal HASH_TABLE in the compiler.&lt;br /&gt;
* ID_AS does no longer inherit from STRING, instead it has a name_id and the string is stored in NAMES_HEAP&lt;br /&gt;
* Added additional applicable inspect-able types to VOMB1 error help text.&lt;br /&gt;
===Road map to ISO Eiffel===&lt;br /&gt;
[[Language_road_map|(Under construction)]]&lt;/div&gt;</summary>
		<author><name>Seilerm</name></author>	</entry>

	<entry>
		<id>https://dev.eiffel.com/index.php?title=Talk:Agent_problems&amp;diff=8086</id>
		<title>Talk:Agent problems</title>
		<link rel="alternate" type="text/html" href="https://dev.eiffel.com/index.php?title=Talk:Agent_problems&amp;diff=8086"/>
				<updated>2007-04-12T16:45:59Z</updated>
		
		<summary type="html">&lt;p&gt;Seilerm: /* Is CAT Call */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Is CAT Call ==&lt;br /&gt;
&lt;br /&gt;
'''--[[User:Schoelle|Schoelle]] 09:26, 21 November 2006 (CET)'''&lt;br /&gt;
&lt;br /&gt;
First comment: I assume you are missing a 'l_f := f'. &lt;br /&gt;
&lt;br /&gt;
Second comment: this is a well known CAT call, caused by the (unsound) inheritance relation 'X[A] is subtype of X[B]' if 'A is subtype of B'. &lt;br /&gt;
&lt;br /&gt;
'''--[[User:konradm|konradm]]'''&lt;br /&gt;
&lt;br /&gt;
This article is in a very early state, so don't bother commenting to much on it. The intention is to list all the problems of the mechanism. Especially the fact that one has to type in a whole lot of type information for very little guarantees from the type system.&lt;br /&gt;
&lt;br /&gt;
I am aware that I am not the first one to be aware of this problem. But I am not sure whether this problem is revered to as a CAT call. When it is, and when the new CAT call solution will indeed be implemented, what are the consequences? You can only make agents to features with arguments of detachable type?&lt;br /&gt;
&lt;br /&gt;
--[[User:Ericb|Ericb]] 17:36, 11 April 2007 (CEST): I tried to compiled this code with Gobo's gec/gelint and I got this error:&lt;br /&gt;
&lt;br /&gt;
 [CATCALL] class FOO (10,14): type 'TUPLE' of actual argument #1 does not conform&lt;br /&gt;
 to type 'TUPLE [B]' of formal argument in feature `item' in class 'FUNCTION [A,&lt;br /&gt;
 TUPLE [B], C]'&lt;br /&gt;
&lt;br /&gt;
'''--[[User:Manus|manus]] 19:41, 11 April 2007 (CEST)''' Which options did you use and which rules of ECMA is supposed to trigger this?&lt;br /&gt;
&lt;br /&gt;
--[[User:Ericb|Ericb]] 23:44, 11 April 2007 (CEST): I ran gec with the default options. If I remember correctly ECMA says that either the compiler should report CAT-calls at compile time, or an exception should be raised at run-time. Gec chose the first alternative using the dynamic type set mechanism as a means to achieve that. The dynamic type set of `l_f' contains only one type: FUNCTION [A, TUPLE [B], C]. This is what I explicitly passed as argument to `foo' in the small program that I tried to compile with gec. So for that target type, the expected argument type for the call to `item' is TUPLE [B]. But what we get is an instance of TUPLE.&lt;br /&gt;
&lt;br /&gt;
--[[User:Seilerm|Seilerm]] 01:55, 12 April 2007 (CEST)&lt;br /&gt;
Is there a plan to prevent this statically from happening?&lt;br /&gt;
&lt;br /&gt;
--[[User:Ericb|Ericb]] 08:11, 12 April 2007 (CEST): gec/gelint do that statically (i.e. at compilation time).&lt;br /&gt;
&lt;br /&gt;
--[[User:Seilerm|Seilerm]] 18:45, 12 April 2007 (CEST)&lt;br /&gt;
I was looking for more information about this. I haven't found anything on gobosoft.com (under construction so far :-). Anyway, the thing is that I thought it's not possible to do this analysis without false positives (or not reporting all CAT calls). I have this from another page which Matthias wrote ([[DynamicTypeSet]]). Is it ok if I would summarize this algorithm as stripped down program execution (not taking into account branches, etc.) which has to know the entire system?&lt;/div&gt;</summary>
		<author><name>Seilerm</name></author>	</entry>

	<entry>
		<id>https://dev.eiffel.com/index.php?title=Talk:Agent_problems&amp;diff=8077</id>
		<title>Talk:Agent problems</title>
		<link rel="alternate" type="text/html" href="https://dev.eiffel.com/index.php?title=Talk:Agent_problems&amp;diff=8077"/>
				<updated>2007-04-11T23:55:56Z</updated>
		
		<summary type="html">&lt;p&gt;Seilerm: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Is CAT Call ==&lt;br /&gt;
&lt;br /&gt;
'''--[[User:Schoelle|Schoelle]] 09:26, 21 November 2006 (CET)'''&lt;br /&gt;
&lt;br /&gt;
First comment: I assume you are missing a 'l_f := f'. &lt;br /&gt;
&lt;br /&gt;
Second comment: this is a well known CAT call, caused by the (unsound) inheritance relation 'X[A] is subtype of X[B]' if 'A is subtype of B'. &lt;br /&gt;
&lt;br /&gt;
'''--[[User:konradm|konradm]]'''&lt;br /&gt;
&lt;br /&gt;
This article is in a very early state, so don't bother commenting to much on it. The intention is to list all the problems of the mechanism. Especially the fact that one has to type in a whole lot of type information for very little guarantees from the type system.&lt;br /&gt;
&lt;br /&gt;
I am aware that I am not the first one to be aware of this problem. But I am not sure whether this problem is revered to as a CAT call. When it is, and when the new CAT call solution will indeed be implemented, what are the consequences? You can only make agents to features with arguments of detachable type?&lt;br /&gt;
&lt;br /&gt;
--[[User:Ericb|Ericb]] 17:36, 11 April 2007 (CEST): I tried to compiled this code with Gobo's gec/gelint and I got this error:&lt;br /&gt;
&lt;br /&gt;
 [CATCALL] class FOO (10,14): type 'TUPLE' of actual argument #1 does not conform&lt;br /&gt;
 to type 'TUPLE [B]' of formal argument in feature `item' in class 'FUNCTION [A,&lt;br /&gt;
 TUPLE [B], C]'&lt;br /&gt;
&lt;br /&gt;
'''--[[User:Manus|manus]] 19:41, 11 April 2007 (CEST)''' Which options did you use and which rules of ECMA is supposed to trigger this?&lt;br /&gt;
&lt;br /&gt;
--[[User:Ericb|Ericb]] 23:44, 11 April 2007 (CEST): I ran gec with the default options. If I remember correctly ECMA says that either the compiler should report CAT-calls at compile time, or an exception should be raised at run-time. Gec chose the first alternative using the dynamic type set mechanism as a means to achieve that. The dynamic type set of `l_f' contains only one type: FUNCTION [A, TUPLE [B], C]. This is what I explicitly passed as argument to `foo' in the small program that I tried to compile with gec. So for that target type, the expected argument type for the call to `item' is TUPLE [B]. But what we get is an instance of TUPLE.&lt;br /&gt;
&lt;br /&gt;
--[[User:Seilerm|Seilerm]] 01:55, 12 April 2007 (CEST)&lt;br /&gt;
Is there a plan to prevent this statically from happening?&lt;/div&gt;</summary>
		<author><name>Seilerm</name></author>	</entry>

	<entry>
		<id>https://dev.eiffel.com/index.php?title=Preventing_CAT_calls_in_Generics&amp;diff=7879</id>
		<title>Preventing CAT calls in Generics</title>
		<link rel="alternate" type="text/html" href="https://dev.eiffel.com/index.php?title=Preventing_CAT_calls_in_Generics&amp;diff=7879"/>
				<updated>2007-04-08T21:11:56Z</updated>
		
		<summary type="html">&lt;p&gt;Seilerm: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Category:ECMA]]&lt;br /&gt;
{{Warning|'''Warning''': Article under development}}&lt;br /&gt;
&lt;br /&gt;
==Introduction==&lt;br /&gt;
&lt;br /&gt;
The problem with the way generics are implemented in Eiffel right now is that CAT calls can occur.&lt;br /&gt;
&amp;lt;e&amp;gt;&lt;br /&gt;
class PERSON&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
class STUDENT&lt;br /&gt;
inherit&lt;br /&gt;
 PERSON&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
class EMPLOYEE&lt;br /&gt;
inherit&lt;br /&gt;
 PERSON&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
class EMPLOYED_STUDENT&lt;br /&gt;
inherit&lt;br /&gt;
 EMPLOYEE&lt;br /&gt;
 STUDENT&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;
  l_person: PERSON&lt;br /&gt;
  l_student: STUDENT&lt;br /&gt;
  l_any_stack: STACK [PERSON]&lt;br /&gt;
  l_integer_stack: STACK [STUDENT]&lt;br /&gt;
do&lt;br /&gt;
  l_person_stack := l_student_stack -- line 1&lt;br /&gt;
  l_person_stack.put (l_person) -- line 2&lt;br /&gt;
  l_student := l_student_stack.item -- line 3&lt;br /&gt;
&amp;lt;/e&amp;gt;&lt;br /&gt;
Currently no static check will prohibit you from writing things like this. At runtime on ''line 2'' the first CAT call occurs, which most likely wont do any harm to a list. But the object returned by &amp;lt;e&amp;gt;item&amp;lt;/e&amp;gt; on ''line 3'' is not of type &amp;lt;e&amp;gt;STUDENT&amp;lt;/e&amp;gt; but of type &amp;lt;e&amp;gt;PERSON&amp;lt;/e&amp;gt; and at least now we have a serious problem if one invokes features specific to a student on &amp;lt;e&amp;gt;l_student&amp;lt;/e&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
The issue is that the &amp;lt;e&amp;gt;put&amp;lt;/e&amp;gt; feature of &amp;lt;e&amp;gt;l_person_stack&amp;lt;/e&amp;gt; allows you to put objects of type &amp;lt;e&amp;gt;PERSON&amp;lt;/e&amp;gt; on the stack even though the actual type of the attached object is &amp;lt;e&amp;gt;STACK [STUDENT]&amp;lt;/e&amp;gt; and is referenced by &amp;lt;e&amp;gt;l_student_stack&amp;lt;/e&amp;gt; whose &amp;lt;e&amp;gt;item&amp;lt;/e&amp;gt; feature guarantees, that the returned object will be of type &amp;lt;e&amp;gt;STUDENT&amp;lt;/e&amp;gt;.&lt;br /&gt;
This solution will now extend the type system and the generic derivation of Eiffel in such away, that the type of a formal occurring as an argument in a feature declaration and the type of a formal occurring as a result type can be set independently. The type system will be extended with rules which allow only assignments between generic types if it cannot possibly lead to problems like the one mentioned above.&lt;br /&gt;
&lt;br /&gt;
== Syntax ==&lt;br /&gt;
&lt;br /&gt;
LIST [G] can be declared in the following way:&lt;br /&gt;
&amp;lt;e&amp;gt;&lt;br /&gt;
l_list: LIST [PERSON..EXMLPOYED_STUDENT]&lt;br /&gt;
&amp;lt;/e&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;e&amp;gt;LIST[A]&amp;lt;/e&amp;gt; is a shorthand for &amp;lt;e&amp;gt;LIST[A..A]&amp;lt;/e&amp;gt;.&lt;br /&gt;
&amp;lt;e&amp;gt;LIST[A..]&amp;lt;/e&amp;gt; is also a possible syntax.&lt;br /&gt;
&lt;br /&gt;
Another syntax could look as follows:&lt;br /&gt;
&amp;lt;e&amp;gt;&lt;br /&gt;
&amp;lt;type_for_arguments&amp;gt;:&amp;lt;type_for_return_types&amp;gt;&lt;br /&gt;
&amp;lt;/e&amp;gt;&lt;br /&gt;
This would more resemble an actual generated signature of a feature which looks initially like&lt;br /&gt;
&amp;lt;e&amp;gt;&lt;br /&gt;
class EXAMPLE [G]&lt;br /&gt;
feature&lt;br /&gt;
  example (a_g: G): G&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/e&amp;gt;&lt;br /&gt;
&lt;br /&gt;
A type declaration with this syntax would look like:&lt;br /&gt;
&amp;lt;e&amp;gt;&lt;br /&gt;
local&lt;br /&gt;
 l_example: EXAMPLE [EMLPOYED_STYDENT: STUDENT]&lt;br /&gt;
 l_employed_student: EMPLOYED_STUDENT&lt;br /&gt;
 l_person: PERSON&lt;br /&gt;
do&lt;br /&gt;
 -- l_example.example (a_g: EMPLOYED_STUDENT): STUDENT &lt;br /&gt;
  l_person := l_example.example (l_employed_student) -- valid&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/e&amp;gt;&lt;br /&gt;
&amp;lt;e&amp;gt;LIST[:A]&amp;lt;/e&amp;gt; is the equivalent to &amp;lt;e&amp;gt;LIST[A..]&amp;lt;/e&amp;gt;.&lt;br /&gt;
&amp;lt;e&amp;gt;LIST[A]&amp;lt;/e&amp;gt; is a shorthand for &amp;lt;e&amp;gt;LIST[A: A]&amp;lt;/e&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
But let's stick with the initial syntax for now.&lt;br /&gt;
&lt;br /&gt;
== Semantics ==&lt;br /&gt;
&lt;br /&gt;
As we already pointed out, this solution is an extension to the type system. It helps you to proper derive an interface of a generic type.&lt;br /&gt;
For example an actual type parameter for G in &amp;lt;e&amp;gt;LIST [G]&amp;lt;/e&amp;gt; is PERSON..EMPLOYED_STUDENT.&lt;br /&gt;
The interface generated by this derivation is simply that the first type (PERSON) is taken wherever G occurs as a return type.&lt;br /&gt;
The second type (EMPLOYED_STUDENT) is taken wherever G occurs as an argument type.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;e&amp;gt;&lt;br /&gt;
(generic derived) class LIST[PERSON..EMPLOYED_STUDENT]&lt;br /&gt;
&lt;br /&gt;
  put (v: EMPLOYED_STUDENT)&lt;br /&gt;
  &lt;br /&gt;
  item: PERSON&lt;br /&gt;
&amp;lt;/e&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If we encounter a form like LIST [A..] it simply means that no feature which has the formal in the argument can be called.&lt;br /&gt;
&lt;br /&gt;
{{Note| Why do we need that?&lt;br /&gt;
We want to ensure that one has a read only list. One cannot use a &amp;lt;e&amp;gt;LIST [ANY..NONE]&amp;lt;/e&amp;gt; because one would not be allowed to assign a &amp;lt;e&amp;gt;LIST [INTEGER]&amp;lt;/e&amp;gt; to it. This is because one can put Void into a list of type &amp;lt;e&amp;gt;LIST [ANY..NONE]&amp;lt;/e&amp;gt;, which is invalid for a list of integer as &amp;lt;e&amp;gt;INTEGER&amp;lt;/e&amp;gt; is expanded.}}&lt;br /&gt;
&lt;br /&gt;
== Validity ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;e&amp;gt;LIST[&amp;lt;first_type&amp;gt;..&amp;lt;second_type&amp;gt;]&amp;lt;/e&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Such a generic derivation is valid if:&lt;br /&gt;
* 1: the second type conforms to the constraint of the formal.&lt;br /&gt;
* 2: the second type conforms to the first type&lt;br /&gt;
&lt;br /&gt;
==Conformance Rules==&lt;br /&gt;
&lt;br /&gt;
We make another more abstract example to illustrate the conformance rules. They can easily be derived by applying the fact that its save for argument types to be contra-variant and for result types to be covariant. This is actually a very important as it is the basis where the conformance is based uppon.&lt;br /&gt;
&lt;br /&gt;
Interface conformance rule:&lt;br /&gt;
 An interface B is conform to an interface A if for every feature f_a in A &lt;br /&gt;
 there is a corresponding feature f_b available from B and for each feature &lt;br /&gt;
 the arguments of f_a conform to those of f_b and the result type of f_b is &lt;br /&gt;
 conform to the one of f_a.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;e&amp;gt;&lt;br /&gt;
local&lt;br /&gt;
  l_a: A&lt;br /&gt;
  l_b: B&lt;br /&gt;
do&lt;br /&gt;
    -- is legal if the interface conformance rule holds&lt;br /&gt;
  l_a := l_b&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/e&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Example of an actual generic conformance table===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;e&amp;gt;&lt;br /&gt;
class T &lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
class U &lt;br /&gt;
inherit T &lt;br /&gt;
  -- no covariant feature redefinition&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/e&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
| conforms to&lt;br /&gt;
! LIST [ANY]&lt;br /&gt;
! LIST [T]&lt;br /&gt;
! LIST [T..NONE]&lt;br /&gt;
! LIST [ANY..T]&lt;br /&gt;
! LIST [U]&lt;br /&gt;
|-&lt;br /&gt;
! LIST [ANY]&lt;br /&gt;
| true&lt;br /&gt;
| false&lt;br /&gt;
| false&lt;br /&gt;
| true&lt;br /&gt;
| false&lt;br /&gt;
|-&lt;br /&gt;
! LIST [T]&lt;br /&gt;
| false&lt;br /&gt;
| true&lt;br /&gt;
| true&lt;br /&gt;
| true&lt;br /&gt;
| false&lt;br /&gt;
|-&lt;br /&gt;
! LIST [T..NONE]&lt;br /&gt;
| false&lt;br /&gt;
| false&lt;br /&gt;
| true&lt;br /&gt;
| false&lt;br /&gt;
| false&lt;br /&gt;
|-&lt;br /&gt;
! LIST [ANY..T]&lt;br /&gt;
| false&lt;br /&gt;
| false &lt;br /&gt;
| false &lt;br /&gt;
| true&lt;br /&gt;
| false&lt;br /&gt;
|-&lt;br /&gt;
! LIST [U]&lt;br /&gt;
| false&lt;br /&gt;
| '''false'''&lt;br /&gt;
| true&lt;br /&gt;
| false&lt;br /&gt;
| true&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;e&amp;gt;&lt;br /&gt;
  -- legal&lt;br /&gt;
T := LIST [T..NONE] .item&lt;br /&gt;
LIST [T..NONE] .put (Void)&lt;br /&gt;
&lt;br /&gt;
  -- illegal&lt;br /&gt;
U := LIST [T..NONE] .item&lt;br /&gt;
LIST [T..NONE] .put (T)&lt;br /&gt;
&lt;br /&gt;
  -- legal&lt;br /&gt;
LIST [ANY..T] .put (T)&lt;br /&gt;
LIST [ANY..T] .put (U)&lt;br /&gt;
ANY := LIST [ANY..T] .item&lt;br /&gt;
&lt;br /&gt;
  -- illegal&lt;br /&gt;
LIST [ANY..T] .put (ANY)&lt;br /&gt;
T := LIST [ANY..T] .item&lt;br /&gt;
&amp;lt;/e&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Agents==&lt;br /&gt;
&lt;br /&gt;
The neat thing about this extension is, that there is no need to cut down the expressiveness of the agent mechanism to make them perfectly save to use with full support for all legal situations. &lt;br /&gt;
&lt;br /&gt;
Procedure class:&lt;br /&gt;
&amp;lt;e&amp;gt;&lt;br /&gt;
class PROCEDURE [BASE_TYPE, OPEN_ARGS -&amp;gt; TUPLE []]&lt;br /&gt;
    -- Signature of call is generated by the compiler. To visualize this we add _reflected to the argument tuple.&lt;br /&gt;
  call (args: OPEN_ARGS_reflected)&lt;br /&gt;
    do end&lt;br /&gt;
&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/e&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Agent example ===&lt;br /&gt;
&lt;br /&gt;
Type declaration:&lt;br /&gt;
&amp;lt;e&amp;gt;&lt;br /&gt;
an_agent: PROCEDURE [ANY..NONE, TUPLE..TUPLE [ANY..T]]  --&amp;gt; like agent (T)&lt;br /&gt;
  -- This signature promises that the caller is going to give at least one argument which conforms to T.&lt;br /&gt;
  -- Note: The signature for the call routine has to be reflected by the compiler into : TUPLE [T..]..NONE&lt;br /&gt;
  --       This is because we can give a tuple containing more than one element and it element type has to conform to T.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
  -- legal&lt;br /&gt;
an_agent.call ([T])&lt;br /&gt;
an_agent.call ([T, ...])&lt;br /&gt;
an_agent.call ([U, ...])&lt;br /&gt;
&lt;br /&gt;
  -- illegal&lt;br /&gt;
an_agent.call ([])&lt;br /&gt;
&amp;lt;/e&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Instantiation:&lt;br /&gt;
&amp;lt;e&amp;gt;&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;
&lt;br /&gt;
  -- legal&lt;br /&gt;
an_agent := agent_empty&lt;br /&gt;
an_agent := agent_any&lt;br /&gt;
an_agent := agent_t&lt;br /&gt;
&lt;br /&gt;
  -- illegal&lt;br /&gt;
an_agent := agent_u&lt;br /&gt;
&amp;lt;/e&amp;gt;&lt;br /&gt;
&lt;br /&gt;
There might be a concern about the fact that the compiler generates the signature of the call method. But I think that its not wrong to have compiler support for agents, as they are such a fundamental core concept that is simply important that one could sacrifice expressive power or type safety just to avoid explicit support from the compiler.&lt;br /&gt;
&lt;br /&gt;
=== How to generate the call signature for a given agent type ===&lt;br /&gt;
&lt;br /&gt;
To build the signature of the call routine one simply takes he second parameter and move it as the first. As the second parameter we put NONE.&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&amp;lt;e&amp;gt;&lt;br /&gt;
TUPLE [ANY..T, ANY..U, ANY..V]&lt;br /&gt;
&amp;lt;/e&amp;gt;&lt;br /&gt;
&lt;br /&gt;
leads to&lt;br /&gt;
&amp;lt;e&amp;gt;&lt;br /&gt;
TUPLE [T..,U..,V..]&lt;br /&gt;
&amp;lt;/e&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This basically states that all I want is to be able to read an object of at least type T, U, V and that I'm not going to put anything into this tuple.&lt;/div&gt;</summary>
		<author><name>Seilerm</name></author>	</entry>

	<entry>
		<id>https://dev.eiffel.com/index.php?title=Preventing_CAT_calls_in_Generics&amp;diff=7875</id>
		<title>Preventing CAT calls in Generics</title>
		<link rel="alternate" type="text/html" href="https://dev.eiffel.com/index.php?title=Preventing_CAT_calls_in_Generics&amp;diff=7875"/>
				<updated>2007-04-08T00:21:31Z</updated>
		
		<summary type="html">&lt;p&gt;Seilerm: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Category:ECMA]]&lt;br /&gt;
{{Warning|'''Warning''': Article under development}}&lt;br /&gt;
&lt;br /&gt;
==Introduction==&lt;br /&gt;
&lt;br /&gt;
The problem with the way generics are implemented in Eiffel right now is that CAT calls can occur.&lt;br /&gt;
&amp;lt;e&amp;gt;&lt;br /&gt;
class PERSON&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
class STUDENT&lt;br /&gt;
inherit&lt;br /&gt;
 PERSON&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
class EMPLOYEE&lt;br /&gt;
inherit&lt;br /&gt;
 PERSON&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
class EMPLOYED_STUDENT&lt;br /&gt;
inherit&lt;br /&gt;
 EMPLOYEE&lt;br /&gt;
 STUDENT&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;
  l_person: PERSON&lt;br /&gt;
  l_student: STUDENT&lt;br /&gt;
  l_any_stack: STACK [PERSON]&lt;br /&gt;
  l_integer_stack: STACK [STUDENT]&lt;br /&gt;
do&lt;br /&gt;
  l_person_stack := l_student_stack -- line 1&lt;br /&gt;
  l_person_stack.put (l_person) -- line 2&lt;br /&gt;
  l_student := l_student_stack.item -- line 3&lt;br /&gt;
&amp;lt;/e&amp;gt;&lt;br /&gt;
Currently no static check will prohibit you from writing things like this. At runtime on ''line 2'' the first CAT call occurs, which most likely wont do any harm to a list. But the object returned by &amp;lt;e&amp;gt;item&amp;lt;/e&amp;gt; on ''line 3'' is not of type &amp;lt;e&amp;gt;STUDENT&amp;lt;/e&amp;gt; but of type &amp;lt;e&amp;gt;PERSON&amp;lt;/e&amp;gt; and at least now we have a serious problem if one invokes features specific to a student on &amp;lt;e&amp;gt;l_student&amp;lt;/e&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
The issue is that the &amp;lt;e&amp;gt;put&amp;lt;/e&amp;gt; feature of &amp;lt;e&amp;gt;l_person_stack&amp;lt;/e&amp;gt; allows you to put objects of type &amp;lt;e&amp;gt;PERSON&amp;lt;/e&amp;gt; on the stack even though the actual type of the attached object is &amp;lt;e&amp;gt;STACK [STUDENT]&amp;lt;/e&amp;gt; and is referenced by &amp;lt;e&amp;gt;l_integer_stack&amp;lt;/e&amp;gt; whose item feature guarantees, that the returned object will be of type &amp;lt;e&amp;gt;STUDENT&amp;lt;/e&amp;gt;.&lt;br /&gt;
This solution will now extend the type system and the generic derivation of Eiffel in such away, that the type of a formal occurring as an argument in a feature declaration and the type of a formal occurring as a result type can be set independently. The type system will be extended with rules which allow only assignments between generic types if it cannot possibly lead to problems like the one mentioned above.&lt;br /&gt;
&lt;br /&gt;
== Syntax ==&lt;br /&gt;
&lt;br /&gt;
LIST [G] can be declared in the following way:&lt;br /&gt;
&amp;lt;e&amp;gt;&lt;br /&gt;
l_list: LIST [PERSON..EXMLPOYED_STUDENT]&lt;br /&gt;
&amp;lt;/e&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;e&amp;gt;LIST[A]&amp;lt;/e&amp;gt; is a shorthand for &amp;lt;e&amp;gt;LIST[A..A]&amp;lt;/e&amp;gt;.&lt;br /&gt;
&amp;lt;e&amp;gt;LIST[A..]&amp;lt;/e&amp;gt; is also a possible syntax.&lt;br /&gt;
&lt;br /&gt;
Another syntax could look as follows:&lt;br /&gt;
&amp;lt;e&amp;gt;&lt;br /&gt;
&amp;lt;type_for_arguments&amp;gt;:&amp;lt;type_for_return_types&amp;gt;&lt;br /&gt;
&amp;lt;/e&amp;gt;&lt;br /&gt;
This would more resemble an actual generated signature of a feature which looks initially like&lt;br /&gt;
&amp;lt;e&amp;gt;&lt;br /&gt;
class EXAMPLE [G]&lt;br /&gt;
feature&lt;br /&gt;
  example (a_g: G): G&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/e&amp;gt;&lt;br /&gt;
&lt;br /&gt;
A type declaration with this syntax would look like:&lt;br /&gt;
&amp;lt;e&amp;gt;&lt;br /&gt;
local&lt;br /&gt;
 l_example: EXAMPLE [EMLPOYED_STYDENT: STUDENT]&lt;br /&gt;
 l_employed_student: EMPLOYED_STUDENT&lt;br /&gt;
 l_person: PERSON&lt;br /&gt;
do&lt;br /&gt;
 -- l_example.example (a_g: EMPLOYED_STUDENT): STUDENT &lt;br /&gt;
  l_person := l_example.example (l_employed_student) -- valid&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/e&amp;gt;&lt;br /&gt;
&amp;lt;e&amp;gt;LIST[:A]&amp;lt;/e&amp;gt; is the equivalent to &amp;lt;e&amp;gt;LIST[A..]&amp;lt;/e&amp;gt;.&lt;br /&gt;
&amp;lt;e&amp;gt;LIST[A]&amp;lt;/e&amp;gt; is a shorthand for &amp;lt;e&amp;gt;LIST[A: A]&amp;lt;/e&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
But let's stick with the initial syntax for now.&lt;br /&gt;
&lt;br /&gt;
== Semantics ==&lt;br /&gt;
&lt;br /&gt;
As we already pointed out, this solution is an extension to the type system. It helps you to proper derive an interface of a generic type.&lt;br /&gt;
For example an actual type parameter for G in &amp;lt;e&amp;gt;LIST [G]&amp;lt;/e&amp;gt; is PERSON..EMPLOYED_STUDENT.&lt;br /&gt;
The interface generated by this derivation is simply that the first type (PERSON) is taken wherever G occurs as a return type.&lt;br /&gt;
The second type (EMPLOYED_STUDENT) is taken wherever G occurs as an argument type.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;e&amp;gt;&lt;br /&gt;
(generic derived) class LIST[PERSON..EMPLOYED_STUDENT]&lt;br /&gt;
&lt;br /&gt;
  put (v: EMPLOYED_STUDENT)&lt;br /&gt;
  &lt;br /&gt;
  item: PERSON&lt;br /&gt;
&amp;lt;/e&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If we encounter a form like LIST [A..] it simply means that no feature which has the formal in the argument can be called.&lt;br /&gt;
&lt;br /&gt;
{{Note: Why do we need that?&lt;br /&gt;
We wan to ensure that one has a read only list as if we would do &amp;lt;e&amp;gt;LIST [ANY..NONE]&amp;lt;/e&amp;gt; one would not be allowed to assign a &amp;lt;e&amp;gt;LIST [INTEGER]&amp;lt;/e&amp;gt; to it as one can put Void into a list of tyep &amp;lt;e&amp;gt;LIST [ANY..NONE]&amp;lt;/e&amp;gt; which is invalid for a list of integer as &amp;lt;e&amp;gt;INTEGER&amp;lt;/e&amp;gt; is expanded.}}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Validity ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;e&amp;gt;LIST[&amp;lt;first_type&amp;gt;..&amp;lt;second_type&amp;gt;]&amp;lt;/e&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Such a generic derivation is valid if:&lt;br /&gt;
* 1: the second type conforms to the constraint of the formal.&lt;br /&gt;
* 2: the second type conforms to the first type&lt;br /&gt;
&lt;br /&gt;
==Conformance Rules==&lt;br /&gt;
&lt;br /&gt;
We make another more abstract example to illustrate the conformance rules. They can easily be derived by applying the fact that its save for argument types to be covariant and for result types to be contra-variant. This is actually a very important as it is the basis where the conformance is based uppon.&lt;br /&gt;
&lt;br /&gt;
Interface conformance rule:&lt;br /&gt;
 An interface B is conform to an interface A if for every feature f_a in A there is a corresponding feature f_b available from B&lt;br /&gt;
 and for each feature the arguments of f_a conform to those of f_b and the result type of f_b is conform to the one of f_a.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;e&amp;gt;&lt;br /&gt;
local&lt;br /&gt;
  l_a: A&lt;br /&gt;
  l_b: B&lt;br /&gt;
do&lt;br /&gt;
    -- is legal if the interface conformance rule holds&lt;br /&gt;
  l_a := l_b&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/e&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Example of an actual generic conformance table===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;e&amp;gt;&lt;br /&gt;
class T &lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
class U &lt;br /&gt;
inherit T &lt;br /&gt;
  -- no covariant feature redefinition&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/e&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
| conforms to&lt;br /&gt;
! LIST [ANY]&lt;br /&gt;
! LIST [T]&lt;br /&gt;
! LIST [T..NONE]&lt;br /&gt;
! LIST [ANY..T]&lt;br /&gt;
! LIST [U]&lt;br /&gt;
|-&lt;br /&gt;
! LIST [ANY]&lt;br /&gt;
| true&lt;br /&gt;
| false&lt;br /&gt;
| false&lt;br /&gt;
| true&lt;br /&gt;
| false&lt;br /&gt;
|-&lt;br /&gt;
! LIST [T]&lt;br /&gt;
| false&lt;br /&gt;
| true&lt;br /&gt;
| true&lt;br /&gt;
| true&lt;br /&gt;
| false&lt;br /&gt;
|-&lt;br /&gt;
! LIST [T..NONE]&lt;br /&gt;
| false&lt;br /&gt;
| false&lt;br /&gt;
| true&lt;br /&gt;
| false&lt;br /&gt;
| false&lt;br /&gt;
|-&lt;br /&gt;
! LIST [ANY..T]&lt;br /&gt;
| false&lt;br /&gt;
| false &lt;br /&gt;
| false &lt;br /&gt;
| true&lt;br /&gt;
| false&lt;br /&gt;
|-&lt;br /&gt;
! LIST [U]&lt;br /&gt;
| false&lt;br /&gt;
| '''false'''&lt;br /&gt;
| true&lt;br /&gt;
| false&lt;br /&gt;
| true&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;e&amp;gt;&lt;br /&gt;
  -- legal&lt;br /&gt;
T := LIST [T..NONE] .item&lt;br /&gt;
LIST [T..NONE] .put (Void)&lt;br /&gt;
&lt;br /&gt;
  -- illegal&lt;br /&gt;
U := LIST [T..NONE] .item&lt;br /&gt;
LIST [T..NONE] .put (T)&lt;br /&gt;
&lt;br /&gt;
  -- legal&lt;br /&gt;
LIST [ANY..T] .put (T)&lt;br /&gt;
LIST [ANY..T] .put (U)&lt;br /&gt;
ANY := LIST [ANY..T] .item&lt;br /&gt;
&lt;br /&gt;
  -- illegal&lt;br /&gt;
LIST [ANY..T] .put (ANY)&lt;br /&gt;
T := LIST [ANY..T] .item&lt;br /&gt;
&amp;lt;/e&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Agents==&lt;br /&gt;
&lt;br /&gt;
The neat thing about this extension is, that there is no need to cut down the expressiveness of the agent mechanism to make them perfectly save to use with full support for all legal situations. &lt;br /&gt;
&lt;br /&gt;
Procedure class:&lt;br /&gt;
&amp;lt;e&amp;gt;&lt;br /&gt;
class PROCEDURE [BASE_TYPE, OPEN_ARGS -&amp;gt; TUPLE []]&lt;br /&gt;
    -- Signature of call is generated by the compiler. To visualize this we add _reflected to the argument tuple.&lt;br /&gt;
  call (args: OPEN_ARGS_reflected)&lt;br /&gt;
    do end&lt;br /&gt;
&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/e&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Agent example ===&lt;br /&gt;
&lt;br /&gt;
Type declaration:&lt;br /&gt;
&amp;lt;e&amp;gt;&lt;br /&gt;
an_agent: PROCEDURE [ANY..NONE, TUPLE..TUPLE [ANY..T]]  --&amp;gt; like agent (T)&lt;br /&gt;
  -- This signature promises that the caller is going to give at least one argument which conforms to T.&lt;br /&gt;
  -- Note: The signature for the call routine has to be reflected by the compiler into : TUPLE [T..]..NONE&lt;br /&gt;
  --       This is because we can give a tuple containing more than one element and it element type has to conform to T.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
  -- legal&lt;br /&gt;
an_agent.call ([T])&lt;br /&gt;
an_agent.call ([T, ...])&lt;br /&gt;
an_agent.call ([U, ...])&lt;br /&gt;
&lt;br /&gt;
  -- illegal&lt;br /&gt;
an_agent.call ([])&lt;br /&gt;
&amp;lt;/e&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Instantiation:&lt;br /&gt;
&amp;lt;e&amp;gt;&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;
&lt;br /&gt;
  -- legal&lt;br /&gt;
an_agent := agent_empty&lt;br /&gt;
an_agent := agent_any&lt;br /&gt;
an_agent := agent_t&lt;br /&gt;
&lt;br /&gt;
  -- illegal&lt;br /&gt;
an_agent := agent_u&lt;br /&gt;
&amp;lt;/e&amp;gt;&lt;br /&gt;
&lt;br /&gt;
There might be a concern about the fact that the compiler generates the signature of the call method. But I think that its not wrong to have compiler support for agents, as they are such a fundamental core concept that is simply important that one could sacrifice expressive power or type safety just to avoid explicit support from the compiler.&lt;br /&gt;
&lt;br /&gt;
=== How to generate the call signature for a given agent type ===&lt;br /&gt;
&lt;br /&gt;
To build the signature of the call routine one simply takes he second parameter and move it as the first. As the second parameter we put NONE.&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&amp;lt;e&amp;gt;&lt;br /&gt;
TUPLE [ANY..T, ANY..U, ANY..V]&lt;br /&gt;
&amp;lt;/e&amp;gt;&lt;br /&gt;
&lt;br /&gt;
leads to&lt;br /&gt;
&amp;lt;e&amp;gt;&lt;br /&gt;
TUPLE [T..,U..,V..]&lt;br /&gt;
&amp;lt;/e&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This basically states that all I want is to be able to read an object of at least type T, U, V and that I'm not going to put anything into this tuple.&lt;/div&gt;</summary>
		<author><name>Seilerm</name></author>	</entry>

	<entry>
		<id>https://dev.eiffel.com/index.php?title=Preventing_CAT_calls_in_Generics&amp;diff=7874</id>
		<title>Preventing CAT calls in Generics</title>
		<link rel="alternate" type="text/html" href="https://dev.eiffel.com/index.php?title=Preventing_CAT_calls_in_Generics&amp;diff=7874"/>
				<updated>2007-04-08T00:20:02Z</updated>
		
		<summary type="html">&lt;p&gt;Seilerm: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Category:ECMA]]&lt;br /&gt;
{{Warning|'''Warning''': Article under development}}&lt;br /&gt;
&lt;br /&gt;
==Introduction==&lt;br /&gt;
&lt;br /&gt;
The problem with the way generics are implemented in Eiffel right now is that CAT calls can occur.&lt;br /&gt;
&amp;lt;e&amp;gt;&lt;br /&gt;
class PERSON&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
class STUDENT&lt;br /&gt;
inherit&lt;br /&gt;
 PERSON&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
class EMPLOYEE&lt;br /&gt;
inherit&lt;br /&gt;
 PERSON&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
class EMPLOYED_STUDENT&lt;br /&gt;
inherit&lt;br /&gt;
 EMPLOYEE&lt;br /&gt;
 STUDENT&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;
  l_person: PERSON&lt;br /&gt;
  l_student: STUDENT&lt;br /&gt;
  l_any_stack: STACK [PERSON]&lt;br /&gt;
  l_integer_stack: STACK [STUDENT]&lt;br /&gt;
do&lt;br /&gt;
  l_person_stack := l_student_stack -- line 1&lt;br /&gt;
  l_person_stack.put (l_person) -- line 2&lt;br /&gt;
  l_student := l_student_stack.item -- line 3&lt;br /&gt;
&amp;lt;/e&amp;gt;&lt;br /&gt;
Currently no static check will prohibit you from writing things like this. At runtime on ''line 2'' the first CAT call occurs, which most likely wont do any harm to a list. But the object returned by &amp;lt;e&amp;gt;item&amp;lt;/e&amp;gt; on ''line 3'' is not of type &amp;lt;e&amp;gt;STUDENT&amp;lt;/e&amp;gt; but of type &amp;lt;e&amp;gt;PERSON&amp;lt;/e&amp;gt; and at least now we have a serious problem if one invokes features specific to a student on &amp;lt;e&amp;gt;l_student&amp;lt;/e&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
The issue is that the &amp;lt;e&amp;gt;put&amp;lt;/e&amp;gt; feature of &amp;lt;e&amp;gt;l_person_stack&amp;lt;/e&amp;gt; allows you to put objects of type &amp;lt;e&amp;gt;PERSON&amp;lt;/e&amp;gt; on the stack even though the actual type of the attached object is &amp;lt;e&amp;gt;STACK [STUDENT]&amp;lt;/e&amp;gt; and is referenced by &amp;lt;e&amp;gt;l_integer_stack&amp;lt;/e&amp;gt; whose item feature guarantees, that the returned object will be of type &amp;lt;e&amp;gt;STUDENT&amp;lt;/e&amp;gt;.&lt;br /&gt;
This solution will now extend the type system and the generic derivation of Eiffel in such away, that the type of a formal occurring as an argument in a feature declaration and the type of a formal occurring as a result type can be set independently. The type system will be extended with rules which allow only assignments between generic types if it cannot possibly lead to problems like the one mentioned above.&lt;br /&gt;
&lt;br /&gt;
== Syntax ==&lt;br /&gt;
&lt;br /&gt;
LIST [G] can be declared in the following way:&lt;br /&gt;
&amp;lt;e&amp;gt;&lt;br /&gt;
l_list: LIST [PERSON..EXMLPOYED_STUDENT]&lt;br /&gt;
&amp;lt;/e&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;e&amp;gt;LIST[A]&amp;lt;/e&amp;gt; is a shorthand for &amp;lt;e&amp;gt;LIST[A..A]&amp;lt;/e&amp;gt;.&lt;br /&gt;
&amp;lt;e&amp;gt;LIST[A..]&amp;lt;/e&amp;gt; is also a possible syntax.&lt;br /&gt;
&lt;br /&gt;
Another syntax could look as follows:&lt;br /&gt;
&amp;lt;e&amp;gt;&lt;br /&gt;
&amp;lt;type_for_arguments&amp;gt;:&amp;lt;type_for_return_types&amp;gt;&lt;br /&gt;
&amp;lt;/e&amp;gt;&lt;br /&gt;
This would more resemble an actual generated signature of a feature which looks initially like&lt;br /&gt;
&amp;lt;e&amp;gt;&lt;br /&gt;
class EXAMPLE [G]&lt;br /&gt;
feature&lt;br /&gt;
  example (a_g: G): G&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/e&amp;gt;&lt;br /&gt;
&lt;br /&gt;
A type declaration with this syntax would look like:&lt;br /&gt;
&amp;lt;e&amp;gt;&lt;br /&gt;
local&lt;br /&gt;
 l_example: EXAMPLE [EMLPOYED_STYDENT: STUDENT]&lt;br /&gt;
 l_employed_student: EMPLOYED_STUDENT&lt;br /&gt;
 l_person: PERSON&lt;br /&gt;
do&lt;br /&gt;
 -- l_example.example (a_g: EMPLOYED_STUDENT): STUDENT &lt;br /&gt;
  l_person := l_example.example (l_employed_student) -- valid&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/e&amp;gt;&lt;br /&gt;
&amp;lt;e&amp;gt;LIST[:A]&amp;lt;/e&amp;gt; is the equivalent to &amp;lt;e&amp;gt;LIST[A..]&amp;lt;/e&amp;gt;.&lt;br /&gt;
&amp;lt;e&amp;gt;LIST[A]&amp;lt;/e&amp;gt; is a shorthand for &amp;lt;e&amp;gt;LIST[A: A]&amp;lt;/e&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
But let's stick with the initial syntax for now.&lt;br /&gt;
&lt;br /&gt;
== Semantics ==&lt;br /&gt;
&lt;br /&gt;
As we already pointed out, this solution is an extension to the type system. It helps you to proper derive an interface of a generic type.&lt;br /&gt;
For example an actual type parameter for G in &amp;lt;e&amp;gt;LIST [G]&amp;lt;/e&amp;gt; is PERSON..EMPLOYED_STUDENT.&lt;br /&gt;
The interface generated by this derivation is simply that the first type (PERSON) is taken wherever G occurs as a return type.&lt;br /&gt;
The second type (EMPLOYED_STUDENT) is taken wherever G occurs as an argument type.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;e&amp;gt;&lt;br /&gt;
(generic derived) class LIST[PERSON..EMPLOYED_STUDENT]&lt;br /&gt;
&lt;br /&gt;
  put (v: EMPLOYED_STUDENT)&lt;br /&gt;
  &lt;br /&gt;
  item: PERSON&lt;br /&gt;
&amp;lt;/e&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If we encounter a form like LIST [A..] it simply means that no feature which has the formal in the argument can be called.&lt;br /&gt;
&lt;br /&gt;
{{Note: Why do we need that?&lt;br /&gt;
We wan to ensure that one has a read only list as if we would do &amp;lt;e&amp;gt;LIST [ANY..NONE]&amp;lt;/e&amp;gt; one would not be allowed to assign a &amp;lt;e&amp;gt;LIST [INTEGER]&amp;lt;/e&amp;gt; to it as one can put Void into a list of tyep &amp;lt;e&amp;gt;LIST [ANY..NONE]&amp;lt;/e&amp;gt; which is invalid for a list of integer as &amp;lt;e&amp;gt;INTEGER&amp;lt;/e&amp;gt; is expanded.}}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Validity ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;e&amp;gt;LIST[&amp;lt;first_type&amp;gt;..&amp;lt;second_type&amp;gt;]&amp;lt;/e&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Such a generic derivation is valid if:&lt;br /&gt;
* 1: the second type conforms to the constraint of the formal.&lt;br /&gt;
* 2: the second type conforms to the first type&lt;br /&gt;
&lt;br /&gt;
==Conformance Rules==&lt;br /&gt;
&lt;br /&gt;
We make another more abstract example to illustrate the conformance rules. They can easily be derived by applying the fact that its save for argument types to be covariant and for result types to be contra-variant. This is actually a very important as it is the basis where the conformance is based uppon.&lt;br /&gt;
&lt;br /&gt;
Interface conformance rule:&lt;br /&gt;
 An interface B is conform to an interface A if for every feature f_a in A there is a corresponding feature f_b available from B&lt;br /&gt;
 and for each feature the arguments of f_a conform to those of f_b and the result type of f_b is conform to the one of f_a.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;e&amp;gt;&lt;br /&gt;
local&lt;br /&gt;
  l_a: A&lt;br /&gt;
  l_b: B&lt;br /&gt;
do&lt;br /&gt;
    -- is legal if the interface conformance rule holds&lt;br /&gt;
  l_a := l_b&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/e&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Example of an actual generic conformance table===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;e&amp;gt;&lt;br /&gt;
class T &lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
class U &lt;br /&gt;
inherit T &lt;br /&gt;
  -- no covariant feature redefinition&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/e&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
| conforms to&lt;br /&gt;
! LIST [ANY]&lt;br /&gt;
! LIST [T]&lt;br /&gt;
! LIST [T..NONE]&lt;br /&gt;
! LIST [ANY..T]&lt;br /&gt;
! LIST [U]&lt;br /&gt;
|-&lt;br /&gt;
! LIST [ANY]&lt;br /&gt;
| true&lt;br /&gt;
| false&lt;br /&gt;
| false&lt;br /&gt;
| true&lt;br /&gt;
| false&lt;br /&gt;
|-&lt;br /&gt;
! LIST [T]&lt;br /&gt;
| false&lt;br /&gt;
| true&lt;br /&gt;
| true&lt;br /&gt;
| true&lt;br /&gt;
| false&lt;br /&gt;
|-&lt;br /&gt;
! LIST [T..NONE]&lt;br /&gt;
| false&lt;br /&gt;
| false&lt;br /&gt;
| true&lt;br /&gt;
| false&lt;br /&gt;
| false&lt;br /&gt;
|-&lt;br /&gt;
! LIST [ANY..T]&lt;br /&gt;
| false&lt;br /&gt;
| false &lt;br /&gt;
| false &lt;br /&gt;
| true&lt;br /&gt;
| false&lt;br /&gt;
|-&lt;br /&gt;
! LIST [U]&lt;br /&gt;
| false&lt;br /&gt;
| '''false'''&lt;br /&gt;
| true&lt;br /&gt;
| false&lt;br /&gt;
| true&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;e&amp;gt;&lt;br /&gt;
  -- legal&lt;br /&gt;
T := LIST [T..NONE] .item&lt;br /&gt;
LIST [T..NONE] .put (Void)&lt;br /&gt;
&lt;br /&gt;
  -- illegal&lt;br /&gt;
U := LIST [T..NONE] .item&lt;br /&gt;
LIST [T..NONE] .put (T)&lt;br /&gt;
&lt;br /&gt;
  -- legal&lt;br /&gt;
LIST [ANY..T] .put (T)&lt;br /&gt;
LIST [ANY..T] .put (U)&lt;br /&gt;
ANY := LIST [ANY..T] .item&lt;br /&gt;
&lt;br /&gt;
  -- illegal&lt;br /&gt;
LIST [ANY..T] .put (ANY)&lt;br /&gt;
T := LIST [ANY..T] .item&lt;br /&gt;
&amp;lt;/e&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Agents==&lt;br /&gt;
&lt;br /&gt;
The neat thing about this extension is, that there is no need to cut down the expressiveness of the agent mechanism to make them perfectly save to use with full support for all legal situations. &lt;br /&gt;
&lt;br /&gt;
Procedure class:&lt;br /&gt;
&amp;lt;e&amp;gt;&lt;br /&gt;
class PROCEDURE [BASE_TYPE, OPEN_ARGS -&amp;gt; TUPLE []]&lt;br /&gt;
    -- Signature of call is generated by the compiler. To visualize this we add _reflected to the argument tuple.&lt;br /&gt;
  call (args: OPEN_ARGS_reflected)&lt;br /&gt;
    do end&lt;br /&gt;
&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/e&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==agent (T)==&lt;br /&gt;
&lt;br /&gt;
Type declaration:&lt;br /&gt;
&amp;lt;e&amp;gt;&lt;br /&gt;
an_agent: PROCEDURE [ANY..NONE, TUPLE..TUPLE [ANY..T]]  --&amp;gt; like agent (T)&lt;br /&gt;
  -- This signature promises that the caller is going to give at least one argument which conforms to T.&lt;br /&gt;
  -- Note: The signature for the call routine has to be reflected by the compiler into : TUPLE [T..]..NONE&lt;br /&gt;
  --       This is because we can give a tuple containing more than one element and it element type has to conform to T.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
  -- legal&lt;br /&gt;
an_agent.call ([T])&lt;br /&gt;
an_agent.call ([T, ...])&lt;br /&gt;
an_agent.call ([U, ...])&lt;br /&gt;
&lt;br /&gt;
  -- illegal&lt;br /&gt;
an_agent.call ([])&lt;br /&gt;
&amp;lt;/e&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Instantiation:&lt;br /&gt;
&amp;lt;e&amp;gt;&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;
&lt;br /&gt;
  -- legal&lt;br /&gt;
an_agent := agent_empty&lt;br /&gt;
an_agent := agent_any&lt;br /&gt;
an_agent := agent_t&lt;br /&gt;
&lt;br /&gt;
  -- illegal&lt;br /&gt;
an_agent := agent_u&lt;br /&gt;
&amp;lt;/e&amp;gt;&lt;br /&gt;
&lt;br /&gt;
There might be a concern about the fact that the compiler generates the signature of the call method. But I think that its not wrong to have compiler support for agents, as they are such a fundamental core concept that is simply important that one could sacrifice expressive power or type safety just to avoid explicit support from the compiler.&lt;br /&gt;
&lt;br /&gt;
== How to generate the call signature for a given agent type ==&lt;br /&gt;
&lt;br /&gt;
To build the signature of the call routine one simply takes he second parameter and move it as the first. As the second parameter we put NONE.&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&amp;lt;e&amp;gt;&lt;br /&gt;
TUPLE [ANY..T, ANY..U, ANY..V]&lt;br /&gt;
&amp;lt;/e&amp;gt;&lt;br /&gt;
&lt;br /&gt;
leads to&lt;br /&gt;
&amp;lt;e&amp;gt;&lt;br /&gt;
TUPLE [T..,U..,V..]&lt;br /&gt;
&amp;lt;/e&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This basically states that all I want is to be able to read an object of at least type T, U, V and that I'm not going to put anything into this tuple.&lt;/div&gt;</summary>
		<author><name>Seilerm</name></author>	</entry>

	<entry>
		<id>https://dev.eiffel.com/index.php?title=Preventing_CAT_calls_in_Generics&amp;diff=7873</id>
		<title>Preventing CAT calls in Generics</title>
		<link rel="alternate" type="text/html" href="https://dev.eiffel.com/index.php?title=Preventing_CAT_calls_in_Generics&amp;diff=7873"/>
				<updated>2007-04-08T00:17:00Z</updated>
		
		<summary type="html">&lt;p&gt;Seilerm: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Category:ECMA]]&lt;br /&gt;
{{Warning|'''Warning''': Article under development}}&lt;br /&gt;
&lt;br /&gt;
==Introduction==&lt;br /&gt;
&lt;br /&gt;
The problem with the way generics are implemented in Eiffel right now is that CAT calls can occur.&lt;br /&gt;
&amp;lt;e&amp;gt;&lt;br /&gt;
class PERSON&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
class STUDENT&lt;br /&gt;
inherit&lt;br /&gt;
 PERSON&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
class EMPLOYEE&lt;br /&gt;
inherit&lt;br /&gt;
 PERSON&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
class EMPLOYED_STUDENT&lt;br /&gt;
inherit&lt;br /&gt;
 EMPLOYEE&lt;br /&gt;
 STUDENT&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;
  l_person: PERSON&lt;br /&gt;
  l_student: STUDENT&lt;br /&gt;
  l_any_stack: STACK [PERSON]&lt;br /&gt;
  l_integer_stack: STACK [STUDENT]&lt;br /&gt;
do&lt;br /&gt;
  l_person_stack := l_student_stack -- line 1&lt;br /&gt;
  l_person_stack.put (l_person) -- line 2&lt;br /&gt;
  l_student := l_student_stack.item -- line 3&lt;br /&gt;
&amp;lt;/e&amp;gt;&lt;br /&gt;
Currently no static check will prohibit you from writing things like this. At runtime the object returned by &amp;lt;e&amp;gt;item&amp;lt;/e&amp;gt; on ''line 3'' is not of type &amp;lt;e&amp;gt;STUDENT&amp;lt;/e&amp;gt; but of type &amp;lt;e&amp;gt;PERSON&amp;lt;/e&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
The issue is that the &amp;lt;e&amp;gt;put&amp;lt;/e&amp;gt; feature of &amp;lt;e&amp;gt;l_person_stack&amp;lt;/e&amp;gt; allows you to put objects of type &amp;lt;e&amp;gt;PERSON&amp;lt;/e&amp;gt; on the stack even though the actual type of the attached object is &amp;lt;e&amp;gt;STACK [STUDENT]&amp;lt;/e&amp;gt; and is referenced by &amp;lt;e&amp;gt;l_integer_stack&amp;lt;/e&amp;gt; whose item feature guarantees, that the returned object will be of type &amp;lt;e&amp;gt;STUDENT&amp;lt;/e&amp;gt;.&lt;br /&gt;
This solution will now extend the type system and the generic derivation of Eiffel in such away, that the type of a formal occurring as an argument in a feature declaration and the type of a formal occurring as a result type can be set independently. The type system will be extended with rules which allow only assignments between generic types if it cannot possibly lead to problems like the one mentioned above.&lt;br /&gt;
&lt;br /&gt;
== Syntax ==&lt;br /&gt;
&lt;br /&gt;
LIST [G] can be declared in the following way:&lt;br /&gt;
&amp;lt;e&amp;gt;&lt;br /&gt;
l_list: LIST [PERSON..EXMLPOYED_STUDENT]&lt;br /&gt;
&amp;lt;/e&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;e&amp;gt;LIST[A]&amp;lt;/e&amp;gt; is a shorthand for &amp;lt;e&amp;gt;LIST[A..A]&amp;lt;/e&amp;gt;.&lt;br /&gt;
&amp;lt;e&amp;gt;LIST[A..]&amp;lt;/e&amp;gt; is also a possible syntax.&lt;br /&gt;
&lt;br /&gt;
Another syntax could look as follows:&lt;br /&gt;
&amp;lt;e&amp;gt;&lt;br /&gt;
&amp;lt;type_for_arguments&amp;gt;:&amp;lt;type_for_return_types&amp;gt;&lt;br /&gt;
&amp;lt;/e&amp;gt;&lt;br /&gt;
This would more resemble an actual generated signature of a feature which looks initially like&lt;br /&gt;
&amp;lt;e&amp;gt;&lt;br /&gt;
class EXAMPLE [G]&lt;br /&gt;
feature&lt;br /&gt;
  example (a_g: G): G&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/e&amp;gt;&lt;br /&gt;
&lt;br /&gt;
A type declaration with this syntax would look like:&lt;br /&gt;
&amp;lt;e&amp;gt;&lt;br /&gt;
local&lt;br /&gt;
 l_example: EXAMPLE [EMLPOYED_STYDENT: STUDENT]&lt;br /&gt;
 l_employed_student: EMPLOYED_STUDENT&lt;br /&gt;
 l_person: PERSON&lt;br /&gt;
do&lt;br /&gt;
 -- l_example.example (a_g: EMPLOYED_STUDENT): STUDENT &lt;br /&gt;
  l_person := l_example.example (l_employed_student) -- valid&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/e&amp;gt;&lt;br /&gt;
&amp;lt;e&amp;gt;LIST[:A]&amp;lt;/e&amp;gt; is the equivalent to &amp;lt;e&amp;gt;LIST[A..]&amp;lt;/e&amp;gt;.&lt;br /&gt;
&amp;lt;e&amp;gt;LIST[A]&amp;lt;/e&amp;gt; is a shorthand for &amp;lt;e&amp;gt;LIST[A: A]&amp;lt;/e&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
But let's stick with the initial syntax for now.&lt;br /&gt;
&lt;br /&gt;
== Semantics ==&lt;br /&gt;
&lt;br /&gt;
As we already pointed out, this solution is an extension to the type system. It helps you to proper derive an interface of a generic type.&lt;br /&gt;
For example an actual type parameter for G in &amp;lt;e&amp;gt;LIST [G]&amp;lt;/e&amp;gt; is PERSON..EMPLOYED_STUDENT.&lt;br /&gt;
The interface generated by this derivation is simply that the first type (PERSON) is taken wherever G occurs as a return type.&lt;br /&gt;
The second type (EMPLOYED_STUDENT) is taken wherever G occurs as an argument type.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;e&amp;gt;&lt;br /&gt;
(generic derived) class LIST[PERSON..EMPLOYED_STUDENT]&lt;br /&gt;
&lt;br /&gt;
  put (v: EMPLOYED_STUDENT)&lt;br /&gt;
  &lt;br /&gt;
  item: PERSON&lt;br /&gt;
&amp;lt;/e&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If we encounter a form like LIST [A..] it simply means that no feature which has the formal in the argument can be called.&lt;br /&gt;
&lt;br /&gt;
{{Note: Why do we need that?&lt;br /&gt;
We wan to ensure that one has a read only list as if we would do &amp;lt;e&amp;gt;LIST [ANY..NONE]&amp;lt;/e&amp;gt; one would not be allowed to assign a &amp;lt;e&amp;gt;LIST [INTEGER]&amp;lt;/e&amp;gt; to it as one can put Void into a list of tyep &amp;lt;e&amp;gt;LIST [ANY..NONE]&amp;lt;/e&amp;gt; which is invalid for a list of integer as &amp;lt;e&amp;gt;INTEGER&amp;lt;/e&amp;gt; is expanded.}}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Validity ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;e&amp;gt;LIST[&amp;lt;first_type&amp;gt;..&amp;lt;second_type&amp;gt;]&amp;lt;/e&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Such a generic derivation is valid if:&lt;br /&gt;
* 1: the second type conforms to the constraint of the formal.&lt;br /&gt;
* 2: the second type conforms to the first type&lt;br /&gt;
&lt;br /&gt;
==Conformance Rules==&lt;br /&gt;
&lt;br /&gt;
We make another more abstract example to illustrate the conformance rules. They can easily be derived by applying the fact that its save for argument types to be covariant and for result types to be contra-variant. This is actually a very important as it is the basis where the conformance is based uppon.&lt;br /&gt;
&lt;br /&gt;
Interface conformance rule:&lt;br /&gt;
 An interface B is conform to an interface A if for every feature f_a in A there is a corresponding feature f_b available from B&lt;br /&gt;
 and for each feature the arguments of f_a conform to those of f_b and the result type of f_b is conform to the one of f_a.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;e&amp;gt;&lt;br /&gt;
local&lt;br /&gt;
  l_a: A&lt;br /&gt;
  l_b: B&lt;br /&gt;
do&lt;br /&gt;
    -- is legal if the interface conformance rule holds&lt;br /&gt;
  l_a := l_b&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/e&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Example of an actual generic conformance table===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;e&amp;gt;&lt;br /&gt;
class T &lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
class U &lt;br /&gt;
inherit T &lt;br /&gt;
  -- no covariant feature redefinition&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/e&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
| conforms to&lt;br /&gt;
! LIST [ANY]&lt;br /&gt;
! LIST [T]&lt;br /&gt;
! LIST [T..NONE]&lt;br /&gt;
! LIST [ANY..T]&lt;br /&gt;
! LIST [U]&lt;br /&gt;
|-&lt;br /&gt;
! LIST [ANY]&lt;br /&gt;
| true&lt;br /&gt;
| false&lt;br /&gt;
| false&lt;br /&gt;
| true&lt;br /&gt;
| false&lt;br /&gt;
|-&lt;br /&gt;
! LIST [T]&lt;br /&gt;
| false&lt;br /&gt;
| true&lt;br /&gt;
| true&lt;br /&gt;
| true&lt;br /&gt;
| false&lt;br /&gt;
|-&lt;br /&gt;
! LIST [T..NONE]&lt;br /&gt;
| false&lt;br /&gt;
| false&lt;br /&gt;
| true&lt;br /&gt;
| false&lt;br /&gt;
| false&lt;br /&gt;
|-&lt;br /&gt;
! LIST [ANY..T]&lt;br /&gt;
| false&lt;br /&gt;
| false &lt;br /&gt;
| false &lt;br /&gt;
| true&lt;br /&gt;
| false&lt;br /&gt;
|-&lt;br /&gt;
! LIST [U]&lt;br /&gt;
| false&lt;br /&gt;
| '''false'''&lt;br /&gt;
| true&lt;br /&gt;
| false&lt;br /&gt;
| true&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;e&amp;gt;&lt;br /&gt;
  -- legal&lt;br /&gt;
T := LIST [T..NONE] .item&lt;br /&gt;
LIST [T..NONE] .put (Void)&lt;br /&gt;
&lt;br /&gt;
  -- illegal&lt;br /&gt;
U := LIST [T..NONE] .item&lt;br /&gt;
LIST [T..NONE] .put (T)&lt;br /&gt;
&lt;br /&gt;
  -- legal&lt;br /&gt;
LIST [ANY..T] .put (T)&lt;br /&gt;
LIST [ANY..T] .put (U)&lt;br /&gt;
ANY := LIST [ANY..T] .item&lt;br /&gt;
&lt;br /&gt;
  -- illegal&lt;br /&gt;
LIST [ANY..T] .put (ANY)&lt;br /&gt;
T := LIST [ANY..T] .item&lt;br /&gt;
&amp;lt;/e&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Agents==&lt;br /&gt;
&lt;br /&gt;
The neat thing about this extension is, that there is no need to cut down the expressiveness of the agent mechanism to make them perfectly save to use with full support for all legal situations. &lt;br /&gt;
&lt;br /&gt;
Procedure class:&lt;br /&gt;
&amp;lt;e&amp;gt;&lt;br /&gt;
class PROCEDURE [BASE_TYPE, OPEN_ARGS -&amp;gt; TUPLE []]&lt;br /&gt;
    -- Signature of call is generated by the compiler. To visualize this we add _reflected to the argument tuple.&lt;br /&gt;
  call (args: OPEN_ARGS_reflected)&lt;br /&gt;
    do end&lt;br /&gt;
&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/e&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==agent (T)==&lt;br /&gt;
&lt;br /&gt;
Type declaration:&lt;br /&gt;
&amp;lt;e&amp;gt;&lt;br /&gt;
an_agent: PROCEDURE [ANY..NONE, TUPLE..TUPLE [ANY..T]]  --&amp;gt; like agent (T)&lt;br /&gt;
  -- This signature promises that the caller is going to give at least one argument which conforms to T.&lt;br /&gt;
  -- Note: The signature for the call routine has to be reflected by the compiler into : TUPLE [T..]..NONE&lt;br /&gt;
  --       This is because we can give a tuple containing more than one element and it element type has to conform to T.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
  -- legal&lt;br /&gt;
an_agent.call ([T])&lt;br /&gt;
an_agent.call ([T, ...])&lt;br /&gt;
an_agent.call ([U, ...])&lt;br /&gt;
&lt;br /&gt;
  -- illegal&lt;br /&gt;
an_agent.call ([])&lt;br /&gt;
&amp;lt;/e&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Instantiation:&lt;br /&gt;
&amp;lt;e&amp;gt;&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;
&lt;br /&gt;
  -- legal&lt;br /&gt;
an_agent := agent_empty&lt;br /&gt;
an_agent := agent_any&lt;br /&gt;
an_agent := agent_t&lt;br /&gt;
&lt;br /&gt;
  -- illegal&lt;br /&gt;
an_agent := agent_u&lt;br /&gt;
&amp;lt;/e&amp;gt;&lt;br /&gt;
&lt;br /&gt;
There might be a concern about the fact that the compiler generates the signature of the call method. But I think that its not wrong to have compiler support for agents, as they are such a fundamental core concept that is simply important that one could sacrifice expressive power or type safety just to avoid explicit support from the compiler.&lt;br /&gt;
&lt;br /&gt;
== How to generate the call signature for a given agent type ==&lt;br /&gt;
&lt;br /&gt;
To build the signature of the call routine one simply takes he second parameter and move it as the first. As the second parameter we put NONE.&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&amp;lt;e&amp;gt;&lt;br /&gt;
TUPLE [ANY..T, ANY..U, ANY..V]&lt;br /&gt;
&amp;lt;/e&amp;gt;&lt;br /&gt;
&lt;br /&gt;
leads to&lt;br /&gt;
&amp;lt;e&amp;gt;&lt;br /&gt;
TUPLE [T..,U..,V..]&lt;br /&gt;
&amp;lt;/e&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This basically states that all I want is to be able to read an object of at least type T, U, V and that I'm not going to put anything into this tuple.&lt;/div&gt;</summary>
		<author><name>Seilerm</name></author>	</entry>

	<entry>
		<id>https://dev.eiffel.com/index.php?title=Preventing_CAT_calls_in_Generics&amp;diff=7872</id>
		<title>Preventing CAT calls in Generics</title>
		<link rel="alternate" type="text/html" href="https://dev.eiffel.com/index.php?title=Preventing_CAT_calls_in_Generics&amp;diff=7872"/>
				<updated>2007-04-07T23:43:53Z</updated>
		
		<summary type="html">&lt;p&gt;Seilerm: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Category:ECMA]]&lt;br /&gt;
{{Warning|'''Warning''': Article under development}}&lt;br /&gt;
&lt;br /&gt;
==Introduction==&lt;br /&gt;
&lt;br /&gt;
The problem with the way generics are implemented in Eiffel right now is that CAT calls can occur.&lt;br /&gt;
&amp;lt;e&amp;gt;&lt;br /&gt;
class PERSON&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
class STUDENT&lt;br /&gt;
inherit&lt;br /&gt;
 PERSON&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
class EMPLOYEE&lt;br /&gt;
inherit&lt;br /&gt;
 PERSON&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
class EMPLOYED_STUDENT&lt;br /&gt;
inherit&lt;br /&gt;
 EMPLOYEE&lt;br /&gt;
 STUDENT&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;
  l_person: PERSON&lt;br /&gt;
  l_student: STUDENT&lt;br /&gt;
  l_any_stack: STACK [PERSON]&lt;br /&gt;
  l_integer_stack: STACK [STUDENT]&lt;br /&gt;
do&lt;br /&gt;
  l_person_stack := l_student_stack -- line 1&lt;br /&gt;
  l_person_stack.put (l_person) -- line 2&lt;br /&gt;
  l_student := l_student_stack.item -- line 3&lt;br /&gt;
&amp;lt;/e&amp;gt;&lt;br /&gt;
Currently no static check will prohibit you from writing things like this. At runtime the object returned by &amp;lt;e&amp;gt;item&amp;lt;/e&amp;gt; on ''line 3'' is not of type &amp;lt;e&amp;gt;STUDENT&amp;lt;/e&amp;gt; but of type &amp;lt;e&amp;gt;PERSON&amp;lt;/e&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
The issue is that the &amp;lt;e&amp;gt;put&amp;lt;/e&amp;gt; feature of &amp;lt;e&amp;gt;l_person_stack&amp;lt;/e&amp;gt; allows you to put objects of type &amp;lt;e&amp;gt;PERSON&amp;lt;/e&amp;gt; on the stack even though the actual type of the attached object is &amp;lt;e&amp;gt;STACK [STUDENT]&amp;lt;/e&amp;gt; and is referenced by &amp;lt;e&amp;gt;l_integer_stack&amp;lt;/e&amp;gt; whose item feature guarantees, that the returned object will be of type &amp;lt;e&amp;gt;STUDENT&amp;lt;/e&amp;gt;.&lt;br /&gt;
This solution will now extend the type system and the generic derivation of Eiffel in such away, that the type of a formal occurring as an argument in a feature declaration and the type of a formal occurring as a result type can be set independently. The type system will be extended with rules which allow only assignments between generic types if it cannot possibly lead to problems like the one mentioned above.&lt;br /&gt;
&lt;br /&gt;
== Syntax ==&lt;br /&gt;
&lt;br /&gt;
LIST [G] can be declared in the following way:&lt;br /&gt;
&amp;lt;e&amp;gt;&lt;br /&gt;
l_list: LIST [PERSON..EXMLPOYED_STUDENT]&lt;br /&gt;
&amp;lt;/e&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Another syntax could look as follows:&lt;br /&gt;
&amp;lt;e&amp;gt;&lt;br /&gt;
&amp;lt;type_for_arguments&amp;gt;:&amp;lt;type_for_return_types&amp;gt;&lt;br /&gt;
&amp;lt;/e&amp;gt;&lt;br /&gt;
This would more resemble an actual generated signature of a feature which looks initially like&lt;br /&gt;
&amp;lt;e&amp;gt;&lt;br /&gt;
class EXAMPLE [G]&lt;br /&gt;
feature&lt;br /&gt;
  example (a_g: G): G&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/e&amp;gt;&lt;br /&gt;
&lt;br /&gt;
A type declaration with this syntax would look like:&lt;br /&gt;
&amp;lt;e&amp;gt;&lt;br /&gt;
local&lt;br /&gt;
 l_example: EXAMPLE [EMLPOYED_STYDENT: STUDENT]&lt;br /&gt;
 l_employed_student: EMPLOYED_STUDENT&lt;br /&gt;
 l_person: PERSON&lt;br /&gt;
do&lt;br /&gt;
 -- l_example.example (a_g: EMPLOYED_STUDENT): STUDENT &lt;br /&gt;
  l_person := l_example.example (l_employed_student) -- valid&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/e&amp;gt;&lt;br /&gt;
But let's stick with the initial syntax for now.&lt;br /&gt;
&lt;br /&gt;
== Semantics ==&lt;br /&gt;
&lt;br /&gt;
As we already pointed out, this solution is an extension to the type system. It helps you to proper derive an interface of a generic type.&lt;br /&gt;
For example an actual type parameter for G in &amp;lt;e&amp;gt;LIST [G]&amp;lt;/e&amp;gt; is PERSON..EMPLOYED_STUDENT.&lt;br /&gt;
The interface generated by this derivation is simply that the first type (PERSON) is taken wherever G occurs as a return type.&lt;br /&gt;
The second type (EMPLOYED_STUDENT) is taken wherever G occurs as an argument type.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;e&amp;gt;&lt;br /&gt;
(generic derived) class LIST[PERSON..EMPLOYED_STUDENT]&lt;br /&gt;
&lt;br /&gt;
  put (v: EMPLOYED_STUDENT)&lt;br /&gt;
  &lt;br /&gt;
  item: PERSON&lt;br /&gt;
&amp;lt;/e&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Conformance Rules==&lt;br /&gt;
&lt;br /&gt;
We make another more abstract example to illustrate the conformance rules. They can easily be derived by applying the fact that its save for argument types to be covariant and for result types to be contra-variant. This is actually a very important as it is the basis where the conformance is based uppon.&lt;br /&gt;
&lt;br /&gt;
 An interface B is conform to an interface A if for every feature f_a in A there is a corresponding feature f_b available from B&lt;br /&gt;
 and for each feature the arguments of f_a conform to those of f_b and the result type of f_b is conform to the one of f_a.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;e&amp;gt;&lt;br /&gt;
 A := B&lt;br /&gt;
&amp;lt;/e&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;e&amp;gt;&lt;br /&gt;
class T &lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
class U &lt;br /&gt;
inherit T &lt;br /&gt;
  -- no covariant feature redefinition&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/e&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Type conformance===&lt;br /&gt;
obsolete?&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
| conforms to &lt;br /&gt;
! T &lt;br /&gt;
! T..NONE &lt;br /&gt;
! ANY..T&lt;br /&gt;
! U&lt;br /&gt;
|-&lt;br /&gt;
! T           &lt;br /&gt;
| true &lt;br /&gt;
| false &lt;br /&gt;
| true&lt;br /&gt;
| false&lt;br /&gt;
|-&lt;br /&gt;
! T..NONE     &lt;br /&gt;
| true &lt;br /&gt;
| false &lt;br /&gt;
| true&lt;br /&gt;
| false&lt;br /&gt;
|-&lt;br /&gt;
! ANY..T      &lt;br /&gt;
| false &lt;br /&gt;
| false &lt;br /&gt;
| false&lt;br /&gt;
| false&lt;br /&gt;
|-&lt;br /&gt;
! U&lt;br /&gt;
| true&lt;br /&gt;
| false&lt;br /&gt;
| true&lt;br /&gt;
| true&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
===Generic conformance===&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
| conforms to&lt;br /&gt;
! LIST [ANY]&lt;br /&gt;
! LIST [T]&lt;br /&gt;
! LIST [T..NONE]&lt;br /&gt;
! LIST [ANY..T]&lt;br /&gt;
! LIST [U]&lt;br /&gt;
|-&lt;br /&gt;
! LIST [ANY]&lt;br /&gt;
| true&lt;br /&gt;
| false&lt;br /&gt;
| false&lt;br /&gt;
| true&lt;br /&gt;
| false&lt;br /&gt;
|-&lt;br /&gt;
! LIST [T]&lt;br /&gt;
| false&lt;br /&gt;
| true&lt;br /&gt;
| true&lt;br /&gt;
| true&lt;br /&gt;
| false&lt;br /&gt;
|-&lt;br /&gt;
! LIST [T..NONE]&lt;br /&gt;
| false&lt;br /&gt;
| false&lt;br /&gt;
| true&lt;br /&gt;
| false&lt;br /&gt;
| false&lt;br /&gt;
|-&lt;br /&gt;
! LIST [ANY..T]&lt;br /&gt;
| false&lt;br /&gt;
| false &lt;br /&gt;
| false &lt;br /&gt;
| true&lt;br /&gt;
| false&lt;br /&gt;
|-&lt;br /&gt;
! LIST [U]&lt;br /&gt;
| false&lt;br /&gt;
| '''false'''&lt;br /&gt;
| true&lt;br /&gt;
| false&lt;br /&gt;
| true&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;e&amp;gt;&lt;br /&gt;
  -- legal&lt;br /&gt;
T := LIST [T..NONE] .item&lt;br /&gt;
LIST [T..NONE] .put (Void)&lt;br /&gt;
&lt;br /&gt;
  -- illegal&lt;br /&gt;
U := LIST [T..NONE] .item&lt;br /&gt;
LIST [T..NONE] .put (T)&lt;br /&gt;
&lt;br /&gt;
  -- legal&lt;br /&gt;
LIST [ANY..T] .put (T)&lt;br /&gt;
LIST [ANY..T] .put (U)&lt;br /&gt;
ANY := LIST [ANY..T] .item&lt;br /&gt;
&lt;br /&gt;
  -- illegal&lt;br /&gt;
LIST [ANY..T] .put (ANY)&lt;br /&gt;
T := LIST [ANY..T] .item&lt;br /&gt;
&amp;lt;/e&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Agents==&lt;br /&gt;
&lt;br /&gt;
The neat thing about this extension is, that there is no need to cut down the expressiveness of the agent mechanism to make them perfectly save to use with full support for all legal situations. &lt;br /&gt;
&lt;br /&gt;
Procedure class:&lt;br /&gt;
&amp;lt;e&amp;gt;&lt;br /&gt;
class PROCEDURE [BASE_TYPE, OPEN_ARGS -&amp;gt; TUPLE []]&lt;br /&gt;
    -- Signature of call is generated by the compiler. To visualize this we add _reflected to the argument tuple.&lt;br /&gt;
  call (args: OPEN_ARGS_reflected)&lt;br /&gt;
    do end&lt;br /&gt;
&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/e&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==agent (T)==&lt;br /&gt;
&lt;br /&gt;
Type declaration:&lt;br /&gt;
&amp;lt;e&amp;gt;&lt;br /&gt;
an_agent: PROCEDURE [ANY..NONE, TUPLE..TUPLE [ANY..T]]  --&amp;gt; like agent (T)&lt;br /&gt;
  -- signature for call has to be inverted: TUPLE [T..NONE]..NONE&lt;br /&gt;
&lt;br /&gt;
  -- legal&lt;br /&gt;
an_agent.call ([T])&lt;br /&gt;
an_agent.call ([T, ...])&lt;br /&gt;
an_agent.call ([U, ...])&lt;br /&gt;
&lt;br /&gt;
  -- illegal&lt;br /&gt;
an_agent.call ([])&lt;br /&gt;
&amp;lt;/e&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Instantiation:&lt;br /&gt;
&amp;lt;e&amp;gt;&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;
&lt;br /&gt;
  -- legal&lt;br /&gt;
an_agent := agent_empty&lt;br /&gt;
an_agent := agent_any&lt;br /&gt;
an_agent := agent_t&lt;br /&gt;
&lt;br /&gt;
  -- illegal&lt;br /&gt;
an_agent := agent_u&lt;br /&gt;
&amp;lt;/e&amp;gt;&lt;br /&gt;
&lt;br /&gt;
There might be a concern about the fact that the compiler generates the signature of the call method. But I think that its not wrong to have compiler support for agents, as they are such a fundamental core concept that is simply important that one could sacrifice expressive power or type safety just to avoid explicit support from the compiler.&lt;br /&gt;
&lt;br /&gt;
== How to generate the call signature for a given agent type ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;todo&amp;gt;&lt;/div&gt;</summary>
		<author><name>Seilerm</name></author>	</entry>

	<entry>
		<id>https://dev.eiffel.com/index.php?title=Preventing_CAT_calls_in_Generics&amp;diff=7871</id>
		<title>Preventing CAT calls in Generics</title>
		<link rel="alternate" type="text/html" href="https://dev.eiffel.com/index.php?title=Preventing_CAT_calls_in_Generics&amp;diff=7871"/>
				<updated>2007-04-07T22:44:55Z</updated>
		
		<summary type="html">&lt;p&gt;Seilerm: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Category:ECMA]]&lt;br /&gt;
{{Warning|'''Warning''': Article under development}}&lt;br /&gt;
&lt;br /&gt;
==Introduction==&lt;br /&gt;
&lt;br /&gt;
The problem with the way generics are implemented in Eiffel right now is that CAT calls can occur.&lt;br /&gt;
&amp;lt;e&amp;gt;&lt;br /&gt;
class PERSON&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
class STUDENT&lt;br /&gt;
inherit&lt;br /&gt;
 PERSON&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
class EMPLOYEE&lt;br /&gt;
inherit&lt;br /&gt;
 PERSON&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
class EMPLOYED_STUDENT&lt;br /&gt;
inherit&lt;br /&gt;
 EMPLOYEE&lt;br /&gt;
 STUDENT&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;
  l_person: PERSON&lt;br /&gt;
  l_student: STUDENT&lt;br /&gt;
  l_any_stack: STACK [PERSON]&lt;br /&gt;
  l_integer_stack: STACK [STUDENT]&lt;br /&gt;
do&lt;br /&gt;
  l_person_stack := l_student_stack -- line 1&lt;br /&gt;
  l_person_stack.put (l_person) -- line 2&lt;br /&gt;
  l_student := l_student_stack.item -- line 3&lt;br /&gt;
&amp;lt;/e&amp;gt;&lt;br /&gt;
Currently no static check will prohibit you from writing things like this. At runtime the object returned by &amp;lt;e&amp;gt;item&amp;lt;/e&amp;gt; on ''line 3'' is not of type &amp;lt;e&amp;gt;STUDENT&amp;lt;/e&amp;gt; but of type &amp;lt;e&amp;gt;PERSON&amp;lt;/e&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
The issue is that the &amp;lt;e&amp;gt;put&amp;lt;/e&amp;gt; feature of &amp;lt;e&amp;gt;l_person_stack&amp;lt;/e&amp;gt; allows you to put objects of type &amp;lt;e&amp;gt;PERSON&amp;lt;/e&amp;gt; on the stack even though the actual type of the attached object is &amp;lt;e&amp;gt;STACK [STUDENT]&amp;lt;/e&amp;gt; and is referenced by &amp;lt;e&amp;gt;l_integer_stack&amp;lt;/e&amp;gt; whose item feature guarantees, that the returned object will be of type &amp;lt;e&amp;gt;STUDENT&amp;lt;/e&amp;gt;.&lt;br /&gt;
This solution will now extend the type system and the generic derivation of Eiffel in such away, that the type of a formal occurring as an argument in a feature declaration and the type of a formal occurring as a result type can be set independently. The type system will be extended with rules which allow only assignments between generic types if it cannot possibly lead to problems like the one mentioned above.&lt;br /&gt;
&lt;br /&gt;
== Syntax ==&lt;br /&gt;
&lt;br /&gt;
LIST [G] can be declared in the following way:&lt;br /&gt;
&amp;lt;e&amp;gt;&lt;br /&gt;
l_list: LIST [PERSON..EXMLPOYED_STUDENT]&lt;br /&gt;
&amp;lt;/e&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Another syntax could look as follows:&lt;br /&gt;
&amp;lt;e&amp;gt;&lt;br /&gt;
&amp;lt;type_for_arguments&amp;gt;:&amp;lt;type_for_return_types&amp;gt;&lt;br /&gt;
&amp;lt;/e&amp;gt;&lt;br /&gt;
This would more resemble an actual generated signature of a feature which looks initially like&lt;br /&gt;
&amp;lt;e&amp;gt;&lt;br /&gt;
class EXAMPLE [G]&lt;br /&gt;
feature&lt;br /&gt;
  example (a_g: G): G&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/e&amp;gt;&lt;br /&gt;
&lt;br /&gt;
A type declaration with this syntax would look like:&lt;br /&gt;
&amp;lt;e&amp;gt;&lt;br /&gt;
local&lt;br /&gt;
 l_example: EXAMPLE [EMLPOYED_STYDENT: STUDENT]&lt;br /&gt;
 l_employed_student: EMPLOYED_STUDENT&lt;br /&gt;
 l_person: PERSON&lt;br /&gt;
do&lt;br /&gt;
 -- l_example.example (a_g: EMPLOYED_STUDENT): STUDENT &lt;br /&gt;
  l_person := l_example.example (l_employed_student) -- valid&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/e&amp;gt;&lt;br /&gt;
But let's stick with the initial syntax for now.&lt;br /&gt;
&lt;br /&gt;
== Semantics ==&lt;br /&gt;
&lt;br /&gt;
As we already pointed out, this solution is an extension to the type system. It helps you to proper derive an interface of a generic type.&lt;br /&gt;
For example an actual type parameter for G in &amp;lt;e&amp;gt;LIST [G]&amp;lt;/e&amp;gt; is PERSON..EMPLOYED_STUDENT.&lt;br /&gt;
The interface generated by this derivation is simply that the first type (PERSON) is taken wherever G occurs as a return type.&lt;br /&gt;
The second type (EMPLOYED_STUDENT) is taken wherever G occurs as an argument type.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;e&amp;gt;&lt;br /&gt;
(generic derived) class LIST[PERSON..EMPLOYED_STUDENT]&lt;br /&gt;
&lt;br /&gt;
  put (v: EMPLOYED_STUDENT)&lt;br /&gt;
  &lt;br /&gt;
  item: PERSON&lt;br /&gt;
&amp;lt;/e&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Conformance Rules==&lt;br /&gt;
&lt;br /&gt;
We make another more abstract example to illustrate the conformance rules. They can easily be derived by applying the fact that its save for argument types to be covariant and for result types to be contra-variant. This is actually a very important as it is the basis where the conformance is based uppon.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;e&amp;gt;&lt;br /&gt;
class T &lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
class U &lt;br /&gt;
inherit T &lt;br /&gt;
  -- no covariant feature redefinition&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/e&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Type conformance===&lt;br /&gt;
obsolete?&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
| conforms to &lt;br /&gt;
! T &lt;br /&gt;
! T..NONE &lt;br /&gt;
! ANY..T&lt;br /&gt;
! U&lt;br /&gt;
|-&lt;br /&gt;
! T           &lt;br /&gt;
| true &lt;br /&gt;
| false &lt;br /&gt;
| true&lt;br /&gt;
| false&lt;br /&gt;
|-&lt;br /&gt;
! T..NONE     &lt;br /&gt;
| true &lt;br /&gt;
| false &lt;br /&gt;
| true&lt;br /&gt;
| false&lt;br /&gt;
|-&lt;br /&gt;
! ANY..T      &lt;br /&gt;
| false &lt;br /&gt;
| false &lt;br /&gt;
| false&lt;br /&gt;
| false&lt;br /&gt;
|-&lt;br /&gt;
! U&lt;br /&gt;
| true&lt;br /&gt;
| false&lt;br /&gt;
| true&lt;br /&gt;
| true&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
===Generic conformance===&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
| conforms to&lt;br /&gt;
! LIST [ANY]&lt;br /&gt;
! LIST [T]&lt;br /&gt;
! LIST [T..NONE]&lt;br /&gt;
! LIST [ANY..T]&lt;br /&gt;
! LIST [U]&lt;br /&gt;
|-&lt;br /&gt;
! LIST [ANY]&lt;br /&gt;
| true&lt;br /&gt;
| false&lt;br /&gt;
| false&lt;br /&gt;
| true&lt;br /&gt;
| false&lt;br /&gt;
|-&lt;br /&gt;
! LIST [T]&lt;br /&gt;
| false&lt;br /&gt;
| true&lt;br /&gt;
| true&lt;br /&gt;
| true&lt;br /&gt;
| false&lt;br /&gt;
|-&lt;br /&gt;
! LIST [T..NONE]&lt;br /&gt;
| false&lt;br /&gt;
| false&lt;br /&gt;
| true&lt;br /&gt;
| false&lt;br /&gt;
| false&lt;br /&gt;
|-&lt;br /&gt;
! LIST [ANY..T]&lt;br /&gt;
| false&lt;br /&gt;
| false &lt;br /&gt;
| false &lt;br /&gt;
| true&lt;br /&gt;
| false&lt;br /&gt;
|-&lt;br /&gt;
! LIST [U]&lt;br /&gt;
| false&lt;br /&gt;
| '''false'''&lt;br /&gt;
| true&lt;br /&gt;
| false&lt;br /&gt;
| true&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;e&amp;gt;&lt;br /&gt;
  -- legal&lt;br /&gt;
T := LIST [T..NONE] .item&lt;br /&gt;
LIST [T..NONE] .put (Void)&lt;br /&gt;
&lt;br /&gt;
  -- illegal&lt;br /&gt;
U := LIST [T..NONE] .item&lt;br /&gt;
LIST [T..NONE] .put (T)&lt;br /&gt;
&lt;br /&gt;
  -- legal&lt;br /&gt;
LIST [ANY..T] .put (T)&lt;br /&gt;
LIST [ANY..T] .put (U)&lt;br /&gt;
ANY := LIST [ANY..T] .item&lt;br /&gt;
&lt;br /&gt;
  -- illegal&lt;br /&gt;
LIST [ANY..T] .put (ANY)&lt;br /&gt;
T := LIST [ANY..T] .item&lt;br /&gt;
&amp;lt;/e&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Agents==&lt;br /&gt;
&lt;br /&gt;
The neat thing about this extension is, that there is no need to cut down the expressiveness of the agent mechanism to make them perfectly save to use with full support for all legal situations. &lt;br /&gt;
&lt;br /&gt;
Procedure class:&lt;br /&gt;
&amp;lt;e&amp;gt;&lt;br /&gt;
class PROCEDURE [BASE_TYPE, OPEN_ARGS -&amp;gt; TUPLE []]&lt;br /&gt;
    -- Signature of call is generated by the compiler. To visualize this we add _reflected to the argument tuple.&lt;br /&gt;
  call (args: OPEN_ARGS_reflected)&lt;br /&gt;
    do end&lt;br /&gt;
&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/e&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==agent (T)==&lt;br /&gt;
&lt;br /&gt;
Type declaration:&lt;br /&gt;
&amp;lt;e&amp;gt;&lt;br /&gt;
an_agent: PROCEDURE [ANY..NONE, TUPLE..TUPLE [ANY..T]]  --&amp;gt; like agent (T)&lt;br /&gt;
  -- signature for call has to be inverted: TUPLE [T..NONE]..NONE&lt;br /&gt;
&lt;br /&gt;
  -- legal&lt;br /&gt;
an_agent.call ([T])&lt;br /&gt;
an_agent.call ([T, ...])&lt;br /&gt;
an_agent.call ([U, ...])&lt;br /&gt;
&lt;br /&gt;
  -- illegal&lt;br /&gt;
an_agent.call ([])&lt;br /&gt;
&amp;lt;/e&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Instantiation:&lt;br /&gt;
&amp;lt;e&amp;gt;&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;
&lt;br /&gt;
  -- legal&lt;br /&gt;
an_agent := agent_empty&lt;br /&gt;
an_agent := agent_any&lt;br /&gt;
an_agent := agent_t&lt;br /&gt;
&lt;br /&gt;
  -- illegal&lt;br /&gt;
an_agent := agent_u&lt;br /&gt;
&amp;lt;/e&amp;gt;&lt;br /&gt;
&lt;br /&gt;
There might be a concern about the fact that the compiler generates the signature of the call method. But I think that its not wrong to have compiler support for agents, as they are such a fundamental core concept that is simply important that one could sacrifice expressive power or type safety just to avoid explicit support from the compiler.&lt;br /&gt;
&lt;br /&gt;
== How to generate the call signature for a given agent type ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;todo&amp;gt;&lt;/div&gt;</summary>
		<author><name>Seilerm</name></author>	</entry>

	<entry>
		<id>https://dev.eiffel.com/index.php?title=Preventing_CAT_calls_in_Generics&amp;diff=7870</id>
		<title>Preventing CAT calls in Generics</title>
		<link rel="alternate" type="text/html" href="https://dev.eiffel.com/index.php?title=Preventing_CAT_calls_in_Generics&amp;diff=7870"/>
				<updated>2007-04-07T22:36:30Z</updated>
		
		<summary type="html">&lt;p&gt;Seilerm: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Category:ECMA]]&lt;br /&gt;
{{Warning|'''Warning''': Article under development}}&lt;br /&gt;
&lt;br /&gt;
==Introduction==&lt;br /&gt;
&lt;br /&gt;
The problem with the way generics are implemented in Eiffel right now is that CAT calls can occur.&lt;br /&gt;
&amp;lt;e&amp;gt;&lt;br /&gt;
class PERSON&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
class STUDENT&lt;br /&gt;
inherit&lt;br /&gt;
 PERSON&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
class EMPLOYEE&lt;br /&gt;
inherit&lt;br /&gt;
 PERSON&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
class EMPLOYED_STUDENT&lt;br /&gt;
inherit&lt;br /&gt;
 EMPLOYEE&lt;br /&gt;
 STUDENT&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;
  l_person: PERSON&lt;br /&gt;
  l_student: STUDENT&lt;br /&gt;
  l_any_stack: STACK [PERSON]&lt;br /&gt;
  l_integer_stack: STACK [STUDENT]&lt;br /&gt;
do&lt;br /&gt;
  l_person_stack := l_student_stack -- line 1&lt;br /&gt;
  l_person_stack.put (l_person) -- line 2&lt;br /&gt;
  l_student := l_student_stack.item -- line 3&lt;br /&gt;
&amp;lt;/e&amp;gt;&lt;br /&gt;
Currently no static check will prohibit you from writing things like this. At runtime the object returned by item on line 3 is not of type &amp;lt;e&amp;gt;STUDENT&amp;lt;/e&amp;gt; but of type &amp;lt;e&amp;gt;PERSON&amp;lt;/e&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
The issue is that the put feature of l_person_stack allows you to put objects of type &amp;lt;e&amp;gt;PERSON&amp;lt;/e&amp;gt; on the stack even though the actual type of the attached object is &amp;lt;e&amp;gt;STACK [STUDENT]&amp;lt;/e&amp;gt; and is referenced by l_integer_stack whose item feature guarantees, that the returned object will be of type &amp;lt;e&amp;gt;STUDENT&amp;lt;/e&amp;gt;.&lt;br /&gt;
This solution will now extend the type system of Eiffel in such away, that the type of a formal occurring as an argument in a feature declaration and the type of a formal occurring as a result type can be set independently. The type system will be extended with rules which allow only assignments between generic types if it cannot possibly lead to problems like the one mentioned above.&lt;br /&gt;
&lt;br /&gt;
== Syntax ==&lt;br /&gt;
&lt;br /&gt;
LIST [G] can be declared in the following way:&lt;br /&gt;
&amp;lt;e&amp;gt;&lt;br /&gt;
l_list: LIST [PERSON..EXMLPOYED_STUDENT]&lt;br /&gt;
&amp;lt;/e&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The semantics are that where ever G occurs as a return type it will be instantiated as STUDENT.&lt;br /&gt;
And wherever G occurs as an argument type it will be instantiated as EMLPOYED_STUDENT.&lt;br /&gt;
&lt;br /&gt;
Another syntax could look as follows:&lt;br /&gt;
&amp;lt;e&amp;gt;&lt;br /&gt;
&amp;lt;type_for_arguments&amp;gt;:&amp;lt;type_for_return_types&amp;gt;&lt;br /&gt;
&amp;lt;/e&amp;gt;&lt;br /&gt;
This would more resemble an actual generated signature of a feature which looks initially like&lt;br /&gt;
&amp;lt;e&amp;gt;&lt;br /&gt;
class EXAMPLE [G]&lt;br /&gt;
feature&lt;br /&gt;
  example (a_g: G): G&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/e&amp;gt;&lt;br /&gt;
&lt;br /&gt;
A type declaration with this syntax would look like:&lt;br /&gt;
&amp;lt;e&amp;gt;&lt;br /&gt;
local&lt;br /&gt;
 l_example: EXAMPLE [EMLPOYED_STYDENT: STUDENT]&lt;br /&gt;
 l_employed_student: EMPLOYED_STUDENT&lt;br /&gt;
 l_person: PERSON&lt;br /&gt;
do&lt;br /&gt;
 -- l_example.example (a_g: EMPLOYED_STUDENT): STUDENT &lt;br /&gt;
  l_person := l_example.example (l_employed_student) -- valid&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/e&amp;gt;&lt;br /&gt;
But let's stick with the initial syntax for now.&lt;br /&gt;
&lt;br /&gt;
== Semantics ==&lt;br /&gt;
&lt;br /&gt;
As we already pointed out, this solution is an extension to the type system. It helps you to proper derive an interface of a generic type.&lt;br /&gt;
For example an actual type parameter for G in &amp;lt;e&amp;gt;LIST [G]&amp;lt;/e&amp;gt; is PERSON..EMPLOYED_STUDENT.&lt;br /&gt;
The interface generated by this derivation is simply that the first type (PERSON) is taken wherever G occurs as a return type.&lt;br /&gt;
The second type (EMPLOYED_STUDENT) is taken wherever G occurs as an argument type.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;e&amp;gt;&lt;br /&gt;
(generic derived) class LIST[PERSON..EMPLOYED_STUDENT]&lt;br /&gt;
&lt;br /&gt;
  put (v: EMPLOYED_STUDENT)&lt;br /&gt;
  &lt;br /&gt;
  item: PERSON&lt;br /&gt;
&amp;lt;/e&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Conformance Rules==&lt;br /&gt;
&lt;br /&gt;
We make another more abstract example to illustrate the conformance rules. They can easily be derived by applying the fact that its save for argument types to be covariant and for result types to be contra-variant. This is actually a very important as it is the basis where the conformance is based uppon.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;e&amp;gt;&lt;br /&gt;
class T &lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
class U &lt;br /&gt;
inherit T &lt;br /&gt;
  -- no covariant feature redefinition&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/e&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Type conformance===&lt;br /&gt;
obsolete?&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
| conforms to &lt;br /&gt;
! T &lt;br /&gt;
! T..NONE &lt;br /&gt;
! ANY..T&lt;br /&gt;
! U&lt;br /&gt;
|-&lt;br /&gt;
! T           &lt;br /&gt;
| true &lt;br /&gt;
| false &lt;br /&gt;
| true&lt;br /&gt;
| false&lt;br /&gt;
|-&lt;br /&gt;
! T..NONE     &lt;br /&gt;
| true &lt;br /&gt;
| false &lt;br /&gt;
| true&lt;br /&gt;
| false&lt;br /&gt;
|-&lt;br /&gt;
! ANY..T      &lt;br /&gt;
| false &lt;br /&gt;
| false &lt;br /&gt;
| false&lt;br /&gt;
| false&lt;br /&gt;
|-&lt;br /&gt;
! U&lt;br /&gt;
| true&lt;br /&gt;
| false&lt;br /&gt;
| true&lt;br /&gt;
| true&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
===Generic conformance===&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
| conforms to&lt;br /&gt;
! LIST [ANY]&lt;br /&gt;
! LIST [T]&lt;br /&gt;
! LIST [T..NONE]&lt;br /&gt;
! LIST [ANY..T]&lt;br /&gt;
! LIST [U]&lt;br /&gt;
|-&lt;br /&gt;
! LIST [ANY]&lt;br /&gt;
| true&lt;br /&gt;
| false&lt;br /&gt;
| false&lt;br /&gt;
| true&lt;br /&gt;
| false&lt;br /&gt;
|-&lt;br /&gt;
! LIST [T]&lt;br /&gt;
| false&lt;br /&gt;
| true&lt;br /&gt;
| true&lt;br /&gt;
| true&lt;br /&gt;
| false&lt;br /&gt;
|-&lt;br /&gt;
! LIST [T..NONE]&lt;br /&gt;
| false&lt;br /&gt;
| false&lt;br /&gt;
| true&lt;br /&gt;
| false&lt;br /&gt;
| false&lt;br /&gt;
|-&lt;br /&gt;
! LIST [ANY..T]&lt;br /&gt;
| false&lt;br /&gt;
| false &lt;br /&gt;
| false &lt;br /&gt;
| true&lt;br /&gt;
| false&lt;br /&gt;
|-&lt;br /&gt;
! LIST [U]&lt;br /&gt;
| false&lt;br /&gt;
| '''false'''&lt;br /&gt;
| true&lt;br /&gt;
| false&lt;br /&gt;
| true&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;e&amp;gt;&lt;br /&gt;
  -- legal&lt;br /&gt;
T := LIST [T..NONE] .item&lt;br /&gt;
LIST [T..NONE] .put (Void)&lt;br /&gt;
&lt;br /&gt;
  -- illegal&lt;br /&gt;
U := LIST [T..NONE] .item&lt;br /&gt;
LIST [T..NONE] .put (T)&lt;br /&gt;
&lt;br /&gt;
  -- legal&lt;br /&gt;
LIST [ANY..T] .put (T)&lt;br /&gt;
LIST [ANY..T] .put (U)&lt;br /&gt;
ANY := LIST [ANY..T] .item&lt;br /&gt;
&lt;br /&gt;
  -- illegal&lt;br /&gt;
LIST [ANY..T] .put (ANY)&lt;br /&gt;
T := LIST [ANY..T] .item&lt;br /&gt;
&amp;lt;/e&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Agents==&lt;br /&gt;
&lt;br /&gt;
The neat thing about this extension is, that there is no need to cut down the expressiveness of the agent mechanism to make them perfectly save to use with full support for all legal situations. &lt;br /&gt;
&lt;br /&gt;
Procedure class:&lt;br /&gt;
&amp;lt;e&amp;gt;&lt;br /&gt;
class PROCEDURE [BASE_TYPE, OPEN_ARGS -&amp;gt; TUPLE []]&lt;br /&gt;
    -- Signature of call is generated by the compiler. To visualize this we add _reflected to the argument tuple.&lt;br /&gt;
  call (args: OPEN_ARGS_reflected)&lt;br /&gt;
    do end&lt;br /&gt;
&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/e&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==agent (T)==&lt;br /&gt;
&lt;br /&gt;
Type declaration:&lt;br /&gt;
&amp;lt;e&amp;gt;&lt;br /&gt;
an_agent: PROCEDURE [ANY..NONE, TUPLE..TUPLE [ANY..T]]  --&amp;gt; like agent (T)&lt;br /&gt;
  -- signature for call has to be inverted: TUPLE [T..NONE]..NONE&lt;br /&gt;
&lt;br /&gt;
  -- legal&lt;br /&gt;
an_agent.call ([T])&lt;br /&gt;
an_agent.call ([T, ...])&lt;br /&gt;
an_agent.call ([U, ...])&lt;br /&gt;
&lt;br /&gt;
  -- illegal&lt;br /&gt;
an_agent.call ([])&lt;br /&gt;
&amp;lt;/e&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Instantiation:&lt;br /&gt;
&amp;lt;e&amp;gt;&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;
&lt;br /&gt;
  -- legal&lt;br /&gt;
an_agent := agent_empty&lt;br /&gt;
an_agent := agent_any&lt;br /&gt;
an_agent := agent_t&lt;br /&gt;
&lt;br /&gt;
  -- illegal&lt;br /&gt;
an_agent := agent_u&lt;br /&gt;
&amp;lt;/e&amp;gt;&lt;br /&gt;
&lt;br /&gt;
There might be a concern about the fact that the compiler generates the signature of the call method. But I think that its not wrong to have compiler support for agents, as they are such a fundamental core concept that is simply important that one could sacrifice expressive power or type safety just to avoid explicit support from the compiler.&lt;br /&gt;
&lt;br /&gt;
== How to generate the call signature for a given agent type ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;todo&amp;gt;&lt;/div&gt;</summary>
		<author><name>Seilerm</name></author>	</entry>

	<entry>
		<id>https://dev.eiffel.com/index.php?title=Preventing_CAT_calls_in_Generics&amp;diff=7869</id>
		<title>Preventing CAT calls in Generics</title>
		<link rel="alternate" type="text/html" href="https://dev.eiffel.com/index.php?title=Preventing_CAT_calls_in_Generics&amp;diff=7869"/>
				<updated>2007-04-07T22:31:57Z</updated>
		
		<summary type="html">&lt;p&gt;Seilerm: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Category:ECMA]]&lt;br /&gt;
{{Warning|'''Warning''': Article under development}}&lt;br /&gt;
&lt;br /&gt;
==Introduction==&lt;br /&gt;
&lt;br /&gt;
The problem with the way generics are implemented in Eiffel right now is that CAT calls can occur.&lt;br /&gt;
&amp;lt;e&amp;gt;&lt;br /&gt;
class PERSON&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
class STUDENT&lt;br /&gt;
inherit&lt;br /&gt;
 PERSON&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
class EMPLOYEE&lt;br /&gt;
inherit&lt;br /&gt;
 PERSON&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
class EMPLOYED_STUDENT&lt;br /&gt;
inherit&lt;br /&gt;
 EMPLOYEE&lt;br /&gt;
 STUDENT&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;
  l_person: PERSON&lt;br /&gt;
  l_student: STUDENT&lt;br /&gt;
  l_any_stack: STACK [PERSON]&lt;br /&gt;
  l_integer_stack: STACK [STUDENT]&lt;br /&gt;
do&lt;br /&gt;
  l_person_stack := l_student_stack -- line 1&lt;br /&gt;
  l_person_stack.put (l_person) -- line 2&lt;br /&gt;
  l_student := l_student_stack.item -- line 3&lt;br /&gt;
&amp;lt;/e&amp;gt;&lt;br /&gt;
Currently no static check will prohibit you from writing things like this. At runtime the object returned by item on line 3 is not of type &amp;lt;e&amp;gt;STUDENT&amp;lt;/e&amp;gt; but of type &amp;lt;e&amp;gt;PERSON&amp;lt;/e&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
The issue is that the put feature of l_person_stack allows you to put objects of type &amp;lt;e&amp;gt;PERSON&amp;lt;/e&amp;gt; on the stack even though the actual type of the attached object is &amp;lt;e&amp;gt;STACK [STUDENT]&amp;lt;/e&amp;gt; and is referenced by l_integer_stack whose item feature guarantees, that the returned object will be of type &amp;lt;e&amp;gt;STUDENT&amp;lt;/e&amp;gt;.&lt;br /&gt;
This solution will now extend the type system of Eiffel in such away, that the type of a formal occurring as an argument in a feature declaration and the type of a formal occuring as a result type can be set independently. The type system will be extended with rules which allow only assignments between generic types if it cannot possibly lead to problems like the one mentioned above.&lt;br /&gt;
&lt;br /&gt;
== Syntax ==&lt;br /&gt;
&lt;br /&gt;
LIST [G] can be decalred in the following way:&lt;br /&gt;
&amp;lt;e&amp;gt;&lt;br /&gt;
l_list: LIST [PERSON..EXMLPOYED_STUDENT]&lt;br /&gt;
&amp;lt;/e&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The semantics are that where ever G occurs as a return type it will be instantiated as STUDENT.&lt;br /&gt;
And wherever G occurs as an argument type it will be instantiated as EMLPOYED_STUDENT.&lt;br /&gt;
&lt;br /&gt;
Another syntax could look as follows:&lt;br /&gt;
&amp;lt;e&amp;gt;&lt;br /&gt;
&amp;lt;type_for_arguments&amp;gt;:&amp;lt;type_for_return_types&amp;gt;&lt;br /&gt;
&amp;lt;/e&amp;gt;&lt;br /&gt;
This would more resemble an actual generated signature of a feature which looks initially like&lt;br /&gt;
&amp;lt;e&amp;gt;&lt;br /&gt;
class EXAMPLE [G]&lt;br /&gt;
feature&lt;br /&gt;
  example (a_g: G): G&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/e&amp;gt;&lt;br /&gt;
&lt;br /&gt;
A type declaration with this syntax would look like:&lt;br /&gt;
&amp;lt;e&amp;gt;&lt;br /&gt;
local&lt;br /&gt;
 l_example: EXAMPLE [EMLPOYED_STYDENT: STUDENT]&lt;br /&gt;
 l_employed_student: EMPLOYED_STUDENT&lt;br /&gt;
 l_person: PERSON&lt;br /&gt;
do&lt;br /&gt;
 -- l_example.example (a_g: EMPLOYED_STUDENT): STUDENT &lt;br /&gt;
  l_person := l_example.example (l_employed_student) -- valid&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/e&amp;gt;&lt;br /&gt;
But let's stick with the initial syntax for now.&lt;br /&gt;
&lt;br /&gt;
== Semantics ==&lt;br /&gt;
&lt;br /&gt;
As we already pointed out, this solution is an extension to the type system. It helps you to proper derive an interface of a generic type.&lt;br /&gt;
For example an actual type parameter for G in &amp;lt;e&amp;gt;LIST [G]&amp;lt;/e&amp;gt; is PERSON..EMPLOYED_STUDENT.&lt;br /&gt;
The interface generated by this derivation is simply that the first type (PERSON) is taken wherever G occurs as a return type.&lt;br /&gt;
The second type (EMPLOYED_STUDENT) is taken wherever G occurs as an argument type.&lt;br /&gt;
&lt;br /&gt;
 '''The conformance rules for such new interfaces simply reflect that arguments are contra-variant and return types are covariant.'''&lt;br /&gt;
&lt;br /&gt;
&amp;lt;e&amp;gt;&lt;br /&gt;
(generic derived) class LIST[PERSON..EMPLOYED_STUDENT]&lt;br /&gt;
&lt;br /&gt;
  put (v: EMPLOYED_STUDENT)&lt;br /&gt;
  &lt;br /&gt;
  item: PERSON&lt;br /&gt;
&amp;lt;/e&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Conformance Rules==&lt;br /&gt;
&lt;br /&gt;
We make another more abstract example to illustrate the conformance rules. They can easily be derived by applying the fact that its save for argument types to be covariant and for result types to be contra-variant.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;e&amp;gt;&lt;br /&gt;
class T &lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
class U &lt;br /&gt;
inherit T &lt;br /&gt;
  -- no covariant feature redefinition&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/e&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Type conformance===&lt;br /&gt;
obsolete?&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
| conforms to &lt;br /&gt;
! T &lt;br /&gt;
! T..NONE &lt;br /&gt;
! ANY..T&lt;br /&gt;
! U&lt;br /&gt;
|-&lt;br /&gt;
! T           &lt;br /&gt;
| true &lt;br /&gt;
| false &lt;br /&gt;
| true&lt;br /&gt;
| false&lt;br /&gt;
|-&lt;br /&gt;
! T..NONE     &lt;br /&gt;
| true &lt;br /&gt;
| false &lt;br /&gt;
| true&lt;br /&gt;
| false&lt;br /&gt;
|-&lt;br /&gt;
! ANY..T      &lt;br /&gt;
| false &lt;br /&gt;
| false &lt;br /&gt;
| false&lt;br /&gt;
| false&lt;br /&gt;
|-&lt;br /&gt;
! U&lt;br /&gt;
| true&lt;br /&gt;
| false&lt;br /&gt;
| true&lt;br /&gt;
| true&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
===Generic conformance===&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
| conforms to&lt;br /&gt;
! LIST [ANY]&lt;br /&gt;
! LIST [T]&lt;br /&gt;
! LIST [T..NONE]&lt;br /&gt;
! LIST [ANY..T]&lt;br /&gt;
! LIST [U]&lt;br /&gt;
|-&lt;br /&gt;
! LIST [ANY]&lt;br /&gt;
| true&lt;br /&gt;
| false&lt;br /&gt;
| false&lt;br /&gt;
| true&lt;br /&gt;
| false&lt;br /&gt;
|-&lt;br /&gt;
! LIST [T]&lt;br /&gt;
| false&lt;br /&gt;
| true&lt;br /&gt;
| true&lt;br /&gt;
| true&lt;br /&gt;
| false&lt;br /&gt;
|-&lt;br /&gt;
! LIST [T..NONE]&lt;br /&gt;
| false&lt;br /&gt;
| false&lt;br /&gt;
| true&lt;br /&gt;
| false&lt;br /&gt;
| false&lt;br /&gt;
|-&lt;br /&gt;
! LIST [ANY..T]&lt;br /&gt;
| false&lt;br /&gt;
| false &lt;br /&gt;
| false &lt;br /&gt;
| true&lt;br /&gt;
| false&lt;br /&gt;
|-&lt;br /&gt;
! LIST [U]&lt;br /&gt;
| false&lt;br /&gt;
| '''false'''&lt;br /&gt;
| true&lt;br /&gt;
| false&lt;br /&gt;
| true&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;e&amp;gt;&lt;br /&gt;
  -- legal&lt;br /&gt;
T := LIST [T..NONE] .item&lt;br /&gt;
LIST [T..NONE] .put (Void)&lt;br /&gt;
&lt;br /&gt;
  -- illegal&lt;br /&gt;
U := LIST [T..NONE] .item&lt;br /&gt;
LIST [T..NONE] .put (T)&lt;br /&gt;
&lt;br /&gt;
  -- legal&lt;br /&gt;
LIST [ANY..T] .put (T)&lt;br /&gt;
LIST [ANY..T] .put (U)&lt;br /&gt;
ANY := LIST [ANY..T] .item&lt;br /&gt;
&lt;br /&gt;
  -- illegal&lt;br /&gt;
LIST [ANY..T] .put (ANY)&lt;br /&gt;
T := LIST [ANY..T] .item&lt;br /&gt;
&amp;lt;/e&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Agents==&lt;br /&gt;
&lt;br /&gt;
The neat thing about this extension is, that there is no need to cut down the expressiveness of the agent mechanism to make them perfectly save to use with full support for all legal situations. &lt;br /&gt;
&lt;br /&gt;
Procedure class:&lt;br /&gt;
&amp;lt;e&amp;gt;&lt;br /&gt;
class PROCEDURE [BASE_TYPE, OPEN_ARGS -&amp;gt; TUPLE []]&lt;br /&gt;
    -- Signature of call is generated by the compiler. To visualize this we add _reflected to the argument tuple.&lt;br /&gt;
  call (args: OPEN_ARGS_reflected)&lt;br /&gt;
    do end&lt;br /&gt;
&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/e&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==agent (T)==&lt;br /&gt;
&lt;br /&gt;
Type declaration:&lt;br /&gt;
&amp;lt;e&amp;gt;&lt;br /&gt;
an_agent: PROCEDURE [ANY..NONE, TUPLE..TUPLE [ANY..T]]  --&amp;gt; like agent (T)&lt;br /&gt;
  -- signature for call has to be inverted: TUPLE [T..NONE]..NONE&lt;br /&gt;
&lt;br /&gt;
  -- legal&lt;br /&gt;
an_agent.call ([T])&lt;br /&gt;
an_agent.call ([T, ...])&lt;br /&gt;
an_agent.call ([U, ...])&lt;br /&gt;
&lt;br /&gt;
  -- illegal&lt;br /&gt;
an_agent.call ([])&lt;br /&gt;
&amp;lt;/e&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Instantiation:&lt;br /&gt;
&amp;lt;e&amp;gt;&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;
&lt;br /&gt;
  -- legal&lt;br /&gt;
an_agent := agent_empty&lt;br /&gt;
an_agent := agent_any&lt;br /&gt;
an_agent := agent_t&lt;br /&gt;
&lt;br /&gt;
  -- illegal&lt;br /&gt;
an_agent := agent_u&lt;br /&gt;
&amp;lt;/e&amp;gt;&lt;br /&gt;
&lt;br /&gt;
There might be a concern about the fact that the compiler generates the signature of the call method. But I think that its not wrong to have compiler support for agents, as they are such a fundamental core concept that is simply important that one could sacrifice expressive power or type safety just to avoid explicit support from the compiler.&lt;br /&gt;
&lt;br /&gt;
== How to generate the call signature for a given agent type ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;todo&amp;gt;&lt;/div&gt;</summary>
		<author><name>Seilerm</name></author>	</entry>

	<entry>
		<id>https://dev.eiffel.com/index.php?title=Preventing_CAT_calls_in_Generics&amp;diff=7868</id>
		<title>Preventing CAT calls in Generics</title>
		<link rel="alternate" type="text/html" href="https://dev.eiffel.com/index.php?title=Preventing_CAT_calls_in_Generics&amp;diff=7868"/>
				<updated>2007-04-07T21:05:19Z</updated>
		
		<summary type="html">&lt;p&gt;Seilerm: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Category:ECMA]]&lt;br /&gt;
{{Warning|'''Warning''': Article under development}}&lt;br /&gt;
&lt;br /&gt;
==Introduction==&lt;br /&gt;
&lt;br /&gt;
===Example===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;e&amp;gt;&lt;br /&gt;
class T &lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
class U &lt;br /&gt;
inherit T &lt;br /&gt;
  -- no covariant feature redefinition&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/e&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Conformance==&lt;br /&gt;
&lt;br /&gt;
===Type conformance===&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
| conforms to &lt;br /&gt;
! T &lt;br /&gt;
! T..NONE &lt;br /&gt;
! ANY..T&lt;br /&gt;
! U&lt;br /&gt;
|-&lt;br /&gt;
! T           &lt;br /&gt;
| true &lt;br /&gt;
| false &lt;br /&gt;
| true&lt;br /&gt;
| false&lt;br /&gt;
|-&lt;br /&gt;
! T..NONE     &lt;br /&gt;
| true &lt;br /&gt;
| false &lt;br /&gt;
| true&lt;br /&gt;
| false&lt;br /&gt;
|-&lt;br /&gt;
! ANY..T      &lt;br /&gt;
| false &lt;br /&gt;
| false &lt;br /&gt;
| false&lt;br /&gt;
| false&lt;br /&gt;
|-&lt;br /&gt;
! U&lt;br /&gt;
| true&lt;br /&gt;
| false&lt;br /&gt;
| true&lt;br /&gt;
| true&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
===Generic conformance===&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
| conforms to&lt;br /&gt;
! LIST [ANY]&lt;br /&gt;
! LIST [T]&lt;br /&gt;
! LIST [T..NONE]&lt;br /&gt;
! LIST [ANY..T]&lt;br /&gt;
! LIST [U]&lt;br /&gt;
|-&lt;br /&gt;
! LIST [ANY]&lt;br /&gt;
| true&lt;br /&gt;
| false&lt;br /&gt;
| false&lt;br /&gt;
| true&lt;br /&gt;
| false&lt;br /&gt;
|-&lt;br /&gt;
! LIST [T]&lt;br /&gt;
| false&lt;br /&gt;
| true&lt;br /&gt;
| true&lt;br /&gt;
| true&lt;br /&gt;
| false&lt;br /&gt;
|-&lt;br /&gt;
! LIST [T..NONE]&lt;br /&gt;
| false&lt;br /&gt;
| false&lt;br /&gt;
| true&lt;br /&gt;
| false&lt;br /&gt;
| false&lt;br /&gt;
|-&lt;br /&gt;
! LIST [ANY..T]&lt;br /&gt;
| false&lt;br /&gt;
| false &lt;br /&gt;
| false &lt;br /&gt;
| true&lt;br /&gt;
| false&lt;br /&gt;
|-&lt;br /&gt;
! LIST [U]&lt;br /&gt;
| false&lt;br /&gt;
| '''false'''&lt;br /&gt;
| true&lt;br /&gt;
| false&lt;br /&gt;
| true&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;e&amp;gt;&lt;br /&gt;
  -- legal&lt;br /&gt;
T := LIST [T..NONE] .item&lt;br /&gt;
LIST [T..NONE] .put (Void)&lt;br /&gt;
&lt;br /&gt;
  -- illegal&lt;br /&gt;
U := LIST [T..NONE] .item&lt;br /&gt;
LIST [T..NONE] .put (T)&lt;br /&gt;
&lt;br /&gt;
  -- legal&lt;br /&gt;
LIST [ANY..T] .put (T)&lt;br /&gt;
LIST [ANY..T] .put (U)&lt;br /&gt;
ANY := LIST [ANY..T] .item&lt;br /&gt;
&lt;br /&gt;
  -- illegal&lt;br /&gt;
LIST [ANY..T] .put (ANY)&lt;br /&gt;
T := LIST [ANY..T] .item&lt;br /&gt;
&amp;lt;/e&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== How should one understand this? ==&lt;br /&gt;
&amp;lt;e&amp;gt;&lt;br /&gt;
class PERSON&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
class STUDENT&lt;br /&gt;
inherit&lt;br /&gt;
 PERSON&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
class EMPLOYEE&lt;br /&gt;
inherit&lt;br /&gt;
 PERSON&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
class EMPLOYED_STUDENT&lt;br /&gt;
inherit&lt;br /&gt;
 EMPLOYEE&lt;br /&gt;
 STUDENT&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/e&amp;gt;&lt;br /&gt;
What this actually is, is an extension to the type system. It helps you to proper derive an interface of a generic type.&lt;br /&gt;
For example an actual type parameter for G in &amp;lt;e&amp;gt;LIST [G]&amp;lt;/e&amp;gt; is [PERSON..EMPLOYED_STUDENT].&lt;br /&gt;
The interface generated by this derivations is simply that the first type (PERSON) is taken wherever G occurs as a return type.&lt;br /&gt;
The second type EMPLOYED_STUDENT is taken wherever G occurs as an argument type.&lt;br /&gt;
&lt;br /&gt;
 '''The conformance rules for such new interfaces simply reflect that arguments are contra-variant and return types are covariant.'''&lt;br /&gt;
&lt;br /&gt;
&amp;lt;e&amp;gt;&lt;br /&gt;
(generic derived) class LIST[PERSON..EMPLOYED_STUDENT]&lt;br /&gt;
&lt;br /&gt;
  put (v: EMPLOYED_STUDENT)&lt;br /&gt;
  &lt;br /&gt;
  item: PERSON&lt;br /&gt;
&amp;lt;/e&amp;gt;&lt;br /&gt;
&lt;br /&gt;
That's basically all there is to say about this enhancement to the Eiffel type system.&lt;br /&gt;
Except that one might adapt the syntax, another idea is:&lt;br /&gt;
&amp;lt;type_for_arguments&amp;gt;:&amp;lt;type_for_return_types&amp;gt;&lt;br /&gt;
This would more resemble an actual generated signature of a feature which looks initialy like&lt;br /&gt;
&amp;lt;e&amp;gt;&lt;br /&gt;
class EXAMPLE [G]&lt;br /&gt;
feature&lt;br /&gt;
  example (a_g: G): G&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/e&amp;gt;&lt;br /&gt;
&lt;br /&gt;
A type declaration with this syntax would look like:&lt;br /&gt;
&amp;lt;e&amp;gt;&lt;br /&gt;
local&lt;br /&gt;
 l_example: EXAMPLE [EMLPOYED_STYDENT: STUDENT]&lt;br /&gt;
 l_employed_student: EMPLOYED_STUDENT&lt;br /&gt;
 l_person: PERSON&lt;br /&gt;
do&lt;br /&gt;
 -- l_example.example (a_g: EMPLOYED_STUDENT): STUDENT &lt;br /&gt;
  l_person := l_example.example (l_employed_student) -- valid&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/e&amp;gt;&lt;br /&gt;
But let's stick with the initial syntax for now.&lt;br /&gt;
&lt;br /&gt;
==Agents==&lt;br /&gt;
&lt;br /&gt;
The neat thing about this extension is, that there is no need to cut down the expressiveness of the agent mechanism to make them perfectly save to use with full support for all legal situations. &lt;br /&gt;
&lt;br /&gt;
Procedure class:&lt;br /&gt;
&amp;lt;e&amp;gt;&lt;br /&gt;
class PROCEDURE [BASE_TYPE, OPEN_ARGS -&amp;gt; TUPLE []]&lt;br /&gt;
    -- Signature of call is generated by the compiler. To visualize this we add _reflected to the argument tuple.&lt;br /&gt;
  call (args: OPEN_ARGS_reflected)&lt;br /&gt;
    do end&lt;br /&gt;
&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/e&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==agent (T)==&lt;br /&gt;
&lt;br /&gt;
Type declaration:&lt;br /&gt;
&amp;lt;e&amp;gt;&lt;br /&gt;
an_agent: PROCEDURE [ANY..NONE, TUPLE..TUPLE [ANY..T]]  --&amp;gt; like agent (T)&lt;br /&gt;
  -- signature for call has to be inverted: TUPLE [T..NONE]..NONE&lt;br /&gt;
&lt;br /&gt;
  -- legal&lt;br /&gt;
an_agent.call ([T])&lt;br /&gt;
an_agent.call ([T, ...])&lt;br /&gt;
an_agent.call ([U, ...])&lt;br /&gt;
&lt;br /&gt;
  -- illegal&lt;br /&gt;
an_agent.call ([])&lt;br /&gt;
&amp;lt;/e&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Instantiation:&lt;br /&gt;
&amp;lt;e&amp;gt;&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;
&lt;br /&gt;
  -- legal&lt;br /&gt;
an_agent := agent_empty&lt;br /&gt;
an_agent := agent_any&lt;br /&gt;
an_agent := agent_t&lt;br /&gt;
&lt;br /&gt;
  -- illegal&lt;br /&gt;
an_agent := agent_u&lt;br /&gt;
&amp;lt;/e&amp;gt;&lt;br /&gt;
&lt;br /&gt;
There might be a concern about the fact that the compiler generates the signature of the call method. But I think that its not wrong to have compiler support for agents, as they are such a fundamental core concept that is simply important that one could sacrifice expressive power or type safety just to avoid explicit support from the compiler.&lt;br /&gt;
&lt;br /&gt;
== How to generate the call signature for a given agent type ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;todo&amp;gt;&lt;/div&gt;</summary>
		<author><name>Seilerm</name></author>	</entry>

	<entry>
		<id>https://dev.eiffel.com/index.php?title=Preventing_CAT_calls_in_Generics&amp;diff=7867</id>
		<title>Preventing CAT calls in Generics</title>
		<link rel="alternate" type="text/html" href="https://dev.eiffel.com/index.php?title=Preventing_CAT_calls_in_Generics&amp;diff=7867"/>
				<updated>2007-04-07T20:02:49Z</updated>
		
		<summary type="html">&lt;p&gt;Seilerm: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Category:ECMA]]&lt;br /&gt;
{{Warning|'''Warning''': Article under development}}&lt;br /&gt;
&lt;br /&gt;
==Introduction==&lt;br /&gt;
&lt;br /&gt;
===Example===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;e&amp;gt;&lt;br /&gt;
class T &lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
class U &lt;br /&gt;
inherit T &lt;br /&gt;
  -- no covariant feature redefinition&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/e&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Conformance==&lt;br /&gt;
&lt;br /&gt;
===Type conformance===&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
| conforms to &lt;br /&gt;
! T &lt;br /&gt;
! T..NONE &lt;br /&gt;
! ANY..T&lt;br /&gt;
! U&lt;br /&gt;
|-&lt;br /&gt;
! T           &lt;br /&gt;
| true &lt;br /&gt;
| false &lt;br /&gt;
| true&lt;br /&gt;
| false&lt;br /&gt;
|-&lt;br /&gt;
! T..NONE     &lt;br /&gt;
| true &lt;br /&gt;
| false &lt;br /&gt;
| true&lt;br /&gt;
| false&lt;br /&gt;
|-&lt;br /&gt;
! ANY..T      &lt;br /&gt;
| false &lt;br /&gt;
| false &lt;br /&gt;
| false&lt;br /&gt;
| false&lt;br /&gt;
|-&lt;br /&gt;
! U&lt;br /&gt;
| true&lt;br /&gt;
| false&lt;br /&gt;
| true&lt;br /&gt;
| true&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
===Generic conformance===&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
| conforms to&lt;br /&gt;
! LIST [ANY]&lt;br /&gt;
! LIST [T]&lt;br /&gt;
! LIST [T..NONE]&lt;br /&gt;
! LIST [ANY..T]&lt;br /&gt;
! LIST [U]&lt;br /&gt;
|-&lt;br /&gt;
! LIST [ANY]&lt;br /&gt;
| true&lt;br /&gt;
| false&lt;br /&gt;
| false&lt;br /&gt;
| true&lt;br /&gt;
| false&lt;br /&gt;
|-&lt;br /&gt;
! LIST [T]&lt;br /&gt;
| false&lt;br /&gt;
| true&lt;br /&gt;
| true&lt;br /&gt;
| true&lt;br /&gt;
| false&lt;br /&gt;
|-&lt;br /&gt;
! LIST [T..NONE]&lt;br /&gt;
| false&lt;br /&gt;
| false&lt;br /&gt;
| true&lt;br /&gt;
| false&lt;br /&gt;
| false&lt;br /&gt;
|-&lt;br /&gt;
! LIST [ANY..T]&lt;br /&gt;
| false&lt;br /&gt;
| false &lt;br /&gt;
| false &lt;br /&gt;
| true&lt;br /&gt;
| false&lt;br /&gt;
|-&lt;br /&gt;
! LIST [U]&lt;br /&gt;
| false&lt;br /&gt;
| '''false'''&lt;br /&gt;
| true&lt;br /&gt;
| false&lt;br /&gt;
| true&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;e&amp;gt;&lt;br /&gt;
  -- legal&lt;br /&gt;
T := LIST [T..NONE] .item&lt;br /&gt;
LIST [T..NONE] .put (Void)&lt;br /&gt;
&lt;br /&gt;
  -- illegal&lt;br /&gt;
U := LIST [T..NONE] .item&lt;br /&gt;
LIST [T..NONE] .put (T)&lt;br /&gt;
&lt;br /&gt;
  -- legal&lt;br /&gt;
LIST [ANY..T] .put (T)&lt;br /&gt;
LIST [ANY..T] .put (U)&lt;br /&gt;
ANY := LIST [ANY..T] .item&lt;br /&gt;
&lt;br /&gt;
  -- illegal&lt;br /&gt;
LIST [ANY..T] .put (ANY)&lt;br /&gt;
T := LIST [ANY..T] .item&lt;br /&gt;
&amp;lt;/e&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== How should one understand this? ==&lt;br /&gt;
&amp;lt;e&amp;gt;&lt;br /&gt;
class PERSON&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
class STUDENT&lt;br /&gt;
inherit&lt;br /&gt;
 PERSON&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
class EMPLOYEE&lt;br /&gt;
inherit&lt;br /&gt;
 PERSON&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
class EMPLOYED_STUDENT&lt;br /&gt;
inherit&lt;br /&gt;
 EMPLOYEE&lt;br /&gt;
 STUDENT&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/e&amp;gt;&lt;br /&gt;
What this actually is, is an extension to the type system. It helps you to proper derive an interface of a generic type.&lt;br /&gt;
For example an actual type parameter for G in &amp;lt;e&amp;gt;LIST [G]&amp;lt;/e&amp;gt; is [PERSON..EMPLOYED_STUDENT].&lt;br /&gt;
The interface generated by this derivations is simply that the first type (PERSON) is taken wherever G occurs as a return type.&lt;br /&gt;
The second type EMPLOYED_STUDENT is taken wherever G occurs as an argument type.&lt;br /&gt;
&lt;br /&gt;
 '''The conformance rules for such new interfaces simply reflect that arguments are contra-variant and return types are covariant.'''&lt;br /&gt;
&lt;br /&gt;
&amp;lt;e&amp;gt;&lt;br /&gt;
(generic derived) class LIST[PERSON..EMPLOYED_STUDENT]&lt;br /&gt;
&lt;br /&gt;
  put (v: EMPLOYED_STUDENT)&lt;br /&gt;
  &lt;br /&gt;
  item: PERSON&lt;br /&gt;
&amp;lt;/e&amp;gt;&lt;br /&gt;
&lt;br /&gt;
That's basically all there is to say about this enhancement to the Eiffel type system.&lt;br /&gt;
Except that one might adapt the syntax, another idea is:&lt;br /&gt;
&amp;lt;type_for_arguments&amp;gt;:&amp;lt;type_for_return_types&amp;gt;&lt;br /&gt;
This would more resemble an actual generated signature of a feature which looks initialy like&lt;br /&gt;
&amp;lt;e&amp;gt;&lt;br /&gt;
class EXAMPLE [G]&lt;br /&gt;
feature&lt;br /&gt;
  example (a_g: G): G&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/e&amp;gt;&lt;br /&gt;
&lt;br /&gt;
A type declaration with this syntax would look like:&lt;br /&gt;
&amp;lt;e&amp;gt;&lt;br /&gt;
local&lt;br /&gt;
 l_example: EXAMPLE [EMLPOYED_STYDENT: STUDENT]&lt;br /&gt;
 l_employed_student: EMPLOYED_STUDENT&lt;br /&gt;
 l_person: PERSON&lt;br /&gt;
do&lt;br /&gt;
 -- l_example.example (a_g: EMPLOYED_STUDENT): STUDENT &lt;br /&gt;
  l_person := l_example.example (l_employed_student)&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/e&amp;gt;&lt;br /&gt;
But let's stick with the initial syntax for now.&lt;br /&gt;
&lt;br /&gt;
==Agents==&lt;br /&gt;
&lt;br /&gt;
The neat thing about this extension is, that there is no need to cut down the expressiveness of the agent mechanism to make them perfectly save to use with full support for all legal situations. &lt;br /&gt;
&lt;br /&gt;
Procedure class:&lt;br /&gt;
&amp;lt;e&amp;gt;&lt;br /&gt;
class PROCEDURE [BASE_TYPE, OPEN_ARGS -&amp;gt; TUPLE []]&lt;br /&gt;
    -- Signature of call is generated by the compiler. To visualize this we add _reflected to the argument tuple.&lt;br /&gt;
  call (args: OPEN_ARGS_reflected) -- valid&lt;br /&gt;
    do end&lt;br /&gt;
&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/e&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==agent (T)==&lt;br /&gt;
&lt;br /&gt;
Type declaration:&lt;br /&gt;
&amp;lt;e&amp;gt;&lt;br /&gt;
an_agent: PROCEDURE [ANY..NONE, TUPLE..TUPLE [ANY..T]]  --&amp;gt; like agent (T)&lt;br /&gt;
  -- signature for call has to be inverted: TUPLE [T..NONE]..NONE&lt;br /&gt;
&lt;br /&gt;
  -- legal&lt;br /&gt;
an_agent.call ([T])&lt;br /&gt;
an_agent.call ([T, ...])&lt;br /&gt;
an_agent.call ([U, ...])&lt;br /&gt;
&lt;br /&gt;
  -- illegal&lt;br /&gt;
an_agent.call ([])&lt;br /&gt;
&amp;lt;/e&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Instantiation:&lt;br /&gt;
&amp;lt;e&amp;gt;&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;
&lt;br /&gt;
  -- legal&lt;br /&gt;
an_agent := agent_empty&lt;br /&gt;
an_agent := agent_any&lt;br /&gt;
an_agent := agent_t&lt;br /&gt;
&lt;br /&gt;
  -- illegal&lt;br /&gt;
an_agent := agent_u&lt;br /&gt;
&amp;lt;/e&amp;gt;&lt;br /&gt;
&lt;br /&gt;
There might be a concern about the fact that the compiler generates the signature of the call method. But I think that its not wrong to have compiler support for agents, as they are such a fundamental core concept that is simply important that one could sacrifice expressive power or type safety just to avoid explicit support from the compiler.&lt;br /&gt;
&lt;br /&gt;
== How to generate the call signature for a given agent type ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;todo&amp;gt;&lt;/div&gt;</summary>
		<author><name>Seilerm</name></author>	</entry>

	</feed>