Improve diagnostics with missing trait implementations

Rejigger a few spans, work around an odd rustc issue, and hopefully
produce higher quality error messages!

Closes #1528
This commit is contained in:
Alex Crichton 2019-05-20 10:49:06 -07:00
parent a02d210d5c
commit 2cbb8b8a69
6 changed files with 68 additions and 9 deletions

View File

@ -1008,12 +1008,23 @@ impl TryToTokens for ast::ImportFunction {
quote!() quote!()
}; };
let invocation = quote! { // Route any errors pointing to this imported function to the identifier
#(#attrs)* // of the function we're imported from so we at least know what function
#[allow(bad_style)] // is causing issues.
#[doc = #doc_comment] //
#[allow(clippy::all)] // Note that this is where type errors like "doesn't implement
#vis fn #rust_name(#me #(#arguments),*) #ret { // FromWasmAbi" or "doesn't implement IntoWasmAbi" currently get routed.
// I suspect that's because they show up in the signature via trait
// projections as types of arguments, and all that needs to typecheck
// before the body can be typechecked. Due to rust-lang/rust#60980 (and
// probably related issues) we can't really get a precise span.
//
// Ideally what we want is to point errors for particular types back to
// the specific argument/type that generated the error, but it looks
// like rustc itself doesn't do great in that regard so let's just do
// the best we can in the meantime.
let extern_fn = respan(
quote! {
#[link(wasm_import_module = "__wbindgen_placeholder__")] #[link(wasm_import_module = "__wbindgen_placeholder__")]
#[cfg(all(target_arch = "wasm32", not(target_os = "emscripten")))] #[cfg(all(target_arch = "wasm32", not(target_os = "emscripten")))]
extern "C" { extern "C" {
@ -1024,6 +1035,17 @@ impl TryToTokens for ast::ImportFunction {
panic!("cannot call wasm-bindgen imported functions on \ panic!("cannot call wasm-bindgen imported functions on \
non-wasm targets"); non-wasm targets");
} }
},
&self.rust_name,
);
let invocation = quote! {
#(#attrs)*
#[allow(bad_style)]
#[doc = #doc_comment]
#[allow(clippy::all)]
#vis fn #rust_name(#me #(#arguments),*) #ret {
#extern_fn
unsafe { unsafe {
#exn_data #exn_data
@ -1444,6 +1466,8 @@ impl<'a, T: ToTokens> ToTokens for Descriptor<'a, T> {
} }
} }
/// Converts `span` into a stream of tokens, and attempts to ensure that `input`
/// has all the appropriate span information so errors in it point to `span`.
fn respan(input: TokenStream, span: &dyn ToTokens) -> TokenStream { fn respan(input: TokenStream, span: &dyn ToTokens) -> TokenStream {
let mut first_span = Span::call_site(); let mut first_span = Span::call_site();
let mut last_span = Span::call_site(); let mut last_span = Span::call_site();

View File

@ -1,7 +1,7 @@
error[E0277]: the trait bound `std::result::Result<wasm_bindgen::JsValue, wasm_bindgen::JsValue>: wasm_bindgen::convert::traits::FromWasmAbi` is not satisfied error[E0277]: the trait bound `std::result::Result<wasm_bindgen::JsValue, wasm_bindgen::JsValue>: wasm_bindgen::convert::traits::FromWasmAbi` is not satisfied
--> $DIR/missing-catch.rs:3:1 --> $DIR/missing-catch.rs:6:9
| |
3 | #[wasm_bindgen] 6 | pub fn foo() -> Result<JsValue, JsValue>;
| ^^^^^^^^^^^^^^^ the trait `wasm_bindgen::convert::traits::FromWasmAbi` is not implemented for `std::result::Result<wasm_bindgen::JsValue, wasm_bindgen::JsValue>` | ^^^ the trait `wasm_bindgen::convert::traits::FromWasmAbi` is not implemented for `std::result::Result<wasm_bindgen::JsValue, wasm_bindgen::JsValue>`
For more information about this error, try `rustc --explain E0277`. For more information about this error, try `rustc --explain E0277`.

View File

@ -0,0 +1,11 @@
use wasm_bindgen::prelude::*;
struct A;
#[wasm_bindgen]
extern "C" {
#[wasm_bindgen]
pub fn foo(a: A);
}
fn main() {}

View File

@ -0,0 +1,7 @@
error[E0277]: the trait bound `A: wasm_bindgen::convert::traits::IntoWasmAbi` is not satisfied
--> $DIR/traits-not-implemented.rs:8:12
|
8 | pub fn foo(a: A);
| ^^^ the trait `wasm_bindgen::convert::traits::IntoWasmAbi` is not implemented for `A`
For more information about this error, try `rustc --explain E0277`.

View File

@ -0,0 +1,10 @@
use wasm_bindgen::prelude::*;
#[wasm_bindgen]
extern "C" {
#[wasm_bindgen]
pub fn foo(a: A);
}
fn main() {}

View File

@ -0,0 +1,7 @@
error[E0412]: cannot find type `A` in this scope
--> $DIR/unknown-type-in-import.rs:6:19
|
6 | pub fn foo(a: A);
| ^ not found in this scope
For more information about this error, try `rustc --explain E0412`.