<commit_before>#![cfg(feature = "extra-traits")]

extern crate syn;
extern crate proc_macro2;

use syn::*;
use proc_macro2::{TokenKind, OpKind, Delimiter, Literal};
use proc_macro2::Delimiter::{Parenthesis, Brace};

fn op(c: char) -> TokenTree {
    TokenTree(proc_macro2::TokenTree {
        span: Default::default(),
        kind: TokenKind::Op(c, OpKind::Alone),
    })
}

fn lit<T: Into<Literal>>(t: T) -> TokenTree {
    TokenTree(proc_macro2::TokenTree {
        span: Default::default(),
        kind: TokenKind::Literal(t.into()),
    })
}

fn word(sym: &str) -> TokenTree {
    TokenTree(proc_macro2::TokenTree {
        span: Default::default(),
        kind: TokenKind::Word(sym.into()),
    })
}

fn delimited(delim: Delimiter, tokens: Vec<TokenTree>) -> TokenTree {
    TokenTree(proc_macro2::TokenTree {
        span: Default::default(),
        kind: TokenKind::Sequence(delim, tokens.into_iter().map(|t| t.0).collect()),
    })
}

#[test]
fn test_unit() {
    let raw = "struct Unit;";

    let expected = DeriveInput {
        ident: "Unit".into(),
        vis: Visibility::Inherited(VisInherited {}),
        attrs: Vec::new(),
        generics: Generics::default(),
        body: Body::Struct(BodyStruct {
            semi_token: Some(Default::default()),
            struct_token: Default::default(),
            data: VariantData::Unit,
        }),
    };

    assert_eq!(expected, raw.parse().unwrap());
}

#[test]
fn test_struct() {
    let raw = "
        #[derive(Debug, Clone)]
        pub struct Item {
            pub ident: Ident,
            pub attrs: Vec<Attribute>
        }
    ";

    let expected = DeriveInput {
        ident: "Item".into(),
        vis: Visibility::Public(VisPublic {
            pub_token: Default::default(),
        }),
        attrs: vec![Attribute {
            bracket_token: Default::default(),
            pound_token: Default::default(),
            style: AttrStyle::Outer,
            path: "derive".into(),
            tts: vec![
                delimited(Parenthesis, vec![
                    word("Debug"),
                    op(','),
                    word("Clone"),
                ]),
            ],
            is_sugared_doc: false,
        }],
        generics: Generics::default(),
        body: Body::Struct(BodyStruct {
            semi_token: None,
            struct_token: Default::default(),
            data: VariantData::Struct(vec![
                Field {
                    ident: Some("ident".into()),
                    colon_token: Some(Default::default()),
                    vis: Visibility::Public(VisPublic {
                        pub_token: Default::default(),
                    }),
                    attrs: Vec::new(),
                    ty: TyPath {
                        qself: None,
                        path: "Ident".into(),
                    }.into(),
                },
                Field {
                    ident: Some("attrs".into()),
                    colon_token: Some(Default::default()),
                    vis: Visibility::Public(VisPublic {
                        pub_token: Default::default(),
                    }),
                    attrs: Vec::new(),
                    ty: TyPath {
                        qself: None,
                        path: Path {
                            leading_colon: None,
                            segments: vec![
                                PathSegment {
                                    ident: "Vec".into(),
                                    parameters: PathParameters::AngleBracketed(
                                        AngleBracketedParameterData {
                                            turbofish: None,
                                            lt_token: Default::default(),
                                            lifetimes: Default::default(),
                                            types: vec![Ty::from(TyPath {
                                                qself: None,
                                                path: "Attribute".into(),
                                            })].into(),
                                            bindings: Default::default(),
                                            gt_token: Default::default(),
                                        },
                                    ),
                                }
                            ].into(),
                        },
                    }.into(),
                },
            ].into(), Default::default()),
        }),
    };

    let actual = raw.parse().unwrap();

    assert_eq!(expected, actual);

    let expected_meta_item: MetaItem = MetaItemList {
        ident: "derive".into(),
        paren_token: Default::default(),
        nested: vec![
            NestedMetaItem::MetaItem(MetaItem::Word("Debug".into())),
            NestedMetaItem::MetaItem(MetaItem::Word("Clone".into())),
        ].into(),
    }.into();

    assert_eq!(expected_meta_item, actual.attrs[0].meta_item().unwrap());
}

#[test]
#[cfg(feature = "full")]
fn test_enum() {
    let raw = r#"
        /// See the std::result module documentation for details.
        #[must_use]
        pub enum Result<T, E> {
            Ok(T),
            Err(E),
            Surprise = 0isize,

            // Smuggling data into a proc_macro_derive,
            // in the style of https://github.com/dtolnay/proc-macro-hack
            ProcMacroHack = (0, "data").0
        }
    "#;

    let expected = DeriveInput {
        ident: "Result".into(),
        vis: Visibility::Public(VisPublic {
            pub_token: Default::default(),
        }),
        attrs: vec![
            Attribute {
                bracket_token: Default::default(),
                pound_token: Default::default(),
                style: AttrStyle::Outer,
                path: "doc".into(),
                tts: vec![
                    op('='),
                    lit(Literal::doccomment("/// See the std::result module documentation for details.")),
                ],
                is_sugared_doc: true,
            },
            Attribute {
                bracket_token: Default::default(),
                pound_token: Default::default(),
                style: AttrStyle::Outer,
                path: "must_use".into(),
                tts: vec![],
                is_sugared_doc: false,
            },
        ],
        generics: Generics {
            lifetimes: Default::default(),
            lt_token: Some(Default::default()),
            gt_token: Some(Default::default()),
            ty_params: vec![
                TyParam {
                    attrs: Vec::new(),
                    ident: "T".into(),
                    bounds: Default::default(),
                    default: None,
                    colon_token: None,
                    eq_token: None,
                },
                TyParam {
                    attrs: Vec::new(),
                    ident: "E".into(),
                    bounds: Default::default(),
                    colon_token: None,
                    eq_token: None,
                    default: None,
                },
            ].into(),
            where_clause: WhereClause::default(),
        },
        body: Body::Enum(BodyEnum {
            variants: vec![
                Variant {
                    ident: "Ok".into(),
                    attrs: Vec::new(),
                    eq_token: None,
                    data: VariantData::Tuple(vec![
                        Field {
                            colon_token: None,
                            ident: None,
                            vis: Visibility::Inherited(VisInherited {}),
                            attrs: Vec::new(),
                            ty: TyPath { qself: None, path: "T".into() }.into(),
                        },
                    ].into(), Default::default()),
                    discriminant: None,
                },
                Variant {
                    ident: "Err".into(),
                    attrs: Vec::new(),
                    eq_token: None,
                    data: VariantData::Tuple(vec![
                        Field {
                            ident: None,
                            colon_token: None,
                            vis: Visibility::Inherited(VisInherited {}),
                            attrs: Vec::new(),
                            ty: TyPath { qself: None, path: "E".into() }.into(),
                        },
                    ].into(), Default::default()),
                    discriminant: None,
                },
                Variant {
                    ident: "Surprise".into(),
                    attrs: Vec::new(),
                    data: VariantData::Unit,
                    eq_token: Some(Default::default()),
                    discriminant: Some(ConstExpr::Lit(Lit {
                        value: LitKind::Other(0isize.into()),
                        span: Default::default(),
                    })),
                },
                Variant {
                    ident: "ProcMacroHack".into(),
                    attrs: Vec::new(),
                    data: VariantData::Unit,
                    eq_token: Some(Default::default()),
                    discriminant: Some(ConstExpr::Other(Expr {
                        node: ExprTupField {
                            expr: Box::new(Expr {
                                node: ExprTup {
                                    lone_comma: None,
                                    paren_token: Default::default(),
                                    args: vec![
                                        Expr {
                                            node: ExprKind::Lit(Lit {
                                                value: LitKind::Other(Literal::integer("0")),
                                                span: Default::default(),
                                            }),
                                            attrs: Vec::new(),
                                        },
                                        Expr {
                                            node: ExprKind::Lit(Lit {
                                                value: LitKind::Other("data".into()),
                                                span: Default::default(),
                                            }),
                                            attrs: Vec::new(),
                                        },
                                    ].into(),
                                }.into(),
                                attrs: Vec::new(),
                            }),
                            dot_token: Default::default(),
                            field: Lit {
                                value: LitKind::Other(Literal::integer("0")),
                                span: Default::default(),
                            },
                        }.into(),
                        attrs: Vec::new(),
                    })),
                },
            ].into(),
            brace_token: Default::default(),
            enum_token: Default::default(),
        }),
    };

    let actual = raw.parse().unwrap();

    assert_eq!(expected, actual);

    let expected_meta_items = vec![
        MetaNameValue {
            ident: "doc".into(),
            eq_token: Default::default(),
            lit: Lit {
                value: LitKind::Other(Literal::doccomment("/// See the std::result module documentation for details.")),
                span: Default::default(),
            },
        }.into(),
        MetaItem::Word("must_use".into()),
    ];

    let actual_meta_items: Vec<_> = actual.attrs.into_iter().map(|attr| attr.meta_item().unwrap()).collect();

    assert_eq!(expected_meta_items, actual_meta_items);
}

#[test]
fn test_attr_with_path() {
    let raw =r#"
        #[::attr_args::identity
            fn main() { assert_eq!(foo(), "Hello, world!"); }]
        struct Dummy;
    "#;

    let expected = DeriveInput {
        ident: "Dummy".into(),
        vis: Visibility::Inherited(VisInherited {}),
        attrs: vec![Attribute {
            bracket_token: Default::default(),
            pound_token: Default::default(),
            style: AttrStyle::Outer,
            path: Path {
                leading_colon: Some(Default::default()),
                segments: vec![
                    PathSegment::from("attr_args"),
                    PathSegment::from("identity"),
                ].into(),
            },
            tts: vec![
                word("fn"),
                word("main"),
                delimited(Parenthesis, vec![]),
                delimited(Brace, vec![
                    word("assert_eq"),
                    op('!'),
                    delimited(Parenthesis, vec![
                        word("foo"),
                        delimited(Parenthesis, vec![]),
                        op(','),
                        lit("Hello, world!"),
                    ]),
                    op(';'),
                ]),
            ],
            is_sugared_doc: false,
        }],
        generics: Generics::default(),
        body: Body::Struct(BodyStruct {
            data: VariantData::Unit,
            semi_token: Some(Default::default()),
            struct_token: Default::default(),
        }),
    };

    let actual = raw.parse().unwrap();

    assert_eq!(expected, actual);

    assert!(actual.attrs[0].meta_item().is_none());
}

#[test]
fn test_attr_with_non_mod_style_path() {
    let raw =r#"
        #[inert <T>]
        struct S;
    "#;

    let expected = DeriveInput {
        ident: "S".into(),
        vis: Visibility::Inherited(VisInherited {}),
        attrs: vec![Attribute {
            bracket_token: Default::default(),
            pound_token: Default::default(),
            style: AttrStyle::Outer,
            path: Path {
                leading_colon: None,
                segments: vec![
                    PathSegment::from("inert"),
                ].into(),
            },
            tts: vec![
                op('<'),
                word("T"),
                op('>'),
            ],
            is_sugared_doc: false,
        }],
        generics: Generics::default(),
        body: Body::Struct(BodyStruct {
            data: VariantData::Unit,
            semi_token: Some(Default::default()),
            struct_token: Default::default(),
        }),
    };

    let actual = raw.parse().unwrap();

    assert_eq!(expected, actual);

    assert!(actual.attrs[0].meta_item().is_none());
}

#[test]
fn test_attr_with_mod_style_path_with_self() {
    let raw =r#"
        #[foo::self]
        struct S;
    "#;

    let expected = DeriveInput {
        ident: "S".into(),
        vis: Visibility::Inherited(VisInherited {}),
        attrs: vec![Attribute {
            bracket_token: Default::default(),
            pound_token: Default::default(),
            style: AttrStyle::Outer,
            path: Path {
                leading_colon: None,
                segments: vec![
                    PathSegment::from("foo"),
                    PathSegment::from("self"),
                ].into(),
            },
            tts: vec![],
            is_sugared_doc: false,
        }],
        generics: Generics::default(),
        body: Body::Struct(BodyStruct {
            data: VariantData::Unit,
            semi_token: Some(Default::default()),
            struct_token: Default::default(),
        }),
    };

    let actual = raw.parse().unwrap();

    assert_eq!(expected, actual);

    assert!(actual.attrs[0].meta_item().is_none());
}

#[test]
fn test_pub_restricted() {
    // Taken from tests/rust/src/test/ui/resolve/auxiliary/privacy-struct-ctor.rs
    let raw =r#"
        pub(in m) struct Z(pub(in m::n) u8);
    "#;

    let expected = DeriveInput {
        ident: "Z".into(),
        vis: Visibility::Restricted(VisRestricted {
            path: Box::new("m".into()),
            in_token: Some(Default::default()),
            paren_token: Default::default(),
            pub_token: Default::default(),
        }),
        attrs: vec![],
        generics: Generics::default(),
        body: Body::Struct(BodyStruct {
            data: VariantData::Tuple(vec![Field {
                ident: None,
                vis: Visibility::Restricted(VisRestricted {
                    path: Box::new(Path {
                        leading_colon: None,
                        segments: vec![
                            PathSegment::from("m"),
                            PathSegment::from("n"),
                        ].into(),
                    }),
                    in_token: Some(Default::default()),
                    paren_token: Default::default(),
                    pub_token: Default::default(),
                }),
                colon_token: None,
                attrs: vec![],
                ty: TyPath {
                    qself: None,
                    path: "u8".into(),
                }.into(),
            }].into(), Default::default()),
            semi_token: Some(Default::default()),
            struct_token: Default::default(),
        }),
    };

    let actual = raw.parse().unwrap();

    assert_eq!(expected, actual);
}

#[test]
fn test_pub_restricted_crate() {
    let raw =r#"
        pub(crate) struct S;
    "#;

    let expected = DeriveInput {
        ident: "S".into(),
        vis: Visibility::Crate(VisCrate {
            pub_token: Default::default(),
            crate_token: Default::default(),
            paren_token: Default::default(),
        }),
        attrs: vec![],
        generics: Generics::default(),
        body: Body::Struct(BodyStruct {
            semi_token: Some(Default::default()),
            struct_token: Default::default(),
            data: VariantData::Unit,
        }),
    };

    let actual = raw.parse().unwrap();

    assert_eq!(expected, actual);
}

#[test]
fn test_pub_restricted_super() {
    let raw =r#"
        pub(super) struct S;
    "#;

    let expected = DeriveInput {
        ident: "S".into(),
        vis: Visibility::Restricted(VisRestricted {
            path: Box::new("super".into()),
            in_token: None,
            paren_token: Default::default(),
            pub_token: Default::default(),
        }),
        attrs: vec![],
        generics: Generics::default(),
        body: Body::Struct(BodyStruct {
            semi_token: Some(Default::default()),
            struct_token: Default::default(),
            data: VariantData::Unit,
        }),
    };

    let actual = raw.parse().unwrap();

    assert_eq!(expected, actual);
}

#[test]
fn test_pub_restricted_in_super() {
    let raw =r#"
        pub(in super) struct S;
    "#;

    let expected = DeriveInput {
        ident: "S".into(),
        vis: Visibility::Restricted(VisRestricted {
            path: Box::new("super".into()),
            in_token: Some(Default::default()),
            paren_token: Default::default(),
            pub_token: Default::default(),
        }),
        attrs: vec![],
        generics: Generics::default(),
        body: Body::Struct(BodyStruct {
            semi_token: Some(Default::default()),
            struct_token: Default::default(),
            data: VariantData::Unit,
        }),
    };

    let actual = raw.parse().unwrap();

    assert_eq!(expected, actual);
}
<commit_msg>Update test_derive_input due to constexpr changes<commit_after>#![cfg(feature = "extra-traits")]

extern crate syn;
extern crate proc_macro2;

use syn::*;
use proc_macro2::{TokenKind, OpKind, Delimiter, Literal};
use proc_macro2::Delimiter::{Parenthesis, Brace};

fn op(c: char) -> TokenTree {
    TokenTree(proc_macro2::TokenTree {
        span: Default::default(),
        kind: TokenKind::Op(c, OpKind::Alone),
    })
}

fn lit<T: Into<Literal>>(t: T) -> TokenTree {
    TokenTree(proc_macro2::TokenTree {
        span: Default::default(),
        kind: TokenKind::Literal(t.into()),
    })
}

fn word(sym: &str) -> TokenTree {
    TokenTree(proc_macro2::TokenTree {
        span: Default::default(),
        kind: TokenKind::Word(sym.into()),
    })
}

fn delimited(delim: Delimiter, tokens: Vec<TokenTree>) -> TokenTree {
    TokenTree(proc_macro2::TokenTree {
        span: Default::default(),
        kind: TokenKind::Sequence(delim, tokens.into_iter().map(|t| t.0).collect()),
    })
}

#[test]
fn test_unit() {
    let raw = "struct Unit;";

    let expected = DeriveInput {
        ident: "Unit".into(),
        vis: Visibility::Inherited(VisInherited {}),
        attrs: Vec::new(),
        generics: Generics::default(),
        body: Body::Struct(BodyStruct {
            semi_token: Some(Default::default()),
            struct_token: Default::default(),
            data: VariantData::Unit,
        }),
    };

    assert_eq!(expected, raw.parse().unwrap());
}

#[test]
fn test_struct() {
    let raw = "
        #[derive(Debug, Clone)]
        pub struct Item {
            pub ident: Ident,
            pub attrs: Vec<Attribute>
        }
    ";

    let expected = DeriveInput {
        ident: "Item".into(),
        vis: Visibility::Public(VisPublic {
            pub_token: Default::default(),
        }),
        attrs: vec![Attribute {
            bracket_token: Default::default(),
            pound_token: Default::default(),
            style: AttrStyle::Outer,
            path: "derive".into(),
            tts: vec![
                delimited(Parenthesis, vec![
                    word("Debug"),
                    op(','),
                    word("Clone"),
                ]),
            ],
            is_sugared_doc: false,
        }],
        generics: Generics::default(),
        body: Body::Struct(BodyStruct {
            semi_token: None,
            struct_token: Default::default(),
            data: VariantData::Struct(vec![
                Field {
                    ident: Some("ident".into()),
                    colon_token: Some(Default::default()),
                    vis: Visibility::Public(VisPublic {
                        pub_token: Default::default(),
                    }),
                    attrs: Vec::new(),
                    ty: TyPath {
                        qself: None,
                        path: "Ident".into(),
                    }.into(),
                },
                Field {
                    ident: Some("attrs".into()),
                    colon_token: Some(Default::default()),
                    vis: Visibility::Public(VisPublic {
                        pub_token: Default::default(),
                    }),
                    attrs: Vec::new(),
                    ty: TyPath {
                        qself: None,
                        path: Path {
                            leading_colon: None,
                            segments: vec![
                                PathSegment {
                                    ident: "Vec".into(),
                                    parameters: PathParameters::AngleBracketed(
                                        AngleBracketedParameterData {
                                            turbofish: None,
                                            lt_token: Default::default(),
                                            lifetimes: Default::default(),
                                            types: vec![Ty::from(TyPath {
                                                qself: None,
                                                path: "Attribute".into(),
                                            })].into(),
                                            bindings: Default::default(),
                                            gt_token: Default::default(),
                                        },
                                    ),
                                }
                            ].into(),
                        },
                    }.into(),
                },
            ].into(), Default::default()),
        }),
    };

    let actual = raw.parse().unwrap();

    assert_eq!(expected, actual);

    let expected_meta_item: MetaItem = MetaItemList {
        ident: "derive".into(),
        paren_token: Default::default(),
        nested: vec![
            NestedMetaItem::MetaItem(MetaItem::Word("Debug".into())),
            NestedMetaItem::MetaItem(MetaItem::Word("Clone".into())),
        ].into(),
    }.into();

    assert_eq!(expected_meta_item, actual.attrs[0].meta_item().unwrap());
}

#[test]
#[cfg(feature = "full")]
fn test_enum() {
    let raw = r#"
        /// See the std::result module documentation for details.
        #[must_use]
        pub enum Result<T, E> {
            Ok(T),
            Err(E),
            Surprise = 0isize,

            // Smuggling data into a proc_macro_derive,
            // in the style of https://github.com/dtolnay/proc-macro-hack
            ProcMacroHack = (0, "data").0
        }
    "#;

    let expected = DeriveInput {
        ident: "Result".into(),
        vis: Visibility::Public(VisPublic {
            pub_token: Default::default(),
        }),
        attrs: vec![
            Attribute {
                bracket_token: Default::default(),
                pound_token: Default::default(),
                style: AttrStyle::Outer,
                path: "doc".into(),
                tts: vec![
                    op('='),
                    lit(Literal::doccomment("/// See the std::result module documentation for details.")),
                ],
                is_sugared_doc: true,
            },
            Attribute {
                bracket_token: Default::default(),
                pound_token: Default::default(),
                style: AttrStyle::Outer,
                path: "must_use".into(),
                tts: vec![],
                is_sugared_doc: false,
            },
        ],
        generics: Generics {
            lifetimes: Default::default(),
            lt_token: Some(Default::default()),
            gt_token: Some(Default::default()),
            ty_params: vec![
                TyParam {
                    attrs: Vec::new(),
                    ident: "T".into(),
                    bounds: Default::default(),
                    default: None,
                    colon_token: None,
                    eq_token: None,
                },
                TyParam {
                    attrs: Vec::new(),
                    ident: "E".into(),
                    bounds: Default::default(),
                    colon_token: None,
                    eq_token: None,
                    default: None,
                },
            ].into(),
            where_clause: WhereClause::default(),
        },
        body: Body::Enum(BodyEnum {
            variants: vec![
                Variant {
                    ident: "Ok".into(),
                    attrs: Vec::new(),
                    eq_token: None,
                    data: VariantData::Tuple(vec![
                        Field {
                            colon_token: None,
                            ident: None,
                            vis: Visibility::Inherited(VisInherited {}),
                            attrs: Vec::new(),
                            ty: TyPath { qself: None, path: "T".into() }.into(),
                        },
                    ].into(), Default::default()),
                    discriminant: None,
                },
                Variant {
                    ident: "Err".into(),
                    attrs: Vec::new(),
                    eq_token: None,
                    data: VariantData::Tuple(vec![
                        Field {
                            ident: None,
                            colon_token: None,
                            vis: Visibility::Inherited(VisInherited {}),
                            attrs: Vec::new(),
                            ty: TyPath { qself: None, path: "E".into() }.into(),
                        },
                    ].into(), Default::default()),
                    discriminant: None,
                },
                Variant {
                    ident: "Surprise".into(),
                    attrs: Vec::new(),
                    data: VariantData::Unit,
                    eq_token: Some(Default::default()),
                    discriminant: Some(Expr{
                        node: Lit {
                            value: LitKind::Other(0isize.into()),
                            span: Default::default(),
                        }.into(),
                        attrs: Vec::new(),
                    }),
                },
                Variant {
                    ident: "ProcMacroHack".into(),
                    attrs: Vec::new(),
                    data: VariantData::Unit,
                    eq_token: Some(Default::default()),
                    discriminant: Some(Expr {
                        node: ExprTupField {
                            expr: Box::new(Expr {
                                node: ExprTup {
                                    lone_comma: None,
                                    paren_token: Default::default(),
                                    args: vec![
                                        Expr {
                                            node: ExprKind::Lit(Lit {
                                                value: LitKind::Other(Literal::integer("0")),
                                                span: Default::default(),
                                            }),
                                            attrs: Vec::new(),
                                        },
                                        Expr {
                                            node: ExprKind::Lit(Lit {
                                                value: LitKind::Other("data".into()),
                                                span: Default::default(),
                                            }),
                                            attrs: Vec::new(),
                                        },
                                    ].into(),
                                }.into(),
                                attrs: Vec::new(),
                            }),
                            dot_token: Default::default(),
                            field: Lit {
                                value: LitKind::Other(Literal::integer("0")),
                                span: Default::default(),
                            },
                        }.into(),
                        attrs: Vec::new(),
                    }),
                },
            ].into(),
            brace_token: Default::default(),
            enum_token: Default::default(),
        }),
    };

    let actual = raw.parse().unwrap();

    assert_eq!(expected, actual);

    let expected_meta_items = vec![
        MetaNameValue {
            ident: "doc".into(),
            eq_token: Default::default(),
            lit: Lit {
                value: LitKind::Other(Literal::doccomment("/// See the std::result module documentation for details.")),
                span: Default::default(),
            },
        }.into(),
        MetaItem::Word("must_use".into()),
    ];

    let actual_meta_items: Vec<_> = actual.attrs.into_iter().map(|attr| attr.meta_item().unwrap()).collect();

    assert_eq!(expected_meta_items, actual_meta_items);
}

#[test]
fn test_attr_with_path() {
    let raw =r#"
        #[::attr_args::identity
            fn main() { assert_eq!(foo(), "Hello, world!"); }]
        struct Dummy;
    "#;

    let expected = DeriveInput {
        ident: "Dummy".into(),
        vis: Visibility::Inherited(VisInherited {}),
        attrs: vec![Attribute {
            bracket_token: Default::default(),
            pound_token: Default::default(),
            style: AttrStyle::Outer,
            path: Path {
                leading_colon: Some(Default::default()),
                segments: vec![
                    PathSegment::from("attr_args"),
                    PathSegment::from("identity"),
                ].into(),
            },
            tts: vec![
                word("fn"),
                word("main"),
                delimited(Parenthesis, vec![]),
                delimited(Brace, vec![
                    word("assert_eq"),
                    op('!'),
                    delimited(Parenthesis, vec![
                        word("foo"),
                        delimited(Parenthesis, vec![]),
                        op(','),
                        lit("Hello, world!"),
                    ]),
                    op(';'),
                ]),
            ],
            is_sugared_doc: false,
        }],
        generics: Generics::default(),
        body: Body::Struct(BodyStruct {
            data: VariantData::Unit,
            semi_token: Some(Default::default()),
            struct_token: Default::default(),
        }),
    };

    let actual = raw.parse().unwrap();

    assert_eq!(expected, actual);

    assert!(actual.attrs[0].meta_item().is_none());
}

#[test]
fn test_attr_with_non_mod_style_path() {
    let raw =r#"
        #[inert <T>]
        struct S;
    "#;

    let expected = DeriveInput {
        ident: "S".into(),
        vis: Visibility::Inherited(VisInherited {}),
        attrs: vec![Attribute {
            bracket_token: Default::default(),
            pound_token: Default::default(),
            style: AttrStyle::Outer,
            path: Path {
                leading_colon: None,
                segments: vec![
                    PathSegment::from("inert"),
                ].into(),
            },
            tts: vec![
                op('<'),
                word("T"),
                op('>'),
            ],
            is_sugared_doc: false,
        }],
        generics: Generics::default(),
        body: Body::Struct(BodyStruct {
            data: VariantData::Unit,
            semi_token: Some(Default::default()),
            struct_token: Default::default(),
        }),
    };

    let actual = raw.parse().unwrap();

    assert_eq!(expected, actual);

    assert!(actual.attrs[0].meta_item().is_none());
}

#[test]
fn test_attr_with_mod_style_path_with_self() {
    let raw =r#"
        #[foo::self]
        struct S;
    "#;

    let expected = DeriveInput {
        ident: "S".into(),
        vis: Visibility::Inherited(VisInherited {}),
        attrs: vec![Attribute {
            bracket_token: Default::default(),
            pound_token: Default::default(),
            style: AttrStyle::Outer,
            path: Path {
                leading_colon: None,
                segments: vec![
                    PathSegment::from("foo"),
                    PathSegment::from("self"),
                ].into(),
            },
            tts: vec![],
            is_sugared_doc: false,
        }],
        generics: Generics::default(),
        body: Body::Struct(BodyStruct {
            data: VariantData::Unit,
            semi_token: Some(Default::default()),
            struct_token: Default::default(),
        }),
    };

    let actual = raw.parse().unwrap();

    assert_eq!(expected, actual);

    assert!(actual.attrs[0].meta_item().is_none());
}

#[test]
fn test_pub_restricted() {
    // Taken from tests/rust/src/test/ui/resolve/auxiliary/privacy-struct-ctor.rs
    let raw =r#"
        pub(in m) struct Z(pub(in m::n) u8);
    "#;

    let expected = DeriveInput {
        ident: "Z".into(),
        vis: Visibility::Restricted(VisRestricted {
            path: Box::new("m".into()),
            in_token: Some(Default::default()),
            paren_token: Default::default(),
            pub_token: Default::default(),
        }),
        attrs: vec![],
        generics: Generics::default(),
        body: Body::Struct(BodyStruct {
            data: VariantData::Tuple(vec![Field {
                ident: None,
                vis: Visibility::Restricted(VisRestricted {
                    path: Box::new(Path {
                        leading_colon: None,
                        segments: vec![
                            PathSegment::from("m"),
                            PathSegment::from("n"),
                        ].into(),
                    }),
                    in_token: Some(Default::default()),
                    paren_token: Default::default(),
                    pub_token: Default::default(),
                }),
                colon_token: None,
                attrs: vec![],
                ty: TyPath {
                    qself: None,
                    path: "u8".into(),
                }.into(),
            }].into(), Default::default()),
            semi_token: Some(Default::default()),
            struct_token: Default::default(),
        }),
    };

    let actual = raw.parse().unwrap();

    assert_eq!(expected, actual);
}

#[test]
fn test_pub_restricted_crate() {
    let raw =r#"
        pub(crate) struct S;
    "#;

    let expected = DeriveInput {
        ident: "S".into(),
        vis: Visibility::Crate(VisCrate {
            pub_token: Default::default(),
            crate_token: Default::default(),
            paren_token: Default::default(),
        }),
        attrs: vec![],
        generics: Generics::default(),
        body: Body::Struct(BodyStruct {
            semi_token: Some(Default::default()),
            struct_token: Default::default(),
            data: VariantData::Unit,
        }),
    };

    let actual = raw.parse().unwrap();

    assert_eq!(expected, actual);
}

#[test]
fn test_pub_restricted_super() {
    let raw =r#"
        pub(super) struct S;
    "#;

    let expected = DeriveInput {
        ident: "S".into(),
        vis: Visibility::Restricted(VisRestricted {
            path: Box::new("super".into()),
            in_token: None,
            paren_token: Default::default(),
            pub_token: Default::default(),
        }),
        attrs: vec![],
        generics: Generics::default(),
        body: Body::Struct(BodyStruct {
            semi_token: Some(Default::default()),
            struct_token: Default::default(),
            data: VariantData::Unit,
        }),
    };

    let actual = raw.parse().unwrap();

    assert_eq!(expected, actual);
}

#[test]
fn test_pub_restricted_in_super() {
    let raw =r#"
        pub(in super) struct S;
    "#;

    let expected = DeriveInput {
        ident: "S".into(),
        vis: Visibility::Restricted(VisRestricted {
            path: Box::new("super".into()),
            in_token: Some(Default::default()),
            paren_token: Default::default(),
            pub_token: Default::default(),
        }),
        attrs: vec![],
        generics: Generics::default(),
        body: Body::Struct(BodyStruct {
            semi_token: Some(Default::default()),
            struct_token: Default::default(),
            data: VariantData::Unit,
        }),
    };

    let actual = raw.parse().unwrap();

    assert_eq!(expected, actual);
}
<|endoftext|>


<commit_before>//! Madgwick's orientation filter
//!
//! This demo runs Madgwick's orientation filter and logs the orientation of the board as
//! quaternions via the ITM. The data is encoded in binary format and logged as COBS frame. The
//! binary format is as follows:
//!
//! - `w`: `f32`, LE (Little Endian), 4 bytes
//! - `x`: `f32`, LE, 4 bytes
//! - `y`: `f32`, LE, 4 bytes
//! - `z`: `f32`, LE, 4 bytes
//!
//! where the quaternion is the tuple `(w, x, y, z)`
//!
//! The suggested way to receive this data is to connect the F3 SWO pin to a UART to USB converter
//! and then to read out the associated device file using `itmdump`. Make sure you configure the
//! serial device before calling `itmdump`. The commands to run are:
//!
//! ``` console
//! $ stty -F /dev/ttyUSB0 raw 2000000 -echo
//!
//! $ itmdump -f /dev/ttyUSB0 > data.txt
//! ```
//!
//! You can pipe the quaternions through the `viz` program (shipped with this crate) to get real
//! time [visualization]. The command to run is:
//!
//! [visualization]: https://mobile.twitter.com/japaricious/status/962770003325005824
//!
//! ``` console
//! $ itmdump -f /dev/ttyUSB0 | viz
//! ```
// #![deny(unsafe_code)]
#![deny(warnings)]
#![no_main]
#![no_std]

extern crate panic_semihosting;

use core::{f32::consts::PI, ptr};

use aligned::Aligned;
use byteorder::{ByteOrder, LE};
use cast::{f32, i32};
use cortex_m::itm;
use cortex_m_rt::entry;
use f3::{
    hal::{i2c::I2c, prelude::*, spi::Spi, stm32f30x, timer::Timer},
    l3gd20::{self, Odr},
    lsm303dlhc::{AccelOdr, MagOdr},
    L3gd20, Lsm303dlhc,
};
use madgwick::{F32x3, Marg};
use nb::block;

// Number of samples to use for gyroscope calibration
const NSAMPLES: i32 = 256;

// Magnetometer calibration parameters
// NOTE you need to use the right parameters for *your* magnetometer
// You can use the `log-sensors` example to calibrate your magnetometer. The producer is explained
// in https://github.com/kriswiner/MPU6050/wiki/Simple-and-Effective-Magnetometer-Calibration
const M_BIAS_X: f32 = -183.;
const M_SCALE_X: f32 = 435.;

const M_BIAS_Y: f32 = -172.;
const M_SCALE_Y: f32 = 507.;

const M_BIAS_Z: f32 = -136.;
const M_SCALE_Z: f32 = 632.;

// Sensitivities of the accelerometer and gyroscope, respectively
const K_G: f32 = 2. / (1 << 15) as f32; // LSB -> g
const K_AR: f32 = 8.75e-3 * PI / 180.; // LSB -> rad/s

// Madgwick filter parameters
const SAMPLE_FREQ: u32 = 220;
const BETA: f32 = 1e-3;

#[entry]
fn main() -> ! {
    let mut cp = cortex_m::Peripherals::take().unwrap();
    let dp = stm32f30x::Peripherals::take().unwrap();

    let mut flash = dp.FLASH.constrain();
    let mut rcc = dp.RCC.constrain();

    let clocks = rcc
        .cfgr
        .sysclk(64.mhz())
        .pclk1(32.mhz())
        .freeze(&mut flash.acr);

    // enable ITM
    // TODO this should be some high level API in the cortex-m crate
    unsafe {
        // enable TPIU and ITM
        cp.DCB.demcr.modify(|r| r | (1 << 24));

        // prescaler
        let swo_freq = 2_000_000;
        cp.TPIU.acpr.write((clocks.sysclk().0 / swo_freq) - 1);

        // SWO NRZ
        cp.TPIU.sppr.write(2);

        cp.TPIU.ffcr.modify(|r| r & !(1 << 1));

        // STM32 specific: enable tracing in the DBGMCU_CR register
        const DBGMCU_CR: *mut u32 = 0xe0042004 as *mut u32;
        let r = ptr::read_volatile(DBGMCU_CR);
        ptr::write_volatile(DBGMCU_CR, r | (1 << 5));

        // unlock the ITM
        cp.ITM.lar.write(0xC5ACCE55);

        cp.ITM.tcr.write(
            (0b000001 << 16) | // TraceBusID
            (1 << 3) | // enable SWO output
            (1 << 0), // enable the ITM
        );

        // enable stimulus port 0
        cp.ITM.ter[0].write(1);
    }

    let mut gpioa = dp.GPIOA.split(&mut rcc.ahb);
    let mut gpiob = dp.GPIOB.split(&mut rcc.ahb);
    let mut gpioe = dp.GPIOE.split(&mut rcc.ahb);

    let mut nss = gpioe
        .pe3
        .into_push_pull_output(&mut gpioe.moder, &mut gpioe.otyper);
    nss.set_high();
    let mut led = gpioe
        .pe9
        .into_push_pull_output(&mut gpioe.moder, &mut gpioe.otyper);

    let sck = gpioa.pa5.into_af5(&mut gpioa.moder, &mut gpioa.afrl);
    let miso = gpioa.pa6.into_af5(&mut gpioa.moder, &mut gpioa.afrl);
    let mosi = gpioa.pa7.into_af5(&mut gpioa.moder, &mut gpioa.afrl);

    let spi = Spi::spi1(
        dp.SPI1,
        (sck, miso, mosi),
        l3gd20::MODE,
        1.mhz(),
        clocks,
        &mut rcc.apb2,
    );

    let mut l3gd20 = L3gd20::new(spi, nss).unwrap();

    l3gd20.set_odr(Odr::Hz380).unwrap();

    let scl = gpiob.pb6.into_af4(&mut gpiob.moder, &mut gpiob.afrl);
    let sda = gpiob.pb7.into_af4(&mut gpiob.moder, &mut gpiob.afrl);

    let i2c = I2c::i2c1(dp.I2C1, (scl, sda), 400.khz(), clocks, &mut rcc.apb1);

    let mut lsm303dlhc = Lsm303dlhc::new(i2c).unwrap();

    lsm303dlhc.accel_odr(AccelOdr::Hz400).unwrap();
    lsm303dlhc.mag_odr(MagOdr::Hz220).unwrap();

    let mut timer = Timer::tim2(dp.TIM2, 380.hz(), clocks, &mut rcc.apb1);

    // Calibrate the gyroscope
    let mut ar_bias_x = 0;
    let mut ar_bias_y = 0;
    let mut ar_bias_z = 0;
    for _ in 0..NSAMPLES {
        block!(timer.wait()).unwrap();

        let ar = l3gd20.gyro().unwrap();

        ar_bias_x += i32(ar.x);
        ar_bias_y += i32(ar.y);
        ar_bias_z += i32(ar.z);
    }
    let ar_bias_x = (ar_bias_x / NSAMPLES) as i16;
    let ar_bias_y = (ar_bias_y / NSAMPLES) as i16;
    let ar_bias_z = (ar_bias_z / NSAMPLES) as i16;

    // Turn on the LED after calibrating the gyroscope
    led.set_high();

    let mut marg = Marg::new(BETA, 1. / f32(SAMPLE_FREQ));
    let mut timer = Timer::tim2(timer.free(), SAMPLE_FREQ.hz(), clocks, &mut rcc.apb1);

    let mut tx_buf: Aligned<u32, [u8; 18]> = Aligned([0; 18]);
    loop {
        block!(timer.wait()).unwrap();

        let m = lsm303dlhc.mag().unwrap();
        let ar = l3gd20.gyro().unwrap();
        let g = lsm303dlhc.accel().unwrap();

        let m_x = (f32(m.x) - M_BIAS_X) / M_SCALE_X;
        let m_y = (f32(m.y) - M_BIAS_Y) / M_SCALE_Y;
        let m_z = (f32(m.z) - M_BIAS_Z) / M_SCALE_Z;

        // Fix the X Y Z components of the magnetometer so they match the gyro axes
        let m = F32x3 {
            x: m_y,
            y: -m_x,
            z: m_z,
        };

        let ar_x = f32(ar.x - ar_bias_x) * K_AR;
        let ar_y = f32(ar.y - ar_bias_y) * K_AR;
        let ar_z = f32(ar.z - ar_bias_z) * K_AR;
        let ar = F32x3 {
            x: ar_x,
            y: ar_y,
            z: ar_z,
        };

        // Fix the X Y Z components of the accelerometer so they match the gyro axes
        let g_x = f32(g.x) * K_G;
        let g_y = f32(g.y) * K_G;
        let g_z = f32(g.z) * K_G;
        let g = F32x3 {
            x: g_y,
            y: -g_x,
            z: g_z,
        };

        // Run the filter
        let quat = marg.update(m, ar, g);

        // Serialize the quaternion
        let mut start = 0;
        let mut buf = [0; 16];
        LE::write_f32(&mut buf[start..start + 4], quat.0);
        start += 4;
        LE::write_f32(&mut buf[start..start + 4], quat.1);
        start += 4;
        LE::write_f32(&mut buf[start..start + 4], quat.2);
        start += 4;
        LE::write_f32(&mut buf[start..start + 4], quat.3);
        // start += 4;

        // Log data
        cobs::encode(&buf, &mut tx_buf.array);

        itm::write_aligned(&mut cp.ITM.stim[0], &tx_buf);
    }
}
<commit_msg>"fix" madgwick example<commit_after>//! Madgwick's orientation filter
//!
//! This demo runs Madgwick's orientation filter and logs the orientation of the board as
//! quaternions via the ITM. The data is encoded in binary format and logged as COBS frame. The
//! binary format is as follows:
//!
//! - `w`: `f32`, LE (Little Endian), 4 bytes
//! - `x`: `f32`, LE, 4 bytes
//! - `y`: `f32`, LE, 4 bytes
//! - `z`: `f32`, LE, 4 bytes
//!
//! where the quaternion is the tuple `(w, x, y, z)`
//!
//! The suggested way to receive this data is to connect the F3 SWO pin to a UART to USB converter
//! and then to read out the associated device file using `itmdump`. Make sure you configure the
//! serial device before calling `itmdump`. The commands to run are:
//!
//! ``` console
//! $ stty -F /dev/ttyUSB0 raw 2000000 -echo
//!
//! $ itmdump -f /dev/ttyUSB0 > data.txt
//! ```
//!
//! You can pipe the quaternions through the `viz` program (shipped with this crate) to get real
//! time [visualization]. The command to run is:
//!
//! [visualization]: https://mobile.twitter.com/japaricious/status/962770003325005824
//!
//! ``` console
//! $ itmdump -f /dev/ttyUSB0 | viz
//! ```
// #![deny(unsafe_code)]
#![deny(warnings)]
#![no_main]
#![no_std]

extern crate panic_semihosting;

use core::{f32::consts::PI, ptr};

use aligned::Aligned;
use byteorder::{ByteOrder, LE};
use cast::{f32, i32};
use cortex_m::itm;
use cortex_m_rt::entry;
use f3::{
    hal::{i2c::I2c, prelude::*, spi::Spi, stm32f30x, timer::Timer},
    l3gd20::{self, Odr},
    lsm303dlhc::{AccelOdr, MagOdr},
    L3gd20, Lsm303dlhc,
};
use madgwick::{F32x3, Marg};
use nb::block;

// Number of samples to use for gyroscope calibration
const NSAMPLES: i32 = 256;

// Magnetometer calibration parameters
// NOTE you need to use the right parameters for *your* magnetometer
// You can use the `log-sensors` example to calibrate your magnetometer. The producer is explained
// in https://github.com/kriswiner/MPU6050/wiki/Simple-and-Effective-Magnetometer-Calibration
const M_BIAS_X: f32 = -183.;
const M_SCALE_X: f32 = 435.;

const M_BIAS_Y: f32 = -172.;
const M_SCALE_Y: f32 = 507.;

const M_BIAS_Z: f32 = -136.;
const M_SCALE_Z: f32 = 632.;

// Sensitivities of the accelerometer and gyroscope, respectively
const K_G: f32 = 2. / (1 << 15) as f32; // LSB -> g
const K_AR: f32 = 8.75e-3 * PI / 180.; // LSB -> rad/s

// Madgwick filter parameters
const SAMPLE_FREQ: u32 = 220;
const BETA: f32 = 1e-3;

#[entry]
fn main() -> ! {
    let mut cp = cortex_m::Peripherals::take().unwrap();
    let dp = stm32f30x::Peripherals::take().unwrap();

    let mut flash = dp.FLASH.constrain();
    let mut rcc = dp.RCC.constrain();

    let clocks = rcc
        .cfgr
        .sysclk(64.mhz())
        .pclk1(32.mhz())
        .freeze(&mut flash.acr);

    // enable ITM
    // TODO this should be some high level API in the cortex-m crate
    unsafe {
        // enable TPIU and ITM
        cp.DCB.demcr.modify(|r| r | (1 << 24));

        // prescaler
        let swo_freq = 2_000_000;
        cp.TPIU.acpr.write((clocks.sysclk().0 / swo_freq) - 1);

        // SWO NRZ
        cp.TPIU.sppr.write(2);

        cp.TPIU.ffcr.modify(|r| r & !(1 << 1));

        // STM32 specific: enable tracing in the DBGMCU_CR register
        const DBGMCU_CR: *mut u32 = 0xe0042004 as *mut u32;
        let r = ptr::read_volatile(DBGMCU_CR);
        ptr::write_volatile(DBGMCU_CR, r | (1 << 5));

        // unlock the ITM
        cp.ITM.lar.write(0xC5ACCE55);

        cp.ITM.tcr.write(
            (0b000001 << 16) | // TraceBusID
            (1 << 3) | // enable SWO output
            (1 << 0), // enable the ITM
        );

        // enable stimulus port 0
        cp.ITM.ter[0].write(1);
    }

    let mut gpioa = dp.GPIOA.split(&mut rcc.ahb);
    let mut gpiob = dp.GPIOB.split(&mut rcc.ahb);
    let mut gpioe = dp.GPIOE.split(&mut rcc.ahb);

    let mut nss = gpioe
        .pe3
        .into_push_pull_output(&mut gpioe.moder, &mut gpioe.otyper);
    nss.set_high();
    let mut led = gpioe
        .pe9
        .into_push_pull_output(&mut gpioe.moder, &mut gpioe.otyper);

    let sck = gpioa.pa5.into_af5(&mut gpioa.moder, &mut gpioa.afrl);
    let miso = gpioa.pa6.into_af5(&mut gpioa.moder, &mut gpioa.afrl);
    let mosi = gpioa.pa7.into_af5(&mut gpioa.moder, &mut gpioa.afrl);

    let spi = Spi::spi1(
        dp.SPI1,
        (sck, miso, mosi),
        l3gd20::MODE,
        1.mhz(),
        clocks,
        &mut rcc.apb2,
    );

    let mut l3gd20 = L3gd20::new(spi, nss).unwrap();

    l3gd20.set_odr(Odr::Hz380).unwrap();

    let scl = gpiob.pb6.into_af4(&mut gpiob.moder, &mut gpiob.afrl);
    let sda = gpiob.pb7.into_af4(&mut gpiob.moder, &mut gpiob.afrl);

    let i2c = I2c::i2c1(dp.I2C1, (scl, sda), 400.khz(), clocks, &mut rcc.apb1);

    let mut lsm303dlhc = Lsm303dlhc::new(i2c).unwrap();

    lsm303dlhc.accel_odr(AccelOdr::Hz400).unwrap();
    lsm303dlhc.mag_odr(MagOdr::Hz220).unwrap();

    let mut timer = Timer::tim2(dp.TIM2, 380.hz(), clocks, &mut rcc.apb1);

    // Calibrate the gyroscope
    let mut ar_bias_x = 0;
    let mut ar_bias_y = 0;
    let mut ar_bias_z = 0;
    for _ in 0..NSAMPLES {
        block!(timer.wait()).unwrap();

        let ar = l3gd20.all().unwrap().gyro;

        ar_bias_x += i32(ar.x);
        ar_bias_y += i32(ar.y);
        ar_bias_z += i32(ar.z);
    }
    let ar_bias_x = (ar_bias_x / NSAMPLES) as i16;
    let ar_bias_y = (ar_bias_y / NSAMPLES) as i16;
    let ar_bias_z = (ar_bias_z / NSAMPLES) as i16;

    // Turn on the LED after calibrating the gyroscope
    led.set_high();

    let mut marg = Marg::new(BETA, 1. / f32(SAMPLE_FREQ));
    let mut timer = Timer::tim2(timer.free(), SAMPLE_FREQ.hz(), clocks, &mut rcc.apb1);

    let mut tx_buf: Aligned<u32, [u8; 18]> = Aligned([0; 18]);
    loop {
        block!(timer.wait()).unwrap();

        let m = lsm303dlhc.mag().unwrap();
        let ar = l3gd20.all().unwrap().gyro;
        let g = lsm303dlhc.accel().unwrap();

        let m_x = (f32(m.x) - M_BIAS_X) / M_SCALE_X;
        let m_y = (f32(m.y) - M_BIAS_Y) / M_SCALE_Y;
        let m_z = (f32(m.z) - M_BIAS_Z) / M_SCALE_Z;

        // Fix the X Y Z components of the magnetometer so they match the gyro axes
        let m = F32x3 {
            x: m_y,
            y: -m_x,
            z: m_z,
        };

        let ar_x = f32(ar.x - ar_bias_x) * K_AR;
        let ar_y = f32(ar.y - ar_bias_y) * K_AR;
        let ar_z = f32(ar.z - ar_bias_z) * K_AR;
        let ar = F32x3 {
            x: ar_x,
            y: ar_y,
            z: ar_z,
        };

        // Fix the X Y Z components of the accelerometer so they match the gyro axes
        let g_x = f32(g.x) * K_G;
        let g_y = f32(g.y) * K_G;
        let g_z = f32(g.z) * K_G;
        let g = F32x3 {
            x: g_y,
            y: -g_x,
            z: g_z,
        };

        // Run the filter
        let quat = marg.update(m, ar, g);

        // Serialize the quaternion
        let mut start = 0;
        let mut buf = [0; 16];
        LE::write_f32(&mut buf[start..start + 4], quat.0);
        start += 4;
        LE::write_f32(&mut buf[start..start + 4], quat.1);
        start += 4;
        LE::write_f32(&mut buf[start..start + 4], quat.2);
        start += 4;
        LE::write_f32(&mut buf[start..start + 4], quat.3);
        // start += 4;

        // Log data
        cobs::encode(&buf, &mut tx_buf.array);

        itm::write_aligned(&mut cp.ITM.stim[0], &tx_buf);
    }
}
<|endoftext|>


<commit_before>use std::u64;

/// A `BufStream` size hint
///
/// The default implementation returns:
///
/// * 0 for `available`
/// * 0 for `lower`
/// * `None` for `upper`.
#[derive(Debug, Default, Clone)]
pub struct SizeHint {
    lower: u64,
    upper: Option<u64>,
}

impl SizeHint {
    /// Returns a new `SizeHint` with default values
    pub fn new() -> SizeHint {
        SizeHint::default()
    }

    /// Returns the lower bound of data that the `BufStream` will yield before
    /// completing.
    pub fn lower(&self) -> u64 {
        self.lower
    }

    /// Set the value of the `lower` hint.
    ///
    /// # Panics
    ///
    /// The function panics if `value` is less than `upper`.
    pub fn set_lower(&mut self, value: u64) {
        assert!(value <= self.upper.unwrap_or(u64::MAX));
        self.lower = value;
    }

    /// Returns the upper bound of data the `BufStream` will yield before
    /// completing, or `None` if the value is unknown.
    pub fn upper(&self) -> Option<u64> {
        self.upper
    }

    /// Set the value of the `upper` hint value.
    ///
    /// # Panics
    ///
    /// This function panics if `value` is less than `lower`.
    pub fn set_upper(&mut self, value: u64) {
        // There is no need to check `available` as that is guaranteed to be
        // less than or equal to `lower`.
        assert!(value >= self.lower, "`value` is less than than `lower`");

        self.upper = Some(value);
    }
}
<commit_msg>Corrected doc for tokio_buf SizeHint (#1003)<commit_after>use std::u64;

/// A `BufStream` size hint
///
/// The default implementation returns:
///
/// * 0 for `available`
/// * 0 for `lower`
/// * `None` for `upper`.
#[derive(Debug, Default, Clone)]
pub struct SizeHint {
    lower: u64,
    upper: Option<u64>,
}

impl SizeHint {
    /// Returns a new `SizeHint` with default values
    pub fn new() -> SizeHint {
        SizeHint::default()
    }

    /// Returns the lower bound of data that the `BufStream` will yield before
    /// completing.
    pub fn lower(&self) -> u64 {
        self.lower
    }

    /// Set the value of the `lower` hint.
    ///
    /// # Panics
    ///
    /// The function panics if `value` is greater than `upper`.
    pub fn set_lower(&mut self, value: u64) {
        assert!(value <= self.upper.unwrap_or(u64::MAX));
        self.lower = value;
    }

    /// Returns the upper bound of data the `BufStream` will yield before
    /// completing, or `None` if the value is unknown.
    pub fn upper(&self) -> Option<u64> {
        self.upper
    }

    /// Set the value of the `upper` hint value.
    ///
    /// # Panics
    ///
    /// This function panics if `value` is less than `lower`.
    pub fn set_upper(&mut self, value: u64) {
        // There is no need to check `available` as that is guaranteed to be
        // less than or equal to `lower`.
        assert!(value >= self.lower, "`value` is less than than `lower`");

        self.upper = Some(value);
    }
}
<|endoftext|>


<commit_before>#![cfg_attr(not(feature = "sync"), allow(dead_code, unreachable_pub))]

//! A multi-producer, single-consumer queue for sending values across
//! asynchronous tasks.
//!
//! Similar to `std`, channel creation provides [`Receiver`] and [`Sender`]
//! handles. [`Receiver`] implements `Stream` and allows a task to read values
//! out of the channel. If there is no message to read, the current task will be
//! notified when a new value is sent. If the channel is at capacity, the send
//! is rejected and the task will be notified when additional capacity is
//! available. In other words, the channel provides backpressure.
//!
//! This module provides two variants of the channel: A bounded and an unbounded
//! variant. The bounded variant has a limit on the number of messages that the
//! channel can store, and if this limit is reached, trying to send another
//! message will sleep until a message is received from the channel. An unbounded
//! channel has an infinite capacity, so the `send` method never does any kind of
//! sleeping. This makes the [`UnboundedSender`] usable from both synchronous and
//! asynchronous code.
//!
//! # Disconnection
//!
//! When all [`Sender`] handles have been dropped, it is no longer
//! possible to send values into the channel. This is considered the termination
//! event of the stream. As such, `Receiver::poll` returns `Ok(Ready(None))`.
//!
//! If the [`Receiver`] handle is dropped, then messages can no longer
//! be read out of the channel. In this case, all further attempts to send will
//! result in an error.
//!
//! # Clean Shutdown
//!
//! When the [`Receiver`] is dropped, it is possible for unprocessed messages to
//! remain in the channel. Instead, it is usually desirable to perform a "clean"
//! shutdown. To do this, the receiver first calls `close`, which will prevent
//! any further messages to be sent into the channel. Then, the receiver
//! consumes the channel to completion, at which point the receiver can be
//! dropped.
//!
//! # Communicating between sync and async code
//!
//! When you want to communicate between synchronous and asynchronous code, there
//! are two situations to consider:
//!
//! **Bounded channel**: If you need a bounded channel, you should use a bounded
//! Tokio `mpsc` channel for both directions of communication. To call the async
//! [`send`][bounded-send] or [`recv`][bounded-recv] methods in sync code, you
//! will need to use [`Handle::block_on`], which allow you to execute an async
//! method in synchronous code. This is necessary because a bounded channel may
//! need to wait for additional capacity to become available.
//!
//! **Unbounded channel**: You should use the kind of channel that matches where
//! the receiver is. So for sending a message _from async to sync_, you should
//! use [the standard library unbounded channel][std-unbounded] or
//! [crossbeam][crossbeam-unbounded].  Similarly, for sending a message _from sync
//! to async_, you should use an unbounded Tokio `mpsc` channel.
//!
//! [`Sender`]: crate::sync::mpsc::Sender
//! [`Receiver`]: crate::sync::mpsc::Receiver
//! [bounded-send]: crate::sync::mpsc::Sender::send()
//! [bounded-recv]: crate::sync::mpsc::Receiver::recv()
//! [`UnboundedSender`]: crate::sync::mpsc::UnboundedSender
//! [`Handle::block_on`]: crate::runtime::Handle::block_on()
//! [std-unbounded]: std::sync::mpsc::channel
//! [crossbeam-unbounded]: https://docs.rs/crossbeam/*/crossbeam/channel/fn.unbounded.html

pub(super) mod block;

mod bounded;
pub use self::bounded::{channel, Receiver, Sender};

mod chan;

pub(super) mod list;

mod unbounded;
pub use self::unbounded::{unbounded_channel, UnboundedReceiver, UnboundedSender};

pub mod error;

/// The number of values a block can contain.
///
/// This value must be a power of 2. It also must be smaller than the number of
/// bits in `usize`.
#[cfg(all(target_pointer_width = "64", not(loom)))]
const BLOCK_CAP: usize = 32;

#[cfg(all(not(target_pointer_width = "64"), not(loom)))]
const BLOCK_CAP: usize = 16;

#[cfg(loom)]
const BLOCK_CAP: usize = 2;
<commit_msg>sync: channel doc grammar change (#2624)<commit_after>#![cfg_attr(not(feature = "sync"), allow(dead_code, unreachable_pub))]

//! A multi-producer, single-consumer queue for sending values across
//! asynchronous tasks.
//!
//! Similar to `std`, channel creation provides [`Receiver`] and [`Sender`]
//! handles. [`Receiver`] implements `Stream` and allows a task to read values
//! out of the channel. If there is no message to read, the current task will be
//! notified when a new value is sent. If the channel is at capacity, the send
//! is rejected and the task will be notified when additional capacity is
//! available. In other words, the channel provides backpressure.
//!
//! This module provides two variants of the channel: bounded and unbounded. The
//! bounded variant has a limit on the number of messages that the channel can
//! store, and if this limit is reached, trying to send another message will
//! wait until a message is received from the channel. An unbounded channel has
//! an infinite capacity, so the `send` method never does any kind of sleeping.
//! This makes the [`UnboundedSender`] usable from both synchronous and
//! asynchronous code.
//!
//! # Disconnection
//!
//! When all [`Sender`] handles have been dropped, it is no longer
//! possible to send values into the channel. This is considered the termination
//! event of the stream. As such, `Receiver::poll` returns `Ok(Ready(None))`.
//!
//! If the [`Receiver`] handle is dropped, then messages can no longer
//! be read out of the channel. In this case, all further attempts to send will
//! result in an error.
//!
//! # Clean Shutdown
//!
//! When the [`Receiver`] is dropped, it is possible for unprocessed messages to
//! remain in the channel. Instead, it is usually desirable to perform a "clean"
//! shutdown. To do this, the receiver first calls `close`, which will prevent
//! any further messages to be sent into the channel. Then, the receiver
//! consumes the channel to completion, at which point the receiver can be
//! dropped.
//!
//! # Communicating between sync and async code
//!
//! When you want to communicate between synchronous and asynchronous code, there
//! are two situations to consider:
//!
//! **Bounded channel**: If you need a bounded channel, you should use a bounded
//! Tokio `mpsc` channel for both directions of communication. To call the async
//! [`send`][bounded-send] or [`recv`][bounded-recv] methods in sync code, you
//! will need to use [`Handle::block_on`], which allow you to execute an async
//! method in synchronous code. This is necessary because a bounded channel may
//! need to wait for additional capacity to become available.
//!
//! **Unbounded channel**: You should use the kind of channel that matches where
//! the receiver is. So for sending a message _from async to sync_, you should
//! use [the standard library unbounded channel][std-unbounded] or
//! [crossbeam][crossbeam-unbounded].  Similarly, for sending a message _from sync
//! to async_, you should use an unbounded Tokio `mpsc` channel.
//!
//! [`Sender`]: crate::sync::mpsc::Sender
//! [`Receiver`]: crate::sync::mpsc::Receiver
//! [bounded-send]: crate::sync::mpsc::Sender::send()
//! [bounded-recv]: crate::sync::mpsc::Receiver::recv()
//! [`UnboundedSender`]: crate::sync::mpsc::UnboundedSender
//! [`Handle::block_on`]: crate::runtime::Handle::block_on()
//! [std-unbounded]: std::sync::mpsc::channel
//! [crossbeam-unbounded]: https://docs.rs/crossbeam/*/crossbeam/channel/fn.unbounded.html

pub(super) mod block;

mod bounded;
pub use self::bounded::{channel, Receiver, Sender};

mod chan;

pub(super) mod list;

mod unbounded;
pub use self::unbounded::{unbounded_channel, UnboundedReceiver, UnboundedSender};

pub mod error;

/// The number of values a block can contain.
///
/// This value must be a power of 2. It also must be smaller than the number of
/// bits in `usize`.
#[cfg(all(target_pointer_width = "64", not(loom)))]
const BLOCK_CAP: usize = 32;

#[cfg(all(not(target_pointer_width = "64"), not(loom)))]
const BLOCK_CAP: usize = 16;

#[cfg(loom)]
const BLOCK_CAP: usize = 2;
<|endoftext|>


<commit_before>#![feature(asm)]
#![feature(const_fn)]
#![feature(proc_macro)]
#![no_std]

extern crate cortex_m;
extern crate cortex_m_rtfm as rtfm;
extern crate blue_pill;

use cortex_m::peripheral::SystClkSource;
use rtfm::{app, Threshold};

mod font5x7;
mod i2c;
mod ssd1306;

use ssd1306::SSD1306;

const OLED_ADDR: u8 = 0x3c;

app! {
    device: blue_pill::stm32f103xx,

    resources: {
        static TICKS: u32 = 0;
    },

    tasks: {
        SYS_TICK: {
            path: tick,
            resources: [TICKS],
        },
        EXTI9_5: {
            path: exti9_5,
            resources: [I2C1, EXTI],
        },
    },
}

fn init(p: init::Peripherals, _r: init::Resources) {
    // 48Mhz
    p.FLASH.acr.modify(
        |_, w| w.prftbe().enabled().latency().one(),
    );

    p.RCC.cfgr.modify(|_, w| unsafe { w.bits(0x0068840A) });
    p.RCC.cr.modify(
        |_, w| w.pllon().set_bit().hsion().set_bit(),
    );
    while p.RCC.cr.read().pllrdy().bit_is_clear() {}
    while p.RCC.cr.read().hsirdy().bit_is_clear() {}

    p.RCC.apb2enr.modify(|_, w| {
        w.iopaen().enabled().iopben().enabled().afioen().enabled()
    });

    p.AFIO.mapr.modify(|_, w| unsafe {
        w.swj_cfg().bits(2).i2c1_remap().clear_bit()
    });

    p.RCC.apb1enr.modify(|_, w| w.i2c1en().enabled());

    p.I2C1.cr1.write(|w| w.pe().clear_bit());

    p.GPIOA.crl.modify(|_, w| w.mode6().input());
    p.GPIOA.crh.modify(|_, w| {
        w.mode8().output50().cnf8().push().mode9().input()
    });
    p.GPIOA.bsrr.write(|w| {
        w.bs6().set_bit().bs8().set_bit().bs9().set_bit()
    });

    p.GPIOB.crl.modify(|_, w| {
        w.mode5()
            .input()
            .mode6()
            .output50()
            .cnf6()
            .alt_open()
            .mode7()
            .output50()
            .cnf7()
            .alt_open()
    });
    p.GPIOB.bsrr.write(|w| w.bs5().set_bit());

    p.AFIO.exticr2.modify(|_, w| unsafe {
        w.exti5().bits(1).exti6().bits(0)
    });

    p.AFIO.exticr3.modify(|_, w| unsafe { w.exti9().bits(0) });

    p.EXTI.imr.modify(|_, w| {
        w.mr5().set_bit().mr6().set_bit().mr9().set_bit()
    });
    p.EXTI.rtsr.modify(|_, w| {
        w.tr5().set_bit().tr6().set_bit().tr9().set_bit()
    });
    p.EXTI.ftsr.modify(|_, w| {
        w.tr5().set_bit().tr6().set_bit().tr9().set_bit()
    });

    p.I2C1.cr2.modify(|_, w| unsafe { w.freq().bits(24) });
    p.I2C1.cr1.modify(|_, w| w.pe().clear_bit());
    p.I2C1.trise.modify(
        |_, w| unsafe { w.trise().bits(24 + 1) },
    );
    p.I2C1.ccr.modify(|_, w| unsafe {
        w.f_s().clear_bit().duty().clear_bit().ccr().bits(120)
    });

    p.I2C1.cr1.modify(|_, w| {
        w.nostretch()
            .clear_bit()
            .ack()
            .set_bit()
            .smbus()
            .clear_bit()
    });

    p.I2C1.cr1.write(|w| w.pe().set_bit());
    p.I2C1.oar1.write(|w| unsafe {
        w.addmode()
            .clear_bit()
            .add0()
            .clear_bit()
            .add7()
            .bits(0)
            .add10()
            .bits(0)
    });

    let oled = SSD1306(OLED_ADDR, &p.I2C1);
    oled.init();
    oled.print(0, 0, "   Hello from   ");
    oled.print(0, 1, "      Rust      ");

    p.SYST.set_clock_source(SystClkSource::Core);
    p.SYST.set_reload(48_000_000);
    p.SYST.enable_interrupt();
    p.SYST.enable_counter();
}

fn idle() -> ! {
    loop {
        rtfm::wfi();
    }
}

fn tick(_t: &mut Threshold, r: SYS_TICK::Resources) {
    **r.TICKS += 1;
}

fn exti9_5(_t: &mut Threshold, r: EXTI9_5::Resources) {
    let exti = &**r.EXTI;
    let i2c1 = &**r.I2C1;
    let oled = SSD1306(OLED_ADDR, &i2c1);
    oled.print(0, 0, "EXTI9_5         ");

    // Button A
    if exti.pr.read().pr6().bit_is_set() {
        oled.print(0, 1, "Button A IRQ    ");
        exti.pr.write(|w| w.pr6().set_bit());
    }

    // Button B
    if exti.pr.read().pr9().bit_is_set() {
        oled.print(0, 1, "Button B IRQ    ");
        exti.pr.write(|w| w.pr9().set_bit());
    }

    // Accelerometer Movement
    if exti.pr.read().pr5().bit_is_set() {
        exti.pr.write(|w| w.pr5().set_bit());
    }
}
<commit_msg>adds EXTI0 to update UI and saves key state<commit_after>#![feature(asm)]
#![feature(const_fn)]
#![feature(proc_macro)]
#![no_std]

extern crate cortex_m;
extern crate cortex_m_rtfm as rtfm;
extern crate blue_pill;

use cortex_m::peripheral::SystClkSource;
use rtfm::{app, Threshold};
use blue_pill::stm32f103xx::Interrupt;

mod font5x7;
mod i2c;
mod ssd1306;

use ssd1306::SSD1306;

const OLED_ADDR: u8 = 0x3c;

pub enum Keys {
    A,
    B,
    AB,
    None,
}

pub struct State {
    pub keys: Keys,
}

app! {
    device: blue_pill::stm32f103xx,

    resources: {
        static TICKS: u32 = 0;
        static KEYS: Keys = Keys::None;
    },

    tasks: {
        SYS_TICK: {
            path: tick,
            resources: [TICKS],
        },
        EXTI0: {
            path: update_ui,
            resources: [I2C1, KEYS],
        },
        EXTI9_5: {
            path: exti9_5,
            resources: [KEYS, GPIOA, EXTI],
        },
    },
}

fn init(p: init::Peripherals, _r: init::Resources) {
    // 48Mhz
    p.FLASH.acr.modify(
        |_, w| w.prftbe().enabled().latency().one(),
    );

    p.RCC.cfgr.modify(|_, w| unsafe { w.bits(0x0068840A) });
    p.RCC.cr.modify(
        |_, w| w.pllon().set_bit().hsion().set_bit(),
    );
    while p.RCC.cr.read().pllrdy().bit_is_clear() {}
    while p.RCC.cr.read().hsirdy().bit_is_clear() {}

    p.RCC.apb2enr.modify(|_, w| {
        w.iopaen().enabled().iopben().enabled().afioen().enabled()
    });

    p.AFIO.mapr.modify(|_, w| unsafe {
        w.swj_cfg().bits(2).i2c1_remap().clear_bit()
    });

    p.RCC.apb1enr.modify(|_, w| w.i2c1en().enabled());

    p.I2C1.cr1.write(|w| w.pe().clear_bit());

    p.GPIOA.crl.modify(|_, w| w.mode6().input());
    p.GPIOA.crh.modify(|_, w| {
        w.mode8().output50().cnf8().push().mode9().input()
    });
    p.GPIOA.bsrr.write(|w| {
        w.bs6().set_bit().bs8().set_bit().bs9().set_bit()
    });

    p.GPIOB.crl.modify(|_, w| {
        w.mode5()
            .input()
            .mode6()
            .output50()
            .cnf6()
            .alt_open()
            .mode7()
            .output50()
            .cnf7()
            .alt_open()
    });
    p.GPIOB.bsrr.write(|w| w.bs5().set_bit());

    p.AFIO.exticr2.modify(|_, w| unsafe {
        w.exti5().bits(1).exti6().bits(0)
    });

    p.AFIO.exticr3.modify(|_, w| unsafe { w.exti9().bits(0) });

    p.EXTI.imr.modify(|_, w| {
        w.mr5().set_bit().mr6().set_bit().mr9().set_bit()
    });
    p.EXTI.rtsr.modify(|_, w| {
        w.tr5().set_bit().tr6().set_bit().tr9().set_bit()
    });
    p.EXTI.ftsr.modify(|_, w| {
        w.tr5().set_bit().tr6().set_bit().tr9().set_bit()
    });

    p.I2C1.cr2.modify(|_, w| unsafe { w.freq().bits(24) });
    p.I2C1.cr1.modify(|_, w| w.pe().clear_bit());
    p.I2C1.trise.modify(
        |_, w| unsafe { w.trise().bits(24 + 1) },
    );
    p.I2C1.ccr.modify(|_, w| unsafe {
        w.f_s().clear_bit().duty().clear_bit().ccr().bits(120)
    });

    p.I2C1.cr1.modify(|_, w| {
        w.nostretch()
            .clear_bit()
            .ack()
            .set_bit()
            .smbus()
            .clear_bit()
    });

    p.I2C1.cr1.write(|w| w.pe().set_bit());
    p.I2C1.oar1.write(|w| unsafe {
        w.addmode()
            .clear_bit()
            .add0()
            .clear_bit()
            .add7()
            .bits(0)
            .add10()
            .bits(0)
    });

    let oled = SSD1306(OLED_ADDR, &p.I2C1);
    oled.init();
    oled.print(0, 0, "   Hello from   ");
    oled.print(0, 1, "      Rust      ");

    p.SYST.set_clock_source(SystClkSource::Core);
    p.SYST.set_reload(48_000_000);
    p.SYST.enable_interrupt();
    p.SYST.enable_counter();
}

fn idle() -> ! {
    rtfm::set_pending(Interrupt::EXTI0);

    loop {
        rtfm::wfi();
    }
}

fn tick(_t: &mut Threshold, r: SYS_TICK::Resources) {
    **r.TICKS += 1;
}

fn update_ui(_t: &mut Threshold, r: EXTI0::Resources) {
    let i2c1 = &**r.I2C1;
    let oled = SSD1306(OLED_ADDR, &i2c1);

    match **r.KEYS {
        Keys::A => {
            oled.print(0, 0, "        A       ");
            oled.print(0, 1, "     pressed    ");
        }
        Keys::B => {
            oled.print(0, 0, "        B       ");
            oled.print(0, 1, "     pressed    ");
        }
        Keys::AB => {
            oled.print(0, 0, "     A and B    ");
            oled.print(0, 1, "     pressed    ");
        }
        Keys::None => {
            oled.print(0, 0, "   Hello from   ");
            oled.print(0, 1, "      Rust      ");
        }
    }
}

fn exti9_5(_t: &mut Threshold, r: EXTI9_5::Resources) {
    let exti = &**r.EXTI;
    let gpioa = &**r.GPIOA;

    // Button A
    if exti.pr.read().pr6().bit_is_set() {
        **r.KEYS = if gpioa.idr.read().idr6().bit_is_clear() {
            Keys::A
        } else {
            Keys::None
        };
        exti.pr.write(|w| w.pr6().set_bit());
    // Button B
    } else if exti.pr.read().pr9().bit_is_set() {
        **r.KEYS = if gpioa.idr.read().idr9().bit_is_clear() {
            Keys::B
        } else {
            Keys::None
        };
        exti.pr.write(|w| w.pr9().set_bit());
    // Movement
    } else if exti.pr.read().pr5().bit_is_set() {
        exti.pr.write(|w| w.pr5().set_bit());
    }

    rtfm::set_pending(Interrupt::EXTI0);
}
<|endoftext|>


<commit_before>// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

// Coherence phase
//
// The job of the coherence phase of typechecking is to ensure that
// each trait has at most one implementation for each type. This is
// done by the orphan and overlap modules. Then we build up various
// mappings. That mapping code resides here.

use hir::def_id::DefId;
use rustc::ty::{self, TyCtxt, TypeFoldable};
use rustc::ty::{Ty, TyBool, TyChar, TyError};
use rustc::ty::{TyParam, TyRawPtr};
use rustc::ty::{TyRef, TyAdt, TyDynamic, TyNever, TyTuple};
use rustc::ty::{TyStr, TyArray, TySlice, TyFloat, TyInfer, TyInt};
use rustc::ty::{TyUint, TyClosure, TyBox, TyFnDef, TyFnPtr};
use rustc::ty::{TyProjection, TyAnon};
use CrateCtxt;
use syntax_pos::Span;
use rustc::dep_graph::DepNode;
use rustc::hir::itemlikevisit::ItemLikeVisitor;
use rustc::hir::{Item, ItemImpl};
use rustc::hir;

mod builtin;
mod orphan;
mod overlap;
mod unsafety;

struct CoherenceChecker<'a, 'tcx: 'a> {
    tcx: TyCtxt<'a, 'tcx, 'tcx>,
}

struct CoherenceCheckVisitor<'a, 'tcx: 'a> {
    cc: &'a CoherenceChecker<'a, 'tcx>,
}

impl<'a, 'tcx, 'v> ItemLikeVisitor<'v> for CoherenceCheckVisitor<'a, 'tcx> {
    fn visit_item(&mut self, item: &Item) {
        if let ItemImpl(..) = item.node {
            self.cc.check_implementation(item)
        }
    }

    fn visit_trait_item(&mut self, _trait_item: &hir::TraitItem) {
    }

    fn visit_impl_item(&mut self, _impl_item: &hir::ImplItem) {
    }
}

impl<'a, 'tcx> CoherenceChecker<'a, 'tcx> {
    // Returns the def ID of the base type, if there is one.
    fn get_base_type_def_id(&self, span: Span, ty: Ty<'tcx>) -> Option<DefId> {
        match ty.sty {
            TyAdt(def, _) => Some(def.did),

            TyDynamic(ref t, ..) => t.principal().map(|p| p.def_id()),

            TyBox(_) => self.tcx.lang_items.owned_box(),

            TyBool | TyChar | TyInt(..) | TyUint(..) | TyFloat(..) | TyStr | TyArray(..) |
            TySlice(..) | TyFnDef(..) | TyFnPtr(_) | TyTuple(..) | TyParam(..) | TyError |
            TyNever | TyRawPtr(_) | TyRef(..) | TyProjection(..) => None,

            TyInfer(..) | TyClosure(..) | TyAnon(..) => {
                // `ty` comes from a user declaration so we should only expect types
                // that the user can type
                span_bug!(span,
                          "coherence encountered unexpected type searching for base type: {}",
                          ty);
            }
        }
    }

    fn check(&self) {
        // Check implementations and traits. This populates the tables
        // containing the inherent methods and extension methods. It also
        // builds up the trait inheritance table.
        self.tcx.visit_all_item_likes_in_krate(
            DepNode::CoherenceCheckImpl,
            &mut CoherenceCheckVisitor { cc: self });
        builtin::check(self.tcx);
    }

    fn check_implementation(&self, item: &Item) {
        let tcx = self.tcx;
        let impl_did = tcx.map.local_def_id(item.id);
        let self_type = tcx.item_type(impl_did);

        // If there are no traits, then this implementation must have a
        // base type.

        if let Some(trait_ref) = self.tcx.impl_trait_ref(impl_did) {
            debug!("(checking implementation) adding impl for trait '{:?}', item '{}'",
                   trait_ref,
                   item.name);

            // Skip impls where one of the self type is an error type.
            // This occurs with e.g. resolve failures (#30589).
            if trait_ref.references_error() {
                return;
            }

            enforce_trait_manually_implementable(self.tcx, item.span, trait_ref.def_id);
            self.add_trait_impl(trait_ref, impl_did);
        } else {
            // Skip inherent impls where the self type is an error
            // type. This occurs with e.g. resolve failures (#30589).
            if self_type.references_error() {
                return;
            }

            // Add the implementation to the mapping from implementation to base
            // type def ID, if there is a base type for this implementation and
            // the implementation does not have any associated traits.
            if let Some(base_def_id) = self.get_base_type_def_id(item.span, self_type) {
                self.add_inherent_impl(base_def_id, impl_did);
            }
        }
    }

    fn add_inherent_impl(&self, base_def_id: DefId, impl_def_id: DefId) {
        self.tcx.inherent_impls.borrow_mut().push(base_def_id, impl_def_id);
    }

    fn add_trait_impl(&self, impl_trait_ref: ty::TraitRef<'tcx>, impl_def_id: DefId) {
        debug!("add_trait_impl: impl_trait_ref={:?} impl_def_id={:?}",
               impl_trait_ref,
               impl_def_id);
        let trait_def = self.tcx.lookup_trait_def(impl_trait_ref.def_id);
        trait_def.record_local_impl(self.tcx, impl_def_id, impl_trait_ref);
    }
}

fn enforce_trait_manually_implementable(tcx: TyCtxt, sp: Span, trait_def_id: DefId) {
    if tcx.sess.features.borrow().unboxed_closures {
        // the feature gate allows all of them
        return;
    }
    let did = Some(trait_def_id);
    let li = &tcx.lang_items;

    let trait_name = if did == li.fn_trait() {
        "Fn"
    } else if did == li.fn_mut_trait() {
        "FnMut"
    } else if did == li.fn_once_trait() {
        "FnOnce"
    } else {
        return; // everything OK
    };
    let mut err = struct_span_err!(tcx.sess,
                                   sp,
                                   E0183,
                                   "manual implementations of `{}` are experimental",
                                   trait_name);
    help!(&mut err,
          "add `#![feature(unboxed_closures)]` to the crate attributes to enable");
    err.emit();
}

pub fn check_coherence(ccx: &CrateCtxt) {
    let _task = ccx.tcx.dep_graph.in_task(DepNode::Coherence);
    CoherenceChecker { tcx: ccx.tcx }.check();
    unsafety::check(ccx.tcx);
    orphan::check(ccx.tcx);
    overlap::check(ccx.tcx);
}
<commit_msg>coherence: check builtin impls after the specialization graph is ready<commit_after>// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

// Coherence phase
//
// The job of the coherence phase of typechecking is to ensure that
// each trait has at most one implementation for each type. This is
// done by the orphan and overlap modules. Then we build up various
// mappings. That mapping code resides here.

use hir::def_id::DefId;
use rustc::ty::{self, TyCtxt, TypeFoldable};
use rustc::ty::{Ty, TyBool, TyChar, TyError};
use rustc::ty::{TyParam, TyRawPtr};
use rustc::ty::{TyRef, TyAdt, TyDynamic, TyNever, TyTuple};
use rustc::ty::{TyStr, TyArray, TySlice, TyFloat, TyInfer, TyInt};
use rustc::ty::{TyUint, TyClosure, TyBox, TyFnDef, TyFnPtr};
use rustc::ty::{TyProjection, TyAnon};
use CrateCtxt;
use syntax_pos::Span;
use rustc::dep_graph::DepNode;
use rustc::hir::itemlikevisit::ItemLikeVisitor;
use rustc::hir::{Item, ItemImpl};
use rustc::hir;

mod builtin;
mod orphan;
mod overlap;
mod unsafety;

struct CoherenceChecker<'a, 'tcx: 'a> {
    tcx: TyCtxt<'a, 'tcx, 'tcx>,
}

impl<'a, 'tcx, 'v> ItemLikeVisitor<'v> for CoherenceChecker<'a, 'tcx> {
    fn visit_item(&mut self, item: &Item) {
        if let ItemImpl(..) = item.node {
            self.check_implementation(item)
        }
    }

    fn visit_trait_item(&mut self, _trait_item: &hir::TraitItem) {
    }

    fn visit_impl_item(&mut self, _impl_item: &hir::ImplItem) {
    }
}

impl<'a, 'tcx> CoherenceChecker<'a, 'tcx> {
    // Returns the def ID of the base type, if there is one.
    fn get_base_type_def_id(&self, span: Span, ty: Ty<'tcx>) -> Option<DefId> {
        match ty.sty {
            TyAdt(def, _) => Some(def.did),

            TyDynamic(ref t, ..) => t.principal().map(|p| p.def_id()),

            TyBox(_) => self.tcx.lang_items.owned_box(),

            TyBool | TyChar | TyInt(..) | TyUint(..) | TyFloat(..) | TyStr | TyArray(..) |
            TySlice(..) | TyFnDef(..) | TyFnPtr(_) | TyTuple(..) | TyParam(..) | TyError |
            TyNever | TyRawPtr(_) | TyRef(..) | TyProjection(..) => None,

            TyInfer(..) | TyClosure(..) | TyAnon(..) => {
                // `ty` comes from a user declaration so we should only expect types
                // that the user can type
                span_bug!(span,
                          "coherence encountered unexpected type searching for base type: {}",
                          ty);
            }
        }
    }

    fn check(&mut self) {
        // Check implementations and traits. This populates the tables
        // containing the inherent methods and extension methods. It also
        // builds up the trait inheritance table.
        self.tcx.visit_all_item_likes_in_krate(DepNode::CoherenceCheckImpl, self);
    }

    fn check_implementation(&self, item: &Item) {
        let tcx = self.tcx;
        let impl_did = tcx.map.local_def_id(item.id);
        let self_type = tcx.item_type(impl_did);

        // If there are no traits, then this implementation must have a
        // base type.

        if let Some(trait_ref) = self.tcx.impl_trait_ref(impl_did) {
            debug!("(checking implementation) adding impl for trait '{:?}', item '{}'",
                   trait_ref,
                   item.name);

            // Skip impls where one of the self type is an error type.
            // This occurs with e.g. resolve failures (#30589).
            if trait_ref.references_error() {
                return;
            }

            enforce_trait_manually_implementable(self.tcx, item.span, trait_ref.def_id);
            self.add_trait_impl(trait_ref, impl_did);
        } else {
            // Skip inherent impls where the self type is an error
            // type. This occurs with e.g. resolve failures (#30589).
            if self_type.references_error() {
                return;
            }

            // Add the implementation to the mapping from implementation to base
            // type def ID, if there is a base type for this implementation and
            // the implementation does not have any associated traits.
            if let Some(base_def_id) = self.get_base_type_def_id(item.span, self_type) {
                self.add_inherent_impl(base_def_id, impl_did);
            }
        }
    }

    fn add_inherent_impl(&self, base_def_id: DefId, impl_def_id: DefId) {
        self.tcx.inherent_impls.borrow_mut().push(base_def_id, impl_def_id);
    }

    fn add_trait_impl(&self, impl_trait_ref: ty::TraitRef<'tcx>, impl_def_id: DefId) {
        debug!("add_trait_impl: impl_trait_ref={:?} impl_def_id={:?}",
               impl_trait_ref,
               impl_def_id);
        let trait_def = self.tcx.lookup_trait_def(impl_trait_ref.def_id);
        trait_def.record_local_impl(self.tcx, impl_def_id, impl_trait_ref);
    }
}

fn enforce_trait_manually_implementable(tcx: TyCtxt, sp: Span, trait_def_id: DefId) {
    if tcx.sess.features.borrow().unboxed_closures {
        // the feature gate allows all of them
        return;
    }
    let did = Some(trait_def_id);
    let li = &tcx.lang_items;

    let trait_name = if did == li.fn_trait() {
        "Fn"
    } else if did == li.fn_mut_trait() {
        "FnMut"
    } else if did == li.fn_once_trait() {
        "FnOnce"
    } else {
        return; // everything OK
    };
    let mut err = struct_span_err!(tcx.sess,
                                   sp,
                                   E0183,
                                   "manual implementations of `{}` are experimental",
                                   trait_name);
    help!(&mut err,
          "add `#![feature(unboxed_closures)]` to the crate attributes to enable");
    err.emit();
}

pub fn check_coherence(ccx: &CrateCtxt) {
    let _task = ccx.tcx.dep_graph.in_task(DepNode::Coherence);
    CoherenceChecker { tcx: ccx.tcx }.check();
    unsafety::check(ccx.tcx);
    orphan::check(ccx.tcx);
    overlap::check(ccx.tcx);
    builtin::check(ccx.tcx);
}
<|endoftext|>


<commit_before>extern crate grpc;
extern crate futures;

mod test_misc;

use std::sync::Arc;

use futures::*;
use futures::stream::Stream;

use grpc::server::*;
use grpc::client::*;
use grpc::method::*;
use grpc::marshall::*;
use grpc::error::*;
use grpc::futures_grpc::*;

use test_misc::TestSync;

fn string_string_method(name: &str, client_streaming: bool, server_streaming: bool)
    -> Arc<MethodDescriptor<String, String>>
{
    Arc::new(MethodDescriptor {
       name: name.to_owned(),
       client_streaming: client_streaming,
       server_streaming: server_streaming,
       req_marshaller: Box::new(MarshallerString),
       resp_marshaller: Box::new(MarshallerString),
   })
}

/// Single method server on random port
fn new_server<H>(name: &str, client_streaming: bool, server_streaming: bool, handler: H) -> GrpcServer
    where H : MethodHandler<String, String> + 'static + Sync + Send
{
    let mut methods = Vec::new();
    methods.push(ServerMethod::new(
        string_string_method(name, client_streaming, server_streaming),
        handler,
    ));
    GrpcServer::new(0, ServerServiceDefinition::new(methods))
}

/// Single unary method server
fn new_server_unary<H>(name: &str, handler: H) -> GrpcServer
    where H : Fn(String) -> GrpcFuture<String> + Sync + Send + 'static
{
    new_server(name, false, false, MethodHandlerUnary::new(handler))
}

/// Single server streaming method server
fn new_server_server_streaming<H>(name: &str, handler: H) -> GrpcServer
    where H : Fn(String) -> GrpcStream<String> + Sync + Send + 'static
{
    new_server(name, false, true, MethodHandlerServerStreaming::new(handler))
}

/// Tester for unary methods
struct TesterUnary {
    name: String,
    client: GrpcClient,
    _server: GrpcServer,
}

impl TesterUnary {
    fn new<H>(handler: H) -> TesterUnary
        where H : Fn(String) -> GrpcFuture<String> + Sync + Send + 'static
    {
        let name = "/text/Unary";
        let server = new_server_unary(name, handler);
        let port = server.local_addr().port();
        TesterUnary {
            name: name.to_owned(),
            _server: server,
            client: GrpcClient::new("::1", port).unwrap()
        }
    }

    fn call(&self, param: &str) -> GrpcFuture<String> {
        self.client.call_unary(param.to_owned(), string_string_method(&self.name, false, false))
    }

    fn call_expect_error<F : FnOnce(&GrpcError) -> bool>(&self, param: &str, expect: F) {
        match self.call(param).wait() {
            Ok(r) => panic!("expecting error, got: {:?}", r),
            Err(e) => assert!(expect(&e), "wrong error: {:?}", e),
        }
    }

    fn call_expect_grpc_error<F : FnOnce(&str) -> bool>(&self, param: &str, expect: F) {
        self.call_expect_error(param, |e| {
            match e {
                &GrpcError::GrpcMessage(GrpcMessageError { ref grpc_message }) if expect(&grpc_message) => true,
                _ => false,
            }
        });
    }

    fn call_expect_grpc_error_contain(&self, param: &str, expect: &str) {
        self.call_expect_grpc_error(param, |m| m.find(expect).is_some());
    }
}

/// Tester for server streaming methods
struct TesterServerStreaming {
    name: String,
    client: GrpcClient,
    _server: GrpcServer,
}

impl TesterServerStreaming {
    fn new<H>(handler: H) -> TesterServerStreaming
        where H : Fn(String) -> GrpcStream<String> + Sync + Send + 'static
    {
        let name = "/test/ServerStreaming";
        let server = new_server_server_streaming(name, handler);
        let port = server.local_addr().port();
        TesterServerStreaming {
            name: name.to_owned(),
            _server: server,
            client: GrpcClient::new("::1", port).unwrap()
        }
    }

    fn call(&self, param: &str) -> GrpcStream<String> {
        self.client.call_server_streaming(param.to_owned(), string_string_method(&self.name, false, true))
    }
}

#[test]
fn unary() {
    let tester = TesterUnary::new(|s| Ok(s).into_future().boxed());

    assert_eq!("aa", tester.call("aa").wait().unwrap());
}

#[test]
fn error_in_handler() {
    let tester = TesterUnary::new(|_| Err(GrpcError::Other("my error")).into_future().boxed());

    tester.call_expect_grpc_error_contain("aa", "my error");
}

#[test]
fn panic_in_handler() {
    let tester = TesterUnary::new(|_| panic!("icnap"));

    tester.call_expect_grpc_error("aa",
        |m| m.find("Panic").is_some() && m.find("icnap").is_some());
}

#[test]
fn server_streaming() {
    let test_sync = Arc::new(TestSync::new());
    let test_sync_server = test_sync.clone();

    let tester = TesterServerStreaming::new(move |s| {
        let sync = test_sync_server.clone();
        test_misc::stream_thread_spawn_iter(move || {
            (0..3).map(move |i| {
                sync.take(i * 2 + 1);
                format!("{}{}", s, i)
            })
        })
    });

    let mut rs = tester.call("x").wait();

    test_sync.take(0);
    assert_eq!("x0", rs.next().unwrap().unwrap());
    test_sync.take(2);
    assert_eq!("x1", rs.next().unwrap().unwrap());
    test_sync.take(4);
    assert_eq!("x2", rs.next().unwrap().unwrap());
    assert!(rs.next().is_none());
}
<commit_msg>a test<commit_after>extern crate grpc;
extern crate futures;

mod test_misc;

use std::sync::Arc;

use futures::*;
use futures::stream::Stream;

use grpc::server::*;
use grpc::client::*;
use grpc::method::*;
use grpc::marshall::*;
use grpc::error::*;
use grpc::futures_grpc::*;

use test_misc::TestSync;

fn string_string_method(name: &str, client_streaming: bool, server_streaming: bool)
    -> Arc<MethodDescriptor<String, String>>
{
    Arc::new(MethodDescriptor {
       name: name.to_owned(),
       client_streaming: client_streaming,
       server_streaming: server_streaming,
       req_marshaller: Box::new(MarshallerString),
       resp_marshaller: Box::new(MarshallerString),
   })
}

/// Single method server on random port
fn new_server<H>(name: &str, client_streaming: bool, server_streaming: bool, handler: H) -> GrpcServer
    where H : MethodHandler<String, String> + 'static + Sync + Send
{
    let mut methods = Vec::new();
    methods.push(ServerMethod::new(
        string_string_method(name, client_streaming, server_streaming),
        handler,
    ));
    GrpcServer::new(0, ServerServiceDefinition::new(methods))
}

/// Single unary method server
fn new_server_unary<H>(name: &str, handler: H) -> GrpcServer
    where H : Fn(String) -> GrpcFuture<String> + Sync + Send + 'static
{
    new_server(name, false, false, MethodHandlerUnary::new(handler))
}

/// Single server streaming method server
fn new_server_server_streaming<H>(name: &str, handler: H) -> GrpcServer
    where H : Fn(String) -> GrpcStream<String> + Sync + Send + 'static
{
    new_server(name, false, true, MethodHandlerServerStreaming::new(handler))
}

/// Tester for unary methods
struct TesterUnary {
    name: String,
    client: GrpcClient,
    _server: GrpcServer,
}

impl TesterUnary {
    fn new<H>(handler: H) -> TesterUnary
        where H : Fn(String) -> GrpcFuture<String> + Sync + Send + 'static
    {
        let name = "/text/Unary";
        let server = new_server_unary(name, handler);
        let port = server.local_addr().port();
        TesterUnary {
            name: name.to_owned(),
            _server: server,
            client: GrpcClient::new("::1", port).unwrap()
        }
    }

    fn call(&self, param: &str) -> GrpcFuture<String> {
        self.client.call_unary(param.to_owned(), string_string_method(&self.name, false, false))
    }

    fn call_expect_error<F : FnOnce(&GrpcError) -> bool>(&self, param: &str, expect: F) {
        match self.call(param).wait() {
            Ok(r) => panic!("expecting error, got: {:?}", r),
            Err(e) => assert!(expect(&e), "wrong error: {:?}", e),
        }
    }

    fn call_expect_grpc_error<F : FnOnce(&str) -> bool>(&self, param: &str, expect: F) {
        self.call_expect_error(param, |e| {
            match e {
                &GrpcError::GrpcMessage(GrpcMessageError { ref grpc_message }) if expect(&grpc_message) => true,
                _ => false,
            }
        });
    }

    fn call_expect_grpc_error_contain(&self, param: &str, expect: &str) {
        self.call_expect_grpc_error(param, |m| m.find(expect).is_some());
    }
}

/// Tester for server streaming methods
struct TesterServerStreaming {
    name: String,
    client: GrpcClient,
    _server: GrpcServer,
}

impl TesterServerStreaming {
    fn new<H>(handler: H) -> TesterServerStreaming
        where H : Fn(String) -> GrpcStream<String> + Sync + Send + 'static
    {
        let name = "/test/ServerStreaming";
        let server = new_server_server_streaming(name, handler);
        let port = server.local_addr().port();
        TesterServerStreaming {
            name: name.to_owned(),
            _server: server,
            client: GrpcClient::new("::1", port).unwrap()
        }
    }

    fn call(&self, param: &str) -> GrpcStream<String> {
        self.client.call_server_streaming(param.to_owned(), string_string_method(&self.name, false, true))
    }
}

#[test]
fn unary() {
    let tester = TesterUnary::new(|s| Ok(s).into_future().boxed());

    assert_eq!("aa", tester.call("aa").wait().unwrap());
}

#[test]
fn server_is_not_running() {
    let client = GrpcClient::new("::1", 2).unwrap();

    // TODO: https://github.com/tokio-rs/tokio-core/issues/12
    if false {
        let result = client.call_unary("aa".to_owned(), string_string_method("/does/not/matter", false, false)).wait();
        assert!(result.is_err(), result);
    }
}

#[test]
fn error_in_handler() {
    let tester = TesterUnary::new(|_| Err(GrpcError::Other("my error")).into_future().boxed());

    tester.call_expect_grpc_error_contain("aa", "my error");
}

#[test]
fn panic_in_handler() {
    let tester = TesterUnary::new(|_| panic!("icnap"));

    tester.call_expect_grpc_error("aa",
        |m| m.find("Panic").is_some() && m.find("icnap").is_some());
}

#[test]
fn server_streaming() {
    let test_sync = Arc::new(TestSync::new());
    let test_sync_server = test_sync.clone();

    let tester = TesterServerStreaming::new(move |s| {
        let sync = test_sync_server.clone();
        test_misc::stream_thread_spawn_iter(move || {
            (0..3).map(move |i| {
                sync.take(i * 2 + 1);
                format!("{}{}", s, i)
            })
        })
    });

    let mut rs = tester.call("x").wait();

    test_sync.take(0);
    assert_eq!("x0", rs.next().unwrap().unwrap());
    test_sync.take(2);
    assert_eq!("x1", rs.next().unwrap().unwrap());
    test_sync.take(4);
    assert_eq!("x2", rs.next().unwrap().unwrap());
    assert!(rs.next().is_none());
}
<|endoftext|>