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

Compiler crashes with "Calling a function with a bad signature" #9382

Closed
bytbox opened this issue Sep 21, 2013 · 10 comments
Closed

Compiler crashes with "Calling a function with a bad signature" #9382

bytbox opened this issue Sep 21, 2013 · 10 comments
Labels
I-crash Issue: The compiler crashes (SIGSEGV, SIGABRT, etc). Use I-ICE instead when the compiler panics. P-medium Medium priority
Milestone

Comments

@bytbox
Copy link
Contributor

bytbox commented Sep 21, 2013

The following code crashes the compiler

trait A {
}
struct S {
    x: int
}
impl A for S {

}
fn new() -> Result<&A, ~str> {
    Err(~"")
}
fn main() {}


rustc hello.rs 
rustc: /home/s/misc/rust/src/llvm/lib/IR/Instructions.cpp:281: void llvm::CallInst::init(llvm::Value*, llvm::ArrayRef<llvm::Value*>, const llvm::Twine&): Assertion `(i >= FTy->getNumParams() || FTy->getParamType(i) == Args[i]->getType()) && "Calling a function with a bad signature!"' failed.
Aborted (core dumped)

The crash does not occur if "&A" is replaced by "@A" or "~A".

@MicahChalmer
Copy link
Contributor

I'm not sure if this is the same underlying bug or not, but you can get the same "Calling a function with a bad signature" compiler crash with this code:

struct A<'self> {
    a: &'self [~int],
    b: ~[int]
}

fn main() {
    let _a = A{
        a:[],
        b:~[]
    };
}

If you remove either of the two fields it works fine. If you move the value of _a.b into its own local variable it works fine, but moving just the value of _a.a into its own local var does not help. The types of the array elements (int here) seem to be irrelevant (same type or different types.) It also does not make a difference whether there are any elements in the array values.

This bug is easy to trigger when trying to create a std::rt::io::process::ProcessConfig. To create a ProcessConfig you have to move both the args and io values into their own local vars to avoid hitting the bug. After encountering it in ProcessConfig, this was the simplest struct I could find that triggered the same ICE.

@alexcrichton
Copy link
Member

Nominating for 1.0, looks like this affects anything which wants to return Enum(&Trait) as I ran into this trying to return Option<&mut Trait> which hinders traits a bit sadly.

@philberty
Copy link

I want to try and have a stab at this now :)

@erickt
Copy link
Contributor

erickt commented Oct 30, 2013

I just spent the last couple minutes reducing a bug down to @MicahChalmer's example :) The little bit extra I can add is that this code compiles fine:

struct A<'self> {
    a: &'self [~int],
    b: ~int,
}

fn main() {
    let _a = A {
        a: &[],
        b: ~1,
    };
}

Also, the assertion is happening in the rustc::middle::trans::glue::call_tydesc_glue_full function, and is happening because the first argument being passed into the drop function is not an llvm *{} type.

@erickt
Copy link
Contributor

erickt commented Oct 30, 2013

Another variation that does not work. We trip over this bug when auto-coercing a ~[T] type into a &[T] type:

struct A<'self> {
    a: &'self [~int],
    b: ~int,
}

fn main() {
    let x: ~[~int] = ~[];
    let _a = A {
        a: x,
        b: ~1,
    };
}

However, if we use vec.as_slice() it works fine:

struct A<'self> {
    a: &'self [~int],
    b: ~int,
}

fn main() {
    let x: &[~int] = [];
    let _a = A {
        a: x.as_slice(),
        b: ~1,
    };
}

So we have work arounds for anyone that runs into this bug.

@cnd
Copy link
Contributor

cnd commented Nov 7, 2013

cc

@kmcallister
Copy link
Contributor

cc me

@kmcallister
Copy link
Contributor

I don't know if this is completely fixed, but as of today (ad58e2c) the program in the original post compiles successfully.

@luqmana
Copy link
Member

luqmana commented Dec 5, 2013

So this seems to be triggered when we auto-slice a vec and the cleanups happen in a landing pad.

Here's a working case: https://gist.github.com/luqmana/47be9ac078b542a50051
Here's a broken case: https://gist.github.com/luqmana/d372a04ef1a2af7fc370

Both use the same struct except for a small change. For the working case the second field is a u64 while in the broken case it's a ~u64.

In the broken case, it seems to try to allocate the ~u64 by doing an invoke to exchange_malloc and it's in the cleanup section where it tries to make the invalid call to drop glue. It's trying to call the drop glue for [0 x i64*]* but passing { i64**, i64 }*. That is, instead of passing the original vec, it's passing the auto-sliced one. And if you look right after, as well as in the "normal return" path, it calls drop glue correctly with the original vec.

@pcwalton
Copy link
Contributor

pcwalton commented Dec 8, 2013

Like a ninja, @luqmana is awesome.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
I-crash Issue: The compiler crashes (SIGSEGV, SIGABRT, etc). Use I-ICE instead when the compiler panics. P-medium Medium priority
Projects
None yet
Development

Successfully merging a pull request may close this issue.

9 participants