Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 4 additions & 3 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ jobs:
- os: ubuntu-latest
toolchain: nightly
variant: docs
features: "--features nightly-diagnostics"
- os: macos-latest
toolchain: beta
- os: windows-latest
Expand All @@ -41,13 +42,13 @@ jobs:

- name: Build docs
if: ${{ matrix.variant == 'docs' }}
run: cargo doc --all-features --all --no-deps
run: cargo doc ${{ matrix.features }} --all --no-deps

- name: Test impl-tools-lib
run: cargo test --manifest-path lib/Cargo.toml --all-features ${{ matrix.targets }}
run: cargo test --manifest-path lib/Cargo.toml ${{ matrix.targets }}

- name: Test impl-tools
run: cargo test --all-features ${{ matrix.targets }}
run: cargo test ${{ matrix.features }} ${{ matrix.targets }}

- name: Test test-cfg
working-directory: tests/test-cfg
Expand Down
6 changes: 6 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,12 @@ edition.workspace = true
[lib]
proc-macro = true

[features]
# Enables better proc-macro diagnostics (including warnings); nightly only.
nightly-diagnostics = ["proc-macro-error2/nightly"]
# Squelch lint: "autoimpl on trait that has a method with Self: Sized bound"
allow-trait-autoimpl-with-sized-fn-bound = ["impl-tools-lib/allow-trait-autoimpl-with-sized-fn-bound"]

[dependencies.proc-macro-error2]
version = "2.0"
default-features = false
Expand Down
File renamed without changes.
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
error: expected `Self` or `A` or `A<...>` or `Trait for Self`, etc
--> compile-errors/expect-self.rs:5:10
--> compile-errors/common/expect-self.rs:5:10
|
5 | impl () {
| ^^
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
error: #[autoimpl(Trait)] can only be used on enum or struct items
--> compile-errors/wrong-item-type.rs:3:1
--> compile-errors/common/wrong-item-type.rs:3:1
|
3 | #[impl_tools::autoimpl(Copy)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Expand Down
16 changes: 16 additions & 0 deletions compile-errors/nightly/expect-self-anon.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
error: expected `Self` or `Trait for Self`
--> compile-errors/nightly/expect-self-anon.rs:6:14
|
6 | impl () {
| ^^

error: expected expression, found end of macro arguments
--> compile-errors/nightly/expect-self-anon.rs:2:13
|
2 | let _ = impl_tools::impl_anon! {
| _____________^
3 | | #[derive(Clone, Debug)]
4 | | struct (i32 = 123);
... |
11 | | };
| |_____^
21 changes: 21 additions & 0 deletions compile-errors/nightly/trait-autoimpl-with-sized-fn-bound.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
use impl_tools::autoimpl;
use core::fmt::Debug;

#[autoimpl(for<'a, T> &'a T, &'a mut T, Box<T> where T: trait + ?Sized)]
trait G<V>
where
V: Debug,
{
fn g(&self) -> V;

fn s<X>(&self, f: impl Fn(V) -> X) -> X
where
Self: Sized,
{
f(self.g())
}
}

fn main() {
compile_error!("Warnings verification");
}
22 changes: 22 additions & 0 deletions compile-errors/nightly/trait-autoimpl-with-sized-fn-bound.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
warning: autoimpl on trait that has a method with Self: Sized bound
--> compile-errors/nightly/trait-autoimpl-with-sized-fn-bound.rs:4:1
|
4 | #[autoimpl(for<'a, T> &'a T, &'a mut T, Box<T> where T: trait + ?Sized)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
note: method impl uses default implementation, not deref
--> compile-errors/nightly/trait-autoimpl-with-sized-fn-bound.rs:11:5
|
11 | / fn s<X>(&self, f: impl Fn(V) -> X) -> X
12 | | where
13 | | Self: Sized,
... |
16 | | }
| |_____^
= note: this warning originates in the attribute macro `autoimpl` (in Nightly builds, run with -Z macro-backtrace for more info)

error: Warnings verification
--> compile-errors/nightly/trait-autoimpl-with-sized-fn-bound.rs:20:5
|
20 | compile_error!("Warnings verification");
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
12 changes: 12 additions & 0 deletions compile-errors/stable/expect-self-anon.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
fn main() {
let _ = impl_tools::impl_anon! {
#[derive(Clone, Debug)]
struct (i32 = 123);

impl () {
fn get(&self) -> i32 {
self.0
}
}
};
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
error: expected `Self` or `Trait for Self`
--> compile-errors/expect-self-anon.rs:6:14
--> compile-errors/stable/expect-self-anon.rs:6:14
|
6 | impl () {
| ^^
4 changes: 4 additions & 0 deletions lib/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,10 @@ repository.workspace = true
rust-version.workspace = true
edition.workspace = true

[features]
# Squelch lint: "autoimpl on trait that has a method with Self: Sized bound"
allow-trait-autoimpl-with-sized-fn-bound = []

[dependencies]
quote = "1.0"
proc-macro2 = "1.0"
Expand Down
8 changes: 7 additions & 1 deletion lib/src/autoimpl/for_deref.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@

use crate::generics::{GenericParam, Generics, TypeParamBound, WherePredicate};
use proc_macro2::{Span, TokenStream};
use proc_macro_error2::{emit_call_site_error, emit_error};
use proc_macro_error2::{emit_call_site_error, emit_call_site_warning, emit_error};
use quote::{quote, ToTokens, TokenStreamExt};
use syn::punctuated::Punctuated;
use syn::spanned::Spanned;
Expand Down Expand Up @@ -198,6 +198,12 @@ impl ForDeref {
"cannot autoimpl trait with Deref";
note = item.span() => "method has a bound on Self and no default implementation";
);
} else if !cfg!(feature = "allow-trait-autoimpl-with-sized-fn-bound") {
// TODO(rust proc_macro_lint): this should be a configurable lint
emit_call_site_warning!(
"autoimpl on trait that has a method with Self: Sized bound";
note = item.span() => "method impl uses default implementation, not deref";
);
}

continue;
Expand Down
10 changes: 6 additions & 4 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -240,10 +240,12 @@ pub fn impl_default(args: TokenStream, item: TokenStream) -> TokenStream {
/// Traits using generics and trait items using generics are, for the most part,
/// supported.
///
/// Items with a where clause with a type bound on `Self` are not supported
/// since the item is not guaranteed to exist on the definitive type.
/// Exception: methods with a default implementation (in this case the item is
/// skipped).
/// Items with a where clause with a type bound on `Self` cannot be implemented
/// via [`Deref`] since the item is not guaranteed to exist on the definitive
/// type. Such items with a default implementation may be implemented using this
/// that default implementation, though this results in a warning by default
/// (requires feature "nightly-diagnostics").
/// In other cases an error is reported.
///
/// An example:
/// ```
Expand Down
8 changes: 7 additions & 1 deletion tests/compile-errors.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,11 @@
#[test]
fn compile_errors() {
let t = trybuild::TestCases::new();
t.compile_fail("compile-errors/*.rs");
t.compile_fail("compile-errors/common/*.rs");

#[cfg(feature = "nightly-diagnostics")]
t.compile_fail("compile-errors/nightly/*.rs");

#[cfg(not(feature = "nightly-diagnostics"))]
t.compile_fail("compile-errors/stable/*.rs");
}
8 changes: 0 additions & 8 deletions tests/for_deref.rs
Original file line number Diff line number Diff line change
Expand Up @@ -67,13 +67,6 @@ where
V: Debug,
{
fn g(&self) -> V;

fn s<X>(&self, f: impl Fn(V) -> X) -> X
where
Self: Sized,
{
f(self.g())
}
}

#[test]
Expand All @@ -87,7 +80,6 @@ fn g() {

fn impls_g(g: impl G<i32>) {
assert_eq!(g.g(), 123);
assert!(g.s(|x| x == 123));
}

impls_g(S);
Expand Down
Loading