-
Notifications
You must be signed in to change notification settings - Fork 35
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Implement unsafe trait support (continued) #155
Changes from all commits
570e95f
c86992d
8ec6589
c9534a0
0e5464c
866b4da
f562ada
72062fc
e03258c
4d615b1
53d0e43
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,3 +1,5 @@ | ||
use std::fmt; | ||
|
||
use formality_core::{set, Set, Upcast}; | ||
use formality_macros::term; | ||
use formality_types::grammar::{ | ||
|
@@ -104,8 +106,10 @@ impl Decls { | |
|
||
/// An "impl decl" indicates that a trait is implemented for a given set of types. | ||
/// One "impl decl" is created for each impl in the Rust source. | ||
#[term(impl $binder)] | ||
#[term($?safety impl $binder)] | ||
pub struct ImplDecl { | ||
/// The safety this impl declares, which needs to match the implemented trait's safety. | ||
pub safety: Safety, | ||
/// The binder covers the generic variables from the impl | ||
pub binder: Binder<ImplDeclBoundData>, | ||
} | ||
|
@@ -122,8 +126,11 @@ pub struct ImplDeclBoundData { | |
|
||
/// A declaration that some trait will *not* be implemented for a type; derived from negative impls | ||
/// like `impl !Foo for Bar`. | ||
#[term(impl $binder)] | ||
#[term($?safety impl $binder)] | ||
pub struct NegImplDecl { | ||
/// The safety this negative impl declares | ||
pub safety: Safety, | ||
|
||
/// Binder comes the generics on the impl | ||
pub binder: Binder<NegImplDeclBoundData>, | ||
} | ||
|
@@ -135,15 +142,37 @@ pub struct NegImplDeclBoundData { | |
pub where_clause: Wcs, | ||
} | ||
|
||
/// Mark a trait or trait impl as `unsafe`. | ||
#[term] | ||
#[customize(debug)] | ||
#[derive(Default)] | ||
pub enum Safety { | ||
#[default] | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I didn't know you could do this, nifty. |
||
Safe, | ||
Unsafe, | ||
} | ||
|
||
impl fmt::Debug for Safety { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Isn't this the default behavior that There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Oh I didn't know this, or test that it would. I'll try, and open a PR to clean this up. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I've fixed this in #156 |
||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { | ||
match self { | ||
Safety::Safe => write!(f, "safe"), | ||
Safety::Unsafe => write!(f, "unsafe"), | ||
} | ||
} | ||
} | ||
|
||
/// A "trait declaration" declares a trait that exists, its generics, and its where-clauses. | ||
/// It doesn't capture the trait items, which will be transformed into other sorts of rules. | ||
/// | ||
/// In Rust syntax, it covers the `trait Foo: Bar` part of the declaration, but not what appears in the `{...}`. | ||
#[term(trait $id $binder)] | ||
#[term($?safety trait $id $binder)] | ||
pub struct TraitDecl { | ||
/// The name of the trait | ||
pub id: TraitId, | ||
|
||
/// Whether the trait is `unsafe` or not | ||
pub safety: Safety, | ||
|
||
/// The binder here captures the generics of the trait; it always begins with a `Self` type. | ||
pub binder: Binder<TraitDeclBoundData>, | ||
} | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,3 +1,3 @@ | ||
[toolchain] | ||
channel = "nightly-2023-10-08" | ||
components = [ "rustc-dev", "llvm-tools" ] | ||
components = ["rustc-dev", "llvm-tools", "rustfmt"] |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
Error: check_neg_trait_impl(unsafe impl ! Foo for u32 {}) | ||
|
||
Caused by: | ||
negative impls cannot be unsafe |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
[ | ||
crate baguette { | ||
trait Foo {} | ||
unsafe impl !Foo for u32 {} | ||
} | ||
] |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
//@check-pass | ||
[ | ||
crate baguette { | ||
safe trait Foo {} | ||
safe impl Foo for u32 {} | ||
} | ||
] |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
Error: check_trait_impl(unsafe impl Foo for u32 { }) | ||
|
||
Caused by: | ||
implementing the trait `Foo` is not unsafe |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
[ | ||
crate baguette { | ||
trait Foo {} | ||
unsafe impl Foo for u32 {} | ||
} | ||
] |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
//@check-pass | ||
[ | ||
crate baguette { | ||
unsafe trait Foo {} | ||
impl !Foo for u32 {} | ||
} | ||
] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
...and I like this version of the fn better