Skip to content

Commit 6dbb6c3

Browse files
Merge pull request #16 from fullofcaffeine/fix/fl57-interface-constructor-forwarding
fix: wrap required interfaces for optional parameters
2 parents c94d52d + f0ab8ad commit 6dbb6c3

129 files changed

Lines changed: 33092 additions & 6 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

docs/rust-raw-authority-inventory.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,7 @@
7171
},
7272
{
7373
"path": "src/reflaxe/rust/RustCompiler.hx",
74-
"line": 17301,
74+
"line": 17345,
7575
"enclosingFunction": "addSpec",
7676
"factory": "traitImplementationAt",
7777
"authorityId": "metadata-owned",

docs/semantic-confidence-summary.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@
1818
"portableCandidateMissingFromTier2": 0,
1919
"portableSemanticDiffCases": 37,
2020
"laneSemanticDiffCases": 2,
21-
"snapshotCases": 138,
21+
"snapshotCases": 139,
2222
"bucketsByClass": {
2323
"compile_inventory": 2,
2424
"targeted_semantic_parity": 8,

docs/semantic-confidence-summary.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ This summary rolls up the current evidence buckets without pretending that Tier2
2626
- Portable candidate missing from Tier2: `0`
2727
- Portable semantic-diff cases: `37`
2828
- Lane semantic-diff cases: `2`
29-
- Snapshot cases: `138`
29+
- Snapshot cases: `139`
3030
- Compile/inventory buckets: `2`
3131
- Targeted semantic/runtime buckets: `8`
3232
- Snapshot/smoke-only buckets: `7`

scripts/lint/dynamic_allowlist.txt

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,9 +15,9 @@ src/reflaxe/rust/RustCompiler.hx:2768
1515
src/reflaxe/rust/RustCompiler.hx:2771
1616
src/reflaxe/rust/RustCompiler.hx:2779
1717
src/reflaxe/rust/RustCompiler.hx:10829
18-
src/reflaxe/rust/RustCompiler.hx:13582
19-
src/reflaxe/rust/RustCompiler.hx:13601
20-
src/reflaxe/rust/RustCompiler.hx:19673
18+
src/reflaxe/rust/RustCompiler.hx:13626
19+
src/reflaxe/rust/RustCompiler.hx:13645
20+
src/reflaxe/rust/RustCompiler.hx:19717
2121
src/reflaxe/rust/RustSourceMap.hx:419
2222
src/reflaxe/rust/analyze/RepresentationAnalysisSnapshot.hx:77
2323
src/reflaxe/rust/analyze/RepresentationAnalysisSnapshot.hx:81

src/reflaxe/rust/RustCompiler.hx

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13265,6 +13265,50 @@ class RustCompiler extends GenericCompiler<RustFile, RustFile, RustExpr, RustFil
1326513265
});
1326613266
}
1326713267

13268+
/**
13269+
Wraps a required trait-object handle when its destination admits null.
13270+
13271+
Why
13272+
- Haxe types an optional interface parameter as `Null<Interface>`, while a required
13273+
interface argument remains the same non-null interface at the call site.
13274+
- Rust represents those values differently: the required value is an `Arc<dyn Trait>`
13275+
and the nullable destination is `HxDynRef<dyn Trait>`.
13276+
13277+
What
13278+
- Converts the already type-checked required interface value into the nullable carrier.
13279+
- Leaves concrete-class upcasts to the existing conversion below.
13280+
13281+
How
13282+
- Detects only the closed `Arc<dyn Trait>` to `HxDynRef<dyn Trait>` representation edge,
13283+
requires structurally equal trait-object inner types, and constructs the nullable wrapper
13284+
directly around the compiled value. Interface-inheritance upcasts remain unadmitted.
13285+
**/
13286+
var requiredTraitSource = unwrapMetaParen(valueExpr);
13287+
while (true) {
13288+
switch (requiredTraitSource.expr) {
13289+
case TCast(inner, _):
13290+
requiredTraitSource = unwrapMetaParen(inner);
13291+
continue;
13292+
case _:
13293+
}
13294+
break;
13295+
}
13296+
var requiredTraitSourceType = switch (requiredTraitSource.expr) {
13297+
case TLocal(variable): variable.t;
13298+
case _: requiredTraitSource.t;
13299+
};
13300+
var requiredTraitSourceRust = toRustType(requiredTraitSourceType, requiredTraitSource.pos);
13301+
var requiredTraitExpectedInner = rustTypeSingleGenericArgument(expectedRust);
13302+
var requiredTraitSourceInner = rustTypeSingleGenericArgument(requiredTraitSourceRust);
13303+
if (rustTypeIsDynRefCarrier(expectedRust)
13304+
&& rustTypeContainsTraitObject(expectedRust)
13305+
&& rustTypeIsRcTraitObject(requiredTraitSourceRust)
13306+
&& requiredTraitExpectedInner != null
13307+
&& requiredTraitSourceInner != null
13308+
&& rustTypesEqual(requiredTraitExpectedInner, requiredTraitSourceInner)) {
13309+
return ECall(rustDynRefMemberExpr("new"), [compiled]);
13310+
}
13311+
1326813312
// `Null<T>` (Option<T>) used where a non-null `T` is expected.
1326913313
//
1327013314
// Haxe allows this implicitly in many places (especially in upstream stdlib for "dynamic-ish"
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
class Channel implements IChannel {
2+
public function new() {}
3+
4+
public function label():String {
5+
return "ready";
6+
}
7+
}
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
class ChannelOwner {
2+
final channel:Null<IChannel>;
3+
4+
public function new(?channel:IChannel) {
5+
this.channel = channel;
6+
}
7+
8+
public function label():String {
9+
return channel == null ? "missing" : channel.label();
10+
}
11+
}
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
interface IChannel {
2+
public function label():String;
3+
}
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
class Main {
2+
static function forward(channel:IChannel):ChannelOwner {
3+
return new ChannelOwner(channel);
4+
}
5+
6+
static function main() {
7+
var channel:IChannel = new Channel();
8+
Sys.println(forward(channel).label());
9+
}
10+
}
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
-cp .
2+
-lib reflaxe.rust
3+
-D reflaxe_rust_strict_examples
4+
-D rust_output=out
5+
-D rust_deny_warnings
6+
-D reflaxe.dont_output_metadata_id
7+
-main Main

0 commit comments

Comments
 (0)