This defers to .fatal and .span_fatal for errors (rather than `fail!`
which prints the ICE message). It also adds the span lookup when an id
doesn't correspond to a block, to show what it is pointing at.
It also makes the argument parser slightly looser, so that passing
`--pretty flowgraph` recognises the `flowgraph` part and suggests to use
an integer.
This plugs a leak where resolve was treating enums defined in parent modules as
in-scope for all children modules when resolving a pattern identifier. This
eliminates the code path in resolve entirely.
If this breaks any existing code, then it indicates that the variants need to be
explicitly imported into the module.
Closes#14221
This plugs a leak where resolve was treating enums defined in parent modules as
in-scope for all children modules when resolving a pattern identifier. This
eliminates the code path in resolve entirely.
If this breaks any existing code, then it indicates that the variants need to be
explicitly imported into the module.
Closes#14221
[breaking-change]
Passing `--pretty flowgraph=<NODEID>` makes rustc print a control flow graph.
In pratice, you will also need to pass the additional option:
`-o <FILE>` to emit output to a `.dot` file for graphviz.
(You can only print the flow-graph for a particular block in the AST.)
----
An interesting implementation detail is the way the code puts both the
node index (`cfg::CFGIndex`) and a reference to the payload
(`cfg::CFGNode`) into the single `Node` type that is used for
labelling and walking the graph. I had once mistakenly thought that I
only wanted the `cfg::CFGNode`, but for labelling, you really want the
cfg index too, rather than e.g. trying to use the `ast::NodeId` as the
label (which breaks down e.g. due to `ast::DUMMY_NODE_ID`).
----
As a drive-by fix, I had to fix `rustc::middle::cfg::construct`
interface to reflect changes that have happened on the master branch
while I was getting this integrated into the compiler. (The next
commit actually adds tests of the `--pretty flowgraph` functionality,
so that should ensure that the `rustc::middle::cfg` code does not go
stale again.)
The core library in theory has 0 dependencies, but in practice it has some in
order for it to be efficient. These dependencies are in the form of the basic
memory operations provided by libc traditionally, such as memset, memcmp, etc.
These functions are trivial to implement and themselves have 0 dependencies.
This commit adds a new crate, librlibc, which will serve the purpose of
providing these dependencies. The crate is never linked to by default, but is
available to be linked to by downstream consumers. Normally these functions are
provided by the system libc, but in other freestanding contexts a libc may not
be available. In these cases, librlibc will suffice for enabling execution with
libcore.
cc #10116
This adds the flag --color, which allows the user to force coloring or
turn it off. The default behavior stays the same as before (colorize, if
output goes to tty).
Why this is beneficial is explained in issue #12881.
Please note that this commit doesn't include any regression tests. I
thought about how I'd write a test for this and it doesn't seem to be
worth the effort to me for a UI change like this.
Fixes#12881.
There's no need to include this specific flag just for android. We can
already deal with what it tries to solve by using -C linker=/path/to/cc
and -C ar=/path/to/ar. The Makefiles for rustc already set this up when
we're crosscompiling.
I did add the flag to compiletest though so it can find gdb. Though, I'm
pretty sure we don't run debuginfo tests on android anyways right now.
[breaking-change]
The goal of this refactoring is to make the rustc driver code easier to understand and use. Since this is as close to an API as we have, I think it is important that it is nice. On getting stuck in, I found that there wasn't as much to change as I'd hoped to make the stage... fns easier to use by tools.
This patch only moves code around - mostly just moving code to different files, but a few extracted method refactorings too. To summarise the changes: I added driver::config which handles everything about configuring the compiler. driver::session now just defines and builds session objects. I moved driver code from librustc/lib.rs to librustc/driver/mod.rs so all the code is one place. I extracted methods to make emulating the compiler without being the compiler a little easier. Within the driver directory, I moved code around to more logically fit in the modules.
for `~str`/`~[]`.
Note that `~self` still remains, since I forgot to add support for
`Box<self>` before the snapshot.
How to update your code:
* Instead of `~EXPR`, you should write `box EXPR`.
* Instead of `~TYPE`, you should write `Box<Type>`.
* Instead of `~PATTERN`, you should write `box PATTERN`.
[breaking-change]
Currently, rustc requires that a linkage be a product of 100% rlibs or 100%
dylibs. This is to satisfy the requirement that each object appear at most once
in the final output products. This is a bit limiting, and the upcoming libcore
library cannot exist as a dylib, so these rules must change.
The goal of this commit is to enable *some* use cases for mixing rlibs and
dylibs, primarily libcore's use case. It is not targeted at allowing an
exhaustive number of linkage flavors.
There is a new dependency_format module in rustc which calculates what format
each upstream library should be linked as in each output type of the current
unit of compilation. The module itself contains many gory details about what's
going on here.
cc #10729
This has long since not been too relevant since the introduction of many crate
type outputs. This commit removes the flag entirely, adjusting all logic to do
the most reasonable thing when building both a library and an executable.
Closes#13337
This has long since not been too relevant since the introduction of many crate
type outputs. This commit removes the flag entirely, adjusting all logic to do
the most reasonable thing when building both a library and an executable.
Closes#13337
Currently, rustc requires that a linkage be a product of 100% rlibs or 100%
dylibs. This is to satisfy the requirement that each object appear at most once
in the final output products. This is a bit limiting, and the upcoming libcore
library cannot exist as a dylib, so these rules must change.
The goal of this commit is to enable *some* use cases for mixing rlibs and
dylibs, primarily libcore's use case. It is not targeted at allowing an
exhaustive number of linkage flavors.
There is a new dependency_format module in rustc which calculates what format
each upstream library should be linked as in each output type of the current
unit of compilation. The module itself contains many gory details about what's
going on here.
cc #10729
Pre-step towards issue #12624 and others: Introduce ExprUseVisitor, remove the
moves computation. ExprUseVisitor is a visitor that walks the AST for a
function and calls a delegate to inform it where borrows, copies, and moves
occur.
In this patch, I rewrite the gather_loans visitor to use ExprUseVisitor, but in
future patches, I think we could rewrite regionck, check_loans, and possibly
other passes to use it as well. This would refactor the repeated code between
those places that tries to determine where copies/moves/etc occur.
r? @alexcrichton
When a syntax extension is loaded by the compiler, the dylib that is opened may
have other dylibs that it depends on. The dynamic linker must be able to find
these libraries on the system or else the library will fail to load.
Currently, unix gets by with the use of rpaths. This relies on the dylib not
moving around too drastically relative to its dependencies. For windows,
however, this is no rpath available, and in theory unix should work without
rpaths as well.
This modifies the compiler to add all -L search directories to the dynamic
linker's set of load paths. This is currently managed through environment
variables for each platform.
Closes#13848
moves computation. ExprUseVisitor is a visitor that walks the AST for a
function and calls a delegate to inform it where borrows, copies, and moves
occur.
In this patch, I rewrite the gather_loans visitor to use ExprUseVisitor, but in
future patches, I think we could rewrite regionck, check_loans, and possibly
other passes to use it as well. This would refactor the repeated code between
those places that tries to determine where copies/moves/etc occur.
This patch removes the special auto-rooting for `@` from the borrow checker. With `@` moving into a library, it doesn't make sense to keep this code around anymore. It also simplifies `trans` by removing root checking from there
@nikomatsakis
Closes: #11586
This adds the target triple to the crate metadata.
When searching for a crate the phase (link, syntax) is taken into account.
During link phase only crates matching the target triple are considered.
During syntax phase, either the target or host triple will be accepted, unless
the crate defines a macro_registrar, in which case only the host triple will
match.
Before, the `--crate-file-name` flag only checked crate attributes for
possible crate types. Now, if any type is specified by one or more
`--crate-type` flags, only the filenames for those types will be
emitted, and any types specified by crate attributes will be ignored.
Before, normal compilation and the --crate-file-name flag would
generate output based on both #![crate_type] attributes and
--crate-type flags. Now, if one or more flag is specified by command
line, only those will be used.
Closes#11573.
This bug was introduced in #13384 by accident, and this commit continues the
work of #13384 by finishing support for loading a syntax extension crate without
registering it with the local cstore.
Closes#13495
When linking, all crates in the local CStore are used to link the final product.
With #[phase(syntax)], crates want to be omitted from this linkage phase, and
this was achieved by dumping the entire CStore after loading crates. This causes
crates like the standard library to get loaded twice. This loading process is a
fairly expensive operation when dealing with decompressing metadata.
This commit alters the loading process to never register syntax crates in
CStore. Instead, only phase(link) crates ever make their way into the map of
crates. The CrateLoader trait was altered to return everything in one method
instead of having separate methods for finding information.
`Reader`, `Writer`, `MemReader`, `MemWriter`, and `MultiWriter` now work with `Vec<u8>` instead of `~[u8]`. This does introduce some extra copies since `from_utf8_owned` isn't usable anymore, but I think that can't be helped until `~str`'s representation changes.
Rust currently defaults to `RelocPIC` regardless. This patch adds a new
codegen option that allows choosing different relocation-model. The
available models are:
- default (Use the target-specific default model)
- static
- pic
- no-pic
For a more detailed information use `llc --help`
Rust currently defaults to `RelocPIC` regardless. This patch adds a new
codegen option that allows choosing different relocation-model. The
available models are:
- default (Use the target-specific default model)
- static
- pic
- no-pic
For a more detailed information use `llc --help`
rustc: move the check_loop pass earlier.
This pass is purely AST based, and by running it earlier we emit more
useful error messages, e.g. type inference fails in the case of
`let r = break;` with few constraints on `r`, but it's more useful to be told that
the `break` is outside the loop (rather than a type error) when it is.
Closes#13292.
Fix#13266.
There is a little bit of acrobatics in the definition of `crate_paths`
to avoid calling `clone()` on the dylib/rlib unless we actually are
going to need them.
The other oddity is that I have replaced the `root_ident: Option<&str>`
parameter with a `root: &Option<CratePaths>`, which may surprise one
who was expecting to see something like: `root: Option<&CratePaths>`.
I went with the approach here because I could not come up with code for
the alternative that was acceptable to the borrow checker.
Add way to print notes with just file:linenum prefix (preserving
integration with source lookup for e.g. vi and emacs) but don't repeat
the other span info.
This pass is purely AST based, and by running it earlier we emit more
useful error messages, e.g. type inference fails in the case of `let r =
break;` with few constraints on `r`, but its more useful to be told that
the `break` is outside a loop (rather than a type error) when it is.
Closes#13292.
A variety of stuff here, mostly aimed at making `make install` work correctly with `--libdir` and `--mandir`. `make install` again goes through `install.sh`.
These are superfluous now that we have fixed rvalue lifetimes and Deref.
I'd also like to kill off `get` and `set`, but that'll be a large change so I want to make sure that we actually want to do that first.
The pretty printer constitues an enormous amount of code, there's no reason for
it to be generic. This just least to a huge amount of metadata which isn't
necessary. Instead, this change migrates the pretty printer to using a trait
object instead.
Closes#12985
This takes the time for `rustc libstd/lib.rs -Z ast-json-noexpand >
file.json` from 9.0s to 3.5s (~0.5s spent parsing etc.) and `-Z
ast-json` from 11s to 5s (~1.5s spent parsing and expanding).
This commit moves all logging out of the standard library into an external
crate. This crate is the new crate which is responsible for all logging macros
and logging implementation. A few reasons for this change are:
* The crate map has always been a bit of a code smell among rust programs. It
has difficulty being loaded on almost all platforms, and it's used almost
exclusively for logging and only logging. Removing the crate map is one of the
end goals of this movement.
* The compiler has a fair bit of special support for logging. It has the
__log_level() expression as well as generating a global word per module
specifying the log level. This is unfairly favoring the built-in logging
system, and is much better done purely in libraries instead of the compiler
itself.
* Initialization of logging is much easier to do if there is no reliance on a
magical crate map being available to set module log levels.
* If the logging library can be written outside of the standard library, there's
no reason that it shouldn't be. It's likely that we're not going to build the
highest quality logging library of all time, so third-party libraries should
be able to provide just as high-quality logging systems as the default one
provided in the rust distribution.
With a migration such as this, the change does not come for free. There are some
subtle changes in the behavior of liblog vs the previous logging macros:
* The core change of this migration is that there is no longer a physical
log-level per module. This concept is still emulated (it is quite useful), but
there is now only a global log level, not a local one. This global log level
is a reflection of the maximum of all log levels specified. The previously
generated logging code looked like:
if specified_level <= __module_log_level() {
println!(...)
}
The newly generated code looks like:
if specified_level <= ::log::LOG_LEVEL {
if ::log::module_enabled(module_path!()) {
println!(...)
}
}
Notably, the first layer of checking is still intended to be "super fast" in
that it's just a load of a global word and a compare. The second layer of
checking is executed to determine if the current module does indeed have
logging turned on.
This means that if any module has a debug log level turned on, all modules
with debug log levels get a little bit slower (they all do more expensive
dynamic checks to determine if they're turned on or not).
Semantically, this migration brings no change in this respect, but
runtime-wise, this will have a perf impact on some code.
* A `RUST_LOG=::help` directive will no longer print out a list of all modules
that can be logged. This is because the crate map will no longer specify the
log levels of all modules, so the list of modules is not known. Additionally,
warnings can no longer be provided if a malformed logging directive was
supplied.
The new "hello world" for logging looks like:
#[phase(syntax, link)]
extern crate log;
fn main() {
debug!("Hello, world!");
}
The `~str` type is not long for this world as it will be superseded by the
soon-to-come DST changes for the language. The new type will be
`~Str`, and matching over the allocation will no longer be supported.
Matching on `&str` will continue to work, in both a pre and post DST world.
The `-g` flag does not take an argument anymore while the argument to `--debuginfo` becomes mandatory. This change makes it possible again to run the compiler like this:
`rustc -g ./file.rs`
This did not work before because `./file.rs` was misinterpreted as the argument to `-g`. In order to get limited debuginfo, one now has to use `--debuginfo=1`.
* `Ord` inherits from `Eq`
* `TotalOrd` inherits from `TotalEq`
* `TotalOrd` inherits from `Ord`
* `TotalEq` inherits from `Eq`
This is a partial implementation of #12517.
If #[feature(default_type_parameters)] is enabled for a crate, then
deriving(Hash) will expand with Hash<W: Writer> instead of Hash<SipState> so
more hash algorithms can be used.
This leverages the new hashing framework and hashmap implementation to provide a
much speedier hashing algorithm for node ids and def ids. The hash algorithm
used is currentl FNV hashing, but it's quite easy to swap out.
I originally implemented hashing as the identity function, but this actually
ended up in slowing down rustc compiling libstd from 8s to 13s. I would suspect
that this is a result of a large number of collisions.
With FNV hashing, we get these timings (compiling with --no-trans, in seconds):
| | before | after |
|-----------|---------:|--------:|
| libstd | 8.324 | 6.703 |
| stdtest | 47.674 | 46.857 |
| libsyntax | 9.918 | 8.400 |
This commit alters the diagnostic emission machinery to be focused around a
Writer for emitting errors. This allows it to not hard-code emission of errors
to stderr (useful for other applications).
This new SVH is used to uniquely identify all crates as a snapshot in time of
their ABI/API/publicly reachable state. This current calculation is just a hash
of the entire crate's AST. This is obviously incorrect, but it is currently the
reality for today.
This change threads through the new Svh structure which originates from crate
dependencies. The concept of crate id hash is preserved to provide efficient
matching on filenames for crate loading. The inspected hash once crate metadata
is opened has been changed to use the new Svh.
The goal of this hash is to identify when upstream crates have changed but
downstream crates have not been recompiled. This will prevent the def-id drift
problem where upstream crates were recompiled, thereby changing their metadata,
but downstream crates were not recompiled.
In the future this hash can be expanded to exclude contents of the AST like doc
comments, but limitations in the compiler prevent this change from being made at
this time.
Closes#10207
- For each *mutable* static item, check that the **type**:
- cannot own any value whose type has a dtor
- cannot own any values whose type is an owned pointer
- For each *immutable* static item, check that the **value**:
- does not contain any ~ or box expressions
(including ~[1, 2, 3] sort of things)
- does not contain a struct literal or call to an enum
variant / struct constructor where
- the type of the struct/enum has a dtor
These two containers are indeed collections, so their place is in
libcollections, not in libstd. There will always be a hash map as part of the
standard distribution of Rust, but by moving it out of the standard library it
makes libstd that much more portable to more platforms and environments.
This conveniently also removes the stuttering of 'std::hashmap::HashMap',
although 'collections::HashMap' is only one character shorter.
This "bubble up an error" macro was originally named if_ok! in order to get it
landed, but after the fact it was discovered that this name is not exactly
desirable.
The name `if_ok!` isn't immediately clear that is has much to do with error
handling, and it doesn't look fantastic in all contexts (if if_ok!(...) {}). In
general, the agreed opinion about `if_ok!` is that is came in as subpar.
The name `try!` is more invocative of error handling, it's shorter by 2 letters,
and it looks fitting in almost all circumstances. One concern about the word
`try!` is that it's too invocative of exceptions, but the belief is that this
will be overcome with documentation and examples.
Close#12037
This is mostly useful for working on rustc, when one is unfamiliar with the
AST a particular construct will produce. It's a -Z flag as it's very much for
debugging.
Closes#10485
This patch replaces all `crate` usage with `krate` before introducing the
new keyword. This ensures that after introducing the keyword, there
won't be any compilation errors.
krate might not be the most expressive substitution for crate but it's a
very close abbreviation for it. `module` was already used in several
places already.
Error messages cleaned in librustc/middle
Error messages cleaned in libsyntax
Error messages cleaned in libsyntax more agressively
Error messages cleaned in librustc more aggressively
Fixed affected tests
Fixed other failing tests
Last failing tests fixed
This commit removes the -c, --emit-llvm, -s, --rlib, --dylib, --staticlib,
--lib, and --bin flags from rustc, adding the following flags:
* --emit=[asm,ir,bc,obj,link]
* --crate-type=[dylib,rlib,staticlib,bin,lib]
The -o option has also been redefined to be used for *all* flavors of outputs.
This means that we no longer ignore it for libraries. The --out-dir remains the
same as before.
The new logic for files that rustc emits is as follows:
1. Output types are dictated by the --emit flag. The default value is
--emit=link, and this option can be passed multiple times and have all options
stacked on one another.
2. Crate types are dictated by the --crate-type flag and the #[crate_type]
attribute. The flags can be passed many times and stack with the crate
attribute.
3. If the -o flag is specified, and only one output type is specified, the
output will be emitted at this location. If more than one output type is
specified, then the filename of -o is ignored, and all output goes in the
directory that -o specifies. The -o option always ignores the --out-dir
option.
4. If the --out-dir flag is specified, all output goes in this directory.
5. If -o and --out-dir are both not present, all output goes in the directory of
the crate file.
6. When multiple output types are specified, the filestem of all output is the
same as the name of the CrateId (derived from a crate attribute or from the
filestem of the crate file).
Closes#7791Closes#11056Closes#11667
This commit removes the -c, --emit-llvm, -s, --rlib, --dylib, --staticlib,
--lib, and --bin flags from rustc, adding the following flags:
* --emit=[asm,ir,bc,obj,link]
* --crate-type=[dylib,rlib,staticlib,bin,lib]
The -o option has also been redefined to be used for *all* flavors of outputs.
This means that we no longer ignore it for libraries. The --out-dir remains the
same as before.
The new logic for files that rustc emits is as follows:
1. Output types are dictated by the --emit flag. The default value is
--emit=link, and this option can be passed multiple times and have all
options stacked on one another.
2. Crate types are dictated by the --crate-type flag and the #[crate_type]
attribute. The flags can be passed many times and stack with the crate
attribute.
3. If the -o flag is specified, and only one output type is specified, the
output will be emitted at this location. If more than one output type is
specified, then the filename of -o is ignored, and all output goes in the
directory that -o specifies. The -o option always ignores the --out-dir
option.
4. If the --out-dir flag is specified, all output goes in this directory.
5. If -o and --out-dir are both not present, all output goes in the current
directory of the process.
6. When multiple output types are specified, the filestem of all output is the
same as the name of the CrateId (derived from a crate attribute or from the
filestem of the crate file).
Closes#7791Closes#11056Closes#11667
They all have to go into a single module at the moment unfortunately.
Ideally, the logging macros would live in std::logging, condition! would
live in std::condition, format! in std::fmt, etc. However, this
introduces cyclic dependencies between those modules and the macros they
use which the current expansion system can't deal with. We may be able
to get around this by changing the expansion phase to a two-pass system
but that's for a later PR.
Closes#2247
cc #11763
By default, the compiler and libraries are all still built with rpaths, but this
can be opted out of with --disable-rpath to ./configure or --no-rpath to rustc.
Closes#5219
By default, the compiler and libraries are all still built with rpaths, but this
can be opted out of with --disable-rpath to ./configure or --no-rpath to rustc.
cc #5219
They all have to go into a single module at the moment unfortunately.
Ideally, the logging macros would live in std::logging, condition! would
live in std::condition, format! in std::fmt, etc. However, this
introduces cyclic dependencies between those modules and the macros they
use which the current expansion system can't deal with. We may be able
to get around this by changing the expansion phase to a two-pass system
but that's for a later PR.
Closes#2247
cc #11763
A mutable and immutable borrow place some restrictions on what you can
with the variable until the borrow ends. This commit attempts to convey
to the user what those restrictions are. Also, if the original borrow is
a mutable borrow, the error message has been changed (more specifically,
i. "cannot borrow `x` as immutable because it is also borrowed as
mutable" and ii. "cannot borrow `x` as mutable more than once" have
been changed to "cannot borrow `x` because it is already borrowed as
mutable").
In addition, this adds a (custom) span note to communicate where the
original borrow ends.
```rust
fn main() {
match true {
true => {
let mut x = 1;
let y = &x;
let z = &mut x;
}
false => ()
}
}
test.rs:6:21: 6:27 error: cannot borrow `x` as mutable because it is already borrowed as immutable
test.rs:6 let z = &mut x;
^~~~~~
test.rs:5:21: 5:23 note: previous borrow of `x` occurs here; the immutable borrow prevents subsequent moves or mutable borrows of `x` until the borrow ends
test.rs:5 let y = &x;
^~
test.rs:7:10: 7:10 note: previous borrow ends here
test.rs:3 true => {
test.rs:4 let mut x = 1;
test.rs:5 let y = &x;
test.rs:6 let z = &mut x;
test.rs:7 }
^
```
```rust
fn foo3(t0: &mut &mut int) {
let t1 = &mut *t0;
let p: &int = &**t0;
}
fn main() {}
test.rs:3:19: 3:24 error: cannot borrow `**t0` because it is already borrowed as mutable
test.rs:3 let p: &int = &**t0;
^~~~~
test.rs:2:14: 2:22 note: previous borrow of `**t0` as mutable occurs here; the mutable borrow prevents subsequent moves, borrows, or modification of `**t0` until the borrow ends
test.rs:2 let t1 = &mut *t0;
^~~~~~~~
test.rs:4:2: 4:2 note: previous borrow ends here
test.rs:1 fn foo3(t0: &mut &mut int) {
test.rs:2 let t1 = &mut *t0;
test.rs:3 let p: &int = &**t0;
test.rs:4 }
^
```
For the "previous borrow ends here" note, if the span is too long (has too many lines), then only the first and last lines are printed, and the middle is replaced with dot dot dot:
```rust
fn foo3(t0: &mut &mut int) {
let t1 = &mut *t0;
let p: &int = &**t0;
}
fn main() {}
test.rs:3:19: 3:24 error: cannot borrow `**t0` because it is already borrowed as mutable
test.rs:3 let p: &int = &**t0;
^~~~~
test.rs:2:14: 2:22 note: previous borrow of `**t0` as mutable occurs here; the mutable borrow prevents subsequent moves, borrows, or modification of `**t0` until the borrow ends
test.rs:2 let t1 = &mut *t0;
^~~~~~~~
test.rs:7:2: 7:2 note: previous borrow ends here
test.rs:1 fn foo3(t0: &mut &mut int) {
...
test.rs:7 }
^
```
(Sidenote: the `span_end_note` currently also has issue #11715)
A mutable and immutable borrow place some restrictions on what you can
with the variable until the borrow ends. This commit attempts to convey
to the user what those restrictions are. Also, if the original borrow is
a mutable borrow, the error message has been changed (more specifically,
i. "cannot borrow `x` as immutable because it is also borrowed as
mutable" and ii. "cannot borrow `x` as mutable more than once" have
been changed to "cannot borrow `x` because it is already borrowed as
mutable").
In addition, this adds a (custom) span note to communicate where the
original borrow ends.
To build for the cortex-M series ARM processors LLC needs to be told to build for the thumb instruction set. There are two ways to do this, either with the triple "thumb\*-\*-\*" or with -march=thumb (which just overrides the triple anyway). I chose the first way.
The following will fail because the local cc doesn't know what to do with -mthumb.
````
rustc test.rs --lib --target thumb-linux-eab
error: linking with `cc` failed: exit code: 1
note: cc: error: unrecognized command line option ‘-mthumb’
````
Changing the linker works as expected.
````
rustc test.rs --lib --target thumb-linux-eabi --linker arm-none-eabi-gcc
````
Ideally I'd have the triple thumb-none-eabi, but adding a new OS looks like much more work (and I'm not familiar enough with what it does to know if it is needed).