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

Comparison of static arrays #7012

Closed
ghost opened this issue Jun 8, 2013 · 9 comments
Closed

Comparison of static arrays #7012

ghost opened this issue Jun 8, 2013 · 9 comments
Labels
E-needs-test Call for participation: An issue has been fixed and does not reproduce, but no test has been added.

Comments

@ghost
Copy link

ghost commented Jun 8, 2013

Hello,

Just posting this to see if it is a bug. The expected behaviour would be that test==test1, therefore 'true' would be printed, however the below prints false. This was tested on windows running 0.6 release.

struct signature<'self> {   
  pattern   : &'self [u32] 
}

static test1: signature<'static> =  signature {
  pattern: &[0x243f6a88u32,0x85a308d3u32,0x13198a2eu32,0x03707344u32,0xa4093822u32,0x299f31d0u32]
};

fn main() {
  let test = &[0x243f6a88u32,0x85a308d3u32,0x13198a2eu32,0x03707344u32,0xa4093822u32,0x299f31d0u32];
  println(fmt!("%b",test==test1.pattern));

}

Edit: changed code, made sure types are correct, retested, returns false on 0.6

@Blei
Copy link
Contributor

Blei commented Jun 8, 2013

This doesn't compile on incoming. Especially the types don't match, test1 should actually a u32 array. After making it compile, it prints true.

@ghost
Copy link
Author

ghost commented Jun 8, 2013

@Blei Hi Blei, my bad, I have fixed the code, could you please confirm this works on incomming? If it is fixed in incomming I will close.

@Blei
Copy link
Contributor

Blei commented Jun 8, 2013

Hmm, this prints false even on incoming. Definitely a bug.

@Aatch
Copy link
Contributor

Aatch commented Jun 8, 2013

As some more information, I did some more checking, and this is almost certainly a bug in codegen.

If you make the comparison a function, marked no-inline, then LLVM compresses it down to a single ret 0 instruction after optimization, so whatever we generate is wrong. Unfortunately there is a lot of IR without optimizations, I don't have the motivation to pour through ~2000 lines of code trying to find the error.

I'm also nominating this.

@dotdash
Copy link
Contributor

dotdash commented Jun 8, 2013

The length is incorrectly set for vector slices in fields in static structs.

struct signature<'self> {
    pattern   : &'self [u32] 
}

struct signature2<'self> {
    pattern   : &'self str,
}

static test1: signature<'static> =  signature {
    pattern:   &[0x243f6a88u32,0x85a308d3u32,0x13198a2eu32,0x03707344u32,0xa4093822u32,0x299f31d0u32],
};
static test2: signature2<'static> =  signature2 {
    pattern:   "Hello!",
};

static test3: &'static [u32] = &[0x243f6a88u32,0x85a308d3u32,0x13198a2eu32,0x03707344u32,0xa4093822u32,0x299f31d0u32];

fn main() {
    println(fmt!("Static &[u32] field:\t%2u", test1.pattern.len()));
    println(fmt!("Static &str field:\t%2u", test2.pattern.len()));
    println(fmt!("Static &[u32]:\t\t%2u", test3.len()));
}

Results in

Static &[u32] field:     4
Static &str field:       6
Static &[u32]:           6

Corresponding llvm code:

@const = private constant [6 x i32] [i32 608135816, i32 -2052912941, i32 320440878, i32 57701188, i32 -1542899678, i32 698298832]
@const1 = private constant { i32*, i64 } { i32* getelementptr inbounds ([6 x i32]* @const, i32 0, i32 0), i64 24 }
@_ZN5test116_69389145026f68d3_00E = internal constant { { { i32*, i64 }*, i64 } } { { { i32*, i64 }*, i64 } { { i32*, i64 }* @const1, i64 16 } }
@str2900 = internal constant [7 x i8] c"Hello!\00"
@_ZN5test217_86eff3e34b82f2c13_00E = internal constant { { i8*, i64 } } { { i8*, i64 } { i8* getelementptr inbounds ([7 x i8]* @str2900, i32 0, i32 0), i64 7 } }
@const2 = private constant [6 x i32] [i32 608135816, i32 -2052912941, i32 320440878, i32 57701188, i32 -1542899678, i32 698298832]
@_ZN5test314_8a97a17587e323_00E = internal constant { i32*, i64 } { i32* getelementptr inbounds ([6 x i32]* @const2, i32 0, i32 0), i64 24 }

@Aatch
Copy link
Contributor

Aatch commented Jun 9, 2013

Between the two of us, me and @dotdash have isolated this down to an auto-borrowing bug.

Basically for this:

static test : Foo<'static> = Foo {
    field: &'static [1,2,3]
};

The [1,2,3] part of the expression is auto-borrowed, then the &'static part causes it to slice. So, it actually constructs a &'static &'static [uint], in terms of the code gen.

One workaround (that will likely break when this is fixed) is to do this:

static test : Foo<'static> = Foo {
    field: [1,2,3]
}

as the vector expression is still auto-borrowed.

I ran up against my understanding of the compiler internals, but I narrowed it down to some wrong logic concerning the adjustments table. What, where or when this happens is beyond my knowledge, unfortunately.

@huonw
Copy link
Member

huonw commented Jun 13, 2013

This seems similar to #5688.

@mstewartgallus
Copy link
Contributor

Unfortunately, this workaround isn't good enough for my purposes because it can not be uniformly applied. See the following example for details.

struct Foo(&'static [&'static [uint]]);

static works: Foo = Foo([&'static [0, 1, 2, 3]]);
// static fails: Foo = Foo([[0, 1, 2, 3]]);

fn main() {
}

@alexcrichton
Copy link
Member

The code example in the original issue now works, flagging as needstest

@huonw huonw closed this as completed in 12099ce Sep 3, 2013
flip1995 pushed a commit to flip1995/rust that referenced this issue Apr 8, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
E-needs-test Call for participation: An issue has been fixed and does not reproduce, but no test has been added.
Projects
None yet
Development

No branches or pull requests

6 participants