[BUG] Endless loop when accepting class definition

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
3 messages Options
Reply | Threaded
Open this post in threaded view
|

[BUG] Endless loop when accepting class definition

Joachim Geidel
Hi,

I accidentally accepted a class definition for an existing class MyClass
which had subclasses and defined the class to be a subclass of itself:

MyNamespace.SubNamespace defineClass: #MyClass
        superclass: #{SubNamespace.MyClass}
        indexedType: #none
        private: false
        instanceVariableNames: ''
        classInstanceVariableNames: ''
        imports: ''
        category: 'MyCategory'

After several minutes I wondered what VisualWorks was doing all the time
and interrupted it. BehaviorBuilderRecord>>verify was in an endless loop
in the following statements when verifying a record for a subclass of
MyClass, which was done before verifying the record for MyClass:

        [s == nil] whileFalse:
                [s fullName = self fullName ifTrue:
                        [self buildError: ((#errSubclassItself << #dialogs >> 'The behavior
<1s> is being made a subclass of itself.') expandMacrosWith: self
fullName)].
                        s := s superclass].

"s := s superclass" always resulted in MyClass. A fix for
BehaviorBuilderRecord>>verify is attached.

Joachim Geidel


<?xml version="1.0"?>

<st-source>
<time-stamp>From VisualWorks® NonCommercial, 7.4.1 of 30. Mai 2006 on 17. Juli 2006 at 18:40:41</time-stamp>


<methods>
<class-id>Kernel.BehaviorBuilderRecord</class-id> <category>mutation</category>

<body package="Kernel-Classes" selector="verify">verify

        | list superType cType s |
        s := self superclass.
        [s == nil] whileFalse:
                [| fullName |
                fullName := s fullName.
                fullName = self fullName ifTrue:
                        [self buildError: ((#errSubclassItself &lt;&lt; #dialogs &gt;&gt; 'The behavior &lt;1s&gt; is being made a subclass of itself.') expandMacrosWith: self fullName)].
                fullName = s superclass fullName ifTrue:
                        [self buildError: ((#errSubclassItself &lt;&lt; #dialogs &gt;&gt; 'The behavior &lt;1s&gt; is being made a subclass of itself.') expandMacrosWith: fullName)].
                        s := s superclass].
        superType := self superBehaviorType.
        ((Behavior isType: self behaviorType legalSubclassTypeForSuperclassType: superType) or:
                        [Behavior isType: self behaviorType promotableSubclassTypeForSuperclassType: superType])
                ifFalse: [self buildError:
                        (((#errCannotBeSubclasses &lt;&lt; #dialogs &gt;&gt; 'Classes of type &lt;1s&gt; cannot be subclasses of classes of type &lt;2s&gt;.')
                                expandMacrosWith: self behaviorType
                                with: superType))].
        cType := (Behavior isType: self behaviorType promotableSubclassTypeForSuperclassType: superType)
                ifTrue: [superType]
                ifFalse: [self behaviorType].
        list := self allInstVarNames.
        ((#(#immediate #bytes) includes: cType) and: [list isEmpty not]) ifTrue:
                [self buildError: (#ByteTypeInstanceVariables &lt;&lt; #dialogs &gt;&gt; 'Byte-type objects cannot have named instance variables')].
        list size &gt; 4095 ifTrue:
                [self buildError: (#errInstanceLimit &lt;&lt; #dialogs &gt;&gt; 'An object is limited to only 255 named instance variables')].
        list := list, #('self' 'super' 'thisContext' 'true' 'false' 'nil').
        list size = list asSet size ifFalse:
                [list do:
                        [:str |
                        (list occurrencesOf: str) = 1 ifFalse:
                                [self buildError: ((#variableOverloaded &lt;&lt; #dialogs &gt;&gt; 'The variable name "&lt;1s&gt;" is overloaded for &lt;2s&gt;' ) expandMacrosWith: str with: self fullName)]]].</body>
</methods>

</st-source>
Reply | Threaded
Open this post in threaded view
|

Re: [BUG] Endless loop when accepting class definition

Alan Knight-2
As Kent Beck would say, "Then don't do that" :-)

This is now AR 50997.

At 12:46 PM 7/17/2006, Joachim Geidel wrote:

>Hi,
>
>I accidentally accepted a class definition for an existing class MyClass
>which had subclasses and defined the class to be a subclass of itself:
>
>MyNamespace.SubNamespace defineClass: #MyClass
>        superclass: #{SubNamespace.MyClass}
>        indexedType: #none
>        private: false
>        instanceVariableNames: ''
>        classInstanceVariableNames: ''
>        imports: ''
>        category: 'MyCategory'
>
>After several minutes I wondered what VisualWorks was doing all the time
>and interrupted it. BehaviorBuilderRecord>>verify was in an endless loop
>in the following statements when verifying a record for a subclass of
>MyClass, which was done before verifying the record for MyClass:
>
>        [s == nil] whileFalse:
>                [s fullName = self fullName ifTrue:
>                        [self buildError: ((#errSubclassItself << #dialogs >> 'The behavior
><1s> is being made a subclass of itself.') expandMacrosWith: self
>fullName)].
>                        s := s superclass].
>
>"s := s superclass" always resulted in MyClass. A fix for
>BehaviorBuilderRecord>>verify is attached.
>
>Joachim Geidel
>
>
><?xml version="1.0"?>
>
><st-source>
><time-stamp>From VisualWorks® NonCommercial, 7.4.1 of 30. Mai 2006 on 17. Juli 2006 at 18:40:41</time-stamp>
>
>
><methods>
><class-id>Kernel.BehaviorBuilderRecord</class-id> <category>mutation</category>
>
><body package="Kernel-Classes" selector="verify">verify
>
>        | list superType cType s |
>        s := self superclass.
>        [s == nil] whileFalse:
>                [| fullName |
>                fullName := s fullName.
>                fullName = self fullName ifTrue:
>                        [self buildError: ((#errSubclassItself &lt;&lt; #dialogs &gt;&gt; 'The behavior &lt;1s&gt; is being made a subclass of itself.') expandMacrosWith: self fullName)].
>                fullName = s superclass fullName ifTrue:
>                        [self buildError: ((#errSubclassItself &lt;&lt; #dialogs &gt;&gt; 'The behavior &lt;1s&gt; is being made a subclass of itself.') expandMacrosWith: fullName)].
>                        s := s superclass].
>        superType := self superBehaviorType.
>        ((Behavior isType: self behaviorType legalSubclassTypeForSuperclassType: superType) or:
>                        [Behavior isType: self behaviorType promotableSubclassTypeForSuperclassType: superType])
>                ifFalse: [self buildError:
>                        (((#errCannotBeSubclasses &lt;&lt; #dialogs &gt;&gt; 'Classes of type &lt;1s&gt; cannot be subclasses of classes of type &lt;2s&gt;.')
>                                expandMacrosWith: self behaviorType
>                                with: superType))].
>        cType := (Behavior isType: self behaviorType promotableSubclassTypeForSuperclassType: superType)
>                ifTrue: [superType]
>                ifFalse: [self behaviorType].
>        list := self allInstVarNames.
>        ((#(#immediate #bytes) includes: cType) and: [list isEmpty not]) ifTrue:
>                [self buildError: (#ByteTypeInstanceVariables &lt;&lt; #dialogs &gt;&gt; 'Byte-type objects cannot have named instance variables')].
>        list size &gt; 4095 ifTrue:
>                [self buildError: (#errInstanceLimit &lt;&lt; #dialogs &gt;&gt; 'An object is limited to only 255 named instance variables')].
>        list := list, #('self' 'super' 'thisContext' 'true' 'false' 'nil').
>        list size = list asSet size ifFalse:
>                [list do:
>                        [:str |
>                        (list occurrencesOf: str) = 1 ifFalse:
>                                [self buildError: ((#variableOverloaded &lt;&lt; #dialogs &gt;&gt; 'The variable name "&lt;1s&gt;" is overloaded for &lt;2s&gt;' ) expandMacrosWith: str with: self fullName)]]].</body>
></methods>
>
></st-source>

--
Alan Knight [|], Cincom Smalltalk Development
[hidden email]
[hidden email]
http://www.cincom.com/smalltalk

"The Static Typing Philosophy: Make it fast. Make it right. Make it run." - Niall Ross

Reply | Threaded
Open this post in threaded view
|

Re: [BUG] Endless loop when accepting class definition

Joachim Geidel
In reply to this post by Joachim Geidel
I should have tested my bug fix a bit more thoroughly. :-(
Forgot to check if the superclass record is nil before asking for its
fullName. The patch of the patch is attached.

Joachim

> Hi,
>
> I accidentally accepted a class definition for an existing class MyClass
> which had subclasses and defined the class to be a subclass of itself:
>
> MyNamespace.SubNamespace defineClass: #MyClass
> superclass: #{SubNamespace.MyClass}
> indexedType: #none
> private: false
> instanceVariableNames: ''
> classInstanceVariableNames: ''
> imports: ''
> category: 'MyCategory'
>
> After several minutes I wondered what VisualWorks was doing all the time
> and interrupted it. BehaviorBuilderRecord>>verify was in an endless loop
> in the following statements when verifying a record for a subclass of
> MyClass, which was done before verifying the record for MyClass:
>
> [s == nil] whileFalse:
> [s fullName = self fullName ifTrue:
> [self buildError: ((#errSubclassItself << #dialogs >> 'The behavior
> <1s> is being made a subclass of itself.') expandMacrosWith: self
> fullName)].
> s := s superclass].
>
> "s := s superclass" always resulted in MyClass. A fix for
> BehaviorBuilderRecord>>verify is attached.
>
> Joachim Geidel

<?xml version="1.0"?>

<st-source>
<time-stamp>From VisualWorks® NonCommercial, 7.4.1 of 30. Mai 2006 on 17. Juli 2006 at 18:57:41</time-stamp>


<methods>
<class-id>Kernel.BehaviorBuilderRecord</class-id> <category>mutation</category>

<body package="Kernel-Classes" selector="verify">verify

        | list superType cType s |
        s := self superclass.
        [s == nil] whileFalse:
                [| fullName |
                fullName := s fullName.
                fullName = self fullName ifTrue:
                        [self buildError: ((#errSubclassItself &lt;&lt; #dialogs &gt;&gt; 'The behavior &lt;1s&gt; is being made a subclass of itself.') expandMacrosWith: self fullName)].
                (s superclass ~~ nil and: [fullName = s superclass fullName]) ifTrue:
                        [self buildError: ((#errSubclassItself &lt;&lt; #dialogs &gt;&gt; 'The behavior &lt;1s&gt; is being made a subclass of itself.') expandMacrosWith: fullName)].
                        s := s superclass].
        superType := self superBehaviorType.
        ((Behavior isType: self behaviorType legalSubclassTypeForSuperclassType: superType) or:
                        [Behavior isType: self behaviorType promotableSubclassTypeForSuperclassType: superType])
                ifFalse: [self buildError:
                        (((#errCannotBeSubclasses &lt;&lt; #dialogs &gt;&gt; 'Classes of type &lt;1s&gt; cannot be subclasses of classes of type &lt;2s&gt;.')
                                expandMacrosWith: self behaviorType
                                with: superType))].
        cType := (Behavior isType: self behaviorType promotableSubclassTypeForSuperclassType: superType)
                ifTrue: [superType]
                ifFalse: [self behaviorType].
        list := self allInstVarNames.
        ((#(#immediate #bytes) includes: cType) and: [list isEmpty not]) ifTrue:
                [self buildError: (#ByteTypeInstanceVariables &lt;&lt; #dialogs &gt;&gt; 'Byte-type objects cannot have named instance variables')].
        list size &gt; 4095 ifTrue:
                [self buildError: (#errInstanceLimit &lt;&lt; #dialogs &gt;&gt; 'An object is limited to only 255 named instance variables')].
        list := list, #('self' 'super' 'thisContext' 'true' 'false' 'nil').
        list size = list asSet size ifFalse:
                [list do:
                        [:str |
                        (list occurrencesOf: str) = 1 ifFalse:
                                [self buildError: ((#variableOverloaded &lt;&lt; #dialogs &gt;&gt; 'The variable name "&lt;1s&gt;" is overloaded for &lt;2s&gt;' ) expandMacrosWith: str with: self fullName)]]].</body>
</methods>

</st-source>