I depend on crates a and b, where I patched b to a git dependency on ref foo:
# Cargo.toml of my crate
[dependencies]
a = "1.0.0"
b = "1.0.0"
[patch.crates-io]
b = { git = "https://github.com/user/example", rev = "foo" }
a also depends on b as a git dependency, but on no specific ref:
# Cargo.toml of a
[dependencies]
b = { git = "https://github.com/user/example" }
I want to force a to use the same ref for b as I do, which I thought I could do like this:
# The ideal Cargo.toml of my crate
[dependencies]
a = "1.0.0"
b = "1.0.0"
# patch local dependency
[patch.crates-io]
b = { git = "https://github.com/user/example", rev = "foo" }
# patch transient dependency
[patch.'https://github.com/user/example']
b = { git = "https://github.com/user/example", rev = "foo" }
This does not work however, since the source I'm patching still points to the same source, just in a different rev:
error: failed to resolve patches for `https://github.com/user/example`
Caused by:
patch for `b` in `https://github.com/user/example` points to the same source, but patches must point to different sources
[Finished running. Exit status: 101]
My workaround so far is to fork b and patch like this:
# Cargo.toml of my crate using a work around
[dependencies]
a = "1.0.0"
b = "1.0.0"
[patch.crates-io]
b = { git = "https://github.com/me/example", rev = "foo" } # Using my fork
[patch.'https://github.com/user/example']
b = { git = "https://github.com/me/example", rev = "foo" } # Using my fork
This works, but the fork is essentially useless. Is there a better way to do this?
I tried this hack, but it does not work either since it just ignores the rev. The whole GitHub issue makes it look like what I'm trying is not supported at the moment, but it's hard to tell, since it's not exactly the same feature.
Per this GitHub issue, this feature is currently not supported, since git dependencies are differentiated exclusively via URL, not revision. Some URLs are treated as the same, e.g. the .git ending always being stripped, but cargo is still just comparing URLs and nothing else.
We can however use this "feature" to our advantage: Adding a ?ref=foo to the end of the URL will make it look like a new source:
# Fixed Cargo.toml
[dependencies]
a = "1.0.0"
b = "1.0.0"
# patch local dependency
[patch.crates-io]
b = { git = "https://github.com/user/example?rev=foo" }
# patch transient dependency
[patch.'https://github.com/user/example']
b = { git = "https://github.com/user/example?rev=foo" }
Be careful to use the URL hack in both patches, otherwise you will create a corrupt Cargo.lock with two definitions of b:
# Corrupt Cargo.toml
[dependencies]
a = "1.0.0"
b = "1.0.0"
# patch local dependency
[patch.crates-io]
b = { git = "https://github.com/user/example", rev = "foo" } # mistake!
# patch transient dependency
[patch.'https://github.com/user/example']
b = { git = "https://github.com/user/example?rev=foo" }
While I did not test it, this approach should in principle also work with patches on branches by appending /tree/<branch> to the URL.
Related
I want to use the hjson format with my program. However, it seems the crate is pretty old. An updated fork is at https://github.com/shi-yan/hjson-rust, which is what I used in my program. Below is my testing program.
# Cargo.toml
[dependencies]
hjson = { git = "https://github.com/shi-yan/hjson-rust", branch = "master" }
serde = "1.0.102"
serde-hjson = "0.9.1"
//! src/main.rs
use serde_hjson::{Value, Map};
fn main() {
let data = r###"
{
name: test3
tag : username, password
}
"###;
let mut xx: Map<String, Value> = serde_hjson::from_str(&data).unwrap();
}
When I run it, I got the following error:
thread 'main' panicked at 'attempted to leave type `linked_hash_map::Node<alloc::string::String, value::Value>` uninitialized, which is invalid', C:\Users\user1\.cargo\registry\src\github.com-1ecc6299db9ec823\linked-hash-map-0.3.0\src\lib.rs:203:52
stack backtrace:
0: std::panicking::begin_panic_handler
at /rustc/4b91a6ea7258a947e59c6522cd5898e7c0a6a88f/library\std\src\panicking.rs:584
1: core::panicking::panic_fmt
at /rustc/4b91a6ea7258a947e59c6522cd5898e7c0a6a88f/library\core\src\panicking.rs:142
2: core::panicking::panic
at /rustc/4b91a6ea7258a947e59c6522cd5898e7c0a6a88f/library\core\src\panicking.rs:48
3: core::mem::uninitialized
at /rustc/4b91a6ea7258a947e59c6522cd5898e7c0a6a88f\library\core\src\mem\mod.rs:685
4: linked_hash_map::LinkedHashMap<alloc::string::String,enum$<serde_hjson::value::Value>,std::collections::hash::map::RandomState>::insert<alloc::string::String,enum$<serde_hjson::value::Value>,std::collections::hash::map::RandomState>
at C:\Users\user1\.cargo\registry\src\github.com-1ecc6299db9ec823\linked-hash-map-0.3.0\src\lib.rs:203
5: linked_hash_map::serde::impl$2::visit_map<alloc::string::String,enum$<serde_hjson::value::Value>,serde_hjson::de::MapVisitor<core::iter::adapters::map::Map<core::slice::iter::Iter<u8>,serde_hjson::de::from_iter::closure_env$2<core::iter::adapters::map::Ma
at C:\Users\user1\.cargo\registry\src\github.com-1ecc6299db9ec823\linked-hash-map-0.3.0\src\serde.rs:72
6: serde_hjson::de::Deserializer<core::iter::adapters::map::Map<core::slice::iter::Iter<u8>,serde_hjson::de::from_iter::closure_env$2<core::iter::adapters::map::Map<core::slice::iter::Iter<u8>,serde_hjson::de::from_slice::closure_env$0<linked_hash_map::Linke
at C:\Users\user1\.cargo\registry\src\github.com-1ecc6299db9ec823\serde-hjson-0.9.1\src\de.rs:151
7: serde_hjson::de::impl$1::deserialize<core::iter::adapters::map::Map<core::slice::iter::Iter<u8>,serde_hjson::de::from_iter::closure_env$2<core::iter::adapters::map::Map<core::slice::iter::Iter<u8>,serde_hjson::de::from_slice::closure_env$0<linked_hash_map
at C:\Users\user1\.cargo\registry\src\github.com-1ecc6299db9ec823\serde-hjson-0.9.1\src\de.rs:443
8: serde_hjson::de::impl$1::deserialize_map<core::iter::adapters::map::Map<core::slice::iter::Iter<u8>,serde_hjson::de::from_iter::closure_env$2<core::iter::adapters::map::Map<core::slice::iter::Iter<u8>,serde_hjson::de::from_slice::closure_env$0<linked_hash
at C:\Users\user1\.cargo\registry\src\github.com-1ecc6299db9ec823\serde-hjson-0.9.1\src\forward.rs:35
9: linked_hash_map::serde::impl$3::deserialize<alloc::string::String,enum$<serde_hjson::value::Value>,serde_hjson::de::Deserializer<core::iter::adapters::map::Map<core::slice::iter::Iter<u8>,serde_hjson::de::from_iter::closure_env$2<core::iter::adapters::map
at C:\Users\user1\.cargo\registry\src\github.com-1ecc6299db9ec823\linked-hash-map-0.3.0\src\serde.rs:88
10: serde_hjson::de::from_iter<core::iter::adapters::map::Map<core::slice::iter::Iter<u8>,serde_hjson::de::from_slice::closure_env$0<linked_hash_map::LinkedHashMap<alloc::string::String,enum$<serde_hjson::value::Value>,std::collections::hash::map::RandomState
at C:\Users\user1\.cargo\registry\src\github.com-1ecc6299db9ec823\serde-hjson-0.9.1\src\de.rs:813
11: serde_hjson::de::from_slice<linked_hash_map::LinkedHashMap<alloc::string::String,enum$<serde_hjson::value::Value>,std::collections::hash::map::RandomState> >
at C:\Users\user1\.cargo\registry\src\github.com-1ecc6299db9ec823\serde-hjson-0.9.1\src\de.rs:846
12: serde_hjson::de::from_str<linked_hash_map::LinkedHashMap<alloc::string::String,enum$<serde_hjson::value::Value>,std::collections::hash::map::RandomState> >
at C:\Users\user1\.cargo\registry\src\github.com-1ecc6299db9ec823\serde-hjson-0.9.1\src\de.rs:853
13: test3::main
at .\src\main.rs:13
14: core::ops::function::FnOnce::call_once<void (*)(),tuple$<> >
at /rustc/4b91a6ea7258a947e59c6522cd5898e7c0a6a88f\library\core\src\ops\function.rs:248
note: Some details are omitted, run with `RUST_BACKTRACE=full` for a verbose backtrace.
error: process didn't exit successfully: `target\debug\test3.exe` (exit code: 101)
Process finished with exit code 101
I have no idea what's happening here. Could anyone give me some help?
In short: the version you're using is unsound, and std converted this unsoundness to panic.
You can see that the panic originates inside std::mem::uninitialized. This panic shows that the type it was trying to create has invalid bit patterns (since it contains the corresponding key, which in your case is String, and String has a non-null pointer field), therefore having an uninitialized value of this type is UB, which panic prevents. There's nothing you can do while remaining on the same versions of dependencies - that's the bug in linked_hash_map.
Now, what you can do?
You can disable the preserve-order feature of serde_hjson, which is the reason for pulling in linked_hash_map. This is done by using the following line in your Cargo.toml:
serde-hjson = { version = "0.9.1", default-features = false }
In this case you, obviously, will lose the order of keys in your maps, but I assume that they're not so important.
Or you can move to the fork of serde_hjson, used by nushell - that is, to nu-json; it uses the updated version of linked_hash_map, which doesn't have this unsoundness.
I am using alpine-3.16 and rust-1.56 with the following packages to compile my program.
expat libbz2 libcrypto1.1 libffi libpq libssl1.1 libtirpc libuuid musl \
ncurses-libs readline xz-libs zlib libc6-compat rust cargo bash
I was able to compile my program before adding the following two dependencies:
geo = "0.22.1"
geo-types = "0.7.6"
Following are the full contents of cargo.toml:
[package]
name = "math-helpers"
version = "0.1.0"
edition = "2021"
[lib]
crate-type = ["cdylib"]
[dependencies.cpython]
version = "0.7.0"
[features]
default = ["python3"]
python3 = ["cpython/python3-sys", "cpython/extension-module"]
[dependencies]
libm = {version = "0.2.0"}
geo = "0.22.1"
geo-types = "0.7.6"
The errors that I am getting are as following:
/math-helpers # cargo build
Compiling geo v0.22.1
error: there is no argument named `pt`
--> /root/.cargo/registry/src/github.com-1ecc6299db9ec823/geo-0.22.1/src/algorithm/sweep/line_or_point.rs:248:59
|
248 | "line intersection before first line: {pt:?}\n\tLine({lp1:?} - {lp2:?}) X Line({lp3:?} - {lp4:?})",
| ^^^^^^
error: there is no argument named `pt`
--> /root/.cargo/registry/src/github.com-1ecc6299db9ec823/geo-0.22.1/src/algorithm/sweep/line_or_point.rs:256:60
|
256 | "line intersection before second line: {pt:?}\n\tLine({lp1:?} - {lp2:?}) X Line({lp3:?} - {lp4:?})",
| ^^^^^^
error: there is no argument named `r`
--> /root/.cargo/registry/src/github.com-1ecc6299db9ec823/geo-0.22.1/src/algorithm/sweep/segment.rs:51:79
|
51 | "intersection point was not ordered within the line: {p:?} <= {r:?} <=> {q:?}",
| ^^^^^
error: there is no argument named `q`
--> /root/.cargo/registry/src/github.com-1ecc6299db9ec823/geo-0.22.1/src/algorithm/sweep/segment.rs:51:89
|
51 | "intersection point was not ordered within the line: {p:?} <= {r:?} <=> {q:?}",
| ^^^^^
It works fine on Ubuntu, though. It's highly likely that I am missing a platform dependency that needs to be installed on Alpine.
I would like to include --help and --version long options without the -h and -V short options. Is this possible?
I'm using clap with yaml. The closest I've been able to come up with is to use hidden (unused) args that mask the short options.
# main.rs
use clap::{load_yaml, App};
fn main() {
let y = load_yaml!("cli.yaml");
let m = App::from_yaml(y).get_matches();
println!("_help {}", m.is_present("_help"));
println!("_version {}", m.is_present("_version"));
}
# Cargo.toml
[package]
name = "app"
version = "0.0.1"
edition = "2018"
[dependencies]
clap = {version = "~2.33.0", features = ["yaml"]}
# cli.yaml
name: app
version: 0.0.1
args:
- opt: { short: "o", long: "opt" }
- _help: { short: "h", hidden: true }
- _version: { short: "V", hidden: true }
$ cargo -q run -- --help
app 0.0.1
USAGE:
app [FLAGS]
FLAGS:
--help Prints help information
-o, --opt
--version Prints version information
$ cargo -q run -- -h
_help true
_version false
$ cargo -q run -- -o
_help false
_version false
$ cargo -q run -- -V
_help false
_version true
$ cargo -q run -- -x
error: Found argument '-x' which wasn't expected, or isn't valid in this context
USAGE:
app [FLAGS]
For more information try --help
This doesn't feel like a very clean approach. Is there another/better way?
Clap is designed more towards creating an args parser. So there aren't really that much functionality for getting and removing existing arguments.
If you simply want to rename "-h" to e.g. "-?", then you can do that with help_short("-?") (see also version_short().)
However, there are ways to work around it.
Assuming you're using e.g. clap = "2.33". Then similarly to what you're already doing, you can override/replace the help and version args, and in that way "remove" the short versions. (For brevity, I'll only include examples for help.)
You can of course keep it in cli.yaml if you want, but I'll add it to main.rs. In short, you want to add a new "help" arg and only give it a long version. It's important that you include help("Prints help information") as this is replacing the existing help arg, so if you don't it won't have the default help message for --help.
The downside to overring "help" is that you'd need to handle print_help() yourself.
use clap::{load_yaml, App, Arg};
fn main() {
let y = load_yaml!("cli.yaml");
let mut app = App::from_yaml(y)
.arg(
Arg::with_name("help")
.long("help")
.help("Prints help information"),
);
let m = app.clone().get_matches();
if m.is_present("help") {
app.print_help().unwrap();
// std::process::exit(0);
// or just
return;
}
}
However, if you're using clap = "3.0.0-beta.2" then that simplifies things, with the introduction of mut_arg(). Because that allows us to mutate the argument. Thereby, we no longer need to call print_help() ourselves.
use clap::{load_yaml, App, Arg};
fn main() {
let y = load_yaml!("cli.yaml");
let m = App::from(y)
.mut_arg("help", |h| {
Arg::new("help")
.long("help")
.about("Prints help information")
})
.get_matches();
}
Note that App::from_yaml() is now App::from(), while Arg::with_name() has become Arg::new(), and help() is now about().
I am trying to build a BDD for monotone multiplication and need to use the negation of the input bits.
I am using the following code:
DdNode *x[N], *y[N], *nx[N], *ny[N];
gbm = Cudd_Init(0,0,CUDD_UNIQUE_SLOTS,CUDD_CACHE_SLOTS,0); /* Initialize a new BDD manager. */
for(k=0;k<N;k++)
{
x[k] = Cudd_bddNewVar(gbm);
nx[k] = Cudd_Not(x[k]);
y[k] = Cudd_bddNewVar(gbm);
ny[k] = Cudd_Not(y[k]);
}
The error that I am getting is:
cuddGarbageCollect: problem in table 0
dead count != deleted
This problem is often due to a missing call to Cudd_Ref
or to an extra call to Cudd_RecursiveDeref.
See the CUDD Programmer's Guide for additional details.Aborted (core dumped)
The multiplier compiles and runs fine when I am using
x[k] = Cudd_bddNewVar(gbm);
nx[k] = Cudd_bddNewVar(gbm);
y[k] = Cudd_bddNewVar(gbm);
ny[k] = Cudd_bddNewVar(gbm);
What should I do, the manual does not help not truing to ref x[k],nx[k]...
Every BDD node that is not referenced is subject to deletion by any Cudd operation. If you want to make sure that all nodes stored in your array remain valid, you need to Cudd_Ref them immediately after they are returned by CUDD. Hence, you need to correct your code to:
for(k=0;k<N;k++)
{
x[k] = Cudd_bddNewVar(gbm);
Cudd_Ref(x[k]);
nx[k] = Cudd_Not(x[k]);
Cudd_Ref(nx[k]);
y[k] = Cudd_bddNewVar(gbm);
Cudd_Ref(y[k]);
ny[k] = Cudd_Not(y[k]);
Cudd_Ref(yn[k]);
}
Before deallocating the Cudd manager, you then need to dereference the nodes:
for(k=0;k<N;k++)
{
Cudd_RecursiveDeref(gbm,x[k]);
Cudd_RecursiveDeref(gbm,nx[k]);
Cudd_RecursiveDeref(gbm,y[k]);
Cudd_RecursiveDeref(gbm,ny[k]);
}
Note that the fact that your code works when allocating more variables does not show that referencing is not needed. It may simply be that you do not ever use enough nodes for the garbage collector to trigger -- and before that, the problem is not detected.
In Rust 0.8:
struct TwoStr {
one: ~str,
two: ~str,
}
#[test]
fn test_contents() {
let strs = TwoStr {
one: ~"pillar",
two: ~"post",
};
assert_eq!(strs.one, ~"pillar");
assert_eq!(strs.two, ~"post");
}
The code won't even compile. The rust test thinks there's an error in the second assert_eq:
error: use of partially moved value: strs
It is somewhat counter-intuitive. I mean, whatever effects the first assert_eq may have, it should be well out of the scope when the execution reaches the second assert_eq. Unless of course, it does some spawn behind the scene. Does it?
If not, why this mysterious error? Hopefully there's no fundamental flaws in my understanding of Rust pointers.
In Rust 0.8, assert_eq! is defined as
macro_rules! assert_eq (
($given:expr , $expected:expr) => (
{
let given_val = $given;
let expected_val = $expected;
// check both directions of equality....
if !((given_val == expected_val) && (expected_val == given_val)) {
fail!(\"assertion failed: `(left == right) && (right == \
left)` (left: `%?`, right: `%?`)\", given_val, expected_val);
}
}
)
)
Note here that it moves both arguments into local let-bindings given_val and expected_val. This is what is causing your error.
In current master, this has been fixed. assert_eq! now takes references to the arguments:
macro_rules! assert_eq (
($given:expr , $expected:expr) => (
{
let given_val = &($given);
let expected_val = &($expected);
// check both directions of equality....
if !((*given_val == *expected_val) &&
(*expected_val == *given_val)) {
fail!("assertion failed: `(left == right) && (right == left)` \
(left: `{:?}`, right: `{:?}`)", *given_val, *expected_val)
}
}
)
)
This means that it no longer moves its arguments, which fixes your error.
If you need to stick with rust 0.8, you can change this to using assert!() instead and do the comparison directly, which will avoid the move. But my recommendation is to upgrade to latest master.
It works on Git master. It must be a bug that was fixed after 0.8 was cut. In general, the released versions are not constrained to be particularly stable before release - they're essentially just snapshots.
The definition of the assert_eq! macro, in libsyntax, takes references to the arguments, so the arguments should not be moved and you can use them after you call the macro.
If you do find another bug, try to compile master if you can, or just make a new issue.