This hack has long since outlived its usefulness; the transition to
trans passing around full substitutions is basically done. Instead of
`ErasedRegions`, just supply substitutions with a suitable number of
`'static` entries, and invoke `erase_regions` when needed (the latter of
which we already do).
Automated conversion using the untry tool [1] and the following command:
```
$ find -name '*.rs' -type f | xargs untry
```
at the root of the Rust repo.
[1]: https://github.com/japaric/untry
projection sensitive to "mode" (most importantly, trans vs middle).
This commit introduces several pieces of iteration infrastructure in the
specialization graph data structure, as well as various helpers for
finding the definition of a given item, given its kind and name.
In addition, associated type projection is now *mode-sensitive*, with
three possible modes:
- **Topmost**. This means that projection is only possible if there is a
non-`default` definition of the associated type directly on the
selected impl. This mode is a bit of a hack: it's used during early
coherence checking before we have built the specialization
graph (and therefore before we can walk up the specialization
parents to find other definitions). Eventually, this should be
replaced with a less "staged" construction of the specialization
graph.
- **AnyFinal**. Projection succeeds for any non-`default` associated
type definition, even if it is defined by a parent impl. Used
throughout typechecking.
- **Any**. Projection always succeeds. Used by trans.
The lasting distinction here is between `AnyFinal` and `Any` -- we wish
to treat `default` associated types opaquely for typechecking purposes.
In addition to the above, the commit includes a few other minor review fixes.
- Rewrites the overlap checker to instead build up a specialization
graph, checking for overlap errors in the process.
- Use the specialization order during impl selection.
This commit does not yet handle associated types correctly, and assumes
that all items are `default` and are overridden.
typestrong const integers
~~It would be great if someone could run crater on this PR, as this has a high danger of breaking valid code~~ Crater ran. Good to go.
----
So this PR does a few things:
1. ~~const eval array values when const evaluating an array expression~~
2. ~~const eval repeat value when const evaluating a repeat expression~~
3. ~~const eval all struct and tuple fields when evaluating a struct/tuple expression~~
4. remove the `ConstVal::Int` and `ConstVal::Uint` variants and replace them with a single enum (`ConstInt`) which has variants for all integral types
* `usize`/`isize` are also enums with variants for 32 and 64 bit. At creation and various usage steps there are assertions in place checking if the target bitwidth matches with the chosen enum variant
5. enum discriminants (`ty::Disr`) are now `ConstInt`
6. trans has its own `Disr` type now (newtype around `u64`)
This obviously can't be done without breaking changes (the ones that are noticable in stable)
We could probably write lints that find those situations and error on it for a cycle or two. But then again, those situations are rare and really bugs imo anyway:
```rust
let v10 = 10 as i8;
let v4 = 4 as isize;
assert_eq!(v10 << v4 as usize, 160 as i8);
```
stops compiling because 160 is not a valid i8
```rust
struct S<T, S> {
a: T,
b: u8,
c: S
}
let s = S { a: 0xff_ff_ff_ffu32, b: 1, c: 0xaa_aa_aa_aa as i32 };
```
stops compiling because `0xaa_aa_aa_aa` is not a valid i32
----
cc @eddyb @pnkfelix
related: https://github.com/rust-lang/rfcs/issues/1071
Distinguish fn item types to allow reification from nothing to fn pointers.
The first commit is a rebase of #26284, except for files that have moved since.
This is a [breaking-change], due to:
* each FFI function has a distinct type, like all other functions currently do
* all generic parameters on functions are recorded in their item types, e.g.:
`size_of::<u8>` & `size_of::<i8>`'s types differ despite their identical signature.
* function items are zero-sized, which will stop transmutes from working on them
The first two cases are handled in most cases with the new coerce-unify logic,
which will combine incompatible function item types into function pointers,
at the outer-most level of if-else chains, match arms and array literals.
The last case is specially handled during type-checking such that transmutes
from a function item type to a pointer or integer type will continue to work for
another release cycle, but are being linted against. To get rid of warnings and
ensure your code will continue to compile, cast to a pointer before transmuting.
There's a lot of stuff wrong with the representation of these types:
TyFnDef doesn't actually uniquely identify a function, TyFnPtr is used to
represent method calls, TyFnDef in the sub-expression of a cast isn't
correctly reified, and probably some other stuff I haven't discovered yet.
Splitting them seems like the right first step, though.
This PR privacy checks paths as they are resolved instead of in `librustc_privacy` (fixes#12334 and fixes#31779). This removes the need for the `LastPrivate` system introduced in PR #9735, the limitations of which cause #31779.
This PR also reports privacy violations in paths to intra- and inter-crate items the same way -- it always reports the first inaccessible segment of the path.
Since it fixes#31779, this is a [breaking-change]. For example, the following code would break:
```rust
mod foo {
pub use foo::bar::S;
mod bar { // `bar` should be private to `foo`
pub struct S;
}
}
impl foo::S {
fn f() {}
}
fn main() {
foo::bar::S::f(); // This is now a privacy error
}
```
r? @alexcrichton
This commit is the result of the FCPs ending for the 1.8 release cycle for both
the libs and the lang suteams. The full list of changes are:
Stabilized
* `braced_empty_structs`
* `augmented_assignments`
* `str::encode_utf16` - renamed from `utf16_units`
* `str::EncodeUtf16` - renamed from `Utf16Units`
* `Ref::map`
* `RefMut::map`
* `ptr::drop_in_place`
* `time::Instant`
* `time::SystemTime`
* `{Instant,SystemTime}::now`
* `{Instant,SystemTime}::duration_since` - renamed from `duration_from_earlier`
* `{Instant,SystemTime}::elapsed`
* Various `Add`/`Sub` impls for `Time` and `SystemTime`
* `SystemTimeError`
* `SystemTimeError::duration`
* Various impls for `SystemTimeError`
* `UNIX_EPOCH`
* `ops::{Add,Sub,Mul,Div,Rem,BitAnd,BitOr,BitXor,Shl,Shr}Assign`
Deprecated
* Scoped TLS (the `scoped_thread_local!` macro)
* `Ref::filter_map`
* `RefMut::filter_map`
* `RwLockReadGuard::map`
* `RwLockWriteGuard::map`
* `Condvar::wait_timeout_with`
Closes#27714Closes#27715Closes#27746Closes#27748Closes#27908Closes#29866
The standard library doesn't depend on rustc_bitflags, so move it to explicit
dependencies on all other crates. Additionally, the arena/fmt_macros deps could
be dropped from libsyntax.
The standard library doesn't depend on rustc_bitflags, so move it to explicit
dependencies on all other crates. Additionally, the arena/fmt_macros deps could
be dropped from libsyntax.
The scope of these refactorings is a little bit bigger than the title implies. See each commit for details.
I’m submitting this for nitpicking now (the first 4 commits), because I feel the basic idea/implementation is sound and should work. I will eventually expand this PR to cover the translator changes necessary for all this to work (+ tests), ~~and perhaps implement a dynamic dropping scheme while I’m at it as well.~~
r? @nikomatsakis
These commits perform a few high-level changes with the goal of enabling i686 MSVC unwinding:
* LLVM is upgraded to pick up the new exception handling instructions and intrinsics for MSVC. This puts us somewhere along the 3.8 branch, but we should still be compatible with LLVM 3.7 for non-MSVC targets.
* All unwinding for MSVC targets (both 32 and 64-bit) are implemented in terms of this new LLVM support. I would like to also extend this to Windows GNU targets to drop the runtime dependencies we have on MinGW, but I'd like to land this first.
* Some tests were fixed up for i686 MSVC here and there where necessary. The full test suite should be passing now for that target.
In terms of landing this I plan to have this go through first, then verify that i686 MSVC works, then I'll enable `make check` on the bots for that target instead of just `make` as-is today.
Closes#25869
This brings some routine upgrades to the bundled LLVM that we're using, the most
notable of which is a bug fix to the way we handle range asserts when loading
the discriminant of an enum. This fix ended up being very similar to f9d4149c
where we basically can't have a range assert when loading a discriminant due to
filling drop, and appropriate flags were added to communicate this to
`trans::adt`.
The purpose of the translation item collector is to find all monomorphic instances of functions, methods and statics that need to be translated into LLVM IR in order to compile the current crate.
So far these instances have been discovered lazily during the trans path. For incremental compilation we want to know the set of these instances in advance, and that is what the trans::collect module provides.
In the future, incremental and regular translation will be driven by the collector implemented here.
r? @nikomatsakis
cc @rust-lang/compiler
Translation Item Collection
===========================
This module is responsible for discovering all items that will contribute to
to code generation of the crate. The important part here is that it not only
needs to find syntax-level items (functions, structs, etc) but also all
their monomorphized instantiations. Every non-generic, non-const function
maps to one LLVM artifact. Every generic function can produce
from zero to N artifacts, depending on the sets of type arguments it
is instantiated with.
This also applies to generic items from other crates: A generic definition
in crate X might produce monomorphizations that are compiled into crate Y.
We also have to collect these here.
The following kinds of "translation items" are handled here:
- Functions
- Methods
- Closures
- Statics
- Drop glue
The following things also result in LLVM artifacts, but are not collected
here, since we instantiate them locally on demand when needed in a given
codegen unit:
- Constants
- Vtables
- Object Shims
General Algorithm
-----------------
Let's define some terms first:
- A "translation item" is something that results in a function or global in
the LLVM IR of a codegen unit. Translation items do not stand on their
own, they can reference other translation items. For example, if function
`foo()` calls function `bar()` then the translation item for `foo()`
references the translation item for function `bar()`. In general, the
definition for translation item A referencing a translation item B is that
the LLVM artifact produced for A references the LLVM artifact produced
for B.
- Translation items and the references between them for a directed graph,
where the translation items are the nodes and references form the edges.
Let's call this graph the "translation item graph".
- The translation item graph for a program contains all translation items
that are needed in order to produce the complete LLVM IR of the program.
The purpose of the algorithm implemented in this module is to build the
translation item graph for the current crate. It runs in two phases:
1. Discover the roots of the graph by traversing the HIR of the crate.
2. Starting from the roots, find neighboring nodes by inspecting the MIR
representation of the item corresponding to a given node, until no more
new nodes are found.
The roots of the translation item graph correspond to the non-generic
syntactic items in the source code. We find them by walking the HIR of the
crate, and whenever we hit upon a function, method, or static item, we
create a translation item consisting of the items DefId and, since we only
consider non-generic items, an empty type-substitution set.
Given a translation item node, we can discover neighbors by inspecting its
MIR. We walk the MIR and any time we hit upon something that signifies a
reference to another translation item, we have found a neighbor. Since the
translation item we are currently at is always monomorphic, we also know the
concrete type arguments of its neighbors, and so all neighbors again will be
monomorphic. The specific forms a reference to a neighboring node can take
in MIR are quite diverse. Here is an overview:
The most obvious form of one translation item referencing another is a
function or method call (represented by a CALL terminator in MIR). But
calls are not the only thing that might introduce a reference between two
function translation items, and as we will see below, they are just a
specialized of the form described next, and consequently will don't get any
special treatment in the algorithm.
A function does not need to actually be called in order to be a neighbor of
another function. It suffices to just take a reference in order to introduce
an edge. Consider the following example:
```rust
fn print_val<T: Display>(x: T) {
println!("{}", x);
}
fn call_fn(f: &Fn(i32), x: i32) {
f(x);
}
fn main() {
let print_i32 = print_val::<i32>;
call_fn(&print_i32, 0);
}
```
The MIR of none of these functions will contain an explicit call to
`print_val::<i32>`. Nonetheless, in order to translate this program, we need
an instance of this function. Thus, whenever we encounter a function or
method in operand position, we treat it as a neighbor of the current
translation item. Calls are just a special case of that.
In a way, closures are a simple case. Since every closure object needs to be
constructed somewhere, we can reliably discover them by observing
`RValue::Aggregate` expressions with `AggregateKind::Closure`. This is also
true for closures inlined from other crates.
Drop glue translation items are introduced by MIR drop-statements. The
generated translation item will again have drop-glue item neighbors if the
type to be dropped contains nested values that also need to be dropped. It
might also have a function item neighbor for the explicit `Drop::drop`
implementation of its type.
A subtle way of introducing neighbor edges is by casting to a trait object.
Since the resulting fat-pointer contains a reference to a vtable, we need to
instantiate all object-save methods of the trait, as we need to store
pointers to these functions even if they never get called anywhere. This can
be seen as a special case of taking a function reference.
Since `Box` expression have special compiler support, no explicit calls to
`exchange_malloc()` and `exchange_free()` may show up in MIR, even if the
compiler will generate them. We have to observe `Rvalue::Box` expressions
and Box-typed drop-statements for that purpose.
Interaction with Cross-Crate Inlining
-------------------------------------
The binary of a crate will not only contain machine code for the items
defined in the source code of that crate. It will also contain monomorphic
instantiations of any extern generic functions and of functions marked with
The collection algorithm handles this more or less transparently. When
constructing a neighbor node for an item, the algorithm will always call
`inline::get_local_instance()` before proceeding. If no local instance can
be acquired (e.g. for a function that is just linked to) no node is created;
which is exactly what we want, since no machine code should be generated in
the current crate for such an item. On the other hand, if we can
successfully inline the function, we subsequently can just treat it like a
local item, walking it's MIR et cetera.
Eager and Lazy Collection Mode
------------------------------
Translation item collection can be performed in one of two modes:
- Lazy mode means that items will only be instantiated when actually
referenced. The goal is to produce the least amount of machine code
possible.
- Eager mode is meant to be used in conjunction with incremental compilation
where a stable set of translation items is more important than a minimal
one. Thus, eager mode will instantiate drop-glue for every drop-able type
in the crate, even of no drop call for that type exists (yet). It will
also instantiate default implementations of trait methods, something that
otherwise is only done on demand.
Open Issues
-----------
Some things are not yet fully implemented in the current version of this
module.
Since no MIR is constructed yet for initializer expressions of constants and
statics we cannot inspect these properly.
Ideally, no translation item should be generated for const fns unless there
is a call to them that cannot be evaluated at compile time. At the moment
this is not implemented however: a translation item will be produced
regardless of whether it is actually needed or not.
<!-- Reviewable:start -->
[<img src="https://reviewable.io/review_button.png" height=40 alt="Review on Reviewable"/>](https://reviewable.io/reviews/rust-lang/rust/30900)
<!-- Reviewable:end -->
This commit removes the `-D warnings` flag being passed through the makefiles to
all crates to instead be a crate attribute. We want these attributes always
applied for all our standard builds, and this is more amenable to Cargo-based
builds as well.
Note that all `deny(warnings)` attributes are gated with a `cfg(stage0)`
attribute currently to match the same semantics we have today
The purpose of the translation item collector is to find all monomorphic instances of functions, methods and statics that need to be translated into LLVM IR in order to compile the current crate.
So far these instances have been discovered lazily during the trans path. For incremental compilation we want to know the set of these instances in advance, and that is what the trans::collect module provides.
In the future, incremental and regular translation will be driven by the collector implemented here.
This commit removes the `-D warnings` flag being passed through the makefiles to
all crates to instead be a crate attribute. We want these attributes always
applied for all our standard builds, and this is more amenable to Cargo-based
builds as well.
Note that all `deny(warnings)` attributes are gated with a `cfg(stage0)`
attribute currently to match the same semantics we have today
libfoo.a -> foo.lib
In order to not cause conflicts, changes the DLL import library name
foo.lib -> foo.dll.lib
Fixes https://github.com/rust-lang/rust/issues/29508
Because this changes output filenames this is a [breaking-change]
Signed-off-by: Peter Atashian <retep998@gmail.com>
This PR changes the `emit_opaque` and `read_opaque` methods in the RBML library to use a space-efficient binary encoder that does not emit any tags and uses the LEB128 variable-length integer format for all numbers it emits.
The space savings are nice, albeit a bit underwhelming, especially for dynamic libraries where metadata is already compressed.
| RLIBs | NEW | OLD |
|--------------|--------|-----------|
|libstd | 8.8 MB | 10.5 MB |
|libcore |15.6 MB | 19.7 MB |
|libcollections| 3.7 MB | 4.8 MB |
|librustc |34.0 MB | 37.8 MB |
|libsyntax |28.3 MB | 32.1 MB |
| SOs | NEW | OLD |
|---------------|-----------|--------|
| libstd | 4.8 MB | 5.1 MB |
| librustc | 8.6 MB | 9.2 MB |
| libsyntax | 7.8 MB | 8.4 MB |
At least this should make up for the size increase caused recently by also storing MIR in crate metadata.
Can this be a breaking change for anyone?
cc @rust-lang/compiler
This fixes a bug in which unused imports can get wrongly marked as used when checking for unused qualifications in `resolve_path` (issue #30078), and it removes unused imports that were previously undetected because of the bug.
Ensure borrows of fn/closure params do not outlive invocations.
Does this by adding a new CallSiteScope to the region (or rather code extent) hierarchy, which outlives even the ParameterScope (which in turn outlives the DestructionScope of a fn/closure's body).
Fix#29793
r? @nikomatsakis
We can now handle name resolution errors and get past type checking (if we're a bit lucky). This is the first step towards doing code completion for partial programs (we need error recovery in the parser and early access to save-analysis).
resolve_lifetime.rs: Switch from BlockScope to FnScope in ScopeChain
construction. Lifetimes introduced by a fn signature are scoped to the
call-site for that fn. (Note `add_scope_and_walk_fn` must only add
FnScope for the walk of body, *not* of the fn signature.)
region.rs: Introduce new CodeExtentData::CallSiteScope variant. Use
CodeExtentData as the cx.parent, rather than just a NodeId. Change
DestructionScopeData to CallSiteScopeData.
regionck.rs: Thread call_site_scope via Rcx; constrain fn return
values.
(update; incorporated review feedback from niko.)
With this commit, metadata encoding and decoding can make use of thread-local encoding and decoding contexts. These allow implementers of `serialize::Encodable` and `Decodable` to access information and
datastructures that would otherwise not be available to them. For example, we can automatically translate def-id and span information during decoding because the decoding context knows which crate the data is decoded from. Or it allows to make `ty::Ty` decodable because the context has access to the `ty::ctxt` that is needed for creating `ty::Ty` instances.
Some notes:
- `tls::with_encoding_context()` and `tls::with_decoding_context()` (as opposed to their unsafe versions) try to prevent the TLS data getting out-of-sync by making sure that the encoder/decoder passed in is actually the same as the one stored in the context. This should prevent accidentally reading from the wrong decoder.
- There are no real tests in this PR. I had a unit tests for some of the core aspects of the TLS implementation but it was kind of brittle, a lot of code for mocking `ty::ctxt`, `crate_metadata`, etc and did actually test not so much. The code will soon be tested by the first incremental compilation auto-tests that rely on MIR being properly serialized. However, if people think that some tests should be added before this can land, I'll try to provide some that make sense.
r? @nikomatsakis
With this commit, metadata encoding and decoding can make use of
thread-local encoding and decoding contexts. These allow implementers
of serialize::Encodable and Decodable to access information and
datastructures that would otherwise not be available to them. For
example, we can automatically translate def-id and span information
during decoding because the decoding context knows which crate the
data is decoded from. Or it allows to make ty::Ty decodable because
the context has access to the ty::ctxt that is needed for creating
ty::Ty instances.
I've measured the time/memory consumption before and after - the difference is lost in statistical noise, so it's mostly a code simplification.
Sizes of `enum`s are not affected.
r? @nrc
I wonder if AST/HIR visitors could run faster if `P`s are systematically removed (except for cases where they control `enum` sizes). Theoretically they should.
Remaining unnecessary `P`s can't be easily removed because many folders accept `P<X>`s as arguments, but these folders can be converted to accept `X`s instead without loss of efficiency.
When I have a mood for some mindless refactoring again, I'll probably try to convert the folders, remove remaining `P`s and measure again.
This commit is the standard API stabilization commit for the 1.6 release cycle.
The list of issues and APIs below have all been through their cycle-long FCP and
the libs team decisions are listed below
Stabilized APIs
* `Read::read_exact`
* `ErrorKind::UnexpectedEof` (renamed from `UnexpectedEOF`)
* libcore -- this was a bit of a nuanced stabilization, the crate itself is now
marked as `#[stable]` and the methods appearing via traits for primitives like
`char` and `str` are now also marked as stable. Note that the extension traits
themeselves are marked as unstable as they're imported via the prelude. The
`try!` macro was also moved from the standard library into libcore to have the
same interface. Otherwise the functions all have copied stability from the
standard library now.
* The `#![no_std]` attribute
* `fs::DirBuilder`
* `fs::DirBuilder::new`
* `fs::DirBuilder::recursive`
* `fs::DirBuilder::create`
* `os::unix::fs::DirBuilderExt`
* `os::unix::fs::DirBuilderExt::mode`
* `vec::Drain`
* `vec::Vec::drain`
* `string::Drain`
* `string::String::drain`
* `vec_deque::Drain`
* `vec_deque::VecDeque::drain`
* `collections::hash_map::Drain`
* `collections::hash_map::HashMap::drain`
* `collections::hash_set::Drain`
* `collections::hash_set::HashSet::drain`
* `collections::binary_heap::Drain`
* `collections::binary_heap::BinaryHeap::drain`
* `Vec::extend_from_slice` (renamed from `push_all`)
* `Mutex::get_mut`
* `Mutex::into_inner`
* `RwLock::get_mut`
* `RwLock::into_inner`
* `Iterator::min_by_key` (renamed from `min_by`)
* `Iterator::max_by_key` (renamed from `max_by`)
Deprecated APIs
* `ErrorKind::UnexpectedEOF` (renamed to `UnexpectedEof`)
* `OsString::from_bytes`
* `OsStr::to_cstring`
* `OsStr::to_bytes`
* `fs::walk_dir` and `fs::WalkDir`
* `path::Components::peek`
* `slice::bytes::MutableByteVector`
* `slice::bytes::copy_memory`
* `Vec::push_all` (renamed to `extend_from_slice`)
* `Duration::span`
* `IpAddr`
* `SocketAddr::ip`
* `Read::tee`
* `io::Tee`
* `Write::broadcast`
* `io::Broadcast`
* `Iterator::min_by` (renamed to `min_by_key`)
* `Iterator::max_by` (renamed to `max_by_key`)
* `net::lookup_addr`
New APIs (still unstable)
* `<[T]>::sort_by_key` (added to mirror `min_by_key`)
Closes#27585Closes#27704Closes#27707Closes#27710Closes#27711Closes#27727Closes#27740Closes#27744Closes#27799Closes#27801
cc #27801 (doesn't close as `Chars` is still unstable)
Closes#28968
The local item-path includes the local crates path to the extern crate
declaration which breaks cross-crate rustdoc links if the extern crate
is not linked into the crate root or renamed via `extern foo as bar`.