[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

bugs old and new



Gregor,
Just a reminder on this bug which could start biting others as they
compose more complicated class hierarchies ...

Date: Wed, 7 Sep 88 14:54:59 CDT
From: Rob Pettengill <rcp>
To: Gregor.pa@Xerox.com
Subject: Bug in effective method computation (compute-combination-points)
Cc: CommonLoops.pa@Xerox.COM, halasz

;;; -*- Mode:Lisp; Package: pclt; Syntax:COMMON-LISP; Base:10 -*-
#|
; (LISP-IMPLEMENTATION-TYPE) = Allegro CL
; (LISP-IMPLEMENTATION-VERSION) = 3.0.1 [sun3] (8/16/88 17:44)
; (SOFTWARE-TYPE) = SMI Unix
; (MACHINE-TYPE) = Sun Microsystems
; PCL::*PCL-SYSTEM-DATE* = 8/28/88 (beta rev 1) AAAI PCL 

This file illustrates a bug in the computation of combined methods which
results in the the effective method missing certain inherited methods.
A simple class hierarchy with a single method foo that illustrates this bug
is shown below.

       	       	   A-WITH-FOO
		   /       \
		  /         \
		 /           \
		/             \
	 B-WITH-FOO       C-WITH-FOO
	     | 	       	 /     |
	     |	 	/      |
	     |	       /       |
             D-WITH-FOO	       E-WITHOUT-FOO
                 \            /
        	  \          /
       		   \        /
		    \      /
		     \    /
		      \  /
		F-WITH-BAZ-THAT-CALLS-FOO


The expected outcome of a call to BAZ on an instance of
F-WITH-BAZ-THAT-CALLS-FOO should be 
<cl> (pclt::run-test)

Hello from BAZ in F
Hello from FOO in D-WITH-FOO
Hello from FOO in B-WITH-FOO
Hello from FOO in C-WITH-FOO
Hello from FOO in A-WITH-FOO
NIL 

however the actual outcome is

<cl> (pclt::run-test)

Hello from BAZ in F
Hello from FOO in B-WITH-FOO
Hello from FOO in C-WITH-FOO
Hello from FOO in A-WITH-FOO
NIL 

We have found a kludge that fixes this particular case by the following
change to combin.lisp
(defun compute-combination-points (generic-function)    
  (let* ((gf-methods (generic-function-methods generic-function))
	 (result ()))      
    (dolist (m (append gf-methods gf-methods))
               ______________________________ changed from gf-methods
so that the list of methods is traversed twice ...

|#
(IN-PACKAGE 'PCLT :USE '(PCL LISP))

(defclass A-WITH-FOO
  ()
  ()
  )

(defmethod FOO ((SELF A-WITH-FOO))
  (format t "~%Hello from FOO in A-WITH-FOO")
  )

(defclass B-WITH-FOO
  (A-WITH-FOO)
  ()
  )

(defmethod FOO ((SELF B-WITH-FOO))
  (format t "~%Hello from FOO in B-WITH-FOO")
  (call-next-method))

(defclass C-WITH-FOO
  (A-WITH-FOO)
  ( )
  )

(defmethod FOO
  ((SELF C-WITH-FOO))
  (format t "~%Hello from FOO in C-WITH-FOO")
  (call-next-method)
  )


(defclass D-WITH-FOO
  (B-WITH-FOO  C-WITH-FOO) ;was bordered- ...
  ()
  )

(defmethod FOO
  ((SELF D-WITH-FOO))
  (format t "~%Hello from FOO in D-WITH-FOO")
  (call-next-method)
  )

(defclass E-WITHOUT-FOO
  (C-WITH-FOO)
  ()
  )

(defclass F-WITH-BAZ-THAT-CALLS-FOO
  (D-WITH-FOO E-WITHOUT-FOO)
  ()
  )

(defmethod BAZ
   ((SELF F-WITH-BAZ-THAT-CALLS-FOO))
  (format t "~%Hello from BAZ in F")
  (FOO SELF))

(defun run-test ()
  (let ((x (make-instance 'F-WITH-BAZ-THAT-CALLS-FOO)))
    (baz x)))