Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

no_std support for the url crate #831

Open
wants to merge 41 commits into
base: main
Choose a base branch
from
Open

Conversation

domenukk
Copy link
Contributor

@domenukk domenukk commented Apr 8, 2023

This extends/rebases/fixes #717.
All checks seem to pass.
For no_std support, however, as mentioned in #717, this still needs a bunch of fixes. Specifically, It looks like we'll have to use the ip_in_core nightly feature, or use this crate: https://docs.rs/no-std-net. I'd personally opt for nightly, as it looks like it will be merged eventually, but I could do both.

/edit: For future reference, in the meantime, net and the Error trait have made their way into core

@domenukk
Copy link
Contributor Author

domenukk commented Apr 8, 2023

Went for ip_in_core now, so it needs nightly, but seems to work.

@domenukk domenukk marked this pull request as ready for review April 8, 2023 16:09
url/src/lib.rs Outdated Show resolved Hide resolved
@domenukk
Copy link
Contributor Author

I spent some time trying to get serde no_std support working, but it doesn't play nicely with the ip_in_core nightly feature - it throws errors like

the trait `Serialize` is not implemented for `Ipv6Addr`

@valenting
Copy link
Collaborator

Went for ip_in_core now, so it needs nightly, but seems to work.

If it breaks stable, that's obviously a no-go.
Also, our msrv is 1.56.0, so preferably the no_std changes would also work on that version.

@codecov
Copy link

codecov bot commented Apr 10, 2023

Codecov Report

All modified and coverable lines are covered by tests ✅

Please upload report for BASE (main@54346fa). Learn more about missing BASE report.

Additional details and impacted files
@@           Coverage Diff           @@
##             main     #831   +/-   ##
=======================================
  Coverage        ?   81.82%           
=======================================
  Files           ?       21           
  Lines           ?     3549           
  Branches        ?        0           
=======================================
  Hits            ?     2904           
  Misses          ?      645           
  Partials        ?        0           

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

@domenukk
Copy link
Contributor Author

It should not break stable, it should only "break" no_std (which never worked in the first place).
Switching to no-std-net also doesn't fix the problem with serde - the project seems stale/would need this to be merged:
dunmatt/no-std-net#16

@domenukk
Copy link
Contributor Author

Moving to no-std-net anyway, since it seems to fit your msrv better

@domenukk
Copy link
Contributor Author

Since I do need the nightly version, but I can see why some people wouldn't, I added two features:

  • no_std_net uses the no_std_net crate, no nightly needed (but the extra dependency)
  • unstable enabled unstable net_in_core feature, and also the error_in_core feature. Due to its opt-in nature, I would assume this is an okay solution (?)

Else we can wait until the features get stabilised.
Feedback welcome.

@@ -453,7 +453,7 @@ impl Idna {
return Errors::default();
}
let mut errors = processing(domain, self.config, &mut self.normalized, out);
self.output = std::mem::replace(out, String::with_capacity(out.len()));
self.output = core::mem::replace(out, String::with_capacity(out.len()));
Copy link
Contributor Author

Choose a reason for hiding this comment

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

FYI, this fixes a bug in the current idna no_std support. Why is it not caught in CI, and should I open an extra PR for it?

Choose a reason for hiding this comment

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

I recently dabbled with no_std stuff as well and I think the sure-fire way to test no_std compatibility is to:

  • target a platform that does not have std (certain ARM platforms) OR
  • have a really simple no_std binary crate which uses the libraries

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yes I'm trying it with cargo +nightly build -Zbuild-std=core,alloc --target aarch64-unknown-none -v --release --no-default-features

Copy link
Collaborator

Choose a reason for hiding this comment

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

Could you split this off into a separate PR?

@domenukk
Copy link
Contributor Author

Any news on this? :)

@domenukk
Copy link
Contributor Author

Any hint on what to do with codecov CI?

Copy link
Contributor

@madsmtm madsmtm left a comment

Choose a reason for hiding this comment

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

I think the guiding principle for this feature should be: "Don't inconvenience people who don't care about no_std", which is... All of url's current users ;)

So, I really don't think we should bump MSRV for this feature - but a way to solve that would be to use rustc_version in a build script to detect when the feature is available. (This does come with a slight compile-time cost, but hopefully that's acceptable, and it will go away once the functionality is in url's MSRV).


[features]
default = []
default = ["std"]
Copy link
Contributor

Choose a reason for hiding this comment

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

I fear this might be a fairly big breaking change?

When I added no_std support for the other libraries in this crate, it was more trivial, since there was only three crates that disabled default features - but that is not the case for url; there are many crates specifying default-features = false, so even though there was no default features previously, this change will affect all of those crates.

Python script for finding crates using `default-features = false`.
import json
import requests
import sys

API_URL = "https://crates.io/api/v1/crates"

crate_name = sys.argv[1]

page = 1
while True:
    # print(f"page {page}")
    data = json.loads(requests.get(f"{API_URL}/{crate_name}/reverse_dependencies?per_page=100&page={page}").content)
    page += 1

    if len(data['versions']) == 0:
        break

    versions = {x['id']: x for x in data['versions']}

    for dep in data['dependencies']:
        if not dep['default_features']:
            crate = versions[dep['version_id']]
            print(f"{crate['crate']} had `default-features = false`")

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I don't see any other way?

Copy link
Contributor

Choose a reason for hiding this comment

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

Well... I see two:

  • Bundling this in with other breaking changes, and releasing url v0.3
  • Calling the feature unstable-no-std instead, to signify that it may break other crates in the dependency chain, and that it is a bad way of doing it which will be rectified once v0.3 is released.

url/Cargo.toml Outdated
no_std_net = ["no-std-net"]
# UNSTABLE FEATURES (requires Rust nightly)
# For no_std: Use errors_in_core and net_in_core
unstable = ["idna/unstable"]
Copy link
Contributor

Choose a reason for hiding this comment

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

rust-lang/rust#108443 is FCP-ing now, so it'll probably land in a few months - perhaps we should wait with this feature until then?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Right now this PR also uses error_in_core (rust-lang/rust#103765) but that part can be removed if we want to go for stable instead

Copy link
Contributor

Choose a reason for hiding this comment

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

The value in that feature is that this could become a non-breaking change (other than bumping MSRV, which is probably acceptable).

Copy link
Contributor

Choose a reason for hiding this comment

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

Update: core::net has landed in Rust 1.77.0

url/Cargo.toml Outdated Show resolved Hide resolved
@madsmtm madsmtm mentioned this pull request Jul 16, 2024
@mspiegel
Copy link

Is this PR still maintained? no_std support can now be achieved using stable rust 1.81. I have a patch ready that keeps the MSRV at 1.56 for the feature std. I see from the comments this would be released as a breaking change for the url crate.

@domenukk
Copy link
Contributor Author

domenukk commented Jul 16, 2024

I'm happy to help to get this patch, your patch, or a mix of both into the url crate, but of course up to the maintainers regarding pace.
I think keeping the MSRV for std, while adding no_std support for the latest stable rust could be a good way forward? (If that is possible at all)

@Manishearth
Copy link
Member

So the upcoming changes to URL affect its msrv but not that intensely, otherwise I'd suggest piggybacking on that.

I'm mostly worried about --no-default-features users having an MSRV change. Do we have an idea as to how many of those there are?

Would be nice to land though.

@mspiegel
Copy link

I modified the Python script (above) for finding crates using default-features = false. The crates are printed along with the version requirement string for the url dependency. All the crates are using some variation of ^2. I was relieved to see nothing with a > comparison requirement. There appears to be a consensus that changing the default features of the url crate would increment the major version number. I have opened #953 for discussion. The PR includes a new section in the crate documentation that explains the breaking change from version 2 to version 3 when default-features = false.

@Manishearth
Copy link
Member

There appears to be a consensus that changing the default features of the url crate would increment the major version number.

Wait, where is this consensus? This is not my experience with Rust.

@Manishearth
Copy link
Member

To be clear, my worry is specifically that if this feature is implemented in a way that changes our MSRV in --no-default-features mode, and we have users in --no-default-features mode that care about MSRV, then we should be a bit wary. But I suspect we do not have such users given that the crate currently doesn't have any default features.

And even if we did, I wouldn't consider it breaking, I would consider it a "tread carefully".

@@ -73,6 +73,14 @@ assert!(data_url.fragment() == Some(""));
# run().unwrap();
```

## Default Features
Copy link
Contributor Author

Choose a reason for hiding this comment

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

@mspiegel I've merged your PR into mine here

Choose a reason for hiding this comment

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

Thanks!

@madsmtm
Copy link
Contributor

madsmtm commented Jul 17, 2024

I agree that the SemVer breakage is lessened now that both Error and the net types are available in core, but even if we're fine with bumping MSRV for users of default-features = false, the breakage is not eliminated, since we're still making certain APIs unavailable to those users.

E.g. both this PR and #953 will still break users of default-features = false if they also use Url::socket_addrs, Url::from_file_path, Url::from_directory_path or Url::to_file_path.

Co-authored-by: Michael Spiegel <michael@hushmesh.com>
@@ -73,6 +73,14 @@ assert!(data_url.fragment() == Some(""));
# run().unwrap();
```

## Default Features

Versions `< 3` of the crate have no default features. Versions `>= 3` have the default feature 'std'.
Copy link
Contributor Author

Choose a reason for hiding this comment

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

This will only be true if we really need to change version numbers

Choose a reason for hiding this comment

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

I realized that changing the text to say <= 2.5.2 and > 2.5.2 so that the docs are correct regardless of whether it’s a major or minor bump.

@domenukk
Copy link
Contributor Author

domenukk commented Jul 17, 2024

FWIW just noticed that Error is going to be available in 8 days from now with 1.80.0, so don't merge just yet! :)

(Else we can also leave out the Error trait for now and add it later, but it'll be a new MSRV discussion)

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.

None yet

8 participants