2017-02-06 37 views
1

如何將EcsClient的實例與簽名impl<P, D> EcsClient<P, D> where P: ProvideAwsCredentials, D: DispatchSignedRequest一起作爲Rust中的參考傳遞給函數?我的嘗試是這樣的:如何傳遞一個帶有類型參數的結構作爲函數參數?

extern crate rusoto; 

use std::default::Default; 

use rusoto::{ DefaultCredentialsProvider, Region }; 
use rusoto::ecs::{ EcsClient }; 
use rusoto::default_tls_client; 

fn get_task_definition_revisions(client: &EcsClient) { 
    // Use EscClient instance here 
} 

fn main() { 
    let provider = DefaultCredentialsProvider::new().unwrap(); 
    let client = EcsClient::new(default_tls_client().unwrap(), provider, Region::EuWest1).unwrap(); 

    get_task_definition_revisions(&client); 

} 

這給了我下面的錯誤:

error[E0243]: wrong number of type arguments: expected 2, found 0 
--> src/main.rs:9:43 
    | 
9 | fn get_task_definition_revisions(client: &EcsClient) { 
    |           ^^^^^^^^^ expected 2 type arguments 

我嘗試了此修復程序是這樣的:

extern crate rusoto; 

use std::default::Default; 

use rusoto::{ 
    DefaultCredentialsProvider, 
    Region, 
    ProvideAwsCredentials, 
    DispatchSignedRequest 
}; 
use rusoto::ecs::{ EcsClient, ListTaskDefinitionsRequest }; 
use rusoto::default_tls_client; 

fn get_task_definition_revisions(client: &EcsClient<ProvideAwsCredentials, DispatchSignedRequest>) { 
    // Use EcsClient instance here 
} 

fn main() { 
    let provider = DefaultCredentialsProvider::new().unwrap(); 
    let client = EcsClient::new(default_tls_client().unwrap(), provider, Region::EuWest1); 

    get_task_definition_revisions(&client); 
} 

這給了我:

error[E0277]: the trait bound `rusoto::ProvideAwsCredentials + 'static: std::marker::Sized` is not satisfied 
    --> src/main.rs:14:1 
    | 
14 | fn get_task_definition_revisions(client: &EcsClient<P, D>) { 
    | _^ starting here... 
15 | | let defs = client.list_task_definitions(&ListTaskDefinitionsRequest { 
16 | |  family_prefix: None, 
17 | |  max_results: None, 
18 | |  next_token: None, 
19 | |  sort: None, 
20 | |  status: Some("ACTIVE".to_string()), 
21 | | }); 
22 | | } 
    | |_^ ...ending here: the trait `std::marker::Sized` is not implemented for `rusoto::ProvideAwsCredentials + 'static` 
    | 
    = note: `rusoto::ProvideAwsCredentials + 'static` does not have a constant size known at compile-time 
    = note: required by `rusoto::ecs::EcsClient` 

error[E0277]: the trait bound `rusoto::DispatchSignedRequest + 'static: std::marker::Sized` is not satisfied 
    --> src/main.rs:14:1 
    | 
14 | fn get_task_definition_revisions(client: &EcsClient<P, D>) { 
    | _^ starting here... 
15 | | let defs = client.list_task_definitions(&ListTaskDefinitionsRequest { 
16 | |  family_prefix: None, 
17 | |  max_results: None, 
18 | |  next_token: None, 
19 | |  sort: None, 
20 | |  status: Some("ACTIVE".to_string()), 
21 | | }); 
22 | | } 
    | |_^ ...ending here: the trait `std::marker::Sized` is not implemented for `rusoto::DispatchSignedRequest + 'static` 
    | 
    = note: `rusoto::DispatchSignedRequest + 'static` does not have a constant size known at compile-time 
    = note: required by `rusoto::ecs::EcsClient` 

這感覺就像一個兔子霍爾我不應該失望。

我也試過改變函數簽名來接受泛型,但是EcsClient是一個結構而不是特性。谷歌搜索沒有提供太多的幫助,因爲我不知道要搜索的正確術語。

This question似乎意味着我應該能夠聲明一個函數,如fn my_func(client: &EcsClient) { ... },它會工作,那麼爲什麼不上述示例?

+0

是否'FN get_task_definition_revisions (客戶端:EcsClient ){...}'工作?您需要聲明您在簽名中使用的任何類型參數。 –

+0

@ChrisEmerson不幸的不是。我得到的錯誤'性狀rusoto :: ProvideAwsCredentials沒有爲ProvideAwsCredentials'實施和'性狀rusoto :: ProvideAwsCredentials沒有爲ProvideAwsCredentials'實現。呼叫簽名應該是什麼樣子?我仍然有它的'get_task_definition_revisions(客戶端);' – Bojangles

回答

2

問題是EcsClient不是一個類型,它是構建一個類型(也稱爲「類型構造函數」)的藍圖。

因此,不能使用只需EcsClient當需要類型時,無論是在函數中還是在struct成員中;相反,每次您都必須通過指定其通用參數來使用它來構建類型。

因此,第一步驟是介紹類型參數:

fn get_task_definition_revisions<P, D>(client: &EcsClient<P, D>) {} 

然而,現在,編譯器會抱怨PD不充分約束:EcsClient只接受一個非常具體的種PD

因此,下一步是查找在EcsClient的定義中爲PD指定的邊界並應用它們。這只是複製/粘貼在這一點:

fn get_task_definition_revisions<P, D>(client: &EcsClient<P, D>) 
    where P: ProvideAwsCredentials, 
      D: DispatchSignedRequest 
{ 
} 

然後你是金。

如果您需要更多能力PD這個特定的功能,可隨時適當限制他們使用+增加更多的界限:

fn get_task_definition_revisions<P, D>(client: &EcsClient<P, D>) 
    where P: ProvideAwsCredentials + 'static, 
      D: DispatchSignedRequest 
{ 
} 

如果你想知道爲什麼鏽病選擇讓你重複PD的界限,因爲它可以完全推斷出它們,這是因爲它關心你。更具體地說,它在6個月之後關心你,並且下一個維護者會來。因此,採取一次寫多讀的態度,它會強制你複製邊界,以便以後不必知道它們是什麼,並且在用於痛苦地聚合所有片斷的每個類型/函數中遞歸地向下鑽取。在Rust中,下一次你閱讀這個函數時,你會得到所有的信息。

+0

非常感謝,這爲我解決了這個問題。我最後寫'FN get_task_definition_revisions (客戶端:&EcsClient ){'。這是否等同?我讀過'where'在想要使用多種類型時很有用,但是因爲我知道我只會使用'ProvideAwsCredentials'和'DispatchSignedRequest',可以接受我使用的語法嗎? – Bojangles

+1

@Bojangles:兩者完全相同。我自己更喜歡使用'where'子句來使參數列表接近函數名稱。 –

1

我是不正確地理解語法。看來PD是佔位符,就像T那樣。我需要指定什麼的類型是,所以它的簽名,現在看起來是這樣的:

fn get_task_definition_revisions<P: ProvideAwsCredentials, D: DispatchSignedRequest>(client: &EcsClient<P, D>) { 
    ... 
} 

我不函數體中使用PD,但他們必須申報。

完整的例子現在看起來像:

extern crate rusoto; 

use std::default::Default; 

use rusoto::{ 
    DefaultCredentialsProvider, 
    Region, 
    ProvideAwsCredentials, 
    DispatchSignedRequest 
}; 
use rusoto::ecs::{ StringList, EcsClient, ListTaskDefinitionsRequest }; 
use rusoto::default_tls_client; 

fn get_task_definition_revisions<P: ProvideAwsCredentials, D: DispatchSignedRequest>(client: &EcsClient<P, D>) { 
    let res = client.list_task_definitions(&ListTaskDefinitionsRequest { 
     family_prefix: None, 
     max_results: None, 
     next_token: None, 
     sort: None, 
     status: Some("ACTIVE".to_string()), 
    }); 

    // ... 
} 

fn main() { 
    let provider = DefaultCredentialsProvider::new().unwrap(); 
    let client = EcsClient::new(default_tls_client().unwrap(), provider, Region::EuWest1); 

    get_task_definition_revisions(&client); 
} 

我仍然不能完全肯定爲什麼這個工程或需要,但我希望這個答案可以幫助別人。

+1

注:也可以這麼說'FN get_task_definition_revisions (客戶端:EcsClient ),其中P:ProvideAwsCredentials,d:DispatchSignedRequest {}'這使得簽名更具有可讀性(恕我直言) –

相關問題