// check-pass
//
// This tests checks that clashing_extern_declarations handles types that are recursive through a
// pointer or ref argument. See #75512.

#![crate_type = "lib"]

mod raw_ptr_recursion {
    mod a {
        #[repr(C)]
        struct Pointy {
            pointy: *const Pointy,
        }

        extern "C" {
            fn run_pointy(pointy: Pointy);
        }
    }
    mod b {
        #[repr(C)]
        struct Pointy {
            pointy: *const Pointy,
        }

        extern "C" {
            fn run_pointy(pointy: Pointy);
        }
    }
}

mod raw_ptr_recursion_once_removed {
    mod a {
        #[repr(C)]
        struct Pointy1 {
            pointy_two: *const Pointy2,
        }

        #[repr(C)]
        struct Pointy2 {
            pointy_one: *const Pointy1,
        }

        extern "C" {
            fn run_pointy2(pointy: Pointy2);
        }
    }

    mod b {
        #[repr(C)]
        struct Pointy1 {
            pointy_two: *const Pointy2,
        }

        #[repr(C)]
        struct Pointy2 {
            pointy_one: *const Pointy1,
        }

        extern "C" {
            fn run_pointy2(pointy: Pointy2);
        }
    }
}

mod ref_recursion {
    mod a {
        #[repr(C)]
        struct Reffy<'a> {
            reffy: &'a Reffy<'a>,
        }

        extern "C" {
            fn reffy_recursion(reffy: Reffy);
        }
    }
    mod b {
        #[repr(C)]
        struct Reffy<'a> {
            reffy: &'a Reffy<'a>,
        }

        extern "C" {
            fn reffy_recursion(reffy: Reffy);
        }
    }
}

mod ref_recursion_once_removed {
    mod a {
        #[repr(C)]
        struct Reffy1<'a> {
            reffy: &'a Reffy2<'a>,
        }

        struct Reffy2<'a> {
            reffy: &'a Reffy1<'a>,
        }

        extern "C" {
            #[allow(improper_ctypes)]
            fn reffy_once_removed(reffy: Reffy1);
        }
    }
    mod b {
        #[repr(C)]
        struct Reffy1<'a> {
            reffy: &'a Reffy2<'a>,
        }

        struct Reffy2<'a> {
            reffy: &'a Reffy1<'a>,
        }

        extern "C" {
            #[allow(improper_ctypes)]
            fn reffy_once_removed(reffy: Reffy1);
        }
    }
}
