gobo-eiffel / gobo

The Gobo Eiffel Project provides the Eiffel community with free and portable Eiffel tools and libraries.
https://sourceforge.net/projects/gobo-eiffel/
Other
59 stars 24 forks source link

gec compiler bug: type '[detachable] STRING_8' of actual argument #1 does not conform to type '[attached] UC_STRING' of formal argument in feature `is_equal' in class '[detachable] UC_STRING' #71

Closed mw66 closed 6 months ago

mw66 commented 6 months ago

Why I cannot make this is_equal call compile?

query := a_class.queries.item(i)
if query.is_attribute and query.first_precursor /= Void then
    if attached query.first_precursor as l_first_precursor then
        if attached l_first_precursor.lower_name as l_lower_name then
             if not query.lower_name.is_equal(l_lower_name) then
              ...

[CATCALL] class [detachable] GEDOC_FIELD_RENAME_FORMAT (142,17): type '[detachable] STRING_8' of actual argument #1 does not conform to type '[attached] UC_STRING' of formal argument in feature `is_equal' in class '[detachable] UC_STRING'
[CATCALL] class [detachable] GEDOC_FIELD_RENAME_FORMAT (142,17): type '[detachable] STRING_8' of actual argument #1 does not conform to type '[attached] UC_UTF8_STRING' of formal argument in feature `is_equal' in class '[detachable] UC_UTF8_STRING'
[CATCALL] class [detachable] GEDOC_FIELD_RENAME_FORMAT (142,17): type '[detachable] UC_STRING' of actual argument #1 does not conform to type '[attached] UC_UTF8_STRING' of formal argument in feature `is_equal' in class '[detachable] UC_UTF8_STRING'

I checked the Void, and if attached ..., why it's still complaining?

mw66 commented 6 months ago

This code cannot compile:

https://github.com/joortcom/gobo/commit/b4fd52e07e4f1b5d9b7b27a2cedcd935878bd3af#diff-a7967707997bb7d8ded4e15dcf1dd46aba93e4e5c10276de9956b75477478a9dR141

mw66 commented 6 months ago

looks like a gec bug, I can use ISE compiler without any problem with the same code:

$ ec -finalize -config src/system.ecf
This project has more than one target: 
 [1] all_classes
 [2] gedoc

Select the target you want (0 to quit): 2
Eiffel Compilation Manager
Version 23.09.10.7341 - linux-x86-64

Degree 6: Examining System
Degree 5: Parsing Classes
Degree 4: Analyzing Inheritance
Degree 3: Checking Types
Degree 2: Generating Byte Code
Degree 1: Generating Metadata
Melting System Changes
...
ebezault commented 6 months ago

It's not a bug in gec. Let me first explain what a CAT-call is. Let's assume we have this code:

class ANIMAL

feature

    f (other: ANIMAL)
        do
        end

end

and:

class BIRD

inherit

    ANIMAL
        redefine
            f
        end

feature

    f (other: BIRD)
        do
            other.fly
        end

    fly
        do
            print ("fly")
        end

end

and finally:

class AA

create

    make

feature

    make
        local
            a: ANIMAL
            other: ANIMAL
            b: BIRD
        do
            create b
            a := b
            create other
            a.f (other)
        end

end

At runtime a is a bird, but other is a regular animal. So we will try to call fly on a regular animal, but there is no such routine in class ANIMAL. The Gobo Eiffel compiler tries to warn about this problem at compile time:

PS C:\sandbox> gec system.ecf
Degree 6: 0/0/0 0:0:0.033
Degree 5: 0/0/0 0:0:0.212
Degree 4: 0/0/0 0:0:0.092
Degree 3: 0/0/0 0:0:0.066
[CATCALL] class [detachable] AA (18,4): type '[detachable] ANIMAL' of actual argument #1 does not conform to type '[attached] BIRD' of formal argument in feature `f' in class '[detachable] BIRD'
Degree -2: 0/0/0 0:0:0.019
Degree -3: 0/0/0 0:0:0.037
Degree -4: 0/0/0 0:0:3.586
Total Time: 0/0/0 0:0:4.051

But by default this should just be a warning. An executable should have been generated. And if you execute it:

PS C:\sandbox> .\aa.exe
CAT-call error!

aa: system execution failed.
Following is the set of recorded exceptions:

-------------------------------------------------------------------------------
Class / Object      Routine                Nature of exception           Effect
-------------------------------------------------------------------------------
AA                  root's creation        CAT-call error.:
<0000000000000000>                         Developer exception.          Fail
-------------------------------------------------------------------------------
AA                  root's creation
<0000000000000000>                         Routine failure.              Exit
-------------------------------------------------------------------------------

gec has a command-line option --catcall:

    --catcall=no|error|warning
                          Should CAT-call errors be considered as fatal errors,
                          as warnings, or just ignored? (default: warning)

So if you don't want to see the warning, just use --catcall=no. With this option, it will behave like ISE Eiffel where is does not warn at compile time, but raises an exception at runtime. This is what we get with ISE Eiffel:

PS C:\sandbox> .\EIFGENs\aa\W_code\aa.exe
Catcall detected in {BIRD}.f for arg#1: expected BIRD but got ANIMAL

aa: system execution failed.
Following is the set of recorded exceptions:

-------------------------------------------------------------------------------
Class / Object      Routine                Nature of exception           Effect
-------------------------------------------------------------------------------
BIRD                f @1                   Segmentation violation:
<000001D97CD095C8>                         Operating system signal.      Fail
-------------------------------------------------------------------------------
BIRD                f @1
<000001D97CD095C8>                         Routine failure.              Fail
-------------------------------------------------------------------------------
AA                  make @4
<000001D97CD09588>                         Routine failure.              Fail
-------------------------------------------------------------------------------
AA                  root's creation
<000001D97CD09588>                         Routine failure.              Exit
-------------------------------------------------------------------------------

The warning reported by gec is based on dynamic type set analysis. It means that gec has detected some likelihood that a CAT-call may occur at runtime. But there is no guarantee that this will actually happen. It depends on the actual execution path in the code.

Now back to your actual code. The routine is_equal is often the source of CAT-call. So I would recommend using same_string instead. But here, when comparing the name of features, I would rather use:

query := a_class.queries.item(i)
if query.is_attribute and attached query.first_precursor as l_first_precursor then
        if not query.name.same_feature_name (l_first_precursor.name) then