Mantis Bug Tracker

View Issue Details Jump to Notes ] Issue History ] Print ]
IDProjectCategoryView StatusDate SubmittedLast Update
0004459OCamlOCaml generalpublic2007-11-29 19:352007-11-30 01:17
Reporterchambart 
Assigned To 
PrioritynormalSeverityminorReproducibilityalways
StatusclosedResolutionfixed 
PlatformOSOS Version
Product Version3.10.0 
Target VersionFixed in Version3.10+dev 
Summary0004459: Problème avec l'héritage et les variables virtuelles
DescriptionLe code :

class virtual a =
object
 val virtual v : int
end

class b =
object
 inherit a
 val v = 1
end

renvoie une exception a l'execution:
Fatal error: exception Not_found
Raised at file "map.ml", line 104, characters 16-25
Called from file "camlinternalOO.ml", line 245, characters 30-54
Called from file "list.ml", line 74, characters 24-34
Called from file "camlinternalOO.ml", line 244, characters 5-100
Called from file "camlinternalOO.ml", line 324, characters 2-11
Called from unknown location
Called from file "camlinternalOO.ml", line 334, characters 17-33
Called from unknown location

Additional Informationpar contre avec

class virtual a =
object
 val virtual v : int
 method get = v
end

il n'y a pas d'exception.

Le problème viens de la simplification dans les lambda termes:

Comme les variables sont declarees avec le tag StrictOpt,
si elle ne sont pas utilisées, leur declaration est suprimée.

avec l'option -drawlamda
  (letrec
    (a/61
       (let (a_tables/71 (makemutable 0 0a 0a 0a))
         (makeblock 0 0a
           (function class/75
             (let
               (v/64 (apply (field 2 (global CamlinternalOO!)) class/75 #"v"))
               (function env/77 self/76
                 (apply (field 23 (global CamlinternalOO!)) self/76 class/75))))
           0a 0a)))

avec -dlamda
  (letrec
    (a/61
       (makeblock 0 0a
         (function class/75
           (function env/77 self/76
             (apply (field 23 (global CamlinternalOO!)) self/76 class/75)))
         0a 0a))


Le problème ne se pose pas avec les méthodes virtuelles car la
déclaration des méthodes se fait avant l'héritage:

class virtual a =
object
  val virtual v : int
  method virtual get : int
end

class b =
object
  inherit a
  val v = 1
  method get = 1
end

avec -dlambda:
(let (shared/96 [0: #"get"] shared/97 [0: #"v"])
    (letrec
      (a/61
         (makeblock 0 0a
           (function class/109
             (function env/111 self/110
               (apply (field 23 (global CamlinternalOO!)) self/110 class/109)))
           0a 0a))
      (letrec
        (b/69
           (let
             (b_init/100
                (function class/90
(* get est déclarée avant l'héritage, donc ce n'est pas grave si la classe a ne l'a pas declare, par contre 'a' n'est déclarée qu'apres *)
                  (let
                    (get/73
                       (apply (field 6 (global CamlinternalOO!)) class/90
                         #"get")
                     inh/98
                       (apply (field 17 (global CamlinternalOO!)) class/90
                         shared/97 shared/96 0a a/61 1a)
                     obj_init/94 (field 0 inh/98)
                     v/72 (field 1 inh/98))
                    (seq
                      (apply (field 9 (global CamlinternalOO!)) class/90
                        get/73
                        (function self-2/75
                          (funct-body 122-136 (before 135-136 1))))
                      (function env/92 self/91
                        (let
                          (self/93
                             (apply (field 23 (global CamlinternalOO!))
                               self/91 class/90))
                          (seq
                            (seq (apply obj_init/94 self/93)
                              (array.unsafe_set self/93 v/72 1))
                            (apply (field 25 (global CamlinternalOO!))
                              self/91 self/93 class/90))))))))
             (apply (field 18 (global CamlinternalOO!)) shared/96 b_init/100)))

Une méthode pour contourner le problème est d'écrire la classe
b sous la forme

class b =
object
  val v = 1
  inherit a
  method get = 1
end


Sinon il est possible d'empecher la simplification problematique du lambda
terme en déclarant les variables par des "let stricts":
remplacer la ligne

      Llet(StrictOpt, id, transl_val tbl create name, rem))

par

      Llet(Strict, id, transl_val tbl create name, rem))

dans la fonction transl_vals de bytecomp/transclass.ml

mais ce n'est pas très satisfaisant.
TagsNo tags attached.
Attached Files

- Relationships

-  Notes
(0004364)
jm (reporter)
2007-11-29 21:22
edited on: 2007-11-29 21:24

Apparemment le problème a été résolu dans la branche release310 :

% ocaml
        Objective Caml version 3.10.1+dev3 (2007-11-26)

# class virtual a =
  object val virtual v : int end;;
class virtual a : object val virtual v : int end
# class b =
  object
   inherit a
   val v = 1
   method get = v
  end;;
class b : object val v : int method get : int end
# print_int (new b)#get;;
1- : unit = ()

Peut-être par ce commit:

Author: Jacques Garrigue
Date: Mon May 21 05:52:07 2007 +0000

    allow delayed creation of virtual instance variables

(0004365)
garrigue (manager)
2007-11-30 01:17

Oui, le probleme apparait quand v n'est pas utilise' dans la classe ou` on l'introduit.
Mais comme vous l'avez remarque', c'est de'ja` corrige'.

- Issue History
Date Modified Username Field Change
2007-11-29 19:35 chambart New Issue
2007-11-29 21:22 jm Note Added: 0004364
2007-11-29 21:24 jm Note Edited: 0004364
2007-11-30 01:17 garrigue Status new => closed
2007-11-30 01:17 garrigue Note Added: 0004365
2007-11-30 01:17 garrigue Resolution open => fixed
2007-11-30 01:17 garrigue Fixed in Version => 3.10+dev


Copyright © 2000 - 2011 MantisBT Group
Powered by Mantis Bugtracker