The goal here is to avoid requiring a division or multiplication to compare against the length. The bounds check previously used an incorrect micro-optimization to replace the division by a multiplication, but now neither is necessary *for slices*. Unique/managed vectors will have to do a division to get the length until they are reworked/replaced.
Remove the old path.
Rename path2 to path.
Update all clients for the new path.
Also make some miscellaneous changes to the Path APIs to help the
adoption process.
This stops labeling everything as "is private" when in fact the destination may
be public. Instead, the clause "is inaccessible" is used and the private part of
the flag is called out with a "is private" message.
Closes#9793
There's currently a fair amount of code which is being ignored on unnamed blocks
(which are the default now), and I opted to leave it commented out for now. I
intend on very soon revisiting on how we perform linking with extern crates in
an effort to support static linking.
There's currently a fair amount of code which is being ignored on unnamed blocks
(which are the default now), and I opted to leave it commented out for now. I
intend on very soon revisiting on how we perform linking with extern crates in
an effort to support static linking.
I borrow some ideas from clang's ABIInfo.h and TargetInfo.cpp.
LLVMType is replaced with ArgType, which is similar to clang's ABIArgInfo,
and I also merge attrs of FnType into it.
Now ABI implementation doesn't need to insert hidden return pointer
to arg_tys of FnType. Instead it is handled in foreign.rs.
This change also fixes LLVM assertion failure when compiling MIPS target.
This fixes a bug in which the visibility rules were approximated by
reachability, but forgot to cover the case where a 'pub use' reexports a private
item. This fixes the commit by instead using the results of the privacy pass of
the compiler to create the initial working set of the reachability pass.
This may have the side effect of increasing the size of metadata, but it's
difficult to avoid for correctness purposes sadly.
Closes#9790
This fixes a bug in which the visibility rules were approximated by
reachability, but forgot to cover the case where a 'pub use' reexports a private
item. This fixes the commit by instead using the results of the privacy pass of
the compiler to create the initial working set of the reachability pass.
This may have the side effect of increasing the size of metadata, but it's
difficult to avoid for correctness purposes sadly.
Closes#9790
Bare functions are another example of a scalar but non-numeric
type (like char) that should be handled separately in casts.
This disallows expressions like `0 as extern "Rust" fn() -> int;`.
It might be advantageous to allow casts between bare functions
and raw pointers in unsafe code in the future, to pass function
pointers between Rust and C.
Closes#8728
This disallows `str[0] = foo` along with `foo = &mut str[i]` to prevent strings
from being modified at runtime (except possibly through the `str` module)
Closes#8891
Since lint check attributes are the preferred way of selectively
enabling/disabling lint checks, the output format of a failed
default check has been changed to reflect that.
When lint checks are being explicitly set by a command-line flag
or an attribute, the behavior is unchanged, so that the user can
quickly pinpoint the source.
Closes#6580
This is the culmination and attempted resolution of #8215. The commits have many more details about implementation details and the consequences of this refinement.
I'll point out specific locations which may be possible causes for alarm. In general, I have been very happy with how things have turned out. I'm a little sad that I couldn't remove privacy from resolve as much as I did, but I blame glob imports (although in theory even some of this can be mitigated as well).
For the benefit of the pretty printer we want to keep track of how
string literals in the ast were originally represented in the source
code.
This commit changes parser functions so they don't extract strings from
the token stream without at least also returning what style of string
literal it was. This is stored in the resulting ast node for string
literals, obviously, for the package id in `extern mod = r"package id"`
view items, for the inline asm in `asm!()` invocations.
For `asm!()`'s other arguments or for `extern "Rust" fn()` items, I just
the style of string, because it seemed disproportionally cumbersome to
thread that information through the string processing that happens with
those string literals, given the limited advantage raw string literals
would provide in these positions.
The other syntax extensions don't seem to store passed string literals
in the ast, so they also discard the style of strings they parse.
This commit fixes all of the fallout of the previous commit which is an attempt
to refine privacy. There were a few unfortunate leaks which now must be plugged,
and the most horrible one is the current `shouldnt_be_public` module now inside
`std::rt`. I think that this either needs a slight reorganization of the
runtime, or otherwise it needs to just wait for the external users of these
modules to get replaced with their `rt` implementations.
Other fixes involve making things pub which should be pub, and otherwise
updating error messages that now reference privacy instead of referencing an
"unresolved name" (yay!).
This commit is the culmination of my recent effort to refine Rust's notion of
privacy and visibility among crates. The major goals of this commit were to
remove privacy checking from resolve for the sake of sane error messages, and to
attempt a much more rigid and well-tested implementation of visibility
throughout rust. The implemented rules for name visibility are:
1. Everything pub from the root namespace is visible to anyone
2. You may access any private item of your ancestors.
"Accessing a private item" depends on what the item is, so for a function this
means that you can call it, but for a module it means that you can look inside
of it. Once you look inside a private module, any accessed item must be "pub
from the root" where the new root is the private module that you looked into.
These rules required some more analysis results to get propagated from trans to
privacy in the form of a few hash tables.
I added a new test in which my goal was to showcase all of the privacy nuances
of the language, and I hope to place any new bugs into this file to prevent
regressions.
Overall, I was unable to completely remove the notion of privacy from resolve.
One use of privacy is for dealing with glob imports. Essentially a glob import
can only import *public* items from the destination, and because this must be
done at namespace resolution time, resolve must maintain the notion of "what
items are public in a module". There are some sad approximations of privacy, but
I unfortunately can't see clear methods to extract them outside.
The other use case of privacy in resolve now is one that must stick around
regardless of glob imports. When dealing with privacy, checking a private path
needs to know "what the last private thing was" when looking at a path. Resolve
is the only compiler pass which knows the answer to this question, so it
maintains the answer on a per-path resolution basis (works similarly to the
def_map generated).
Closes#8215
This pull request changes to memory layout of the `CrateMap` struct to use static slices instead of raw pointers. Most of the discussion took place [here](63b5975efa (L1R92)) .
The memory layout of CrateMap changed, without bumping the version number in the struct. Another, more backward compatible, solution would be to keep the old code and increase the version number in the new struct. On the other hand, the `annihilate_fn` pointer was removed without bumping the version number recently.
At the moment, the stage0 compiler does not use the new memory layout, which would lead the segfaults during stage0 compilation, so I've added a dummy `iter_crate_map` function for stage0, which does nothing. Again, this could be avoided if we'd bump the version number in the struct and keep the old code.
I'd like to use a normal `for` loop [here](https://github.com/fhahn/rust/compare/logging-unsafe-removal?expand=1#L1R109),
for child in children.iter() {
do_iter_crate_map(child, |x| f(x), visited);
}
but for some reason this only yields `error: unresolved enum variant, struct or const 'Some'` and I have no idea why.
This PR solves one of the pain points with c-style enums. Simplifies writing a fn to convert from an int/uint to an enum. It does this through a `#[deriving(FromPrimitive)]` syntax extension.
Before this is committed though, we need to discuss if `ToPrimitive`/`FromPrimitive` has the right design (cc #4819). I've changed all the `.to_int()` and `from_int()` style functions to return `Option<int>` so we can handle partial functions. For this PR though only enums and `extra::num::bigint::*` take advantage of returning None for unrepresentable values. In the long run it'd be better if `i64.to_i8()` returned `None` if the value was too large, but I'll save this for a future PR.
Closes#3868.
According to http://huonw.github.io/isrustfastyet/mem/#012f909, the "const
marking" pass generates about 400MB of extra memory during compilation. It
appears that this is due to two different factors:
1. There is a `ccache` map in the ty::ctxt which is only ever used in this
pass, so this commit moves the map out of the ty::ctxt struct and into
just this pass's visitor. This turned out to not benefit that much in
memory (as indicated by http://i.imgur.com/Eo4iOzK.png), but it's helpful
to do nonetheless.
2. During const_eval, there are a lot of lookups into decoding inlined items
from external crates. There is no caching involved here, so the same
static or variant could be re-translated many times. After adding
separate caches for variants and statics, the memory peak of compiling
rustc decreased by 200MB (as evident by http://i.imgur.com/ULAUMtq.png)
The culmination of this is basically a slight reorganization of a caching map
for the const_eval pass along with a 200MB decrease in peak memory usage when
compiling librustc.
Avoid cloning the stack on every `push_ctxt` call in trans
Rewrite the use of TLS variable for `push_ctxt` so that it uses a ~[]
instead of a @~[]. Before it cloned the whole vector on each push and
pop, which is unnecessary.
Rewrite the use of TLS variable for `push_ctxt` so that it uses a ~[]
instead of a @~[]. Before it cloned the whole vector on each push and
pop, which is unnecessary.
rustc: Use static strings in a few literals
Avoid allocating extra copies of strings by using "" instead of ~"" for
the debug options list and for the `time` function. This is a small
change, but it is in a path that's always executed.
Avoid allocating extra copies of strings by using "" instead of ~"" for
the debug options list and for the `time` function. This is a small
change, but it is in a path that's always executed.
This purges about 500 lines of visitor cruft from lint passes. All lints are
handled in a much more sane way at this point. The other huge bonus of this
commit is that there are no more @-boxes in the lint passes, fixing the 500MB
memory regression seen when the lint passes were refactored.
Closes#8589
This purges about 500 lines of visitor cruft from lint passes. All lints are
handled in a much more sane way at this point. The other huge bonus of this
commit is that there are no more @-boxes in the lint passes, fixing the 500MB
memory regression seen when the lint passes were refactored.
Closes#8589
This makes sure that the top-level crate name is correct when emitting log
statements for a monomorphized function in another crate. This happens by
tracing the monomorphized ID back to the external source and then using that
crate index to get the name of the crate.
Closes#3046
This fixes two existing bugs along the way:
* The `transmute` intrinsic did not correctly handle casts of immediate
aggregates like newtype structs and tuples.
* The code for calling foreign functions used the wrong type to create
an `alloca` temporary
enum Foo { A, B }
fn foo() -> Foo { A }
Before:
; Function Attrs: nounwind uwtable
define void @_ZN3foo18hbedc642d5d9cf5aag4v0.0E(%enum.Foo* noalias nocapture sret, { i64, %tydesc*, i8*, i8*, i8 }* nocapture readnone) #0 {
"function top level":
%2 = getelementptr inbounds %enum.Foo* %0, i64 0, i32 0
store i64 0, i64* %2, align 8
ret void
}
After:
; Function Attrs: nounwind readnone uwtable
define %enum.Foo @_ZN3foo18hbedc642d5d9cf5aag4v0.0E({ i64, %tydesc*, i8*, i8*, i8 }* nocapture readnone) #0 {
"function top level":
ret %enum.Foo zeroinitializer
}
It is simply defined as `f64` across every platform right now.
A use case hasn't been presented for a `float` type defined as the
highest precision floating point type implemented in hardware on the
platform. Performance-wise, using the smallest precision correct for the
use case greatly saves on cache space and allows for fitting more
numbers into SSE/AVX registers.
If there was a use case, this could be implemented as simply a type
alias or a struct thanks to `#[cfg(...)]`.
Closes#6592
The mailing list thread, for reference:
https://mail.mozilla.org/pipermail/rust-dev/2013-July/004632.html
This is mostly an incremental change, picking off some uses of
@- or @mut-pointers that can be replaced by references.
Almost all of the builder functions in trans::build are updated,
mostly using `&Block` arguments instead of `@mut Block`.
Use &mut Block and &Block references where possible in the builder
functions in trans::build.
@mut Block remains in a few functions where I could not (not yet at
least) track down the runtime borrowck failures.
std::vec: Sane implementations for connect_vec and concat_vec
Avoid unnecessary copying of subvectors, and calculate the needed space
beforehand. These implementations are simple but better than the
previous.
Also only implement it once, for all `Vector<T>` using:
impl<'self, T: Clone, V: Vector<T>> VectorVector<T> for &'self [V]
Closes#9581
This is broken, and results in poor performance due to the undefined
behaviour in the LLVM IR. LLVM's `mergefunc` is a *much* better way of
doing this since it merges based on the equality of the bytecode.
For example, consider `std::repr`. It generates different code per
type, but is not included in the type bounds of generics.
The `mergefunc` pass works for most of our code but currently hits an
assert on libstd. It is receiving attention upstream so it will be
ready soon, but I don't think removing this broken code should wait any
longer. I've opened #9536 about enabling it by default.
Closes#8651Closes#3547Closes#2537Closes#6971Closes#9222
This is broken, and results in poor performance due to the undefined
behaviour in the LLVM IR. LLVM's `mergefunc` is a *much* better way of
doing this since it merges based on the equality of the bytecode.
For example, consider `std::repr`. It generates different code per
type, but is not included in the type bounds of generics.
The `mergefunc` pass works for most of our code but currently hits an
assert on libstd. It is receiving attention upstream so it will be
ready soon, but I don't think removing this broken code should wait any
longer. I've opened #9536 about enabling it by default.
Closes#8651Closes#3547Closes#2537Closes#6971Closes#9222
If an item is skipped due to it being unreachable or for some optimization, then
it shouldn't be encoded into the metadata (because it wasn't present in the
first place).
I have tried this fix and it seems to work either with single or multiple trait inheritance.
trait Base:Base2 + Base3{
fn foo(&self);
}
trait Base2 {
fn baz(&self);
}
trait Base3{
fn root(&self);
}
trait Super: Base{
fn bar(&self);
}
struct X;
impl Base for X {
fn foo(&self) {
println("base foo");
}
}
impl Base2 for X {
fn baz(&self) {
println("base2 baz");
}
}
impl Base3 for X {
fn root(&self) {
println("base3 root");
}
}
impl Super for X {
fn bar(&self) {
println("super bar");
}
}
fn main() {
let n = X;
let s = &n as &Super;
s.bar();
s.foo(); // super bar
s.baz();
s.root();
}
bmaxa@maxa:~/examples/rust$ rustc error.rs
bmaxa@maxa:~/examples/rust$ ./error
super bar
base foo
base2 baz
base3 root
This solves problem of incorrect indexing into vtable
when method from super trait was called through pointer
to derived trait.
Problem was that offset of super trait vtables
was not calculated at all.
Now it works, correct offset is calculated by
traversing all super traits up to super trait
where method belongs. That is how it is
intended to work.
r? anyone
Part of #7081.
Removed many unnecessary context arguments, turning them into visitors. Removed some @allocation.
If this lands, then I think the only thing left that is unaddressed are:
* the various lint visitors, and
* middle/privacy.rs, which has `impl<'self> Visitor<&'self method_map> for PrivacyVisitor`
This fixes private statics and functions from being usable cross-crates, along
with some bad privacy error messages. This is a reopening of #8365 with all the
privacy checks in privacy.rs instead of resolve.rs (where they should be
anyway).
These maps of exported items will hopefully get used for generating
documentation by rustdoc
Closes#8592
This fixes private statics and functions from being usable cross-crates, along
with some bad privacy error messages. This is a reopening of #8365 with all the
privacy checks in privacy.rs instead of resolve.rs (where they should be
anyway).
These maps of exported items will hopefully get used for generating
documentation by rustdoc
Closes#8592
r? anyone
Also got rid of a bit of `@mut` allocation. (Though not the monster that is `@mut FnCtxt`; that case is documented already on #7081; if we attack it, it will probably be its own ticket, not part of #7081.)
r? anyone.
Part of #7081.
More refactorings of the syntax::visit::Visitor implementations, folding so-called "environments" into the visitor impl when the latter was previously a trivial unit struct.
As usual, this refactoring only applies when the environments are not actually carrying state that is meant to be pushed and popped as we traverse the expression. (For an example where the environment *isn't* just passed through, see the `visit_fn` in `liveness.rs`.)
Got rid of a bit of @-allocation in borrowck.
Both cases should be pure-refactorings.
Resolves third bullet of #4691: if the functional-struct-update (FSU) expression `{ a: b, ..s }` causes `s` to move and `s` has a destructor, then the expression is illegal.
r? @nikomatsakis
This is for consistency in naming conventions.
- ``std::num::Float::NaN()`` is changed to ``nan()``;
- ``std::num::Float.is_NaN()`` is changed to ``is_nan()``; and
- ``std::num::strconv::NumStrConv::NaN()`` is changed to ``nan()``.
Fixes#9319.
This is the second of two parts of #8991, now possible as a new snapshot
has been made. (The first part implemented the unreachable!() macro; it
was #8992, 6b7b8f2682.)
``std::util::unreachable()`` is removed summarily; any code which used
it should now use the ``unreachable!()`` macro.
Closes#9312.
Closes#8991.
This is for consistency in naming conventions.
- ``std::num::Float::NaN()`` is changed to ``nan()``;
- ``std::num::Float.is_NaN()`` is changed to ``is_nan()``; and
- ``std::num::strconv::NumStrConv::NaN()`` is changed to ``nan()``.
Fixes#9319.
This is the second of two parts of #8991, now possible as a new snapshot
has been made. (The first part implemented the unreachable!() macro; it
was #8992, 6b7b8f2682.)
``std::util::unreachable()`` is removed summarily; any code which used
it should now use the ``unreachable!()`` macro.
Closes#9312.
Closes#8991.
std: Remove {float,f64,f32}::from_str in favor of from_str in the prelude
Like issue #9209, remove float::{from_str, from_str_radix} in favor of
the two corresponding traits. The same for modules f64 and f32.
New usage is:
from_str::<float>("1.2e34")
Like issue #9209, remove float::{from_str, from_str_radix} in favor of
the two corresponding traits. The same for modules f64 and f32.
New usage is
from_str::<float>("1.2e34")
If a static is flagged as address_insignificant, then for LLVM to actually
perform the relevant optimization it must have an internal linkage type. What
this means, though, is that the static will not be available to other crates.
Hence, if you have a generic function with an inner static, it will fail to link
when built as a library because other crates will attempt to use the inner
static externally.
This gets around the issue by inlining the static into the metadata. The same
relevant optimization is then applied separately in the external crate. What
this ends up meaning is that all statics tagged with #[address_insignificant]
will appear at most once per crate (by value), but they could appear in multiple
crates.
This should be the last blocker for using format! ...
This doesn't close any bugs as the goal is to convert the parameter to by-value, but this is a step towards being able to make guarantees about `&T` pointers (where T is Freeze) to LLVM.
In #8185 cross-crate condition handlers were fixed by ensuring that globals
didn't start appearing in different crates with different addressed. An
unfortunate side effect of that pull request is that constants weren't inlined
across crates (uint::bits is unknown to everything but libstd).
This commit fixes this inlining by using the `available_eternally` linkage
provided by LLVM. It partially reverts #8185, and then adds support for this
linkage type. The main caveat is that not all statics could be inlined into
other crates. Before this patch, all statics were considered "inlineable items",
but an unfortunate side effect of how we deal with `&static` and `&[static]`
means that these two cases cannot be inlined across crates. The translation of
constants was modified to propogate this condition of whether a constant
should be considered inlineable into other crates.
Closes#9036
also removes the unused `FastInvoke` wrapper, as it's never actually
going to be used (we can't *partially* switch to `fastcc`, and this is
only used for Rust functions)
The `noalias` attributes were being set only on function definitions,
not on all declarations. This is harmless for `noalias`, but prevented
some optimization opportunities and is *not* harmless for other
attributes like `sret` with ABI implications.
Closes#9104
In #8185 cross-crate condition handlers were fixed by ensuring that globals
didn't start appearing in different crates with different addressed. An
unfortunate side effect of that pull request is that constants weren't inlined
across crates (uint::bits is unknown to everything but libstd).
This commit fixes this inlining by using the `available_eternally` linkage
provided by LLVM. It partially reverts #8185, and then adds support for this
linkage type. The main caveat is that not all statics could be inlined into
other crates. Before this patch, all statics were considered "inlineable items",
but an unfortunate side effect of how we deal with `&static` and `&[static]`
means that these two cases cannot be inlined across crates. The translation of
constants was modified to propogate this condition of whether a constant
should be considered inlineable into other crates.
Closes#9036
While they may have the same name within various scopes, this changes static
names to use path_pretty_name to append some hash information at the end of the
symbol. We're then guaranteed that each static has a unique NodeId, so this
NodeId is as the "hash" of the pretty name.
Closes#9188
Beforehand it was assumed that the standard cdecl abi was used for all extern
fns of extern crates, but this reads the abi of the extern fn type and declares
the function in the local crate with the appropriate type.
I was trying to think of how to write a test for this, but I was just drawing up blanks :(. Are there standard functions in libc which are not of the cdecl abi? If so we could try linking to them and make sure that the cal completes successfully.
Otherwise, I manually verified that the function was declared correctly by looking at the llvm assembly.
cc #9055 (I'm not sure if this will fix that issue)
Beforehand it was assumed that the standard cdecl abi was used for all extern
fns of extern crates, but this reads the abi of the extern fn type and declares
the function in the local crate with the appropriate type.
Also fixed nasty bug caused by calling LLVMDIBuilderCreateStructType() with a null pointer where an empty array was expected (which would trigger an unintelligable assertion somewhere down the line).
While they may have the same name within various scopes, this changes static
names to use path_pretty_name to append some hash information at the end of the
symbol. We're then guaranteed that each static has a unique NodeId, so this
NodeId is as the "hash" of the pretty name.
Closes#9188
This is a series of patches to modernize option and result. The highlights are:
* rename `.unwrap_or_default(value)` and etc to `.unwrap_or(value)`
* add `.unwrap_or_default()` that uses the `Default` trait
* add `Default` implementations for vecs, HashMap, Option
* add `Option.and(T) -> Option<T>`, `Option.and_then(&fn() -> Option<T>) -> Option<T>`, `Option.or(T) -> Option<T>`, and `Option.or_else(&fn() -> Option<T>) -> Option<T>`
* add `option::ToOption`, `option::IntoOption`, `option::AsOption`, `result::ToResult`, `result::IntoResult`, `result::AsResult`, `either::ToEither`, and `either::IntoEither`, `either::AsEither`
* renamed `Option::chain*` and `Result::chain*` to `and_then` and `or_else` to avoid the eventual collision with `Iterator.chain`.
* Added a bunch of impls of `Default`
* Added a `#[deriving(Default)]` syntax extension
* Removed impls of `Zero` for `Option<T>` and vecs.
Since function pointers do not carry along the function attributes with
them in the type, this needs to be set on the call instruction itself.
Closes#9152
This is mostly for consistency, as you can now compare raw pointers in
constant expressions or without the standard library.
It also reduces the number of `ptrtoint` instructions in the IR, making
tracking down culprits of what's usually an anti-pattern easier.
This is mostly for consistency, as you can now compare raw pointers in
constant expressions or without the standard library.
It also reduces the number of `ptrtoint` instructions in the IR, making
tracking down culprits of what's usually an anti-pattern easier.
Who would have thought that namespaces are such a can of worms `:P` This is mostly because of some GDB idiosyncrasies (does not use namespace information but linkage-name attributes for displaying items contained in namespaces, also cannot handle functions lexically nested within functions), monomorphization, and information about external items only available from metadata.
This pull request tries to tackle the problem anyway:
* The `DW_AT_linkage_name` for functions is generated just to make GDB display a proper namespace-enabled function name. To this end, a pseudo-mangled name is generated, not corresponding to the real linkage name. This approach shows some success and could be extended to make GDB also show proper parameter types.
* As GDB won't accept subprogram DIEs nested within other subprogram DIEs, the `debuginfo` module now generates a *companion namespace* for each functions (iff needed). A function `fn abc()` will get a companion namespace with name `abc()`, which contains all items (modules, types, functions) declared within the functions scope. The real, proper solution, in my opinion, would be to faithfully reflect the program's lexical structure within DWARF (which allows arbitrary nesting of DIEs, afaik), but I am not sure LLVM's source level debugging implementation would like that and I am pretty sure GDB won't support this in the foreseeable future.
* Monomorphization leads to functions and companion namespaces like `somelib::some_func<int, float>()::some_other_function<bool, bool, bool>()`, which I think is the desired behaviour. There is some design space here, however. Maybe you people prefer `somelib::some_func()::some_other_function<bool, bool, bool>()` or `somelib::some_func()::some_other_function::<int, float, bool, bool, bool>()`.
The solution will work for now but there are a few things on my 'far future wish list':
* A real specification somewhere, what language constructs are mapped to what DWARF structures.
* Proper tests that directly compare the generated DWARF information to the expected results (possibly using something like [pyelftools](https://github.com/eliben/pyelftools) or llvm-dwarfdump)
* A unified implementation for crate-local and crate-external items (which would possibly involve beefing up `ast_map::path` and metadata a bit)
Any comments are welcome!
Closes#1541Closes#1542 (there might be other issues with function name prettiness, but this specific issue should be fixed)
Closes#7715 (source locations for structs and enums are now read correctly from the AST)