Gavin Gray (@gavinleroy) | ETH Zürich |
Will Crichton | Brown University |
forth!(
: factorial (n -- n) 1 swap fact0 ;
: fact0 (n n -- n) dup 1 = if drop else dup rot * swap pred fact0 then ;
5 factorial .
);
trait IntoString {
fn to_string(&self) -> String;
}
impl IntoString for (i32, i32) {
fn to_string(&self) -> String {
format!(
"({}, {})",
self.0, self.1
)
}
}
impl<T: IntoString>
IntoString for Vec<T> {
fn to_string(&self) -> String
{ /* ... */ }
}
fn main() {
let v: Vec<(i32, i32)> = vec![
(0, 1), (2, 3)
];
println!("{}", v.to_string());
}
A trait definition, establishing the unit of shared behavior.
trait IntoString {
fn to_string(&self) -> String;
}
impl IntoString for (i32, i32) {
fn to_string(&self) -> String {
format!(
"({}, {})",
self.0, self.1
)
}
}
impl<T: IntoString>
IntoString for Vec<T> {
fn to_string(&self) -> String
{ /* ... */ }
}
fn main() {
let v: Vec<(i32, i32)> = vec![
(0, 1), (2, 3)
];
println!("{}", v.to_string());
}
(i32, i32): IntoString.
A trait implementation associates a type with a trait.
trait IntoString {
fn to_string(&self) -> String;
}
impl IntoString for (i32, i32) {
fn to_string(&self) -> String {
format!(
"({}, {})",
self.0, self.1
)
}
}
impl<T: IntoString>
IntoString for Vec<T> {
fn to_string(&self) -> String
{ /* ... */ }
}
fn main() {
let v: Vec<(i32, i32)> = vec![
(0, 1), (2, 3)
];
println!("{}", v.to_string());
}
(i32, i32): IntoString.
Vec<T>: IntoString :-
T: IntoString.
Implementations can be parametric.
trait IntoString {
fn to_string(&self) -> String;
}
impl IntoString for (i32, i32) {
fn to_string(&self) -> String {
format!(
"({}, {})",
self.0, self.1
)
}
}
impl<T: IntoString>
IntoString for Vec<T> {
fn to_string(&self) -> String
{ /* ... */ }
}
fn main() {
let v: Vec<(i32, i32)> = vec![
(0, 1), (2, 3)
];
println!("{}", v.to_string());
}
(i32, i32): IntoString.
Vec<T>: IntoString :-
T: IntoString.
?- Vec<(i32, i32)>: IntoString.
Type-checking queries the current facts.
(i32, i32): IntoString.
Vec<T>: IntoString :-
T: IntoString.
?- Vec<(i32, i32)>: IntoString.
flowchart TD A["?- Vec<(i32, i32)>: IntoString"]
(i32, i32): IntoString.
Vec<T>: IntoString :-
T: IntoString.
?- Vec<(i32, i32)>: IntoString.
flowchart TD A["?- Vec<(i32, i32)>: IntoString"] B["(i32, i32): IntoString"]; A --> B
(i32, i32): IntoString.
Vec<T>: IntoString :-
T: IntoString.
?- Vec<(i32, i32)>: IntoString.
flowchart TD A["?- Vec<(i32, i32)>: IntoString"] B["(i32, i32): IntoString"]; A --> B C["Yes"] B --> C
(i32, i32): IntoString.
Vec<T>: IntoString :-
T: IntoString.
?- Vec<String>: IntoString.
fn main() {
let v: Vec<String> = vec![
String::from("We're"),
String::from("Strings!")
];
println!("{}", v.to_string());
}
flowchart TD A["?- Vec<String>: IntoString"] B["String: IntoString"]; A --> B C["No"] B --> C
error[E0599]: the method `to_string` exists for struct `Vec<String>`,
but its trait bounds were not satisfied
--> src/main.rs:24:20
|
24 | println!("{}", v.to_string());
| ^^^^^^^^^
| method cannot be called on `Vec<String>` due to unsatisfied trait bounds
|
= note: doesn't satisfy `String: IntoString`
= note: doesn't satisfy `Vec<String>: IntoString`
|
note: trait bound `String: IntoString` was not satisfied
--> src/main.rs:14:9
|
14 | impl<T: IntoString>
| ^^^^^^^^^^ unsatisfied trait bound introduced here
15 | IntoString for Vec<T> {
| ---------- ------
flowchart TD A["?- Vec<String>: IntoString"] B["String: IntoString"]; A --> B C["No"] B --> C
bevy: game development.
How simple is it really?
use bevy::prelude::*;
#[derive(Resource)]
struct Timer(usize);
fn run_timer(timer: Res<Timer>) {
/* ... */
}
fn main() {
App::new()
.insert_resource(Timer(0))
.add_system(run_timer)
.run();
}
use bevy::prelude::*;
#[derive(Resource)]
struct Timer(usize);
fn run_timer(timer: Timer) {
/* ... */
}
fn main() {
App::new()
.insert_resource(Timer(0))
.add_system(run_timer)
.run();
}
We’re looking for the information about Timer: SystemParam.
Timer nor SystemParam is mentioned in the ~30 line diagnostic.
The trait bound `fn(Timer) {run_timer}: IntoSystem<(), (), _>` is not satisfied
--> src/main.rs:6:24
|
6 | fn main() { use_system(run_timer) }
| ---------- ^^^^^^^^^ the trait `IntoSystem<(), (), _>`
| | is not implemented for fn item `fn(Timer) {run_timer}`
| |
| required by a bound introduced by this call
|
note: required for `fn(Timer) {run_timer}` to implement `bevy::prelude::IntoSystemConfig<_>`
--> src/main.rs:41:9
|
41 | IntoSystemConfig<Marker> for F
| ^^^^^^^^^^^^^^^^^^^^^^^^ ^
42 | where F: IntoSystem<(), (), Marker> {}
| ------------------ unsatisfied trait bound introduced here
note: required by a bound in `use_system`
--> src/main.rs:4:26
|
4 | fn use_system<M>(_: impl IntoSystemConfig<M>) {}
| ^^^^^^^^^^^^^^^^^^^ required by this bound in `use_system`
Shouldn’t documentation aid developers in understanding diagnostics?
3 pages
92 trait implementations!
Timer: Resource.
Res<T>: SystemParam :-
T: Resource.
fn(P0): SystemParamFunc :-
P0: SystemParam.
fn(TheWorld): ExclSystemParamFunc.
F: IntoSystem :-
F: SystemParamFunc.
F: IntoSystem :-
F: ExclSystemParamFunc.
F: IntoSystemConfigs :-
F: IntoSystem.
?- fn(Timer): IntoSystem.
flowchart TD classDef invisible display:none A["?- fn(Timer): IntoSystemConfigs"] B{{"fn(Timer): IntoSystem"}} C["fn(Timer): SystemParamFunc"] D["Timer: SystemParam"] E["No"] F["fn(Timer): ExclSystemParamFunc"] H["No"] class A,B,C,D,E,F,H invisible A ~~~ B B ~~~ C C ~~~ D D ~~~ E B ~~~ F F ~~~ H
Timer: Resource.
Res<T>: SystemParam :-
T: Resource.
fn(P0): SystemParamFunc :-
P0: SystemParam.
fn(TheWorld): ExclSystemParamFunc.
F: IntoSystem :-
F: SystemParamFunc.
F: IntoSystem :-
F: ExclSystemParamFunc.
F: IntoSystemConfigs :-
F: IntoSystem.
?- fn(Timer): IntoSystem.
flowchart TD classDef invisible display:none A["?- fn(Timer): IntoSystemConfigs"] B{{"fn(Timer): IntoSystem"}} C["fn(Timer): SystemParamFunc"] D["Timer: SystemParam"] E["No"] F["fn(Timer): ExclSystemParamFunc"] H["No"] class A,C,D,E,F,H invisible B ~~~ C C ~~~ D D ~~~ E B ~~~ F F ~~~ H
Timer: Resource.
Res<T>: SystemParam :-
T: Resource.
fn(P0): SystemParamFunc :-
P0: SystemParam.
fn(TheWorld): ExclSystemParamFunc.
F: IntoSystem :-
F: SystemParamFunc.
F: IntoSystem :-
F: ExclSystemParamFunc.
F: IntoSystemConfigs :-
F: IntoSystem.
?- fn(Timer): IntoSystem.
flowchart TD classDef invisible display:none A["?- fn(Timer): IntoSystemConfigs"] B{{"fn(Timer): IntoSystem"}} C["fn(Timer): SystemParamFunc"] D["Timer: SystemParam"] E["No"] F["fn(Timer): ExclSystemParamFunc"] H["No"] class A,D,E,H invisible B -.-> C C ~~~ D D ~~~ E B -.-> F F ~~~ H
Timer: Resource.
Res<T>: SystemParam :-
T: Resource.
fn(P0): SystemParamFunc :-
P0: SystemParam.
fn(TheWorld): ExclSystemParamFunc.
F: IntoSystem :-
F: SystemParamFunc.
F: IntoSystem :-
F: ExclSystemParamFunc.
F: IntoSystemConfigs :-
F: IntoSystem.
?- fn(Timer): IntoSystem.
flowchart TD classDef invisible display:none A["?- fn(Timer): IntoSystemConfigs"] B{{"fn(Timer): IntoSystem"}} C["fn(Timer): SystemParamFunc"] D["Timer: SystemParam"] E["No"] F["fn(Timer): ExclSystemParamFunc"] H["No"] class A,D,E invisible B -.-> C C ~~~ D D ~~~ E B -.-> F F --> H
Timer: Resource.
Res<T>: SystemParam :-
T: Resource.
fn(P0): SystemParamFunc :-
P0: SystemParam.
fn(TheWorld): ExclSystemParamFunc.
F: IntoSystem :-
F: SystemParamFunc.
F: IntoSystem :-
F: ExclSystemParamFunc.
F: IntoSystemConfigs :-
F: IntoSystem.
?- fn(Timer): IntoSystem.
flowchart TD classDef invisible display:none A["?- fn(Timer): IntoSystemConfigs"] B{{"fn(Timer): IntoSystem"}} C["fn(Timer): SystemParamFunc"] D["Timer: SystemParam"] E["No"] F["fn(Timer): ExclSystemParamFunc"] H["No"] class A,E invisible B -.-> C C --> D D ~~~ E B -.-> F F --> H
Timer: Resource.
Res<T>: SystemParam :-
T: Resource.
fn(P0): SystemParamFunc :-
P0: SystemParam.
fn(TheWorld): ExclSystemParamFunc.
F: IntoSystem :-
F: SystemParamFunc.
F: IntoSystem :-
F: ExclSystemParamFunc.
F: IntoSystemConfigs :-
F: IntoSystem.
?- fn(Timer): IntoSystem.
flowchart TD classDef invisible display:none A["?- fn(Timer): IntoSystemConfigs"] B{{"fn(Timer): IntoSystem"}} C["fn(Timer): SystemParamFunc"] D["Timer: SystemParam"] E["No"] F["fn(Timer): ExclSystemParamFunc"] H["No"] class A invisible B -.-> C C --> D D --> E B -.-> F F --> H
error[E0599]: the method `to_string` exists for struct `Vec<String>`,
but its trait bounds were not satisfied
--> src/main.rs:24:20
|
24 | println!("{}", v.to_string());
| ^^^^^^^^^
| method cannot be called on `Vec<String>` due to unsatisfied trait bounds
|
= note: doesn't satisfy `String: IntoString`
= note: doesn't satisfy `Vec<String>: IntoString`
|
note: trait bound `String: IntoString` was not satisfied
--> src/main.rs:14:9
|
14 | impl<T: IntoString>
| ^^^^^^^^^^ unsatisfied trait bound introduced here
15 | IntoString for Vec<T> {
| ---------- ------
flowchart TD A["?- Vec<String>: IntoString"] B["String: IntoString"]; A --> B C["No"] B --> C
The trait bound `fn(Timer) {run_timer}: IntoSystem<(), (), _>` is not satisfied
--> src/main.rs:6:24
|
6 | fn main() { use_system(run_timer) }
| ---------- ^^^^^^^^^ the trait `IntoSystem<(), (), _>`
| | is not implemented for fn item `fn(Timer) {run_timer}`
| |
| required by a bound introduced by this call
|
note: required for `fn(Timer) {run_timer}` to implement `bevy::prelude::IntoSystemConfig<_>`
--> src/main.rs:41:9
|
41 | IntoSystemConfig<Marker> for F
| ^^^^^^^^^^^^^^^^^^^^^^^^ ^
42 | where F: IntoSystem<(), (), Marker> {}
| ------------------ unsatisfied trait bound introduced here
note: required by a bound in `use_system`
--> src/main.rs:4:26
|
4 | fn use_system<M>(_: impl IntoSystemConfig<M>) {}
| ^^^^^^^^^^^^^^^^^^^ required by this bound in `use_system`
flowchart TD classDef invisible display:none A["?- fn(Timer): IntoSystemConfigs"] B{{"fn(Timer): IntoSystem"}} C["fn(Timer): SystemParamFunc"] D["Timer: SystemParam"] E["No"] F["fn(Timer): ExclSystemParamFunc"] H["No"] class A invisible B -.-> C C --> D D --> E B -.-> F F --> H
We see this as an interface problem.
flowchart TD classDef invisible display:none A["?- fn(Timer): IntoSystemConfigs"] B{{"fn(Timer): IntoSystem"}} C["fn(Timer): SystemParamFunc"] D["Timer: SystemParam"] E["No"] F["fn(Timer): ExclSystemParamFunc"] H["No"] class A invisible B -.-> C C --> D D --> E B -.-> F F --> H
overflow evaluating the requirement `_: diesel::Expression`
--> src/main.rs:15:10
|
15 | .group_by(users::id)
| ^^^^^^^^
requirements on the impl of `LoadQuery<'_, _, (i32, std::string::String)>` for `SelectStatement<FromClause<users::table>, diesel::query_builder::select_clause::DefaultSelectClause<FromClause<users::table>>, diesel::query_builder::distinct_clause::NoDistinctClause, diesel::query_builder::where_clause::WhereClause<diesel::expression::grouped::Grouped<diesel::expression::operators::Eq<users::columns::id, posts::columns::id>>>>`
requirements on the impl ofLoadQueryfor●'_, _,()●i32, StringSelectStatement●FromClause,●users::tableDefaultSelectClause●FromClause, NoDistinctClause,●users::tableWhereClause●Grouped●Eq●users::columns::id, posts::columns::id
App::new()
.insert_resource(Timer(0))
.add_system(run_timer)
.run();
flowchart TD A["?- Vec<String>: IntoString"] B["String: IntoString"]; A --> B C["No"] B --> C
flowchart TD classDef invisible display:none A["?- fn(Timer): IntoSystemConfigs"] B{{"fn(Timer): IntoSystem"}} C["fn(Timer): SystemParamFunc"] D["Timer: SystemParam"] E["No"] F["fn(Timer): ExclSystemParamFunc"] H["No"] class A invisible B -.-> C C --> D D --> E B -.-> F F --> H
LoadQuery:●'_, _,()●i32, StringSelectStatement●FromClause,●users::tableDefaultSelectClause●FromClause, NoDistinctClause,●users::tableWhereClause●Grouped●Eq●users::columns::id, posts::columns::id
What approach would you take if you were to build a trait debugger?
Are there related problems where this approach could be useful? (E.g., I think debugging Coq tactics is closely relatead.)
What features would you want in such an interface?