Discussion:
[fpc-devel] Bug in FPC and declaring distinct types
Graeme Geldenhuys
2008-09-18 07:08:04 UTC
Permalink
Hi,

I was following a discussion in the delphi.non-technical newsgroup.
They raised an issue about distinct types. I tried the following
example under FPC and unexpectedly, FPC doesn't raise any errors!

If you declare a distinct type as follows:
type TMyInteger = type Integer;

The type TMyInteger <> Integer so you are not supposed to be allowed
to assign one to the other. Yet you can. See the following program.

----------------------[ test1.pas ]--------------------------
program test1;

{$mode objfpc}{$H+}

uses
Classes, SysUtils;

type
Angle = type Double;
Length = type Double;

function AngleToLength(var a: Angle):Length; { Note the var parameter }
begin
result := a;
end;

function AngleToLength2(a: Angle):Length; { Here is NO var parameter }
begin
result := a;
end;

procedure Test;
var
a: Angle;
l: Length;
d: Double;
begin
d := Now;
a := d;
l := a; // Should this have failed ????

{ FPC raises no errors, but at least Delphi raises an error wit the
var parameter type. }
a := AngleToLength(l); // This should definitely have failed!!
a := AngleToLength2(l); // Should this fail too?
end;

begin
Test;
end.
--------------------------[ end ]-----------------------------

The program was compiled with FPC 2.2.3:
fpc test1.pas
./test1


Regards,
- Graeme -


_______________________________________________
fpGUI - a cross-platform Free Pascal GUI toolkit
http://opensoft.homeip.net/fpgui/
Michael Van Canneyt
2008-09-18 07:42:39 UTC
Permalink
Post by Graeme Geldenhuys
Hi,
I was following a discussion in the delphi.non-technical newsgroup.
They raised an issue about distinct types. I tried the following
example under FPC and unexpectedly, FPC doesn't raise any errors!
type TMyInteger = type Integer;
The type TMyInteger <> Integer so you are not supposed to be allowed
to assign one to the other. Yet you can. See the following program.
But obviously delphi also allows it ? It compiles everything,
just not as a var parameter.

The whole 'Type' thing is a bit ridiculous: the only reason they did it
is so they can have different type pointers in the RTTI for something which
is the same 'type' anyway. For the rest it is extremely badly designed,
and not really consistent. It serves no purpose. FPC introduced it to
be able to compile Delphi code, no other reason.

Michael.
Post by Graeme Geldenhuys
----------------------[ test1.pas ]--------------------------
program test1;
{$mode objfpc}{$H+}
uses
Classes, SysUtils;
type
Angle = type Double;
Length = type Double;
function AngleToLength(var a: Angle):Length; { Note the var parameter }
begin
result := a;
end;
function AngleToLength2(a: Angle):Length; { Here is NO var parameter }
begin
result := a;
end;
procedure Test;
var
a: Angle;
l: Length;
d: Double;
begin
d := Now;
a := d;
l := a; // Should this have failed ????
{ FPC raises no errors, but at least Delphi raises an error wit the
var parameter type. }
a := AngleToLength(l); // This should definitely have failed!!
a := AngleToLength2(l); // Should this fail too?
end;
begin
Test;
end.
--------------------------[ end ]-----------------------------
fpc test1.pas
./test1
Regards,
- Graeme -
_______________________________________________
fpGUI - a cross-platform Free Pascal GUI toolkit
http://opensoft.homeip.net/fpgui/
_______________________________________________
http://lists.freepascal.org/mailman/listinfo/fpc-devel
Graeme Geldenhuys
2008-09-18 08:02:11 UTC
Permalink
On Thu, Sep 18, 2008 at 9:42 AM, Michael Van Canneyt
Post by Michael Van Canneyt
Post by Graeme Geldenhuys
The type TMyInteger <> Integer so you are not supposed to be allowed
to assign one to the other. Yet you can. See the following program.
But obviously delphi also allows it ? It compiles everything,
just not as a var parameter.
Which still doesn't discount it as a bug in both FPC and Delphi! At
least in Delphi it fails on the var parameter, so it's 50% there - it
should really fail on both counts. You are not allowed to do that
(assign different types) with any other types, so why allow it with
custom made types??
Post by Michael Van Canneyt
The whole 'Type' thing is a bit ridiculous: the only reason they did it
is so they can have different type pointers in the RTTI for something which
is the same 'type' anyway. For the rest it is extremely badly designed,
and not really consistent. It serves no purpose. FPC introduced it to
be able to compile Delphi code, no other reason.
I'm not going to get into the whole argument about the usefulness of
distinct types - for that you can read the thread posted in
delphi.non-technical titled: "Generics. How can I?" dated 2008-09-15

All I can say, is that distinct types (custom made types) are used all
over the place, in Delphi, Lazarus, fpGUI and I'm pretty sure FPC as
well. It's a handy language feature and should allow type safety like
all other types.


Regards,
- Graeme -


_______________________________________________
fpGUI - a cross-platform Free Pascal GUI toolkit
http://opensoft.homeip.net/fpgui/
Michael Van Canneyt
2008-09-18 08:11:50 UTC
Permalink
Post by Graeme Geldenhuys
On Thu, Sep 18, 2008 at 9:42 AM, Michael Van Canneyt
Post by Michael Van Canneyt
Post by Graeme Geldenhuys
The type TMyInteger <> Integer so you are not supposed to be allowed
to assign one to the other. Yet you can. See the following program.
But obviously delphi also allows it ? It compiles everything,
just not as a var parameter.
Which still doesn't discount it as a bug in both FPC and Delphi! At
least in Delphi it fails on the var parameter, so it's 50% there - it
should really fail on both counts. You are not allowed to do that
(assign different types) with any other types, so why allow it with
custom made types??
Post by Michael Van Canneyt
The whole 'Type' thing is a bit ridiculous: the only reason they did it
is so they can have different type pointers in the RTTI for something which
is the same 'type' anyway. For the rest it is extremely badly designed,
and not really consistent. It serves no purpose. FPC introduced it to
be able to compile Delphi code, no other reason.
I'm not going to get into the whole argument about the usefulness of
distinct types - for that you can read the thread posted in
delphi.non-technical titled: "Generics. How can I?" dated 2008-09-15
All I can say, is that distinct types (custom made types) are used all
over the place, in Delphi, Lazarus, fpGUI and I'm pretty sure FPC as
well. It's a handy language feature and should allow type safety like
all other types.
And it is also very annoying because

Type
MyString = type string;

Const
AString = 'something';

Var
M : MyString;

begin
M:=AString;
end.

Will no longer compile if you are too strict. They should at least remain
assignment compatible. Delphi does the best it can, FPC should maybe be
a bit more strict - it should not allow the var parameter.

Michael.
Graeme Geldenhuys
2008-09-18 09:31:24 UTC
Permalink
On Thu, Sep 18, 2008 at 10:11 AM, Michael Van Canneyt
Post by Michael Van Canneyt
And it is also very annoying because
Type
MyString = type string;
Const
AString = 'something';
Var
M : MyString;
begin
M:=AString;
end.
Will no longer compile if you are too strict. They should at least remain
assignment compatible.
That's the whole point - it shouldn't be assignment compatible. You
are creating a new MyString type, irrespective of what base-type it
was based on. Only MyString types should be assigned to MyString
types, otherwise you could simply have used String type.

I thought the example given in the delphi.non-technical discussion was
quite a good. Using mathematics and defining a Angle and Elevation
type. Both used the base-type Double. But in a math function you need
to know which one you are working with and what functions allow what
types (speaking of radians and degrees).

"Believe me, if you work with angles, one can easily confuse radians
and degrees (IOW, one can easily forget to convert between them),
especially if the user is used to using degrees, while the library
(sine, cosine, etc.) requires radians." -- Rudy Velthuis


Regards,
- Graeme -


_______________________________________________
fpGUI - a cross-platform Free Pascal GUI toolkit
http://opensoft.homeip.net/fpgui/
Florian Klaempfl
2008-09-18 09:34:55 UTC
Permalink
Post by Graeme Geldenhuys
On Thu, Sep 18, 2008 at 10:11 AM, Michael Van Canneyt
Post by Michael Van Canneyt
And it is also very annoying because
Type
MyString = type string;
Const
AString = 'something';
Var
M : MyString;
begin
M:=AString;
end.
Will no longer compile if you are too strict. They should at least remain
assignment compatible.
That's the whole point - it shouldn't be assignment compatible. You
are creating a new MyString type, irrespective of what base-type it
was based on. Only MyString types should be assigned to MyString
types, otherwise you could simply have used String type.
I thought the example given in the delphi.non-technical discussion was
quite a good.
It's as useless as any talk in this newsgroup. If you don't like two
types being assignment compatible, use classes, records whatever.
Post by Graeme Geldenhuys
Using mathematics and defining a Angle and Elevation
type. Both used the base-type Double. But in a math function you need
to know which one you are working with and what functions allow what
types (speaking of radians and degrees).
"Believe me, if you work with angles, one can easily confuse radians
and degrees (IOW, one can easily forget to convert between them),
especially if the user is used to using degrees, while the library
(sine, cosine, etc.) requires radians." -- Rudy Velthuis
See above.
Graeme Geldenhuys
2008-09-18 10:55:03 UTC
Permalink
On Thu, Sep 18, 2008 at 11:34 AM, Florian Klaempfl
Post by Graeme Geldenhuys
That's the whole point - it shouldn't be assignment compatible. You
are creating a new MyString type, irrespective of what base-type it
was based on. Only MyString types should be assigned to MyString
types, otherwise you could simply have used String type.
I thought the example given in the delphi.non-technical discussion was
quite a good.
It's as useless as any talk in this newsgroup. If you don't like two types
being assignment compatible, use classes, records whatever.
If the developer wants assignment compatibility surely he could then
use the alias types??

eg: #1

type
MyType = Double;
MyOtherType = Double;

With the above types you should have assignment compatibility between
MyType, MyOtherType and Double.
When creating distinct types as show below, type safety should come
into play and assignment compatibility should be broken.

eg: #2

type
MyType = type Double;
MyOtherType = type Double;


Otherwise, what's the different between a "alias" type (eg #1) and a
"distinct" type (eg #2)??


Regards,
- Graeme -


_______________________________________________
fpGUI - a cross-platform Free Pascal GUI toolkit
http://opensoft.homeip.net/fpgui/
Florian Klaempfl
2008-09-18 10:57:48 UTC
Permalink
Post by Graeme Geldenhuys
eg: #2
type
MyType = type Double;
MyOtherType = type Double;
Otherwise, what's the different between a "alias" type (eg #1) and a
"distinct" type (eg #2)??
As I said: overloading. It means: compatible but not equal. If you want
distinct: use as said, classes, records etc.
Florian Klaempfl
2008-09-18 08:51:41 UTC
Permalink
Post by Michael Van Canneyt
Post by Graeme Geldenhuys
Hi,
I was following a discussion in the delphi.non-technical newsgroup.
They raised an issue about distinct types. I tried the following
example under FPC and unexpectedly, FPC doesn't raise any errors!
type TMyInteger = type Integer;
The type TMyInteger <> Integer so you are not supposed to be allowed
to assign one to the other. Yet you can. See the following program.
But obviously delphi also allows it ? It compiles everything,
just not as a var parameter.
The whole 'Type' thing is a bit ridiculous: the only reason they did it
is so they can have different type pointers in the RTTI for something which
is the same 'type' anyway. For the rest it is extremely badly designed,
and not really consistent. It serves no purpose. FPC introduced it to
be able to compile Delphi code, no other reason.
This is not true. The main purpose is to be able to overload
functions/operators:

type
TUTF8String = type ansistring;

enables you to overload all procedure already defined for ansistrings
with UTF8String functions but reusing ansistring support functionality
and this is supported for years. Because nobody used this yet to make an
utf-8 unit, I never took the unicode string support serious :)
Michael Van Canneyt
2008-09-18 09:12:38 UTC
Permalink
Post by Florian Klaempfl
Post by Michael Van Canneyt
Post by Graeme Geldenhuys
Hi,
I was following a discussion in the delphi.non-technical newsgroup.
They raised an issue about distinct types. I tried the following
example under FPC and unexpectedly, FPC doesn't raise any errors!
type TMyInteger = type Integer;
The type TMyInteger <> Integer so you are not supposed to be allowed
to assign one to the other. Yet you can. See the following program.
But obviously delphi also allows it ? It compiles everything,
just not as a var parameter.
The whole 'Type' thing is a bit ridiculous: the only reason they did it
is so they can have different type pointers in the RTTI for something which
is the same 'type' anyway. For the rest it is extremely badly designed, and
not really consistent. It serves no purpose. FPC introduced it to be able to
compile Delphi code, no other reason.
This is not true. The main purpose is to be able to overload
type
TUTF8String = type ansistring;
Well, that was not so for delphi. The delphi help explicitly says:

"if your purpose in defining a new type is to utilize runtime type
information--for example, to associate a property editor with properties of
a particular type--the distinction between "different name" and "different
type" becomes important. In this case, use the syntax"

I've lived with this knowledge for years :-)
Post by Florian Klaempfl
enables you to overload all procedure already defined for ansistrings with
UTF8String functions but reusing ansistring support functionality and this is
supported for years. Because nobody used this yet to make an utf-8 unit, I
never took the unicode string support serious :)
Aha, in that case, you should have told me this so I could document it !

I cannot see inside your head, you know :-)

Maybe make a backup of your brain and send it to me ?
A 1Tb. external disk is no longer so expensive :-)

Michael.
Yury Sidorov
2008-09-18 09:25:55 UTC
Permalink
Post by Florian Klaempfl
Post by Michael Van Canneyt
Post by Graeme Geldenhuys
Hi,
I was following a discussion in the delphi.non-technical
newsgroup.
They raised an issue about distinct types. I tried the following
example under FPC and unexpectedly, FPC doesn't raise any errors!
type TMyInteger = type Integer;
The type TMyInteger <> Integer so you are not supposed to be
allowed
to assign one to the other. Yet you can. See the following
program.
But obviously delphi also allows it ? It compiles everything,
just not as a var parameter.
The whole 'Type' thing is a bit ridiculous: the only reason they did it
is so they can have different type pointers in the RTTI for
something which
is the same 'type' anyway. For the rest it is extremely badly
designed, and not really consistent. It serves no purpose. FPC
introduced it to be able to compile Delphi code, no other reason.
This is not true. The main purpose is to be able to overload
type
TUTF8String = type ansistring;
enables you to overload all procedure already defined for
ansistrings with UTF8String functions but reusing ansistring support
functionality and this is supported for years. Because nobody used
this yet to make an utf-8 unit, I never took the unicode string
support serious :)
Yes. But it works only partially. For example the following code is
not compilable:

//------
type
TUTF8String = type ansistring;

procedure DoTest(const s: ansistring); overload;
begin
end;

procedure DoTest(const s: TUTF8String); overload;
begin
end;

begin
DoTest('1234');
end.

//------

Yury Sidorov.
Florian Klaempfl
2008-09-18 09:36:32 UTC
Permalink
Post by Florian Klaempfl
Post by Michael Van Canneyt
Post by Graeme Geldenhuys
Hi,
I was following a discussion in the delphi.non-technical newsgroup.
They raised an issue about distinct types. I tried the following
example under FPC and unexpectedly, FPC doesn't raise any errors!
type TMyInteger = type Integer;
The type TMyInteger <> Integer so you are not supposed to be allowed
to assign one to the other. Yet you can. See the following program.
But obviously delphi also allows it ? It compiles everything,
just not as a var parameter.
The whole 'Type' thing is a bit ridiculous: the only reason they did it
is so they can have different type pointers in the RTTI for something which
is the same 'type' anyway. For the rest it is extremely badly
designed, and not really consistent. It serves no purpose. FPC
introduced it to be able to compile Delphi code, no other reason.
This is not true. The main purpose is to be able to overload
type
TUTF8String = type ansistring;
enables you to overload all procedure already defined for ansistrings
with UTF8String functions but reusing ansistring support functionality
and this is supported for years. Because nobody used this yet to make
an utf-8 unit, I never took the unicode string support serious :)
Yes. But it works only partially. For example the following code is not
Well, I wouldn't know either what you expect :)
//------
type
TUTF8String = type ansistring;
procedure DoTest(const s: ansistring); overload;
begin
end;
procedure DoTest(const s: TUTF8String); overload;
begin
end;
begin
DoTest('1234');
end.
//------
Yury Sidorov. _______________________________________________
http://lists.freepascal.org/mailman/listinfo/fpc-devel
Yury Sidorov
2008-09-18 13:06:26 UTC
Permalink
Post by Florian Klaempfl
Post by Yury Sidorov
Post by Florian Klaempfl
Post by Michael Van Canneyt
Post by Graeme Geldenhuys
Hi,
I was following a discussion in the delphi.non-technical
newsgroup.
They raised an issue about distinct types. I tried the following
example under FPC and unexpectedly, FPC doesn't raise any
errors!
type TMyInteger = type Integer;
The type TMyInteger <> Integer so you are not supposed to be allowed
to assign one to the other. Yet you can. See the following
program.
But obviously delphi also allows it ? It compiles everything,
just not as a var parameter.
The whole 'Type' thing is a bit ridiculous: the only reason they did it
is so they can have different type pointers in the RTTI for
something which
is the same 'type' anyway. For the rest it is extremely badly
designed, and not really consistent. It serves no purpose. FPC
introduced it to be able to compile Delphi code, no other reason.
This is not true. The main purpose is to be able to overload
type
TUTF8String = type ansistring;
enables you to overload all procedure already defined for
ansistrings with UTF8String functions but reusing ansistring
support functionality and this is supported for years. Because
nobody used this yet to make an utf-8 unit, I never took the
unicode string support serious :)
Yes. But it works only partially. For example the following code is
Well, I wouldn't know either what you expect :)
I expect that compiler will choose DoTest with ansistring parameter in
that case.
Post by Florian Klaempfl
Post by Yury Sidorov
//------
type
TUTF8String = type ansistring;
procedure DoTest(const s: ansistring); overload;
begin
end;
procedure DoTest(const s: TUTF8String); overload;
begin
end;
begin
DoTest('1234');
end.
//------
Florian Klaempfl
2008-09-18 13:14:22 UTC
Permalink
Post by Yury Sidorov
Post by Florian Klaempfl
Post by Yury Sidorov
Yes. But it works only partially. For example the following code is
Well, I wouldn't know either what you expect :)
I expect that compiler will choose DoTest with ansistring parameter in
that case.
What rule do you apply to say this?
Post by Yury Sidorov
Post by Florian Klaempfl
Post by Yury Sidorov
//------
type
TUTF8String = type ansistring;
procedure DoTest(const s: ansistring); overload;
begin
end;
procedure DoTest(const s: TUTF8String); overload;
begin
end;
begin
DoTest('1234');
end.
//------
_______________________________________________
http://lists.freepascal.org/mailman/listinfo/fpc-devel
Yury Sidorov
2008-09-18 13:37:30 UTC
Permalink
From: "Florian Klaempfl" <***@freepascal.org>
To: "FPC developers' list" <fpc-***@lists.freepascal.org>
Sent: Thursday, September 18, 2008 4:14 PM
Subject: Re: [fpc-devel] Bug in FPC and declaring distinct types
Post by Florian Klaempfl
Post by Yury Sidorov
Post by Florian Klaempfl
Post by Yury Sidorov
Yes. But it works only partially. For example the following code
Well, I wouldn't know either what you expect :)
I expect that compiler will choose DoTest with ansistring parameter
in that case.
What rule do you apply to say this?
Compiler treats '1234' as ansistring constant. Therefore ansistring
overload must be choosen here.

Like in this case:

const
sss: ansistring = '1234';
...
DoTest(sss);
Post by Florian Klaempfl
Post by Yury Sidorov
Post by Florian Klaempfl
Post by Yury Sidorov
//------
type
TUTF8String = type ansistring;
procedure DoTest(const s: ansistring); overload;
begin
end;
procedure DoTest(const s: TUTF8String); overload;
begin
end;
begin
DoTest('1234');
end.
//------
Florian Klaempfl
2008-09-18 13:40:10 UTC
Permalink
Post by Yury Sidorov
Sent: Thursday, September 18, 2008 4:14 PM
Subject: Re: [fpc-devel] Bug in FPC and declaring distinct types
Post by Florian Klaempfl
Post by Yury Sidorov
Post by Florian Klaempfl
Post by Yury Sidorov
Yes. But it works only partially. For example the following code is
Well, I wouldn't know either what you expect :)
I expect that compiler will choose DoTest with ansistring parameter
in that case.
What rule do you apply to say this?
Compiler treats '1234' as ansistring constant. Therefore ansistring
overload must be choosen here.
No, '1234' is taken as generic string constant.
Post by Yury Sidorov
const
sss: ansistring = '1234';
...
DoTest(sss);
Post by Florian Klaempfl
Post by Yury Sidorov
Post by Florian Klaempfl
Post by Yury Sidorov
//------
type
TUTF8String = type ansistring;
procedure DoTest(const s: ansistring); overload;
begin
end;
procedure DoTest(const s: TUTF8String); overload;
begin
end;
begin
DoTest('1234');
end.
//------
_______________________________________________
http://lists.freepascal.org/mailman/listinfo/fpc-devel
Graeme Geldenhuys
2008-09-18 13:49:14 UTC
Permalink
On Thu, Sep 18, 2008 at 3:40 PM, Florian Klaempfl
Post by Florian Klaempfl
Post by Yury Sidorov
Post by Florian Klaempfl
What rule do you apply to say this?
Compiler treats '1234' as ansistring constant. Therefore ansistring
overload must be choosen here.
No, '1234' is taken as generic string constant.
And which type is a generic string? When compiled with {$mode objfpc}{$H+}
I would have thought ansistring? Well, at least that is how I
understood the $H directive.

Either way, I still think FPC and Delphi is broken (FPC more so than
Delphi) with regards to distinct type declarations.


Regards,
- Graeme -


_______________________________________________
fpGUI - a cross-platform Free Pascal GUI toolkit
http://opensoft.homeip.net/fpgui/
Florian Klaempfl
2008-09-18 13:55:50 UTC
Permalink
Post by Graeme Geldenhuys
On Thu, Sep 18, 2008 at 3:40 PM, Florian Klaempfl
Post by Florian Klaempfl
Post by Yury Sidorov
Post by Florian Klaempfl
What rule do you apply to say this?
Compiler treats '1234' as ansistring constant. Therefore ansistring
overload must be choosen here.
No, '1234' is taken as generic string constant.
And which type is a generic string?
It has no particular type, guess why FPC internally has this:

tconststringtype = (
cst_conststring,
cst_shortstring,
cst_longstring,
cst_ansistring,
cst_widestring,
cst_unicodestring
);

Without any further code, the type 'asdf' is not defined, $H means only
ansistring might be prefered.
Post by Graeme Geldenhuys
When compiled with {$mode objfpc}{$H+}
I would have thought ansistring? Well, at least that is how I
understood the $H directive.
Either way, I still think FPC and Delphi is broken (FPC more so than
Delphi) with regards to distinct type declarations.
I can't help you if you don't get what "= type ..." actually means :)
Graeme Geldenhuys
2008-09-18 14:13:00 UTC
Permalink
On Thu, Sep 18, 2008 at 3:55 PM, Florian Klaempfl
Post by Florian Klaempfl
Without any further code, the type 'asdf' is not defined, $H means only
ansistring might be prefered.
So does that mean if you have {$H+} enabled, then in the example
below, the p1(ansistring) version will be called?


procedure p1 (s : shortstring); overload;
procedure p1 (s : ansistring); overload;
procedure p1 (s : widestring); overload;

implementation

procedure main;
begin
p1('xx');
end;
Post by Florian Klaempfl
I can't help you if you don't get what "= type ..." actually means :)
I'm trying too Florian. And clearly my initial idea of this was wrong. :-(


Regards,
- Graeme -


_______________________________________________
fpGUI - a cross-platform Free Pascal GUI toolkit
http://opensoft.homeip.net/fpgui/
Yury Sidorov
2008-09-18 13:50:43 UTC
Permalink
Post by Florian Klaempfl
Post by Yury Sidorov
Sent: Thursday, September 18, 2008 4:14 PM
Subject: Re: [fpc-devel] Bug in FPC and declaring distinct types
Post by Florian Klaempfl
Post by Yury Sidorov
Post by Florian Klaempfl
Post by Yury Sidorov
Yes. But it works only partially. For example the following
Well, I wouldn't know either what you expect :)
I expect that compiler will choose DoTest with ansistring
parameter in that case.
What rule do you apply to say this?
Compiler treats '1234' as ansistring constant. Therefore ansistring
overload must be choosen here.
No, '1234' is taken as generic string constant.
Yes, I just tried to explain possible logic :)

Also the following code is not possible currently:

//------
operator := (const s: ansistring) r: TUTF8String;
begin
end;

operator := (const s: TUTF8String) r: ansistring;
begin
end;
//------

It makes implementation of utf8string impossible using this
approach...
Post by Florian Klaempfl
Post by Yury Sidorov
Post by Florian Klaempfl
Post by Yury Sidorov
Post by Florian Klaempfl
Post by Yury Sidorov
//------
type
TUTF8String = type ansistring;
procedure DoTest(const s: ansistring); overload;
begin
end;
procedure DoTest(const s: TUTF8String); overload;
begin
end;
begin
DoTest('1234');
end.
//------
_______________________________________________
http://lists.freepascal.org/mailman/listinfo/fpc-devel
_______________________________________________
http://lists.freepascal.org/mailman/listinfo/fpc-devel
Florian Klaempfl
2008-09-18 13:58:49 UTC
Permalink
Post by Yury Sidorov
Post by Florian Klaempfl
Post by Yury Sidorov
Sent: Thursday, September 18, 2008 4:14 PM
Subject: Re: [fpc-devel] Bug in FPC and declaring distinct types
Post by Florian Klaempfl
Post by Yury Sidorov
Post by Florian Klaempfl
Post by Yury Sidorov
Yes. But it works only partially. For example the following code
Well, I wouldn't know either what you expect :)
I expect that compiler will choose DoTest with ansistring parameter
in that case.
What rule do you apply to say this?
Compiler treats '1234' as ansistring constant. Therefore ansistring
overload must be choosen here.
No, '1234' is taken as generic string constant.
Yes, I just tried to explain possible logic :)
//------
operator := (const s: ansistring) r: TUTF8String;
begin
end;
operator := (const s: TUTF8String) r: ansistring;
begin
end;
//------
It makes implementation of utf8string impossible using this approach...
We discussed this once and concluded, that something like this hurts
more than it helps because an overloaded assignment operator allows the
compiler always to mess really around :)
Yury Sidorov
2008-09-18 14:10:51 UTC
Permalink
Post by Florian Klaempfl
Post by Yury Sidorov
Post by Florian Klaempfl
Post by Yury Sidorov
Sent: Thursday, September 18, 2008 4:14 PM
Subject: Re: [fpc-devel] Bug in FPC and declaring distinct types
Post by Florian Klaempfl
Post by Yury Sidorov
Post by Florian Klaempfl
Post by Yury Sidorov
Yes. But it works only partially. For example the following
Well, I wouldn't know either what you expect :)
I expect that compiler will choose DoTest with ansistring
parameter in that case.
What rule do you apply to say this?
Compiler treats '1234' as ansistring constant. Therefore
ansistring overload must be choosen here.
No, '1234' is taken as generic string constant.
Yes, I just tried to explain possible logic :)
//------
operator := (const s: ansistring) r: TUTF8String;
begin
end;
operator := (const s: TUTF8String) r: ansistring;
begin
end;
//------
It makes implementation of utf8string impossible using this
approach...
We discussed this once and concluded, that something like this hurts
more than it helps because an overloaded assignment operator allows
the compiler always to mess really around :)
Maybe.
But you stated that it is possible to create fully functional
utf8string type from ansistring. :)
Unfortunately it is not true :(

Yury.
Florian Klaempfl
2008-09-18 14:20:58 UTC
Permalink
Post by Yury Sidorov
Post by Florian Klaempfl
We discussed this once and concluded, that something like this hurts
more than it helps because an overloaded assignment operator allows
the compiler always to mess really around :)
Maybe.
But you stated that it is possible to create fully functional utf8string
type from ansistring. :)
Unfortunately it is not true :(
Indeed, you can only to a certain limit, but imo you can get very far.
Things like rtti, writeln etc. aren't fixable indeed.
Graeme Geldenhuys
2008-09-18 14:00:29 UTC
Permalink
Post by Yury Sidorov
It makes implementation of utf8string impossible using this approach...
I agree. I created a distinct string type (TfpgString) in fpGUI. That
way I could ensure TfpgString is a UTF-8 string and String is a
AnsiString string. I replaced all String parameters with TfpgString
where UTF-8 strings are expected and hoped that the compiled would
complain and tell me where I tried to assign String to a TfpgString. I
got no complaints... and assumed all was okay. :-(

So that means my whole assumption of type safety has gone for a ball
of s**t! (well used S.African expression) ;-)


Regards,
- Graeme -


_______________________________________________
fpGUI - a cross-platform Free Pascal GUI toolkit
http://opensoft.homeip.net/fpgui/
Martin Friebe
2008-09-18 13:55:24 UTC
Permalink
Post by Florian Klaempfl
Post by Yury Sidorov
Post by Florian Klaempfl
Post by Yury Sidorov
Post by Florian Klaempfl
Post by Yury Sidorov
Yes. But it works only partially. For example the following code
Well, I wouldn't know either what you expect :)
I expect that compiler will choose DoTest with ansistring parameter
in that case.
What rule do you apply to say this?
Compiler treats '1234' as ansistring constant. Therefore ansistring
overload must be choosen here.
No, '1234' is taken as generic string constant.
I was able (with "Free Pascal Compiler version 2.2.2rc1 [2008/06/27] for
i386") to compile the below.
(I know it's an old fpc version, but I am not at my home PC)

As shown with the non-overloaded procedures p1a, p1w, p1s: the string
'xx' can be given to any of them.
On the other hand the compiler allowed me to overload p1 for short, ansi
and wide-sring

I do not know which rule it followes if p1('xx') is called?

type
sstr = String[3];

procedure p1s (s : sstr);
procedure p1a (s : ansistring);
procedure p1w (s : widestring);

procedure p1 (s : sstr); overload;
procedure p1 (s : ansistring); overload;
procedure p1 (s : widestring); overload;

implementation

procedure main;
begin
p1('xx');
p1s('xx');
p1a('xx');
p1w('xx');
end;


Warning: Use of ppc386.cfg is deprecated, please use fpc.cfg instead
Hint: Start of reading config file
c:\lazarus\fpc\2.2.2\bin\i386-win32\fpc.cfg
Hint: End of reading config file c:\lazarus\fpc\2.2.2\bin\i386-win32\fpc.cfg
Warning: You are using the obsolete switch -OG
Free Pascal Compiler version 2.2.2rc1 [2008/06/27] for i386
Copyright (c) 1993-2008 by Florian Klaempfl
Target OS: Win32 for i386
Compiling C:\DOCUME~1\Martin\LOCALS~1\Temp\project1.lpr
Compiling unit1.pas
unit1.pas(23,18) Hint: Parameter "s" not used
unit1.pas(24,18) Hint: Parameter "s" not used
unit1.pas(25,18) Hint: Parameter "s" not used
unit1.pas(27,17) Hint: Parameter "s" not used
unit1.pas(28,17) Hint: Parameter "s" not used
unit1.pas(29,17) Hint: Parameter "s" not used
Linking C:\DOCUME~1\Martin\LOCALS~1\Temp\project1.exe
101 lines compiled, 1.3 sec , 1056816 bytes code, 280748 bytes data
2 warning(s) issued
8 hint(s) issued
Project "project1" successfully built. :)
Post by Florian Klaempfl
Post by Yury Sidorov
const
sss: ansistring = '1234';
...
DoTest(sss);
Post by Florian Klaempfl
Post by Yury Sidorov
Post by Florian Klaempfl
Post by Yury Sidorov
//------
type
TUTF8String = type ansistring;
procedure DoTest(const s: ansistring); overload;
begin
end;
procedure DoTest(const s: TUTF8String); overload;
begin
end;
begin
DoTest('1234');
end.
//------
_______________________________________________
http://lists.freepascal.org/mailman/listinfo/fpc-devel
_______________________________________________
http://lists.freepascal.org/mailman/listinfo/fpc-devel
Graeme Geldenhuys
2008-09-18 14:31:35 UTC
Permalink
On Thu, Sep 18, 2008 at 10:51 AM, Florian Klaempfl
Post by Florian Klaempfl
This is not true. The main purpose is to be able to overload
type
TUTF8String = type ansistring;
enables you to overload all procedure already defined for ansistrings with
UTF8String functions but reusing ansistring support functionality and this
is supported for years. Because nobody used this yet to make an utf-8 unit,
I never took the unicode string support serious :)
OK, bare with me here... :-) Lets see if I understand it now. "... =
type ...;" simply held or 'hints' to the compiler what overloaded
function to use - nothing more - no type safety!

type
TUTF8String = type ansistring;

procedure DoTest(const s: ansistring); overload;
begin
end;

procedure DoTest(const s: TUTF8String); overload;
begin
end;

var
a: String; // ansistring because I have {$H+} enabled
u: TUTF8String;
begin
a := '1234';
u := a; // allowed yes because utf8string is a ansistring
u := 'aaaaa';
a := u; // allowed yes because ansistring is a utf8string

{ Due to type of u, compiler will know to call DoTest(utf8string) }
DoTest(u);

{ Due to type of a, compiler will know to call DoTest(ansistring) }
DoTest(a);

end.


Have I got this write so far?

So going with what you said about UTF8String type.... The idea was to
have overloaded copies of string functions for AnsiString, WideString
and UTF8String, all having different implementations. Based on the
string type passed into a function, the compiler could make a better
choice as to which implementation of a function (eg: Copy(...) ) to
call.

If I got this right, then clearly the Delphi/Kylix help could have
explained distinct types MUCH better than they did. I (and many
others) understood it as having type safety as well - assignment
incompatible.

[...sorry, it's been a loooooong week for me...]

Regards,
- Graeme -


_______________________________________________
fpGUI - a cross-platform Free Pascal GUI toolkit
http://opensoft.homeip.net/fpgui/

Marco van de Voort
2008-09-18 08:44:36 UTC
Permalink
Post by Michael Van Canneyt
And it is also very annoying because
Type
MyString = type string;
Const
AString = 'something';
Var
M : MyString;
begin
M:=AString;
end.
Will no longer compile if you are too strict. They should at least remain
assignment compatible. Delphi does the best it can, FPC should maybe be
a bit more strict - it should not allow the var parameter.
Well, IMHO that is the idea! So that you can e.g. declare a UTF8string that
way (in pre Tiburon land), and get compiler errors on the spot where you
need to call conversion routines.

But I agree it works poorly. In both.
Ivo Steinmann
2008-09-18 10:43:08 UTC
Permalink
Post by Graeme Geldenhuys
Hi,
I was following a discussion in the delphi.non-technical newsgroup.
They raised an issue about distinct types. I tried the following
example under FPC and unexpectedly, FPC doesn't raise any errors!
type TMyInteger = type Integer;
The type TMyInteger <> Integer so you are not supposed to be allowed
to assign one to the other. Yet you can. See the following program.
----------------------[ test1.pas ]--------------------------
program test1;
{$mode objfpc}{$H+}
uses
Classes, SysUtils;
type
Angle = type Double;
Length = type Double;
function AngleToLength(var a: Angle):Length; { Note the var parameter }
begin
result := a;
end;
function AngleToLength2(a: Angle):Length; { Here is NO var parameter }
begin
result := a;
end;
procedure Test;
var
a: Angle;
l: Length;
d: Double;
begin
d := Now;
a := d;
l := a; // Should this have failed ????
{ FPC raises no errors, but at least Delphi raises an error wit the
var parameter type. }
a := AngleToLength(l); // This should definitely have failed!!
a := AngleToLength2(l); // Should this fail too?
end;
begin
Test;
end.
--------------------------[ end ]-----------------------------
fpc test1.pas
./test1
Regards,
- Graeme -
This one is working also ;) No idea if it should or not....


program test;

{$mode objfpc}
{$H+}

type
TTypeA = type Integer;
TTypeB = type Integer;

IIntf = interface
function GetSomething: TTypeA;
end;

TMyObject = class(TInterfacedObject, IIntf)
function GetSomething: TTypeB; virtual;
end;

TMyObject2 = class(TMyObject)
function GetSomething: TTypeA; override;
end;

function TMyObject.GetSomething: TTypeB;
begin
end;

function TMyObject2.GetSomething: TTypeA;
begin
end;

begin
end.
Loading...