-
Notifications
You must be signed in to change notification settings - Fork 782
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
#[new]
doesn't play nice with cfg_attr
#780
Comments
According to gitter this is also an issue for Probably needs a thorough review of |
Version |
Thanks for the update. I'll try to give this some investigation soon. |
I can't reproduce the latest report; the example given above compiles fine with 0.10 if I make the It does not compile without |
I'm not sure how to resolve this. We can of course look into Is there a way at all to resolve |
I don't know if we can "resolve" I suggest we start building a list of examples in this thread. For each example, we can either:
My hope is that we can support "typical" use cases in this way. Or we're pleasantly surprised and find an elegant solution for everything! @c410-f3r it would be really helpful if you could start us off by providing the new examples which you reported today as not working with |
Can we, though? When the |
Oh, darn. But the other ones still present? |
maybe something like the cfg_expr crate could be used to evaluate |
Yes, that's the problem. I quickly checked with a serde EDIT: confirmed, it's the latter. @programmerjake as I understand, that's one half of the puzzle. (Already very helpful!) The other would be to get the current build config and use it evaluating these expressions. Does the proc macro have access to it? |
I think it might through env vars from cargo. Created thread on rust internals: https://internals.rust-lang.org/t/add-api-for-evaluating-cfg-conditions-from-proc-macros/12459?u=programmerjake |
@davidhewitt There are no errors with |
Is there a work around for this besides just manually implementing the getter/setter in a |
At the moment, I'm not aware of any "nice" workaround. I wonder if we can resolve this by changing |
…NOTE bug in pyo3 is blocking use of feature: PyO3/pyo3#780
The CFG can easily be acquired through environment variables. See this: https://doc.rust-lang.org/cargo/reference/environment-variables.html#environment-variables-cargo-sets-for-build-scripts
It should be possible to use those two to evaluate everything we might need. |
Looks like rust-lang/rust#83824 would resolve this on a sufficiently new rust (nightly atm). If anyone gets a chance to verify this, then this would become just a documentation ticket. |
It looks that way. Is there a way we can insert this attribute ourselves rather than having users use it? It would be nice to make this Just Work. |
I guess we could have #[pyclass]
struct Foo { } literally just adds #[cfg_eval]
#[pyclass(cfg_eval = false)]
struct Foo {} where ... but if we do that, we'll suprise people because the We'd also only be able to do the automatic cfg-eval on Rust versions which actually support it, which again makes it seem better that users should have to manually update to a new enough compiler version and explicitly add |
I worked around this by creating a proc macro that inserts #[cfg_attr(feature = "pyo3", macro_utils::pyo3_get_all)]
#[cfg_attr(feature = "pyo3", pyclass)]
#[derive(Serialize, Clone, Debug, Default)]
pub struct Foo{
pub id: u32,
pub name: Option<String>,
} That works out because all the (hundred+) fields are public anyway. Perhaps we can do something similar like |
That's a really interesting idea. Very much related to the idea in #1375.
|
The example @c410-f3r posted now works if you use #![feature(cfg_eval)]
#[cfg(feature = "with_pyo3")]
use pyo3::prelude::*;
#[cfg_attr(feature = "with_pyo3", pyclass)]
#[derive(Debug)]
pub struct Foo {
field: i32,
}
#[cfg_eval]
#[cfg_attr(feature = "with_pyo3", pymethods)]
impl Foo {
#[cfg_attr(feature = "with_pyo3", new)]
pub fn new(field: i32) -> Self {
Self { field }
}
pub fn get_field(&self) -> i32 {
self.field
}
}
#[cfg(feature = "with_pyo3")]
#[pymodule]
fn my_module(_py: Python, m: &PyModule) -> PyResult<()> {
m.add_class::<Foo>()?;
Ok(())
} from my_module import Foo
c = Foo(5)
print(c.get_field()) This currently requires Rust nightly (so |
Closing due to inactivity. Feel free to re-open this issue if desired. |
Would you mind making this macro a gist (assuming you still have it)? It seems like the nightly feature used above isn't going to be stabalized anytime soon, and I've ran into the same situation of annotating large structs with getters and don't care about using a hack as this is just a hobby project. |
@andyblarblar see https://github.com/mejrs/rs3cache/blob/master/rs3cache_macros/src/lib.rs Note that functionality like |
Hello, I ran into the same issue today. It seems that the solution using |
I think this issue needs to be reopened seeing as it doesn't look like
EDIT: never mind, the environment variables in question are not set when |
Happy to reopen this issue, however there is still no clear solution to this - and as the comment above points out, I'm not aware of any way that we could expand cfgs ourself. So I think we basically need someone willing to help upstream rust figure out the path (if it's not |
At least for this project, it seems that upstream is the only solution. You guys might want to reach out Vadim Petrochenkov (OP of rust-lang/rust#87221) to see if any help is needed. Otherwise, it is possible that this issue will be open for years to come. |
I am house-keeping my dashboard closing issues that will probably take time to resolve and are not on my radar any more. If desired, feel free to create another issue with any updated status from #2692. |
Any chance the |
|
Ah fantastic, thanks @davidhewitt! |
My current workaround is just to define the #[cfg_attr(feature = "python-bindings", pymethods)]
impl Parser {
#[cfg(feature = "python-bindings")]
#[new]
pub fn new() -> Parser {
Parser {
token_definitions: TokenDefinitions::new(),
}
}
pub fn parse_variable(&self, input: &str) -> Result<Variable, Error> {
let token_definition = &self.token_definitions.variable;
match (&token_definition.regex).find(input) {
Some(m) => {
let name = String::from(m.as_str());
Ok(Variable { name })
}
None => {
let message = format!("Not a {}.", token_definition.description);
Err(Error { message })
}
}
}
}
#[cfg(not(feature = "python-bindings"))]
impl Parser {
pub fn new() -> Parser {
Parser {
token_definitions: TokenDefinitions::new(),
}
}
} Just for reference. I might have missed a similar approach somewhere above. If the |
@zuckerruebe To avoid replicating the #[cfg_attr(feature = "python-bindings", pymethods)]
impl Parser {
#[cfg(feature = "python-bindings")]
#[new]
pub fn new_py() -> Parser {
Parser::new()
}
pub fn parse_variable(&self, input: &str) -> Result<Variable, Error> {
let token_definition = &self.token_definitions.variable;
match (&token_definition.regex).find(input) {
Some(m) => {
let name = String::from(m.as_str());
Ok(Variable { name })
}
None => {
let message = format!("Not a {}.", token_definition.description);
Err(Error { message })
}
}
}
}
impl Parser {
pub fn new() -> Parser {
Parser {
token_definitions: TokenDefinitions::new(),
}
}
} In my project, it made no difference to usability from any resource. Hope this helps! |
Compiles:
Doesn't compile with
Invalid type as custom self
andcannot find attribute 'new' in this scope
errors:The text was updated successfully, but these errors were encountered: