pub extern crate r2d2;
pub extern crate tiberius;
pub extern crate futures;
use self::tiberius::BoxableIo;
use self::futures::prelude::*;
use core::fmt::Debug;
#[allow(unused_imports)]
use std::error::Error;
type TiberiusConnection = self::tiberius::SqlConnection<Box<BoxableIo>>;
#[derive(Debug)]
pub enum Errors { TiberiusError(tiberius::Error) }
#[derive(Debug)]
pub struct MSSQLConnectionManagerError(Errors);
impl ::std::error::Error for MSSQLConnectionManagerError {
fn description(&self) -> &str {
match self.0 {
Errors::TiberiusError(ref e) => {
match e {
tiberius::Error::Io(e) => e.description(),
tiberius::Error::Protocol(msg) => &msg,
tiberius::Error::Encoding(msg) => &msg,
tiberius::Error::Conversion(msg) => &msg,
tiberius::Error::Utf8(e) => e.description(),
tiberius::Error::Utf16(e) => e.description(),
tiberius::Error::ParseInt(e) => e.description(),
// TODO: parse the server token if possible and report the actual error that occurred, like invalid login, etc.
tiberius::Error::Server(_) => "TDS token error occurred! When connecting, most often an invalid login.",
tiberius::Error::Canceled => "Canceled!",
}
}
}
}
}
impl ::std::fmt::Display for MSSQLConnectionManagerError {
fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
match self.0 { Errors::TiberiusError(ref e) => e.fmt(f), }
}
}
pub struct MSSQLConnection(TiberiusConnection);
pub struct MSSQLConnectionManager { connection_string: String }
impl MSSQLConnectionManager {
pub fn new(connection_string: String) -> MSSQLConnectionManager {
MSSQLConnectionManager { connection_string }
}
pub fn from_env() -> Result<MSSQLConnectionManager, ::std::env::VarError> {
let connection_string = ::std::env::var("MSSQL_CONNECTION_STRING")?;
Ok(MSSQLConnectionManager { connection_string })
}
}
impl r2d2::ManageConnection for MSSQLConnectionManager {
type Connection = MSSQLConnection;
type Error = MSSQLConnectionManagerError;
fn connect(&self) -> Result<Self::Connection, Self::Error> {
let connection_result = TiberiusConnection::connect(&self.connection_string)
.and_then(|c| Ok(c)).wait();
match connection_result {
Ok(c) => Ok(MSSQLConnection(c)),
Err(e) => Err(MSSQLConnectionManagerError(Errors::TiberiusError(e))),
}
}
fn is_valid(&self, _conn: &mut Self::Connection) -> Result<(), Self::Error> {
// TODO: Fix this quick and dirty implementation by checking the result of a simple query.
Ok(())
}
fn has_broken(&self, _conn: &mut Self::Connection) -> bool {
// TODO: Fix this quick and dirty implementation by checking underlying TCP socket state.
false
}
}
编译器提示 Ok(c) => Ok(Self::Connection(c)),
:
error[E0599]: no associated item named `Connection` found for type `persistence::mssql::MSSQLConnectionManager` in the current scope
--> src/persistence/mssql.rs:77:25
|
56 | pub struct MSSQLConnectionManager { connection_string: String }
| --------------------------------- associated item `Connection` not found for this
...
77 | Ok(c) => Ok(Self::Connection(c)),
| ^^^^^^^^^^^^^^^^ associated item not found in `persistence::mssql::MSSQLConnectionManager`
当我明确地写它时,像这样:
match connection_result {
Ok(c) => Ok(MSSQLConnection(c)),
Err(e) => Err(MSSQLConnectionManagerError(Errors::TiberiusError(e))),
}
现在编译成功了。
如果我尝试使用 L10 返回 Err(Self::Error(e))
,我确实会遇到相同的编译器错误。
为什么这不像我预期的那样工作?
最佳答案
这是一个重现相同问题的最小示例。为清楚起见,更改了一些类型名称。
trait Manager {
type Connection;
fn connect(&self) -> Self::Connection;
}
pub struct ConnectionId(usize);
pub struct FooManager;
impl Manager for FooManager {
type Connection = ConnectionId;
fn connect(&self) -> Self::Connection {
Self::Connection(5)
}
}
错误是由于尝试使用关联类型 Connection
作为具体类型 ConnectionId
的别名而出现的,正如 Manager
的实现所定义的>。但是,关联类型的行为并不完全像类型别名。即使我们可以构造一个 ConnectionId
(因为它是一个元组结构,并且我们可以看到它在这个模块中的成员),我们不能通过关联类型 Self::Connection< 来做到这一点
。我们可以做的是访问由其约束定义的其他符号。例如,如果我们有这个:
trait Manager {
type Connection: Default;
// ...
}
我们可以从 Self::Connection
调用 default
。
因此,将原始示例中的表达式 Ok(Self::Connection(c))
更改为 Ok(MSSQLConnection(c)),
是正确的方法解决这个问题。如果即使在这一步也需要将类型抽象掉,您可以将关联类型限制为提供必要构造方法的新特征。
关于compiler-errors - 从方法内部的模式匹配返回时在当前范围内找不到关联类型,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52651566/