Skip to content

Commit

Permalink
Added new errors
Browse files Browse the repository at this point in the history
  • Loading branch information
TheLazyDutchman committed Dec 18, 2023
1 parent 0ecbf42 commit 875acc3
Show file tree
Hide file tree
Showing 6 changed files with 78 additions and 4 deletions.
12 changes: 10 additions & 2 deletions examples/partial.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ pub trait A {
}: User,
) {
}

fn not_sealed();
}

pub struct Email(String);
Expand All @@ -25,18 +27,24 @@ pub struct User {
pub struct Impl;

#[sealed]
impl A for Impl {}
impl A for Impl {
fn not_sealed() {}
}

#[sealed(partial)]
pub trait B {
#[seal(callable)]
fn no_default(email: Email);
fn no_default(_email: Email) {}

fn hello();
}

#[sealed]
impl B for Impl {
#[seal(callable)]
fn no_default(_email: Email) {}

fn hello() {}
}

#[sealed]
Expand Down
31 changes: 29 additions & 2 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -158,6 +158,9 @@ fn parse_sealed_trait(mut item_trait: syn::ItemTrait, args: TraitArguments) -> T

let mut wrappers = Vec::<syn::TraitItem>::new();

let mut all_implementable = true;
let mut none_implementable = true;

for item in &mut item_trait.items {
if let syn::TraitItem::Fn(item) = item {
let input = match parse_function_arguments(&item.attrs) {
Expand All @@ -170,6 +173,7 @@ fn parse_sealed_trait(mut item_trait: syn::ItemTrait, args: TraitArguments) -> T
};

let Some((attr, input)) = input else {
none_implementable = false;
continue;
};

Expand All @@ -189,8 +193,20 @@ fn parse_sealed_trait(mut item_trait: syn::ItemTrait, args: TraitArguments) -> T
.into_compile_error()
.into()
}
Ok(Some(wrapper)) => wrappers.push(wrapper.into()),
Ok(None) => {}
Ok(_) if args.partial && item.default.is_none() => {
return syn::Error::new(
attr.span(),
"This function is sealed from implementation, \
but it does not have a default implementation. \
This effectively seals the entire trait, \
which would be clearer to do by not having the trait seal be partial."
).into_compile_error().into()
}
Ok(Some(wrapper)) => {
all_implementable = false;
wrappers.push(wrapper.into())
},
Ok(None) => all_implementable = false,
Err(err) => {
return err
.into_compile_error()
Expand All @@ -200,6 +216,17 @@ fn parse_sealed_trait(mut item_trait: syn::ItemTrait, args: TraitArguments) -> T
}
}

if args.partial && all_implementable {
return syn::Error::new(item_trait.ident.span(), "This trait is partially sealed, \
however none of its methods are sealed, so it does nothing. \
Either seal a function or remove `partial` from the `sealed` attribute.").to_compile_error().into();
}

if args.partial && none_implementable {
return syn::Error::new(item_trait.ident.span(), "This trait is partially sealed, \
however none of its methods are implementable, so the `partial` argument does nothing.").into_compile_error().into();
}

item_trait
.items
.extend(wrappers);
Expand Down
14 changes: 14 additions & 0 deletions tests/fail/09-partial-argument.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
use sealed::sealed;

#[sealed(partial)]
pub trait A {
#[seal]
fn sealed() {}
}

#[sealed(partial)]
pub trait B {
fn not_sealed();
}

fn main() {}
11 changes: 11 additions & 0 deletions tests/fail/09-partial-argument.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
error: This trait is partially sealed, however none of its methods are implementable, so the `partial` argument does nothing.
--> tests/fail/09-partial-argument.rs:4:11
|
4 | pub trait A {
| ^

error: This trait is partially sealed, however none of its methods are sealed, so it does nothing. Either seal a function or remove `partial` from the `sealed` attribute.
--> tests/fail/09-partial-argument.rs:10:11
|
10 | pub trait B {
| ^
9 changes: 9 additions & 0 deletions tests/fail/10-partial-without-default.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
use sealed::sealed;

#[sealed(partial)]
pub trait A {
#[seal]
fn sealed();
}

fn main() {}
5 changes: 5 additions & 0 deletions tests/fail/10-partial-without-default.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
error: This function is sealed from implementation, but it does not have a default implementation. This effectively seals the entire trait, which would be clearer to do by not having the trait seal be partial.
--> tests/fail/10-partial-without-default.rs:5:2
|
5 | #[seal]
| ^^^^^^^

0 comments on commit 875acc3

Please sign in to comment.