Unable to coerce &String to &str - string

I'm trying to compile the following code, from the Rust book at the Rust official website.
fn takes_slice(slice: &str) {
println!("Got: {}", slice);
}
fn main() {
let s = "Hello".to_string();
takes_slice(&s);
}
At compilation, it throws the following error
/devl/rust/bc_09/src/main.rs:7:17: 7:19 error: mismatched types:
expected &str, found &collections::string::String (expected str,
found struct collections::string::String)
/devl/rust/bc_09/src/main.rs:7 takes_slice(&s);
^~ error: aborting due to previous error Could not compile hello_world.
Here is the Rust version I'm running: rustc 1.0.0-nightly (44a287e6e 2015-01-08 17:03:40 -0800)

That's a really old version of the nightly in Rust terms! Old enough that the &String -> &str coercion isn't available. You just need to upgrade to a newer version.

Related

Rust-Rocket cannot be compiled

I have set up a rust base project according to the Getting Started page of the rocket-framework:
I added this line to my Cargo.toml: rocket = "0.4.10"
My main.rs:
#![feature(proc_macro_hygiene, decl_macro)]
#[macro_use] extern crate rocket;
#[get("/")]
fn index() -> &'static str {
"Hello, world!"
}
fn main() {
rocket::ignite().mount("/", routes![index]).launch();
}
When I try to run (or cargo build it) I get the following error:
Compiling rocket v0.4.10 error[E0277]: the trait bound `(dyn handler::Handler + 'static): handler::Handler` is not satisfied --> /Users/.../.cargo/registry/src/github.com-1ecc6299db9ec823/rocket-0.4.10/src/rocket.rs:299:41
| 299 | let outcome = route.handler.handle(request, data);
| ^^^^^^ the trait `handler::Handler` is not implemented for `(dyn handler::Handler + 'static)`
For more information about this error, try `rustc --explain E0277`. error: could not compile `rocket` due to previous error
I also tried it with previous versions of the rocket framework, all of them threw the same error.
Of course I'm using the latest nightly version of rust, right before cargo build I entered following commands:
rustup override set nightly
info: using existing install for 'nightly-x86_64-apple-darwin'
info: override toolchain for '/Users/...' set to 'nightly-x86_64-apple-darwin'
nightly-x86_64-apple-darwin unchanged - rustc 1.58.0-nightly (bd41e09da 2021-10-18)
Is there a known issue with the latest rust compiler on MacOS? Is there any other solution I could try?

How to make OwningRef work with iterators?

I have a RwLock protected global WORLD, and I want to write a function that read locks it and returns an iterator (of type Neighbors) that iterates over edges in a petgraph::stable_graph::StableGraph that is stored inside the global. I'm using OwningRef to deal with keeping the read lock guard alive after the function exits, which has worked for me in the past when just returning a field of World directly. I've included a compilable example and the error I'm getting below -- it seems there is some sort of type problem but I haven't been able to figure it out. I think it might have to do with OwningRef wanting to deal with a reference rather than an object containing a reference (Neighbors) but I'm not sure how to work around that.
Cargo.toml:
[package]
name = "problem_demo"
version = "0.1.0"
authors = ["Joseph Garvin <joseph.h.garvin#gmail.com>"]
edition = "2018"
[dependencies]
owning_ref="0.4.1"
once_cell="1.4.0"
petgraph={version="0.5.1", features=["serde-1"]}
main.rs:
use std::{sync::RwLock};
use once_cell::sync::OnceCell;
use owning_ref::RwLockReadGuardRef;
use petgraph::stable_graph::{StableGraph, Neighbors};
struct Bar {
data: i32
}
struct World {
graph: StableGraph<(), Bar, petgraph::Directed, u32>
}
pub static WORLD: OnceCell<RwLock<World>> = OnceCell::new();
fn neighbors(id: u32) -> Result<RwLockReadGuardRef<'static, World, Neighbors<'static, Bar, u32>>, Box<dyn std::error::Error>> {
RwLockReadGuardRef::new(WORLD.get().unwrap().read().unwrap())
.try_map(
|world: &World| -> std::result::Result<Neighbors<'static, Bar, u32>, Box<dyn std::error::Error>>
{
let neighbors = world.graph.neighbors_directed(
petgraph::graph::NodeIndex::new(id as usize),
petgraph::Direction::Outgoing
);
Ok(neighbors)
}
)
}
Errors:
error[E0271]: type mismatch resolving `for<'r> <[closure#src/main.rs:21:13: 29:14 id:_] as std::ops::FnOnce<(&'r World,)>>::Output == std::result::Result<&'r _, _>`
--> src/main.rs:20:10
|
20 | .try_map(
| ^^^^^^^ expected struct `petgraph::stable_graph::Neighbors`, found reference
|
= note: expected enum `std::result::Result<petgraph::stable_graph::Neighbors<'static, Bar>, std::boxed::Box<dyn std::error::Error>>`
found enum `std::result::Result<&_, _>`
error: aborting due to previous error
For more information about this error, try `rustc --explain E0271`.
error: could not compile `playground`.
To learn more, run the command again with --verbose.

Compile Error len is not yet stable as a const fn

I get an error from one of my dependencies bytes 0.5.2. Here a code example of the error:
pub const fn foo(foo: &'static [u8]) -> usize {
foo.len()
}
error: `core::slice::<impl [T]>::len` is not yet stable as a const fn
--> <source>:2:5
|
2 | foo.len()
| ^^^^^^^^^
error: aborting due to previous error
active toolchain
----------------
stable-x86_64-pc-windows-msvc (default) rustc 1.38.0 (625451e37 2019-09-23)
The 0.5.x would appear to require Rust 1.39 so the easiest option would likely be upgrading to the newest version.
The error states
core::slice::<impl [T]>::len is not yet stable as a const fn
and if you look at the release notes for 1.39 you can see that one of the entries is
str::len, [T]::len and str::as_bytes are now const functions
so this crate specifically requires >=1.39

"try!" macro stopped working after Rust upgrade

Here is a simple testcase, which still works on the playpen:
use std::num;
use std::str::FromStr;
use std::convert::From;
#[derive(Debug)]
struct Error(String);
impl From<num::ParseFloatError> for Error {
fn from(err: num::ParseFloatError) -> Error {
Error(format!("{}", err))
}
}
fn parse(s: &String) -> Result<f64, Error> {
Ok(try!(<f64 as FromStr>::from_str(&s[..])))
}
fn main() {
println!("{:?}", parse(&"10.01".to_string()));
}
However, after I built the latest rustc from git (now it's rustc 1.1.0-dev (1114fcd94 2015-04-23)), it stopped compiling with following error:
<std macros>:6:1: 6:32 error: the trait `core::convert::From<core::num::ParseFloatError>` is not implemented for the type `Error` [E0277]
<std macros>:6 $ crate:: convert:: From:: from ( err ) ) } } )
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
<std macros>:1:1: 6:48 note: in expansion of try!
exp.rs:15:8: 15:48 note: expansion site
error: aborting due to previous error
I'm unable to find out what's wrong. Why is the compiler unable to find my trait implementation?
This looks like it is a bug: std::num::ParseFloatError and <f64 as FromStr>::Err are different types:
the impl of FromStr for f64 is in core, and hence uses a ParseFloatError type defined in that crate, so any uses of FromStr/.parse() will get this type.
std::num defines a new ParseFloatError type, so an import from std::num gets this one.
The impl From<num::ParseFloatError> for Error is using the latter, while <f64 as FromStr>::from_str(...) is returning the former.
I opened #24748 about it. I also opened #24747 about improving the diagnostics to make this easier to debug in future.
One can work around this by insteading implementing the trait for core::num::ParseFloatError. You'll need to load the core crate with extern crate core; and will need some feature gates.

Why does using a reference inside of a match result in "cannot move out of dereference"?

Editor's note: This code example is from a version of Rust prior to 1.0 and is not valid Rust 1.0 code. Updated versions of this code produce different errors, but the answers still contain valuable information.
I don't understand why the following code is not working.
use std::string::String;
use std::str;
fn append_byte_to_string(string: &String, bytes: &[u8]) {
let msg = str::from_utf8(bytes);
match msg {
Some(msg_str) => {
string.append("plop");//msg_str);
},
None => {}
}
}
fn main() {
append_byte_to_string(&String::new(), [64,65]);
}
I've got the following error:
test.rs:8:4: 8:10 error: cannot move out of dereference of `&`-pointer
test.rs:8 string.append("plop");//msg_str);
^~~~~~
error: aborting due to previous error
I've seen explanations, but I don't understand how it is applicable to my code.
You have a &String: an immutable reference to a String object. Your method will need to take &mut String in order to be able to mutate the string:
use std::str;
fn append_byte_to_string(string: &mut String, bytes: &[u8]) {
if let Ok(msg) = str::from_utf8(bytes) {
string.push_str(msg);
}
}
fn main() {
append_byte_to_string(&mut String::new(), &[64, 65]);
}
By the way, you want push_str rather than append, as append (or in Rust 1.0, Add::add) consumes its argument and returns it, whereas push_str takes &mut self.

Resources