Skip to content

Add support for attributes for struct fields #3880

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

Merged
merged 4 commits into from
Apr 9, 2020
Merged

Conversation

bnjjj
Copy link
Contributor

@bnjjj bnjjj commented Apr 7, 2020

Hello I try to solve this example:

struct MyStruct {
    my_val: usize,
    #[cfg(feature = "foo")]
    bar: bool,
}
impl MyStruct {
    #[cfg(feature = "foo")]
    pub(crate) fn new(my_val: usize, bar: bool) -> Self {
        Self { my_val, bar }
    }
    #[cfg(not(feature = "foo"))]
    pub(crate) fn new(my_val: usize, _bar: bool) -> Self {
        Self { my_val }
    }
}

Here is a draft PR to try to solve this issue. In fact for now when i have this kind of example, rust-analyzer tells me that my second Self {} miss the bar field. Which is a bug.

I have some difficulties to add this features. Here in my draft I share my work about adding attributes support on struct field data. But I'm stuck when I have to fetch attributes from parent expressions. I don't really know how to do that. For the first iteration I just want to solve my issue without solving on all different expressions. And then after I will try to implement that on different kind of expression. I think I have to fetch my FunctionId and then I will be able to find attributes with myFunction.attrs() But I don't know if it's the right way.

@matklad (or anyone else) if you can help me it would be great :D

},
);
}
StructKind::Tuple
}
ast::StructKind::Record(fl) => {
for fd in fl.fields() {
let attrs = Attrs::new(&fd, &Hygiene::new(db.upcast(), ast.file_id));
// Need verification about parent cfg_options and current with current attributes
// If it is we are in a case where the cfg is not enabled then we don't have to add this field to check
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, this is what we ideally should do here, but, in the current model, we just have one global set of active cfgs, so there won't be parent in the first place if it is disabled.

let lit_fields: FxHashSet<_> = fields
.iter()
.filter_map(|f| {
// TODO: check if cfg_is_enabled with .attrs ?
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

SO, if the cfg is disabled, there shouldn't be fields here in the first place, beucase they weren't alloced when we created corresponding VariantData

@@ -319,3 +319,32 @@ fn no_such_field_diagnostics() {
"###
);
}

#[test]
fn no_such_field_with_feature_flag_diagnostics() {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍

@matklad
Copy link
Member

matklad commented Apr 8, 2020

Yeah, this generally moves in the right direction, except that, I think, you don't actually need to fetch attributes from the parent. There's just a global set of attributes enabled per-crate which you can use.

Long-term, we should do something smarter here, like adding "deactivated" items, such that completion works even in cfged-out code, but that's not on the horizon yet.

@bnjjj
Copy link
Contributor Author

bnjjj commented Apr 8, 2020

Updated, the test now pass. Let me know what do you want to change :)

@bnjjj bnjjj marked this pull request as ready for review April 8, 2020 16:14
@bnjjj bnjjj changed the title [need mentor] Add support for attributes for struct fields Add support for attributes for struct fields Apr 9, 2020
@bnjjj bnjjj requested a review from matklad April 9, 2020 07:45
@matklad
Copy link
Member

matklad commented Apr 9, 2020

Yup, lgtm, although I think the orginal bit about attrs on structs was also good, and can be added back!

Specifically, I think the following test would be good to add

struct S {
  #[cfg(feature = "foo")] foo: u32,
  #[cfg(not(feature = "foo"))] bar: u32,
}

impl S {
  #[cfg(feature = "foo")]
  fn new(foo: u32) -> S { S { foo } }
  #[cfg(not(feature = "foo"))] 
  fn new(bar u32) -> S { S { bar } }
}

but

bors r+

as this is indeed more correct than what we had before

@matklad
Copy link
Member

matklad commented Apr 9, 2020

Ah, seems like Ci is failing though?

@bnjjj
Copy link
Contributor Author

bnjjj commented Apr 9, 2020

Ok will check :)

bors bot added a commit that referenced this pull request Apr 9, 2020
3880: Add support for attributes for struct fields r=matklad a=bnjjj

Hello I try to solve this example:
```rust
struct MyStruct {
    my_val: usize,
    #[cfg(feature = "foo")]
    bar: bool,
}
impl MyStruct {
    #[cfg(feature = "foo")]
    pub(crate) fn new(my_val: usize, bar: bool) -> Self {
        Self { my_val, bar }
    }
    #[cfg(not(feature = "foo"))]
    pub(crate) fn new(my_val: usize, _bar: bool) -> Self {
        Self { my_val }
    }
}
```

Here is a draft PR to try to solve this issue. In fact for now when i have this kind of example, rust-analyzer tells me that my second Self {} miss the bar field. Which is a bug.

I have some difficulties to add this features. Here in my draft I share my work about adding attributes support on struct field data. But I'm stuck when I have to fetch attributes from parent expressions. I don't really know how to do that. For the first iteration I just want to solve my issue without solving on all different expressions. And then after I will try to implement that on different kind of expression. I think I have to fetch my FunctionId and then I will be able to find attributes with myFunction.attrs() But I don't know if it's the right way.

@matklad (or anyone else) if you can help me it would be great :D 

Co-authored-by: Benjamin Coenen <[email protected]>
@bors
Copy link
Contributor

bors bot commented Apr 9, 2020

Build failed

@bnjjj
Copy link
Contributor Author

bnjjj commented Apr 9, 2020

Yup, lgtm, although I think the orginal bit about attrs on structs was also good, and can be added back!

Specifically, I think the following test would be good to add

struct S {
  #[cfg(feature = "foo")] foo: u32,
  #[cfg(not(feature = "foo"))] bar: u32,
}

impl S {
  #[cfg(feature = "foo")]
  fn new(foo: u32) -> S { S { foo } }
  #[cfg(not(feature = "foo"))] 
  fn new(bar u32) -> S { S { bar } }
}

but

bors r+

as this is indeed more correct than what we had before

For sure I will add this support but if you don't care I would like to do it in another PR. In fact as I only access to an ast: &InFile<ast::StructKind> in lower_struct I have to add a parameter which I think should be the StructId to be able to fetch the moduleId and then get the crateData for cfg_options.

BTW I fix the failing test, it was a trailing whitespace in my test case.

So next step, I will open a new PR to support also your example you can count on me :)

@matklad
Copy link
Member

matklad commented Apr 9, 2020

bors r+

@bors
Copy link
Contributor

bors bot commented Apr 9, 2020

@bors bors bot merged commit 412eda7 into rust-lang:master Apr 9, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants