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

gio::SubprocessLauncher::set_environ and gio::ApplicationCommandLine::environ don't compose well #1638

Closed
pjungkamp opened this issue Jan 25, 2025 · 5 comments
Labels
enhancement New feature or request

Comments

@pjungkamp
Copy link
Contributor

I noticed that gio::ApplicationCommandLine::environ returns a Vec<OsString> and that gio::SubprocessLauncher::set_environ only takes a &[&Path] as argument.

This seems rather unfortunate. My application should share a primary instance for multiple windows, but still needs to spawn processes with the environment that spawned a new window on the primary instance. This currently needs an intermediate collection to collect the Path references that can be passed to gio::SubprocessLauncher::set_environ.

let cmd: gio:ApplicationCommandLine; // from the parameter of the `gio::Application::command_line` signal
let launcher = gio::SubprocessLauncher::new();

launcher.set_environ(cmd.environ().iter().map(<OsString as AsRef<Path>>::as_ref).collect::<Vec<&Path>>().as_slice());

This could be generic over all ToGlibContainerFromSlice types that coerce properly like &OsStr, &str, &Path and their owned variants OsString, String, PathBuf.

I think an intermediary trait for all kinds of OsStr-like values could help to make the gio::SubprocessLauncher::set_environ method more usable.

Maybe something like fn set_environ<'a>(&self, envs: &'a [impl AsOsStr<'a>])? Where AsOsStr<'a> is a subtrait of glib::translate::ToGlibContainerFromSlice<'a, *const *const i8> so the .to_glib_none() in the generated bindings still works?

trait AsOsStr<'a> : glib::translate::ToGlibContainerFromSlice<'a, *const *const i8> {}
impl<'a> AsOsStr<'a> for T where T: AsRef<OsStr> + glib::translate::ToGlibContainerFromSlice<'a, *const *const i8> {}

On a side-note: Why doesn't CString and &CStr implement ToGlibContainerFromSlice?


It's just a minor inconvenience but I wanted to start some discussion on these OsStr-like slices in function arguments.

@pjungkamp pjungkamp added the enhancement New feature or request label Jan 25, 2025
@sdroege
Copy link
Member

sdroege commented Jan 27, 2025

I noticed that gio::ApplicationCommandLine::environ returns a Vec and that gio::SubprocessLauncher::set_environ only takes a &[&Path] as argument.

It should really take an &OsStr instead of &Path, that would be the first problem here :)

And then this could simply become a &[&impl AsRef<Path>] or not? Do you want to give that a try?

Why doesn't CString and &CStr implement ToGlibContainerFromSlice?

Probably just forgotten / wasn't needed yet. Do you want to add that?

@pjungkamp
Copy link
Contributor Author

Why doesn't CString and &CStr implement ToGlibContainerFromSlice?

Probably just forgotten / wasn't needed yet. Do you want to add that?

Just opened PR #1641.

@pjungkamp
Copy link
Contributor Author

And then this could simply become a &[&impl AsRef] or not? Do you want to give that a try?

The problem is that &[&impl AsRef<OsStr>] or &[impl AsRef<Path>] do not implement ToGlibPtr. This is only implemented for slices where the element type implements ToGlibContainerFromSlice. But AsRef<OsStr> and AsRef<Path> are not strict supertraits of ToGlibContainerFromSlice and thus the &[&impl AsRef<OsStr>] or &[&impl AsRef<Path>] slices do not implement ToGlibPtr for the ffi translation.

@pjungkamp pjungkamp changed the title gio::SubprocessLauncher::set_environ and gio::ApplicationCommandLine::environ` don't composed well gio::SubprocessLauncher::set_environ and gio::ApplicationCommandLine::environ don't compose well Jan 27, 2025
@pjungkamp
Copy link
Contributor Author

pjungkamp commented Jan 27, 2025

Here's the Rust error message:

error[E0599]: the method `to_glib_none` exists for reference `&[impl AsRef<OsStr>]`, but its trait bounds were not satisfied
  --> gio/src/subprocess_launcher.rs:25:79
   |
25 |             ffi::g_subprocess_launcher_set_environ(self.to_glib_none().0, env.to_glib_none().0);
   |                                                                               ^^^^^^^^^^^^ method cannot be called on `&[impl AsRef<OsStr>]` due to unsatisfied trait bounds
   |
   = note: the following trait bounds were not satisfied:
           `impl AsRef<OsStr>: glib::translate::ToGlibContainerFromSlice<'_, _>`
           which is required by `[impl AsRef<OsStr>]: glib::translate::ToGlibPtr<'_, _>`
           `[impl AsRef<OsStr>]: glib::translate::ToGlibPtr<'_, _>`
           which is required by `&[impl AsRef<OsStr>]: glib::translate::ToGlibPtr<'_, _>`

I've found another place that takes a slice of environment variables at environ_getenv.

gtk-rs-core/glib/Gir.toml

Lines 356 to 359 in 35e15b7

[[object.function]]
name = "environ_getenv"
# manual input &[OsString]
ignore = true

So maybe just use &[OsString] for set_environ to be consistent?

@sdroege
Copy link
Member

sdroege commented Jan 28, 2025

So maybe just use &[OsString] for set_environ to be consistent?

Yes that probably makes most sense for now

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

No branches or pull requests

2 participants