Rust-analyzer: New weekly build crashs reproducily

Created on 20 Apr 2020  Â·  23Comments  Â·  Source: rust-analyzer/rust-analyzer

I've doing some work on diesel. Pointing with the cursor to this line reproducibly crashes rust-analyzer with the attached backtrace.

Version: rust-analyzer 90f8378
OS: Ubuntu 20.04
IDE: Emacs

Backtrace: 
thread '<unnamed>' panicked at 'index out of bounds: the len is 1 but the index is 7', /home/runner/.cargo/git/checkouts/chalk-7b02fa8caa2cec94/28cef6f/chalk-ir/src/fold/subst.rs:56:19
stack backtrace:
   0: <unknown>
   1: <unknown>
   2: <unknown>
   3: <unknown>
   4: <unknown>
   5: <unknown>
   6: <unknown>
   7: <unknown>
   8: <unknown>
   9: <unknown>
  10: <unknown>
  11: <unknown>
  12: <unknown>
  13: <unknown>
  14: <unknown>
  15: <unknown>
  16: <unknown>
  17: <unknown>
  18: <unknown>
  19: <unknown>
  20: <unknown>
  21: <unknown>
  22: <unknown>
  23: <unknown>
  24: <unknown>
  25: <unknown>
  26: <unknown>
  27: <unknown>
  28: <unknown>
  29: <unknown>
  30: <unknown>
  31: <unknown>
  32: <unknown>
  33: <unknown>
  34: <unknown>
  35: <unknown>
  36: <unknown>
  37: <unknown>
  38: <unknown>
  39: <unknown>
  40: <unknown>
  41: <unknown>
  42: <unknown>
  43: <unknown>
  44: <unknown>
  45: <unknown>
  46: <unknown>
  47: <unknown>
  48: <unknown>
  49: <unknown>
  50: <unknown>
  51: <unknown>
  52: <unknown>
  53: <unknown>
  54: <unknown>
  55: <unknown>
  56: <unknown>
  57: <unknown>
  58: <unknown>
  59: <unknown>
  60: <unknown>
  61: <unknown>
  62: <unknown>
  63: <unknown>
  64: <unknown>
  65: <unknown>
  66: <unknown>
  67: <unknown>
  68: <unknown>
  69: <unknown>
  70: <unknown>
  71: <unknown>
  72: <unknown>
  73: <unknown>
  74: <unknown>
  75: <unknown>
  76: <unknown>
  77: <unknown>
  78: <unknown>
  79: <unknown>
  80: <unknown>
  81: <unknown>
note: Some details are omitted, run with `RUST_BACKTRACE=full` for a verbose backtrace.
A-ty

Most helpful comment

Small guide to minimizing the reproducer for such a crash, in case someone is interested:

  • we know the function that crashes RA already, and indeed rust-analyzer analysis-stats -o internal_into_boxed . causes the crash; otherwise I'd see where the progress bar says we are and hope that's the right function
  • I removed the other impls of internal_into_boxed so they don't interfere, and checked that it still crashes
  • then, since I suspected the dyn type, I commented out the where clause involving the dyn, and indeed then the crash is gone
  • then I just commented out various groups of lines to see whether it still crashes - we can remove all the other where clauses, actually, and only need the self.order.into(); call (keep in mind that we don't need the result to type-check, just to crash in the same way...)
  • then I replaced some names by non-existing ones to see whether it's necessary that they resolve, and removed the Options and Boxes
  • then I copied the definitions of the remaining types next to the impl, and simplified them a bit as well
  • and I kept removing things to simplify.

In the end I ended up with:

trait BoxedDsl<DB> {
    type Output;
    fn internal_into_boxed(self) -> Self::Output;
}

struct SelectStatement<From, Select, Distinct, Where, Order, LimitOffset, GroupBy, Locking> {
    order: Order,
}

trait QueryFragment<DB: Backend> {}

trait Into<T> { fn into(self) -> T; }

impl<F, S, D, W, O, LOf, DB> BoxedDsl<DB>
    for SelectStatement<F, S, D, W, O, LOf, G>
where
    O: Into<dyn QueryFragment<DB>>,
{
    type Output = XXX;

    fn internal_into_boxed(self) -> Self::Output {
        self.order.into();
    }
}

and copied that to a test, where it indeed still crashed. With that, finding and fixing the bug was just a matter of some print debugging :wink:

All 23 comments

Probably duplicate of #4050.

Edit: Panic message is different.

Yeah, that's a different one. The backtrace isn't very helpful though.

I know that the backtrace isn't that helpful. I will trying to get another one. Is there any way to get a complete backtrace without rebuilding the binary manually?

I suggest enabling debug = 2 in Cargo.toml and building from source.

@matklad I recall you mentioning that the release binaries are stripped, but I can't find that in the workflows. What would you say about enabling debug info for nightly builds?

but I can't find that in the workflows.

That's in dist.rs

What would you say about enabling debug info for nightly builds?

Yes :)

        if !nightly {
            run!("strip ./target/x86_64-unknown-linux-musl/release/rust-analyzer")?;
        }

Oh, right.

@weiznich maybe you could try the nightly version?

Using the latest nightly build prints the following backtrace:

$ rust-analyzer-linux analysis-bench --goto-def diesel/diesel/src/query_builder/select_statement/dsl_impls.rs:359:1
…
from scratch:   thread 'main' panicked at 'index out of bounds: the len is 1 but the index is 8', /home/runner/.cargo/git/checkouts/chalk-7b02fa8caa2cec94/28cef6f/chalk-ir/src/fold/subst.rs:56:19
stack backtrace:
   0: backtrace::backtrace::libunwind::trace
             at /cargo/registry/src/github.com-1ecc6299db9ec823/backtrace-0.3.40/src/backtrace/libunwind.rs:88
   1: backtrace::backtrace::trace_unsynchronized
             at /cargo/registry/src/github.com-1ecc6299db9ec823/backtrace-0.3.40/src/backtrace/mod.rs:66
   2: std::sys_common::backtrace::_print_fmt
             at src/libstd/sys_common/backtrace.rs:77
   3: <std::sys_common::backtrace::_print::DisplayBacktrace as core::fmt::Display>::fmt
             at src/libstd/sys_common/backtrace.rs:59
   4: core::fmt::write
             at src/libcore/fmt/mod.rs:1052
   5: std::io::Write::write_fmt
             at src/libstd/io/mod.rs:1426
   6: std::sys_common::backtrace::_print
             at src/libstd/sys_common/backtrace.rs:62
   7: std::sys_common::backtrace::print
             at src/libstd/sys_common/backtrace.rs:49
   8: std::panicking::default_hook::{{closure}}
             at src/libstd/panicking.rs:204
   9: std::panicking::default_hook
             at src/libstd/panicking.rs:224
  10: std::panicking::rust_panic_with_hook
             at src/libstd/panicking.rs:472
  11: rust_begin_unwind
             at src/libstd/panicking.rs:380
  12: core::panicking::panic_fmt
             at src/libcore/panicking.rs:85
  13: core::panicking::panic_bounds_check
             at src/libcore/panicking.rs:63
  14: <chalk_ir::fold::subst::Subst<I> as chalk_ir::fold::Folder<I>>::fold_free_var_ty
  15: <chalk_ir::Ty<I> as chalk_ir::fold::SuperFold<I,TI>>::super_fold_with
  16: chalk_ir::fold::boring_impls::<impl chalk_ir::fold::Fold<I,TI> for chalk_ir::Parameter<I>>::fold_with
  17: <alloc::vec::Vec<T> as alloc::vec::SpecExtend<T,I>>::from_iter
  18: core::iter::adapters::process_results
  19: chalk_ir::_DERIVE_chalk_ir_fold_Fold_I_TI_FOR_WhereClause::<impl chalk_ir::fold::Fold<I,_TI> for chalk_ir::WhereClause<I>>::fold_with
  20: chalk_ir::fold::binder_impls::<impl chalk_ir::fold::Fold<I,TI> for chalk_ir::Binders<T>>::fold_with
  21: <core::iter::adapters::ResultShunt<I,E> as core::iter::traits::iterator::Iterator>::next
  22: <alloc::vec::Vec<T> as alloc::vec::SpecExtend<T,I>>::from_iter
  23: chalk_ir::fold::boring_impls::<impl chalk_ir::fold::Fold<I,TI> for chalk_ir::QuantifiedWhereClauses<I>>::fold_with
  24: chalk_solve::infer::instantiate::<impl chalk_solve::infer::InferenceTable<I>>::instantiate_binders_universally
  25: <chalk_solve::infer::unify::Unifier<I> as chalk_ir::zip::Zipper<I>>::zip_binders
  26: chalk_solve::infer::unify::Unifier<I>::unify_ty_ty
  27: <chalk_ir::Substitution<I> as chalk_ir::zip::Zip<I>>::zip_with
  28: chalk_solve::infer::unify::Unifier<I>::unify_ty_ty
  29: <chalk_ir::Substitution<I> as chalk_ir::zip::Zip<I>>::zip_with
  30: chalk_solve::infer::unify::Unifier<I>::unify_ty_ty
  31: <chalk_ir::DomainGoal<I> as chalk_ir::zip::Zip<I>>::zip_with
  32: chalk_solve::infer::unify::Unifier<I>::unify
  33: chalk_solve::infer::unify::<impl chalk_solve::infer::InferenceTable<I>>::unify
  34: chalk_solve::recursive::Solver<I>::solve_via_implication
  35: chalk_solve::recursive::Solver<I>::solve_goal
  36: chalk_solve::recursive::fulfill::Fulfill<I>::prove
  37: chalk_solve::recursive::fulfill::Fulfill<I>::solve
  38: chalk_solve::recursive::Solver<I>::solve_via_implication
  39: chalk_solve::recursive::Solver<I>::solve_goal
  40: chalk_solve::recursive::fulfill::Fulfill<I>::prove
  41: chalk_solve::recursive::fulfill::Fulfill<I>::solve
  42: chalk_solve::recursive::Solver<I>::solve_via_implication
  43: chalk_solve::recursive::Solver<I>::solve_goal
  44: chalk_solve::recursive::fulfill::Fulfill<I>::prove
  45: chalk_solve::recursive::fulfill::Fulfill<I>::solve
  46: chalk_solve::recursive::Solver<I>::solve_via_implication
  47: chalk_solve::recursive::Solver<I>::solve_goal
  48: chalk_solve::recursive::Solver<I>::solve_root_goal
  49: ra_hir_ty::traits::trait_solve_query
  50: salsa::runtime::Runtime<DB>::execute_query_implementation
  51: salsa::derived::slot::Slot<DB,Q,MP>::read_upgrade
  52: salsa::derived::slot::Slot<DB,Q,MP>::read
  53: <salsa::derived::DerivedStorage<DB,Q,MP> as salsa::plumbing::QueryStorageOps<DB,Q>>::try_fetch
  54: salsa::QueryTable<DB,Q>::get
  55: <T as ra_hir_ty::db::HirDatabase>::trait_solve
  56: ra_hir_ty::infer::InferenceContext::resolve_ty_as_possible
  57: ra_hir_ty::infer::path::<impl ra_hir_ty::infer::InferenceContext>::infer_path
  58: ra_hir_ty::infer::expr::<impl ra_hir_ty::infer::InferenceContext>::infer_expr_inner
  59: ra_hir_ty::infer::expr::<impl ra_hir_ty::infer::InferenceContext>::infer_expr
  60: ra_hir_ty::infer::expr::<impl ra_hir_ty::infer::InferenceContext>::infer_expr_inner
  61: ra_hir_ty::infer::expr::<impl ra_hir_ty::infer::InferenceContext>::infer_expr_coerce
  62: ra_hir_ty::infer::expr::<impl ra_hir_ty::infer::InferenceContext>::infer_block
  63: ra_hir_ty::infer::expr::<impl ra_hir_ty::infer::InferenceContext>::infer_expr_inner
  64: ra_hir_ty::infer::expr::<impl ra_hir_ty::infer::InferenceContext>::infer_expr_coerce
  65: ra_hir_ty::infer::infer_query
  66: salsa::runtime::Runtime<DB>::execute_query_implementation
  67: salsa::derived::slot::Slot<DB,Q,MP>::read_upgrade
  68: salsa::derived::slot::Slot<DB,Q,MP>::read
  69: <salsa::derived::DerivedStorage<DB,Q,MP> as salsa::plumbing::QueryStorageOps<DB,Q>>::try_fetch
  70: <T as ra_hir_ty::db::HirDatabase>::infer_query
  71: ra_hir_ty::db::infer_wait
  72: ra_hir::source_analyzer::SourceAnalyzer::new_for_body
  73: ra_hir::semantics::Semantics<DB>::analyze2
  74: ra_hir::semantics::Semantics<DB>::descend_into_macros
  75: ra_ide::goto_definition::goto_definition
  76: std::panicking::try::do_call
  77: __rust_maybe_catch_panic
             at src/libpanic_unwind/lib.rs:86
  78: ra_ide::Analysis::goto_definition
  79: rust_analyzer::cli::analysis_bench::analysis_bench
  80: rust_analyzer::main
  81: std::rt::lang_start::{{closure}}
  82: std::rt::lang_start_internal::{{closure}}
             at src/libstd/rt.rs:52
  83: std::panicking::try::do_call
             at src/libstd/panicking.rs:305
  84: __rust_maybe_catch_panic
             at src/libpanic_unwind/lib.rs:86
  85: std::panicking::try
             at src/libstd/panicking.rs:281
  86: std::panic::catch_unwind
             at src/libstd/panic.rs:394
  87: std::rt::lang_start_internal
             at src/libstd/rt.rs:51
  88: main
note: Some details are omitted, run with `RUST_BACKTRACE=full` for a verbose backtrace.

if !nightly {

Ah, so that wasn't a Deja vu :)

So another crash related to binders in dyn Trait... I really thought #4023 would be the last one :grimacing:

(Also, wow, those where clauses...)

I'm seeing this too:

thread '<unnamed>' panicked at 'index out of bounds: the len is 1 but the index is 8', C:\Users\runneradmin\.cargo\git\checkouts\chalk-7b02fa8caa2cec94\28cef6f\chalk-ir\src\fold\subst.rs:56:19

I think we need more people trying out the nightlies, or to check analysis-stats on nightlies on more projects :grimacing:

to check analysis-stats on nightlies on more projects

What's the easiest way for me to run stable/weekly RA in vs-code, but run also run nightly "analysis-stats" if i notice problems? Is this just a matter of cloning the latest RA source, building, and then cargo runing something?

Yeah, either cargo build --release from source (you really need the release build), or download a nightly build from our releases.

or to check analysis-stats on nightlies on more projects

+1 to this

I'd really like to see the nightly CI job gate the release on a succesful run against some representative projects.

I'd really like to see the nightly CI job gate the release on a succesful run against some representative projects

A helpful first step would be to find a specific less-than-huge project which causes the currently weekly to die. I think setting up the actual CI process would be on me, but I'd love to have one project to start with :)

Actually, diesel would be a good example. I'll add it to CI, once we stop crashing on it.

Hm, actually, why re-invent the wheel? We should just re-use https://github.com/rust-lang/rustc-perf/tree/master/collector/benchmarks

That's where @edwin0cheng's page gets its test cases from, IIRC :smile:

The only problem so far it seems like we don't crash on those crates (though it looks like we are doing something exponential in servo's crates) =/ We do crash on diesel at the moment though.

Another, more time-consuming, but probably better option, is to learn to run analys-stats on rustc's test suite. This should be both faster and give us better coverage than analyzing full projects.

Oh, that's indeed an interesting idea :thinking:

I always had plans to someday test the type inference on rustc's test suite, but only once we're mostly complete. But just checking that it doesn't crash would be possible right now, of course...

Wait, no, we do in fact crash with this error on https://github.com/rust-lang/rustc-perf/tree/master/collector/benchmarks/hyper-2, which might be better (or worse) than diesel.

Did a first stab at the idea at https://github.com/rust-analyzer/rust-analyzer/pull/4104

At the moment, it does just a single-file analysis, without stdlib. it only found a couple of problems with macro expansion :(

Small guide to minimizing the reproducer for such a crash, in case someone is interested:

  • we know the function that crashes RA already, and indeed rust-analyzer analysis-stats -o internal_into_boxed . causes the crash; otherwise I'd see where the progress bar says we are and hope that's the right function
  • I removed the other impls of internal_into_boxed so they don't interfere, and checked that it still crashes
  • then, since I suspected the dyn type, I commented out the where clause involving the dyn, and indeed then the crash is gone
  • then I just commented out various groups of lines to see whether it still crashes - we can remove all the other where clauses, actually, and only need the self.order.into(); call (keep in mind that we don't need the result to type-check, just to crash in the same way...)
  • then I replaced some names by non-existing ones to see whether it's necessary that they resolve, and removed the Options and Boxes
  • then I copied the definitions of the remaining types next to the impl, and simplified them a bit as well
  • and I kept removing things to simplify.

In the end I ended up with:

trait BoxedDsl<DB> {
    type Output;
    fn internal_into_boxed(self) -> Self::Output;
}

struct SelectStatement<From, Select, Distinct, Where, Order, LimitOffset, GroupBy, Locking> {
    order: Order,
}

trait QueryFragment<DB: Backend> {}

trait Into<T> { fn into(self) -> T; }

impl<F, S, D, W, O, LOf, DB> BoxedDsl<DB>
    for SelectStatement<F, S, D, W, O, LOf, G>
where
    O: Into<dyn QueryFragment<DB>>,
{
    type Output = XXX;

    fn internal_into_boxed(self) -> Self::Output {
        self.order.into();
    }
}

and copied that to a test, where it indeed still crashed. With that, finding and fixing the bug was just a matter of some print debugging :wink:

Was this page helpful?
0 / 5 - 0 ratings

Related issues

matklad picture matklad  Â·  28Comments

matklad picture matklad  Â·  25Comments

Geobert picture Geobert  Â·  28Comments

bryanburgers picture bryanburgers  Â·  31Comments

aloucks picture aloucks  Â·  32Comments