Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Segfault when returning deep function compositions #93237

Open
fredlahde opened this issue Jan 23, 2022 · 5 comments
Open

Segfault when returning deep function compositions #93237

fredlahde opened this issue Jan 23, 2022 · 5 comments
Labels
A-impl-trait Area: `impl Trait`. Universally / existentially quantified anonymous types with static dispatch. C-bug Category: This is a bug. glacier ICE tracked in rust-lang/glacier. I-crash Issue: The compiler crashes (SIGSEGV, SIGABRT, etc). Use I-ICE instead when the compiler panics. S-bug-has-test Status: This bug is tracked inside the repo by a `known-bug` test. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue.

Comments

@fredlahde
Copy link

This issue is tightly bound to this PR (93082), which aims to add the ability to return impl Fn() -> impl Trait from a function.

I played around with it, and got the idea to test out if there is a limit to how deep we can nest those functions (since the PR also enables impl Fn() -> impl Fn() -> impl Trait). It quickly noticed a segfault from rustc and was able to determine the exact depth that causes the crash.

Code

For generating test files quickly, I wrote a small code generator:

const FILE_NAME: &str = "test.rs";

use std::io::Write;
use std::env;

fn main() {
    let args: Vec<String> = env::args().collect();
    let n_depth: usize = args[1].parse().unwrap();
    let mut fd = std::fs::OpenOptions::new()
        .create(true)
        .truncate(true)
        .write(true)
        .open(FILE_NAME)
        .unwrap();
    fd.write(b"use std::fmt::Debug;\n").unwrap();
    fd.write(b"fn foo()").unwrap();
    (0..n_depth).for_each(|_| {
        let _w = fd.write(b"-> impl Fn() ").unwrap();
    });
    fd.write(b"-> impl Debug {\n").unwrap();
    (0..n_depth).for_each(|_| {
        let _w = fd.write(b"|| ").unwrap();
    });
    fd.write(br#""hi""#).unwrap();
    fd.write(b"}\n").unwrap();

    fd.write(br#"
        fn main() {
            let x = foo()"#).unwrap();
    (0..n_depth).for_each(|_| {
        let _w = fd.write(b"()").unwrap();
    });
    fd.write(br#";
        println!("{:?}", x);
        }"#).unwrap();
}

Once compiled, one can call it like this: ./gen <depth>. The depth argument controls the count of -> impl Fn() that is emitted. The following listing is an example with depth set to 5:

use std::fmt::Debug;
fn foo()-> impl Fn() -> impl Fn() -> impl Fn() -> impl Fn() -> impl Fn() -> impl Debug {
|| || || || || "hi"}

        fn main() {
            let x = foo()()()()()();
        println!("{:?}", x);
        }

If one then tries to compile this with the rustc from the PR at commit 3ed486b37477dde94c87539, the test program compiles successfully.

However, when I set depth to 560, I get a segfault.

Meta

rustc --version --verbose:

rustc 1.60.0-dev
binary: rustc
commit-hash: unknown
commit-date: unknown
host: x86_64-unknown-linux-gnu
release: 1.60.0-dev
LLVM version: 13.0.0

Error output

I got a backtrace from gdb:

#0  0x00007ffff5a28670 in core::iter::adapters::process_results::<core::iter::adapters::map::Map<core::iter::adapters::enumerate::Enumerate<core::iter::adapters::zip::Zip<core::iter::adapters::copied::Copied<core::slice::iter::Iter<rustc_middle::ty::subst::GenericArg>>, core::iter::adapters::copied::Copied<core::slice::iter::Iter<rustc_middle::ty::subst::GenericArg>>>>, rustc_middle::ty::relate::relate_substs<rustc_infer::infer::nll_relate::TypeRelating<rustc_borrowck::type_check::relate_tys::NllTypeRelatingDelegate>>::{closure#0}>, rustc_middle::ty::subst::GenericArg, rustc_middle::ty::error::TypeError, <core::result::Result<smallvec::SmallVec<[rustc_middle::ty::subst::GenericArg; 8]>, rustc_middle::ty::error::TypeError> as core::iter::traits::collect::FromIterator<core::result::Result<rustc_middle::ty::subst::GenericArg, rustc_middle::ty::error::TypeError>>>::from_iter<core::iter::adapters::map::Map<core::iter::adapters::enumerate::Enumerate<core::iter::adapters::zip::Zip<core::iter::adapters::copied::Copied<core::slice::iter::Iter<rustc_middle::ty::subst::GenericArg>>, core::iter::adapters::copied::Copied<core::slice::iter::Iter<rustc_middle::ty::subst::GenericArg>>>>, rustc_middle::ty::relate::relate_substs<rustc_infer::infer::nll_relate::TypeRelating<rustc_borrowck::type_check::relate_tys::NllTypeRelatingDelegate>>::{closure#0}>>::{closure#0}, smallvec::SmallVec<[rustc_middle::ty::subst::GenericArg; 8]>> ()
   from /mnt/work/home/fredlahde/research/rust-impl-fn-depth-test/rust-fork/build/x86_64-unknown-linux-gnu/stage1/bin/../lib/librustc_driver-135a9886b846246a.so
#1  0x00007ffff5ab8cb0 in <core::result::Result<rustc_middle::ty::subst::GenericArg, rustc_middle::ty::error::TypeError> as rustc_middle::ty::context::InternIteratorElement<rustc_middle::ty::subst::GenericArg, &rustc_middle::ty::list::List<rustc_middle::ty::subst::GenericArg>>>::intern_with::<core::iter::adapters::map::Map<core::iter::adapters::enumerate::Enumerate<core::iter::adapters::zip::Zip<core::iter::adapters::copied::Copied<core::slice::iter::Iter<rustc_middle::ty::subst::GenericArg>>, core::iter::adapters::copied::Copied<core::slice::iter::Iter<rustc_middle::ty::subst::GenericArg>>>>, rustc_middle::ty::relate::relate_substs<rustc_infer::infer::nll_relate::TypeRelating<rustc_borrowck::type_check::relate_tys::NllTypeRelatingDelegate>>::{closure#0}>, <rustc_middle::ty::context::TyCtxt>::mk_substs<core::iter::adapters::map::Map<core::iter::adapters::enumerate::Enumerate<core::iter::adapters::zip::Zip<core::iter::adapters::copied::Copied<core::slice::iter::Iter<rustc_middle::ty::subst::GenericArg>>, core::iter::adapters::copied::Copied<core::slice::iter::Iter<rustc_middle::ty::subst::GenericArg>>>>, rustc_middle::ty::relate::relate_substs<rustc_infer::infer::nll_relate::TypeRelating<rustc_borrowck::type_check::relate_tys::NllTypeRelatingDelegate>>::{closure#0}>>::{closure#0}> ()
   from /mnt/work/home/fredlahde/research/rust-impl-fn-depth-test/rust-fork/build/x86_64-unknown-linux-gnu/stage1/bin/../lib/librustc_driver-135a9886b846246a.so
#2  0x00007ffff598b20d in <rustc_middle::ty::context::TyCtxt>::mk_substs::<core::iter::adapters::map::Map<core::iter::adapters::enumerate::Enumerate<core::iter::adapters::zip::Zip<core::iter::adapters::copied::Copied<core::slice::iter::Iter<rustc_middle::ty::subst::GenericArg>>, core::iter::adapters::copied::Copied<core::slice::iter::Iter<rustc_middle::ty::subst::GenericArg>>>>, rustc_middle::ty::relate::relate_substs<rustc_infer::infer::nll_relate::TypeRelating<rustc_borrowck::type_check::relate_tys::NllTypeRelatingDelegate>>::{closure#0}>> ()
   from /mnt/work/home/fredlahde/research/rust-impl-fn-depth-test/rust-fork/build/x86_64-unknown-linux-gnu/stage1/bin/../lib/librustc_driver-135a9886b846246a.so
#3  0x00007ffff5af7b0a in rustc_middle::ty::relate::relate_substs::<rustc_infer::infer::nll_relate::TypeRelating<rustc_borrowck::type_check::relate_tys::NllTypeRelatingDelegate>> ()
   from /mnt/work/home/fredlahde/research/rust-impl-fn-depth-test/rust-fork/build/x86_64-unknown-linux-gnu/stage1/bin/../lib/librustc_driver-135a9886b846246a.so
#4  0x00007ffff5ae1780 in <&rustc_middle::ty::list::List<rustc_middle::ty::subst::GenericArg> as rustc_middle::ty::relate::Relate>::relate::<rustc_infer::infer::nll_relate::TypeRelating<rustc_borrowck::type_check::relate_tys::NllTypeRelatingDelegate>> ()
   from /mnt/work/home/fredlahde/research/rust-impl-fn-depth-test/rust-fork/build/x86_64-unknown-linux-gnu/stage1/bin/../lib/librustc_driver-135a9886b846246a.so
#5  0x00007ffff5af8f11 in rustc_middle::ty::relate::super_relate_tys::<rustc_infer::infer::nll_relate::TypeRelating<rustc_borrowck::type_check::relate_tys::NllTypeRelatingDelegate>> ()
   from /mnt/work/home/fredlahde/research/rust-impl-fn-depth-test/rust-fork/build/x86_64-unknown-linux-gnu/stage1/bin/../lib/librustc_driver-135a9886b846246a.so
#6  0x00007ffff59cb2e6 in <rustc_infer::infer::InferCtxt>::super_combine_tys::<rustc_infer::infer::nll_relate::TypeRelating<rustc_borrowck::type_check::relate_tys::NllTypeRelatingDelegate>> ()
   from /mnt/work/home/fredlahde/research/rust-impl-fn-depth-test/rust-fork/build/x86_64-unknown-linux-gnu/stage1/bin/../lib/librustc_driver-135a9886b846246a.so
#7  0x00007ffff5a99bd7 in <rustc_infer::infer::nll_relate::TypeRelating<rustc_borrowck::type_check::relate_tys::NllTypeRelatingDelegate> as rustc_middle::ty::relate::TypeRelation>::relate::<&rustc_middle::ty::TyS> ()
   from /mnt/work/home/fredlahde/research/rust-impl-fn-depth-test/rust-fork/build/x86_64-unknown-linux-gnu/stage1/bin/../lib/librustc_driver-135a9886b846246a.so
#8  0x00007ffff5b011c3 in <&mut <rustc_middle::ty::sty::FnSig as rustc_middle::ty::relate::Relate>::relate<rustc_infer::infer::nll_relate::TypeRelating<rustc_borrowck::type_check::relate_tys::NllTypeRelatingDelegate>>::{closure#1} as core::ops::function::FnOnce<(((&rustc_middle::ty::TyS, &rustc_middle::ty::TyS), bool),)>>::call_once ()
   from /mnt/work/home/fredlahde/research/rust-impl-fn-depth-test/rust-fork/build/x86_64-unknown-linux-gnu/stage1/bin/../lib/librustc_driver-135a9886b846246a.so
#9  0x00007ffff5abe042 in <core::iter::adapters::map::Map<core::iter::adapters::enumerate::Enumerate<core::iter::adapters::map::Map<core::iter::adapters::chain::Chain<core::iter::adapters::map::Map<core::iter::adapters::zip::Zip<core::slice::iter::Iter<&rustc_middle::ty::TyS>, core::slice::iter::Iter<&rustc_middle::ty::TyS>>, <rustc_middle::ty::sty::FnSig as rustc_middle::ty::relate::Relate>::relate<rustc_infer::infer::nll_relate::TypeRelating<rustc_borrowck::type_check::relate_tys::NllTypeRelatingDelegate>>::{closure#0}>, core::iter::sources::once::Once<((&rustc_middle::ty::TyS, &rustc_middle::ty::TyS), bool)>>, <rustc_middle::ty::sty::FnSig as rustc_middle::ty::relate::Relate>::relate<rustc_infer::infer::nll_relate::TypeRelating<rustc_borrowck::type_check::relate_tys::NllTypeRelatingDelegate>>::{closure#1}>>, <rustc_middle::ty::sty::FnSig as rustc_middle::ty::relate::Relate>::relate<rustc_infer::infer::nll_relate::TypeRelating<rustc_borrowck::type_check::relate_tys::NllTypeRelatingDelegate>>::{closure#2}> as core::iter::traits::iterator::Iterator>::next ()
   from /mnt/work/home/fredlahde/research/rust-impl-fn-depth-test/rust-fork/build/x86_64-unknown-linux-gnu/stage1/bin/../lib/librustc_driver-135a9886b846246a.so

I am not entirely sure, if this is important enough for having it's own issue, since it's so tightly bound to the PR. Feel free to close / move accordingly.

@fredlahde fredlahde added C-bug Category: This is a bug. I-ICE Issue: The compiler panicked, giving an Internal Compilation Error (ICE) ❄️ T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. labels Jan 23, 2022
@fredlahde fredlahde changed the title ICE / Segfault when returning deep function compositions Segfault when returning deep function compositions Jan 23, 2022
@WaffleLapkin
Copy link
Member

Note that this issue is not actually related to #93082, since you can reach the same segfault on stable. Here is a MRE:

use std::io::Write;

fn main() {
    let n = 1380;
    let open = "impl Trait<Assoc = ".repeat(n);
    let close = ">".repeat(n);

    let code = format!("
trait Trait {{ type Assoc; }}
impl Trait for () {{ type Assoc = (); }}

fn _f() -> {open}(){close} {{}}

fn main() {{}}
");

    std::fs::File::options()
        .truncate(true)
        .write(true)
        .create(true)
        .open("./nested_rpit.rs")
        .unwrap()
        .write(code.as_bytes())
        .unwrap();   
}

(this generates a file nested_rpit.rs that segfaults the compiler)

@fredlahde
Copy link
Author

Interestingly, the MRE from @WaffleLapkin only segfaults on stable (1.58.1) but not on nightly (rustc 1.60.0-nightly (bfe1564 2022-01-22)) https://dpaste.com/4AQ2Q3GE6

@WaffleLapkin
Copy link
Member

For nightly you just need a higher n, like n = 1500

@fredlahde
Copy link
Author

@rustbot label: -I-ICE +I-crash

@rustbot rustbot added I-crash Issue: The compiler crashes (SIGSEGV, SIGABRT, etc). Use I-ICE instead when the compiler panics. and removed I-ICE Issue: The compiler panicked, giving an Internal Compilation Error (ICE) ❄️ labels Jan 23, 2022
@steffahn
Copy link
Member

@WaffleLapkin We don’t need to write code generators, we have macros…

trait Trait {
    type Assoc;
}
impl Trait for () {
    type Assoc = ();
}

macro_rules! m {
    ([#$($t:tt)*] [$($open:tt)*] [$($close:tt)*]) => {
        m!{[$($t)*][$($open)*$($open)*][$($close)*$($close)*]}
    };
    ([] [$($open:tt)*] [$($close:tt)*]) => {
        fn _f() -> $($open)*()$($close)* {}
    };
}

m! {[###########][impl Trait<Assoc =][>]}

(playground)

@rust-lang-glacier-bot rust-lang-glacier-bot added the glacier ICE tracked in rust-lang/glacier. label Jan 26, 2022
@Enselic Enselic added the A-impl-trait Area: `impl Trait`. Universally / existentially quantified anonymous types with static dispatch. label Jan 6, 2024
@matthiaskrgr matthiaskrgr added the S-bug-has-test Status: This bug is tracked inside the repo by a `known-bug` test. label Apr 15, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-impl-trait Area: `impl Trait`. Universally / existentially quantified anonymous types with static dispatch. C-bug Category: This is a bug. glacier ICE tracked in rust-lang/glacier. I-crash Issue: The compiler crashes (SIGSEGV, SIGABRT, etc). Use I-ICE instead when the compiler panics. S-bug-has-test Status: This bug is tracked inside the repo by a `known-bug` test. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue.
Projects
None yet
Development

No branches or pull requests

7 participants