Sign in Join

Live chat for Free Pascal, Lazarus, Delphi and every Pascal programmer.

Mailing lists / fpc-pascal / 2019-01

type helpers

6 messages · 3 people ·

Reply by email Subscribe to this list Your subscription

Read-only archive. Use j and k to move between messages.

Mattias Gaertner

Hi,

A type helper can change Self.
I wondered how FPC 3.3.1 handles properties and got some unexpected results. Is this by design, a bug, or not-yet-implemented?

{$mode objfpc}{$modeswitch typehelpers}
type
  TIntHlp = type helper for word
    procedure DoIt;
  end;
  TBig = class
  strict private
    FW: word;
    procedure SetW(const AValue: word);
  public
    property W: word read FW write SetW;
  end;
var b: TBird;
procedure TBig.SetW(const AValue: word);
begin
  // not called by type helper
  writeln('TBig.SetW');
end;
procedure TIntHlp.DoIt;
begin
  writeln('TIntHlp.DoIt START ',Self,' w=',b.w);
  Self:=4; // changes b.FW directly
  writeln('TIntHlp.DoIt END ',Self,' w=',b.w);
end;
begin
  b:=TBig.Create;
  b.w.DoIt;
end.

Mattias

Reply by email

Michael Van Canneyt
to Mattias Gaertner
Mattias Gaertner wrote 5 lines
Hi, A type helper can change Self. I wondered how FPC 3.3.1 handles properties and got some unexpected results. Is this by design, a bug, or not-yet-implemented?

Delphi acts the same, so for FPC: by design...

You will see that there are other pitfalls, for example when using helpers on properties of type record. I have been bitten by this more than once.

Michael.

Reply by email

Sven Barth
to Mattias Gaertner: A type helper can change Self. I wondered how FPC 3.3.1 handles properties and got some…

Am Fr., 11. Jan. 2019, 11:24 hat Mattias Gaertner via fpc-pascal <

Show quoted text 42 lines
geschrieben: Hi, A type helper can change Self. I wondered how FPC 3.3.1 handles properties and got some unexpected results. Is this by design, a bug, or not-yet-implemented? {$mode objfpc}{$modeswitch typehelpers} type TIntHlp = type helper for word procedure DoIt; end; TBig = class strict private FW: word; procedure SetW(const AValue: word); public property W: word read FW write SetW; end; var b: TBird; procedure TBig.SetW(const AValue: word); begin // not called by type helper writeln('TBig.SetW'); end; procedure TIntHlp.DoIt; begin writeln('TIntHlp.DoIt START ',Self,' w=',b.w); Self:=4; // changes b.FW directly writeln('TIntHlp.DoIt END ',Self,' w=',b.w); end; begin b:=TBig.Create; b.w.DoIt; end.

This is by design. In this case DoIt is called on a temp variable that gets its value from b.w, the value of b.FW does not change (same reason why the C operators do not work on properties). Same happens with constants btw: Word(42).DoIt will work as well.

Regards,
Sven

Reply by email

Michael Van Canneyt
to Sven Barth
Sven Barth wrote 48 lines
Am Fr., 11. Jan. 2019, 11:24 hat Mattias Gaertner via fpc-pascal < > geschrieben: > Hi, > > A type helper can change Self. > I wondered how FPC 3.3.1 handles properties and got some > unexpected results. Is this by design, a bug, or not-yet-implemented? > > {$mode objfpc}{$modeswitch typehelpers} > type > TIntHlp = type helper for word > procedure DoIt; > end; > > TBig = class > strict private > FW: word; > procedure SetW(const AValue: word); > public > property W: word read FW write SetW; > end; > > var b: TBird; > > procedure TBig.SetW(const AValue: word); > begin > // not called by type helper > writeln('TBig.SetW'); > end; > > procedure TIntHlp.DoIt; > begin > writeln('TIntHlp.DoIt START ',Self,' w=',b.w); > Self:=4; // changes b.FW directly > writeln('TIntHlp.DoIt END ',Self,' w=',b.w); > end; > > begin > b:=TBig.Create; > b.w.DoIt; > end. > This is by design. In this case DoIt is called on a temp variable that gets its value from b.w, the value of b.FW does not change (same reason why the C operators do not work on properties). Same happens with constants btw: Word(42).DoIt will work as well.

IMO It makes sense to forbid this.
For simple types and records, writing to self means self is treated like a var parameter (i.e. there is an address). The compiler can detect this.

For properties there is no address (it cannot be used as var param), so treating self as a var parameter would automatically forbid writing using a method - that writes to self - on a property.

The behaviour to make a copy has bitten me more than once, and I would much prefer that the compiler simply does not allow me to do something which will guaranteed not give me what I was expecting.

Michael.

Reply by email

Mattias Gaertner
to Sven Barth: Am Fr., 11. Jan. 2019, 11:24 hat Mattias Gaertner via fpc-pascal < This is by design. In…
[...] This is by design. In this case DoIt is called on a temp variable that gets its value from b.w, the value of b.FW does not change

Ehm, in this case b.FW *does* changes.
Maybe you mean the case

  property W: word read GetW;

?

With a getter method indeed a temp variable is changed by the helper.

(same reason why the C operators do not work on properties). Same happens with constants btw: Word(42).DoIt will work as well.

Well, at least 3.DoIt is rejected.

Mattias

Show quoted text 5 lines
Regards, Sven >

Reply by email

Sven Barth
to Mattias Gaertner

Am Fr., 11. Jan. 2019, 14:52 hat Mattias Gaertner via fpc-pascal <

Show quoted text 17 lines
geschrieben: On Fri, 11 Jan 2019 14:27:13 +0100 Sven Barth via fpc-pascal wrote: >[...] > This is by design. In this case DoIt is called on a temp variable > that gets its value from b.w, the value of b.FW does not change Ehm, in this case b.FW *does* changes. Maybe you mean the case property W: word read GetW; ? With a getter method indeed a temp variable is changed by the helper.

Dang it. Seems I've missed that part of your example. In my opinion it should use a temp in that case.

Show quoted text 6 lines
> (same > reason why the C operators do not work on properties). Same happens > with constants btw: Word(42).DoIt will work as well. Well, at least 3.DoIt is rejected.

"3" is not a Word ;)

Regards,
Sven

Reply by email