Why doesn't this Rust code compile?
use std::fs;
use std::io;
use std::path::Path;
fn do_job(path: &Path) -> io::Result<()> {
let mut files: Vec<&Path> = Vec::new();
for entry in try!(fs::read_dir(path)) {
entry = try!(entry);
}
}
it's very similar to code in the docs.
compile error:
<std macros>:3:43: 3:46 error: mismatched types:
expected `core::result::Result<std::fs::DirEntry, std::io::error::Error>`,
found `std::fs::DirEntry`
(expected enum `core::result::Result`,
found struct `std::fs::DirEntry`) [E0308]
<std macros>:3 $ crate:: result:: Result:: Ok ( val ) => val , $ crate:: result:: Result::
^~~
src/main.rs:13:17: 13:28 note: in this expansion of try! (defined in <std macros>)
<std macros>:3:43: 3:46 help: run `rustc --explain E0308` to see a detailed explanation
src/main.rs:12:5: 14:6 error: mismatched types:
expected `core::result::Result<(), std::io::error::Error>`,
found `()`
(expected enum `core::result::Result`,
found ()) [E0308]
src/main.rs:12 for entry in try!(fs::read_dir(path)) {
src/main.rs:13 entry = try!(entry);
src/main.rs:14 }
src/main.rs:12:5: 14:6 help: run `rustc --explain E0308` to see a detailed explanation
It looks like you want a new binding for each directory entry in your loop:
for entry in fs::read_dir(path)? {
let entry = entry?;
}
this new binding will shadow the one introduced in the for expression.
The type of entry introduced by the loop is Result<DirEntry> which you are trying to unwrap using ? (formerly try!). However you are attempting to assign the resulting DirEntry to a binding with type Result<DirEntry>, hence the error.
The second error indicates that the return value from your function does not match the declared type of io::Result<()>. You can simply return Ok(()):
fn do_job(path: &Path) -> io::Result<()> {
let mut files: Vec<&Path> = Vec::new();
for entry in fs::read_dir(path)? {
let entry = entry?;
//process entry
}
Ok(())
}
Related
Getting the following error:
error[E0308]: mismatched types
--> src/u/r/api/products/articles.rs:17:69
|
17 | let query = web::block(move || articles::table.load::<Articles>(&*connection).unwrap()).await;
| ---------------- ^^^^^^^^^^^^ types differ in mutability
| |
| arguments to this function are incorrect
|
= note: expected mutable reference `&mut _`
found reference `&PgConnection`
note: associated function defined here
--> /Users/b/.cargo/registry/src/github.com/diesel-2.0.2/src/query_dsl/mod.rs:1497:8
|
1497 | fn load<'query, U>(self, conn: &mut Conn) -> QueryResult<Vec<U>>
| ^^^^
I am using Diesel v2, it worked before I upgraded to the latest version.
What am I doing wrong?
use crate::u::db::connection::DbPool;
use actix_web::{get, web, HttpResponse, Responder};
#[get("/product/articles")]
pub async fn list(db_pool: web::Data<DbPool>) -> impl Responder {
use crate::u::db::models::products::Articles;
use crate::u::db::schemas::products::articles;
let connection = db_pool.get();
if let Err(e) = connection {
return HttpResponse::InternalServerError().body(format!("E1-{:?}", e));
}
let connection = connection.unwrap();
let query = web::block(move || articles::table.load::<Articles>(&*connection).unwrap()).await;
if let Err(e) = query {
return HttpResponse::InternalServerError().body(format!("E2-{:?}", e));
}
let q = query.expect("oops not Ok");
HttpResponse::Ok().json(q)
}
models/products.rs
use chrono::{DateTime, Utc};
use uuid::Uuid;
use crate::u::db::schemas::products::*;
#[derive(Queryable, Debug, Identifiable, serde::Serialize, serde::Deserialize)]
#[table_name = "articles"]
#[primary_key(prod_art_pvt_uuid)]
pub struct Articles {
pub prod_art_pvt_uuid: Uuid,
pub prod_art_pub_uuid: Uuid,
pub prod_article_pub_id: i32,
pub t: DateTime<Utc>,
}
db/connection.rs
use crate::u::config;
use diesel::pg::PgConnection;
use diesel::r2d2::ConnectionManager;
use r2d2::Pool;
pub type DbPool = r2d2::Pool<ConnectionManager<PgConnection>>;
pub fn get_pool() -> DbPool {
let url: String = config::get("database_url");
println!("Connecting to database...");
let manager = ConnectionManager::<PgConnection>::new(url);
Pool::builder()
.build(manager)
.expect("Failed to create database connection pool.")
}
The error message already indicates what needs to be change. The important part is that one:
error[E0308]: mismatched types
--> src/u/r/api/products/articles.rs:17:69
|
17 | let query = web::block(move || articles::table.load::<Articles>(&*connection).unwrap()).await;
| ---------------- ^^^^^^^^^^^^ types differ in mutability
| |
| arguments to this function are incorrect
|
= note: expected mutable reference `&mut _`
found reference `&PgConnection`
As you can see there you need to change the argument of the load function to a mutable reference. You try to pass an immutable reference, which is something that's not accepted by the underlying function.
I recommend to checkout the Diesel Migration guide which contains an overview of most user-facing breaking changes of the 2.0 release.
Is there a way to specialize the generic and test for the optional in one line? In others words, have line #1 and #2 I-as a single line of code?
func getTo<T>() -> T? {
// Real code here replaced by setting nil for clarity
nil
}
// Working version
// Line #1
let _r: [Any]? = getTo()
// Line #2
if let r = _r {
for e in r {
print ("\(e)")
}
}
// Not working single line version
// Single line
if let r: [Any]? = getTo() {
// Error here: error: for-in loop requires '[Any]?' to conform to 'Sequence'; did you mean to unwrap optional?
//for e in r {
// ^
for e in r {
print ("\(e)")
}
}
PS: Sorry, initial code was truncated.
Yes. This works:
guard let r: [Any] = getTo(breadcrumbs: ["here"]) else {
return nil
}
I have following function:
func myNSLog(_ givenFormat: String, _ args: CVarArg..., _ function:String = #function) {
let format = "\(function): \(givenFormat)"
NSLog(format, args)
Which results in the following error:
'NSLog' has been explicitly marked unavailable here (Foundation.NSLog)
Within the documentation is it explicit listed as available. What do I miss?
Similar as in C, you cannot pass a variable argument list directly
to another function. You have to create a CVaListPointer (the Swift
equivalent of va_list) and pass that to the NSLogv variant:
func myNSLog(_ givenFormat: String, _ args: CVarArg..., _ function:String = #function) {
let format = "\(function): \(givenFormat)"
withVaList(args) { NSLogv(format, $0) }
}
(Swift 3 code.)
I have a C function called Foo_C_Func, which I need to use as a callback. The rest of the app is coded in Swift. As I understand it, the following code should work, but instead I get a compiler error.
// typealias makes our function signature easier to read
typealias Sig = ( EventHandlerCallRef, EventRef, UnsafeMutablePointer<Void>) -> OSStatus
// We need to make a CFunctionPointer to the C function
var ptr = UnsafeMutablePointer<Sig>.alloc(1)
ptr.initialize( Foo_C_Func )
let c_ptr = COpaquePointer( ptr )
let proc_ptr = CFunctionPointer<Sig>( c_ptr ) as EventHandlerProcPtr
// now we should be able to create the EventHandlerUPP
let handler_upp = NewEventHandlerUPP( proc_ptr )
Trying to Build this fails with the following error:
Undefined symbols for architecture x86_64:
"_Foo_C_Func", referenced from:
__TTOFSC10Foo_C_FuncFTVSs14COpaquePointerS_GVSs20UnsafeMutablePointerT___VSs5Int32 in Demo.o
"_NewEventHandlerUPP", referenced from:
__TFC17DemocfMS0_FT_S0_ in Demo.o
ld: symbol(s) not found for architecture x86_64
I also notice when I hover over the last line, that the Xcode tooltip shows the return type of NewEventHandlerUpp to be (EventHandlerProcPtr) rather than EventHandlerProcPtr.
Am I doing it wrong, or is it impossible to create an EventHandlerUPP within Swift?
I'm posting this for user MAH, though I have abandoned the original project. The following code compiles in Swift 3. I haven't check whether it works beyond that.
import Carbon
func hotkey_callback( _:EventHandlerCallRef?, _ event:EventRef?, _ context:UnsafeMutablePointer<Void>? ) -> OSStatus {
// Do stuff
return noErr
}
let handler_ref_ptr = UnsafeMutablePointer<EventHandlerRef?>( allocatingCapacity: 1 )
let spec_ptr = UnsafeMutablePointer<EventTypeSpec>( allocatingCapacity: 1 )
spec_ptr.pointee = EventTypeSpec( eventClass: OSType( kEventClassKeyboard ), eventKind: UInt32( kEventHotKeyPressed ) )
let hotkey_callback_pointer = hotkey_callback as! EventHandlerUPP
let status = InstallEventHandler( GetEventDispatcherTarget(), hotkey_callback_pointer, 1, spec_ptr, nil, handler_ref_ptr )
Here's an alternate answer, if you're using Swift 3. Swift 2 is different than Swift 3, in that the former sucks, whereas the latter is usable.
let hotkey_callback: EventHandlerUPP = { _, _, _ in
// Do stuff
return noErr
}
var handler: EventHandlerRef? = nil
var spec = EventTypeSpec(
eventClass: OSType(kEventClassKeyboard), eventKind: UInt32(kEventHotKeyPressed)
)
let status = InstallEventHandler(
GetEventDispatcherTarget(), hotkey_callback, 1, &spec, nil, &handler
)
Note that we can use "&" to avoid manually allocating pointers now, and note that adhering to the informal "EventHandlerUPP" protocol is now explicit and doesn't require our manually declaring the Type of each argument. So much easier to read :)
According to Apple's Swift guide, when you have the following Array and the following function to search through an Array:
let namesArray = ["John", "Lisa", "Bill", "Jennifer"]
// Note this function is set-up to return an OPTIONAL Int:
func findName (personName:String, arrayToSearchIn:String[]) -> Int? {
for (indexOfName, nameValue) in enumerate(arrayToSearchIn) {
if nameValue == personName {
return indexOfName
}
}
return nil
}
...so you can capture the Optional Int returned by this function - and then check to see if its nil or not - in the following manner:
let nameIndex: Int? = findName("Lisa", arrayToSearchIn: namesArray)
if nameIndex {
println("found \(namesArray[nameIndex!])")
}
else {
println("NOT found")
}
This is all good - but their next example, in which they streamline the code by collapsing the 2 statements into one - confuses me because they suddenly drop the Optional "?" and "!" from their syntax:
if let nameIndex = findName("Lisa", arrayToSearchIn: namesArray) {
println("found \(namesArray[nameIndex])")
}
And this works perfectly well.
So why is it that in the first example nameIndex was declared with a "?" - like so:
nameIndex:Int?
and the forced-unwrapping occurs using a "!"
[nameIndex!]
but in the second example neither "?" or "!" one is used in the syntax?
The handling of the declaration in an if let is special; one should treat it as its own language construct (not as a simple combination of if and let). In
if let nameIndex = findName("Lisa", arrayToSearchIn: namesArray) {
println("found \(namesArray[nameIndex]")
}
the type of nameIndex does not need to be expressed because it can be inferred as the return type of findName() which is Int?. In the body of the if let ... the value of nameIndex is not bound to an optional and thus unwrapping is not needed - the value will be an Int.
Here is an example of how the if let binding is treated. Notice that an explicit declaration of the type is essentially ignored:
> func test () -> Int? { return 111 }
> if let x : Int? = test () { return x }
$R6: Int? = 111
> if let x : Int = test () { return x }
$R7: Int = 111
> if let x = test () { return x }
$R8: Int = 111
but if you try to be so 'flexible' outside of an if let, you draw an error from the compiler:
> let y : Int = test ()
<REPL>:33:15: error: value of optional type 'Int?' not unwrapped;
did you mean to use '!' or '?'?
? is the operator to explicitly declare an optional type. ! is the operator to force-unwrap an optional. The syntax in the example is a special Swift shorthand for checking and unwrapping in one concise line. It says, “assign nameIndex to the result of findName(...), and if it is not nil, run the following code: ...”