Skip to content

Local::borrow tweak and basic task pinning. #2

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

Merged
merged 4 commits into from
Jun 16, 2013
Merged

Local::borrow tweak and basic task pinning. #2

merged 4 commits into from
Jun 16, 2013

Conversation

toddaaro
Copy link

Includes two commits:

  1. A modification of the Local::borrow function to support returning an argument. Required changing a large number of files to add an extra type parameter.
  2. A basic implementation of task pinning. A task started with a designated "home" scheduler will only run on that scheduler. IO interactions are not yet implemented, and forwarding of tasks off "special" schedulers is not yet implemented.

Running with a high (greater than 100) RUST_RT_STRESS variable could result in nontrivial test execution times.

toddaaro added 4 commits June 10, 2013 15:29
…ain io branch and modified the incoming new file lang.rs to be api-compatible
…ions have been planned for, and no forwarding of tasks off special schedulers is supported.
@toddaaro
Copy link
Author

In response to the "run_anything" issue:

I'm not sure what exactly we want to do here. The current approach is entirely dependent on the shared work queue, and assumes that eventually a different scheduler will win on the dequeue. Without the shared dequeue we need some sort of forwarding location, and I'm not sure where that should be. Specifying on scheduler creation is a bit weird, but certainly possible. It creates a dependency cycle among the schedulers, where they need to know about each other for forwarding reasons.

In the short term initializing the platform thread by building it as the second scheduler, and having it point to the first scheduler, makes sense to me. But this assumes that we really don't want the enqueue locally in this case - I'm not sure what the real world hit is.

@toddaaro
Copy link
Author

Paraphrasing some IRC discussion:

The servo usecase of a platform thread works well with brson's suggestion. We create a scheduler, then create the platform scheduler. The platform scheduler then gets the first scheduler's handle to use as a forwarding address.

The issue is the long term - in the currently not known usecase of lots of complicated scheduler pinning it becomes unpleasant to provide each scheduler an appropriate forwarding location, and to ensure that schedulers don't all forward to the same destination. This will require some thinking.

Since we know the scheduler design will change radically with the work stealing changes, we will do what works in the short term.

@brson brson merged commit d1ec8b5 into brson:io Jun 16, 2013
@brson
Copy link
Owner

brson commented Jun 16, 2013

Merged.

brson pushed a commit that referenced this pull request Aug 23, 2013
…inger

Attempt #2 of [this pull request](rust-lang#8597) since my tired mind decided messing up my repo, then deleting and re-forking was a good idea.  This is identical to the second last commit in that PR.  (The one before I ruined everything.)

This is an improvement to use_decl docs, which will hopefully improve understanding of how resolution works and where `extern mod` and module declarations should go to make them visible to use declarations.
brson pushed a commit that referenced this pull request Nov 1, 2014
…ariables

Diagnostics such as the following

```
mismatched types: expected `core::result::Result<uint,()>`, found `core::option::Option<<generic #1>>`
<anon>:6     let a: Result<uint, ()> = None;
                                       ^~~~
mismatched types: expected `&mut <generic #2>`, found `uint`
<anon>:7     f(42u);
               ^~~
```

tend to be fairly unappealing to new users. While specific type var IDs are valuable in
diagnostics that deal with more than one such variable, in practice many messages
only mention one. In those cases, leaving out the specific number makes the messages
slightly less terrifying.

In addition, type variables have been changed to use the type hole syntax `_` in diagnostics.
With a variable ID, they're printed as `_#id` (e.g. `_#1`). In cases where the ID is left out,
it's simply `_`. Integer and float variables have an additional suffix after the number, e.g.
`_#1i` or `_#3f`.
bors added a commit that referenced this pull request Nov 1, 2014
…, r=nikomatsakis

This PR aims to improve the readability of diagnostic messages that involve unresolved type variables. Currently, messages like the following:

```rust
mismatched types: expected `core::result::Result<uint,()>`, found `core::option::Option<<generic #1>>`
<anon>:6     let a: Result<uint, ()> = None;
                                       ^~~~
mismatched types: expected `&mut <generic #2>`, found `uint`
<anon>:7     f(42u);
               ^~~
```

tend to appear unapproachable to new users. [0] While specific type var IDs are valuable in
diagnostics that deal with more than one such variable, in practice many messages
only mention one. In those cases, leaving out the specific number makes the messages
slightly less terrifying.

```rust
mismatched types: expected `core::result::Result<uint, ()>`, found `core::option::Option<_>`
<anon>:6     let a: Result<uint, ()> = None;
                                       ^~~~
mismatched types: expected `&mut _`, found `uint`
<anon>:7     f(42u);
               ^~~
```

As you can see, I also tweaked the aesthetics slightly by changing type variables to use the type hole syntax _. For integer variables, the syntax used is:

```rust
mismatched types: expected `core::result::Result<uint, ()>`, found `core::option::Option<_#1i>`
<anon>:6     let a: Result<uint, ()> = Some(1);
```

and float variables:

```rust
mismatched types: expected `core::result::Result<uint, ()>`, found `core::option::Option<_#1f>`
<anon>:6     let a: Result<uint, ()> = Some(0.5);
```

[0] https://twitter.com/coda/status/517713085465772032

Closes rust-lang#2632.
Closes rust-lang#3404.
Closes rust-lang#18426.
alexcrichton added a commit that referenced this pull request Dec 31, 2014
Fixes rust-lang#19707.

In terms of output, it currently uses the form `argument #1`, `argument #2`, etc. If anyone has any better suggestions I would be glad to consider them.
brson pushed a commit that referenced this pull request Jul 30, 2015
brson pushed a commit that referenced this pull request Aug 16, 2016
rustc_trans: don't Assert(Overflow(Neg)) when overflow checks are off.

Generic functions using `Neg` on primitive types would panic even in release mode, with MIR trans.
The solution is a bit hacky, as I'm checking the message, since there's no dedicated `CheckedUnOp`.

Blocks Servo rustup ([failure #1](http://build.servo.org/builders/linux-rel/builds/2477/steps/test_3/logs/stdio), [failure #2](http://build.servo.org/builders/mac-rel-css/builds/2364/steps/test/logs/stdio)) - this should be the last hurdle, it affects only one test.
brson pushed a commit that referenced this pull request Jan 26, 2017
For a given file

```rust
trait A { fn foo(&self) {} }
trait B : A { fn foo(&self) {} }

fn bar<T: B>(a: &T) {
  a.foo()
}
```

provide the following output

```
error[E0034]: multiple applicable items in scope
 --> file.rs:6:5
  |
6 |   a.foo(1)
  |     ^^^ multiple `foo` found
  |
note: candidate #1 is defined in the trait `A`
 --> file.rs:2:11
  |
2 | trait A { fn foo(&self, a: usize) {} }
  |           ^^^^^^^^^^^^^^^^^^^^^^^^^^
help: to use it here write `A::foo(&a, 1)` instead
 --> file.rs:6:5
  |
6 |   a.foo(1)
  |     ^^^
note: candidate #2 is defined in the trait `B`
 --> file.rs:3:15
  |
3 | trait B : A { fn foo(&self, a: usize) {} }
  |               ^^^^^^^^^^^^^^^^^^^^^^^^^^
help: to use it here write `B::foo(&a, 1)` instead
 --> file.rs:6:5
  |
6 |   a.foo(1)
  |     ^^^
```
brson pushed a commit that referenced this pull request Jan 26, 2017
E0034: provide disambiguated syntax for candidates

For a given file

```rust
trait A { fn foo(&self) {} }
trait B : A { fn foo(&self) {} }

fn bar<T: B>(a: &T) {
  a.foo()
}
```

provide the following output

```
error[E0034]: multiple applicable items in scope
 --> file.rs:6:5
  |
6 |   a.foo(1)
  |     ^^^ multiple `foo` found
  |
note: candidate #1 is defined in the trait `A`
 --> file.rs:2:11
  |
2 | trait A { fn foo(&self, a: usize) {} }
  |           ^^^^^^^^^^^^^^^^^^^^^^^^^^
help: to use it here write `A::foo(&a, 1)` instead
 --> file.rs:6:5
  |
6 |   a.foo(1)
  |     ^^^
note: candidate #2 is defined in the trait `B`
 --> file.rs:3:15
  |
3 | trait B : A { fn foo(&self, a: usize) {} }
  |               ^^^^^^^^^^^^^^^^^^^^^^^^^^
help: to use it here write `B::foo(&a, 1)` instead
 --> file.rs:6:5
  |
6 |   a.foo(1)
  |     ^^^
```

Fix rust-lang#37767.
brson pushed a commit that referenced this pull request Feb 10, 2017
LeakSanitizer, ThreadSanitizer, AddressSanitizer and MemorySanitizer support

```
$ cargo new --bin leak && cd $_

$ edit Cargo.toml && tail -n3 $_
```

``` toml
[profile.dev]
opt-level = 1
```

```
$ edit src/main.rs && cat $_
```

``` rust
use std::mem;

fn main() {
    let xs = vec![0, 1, 2, 3];
    mem::forget(xs);
}
```

```
$ RUSTFLAGS="-Z sanitizer=leak" cargo run --target x86_64-unknown-linux-gnu; echo $?
    Finished dev [optimized + debuginfo] target(s) in 0.0 secs
     Running `target/debug/leak`

=================================================================
==10848==ERROR: LeakSanitizer: detected memory leaks

Direct leak of 16 byte(s) in 1 object(s) allocated from:
    #0 0x557c3488db1f in __interceptor_malloc /shared/rust/checkouts/lsan/src/compiler-rt/lib/lsan/lsan_interceptors.cc:55
    #1 0x557c34888aaa in alloc::heap::exchange_malloc::h68f3f8b376a0da42 /shared/rust/checkouts/lsan/src/liballoc/heap.rs:138
    #2 0x557c34888afc in leak::main::hc56ab767de6d653a $PWD/src/main.rs:4
    #3 0x557c348c0806 in __rust_maybe_catch_panic ($PWD/target/debug/leak+0x3d806)

SUMMARY: LeakSanitizer: 16 byte(s) leaked in 1 allocation(s).
23
```

```
$ cargo new --bin racy && cd $_

$ edit src/main.rs && cat $_
```

``` rust
use std::thread;

static mut ANSWER: i32 = 0;

fn main() {
    let t1 = thread::spawn(|| unsafe { ANSWER = 42 });
    unsafe {
        ANSWER = 24;
    }
    t1.join().ok();
}
```

```
$ RUSTFLAGS="-Z sanitizer=thread" cargo run --target x86_64-unknown-linux-gnu; echo $?
==================
WARNING: ThreadSanitizer: data race (pid=12019)
  Write of size 4 at 0x562105989bb4 by thread T1:
    #0 racy::main::_$u7b$$u7b$closure$u7d$$u7d$::hbe13ea9e8ac73f7e $PWD/src/main.rs:6 (racy+0x000000010e3f)
    #1 _$LT$std..panic..AssertUnwindSafe$LT$F$GT$$u20$as$u20$core..ops..FnOnce$LT$$LP$$RP$$GT$$GT$::call_once::h2e466a92accacc78 /shared/rust/checkouts/lsan/src/libstd/panic.rs:296 (racy+0x000000010cc5)
    #2 std::panicking::try::do_call::h7f4d2b38069e4042 /shared/rust/checkouts/lsan/src/libstd/panicking.rs:460 (racy+0x00000000c8f2)
    #3 __rust_maybe_catch_panic <null> (racy+0x0000000b4e56)
    #4 std::panic::catch_unwind::h31ca45621ad66d5a /shared/rust/checkouts/lsan/src/libstd/panic.rs:361 (racy+0x00000000b517)
    #5 std::thread::Builder::spawn::_$u7b$$u7b$closure$u7d$$u7d$::hccfc37175dea0b01 /shared/rust/checkouts/lsan/src/libstd/thread/mod.rs:357 (racy+0x00000000c226)
    #6 _$LT$F$u20$as$u20$alloc..boxed..FnBox$LT$A$GT$$GT$::call_box::hd880bbf91561e033 /shared/rust/checkouts/lsan/src/liballoc/boxed.rs:605 (racy+0x00000000f27e)
    #7 std::sys::imp::thread::Thread::new::thread_start::hebdfc4b3d17afc85 <null> (racy+0x0000000abd40)

  Previous write of size 4 at 0x562105989bb4 by main thread:
    #0 racy::main::h23e6e5ca46d085c3 $PWD/src/main.rs:8 (racy+0x000000010d7c)
    #1 __rust_maybe_catch_panic <null> (racy+0x0000000b4e56)
    #2 __libc_start_main <null> (libc.so.6+0x000000020290)

  Location is global 'racy::ANSWER::h543d2b139f819b19' of size 4 at 0x562105989bb4 (racy+0x0000002f8bb4)

  Thread T1 (tid=12028, running) created by main thread at:
    #0 pthread_create /shared/rust/checkouts/lsan/src/compiler-rt/lib/tsan/rtl/tsan_interceptors.cc:902 (racy+0x00000001aedb)
    #1 std::sys::imp::thread::Thread::new::hce44187bf4a36222 <null> (racy+0x0000000ab9ae)
    #2 std::thread::spawn::he382608373eb667e /shared/rust/checkouts/lsan/src/libstd/thread/mod.rs:412 (racy+0x00000000b5aa)
    #3 racy::main::h23e6e5ca46d085c3 $PWD/src/main.rs:6 (racy+0x000000010d5c)
    #4 __rust_maybe_catch_panic <null> (racy+0x0000000b4e56)
    #5 __libc_start_main <null> (libc.so.6+0x000000020290)

SUMMARY: ThreadSanitizer: data race $PWD/src/main.rs:6 in racy::main::_$u7b$$u7b$closure$u7d$$u7d$::hbe13ea9e8ac73f7e
==================
ThreadSanitizer: reported 1 warnings
66
```

```
$ cargo new --bin oob && cd $_

$ edit src/main.rs && cat $_
```

``` rust
fn main() {
    let xs = [0, 1, 2, 3];
    let y = unsafe { *xs.as_ptr().offset(4) };
}
```

```
$ RUSTFLAGS="-Z sanitizer=address" cargo run --target x86_64-unknown-linux-gnu; echo $?
=================================================================
==13328==ERROR: AddressSanitizer: stack-buffer-overflow on address 0x7fff29f3ecd0 at pc 0x55802dc6bf7e bp 0x7fff29f3ec90 sp 0x7fff29f3ec88
READ of size 4 at 0x7fff29f3ecd0 thread T0
    #0 0x55802dc6bf7d in oob::main::h0adc7b67e5feb2e7 $PWD/src/main.rs:3
    #1 0x55802dd60426 in __rust_maybe_catch_panic ($PWD/target/debug/oob+0xfe426)
    #2 0x55802dd58dd9 in std::rt::lang_start::hb2951fc8a59d62a7 ($PWD/target/debug/oob+0xf6dd9)
    #3 0x55802dc6c002 in main ($PWD/target/debug/oob+0xa002)
    #4 0x7fad8c3b3290 in __libc_start_main (/usr/lib/libc.so.6+0x20290)
    #5 0x55802dc6b719 in _start ($PWD/target/debug/oob+0x9719)

Address 0x7fff29f3ecd0 is located in stack of thread T0 at offset 48 in frame
    #0 0x55802dc6bd5f in oob::main::h0adc7b67e5feb2e7 $PWD/src/main.rs:1

  This frame has 1 object(s):
    [32, 48) 'xs' <== Memory access at offset 48 overflows this variable
HINT: this may be a false positive if your program uses some custom stack unwind mechanism or swapcontext
      (longjmp and C++ exceptions *are* supported)
SUMMARY: AddressSanitizer: stack-buffer-overflow $PWD/src/main.rs:3 in oob::main::h0adc7b67e5feb2e7
Shadow bytes around the buggy address:
  0x1000653dfd40: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x1000653dfd50: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x1000653dfd60: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x1000653dfd70: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x1000653dfd80: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
=>0x1000653dfd90: 00 00 00 00 f1 f1 f1 f1 00 00[f3]f3 00 00 00 00
  0x1000653dfda0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x1000653dfdb0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x1000653dfdc0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x1000653dfdd0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x1000653dfde0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
Shadow byte legend (one shadow byte represents 8 application bytes):
  Addressable:           00
  Partially addressable: 01 02 03 04 05 06 07
  Heap left redzone:       fa
  Heap right redzone:      fb
  Freed heap region:       fd
  Stack left redzone:      f1
  Stack mid redzone:       f2
  Stack right redzone:     f3
  Stack partial redzone:   f4
  Stack after return:      f5
  Stack use after scope:   f8
  Global redzone:          f9
  Global init order:       f6
  Poisoned by user:        f7
  Container overflow:      fc
  Array cookie:            ac
  Intra object redzone:    bb
  ASan internal:           fe
  Left alloca redzone:     ca
  Right alloca redzone:    cb
==13328==ABORTING
1
```

```
$ cargo new --bin uninit && cd $_

$ edit src/main.rs && cat $_
```

``` rust
use std::mem;

fn main() {
    let xs: [u8; 4] = unsafe { mem::uninitialized() };
    let y = xs[0] + xs[1];
}
```

```
$ RUSTFLAGS="-Z sanitizer=memory" cargo run; echo $?
==30198==WARNING: MemorySanitizer: use-of-uninitialized-value
    #0 0x563f4b6867da in uninit::main::hc2731cd4f2ed48f8 $PWD/src/main.rs:5
    #1 0x563f4b7033b6 in __rust_maybe_catch_panic ($PWD/target/debug/uninit+0x873b6)
    #2 0x563f4b6fbd69 in std::rt::lang_start::hb2951fc8a59d62a7 ($PWD/target/debug/uninit+0x7fd69)
    #3 0x563f4b6868a9 in main ($PWD/target/debug/uninit+0xa8a9)
    #4 0x7fe844354290 in __libc_start_main (/usr/lib/libc.so.6+0x20290)
    #5 0x563f4b6864f9 in _start ($PWD/target/debug/uninit+0xa4f9)

SUMMARY: MemorySanitizer: use-of-uninitialized-value $PWD/src/main.rs:5 in uninit::main::hc2731cd4f2ed48f8
Exiting
77
```
brson pushed a commit that referenced this pull request Mar 4, 2017
brson pushed a commit that referenced this pull request Mar 9, 2017
Group "missing variable bind" spans in `or` matches and clarify wording
for the two possible cases: when a variable from the first pattern is
not in any of the subsequent patterns, and when a variable in any of the
other patterns is not in the first one.

Before:

```
error[E0408]: variable `a` from pattern #1 is not bound in pattern #2
  --> file.rs:10:23
   |
10 |         T::T1(a, d) | T::T2(d, b) | T::T3(c) | T::T4(a) => { println!("{:?}", a); }
   |                       ^^^^^^^^^^^ pattern doesn't bind `a`

error[E0408]: variable `b` from pattern #2 is not bound in pattern #1
  --> file.rs:10:32
   |
10 |         T::T1(a, d) | T::T2(d, b) | T::T3(c) | T::T4(a) => { println!("{:?}", a); }
   |                                ^ pattern doesn't bind `b`

error[E0408]: variable `a` from pattern #1 is not bound in pattern #3
  --> file.rs:10:37
   |
10 |         T::T1(a, d) | T::T2(d, b) | T::T3(c) | T::T4(a) => { println!("{:?}", a); }
   |                                     ^^^^^^^^ pattern doesn't bind `a`

error[E0408]: variable `d` from pattern #1 is not bound in pattern #3
  --> file.rs:10:37
   |
10 |         T::T1(a, d) | T::T2(d, b) | T::T3(c) | T::T4(a) => { println!("{:?}", a); }
   |                                     ^^^^^^^^ pattern doesn't bind `d`

error[E0408]: variable `c` from pattern #3 is not bound in pattern #1
  --> file.rs:10:43
   |
10 |         T::T1(a, d) | T::T2(d, b) | T::T3(c) | T::T4(a) => { println!("{:?}", a); }
   |                                           ^ pattern doesn't bind `c`

error[E0408]: variable `d` from pattern #1 is not bound in pattern #4
  --> file.rs:10:48
   |
10 |         T::T1(a, d) | T::T2(d, b) | T::T3(c) | T::T4(a) => { println!("{:?}", a); }
   |                                                ^^^^^^^^ pattern doesn't bind `d`

error: aborting due to 6 previous errors
```

After:

```
error[E0408]: variable `a` is not bound in all patterns
  --> file.rs:20:37
   |
20 |         T::T1(a, d) | T::T2(d, b) | T::T3(c) | T::T4(a) => {
intln!("{:?}", a); }
   |               -       ^^^^^^^^^^^   ^^^^^^^^         - variable
t in all patterns
   |               |       |             |
   |               |       |             pattern doesn't bind `a`
   |               |       pattern doesn't bind `a`
   |               variable not in all patterns

error[E0408]: variable `d` is not bound in all patterns
  --> file.rs:20:37
   |
20 |         T::T1(a, d) | T::T2(d, b) | T::T3(c) | T::T4(a) => {
intln!("{:?}", a); }
   |                  -          -       ^^^^^^^^   ^^^^^^^^ pattern
esn't bind `d`
   |                  |          |       |
   |                  |          |       pattern doesn't bind `d`
   |                  |          variable not in all patterns
   |                  variable not in all patterns

error[E0408]: variable `b` is not bound in all patterns
  --> file.rs:20:37
   |
20 |         T::T1(a, d) | T::T2(d, b) | T::T3(c) | T::T4(a) => {
intln!("{:?}", a); }
   |         ^^^^^^^^^^^            -    ^^^^^^^^   ^^^^^^^^ pattern
esn't bind `b`
   |         |                      |    |
   |         |                      |    pattern doesn't bind `b`
   |         |                      variable not in all patterns
   |         pattern doesn't bind `b`

error[E0408]: variable `c` is not bound in all patterns
  --> file.rs:20:48
   |
20 |         T::T1(a, d) | T::T2(d, b) | T::T3(c) | T::T4(a) => {
intln!("{:?}", a); }
   |         ^^^^^^^^^^^   ^^^^^^^^^^^         -    ^^^^^^^^ pattern
esn't bind `c`
   |         |             |                   |
   |         |             |                   variable not in all
tterns
   |         |             pattern doesn't bind `c`
   |         pattern doesn't bind `c`

error: aborting due to 4 previous errors
```

* Have only one presentation for binding consistency errors
* Point to same binding in multiple patterns when possible
* Check inconsistent bindings in all arms
* Simplify wording of diagnostic message
* Sort emition and spans of binding errors for deterministic output
brson pushed a commit that referenced this pull request Mar 9, 2017
Clean up "pattern doesn't bind x" messages

Group "missing variable bind" spans in `or` matches and clarify wording
for the two possible cases: when a variable from the first pattern is
not in any of the subsequent patterns, and when a variable in any of the
other patterns is not in the first one.

Before:

```rust
error[E0408]: variable `a` from pattern #1 is not bound in pattern #2
  --> file.rs:10:23
   |
10 |         T::T1(a, d) | T::T2(d, b) | T::T3(c) | T::T4(a) => { println!("{:?}", a); }
   |                       ^^^^^^^^^^^ pattern doesn't bind `a`

error[E0408]: variable `b` from pattern #2 is not bound in pattern #1
  --> file.rs:10:32
   |
10 |         T::T1(a, d) | T::T2(d, b) | T::T3(c) | T::T4(a) => { println!("{:?}", a); }
   |                                ^ pattern doesn't bind `b`

error[E0408]: variable `a` from pattern #1 is not bound in pattern #3
  --> file.rs:10:37
   |
10 |         T::T1(a, d) | T::T2(d, b) | T::T3(c) | T::T4(a) => { println!("{:?}", a); }
   |                                     ^^^^^^^^ pattern doesn't bind `a`

error[E0408]: variable `d` from pattern #1 is not bound in pattern #3
  --> file.rs:10:37
   |
10 |         T::T1(a, d) | T::T2(d, b) | T::T3(c) | T::T4(a) => { println!("{:?}", a); }
   |                                     ^^^^^^^^ pattern doesn't bind `d`

error[E0408]: variable `c` from pattern #3 is not bound in pattern #1
  --> file.rs:10:43
   |
10 |         T::T1(a, d) | T::T2(d, b) | T::T3(c) | T::T4(a) => { println!("{:?}", a); }
   |                                           ^ pattern doesn't bind `c`

error[E0408]: variable `d` from pattern #1 is not bound in pattern #4
  --> file.rs:10:48
   |
10 |         T::T1(a, d) | T::T2(d, b) | T::T3(c) | T::T4(a) => { println!("{:?}", a); }
   |                                                ^^^^^^^^ pattern doesn't bind `d`

error: aborting due to 6 previous errors
```

After:

```rust
error[E0408]: variable `d` is not bound in all patterns
  --> $DIR/issue-39698.rs:20:37
   |
20 |         T::T1(a, d) | T::T2(d, b) | T::T3(c) | T::T4(a) => { println!("{:?}", a); }
   |                  -          -       ^^^^^^^^   ^^^^^^^^ pattern doesn't bind `d`
   |                  |          |       |
   |                  |          |       pattern doesn't bind `d`
   |                  |          variable not in all patterns
   |                  variable not in all patterns

error[E0408]: variable `c` is not bound in all patterns
  --> $DIR/issue-39698.rs:20:48
   |
20 |         T::T1(a, d) | T::T2(d, b) | T::T3(c) | T::T4(a) => { println!("{:?}", a); }
   |         ^^^^^^^^^^^   ^^^^^^^^^^^         -    ^^^^^^^^ pattern doesn't bind `c`
   |         |             |                   |
   |         |             |                   variable not in all patterns
   |         |             pattern doesn't bind `c`
   |         pattern doesn't bind `c`

error[E0408]: variable `a` is not bound in all patterns
  --> $DIR/issue-39698.rs:20:37
   |
20 |         T::T1(a, d) | T::T2(d, b) | T::T3(c) | T::T4(a) => { println!("{:?}", a); }
   |               -       ^^^^^^^^^^^   ^^^^^^^^         - variable not in all patterns
   |               |       |             |
   |               |       |             pattern doesn't bind `a`
   |               |       pattern doesn't bind `a`
   |               variable not in all patterns

error[E0408]: variable `b` is not bound in all patterns
  --> $DIR/issue-39698.rs:20:37
   |
20 |         T::T1(a, d) | T::T2(d, b) | T::T3(c) | T::T4(a) => { println!("{:?}", a); }
   |         ^^^^^^^^^^^            -    ^^^^^^^^   ^^^^^^^^ pattern doesn't bind `b`
   |         |                      |    |
   |         |                      |    pattern doesn't bind `b`
   |         |                      variable not in all patterns
   |         pattern doesn't bind `b`

error: aborting due to 4 previous errors
```

Fixes rust-lang#39698.
brson pushed a commit that referenced this pull request Jun 6, 2017
Without that flag, LLVM generates unaligned memory access instructions, which are not allowed on ARMv5.

For example, the 'hello world' example from `cargo --new` failed with:
```
$ ./hello
Hello, world!
thread 'main' panicked at 'assertion failed: end <= len', src/libcollections/vec.rs:1113
note: Run with `RUST_BACKTRACE=1` for a backtrace.
```

I traced this error back to the following assembler code in `BufWriter::flush_buf`:
```
    6f44:       e28d0018        add     r0, sp, #24
[...]
    6f54:       e280b005        add     fp, r0, #5
[...]
    7018:       e5cd001c        strb    r0, [sp, #28]
    701c:       e1a0082a        lsr     r0, sl, #16
    7020:       03a01001        moveq   r1, #1
    7024:       e5cb0002        strb    r0, [fp, #2]
    7028:       e1cba0b0        strh    sl, [fp]
```

Note that `fp` points to `sp + 29`, so the three `str*`-instructions should fill up a 32bit - value at `sp + 28`, which is later used as the value `n` in `Ok(n) => written += n`. This doesn't work on ARMv5 as the `strh` can't write to the unaligned contents of `fp`, so the upper bits of `n` won't get cleared, leading to the assertion failure in Vec::drain.

With `+strict-align`, the code works as expected.
brson pushed a commit that referenced this pull request Jun 6, 2017
ARMv5 needs +strict-align

Without that flag, LLVM generates unaligned memory access instructions, which are not allowed on ARMv5.

For example, the 'hello world' example from `cargo --new` failed with:
```
$ ./hello
Hello, world!
thread 'main' panicked at 'assertion failed: end <= len', src/libcollections/vec.rs:1113
note: Run with `RUST_BACKTRACE=1` for a backtrace.
```

I traced this error back to the following assembler code in `BufWriter::flush_buf`:
```
    6f44:       e28d0018        add     r0, sp, #24
[...]
    6f54:       e280b005        add     fp, r0, #5
[...]
    7018:       e5cd001c        strb    r0, [sp, #28]
    701c:       e1a0082a        lsr     r0, sl, #16
    7020:       03a01001        moveq   r1, #1
    7024:       e5cb0002        strb    r0, [fp, #2]
    7028:       e1cba0b0        strh    sl, [fp]
```

Note that `fp` points to `sp + 29`, so the three `str*`-instructions should fill up a 32bit - value at `sp + 28`, which is later used as the value `n` in `Ok(n) => written += n`. This doesn't work on ARMv5 as the `strh` can't write to the unaligned contents of `fp`, so the upper bits of `n` won't get cleared, leading to the assertion failure in Vec::drain.

With `+strict-align`, the code works as expected.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants