Fable
Fable copied to clipboard
Object expression should not inline variable in getter in `Release` mode
Description
[<AbstractClass>]
type Reader() =
abstract Warnings: ResizeArray<string> with get
let reader =
let warnins = ResizeArray<string>()
{ new Reader() with
member __.Warnings = warnins
}
reader.Warnings.Add("Warning 1")
reader.Warnings.Add("Warning 2")
printfn "Count: %A" reader.Warnings.Count
In watch mode:
export const reader = (() => {
const warnins = [];
return new (class extends Reader {
constructor() {
super();
}
"Glutinum.Web.Main.Reader.get_Warnings"() {
return warnins;
}
}
)();
})();
In build mode:
export const reader = new (class extends Reader {
constructor() {
super();
}
"Glutinum.Web.Main.Reader.get_Warnings"() {
return [];
}
}
)();
This cause a problem because, now the getter always reset the value of warnings in build mode.
Meaning that in Release mode we get 0 instead of 2.
Expected and actual results
Should returns 2 in Release mode too.
Related information
- Fable version: 4.14.0
- Operating system: OSX
@MangelMaxime Perhaps I'm doing something wrong, but I cannot reproduce with v4.14, with or without --watch.
import { class_type } from "../fable_modules/fable-library-js.4.14.0/Reflection.js";
import { format } from "../fable_modules/fable-library-js.4.14.0/String.js";
export class Reader {
constructor() {
}
}
export function Reader_$reflection() {
return class_type("TestApp.Reader", void 0, Reader);
}
export function Reader_$ctor() {
return new Reader();
}
export const reader = (() => {
let warnings = [];
return new (class extends Reader {
constructor() {
super();
}
"TestApp.Reader.get_Warnings"() {
return warnings;
}
}
)();
})();
Can you post your full build command line?
@ncave Here are the steps I used to test it out:
-
Create
test.fsxwith the following content[<AbstractClass>] type Reader() = abstract Warnings: ResizeArray<string> with get let reader = let warnins = ResizeArray<string>() { new Reader() with member __.Warnings = warnins } reader.Warnings.Add("Warning 1") reader.Warnings.Add("Warning 2") printfn "Count: %A" reader.Warnings.Count -
Run
dotnet fable test.fsx, it should generates:
import { class_type } from "./fable_modules/fable-library-js.4.14.0/Reflection.js";
import { printf, toConsole } from "./fable_modules/fable-library-js.4.14.0/String.js";
export class Reader {
constructor() {
}
}
export function Reader_$reflection() {
return class_type("Test.Reader", void 0, Reader);
}
export function Reader_$ctor() {
return new Reader();
}
export const reader = new (class extends Reader {
constructor() {
super();
}
"Test.Reader.get_Warnings"() {
return [];
}
}
)();
void (reader["Test.Reader.get_Warnings"]().push("Warning 1"));
void (reader["Test.Reader.get_Warnings"]().push("Warning 2"));
(function () {
const arg = reader["Test.Reader.get_Warnings"]().length | 0;
toConsole(printf("Count: %A"))(arg);
})();
The problematic lines are:
"Test.Reader.get_Warnings"() {
return [];
}
If you run dotnet fable -c Debug now you should get:
import { class_type } from "./fable_modules/fable-library-js.4.14.0/Reflection.js";
import { printf, toConsole } from "./fable_modules/fable-library-js.4.14.0/String.js";
export class Reader {
constructor() {
}
}
export function Reader_$reflection() {
return class_type("Test.Reader", void 0, Reader);
}
export function Reader_$ctor() {
return new Reader();
}
export const reader = (() => {
const warnins = [];
return new (class extends Reader {
constructor() {
super();
}
"Test.Reader.get_Warnings"() {
return warnins;
}
}
)();
})();
void (reader["Test.Reader.get_Warnings"]().push("Warning 1"));
void (reader["Test.Reader.get_Warnings"]().push("Warning 2"));
(function () {
const arg = reader["Test.Reader.get_Warnings"]().length | 0;
toConsole(printf("Count: %A"))(arg);
})();
Which is "correct".
I tested it on OSX and Linux (dev container) with Fable 4.14 instead from NuGet for both of them.
@MangelMaxime Probably different default configurations when using a project file vs a script.
In theory an array is mutable so it shouldn't be beta reduced (like other mutables or side effects), we have to see if it's the F# compiler optimizing it, or Fable.
@ncave Here I used fsx because it was easier for the reproduction but in my case the problem happens also when using a project file.
Here is a reproduction project:
https://github.com/MangelMaxime/fable-reproduction-issue-3779
If you run dotnet fable you will see that the array has been inlined. But if you run dotnet build -c Debug it is not.
Steps used to setup that repository
dotnet new console -lang F#dotnet new tool-manifestdotnet tool install fable- Change the content of
Program.fsto the reproduction code (see comments above) - Run
dotnet fableanddotnet fable -c Debug