Re: typing of a class

From: Benoit Deboursetty (debourse@email.enst.fr)
Date: Thu Mar 09 2000 - 01:52:02 MET

  • Next message: Sven LUTHER: "Re: Building a cross-compiling ocaml"

    > I've been using the OO features of Caml these past days, and soon
    > observed a behavior of the typing system that I don't understand. Here
    > is a simplified version of my problem:
    >
    > # class a (arg : a -> b) = object(self)
    > val ob = arg self
    > end
    > and b = object
    > end;;
    >
    > The instance variable self
    > cannot be accessed from the definition of another instance variable
    >
    > I don't understand why it is forbidden for an object to pass itself to
    > another one (which is possible in Java or Eiffel for example). Could
    > someone explain me? Or is there a paper talking about this?

    Ce n'est pas parce que l'objet se passe à un autre qu'une erreur est
    détectée... Mais parce que les variables d'instance ne peuvent pas se
    faire récursivement référence.

    Les variables d'instance sont celles qui sont propres à chaque instance de
    l'objet. Elles sont construites, à l'exécution, les unes après les autres
    dans un ordre non spécifié (sauf "self", qui est toujours la dernière, je
    suppose...) Dans votre cas, "self" et "ob" sont des variables d'instance
    de la classe a.

    Par exemple, imaginez que le système soit au moment de construire la
    première variable d'instance d'un objet, mais que pour la construire il
    ait besoin des autres variables d'instance...

    [J'ai l'impression que c'est le même genre de raison qui empêche (pour le
    moment ?) d'avoir des dépendances cycliques entre modules et des
    applications de fonctions dans les membres droits des "let rec" (et là
    j'interroge l'équipe de caml...)]

    Le problème apparaît si la fonction que vous passez en argument fait accès
    aux méthodes de self. Modifions un peu votre exemple, en faisant
    l'hypothèse que le compilateur accepte le code suivant :

    # class a (arg : a -> int) = object (self)
        val ob = arg self
        method get_ob = ob
      end;;

    # let bad_arg = fun x -> ignore (x#get_ob); 0;;

    # let instance_of_a = new a bad_arg;;

    Que se passe-t-il à la construction de l'instance "instance_of_a" ? En y
    réfléchissant un tout petit peu, vous verrez très vite qu'il va forcément
    y avoir un pointeur invalide déréférencé (dans "bad_arg", "x#get_ob").

    ---
    

    It is not especially forbidden to an object to pass itself to another one.

    The error message means that you cannot recursively nest instance variable declarations. Instance variable means variable that are built with each instance of an object; here, ob and self are instance variable (they are different for each object). When you call "new", the instance variables are built one after the other in a non specified order (except that self is always the last one I suppose). Suppose for example the runtime builds the first instance variable, but that instance variable depends on other instance variable that will only be built later. This is clearly a safeness pitfall!

    (I think it is the same kind of problem that leads to a difficulty in recursively nesting modules and "right side of let rec" problems?)

    Let me somewhat modify your example to show you more concretely the point of the error and assume the compiler accept this:

    # class a (arg : a -> int) = object (self) val ob = arg self method get_ob = ob end

    # let bad_arg = fun x -> ignore (x#get_ob); 0;;

    # let instance_of_a = new a bad_arg;;

    If you only imagine the building of an instance of that object, you will soon see that an invalid pointer is going to be dereferenced no matter what is the runtime implementation.

    Best regards, Benoit de Boursetty.



    This archive was generated by hypermail 2b29 : Fri Mar 10 2000 - 09:12:06 MET