diff --git a/.travis.yml b/.travis.yml index 396d127..5509cc4 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,14 +1,21 @@ language: rust -rust: - - nightly -script: - - cargo build --verbose - - cargo test --verbose - - cargo build --verbose --features=nightly - - cargo test --verbose --features=nightly +matrix: + include: + - name: "Build & test on nightly WITH nightly feature" + rust: nightly + script: + - cargo build --verbose --features=nightly || travis_terminate 1 + - cargo test --verbose --features=nightly || travis_terminate 1 + - name: "Build & test on nightly WITHOUT nightly feature" + rust: nightly + script: + - cargo build --verbose || travis_terminate 1 + - cargo test --verbose || travis_terminate 1 + - name: "Build on beta" + rust: beta + script: cargo build --verbose env: - - RUST_FLAGS="--deny warnings" - -cache: cargo + global: + - RUSTFLAGS="--deny warnings" diff --git a/src/gen.rs b/src/gen.rs index f725b4e..a4d08eb 100644 --- a/src/gen.rs +++ b/src/gen.rs @@ -430,9 +430,39 @@ fn gen_method_item( // Generate the list of argument used to call the method. let args = get_arg_list(sig.decl.inputs.iter())?; - // Builds turbofish with generic types - let (_, generic_types, _) = sig.decl.generics.split_for_impl(); - let generic_types = generic_types.as_turbofish(); + // Build the turbofish type parameters. We need to pass type parameters + // explicitly as they cannot be inferred in all cases (e.g. something like + // `mem::size_of`). However, we don't explicitly specify lifetime + // parameters. Most lifetime parameters are so called late-bound lifetimes + // (ones that stick to input parameters) and Rust prohibits us from + // specifying late-bound lifetimes explicitly (which is not a problem, + // because those can always be correctly inferred). It would be possible to + // explicitly specify early-bound lifetimes, but this is hardly useful. + // Early-bound lifetimes are lifetimes that are only attached to the return + // type. Something like: + // + // fn foo<'a>() -> &'a i32 + // + // It's hard to imagine how such a function would even work. So since those + // functions are really rare and special, we won't support them. In + // particular, for us to determine if a lifetime parameter is early- or + // late-bound would be *really* difficult. + // + // So we just specify type parameters. In the future, however, we need to + // add support for const parameters. But those are not remotely stable yet, + // so we can wait a bit still. + let generic_types = sig.decl.generics + .type_params() + .map(|param| { + let name = ¶m.ident; + quote! { #name , } + }) + .collect::(); + let generic_types = if generic_types.is_empty() { + generic_types + } else { + quote ! { ::<#generic_types> } + }; // Generate the body of the function. This mainly depends on the self type, // but also on the proxy type. @@ -452,14 +482,14 @@ fn gen_method_item( // Receiver `self` (by value) SelfType::Value => { // The proxy type is a Box. - quote! { (*self).#name#generic_types(#args) } + quote! { (*self).#name #generic_types(#args) } } // `&self` or `&mut self` receiver SelfType::Ref | SelfType::Mut => { // The proxy type could be anything in the `Ref` case, and `&mut` // or Box in the `Mut` case. - quote! { (*self).#name#generic_types(#args) } + quote! { (*self).#name #generic_types(#args) } } }; diff --git a/src/lib.rs b/src/lib.rs index 109b025..f1dede1 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -2,7 +2,10 @@ //! references, some common smart pointers and closures. -#![cfg_attr(feature = "nightly", feature(proc_macro_diagnostic, proc_macro_span))] +#![cfg_attr( + feature = "nightly", + feature(proc_macro_diagnostic, proc_macro_span, proc_macro_def_site) +)] extern crate proc_macro; #[macro_use] diff --git a/tests/util/mod.rs b/tests/util/mod.rs index 06686ce..b849a54 100644 --- a/tests/util/mod.rs +++ b/tests/util/mod.rs @@ -21,11 +21,14 @@ pub(crate) fn get_dep_path() -> PathBuf { // Obtain the build plan from `cargo build`. This JSON plan will tell us // several things, including the path of the output of `auto_impl` (usually // an .so file on Linux). - let output = Command::new(env!("CARGO")) - .args(&["build", "-Z", "unstable-options", "--build-plan"]) - .stderr(Stdio::inherit()) - .output() - .expect("failed to run `cargo build`"); + let mut command = Command::new(env!("CARGO")); + command.args(&["build", "-Z", "unstable-options", "--build-plan"]); + command.stderr(Stdio::inherit()); + + #[cfg(feature = "nightly")] + command.arg("--features=nightly"); + + let output = command.output().expect("failed to run `cargo build`"); if !output.status.success() { panic!("failed to run `cargo build`");