Skip to content
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

Error message for use of a keyword in ident position could be tweaked #15358

Closed
sschepens opened this issue Jul 2, 2014 · 10 comments · Fixed by #16839
Closed

Error message for use of a keyword in ident position could be tweaked #15358

sschepens opened this issue Jul 2, 2014 · 10 comments · Fixed by #16839
Labels
A-diagnostics Area: Messages for errors, warnings, and lints

Comments

@sschepens
Copy link

In the example below, the error message could at least mention that type is keyword, or be changed more radically: #15358 (comment)

Previously:

Cannot declare a field 'type' on struct

Declaring for example the following struct:

struct Serie {
  metric: String,
  type: String
}

Yields the following error:

error: found `type` in ident position
type: String

Is this intended?

@huonw
Copy link
Member

huonw commented Jul 2, 2014

type is a keyword (used for creating type aliases type Foo = int; is the same as the Haskell use of type, and the same as typedef int Foo; in C). Currently, Rust has no contextual keywords, so a keyword can only be used for its intended purposes.

However, I think the error message could be improved to include a reference to "keyword", e.g. error: found keyword type in ident position (or radically changed to something like error: expected identifier but found keyword type``).

Repurposing the bug for this behaviour.

(Thanks for filing!)

@huonw huonw changed the title Cannot declare a field 'type' on struct Error message for use of a keyword in ident position could be tweaked Jul 2, 2014
@huonw
Copy link
Member

huonw commented Jul 2, 2014

(I believe the idiomatic way to use a keyword as an identifier is adding a trailing _, e.g. type_; @aturon may be able to confirm.)

@aturon
Copy link
Member

aturon commented Jul 2, 2014

@huonw Yes, that's the typical pattern.

Humorous aside: the main exception I've seen is krate rather than crate_.

@huonw
Copy link
Member

huonw commented Jul 3, 2014

Heh, maybe we should use tipe, strukt, trayt etc. instead. :P

@sschepens
Copy link
Author

The thing is, i'm using this structure for JSON de/serializing and i cant remove the type field, is there any way to make serialize crate drop the field 'type' in a field say '_type'?

@huonw
Copy link
Member

huonw commented Jul 3, 2014

Not yet, unfortunately. #14268 is related.

@sschepens
Copy link
Author

Well, that means rust is not an option for me now :(
Are there any plans to implement contextual keywords?

@huonw
Copy link
Member

huonw commented Jul 3, 2014

I misspoke: the situation is slightly more subtle than just "no". There's currently no way to get the automatic Encodable and Decodable instances (i.e. created via #[deriving]) to change the name of a field, but you can implement those traits "manually". I would recommend just editing the code that the derived instances creates. Specifically, if you have:

// foo.rs

#[deriving(Encodable, Decodable)]
struct Serie {
  metric: String,
  type_: String
}

rustc --pretty expanded foo.rs prints

struct Serie {
    metric: String,
    type_: String,
}
impl <__D: ::serialize::Decoder<__E>, __E> ::serialize::Decodable<__D, __E>
     for Serie {
    fn decode(__arg_0: &mut __D) -> ::std::result::Result<Serie, __E> {
        __arg_0.read_struct("Serie", 2u,
                            |_d|
                                ::std::result::Ok(Serie{metric:
                                                            match _d.read_struct_field("metric",
                                                                                       0u,
                                                                                       |_d|
                                                                                           ::serialize::Decodable::decode(_d))
                                                                {
                                                                Ok(__try_var)
                                                                => __try_var,
                                                                Err(__try_var)
                                                                =>
                                                                return Err(__try_var)
                                                            },
                                                        type_:
                                                            match _d.read_struct_field("type_",
                                                                                       1u,
                                                                                       |_d|
                                                                                           ::serialize::Decodable::decode(_d))
                                                                {
                                                                Ok(__try_var)
                                                                => __try_var,
                                                                Err(__try_var)
                                                                =>
                                                                return Err(__try_var)
                                                            },}))
    }
}
impl <__S: ::serialize::Encoder<__E>, __E> ::serialize::Encodable<__S, __E>
     for Serie {
    fn encode(&self, __arg_0: &mut __S) -> ::std::result::Result<(), __E> {
        match *self {
            Serie{metric: ref __self_0_0, type_: ref __self_0_1} =>
            __arg_0.emit_struct("Serie", 2u, |_e| {
                                match _e.emit_struct_field("metric", 0u,
                                                           |_e|
                                                               (*__self_0_0).encode(_e))
                                    {
                                    Ok(__try_var) => __try_var,
                                    Err(__try_var) => return Err(__try_var)
                                };
                                return _e.emit_struct_field("type_", 1u,
                                                            |_e|
                                                                (*__self_0_1).encode(_e));
                            })
        }
    }
}

The "type_" strings can be changed to "type" in these manual implementations. (It's ugly but it should allow you to continue experimenting with Rust. :) )

@sschepens
Copy link
Author

@huonw Awesome! will try that as soon as i can, thanks a lot!

@kumaraguru1735
Copy link

I use different approch, but it works in best way

#[derive(Debug, serde::Deserialize,)]
struct Data {
    url: String,
    preview: String,
    udp_url: String,
    #[serde(rename = "type")]
    type_: String,
    video_resolution: String,
    video_bitrate: u32,
    audio_bitrate: u32,
    audio_samplerate: u32,
    audio_channels: u32,
    audio_codec: String,
    video_codec: String,
    video_fps: u32,
}

here

    #[serde(rename = "type")]
    type_: String,

type_ will convert to type while Deserialize the struct

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-diagnostics Area: Messages for errors, warnings, and lints
Projects
None yet
Development

Successfully merging a pull request may close this issue.

4 participants