<?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=Chengchangwu</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=Chengchangwu"/>
		<link rel="alternate" type="text/html" href="https://dev.eiffel.com/Special:Contributions/Chengchangwu"/>
		<updated>2026-05-02T13:28:16Z</updated>
		<subtitle>User contributions</subtitle>
		<generator>MediaWiki 1.24.1</generator>

	<entry>
		<id>https://dev.eiffel.com/index.php?title=Preventing_CAT_calls_in_Generics&amp;diff=7880</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=7880"/>
				<updated>2007-04-09T02:07:41Z</updated>
		
		<summary type="html">&lt;p&gt;Chengchangwu: /* Introduction */&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_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 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>Chengchangwu</name></author>	</entry>

	</feed>