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.
(i32, i32): IntoString. Vec<T>: IntoString :- T: IntoString.
?- Vec<(i32, i32)>: IntoString.
(i32, i32): IntoString. Vec<T>: IntoString :- T: IntoString.
?- Vec<(i32, i32)>: IntoString.
(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()); }
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> { | ---------- ------
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> { | ---------- ------
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> { | ---------- ------
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.
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.
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.
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.
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.
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.
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> {
| ---------- ------
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`
We see this as an interface problem.
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();
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?