Skip to content

feat(rust): System.Uri (PR 7 of 7 Rust improvements)#4790

Open
Thorium wants to merge 7 commits into
fable-compiler:mainfrom
Thorium:pr/7c-rust-uri
Open

feat(rust): System.Uri (PR 7 of 7 Rust improvements)#4790
Thorium wants to merge 7 commits into
fable-compiler:mainfrom
Thorium:pr/7c-rust-uri

Conversation

@Thorium

@Thorium Thorium commented Jul 14, 2026

Copy link
Copy Markdown
Contributor

Adds System.Uri to Rust target.
Last part of the dependency chain for Rust improvements.

@Thorium
Thorium force-pushed the pr/7c-rust-uri branch 4 times, most recently from 682fcb0 to 623d897 Compare July 14, 2026 23:50
@MangelMaxime

Copy link
Copy Markdown
Member

Hello @Thorium,

Thanks for the contributions! Using AI to assist with PRs is fine, but it's crucial that you thoroughly review and curate the output before submitting, keeping the maintainers' workload in mind. Right now, with this batch of PRs, it's difficult for us to even know where to start reviewing.

To help us help you, please keep these guidelines in mind for future contributions:

  • Keep PRs independent and focused. Chained PRs (where one requires another to be merged first) are very hard to review. This PR, for instance, likely only needed your final commit.

    Chained PRs can happens some times but they are the exceptions.

  • Use meaningful PR name: The name of the PR is used for generating the CHANGELOG.md

  • Curate the AI output: Don't trust what AI produce but challenge it

We maintain Fable in our free time. Small and focused contributions are much easier for us to merge than large batches of complex changes.

Thanks for understanding!

@Thorium

Thorium commented Jul 15, 2026

Copy link
Copy Markdown
Contributor Author

Thanks. The chain reason is that all of these PRs focus on bringing the Rust target closer to the current TS/JS reference implementation, so they touch the same files (mainly src\Fable.Transforms\Rust\Fable2Rust.fs and src\Fable.Transforms\Rust\Replacements.fs). So, if they build on without a chain, there will be many merge conflicts.

The non-Rust commits are independent and not chained (except "feat(all): quotations" #4780, let's start from that please), which is needed by many quotation PRs). The main feature for that PR is to bring more types supported to quotations, which right now seems to be quite much like "number or string, and everything else is an obj".

Either you start from the bottom of the chain, or you only use the top one.

Thorium and others added 3 commits July 15, 2026 21:58
…4781)

=== changelog ===

- Cast `bool` to integer types; support `**` via `.powf`
- Add `Decimal.IsInteger/IsEvenInteger/IsOddInteger/IsCanonical`
- Fix two-switch decision trees dispatching to the wrong target
- Fix reference-typed match bindings panicking via `mem::zeroed`
- Fix string and non-ident option pattern matches emitting invalid Rust `match` arms
- Fix `Convert.ToXxx(bool)`
- Fix `Char.ToUpper/ToLower` truncating multi-char case mappings
- Fix `Random.nextDouble` panic message
- Fix `Map.find/tryFind` panicking on reference-typed values

=== changelog ===

Co-authored-by: Mangel Maxime <me@mangelmaxime.fr>

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR extends the Rust target runtime and compiler replacements to support System.Uri (and related runtime features needed by the dependency chain), and enables/expands Rust test coverage for these newly supported APIs.

Changes:

  • Add a Rust runtime Uri implementation plus compiler routing for System.Uri constructors/members, and enable Rust UriTests.
  • Introduce/expand Rust runtime support for reflection + quotations + events/observables, and add corresponding Rust tests.
  • Add std-only Rust runtime modules and tests for System.Environment and System.IO (Path/File), gated for no_std.

Reviewed changes

Copilot reviewed 25 out of 26 changed files in this pull request and generated 6 comments.

Show a summary per file
File Description
tests/Rust/tests/src/UriTests.fs Adds regression tests for authority-less absolute schemes and dot-segment collapsing.
tests/Rust/tests/src/SystemIOTests.fs Adds std-only tests for System.IO.Path/System.IO.File.
tests/Rust/tests/src/RecordReflectionTests.fs Adds std-only tests for record reflection MVP (FSharpType/FSharpValue).
tests/Rust/tests/src/QuotationTests.fs Adds quotation evaluation/deconstruction tests for Rust.
tests/Rust/tests/src/ObservableTests.fs Adjusts observable test helper for Rust backend limitations.
tests/Rust/tests/src/EventTests.fs Disables unsupported Rust event scenarios; keeps core module-function tests.
tests/Rust/tests/src/EnvironmentTests.fs Adds std-only tests for System.Environment basics.
tests/Rust/tests/src/EnumerableTests.fs Re-enables enumerable tests and adjusts type/interface layout formatting.
tests/Rust/Fable.Tests.Rust.fsproj Enables newly added Rust test sources (Uri/IO/Env/Quotations/etc.).
src/Fable.Transforms/Rust/Replacements.fs Routes Rust compiler replacements for System.Uri, System.Environment, System.IO.Path/File, and reflection/quotation carriers.
src/Fable.Transforms/Rust/Fable2Rust.fs Updates Rust type/boxing rules for System.Type, quotation carriers, System.Uri, and object-expression generic handling.
src/fable-library-rust/src/Util.fs Adds Uri escape/unescape helpers (currently stubs).
src/fable-library-rust/src/Uri.rs Adds Rust runtime Uri implementation and constructors/tryCreate helpers.
src/fable-library-rust/src/Reflection.rs Expands reflection runtime: record registry/type equality/property accessors/GetType-from-obj.
src/fable-library-rust/src/QuotationTypes.fs Adds Rust-target quotation AST carrier types under Microsoft.FSharp.Quotations.
src/fable-library-rust/src/Quotation.fs Adds Rust-target quotation runtime constructors, pattern helpers, and evaluator subset.
src/fable-library-rust/src/Path.rs Adds std-only Rust runtime System.IO.Path helpers.
src/fable-library-rust/src/Observable.rs Adds Rust runtime Observable/Observer/combinators used by F# Observable APIs.
src/fable-library-rust/src/Native.rs Adds box_lrc/unbox_lrc helpers for boxing reference-typed records/unions into obj.
src/fable-library-rust/src/lib.fs Registers additional runtime imports (Uri/Path/File/Observable/Event/Environment).
src/fable-library-rust/src/Interfaces.fs Adds System.IObservable/IObserver and Microsoft.FSharp.Control event interfaces needed by runtime.
src/fable-library-rust/src/File.rs Adds std-only Rust runtime System.IO.File helpers.
src/fable-library-rust/src/Fable.Library.Rust.fsproj Includes quotation runtime sources in the Rust library project.
src/fable-library-rust/src/Event.rs Adds Rust runtime event implementation (FSharpEvent\1` and event combinators).
src/fable-library-rust/src/Environment.rs Adds std-only Rust runtime System.Environment helpers.
src/fable-library-rust/src/Async.rs Adjusts monitor lock addressing to support obj/fat pointers.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread src/fable-library-rust/src/Path.rs
Comment thread src/fable-library-rust/src/Uri.rs
Comment thread src/fable-library-rust/src/Uri.rs
Comment on lines +410 to +412
if !baseUri.isAbsolute {
panic!("Invalid URI: A relative URI cannot be created because the 'uriString' parameter represents an absolute URI.");
}
Comment on lines +33 to +40
// System.Uri escape/unescape helpers (percent-encode/decode).
// NOTE: minimal identity stubs; not currently exercised by the enabled
// Rust UriTests. Provided so the `uris` replacement routing resolves.
// Replace with real percent-encoding if/when Uri escape members are tested.
let escapeDataString (s: string) : string = s
let unescapeDataString (s: string) : string = s
let escapeUriString (s: string) : string = s
let unescapeUriString (s: string) : string = s
Comment on lines +715 to +723
#[cfg(not(feature = "lrc_ptr"))]
pub fn box_lrc<T: 'static>(o: LrcPtr<T>) -> LrcPtr<dyn Any> {
o
}

#[cfg(not(feature = "lrc_ptr"))]
pub fn unbox_lrc<T: Clone + 'static>(o: LrcPtr<dyn Any>) -> LrcPtr<T> {
LrcPtr::new((*o).downcast_ref::<T>().expect("Invalid unbox").clone())
}
@Thorium

Thorium commented Jul 16, 2026

Copy link
Copy Markdown
Contributor Author

System.Uri gives some parity to Fable reference implementation TS/JS. It makes sense in fronted-web-target (original goal of Fable). But for F# -> Rust, I think there would be more important namespaces like for example System.Data (or ADO in general).

Any point of view from the maintainers? (As it'd be pointless to implement if that's not the direction wanted.)

@ncave

ncave commented Jul 16, 2026

Copy link
Copy Markdown
Collaborator

@Thorium We probably don't want to start onboarding new large surface namespaces from BCL, as we have limited resources to maintain that, but System.Uri is fine for parity.

This PR looks ok, perhaps you can consider the Copilot suggestion for a fall-back for Native::box_lrc/unbox_lrc, or perhaps just specialize the existing Native::box_/unbox with the more efficient implementation, when available, instead of new functions.

@MangelMaxime

Copy link
Copy Markdown
Member

We probably don't want to start onboarding new large surface namespaces from BCL, as we have limited resources to maintain that, but System.Uri is fine for parity.

To complete this answer, I have a working prototype locally which would allows people to use Fable Plugins to add new BCL API support. I will open a PR with it so we can discuss more about it.

The need for it, come from my need to improve the cross target story for Fable and the need to support more BCL API which are niche and so not worth maintaining in Fable.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants