Join GitHub today
GitHub is home to over 31 million developers working together to host and review code, manage projects, and build software together.
Sign upLLVM error: Call parameter type does not match function signature #36744
Comments
This comment has been minimized.
This comment has been minimized.
|
stable 1.8.0 is fine, stable 1.9.0 fails |
This comment has been minimized.
This comment has been minimized.
|
Nominating as this was a stable-to-stable regression |
This comment has been minimized.
This comment has been minimized.
|
On nightly, this was introduced between |
This comment has been minimized.
This comment has been minimized.
|
According to git-bisect f3ac509 is the cause. |
pnkfelix
added
P-high
and removed
I-nominated
labels
Sep 29, 2016
pnkfelix
self-assigned this
Sep 29, 2016
This comment has been minimized.
This comment has been minimized.
|
First off, this is a more minimal test: struct A<'a> {
a: &'a i32,
}
fn call<T>(s: T, functions: &Vec<fn(&T)>) {
}
fn f(a: &A) { }
fn main() {
let a = A { a: &10 };
let vec: Vec<fn(&A)> = vec![f];
call(a, &vec); // 'x
}In any case, @pnkfelix, I looked into this a bit. I am not sure why this ever worked, but I think I see the problem. It has to do with the subtyping (as opposed to coercion) relationship between bound and free regions. In particular, Now, in Presumably some bug or other made this work before. We probably just want to insert an LLVM cast in such cases though. |
This comment has been minimized.
This comment has been minimized.
|
The problem even arises with this slightly further reduced, independently-developed variant of what @nikomatsakis posted: #![allow(dead_code)]
struct A<'l> { _a: &'l i32 }
fn call<'m, T>(_functions: &'m Vec<for <'n> fn(&'n T)>) { }
#[cfg(wont_compile_due_to_type_mismatch)]
fn caller1<'o>(vec: &'o Vec<for <'s> fn(&'s A<'s>)>) { call(vec); }
fn caller2<'t>(vec: &'t Vec<for <'u,'v> fn(&'u A<'v>)>) { call(vec); }
fn main() { }Even here, where we are not passing a value of type
|
This comment has been minimized.
This comment has been minimized.
|
It seems to me that fully erasing even bound regions in LLVM types might well be a reasonable thing to do. But that might then lead to duplicate definitions of types, I suppose? For example, these two vector types are distinct types that are both declared, presumably. The only option I see is inserting casts to account for subtyping, which I believe we used to do (I remember hitting this problem before in the distant past). Perhaps this code just got left out of MIR trans? |
This comment has been minimized.
This comment has been minimized.
|
We could just erase all bound lifetimes in covariant slots - since these can't matter for layout. |
This comment has been minimized.
This comment has been minimized.
|
@arielb1 I'm not sure why you singled out "covariant slots" here (or even what you mean by a "covariant slot", actually). For example, if the type were |
This comment has been minimized.
This comment has been minimized.
|
Sure, you have to look at the variance of the binder, not of the lifetime. OTOH, this would make extracting type parameters from NOTE: this can be reached even without calls: pub struct A<'a>(&'a ());
pub struct S<T>(T);
#[no_mangle]
pub fn bad<'s>(v: &mut S<fn(A<'s>)>, y: S<for<'b> fn(A<'b>)>) {
*v = y;
}
fn main() {}This occurs at every place MIR has subtyping. If MIR type-checking is correct, this is function arguments, function return values, and assignments. If we go by that, this bug could be fixed by checking whether the erased Rust types are different at these points and performing the appropriate cast (this could hide bugs, but that's life - maybe add "proper-subtype" annotations to MIR or something). |
This comment has been minimized.
This comment has been minimized.
Yeah, this is precisely what I was thinking of doing. I agree it can hide bugs, but we can at minimum add some kind of assertions (same size, etc). One other thought I had is that we could probably erase lifetimes fully when generating LLVM types, but we'd have to be aware that distinct Rust types may map to the same LLVM type (but it should have the same runtime representation). We could probably just keep a set of the LLVM types that have been created. IOW, if we have |
This comment has been minimized.
This comment has been minimized.
|
@nikomatsakis If I may ruin your dream... those types can be distinct in stable Rust. |
This comment has been minimized.
This comment has been minimized.
|
@eddyb I am aware of that, but they can still share the same LLVM representation without a problem, I think? |
This comment has been minimized.
This comment has been minimized.
|
@nikomatsakis How would you even determine that automatically without building them first? |
This comment has been minimized.
This comment has been minimized.
|
@eddyb hmm, ok, I see your point. Yeah, I was wrong. =) |
C4K3 commentedSep 26, 2016
I get the error
on this code (which I reduced as much as possible while still getting the error)
This is on Rust 1.11.0, on Linux 64.