Existentials: "x as some_iface" promotion makes polymorphic fns monomorphise wrong #2734

Closed
bblum opened this Issue Jun 28, 2012 · 7 comments

Projects

None yet

3 participants

@bblum
Contributor
bblum commented Jun 28, 2012

This segfaults:

iface hax { } 
impl <A> of hax for A { } 
fn perform_hax<T>(x: @T) -> hax {
    x as hax 
}
fn deadcode() {
    perform_hax(@"deadcode");
}
fn main() {
    let _ = perform_hax(@42);
}

When the destructor for _ runs at the end of main, it tries to destroy @42 as though it were an @str, causing a call to free((void*)42).

It runs without segfaulting if the call in deadcode() is commented out. That call causes perform_hax(x) to get monomorphised to promote x as hax as though x were @str. With the call gone, the first monomorphisation happens at main's call, for @int.

It runs without segfaulting if deadcode() and main() are reordered lexicographically, for the same reason as above.

It runs without segfaulting if perform_hax is manually inlined (so that there are two '... as hax').

It runs without segfaulting if "let _ =" is removed in main. Filing a separate issue for that.

@bblum
Contributor
bblum commented Jun 28, 2012

note: I believe this to be an issue in the monomorphisation implementation, rather than an inherent flaw of the type system.

@bblum
Contributor
bblum commented Jun 28, 2012

Problem seems to be more general than existentials (still to do with monomorphising). I've also run into it (i.e., presence or absence of deadcode toggles segfaults) with two other open-coded approaches to implementing similar functionality, all with @-boxes.

(edit: although note that both of those involved unsafe::transmute, and i'm not sure i could reproduce without either iface or transmute.)

@catamorphism catamorphism was assigned Jun 28, 2012
@catamorphism
Contributor

Backing up that this is because of monomorphizing, the following hand-monomorphized version of the code doesn't leak:

iface hax { } 
impl <A> of hax for A { } 
fn perform_hax<T>(x: @T) -> hax {
    x as hax 
}
fn perform_hax_int(x: @int) -> hax {
    x as hax 
}
fn perform_hax_str(x: @str) -> hax {
    x as hax 
}
fn deadcode() {
    perform_hax_str(@"deadcode");
}
fn main() {
    let _ = perform_hax_int(@42);
}

I have a hypothesis about what the bug is, but I'll keep digging.

@bblum
Contributor
bblum commented Jun 28, 2012

Perhaps more illuminating than your code (i.e., narrowing it down) -- if you change it to this, it still doesn't crash:

fn perform_hax_int<T>(x: @T) -> hax {
    x as hax 
}
fn perform_hax_str<T>(x: @T) -> hax {
    x as hax 
}

(and then of course if you change deadcode to call perform_hax_int, it starts crashing again)

@bblum bblum added a commit that referenced this issue Jun 28, 2012
@bblum bblum Add test case for issue #2734 (xfailed) b2b4981
@catamorphism
Contributor

I believe this is a bug in type_use. I'll keep investigating further.

@catamorphism catamorphism added a commit that closed this issue Jun 30, 2012
@catamorphism catamorphism Descend into ty_boxes in type_use
type_use was failing to look into ty_boxes, which caused monomorphize
to coalesce instances that shouldn't have been coalesced (because they
should actually use different type glue)

Closes #2734
f64c23f
@pcwalton
Collaborator

Awesome detective work here.

@catamorphism
Contributor

Good work on @bblum 's part as well for coming up with the test case!

@catamorphism catamorphism added a commit that referenced this issue Jul 11, 2012
@catamorphism catamorphism Test for issue 2735
This probably doesn't test the actual bug, but the fix for
issue 2734 probably camouflages the actual bug (since the
effect of the #2734 test case is now "do nothing observable"
rather than "segfault").

Closes #2735
7b4190d
@catamorphism catamorphism was unassigned by bblum Jun 16, 2014
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment