#![feature(macro_metavar_expr_concat)]

macro_rules! wrong_concat_declarations {
    ($ex:expr) => {
        ${concat()}
        //~^ ERROR expected identifier

        ${concat(aaaa)}
        //~^ ERROR `concat` must have at least two elements

        ${concat(aaaa,)}
        //~^ ERROR expected identifier

        ${concat(_, aaaa)}

        ${concat(aaaa aaaa)}
        //~^ ERROR expected comma

        ${concat($ex)}
        //~^ ERROR `concat` must have at least two elements

        ${concat($ex, aaaa)}
        //~^ ERROR metavariables of `${concat(..)}` must be of type

        ${concat($ex, aaaa 123)}
        //~^ ERROR expected comma

        ${concat($ex, aaaa,)}
        //~^ ERROR expected identifier
    };
}

macro_rules! dollar_sign_without_referenced_ident {
    ($ident:ident) => {
        const ${concat(FOO, $foo)}: i32 = 2;
        //~^ ERROR variable `foo` is not recognized in meta-variable expression
    };
}

macro_rules! starting_number {
    ($ident:ident) => {{
        let ${concat("1", $ident)}: () = ();
        //~^ ERROR `${concat(..)}` is not generating a valid identifier
    }};
}

macro_rules! starting_valid_unicode {
    ($ident:ident) => {{
        let ${concat("Ý", $ident)}: () = ();
    }};
}

macro_rules! starting_invalid_unicode {
    ($ident:ident) => {{
        let ${concat("\u{00BD}", $ident)}: () = ();
        //~^ ERROR `${concat(..)}` is not generating a valid identifier
    }};
}

macro_rules! ending_number {
    ($ident:ident) => {{
        let ${concat($ident, "1")}: () = ();
    }};
}

macro_rules! ending_valid_unicode {
    ($ident:ident) => {{
        let ${concat($ident, "Ý")}: () = ();
    }};
}

macro_rules! ending_invalid_unicode {
    ($ident:ident) => {{
        let ${concat($ident, "\u{00BD}")}: () = ();
        //~^ ERROR `${concat(..)}` is not generating a valid identifier
    }};
}

macro_rules! empty {
    () => {{
        let ${concat("", "")}: () = ();
        //~^ ERROR `${concat(..)}` is not generating a valid identifier
    }};
}

macro_rules! unsupported_literals {
    ($ident:ident) => {{
        let ${concat(_a, 'b')}: () = ();
        //~^ ERROR expected identifier or string literal
        //~| ERROR expected pattern
        let ${concat(_a, 1)}: () = ();
        //~^ ERROR expected identifier or string literal

        let ${concat($ident, 'b')}: () = ();
        //~^ ERROR expected identifier or string literal
        let ${concat($ident, 1)}: () = ();
        //~^ ERROR expected identifier or string literal
    }};
}

macro_rules! bad_literal_string {
    ($literal:literal) => {
        const ${concat(_foo, $literal)}: () = ();
        //~^ ERROR `${concat(..)}` is not generating a valid identifier
        //~| ERROR `${concat(..)}` is not generating a valid identifier
        //~| ERROR `${concat(..)}` is not generating a valid identifier
        //~| ERROR `${concat(..)}` is not generating a valid identifier
        //~| ERROR `${concat(..)}` is not generating a valid identifier
        //~| ERROR `${concat(..)}` is not generating a valid identifier
        //~| ERROR `${concat(..)}` is not generating a valid identifier
    }
}

macro_rules! bad_literal_non_string {
    ($literal:literal) => {
        const ${concat(_foo, $literal)}: () = ();
        //~^ ERROR metavariables of `${concat(..)}` must be of type
        //~| ERROR metavariables of `${concat(..)}` must be of type
        //~| ERROR metavariables of `${concat(..)}` must be of type
        //~| ERROR metavariables of `${concat(..)}` must be of type
        //~| ERROR metavariables of `${concat(..)}` must be of type
    }
}

macro_rules! bad_tt_literal {
    ($tt:tt) => {
        const ${concat(_foo, $tt)}: () = ();
        //~^ ERROR metavariables of `${concat(..)}` must be of type
        //~| ERROR metavariables of `${concat(..)}` must be of type
        //~| ERROR metavariables of `${concat(..)}` must be of type
    }
}

fn main() {
    wrong_concat_declarations!(1);

    dollar_sign_without_referenced_ident!(VAR);

    starting_number!(_abc);
    starting_valid_unicode!(_abc);
    starting_invalid_unicode!(_abc);

    ending_number!(_abc);
    ending_valid_unicode!(_abc);
    ending_invalid_unicode!(_abc);
    unsupported_literals!(_abc);

    empty!();

    bad_literal_string!("\u{00BD}");
    bad_literal_string!("\x41");
    bad_literal_string!("🤷");
    bad_literal_string!("d[-_-]b");

    bad_literal_string!("-1");
    bad_literal_string!("1.0");
    bad_literal_string!("'1'");

    bad_literal_non_string!(1);
    bad_literal_non_string!(-1);
    bad_literal_non_string!(1.0);
    bad_literal_non_string!('1');
    bad_literal_non_string!(false);

    bad_tt_literal!(1);
    bad_tt_literal!(1.0);
    bad_tt_literal!('1');
}