Implement cannot-assume-parametricity (CAP) from RFC 1238, and add the
UGEH attribute.
----
Note that we check for the attribute attached to the dtor method, not
the Drop impl.
(This is just to match the specification of RFC and the tests; I am
not wedded to this approach.)
By RFC1214:
> Before calling a fn, we check that its argument and return types are WF.
The previous code only checked the trait-ref, which was not enough
in several cases.
As this is a soundness fix, it is a [breaking-change]. Some new annotations are needed, which I think are because of #18653 and the imperfection of `projection_must_outlive` (that can probably be worked around by moving the wf obligation later).
Fixes#28609
r? @nikomatsakis
libcore.rlib reduced from 19121 kiB to 15934 kiB - 20% win.
The librustc encoded AST is 9013500 bytes long - for the record, librustc consists of about 2254126 characters. Might be worth looking at.
r? @eddyb
The behavior here isn't really ideal, but we can't really do much better
given the current state of constant evaluation.
The changes to ExprUseVisitor are to avoid a compile error; apparently
that bit of code is extremely sensitive to changes in other areas of the
compiler.
Fixes#28670, and probably a bunch of duplicates.
have always been returning None anyway, since it was comparing node-ids
across crates incorrectly -- and remove the now unused map
`extern_const_variants`
paths, and construct paths for all definitions. Also, stop rewriting
DefIds for closures, and instead just load the closure data from
the original def-id, which may be in another crate.
were returned, either the trait or the *self type itself*, were not
particularly representative of what the Def is (a type parameter).
Rewrite paths to handle this case specially, just as they handle the
primitive case specifically. This entire `def_id` codepath is kind of a
mess.
The behavior here isn't really ideal, but we can't really do much better
given the current state of constant evaluation.
Fixes#28670, and probably a bunch of duplicates.
this simplifies the code while reducing the size of libcore.rlib by
3.3 MiB (~1M of which is bloat a separate patch of mine removes
too), while reducing rustc memory usage on small crates by 18MiB.
This also simplifies the code considerably.
This prevents ICEs when old crates are used with a new version of
rustc. Currently, the linking of crates compiled with different
versions of rustc is completely unsupported.
Fixes#28700
r? @nrc
Because of type inference, duplicate obligations exist and cause duplicate
errors. To avoid this, only display the first error for each (predicate,span).
The inclusion of the span is somewhat bikesheddy, but *is* the more
conservative option (it does not remove some instability, as duplicate
obligations are ignored by `duplicate_set` under some inference conditions).
Fixes#28098
cc #21528 (is it a dupe?)
This PR removes random remaining `Ident`s outside of libsyntax and performs general cleanup
In particular, interfaces of `Name` and `Ident` are tidied up, `Name`s and `Ident`s being small `Copy` aggregates are always passed to functions by value, and `Ident`s are never used as keys in maps, because `Ident` comparisons are tricky.
Although this PR closes https://github.com/rust-lang/rust/issues/6993 there's still work related to it:
- `Name` can be made `NonZero` to compress numerous `Option<Name>`s and `Option<Ident>`s but it requires const unsafe functions.
- Implementation of `PartialEq` on `Ident` should be eliminated and replaced with explicit hygienic, non-hygienic or member-wise comparisons.
- Finally, large parts of AST can potentially be converted to `Name`s in the same way as HIR to clearly separate identifiers used in hygienic and non-hygienic contexts.
r? @nrc
Make sure Name, SyntaxContext and Ident are passed by value
Make sure Idents don't serve as keys (or parts of keys) in maps, Ident comparison is not well defined
Part of https://github.com/rust-lang/rust/issues/6993
This patch replaces `Ident`s with `Name`s in data structures of HIR and updates the dependent crates to compile and pass `make check`.
Some HIR structures still use `Ident`s, namely `PathSegment`, `PatIdent`, `ExprWhile`, `ExprLoop`, `ExprBreak` and `ExprAgain`, they need them for resolve (but `PathSegment` is special, see https://github.com/rust-lang/rust/issues/6993#issuecomment-141256292).
r? @nrc
Fixes#28279.
Currently
`common_supertype(*mut for<'a> Fn(&'a usize), *mut for<'a> Fn(&'a usize) + 'static)`
equals `*mut Fn(&usize)` which seems to be caused by `higher_ranked_sub()` allowing region variables to escape the comparison. This prevents inference from working properly with stuff like `Rc<Fn(&T)>`.
r? @nikomatsakis
new error style:
```
path.rs:4:6: 4:7 error: the trait `core::marker::Sized` is not implemented for the type `[u8]` [E0277]
path.rs:4 fn f(p: Path) {}
^
path.rs:4:6: 4:7 help: run `rustc --explain E0277` to see a detailed explanation
path.rs:4:6: 4:7 note: `[u8]` does not have a constant size known at compile-time
path.rs:4:6: 4:7 note: required because it appears within the type `std::sys::os_str::Slice`
path.rs:4:6: 4:7 note: required because it appears within the type `std::ffi::os_str::OsStr`
path.rs:4:6: 4:7 note: required because it appears within the type `std::path::Path`
path.rs:4:6: 4:7 note: all local variables must have a statically known size
path.rs:7:5: 7:36 error: the trait `core::marker::Send` is not implemented for the type `alloc::rc::Rc<()>` [E0277]
path.rs:7 foo::<BTreeMap<Rc<()>, Rc<()>>>();
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
path.rs:7:5: 7:36 help: run `rustc --explain E0277` to see a detailed explanation
path.rs:7:5: 7:36 note: `alloc::rc::Rc<()>` cannot be sent between threads safely
path.rs:7:5: 7:36 note: required because it appears within the type `collections::btree::node::Node<alloc::rc::Rc<()>, alloc::rc::Rc<()>>`
path.rs:7:5: 7:36 note: required because it appears within the type `collections::btree::map::BTreeMap<alloc::rc::Rc<()>, alloc::rc::Rc<()>>`
path.rs:7:5: 7:36 note: required by `foo`
error: aborting due to 2 previous errors
```
Fixes#21793Fixes#23286
r? @nikomatsakis
The sort key is a (DefId, Name), which is *not* stable between
runs, so we must re-sort when loading.
Fixes#24063Fixes#25467Fixes#27222Fixes#28377
r? @eddyb
new error style:
```
path.rs:4:6: 4:7 error: the trait `core::marker::Sized` is not implemented for the type `[u8]` [E0277]
path.rs:4 fn f(p: Path) {}
^
path.rs:4:6: 4:7 help: run `rustc --explain E0277` to see a detailed explanation
path.rs:4:6: 4:7 note: `[u8]` does not have a constant size known at compile-time
path.rs:4:6: 4:7 note: required because it appears within the type `std::sys::os_str::Slice`
path.rs:4:6: 4:7 note: required because it appears within the type `std::ffi::os_str::OsStr`
path.rs:4:6: 4:7 note: required because it appears within the type `std::path::Path`
path.rs:4:6: 4:7 note: all local variables must have a statically known size
path.rs:7:5: 7:36 error: the trait `core::marker::Send` is not implemented for the type `alloc::rc::Rc<()>` [E0277]
path.rs:7 foo::<BTreeMap<Rc<()>, Rc<()>>>();
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
path.rs:7:5: 7:36 help: run `rustc --explain E0277` to see a detailed explanation
path.rs:7:5: 7:36 note: `alloc::rc::Rc<()>` cannot be sent between threads safely
path.rs:7:5: 7:36 note: required because it appears within the type `collections::btree::node::Node<alloc::rc::Rc<()>, alloc::rc::Rc<()>>`
path.rs:7:5: 7:36 note: required because it appears within the type `collections::btree::map::BTreeMap<alloc::rc::Rc<()>, alloc::rc::Rc<()>>`
path.rs:7:5: 7:36 note: required by `foo`
error: aborting due to 2 previous errors
```
This improves the #21793/#23286 situation
this resolves type-variables early in assemble_candidates and
bails out quickly if the self type is an inference variable (which would
fail anyway because of `assemble_candidates_from_projected_tys`).
In both these cases, `assemble_candidates_from_impls` would try to go
over all impls and match them, leading to O(`n*m`) performance. Fixing this
improves rustc type-checking performance by 10%. As type-checking is only
is 5% of compilation, this doesn't impact bootstrap times, but *does*
improve type-error-detection time which is nice.
Crates that have many dependencies and contain significant amounts of
generic functions could see a bigger perf boost. As a microbenchmark,
the crate generated by
```
echo '#![feature(rustc_private)]'
echo 'extern crate rustc_driver;'
for i in {1..1000}; do cat << _EOF_
pub fn foo$i<T>() {
let mut v = Vec::new();
let _w = v.clone();
v.push("");
}
_EOF_
done
```
sees performance improve from 7.2 to 1.4 seconds. I imagine many crates
would fall somewhere in-between.
r? @nikomatsakis
this resolves type-variables early in assemble_candidates and
bails out quickly if the self type is an inference variable (which would
fail anyway because of `assemble_candidates_from_projected_tys`).
In both these cases, `assemble_candidates_from_impls` would try to go
over all impls and match them, leading to O(n*m) performance. Fixing this
improves rustc type-checking performance by 10%. As type-checking is only
is 5% of compilation, this doesn't impact bootstrap times, but *does*
improve type-error-detection time which is nice.
Crates that have many dependencies and contain significant amounts of
generic functions could see a bigger perf boost. As a microbenchmark,
the crate generated by
echo '#![feature(rustc_private)]'
echo 'extern crate rustc_driver;'
for i in {1..1000}; do cat << _EOF_
pub fn foo$i<T>() {
let mut v = Vec::new();
let _w = v.clone();
v.push("");
}
_EOF_
done
sees performance improve from 7.2 to 1.4 seconds. I imagine many crates
would fall somewhere in-between.
* Suppresses warnings that main is unused when testing (#12327)
* Makes `--test` work with explicit `#[start]` (#11766)
* Fixes some cases where the normal main would not be disabled by `--test`, resulting in compilation failures.
This increases regionck performance greatly - type-checking on
librustc decreased from 9.1s to 8.1s. Because of Amdahl's law,
total performance is improved only by about 1.5% (LLVM wizards,
this is your opportunity to shine!).
before:
576.91user 4.26system 7:42.36elapsed 125%CPU (0avgtext+0avgdata 1142192maxresident)k
after:
566.50user 4.84system 7:36.84elapsed 125%CPU (0avgtext+0avgdata 1124304maxresident)k
I am somewhat worried really need to find out why we have this Red Queen's
Race going on here. Originally I suspected it may be a problem from RFC1214's
warnings, but it seems to be an effect from other changes.
However, the increase seems to be mostly in LLVM's time, so I guess
it's the LLVM wizards' problem.
Since enums are namespaced now, should we also remove the `Fk` prefixes from `FnKind` and remove the reexport? (The reexport must be removed because otherwise it clashes with glob imports containing `ItemFn`). IMO writing `FnKind::Method` is much clearer than `FkMethod`.
also, use the right caching logic for type_moves_by_default (this was
broken by @jroesch).
```
before:
593.10user 5.21system 7:51.41elapsed 126%CPU (0avgtext+0avgdata 1150016maxresident)k
after:
567.03user 4.00system 7:28.23elapsed 127%CPU (0avgtext+0avgdata 1133112maxresident)k
```
A nice 4.5% improvement. For reference, on the last run LLVM takes 429.267s, which is 75% - hopefully this can be reduced.
I think the regression since #27751 is because of the wf patch - need to investigate it through.
r? @nikomatsakis
Just a little code cleanup I was doing as part of another refactoring (which may turn out not to be needed). The main thrust of this is to cleanup the interface to `tydecode.rs` to be less ridiculously repetitive. I also purged the generic "def-id conversion" parameter in favor of a trait object, just to reduce code duplication a bit and make the signatures a bit less messy. I measured the bootstrapping time to build stage2 with these changes, it was identical. (But it'd be easy enough to restore the unboxed closure if we wanted it.)
This commit is an implementation of [RFC 1183][rfc] which allows swapping out
the default allocator on nightly Rust. No new stable surface area should be
added as a part of this commit.
[rfc]: https://github.com/rust-lang/rfcs/pull/1183
Two new attributes have been added to the compiler:
* `#![needs_allocator]` - this is used by liballoc (and likely only liballoc) to
indicate that it requires an allocator crate to be in scope.
* `#![allocator]` - this is a indicator that the crate is an allocator which can
satisfy the `needs_allocator` attribute above.
The ABI of the allocator crate is defined to be a set of symbols that implement
the standard Rust allocation/deallocation functions. The symbols are not
currently checked for exhaustiveness or typechecked. There are also a number of
restrictions on these crates:
* An allocator crate cannot transitively depend on a crate that is flagged as
needing an allocator (e.g. allocator crates can't depend on liballoc).
* There can only be one explicitly linked allocator in a final image.
* If no allocator is explicitly requested one will be injected on behalf of the
compiler. Binaries and Rust dylibs will use jemalloc by default where
available and staticlibs/other dylibs will use the system allocator by
default.
Two allocators are provided by the distribution by default, `alloc_system` and
`alloc_jemalloc` which operate as advertised.
Closes#27389
`implicator`. These definitions are also in accordance with RFC 1214 (or
more so), and hence somewhat different from the implicator. This commit
also modifies the implicator to remove the older rules for projections,
which can easily trigger infinite loops.
This commit removes all morestack support from the compiler which entails:
* Segmented stacks are no longer emitted in codegen.
* We no longer build or distribute libmorestack.a
* The `stack_exhausted` lang item is no longer required
The only current use of the segmented stack support in LLVM is to detect stack
overflow. This is no longer really required, however, because we already have
guard pages for all threads and registered signal handlers watching for a
segfault on those pages (to print out a stack overflow message). Additionally,
major platforms (aka Windows) already don't use morestack.
This means that Rust is by default less likely to catch stack overflows because
if a function takes up more than one page of stack space it won't hit the guard
page. This is what the purpose of morestack was (to catch this case), but it's
better served with stack probes which have more cross platform support and no
runtime support necessary. Until LLVM supports this for all platform it looks
like morestack isn't really buying us much.
cc #16012 (still need stack probes)
Closes#26458 (a drive-by fix to help diagnostics on stack overflow)
r? @brson
This commit removes all morestack support from the compiler which entails:
* Segmented stacks are no longer emitted in codegen.
* We no longer build or distribute libmorestack.a
* The `stack_exhausted` lang item is no longer required
The only current use of the segmented stack support in LLVM is to detect stack
overflow. This is no longer really required, however, because we already have
guard pages for all threads and registered signal handlers watching for a
segfault on those pages (to print out a stack overflow message). Additionally,
major platforms (aka Windows) already don't use morestack.
This means that Rust is by default less likely to catch stack overflows because
if a function takes up more than one page of stack space it won't hit the guard
page. This is what the purpose of morestack was (to catch this case), but it's
better served with stack probes which have more cross platform support and no
runtime support necessary. Until LLVM supports this for all platform it looks
like morestack isn't really buying us much.
cc #16012 (still need stack probes)
Closes#26458 (a drive-by fix to help diagnostics on stack overflow)
After #26694, the overloaded operator and "impl not known at method lookup time" cases started triggering the lint.
I've also added checks for overloaded autoderef and method calls via paths (i.e. `T::method()`).
All new 8 test cases did not trigger the lint before #26694.
r? @huonw
Many of these have long since reached their stage of being obsolete, so this
commit starts the removal process for all of them. The unstable features that
were deprecated are:
* box_heap
* cmp_partial
* fs_time
* hash_default
* int_slice
* iter_min_max
* iter_reset_fuse
* iter_to_vec
* map_in_place
* move_from
* owned_ascii_ext
* page_size
* read_and_zero
* scan_state
* slice_chars
* slice_position_elem
* subslice_offset
Many of these have long since reached their stage of being obsolete, so this
commit starts the removal process for all of them. The unstable features that
were deprecated are:
* cmp_partial
* fs_time
* hash_default
* int_slice
* iter_min_max
* iter_reset_fuse
* iter_to_vec
* map_in_place
* move_from
* owned_ascii_ext
* page_size
* read_and_zero
* scan_state
* slice_chars
* slice_position_elem
* subslice_offset
This does two things:
* removes ast::LocalSource, where only one variant was used because for-loop expansion has changed. One reason that this slipped into here is because the code in `check_local` which checks for `LocalSource::LocalFor` would report the same error as in `check_exhaustive` while using the wrong error code (E0005 instead of E0297).
* silences the warning about already used diagnostic code E0005 (fixes#27279)
passes `make check` locally.
`LocalSource` indicated wether a let binding originated from for-loop desugaring to enable specialized error messages, but for-loop expansion has changed and this is now achieved through `MatchSource::ForLoopDesugar`.
The algorithm was not correctly detecting conflicts after moving
defaults into TypeVariableValue. The updated algorithm
correctly detects and reports conflicts with information about
where the conflict occured and which items the defaults were
introduced by. The span's for said items are not being correctly
attached and still need to be patched.
This patch allows type parameter defaults to influence type inference. This is a possible breaking change since it effects the way type inference works and will have different behavior when mixing defaults and literal fallback.
Correct regression in type-inference caused by failing to reconfirm that
the object trait matches the required trait during trait selection. The
existing code was checking that the object trait WOULD match (in a
probe), but never executing the match outside of a probe.
This corrects various regressions observed in the wild, including
issue #26952. Fixes#26952.
r? @eddyb
cc @frankmcsherry
***Edit: Fixed now.*** I'm pretty sure the way I'm using LLVMReplaceAllUsesWith here is
unsafe... but before I figure out how to fix that, I'd like a
reality-check: is this actually useful?
I'll be adding more commits to this PR as the weekend progresses. Was hoping to make this a mega-PR, but getting some eyes on this early would be nice too.
r? @steveklabnik
r? @eddyb on the object safety bits
cc @michaelsproul
Part of #24407
Hi all.
This is my first contribution to Rust and fixes an issue causing an invalid error message to be presented to the user when using unit struct as length of a repeat expression, issue #27008. The solution is based on suggestions by @oli-obk, but as I'm a complete newbie to this, I have no clue if I got them right :)
The biggest concern I have is that if the `NodeId` I'm returning is the correct one or not (it's not meaningful in this case but I think it would be nice to get it right).
Refactors the "desugaring" of closures to expose the types of the upvars. This is necessary to be faithful with how actual structs work. The reasoning of the particular desugaring that I chose is explained in a fairly detailed comment.
As a side-effect, recursive closure types are prohibited unless a trait object intermediary is used. This fixes#25954 and also eliminates concerns about unrepresentable closure types that have infinite size, I believe. I don't believe this can cause regressions because of #25954.
(As for motivation, besides #25954 etc, this work is also intended as refactoring in support of incremental compilation, since closures are one of the thornier cases encountered when attempting to split node-ids into item-ids and within-item-ids. The goal is to eliminate the "internal def-id" distinction in astdecoding. However, I have to do more work on trans to really make progress there.)
r? @nrc
the object trait matches the required trait during trait selection. The
existing code was checking that the object trait WOULD match (in a
probe), but never executing the match outside of a probe.
This corrects various regressions observed in the wild, including
issue #26952. Fixes#26952.
Macro desugaring of `in PLACE { BLOCK }` into "simpler" expressions following the in-development "Placer" protocol.
Includes Placer API that one can override to integrate support for `in` into one's own type. (See [RFC 809].)
[RFC 809]: https://github.com/rust-lang/rfcs/blob/master/text/0809-box-and-in-for-stdlib.md
Part of #22181
Replaced PR #26180.
Turns on the `in PLACE { BLOCK }` syntax, while leaving in support for the old `box (PLACE) EXPR` syntax (since we need to support that at least until we have a snapshot with support for `in PLACE { BLOCK }`.
(Note that we are not 100% committed to the `in PLACE { BLOCK }` syntax. In particular I still want to play around with some other alternatives. Still, I want to get the fundamental framework for the protocol landed so we can play with implementing it for non `Box` types.)
----
Also, this PR leaves out support for desugaring-based `box EXPR`. We will hopefully land that in the future, but for the short term there are type-inference issues injected by that change that we want to resolve separately.
is being used now before the final regionck stage and in some cases SOME
amount of unresolved inference is OK. In fact, we could probably just
allow inference variables as well with only minimal pain.
TyClosure variant; thread this through wherever closure substitutions
are expected, which leads to a net simplification. Simplify trans
treatment of closures in particular.
Makes the lint a bit more accurate, and improves the quality of the diagnostic
messages by explicitly returning an error message.
The new lint is also a little more aggressive: specifically, it now
rejects tuples, and it recurses into function pointers.
Even after expansion, the generated expressions still track depth of
such pushes (i.e. how often you have "pushed" without a corresponding
"pop"), and we add a rule that in a context with a positive
`push_unsafe!` depth, it is effectively an `unsafe` block context.
(This way, we can inject code that uses `unsafe` features, but still
contains within it a sub-expression that should inherit the outer
safety checking setting, outside of the injected code.)
This is a total hack; it not only needs a feature-gate, but probably
should be feature-gated forever (if possible).
ignore-pretty in test/run-pass/pushpop-unsafe-okay.rs
The "hint" mechanism is essentially used as a workaround to compute
types for expressions which have not yet been type-checked. This
commit clarifies that usage, and limits the effects to the places
where it is currently necessary.
Fixes#26210.
This commit moves the IR files in the distribution, rust_try.ll,
rust_try_msvc_64.ll, and rust_try_msvc_32.ll into the compiler from the main
distribution. There's a few reasons for this change:
* LLVM changes its IR syntax from time to time, so it's very difficult to
have these files build across many LLVM versions simultaneously. We'll likely
want to retain this ability for quite some time into the future.
* The implementation of these files is closely tied to the compiler and runtime
itself, so it makes sense to fold it into a location which can do more
platform-specific checks for various implementation details (such as MSVC 32
vs 64-bit).
* This removes LLVM as a build-time dependency of the standard library. This may
end up becoming very useful if we move towards building the standard library
with Cargo.
In the immediate future, however, this commit should restore compatibility with
LLVM 3.5 and 3.6.
This commit moves the IR files in the distribution, rust_try.ll,
rust_try_msvc_64.ll, and rust_try_msvc_32.ll into the compiler from the main
distribution. There's a few reasons for this change:
* LLVM changes its IR syntax from time to time, so it's very difficult to
have these files build across many LLVM versions simultaneously. We'll likely
want to retain this ability for quite some time into the future.
* The implementation of these files is closely tied to the compiler and runtime
itself, so it makes sense to fold it into a location which can do more
platform-specific checks for various implementation details (such as MSVC 32
vs 64-bit).
* This removes LLVM as a build-time dependency of the standard library. This may
end up becoming very useful if we move towards building the standard library
with Cargo.
In the immediate future, however, this commit should restore compatibility with
LLVM 3.5 and 3.6.
Fixes#25343
To be honest I'm not sure if this is the right fix (I haven't yet fully understood the code),
but it seems to work. I'll look closer at the code when I have some time, in the meantime if this
is the right fix it would be nice to get verification from someone who does understand the code 😄
r? @pnkfelix
r? @eddyb
Adding new variants is annoying as one needs to modify all these places that **don't** handle the new variant.
I chose not to use `Display` as I don't think it is appropriate.
The "hint" mechanism is essentially used as a workaround to compute
types for expressions which have not yet been type-checked. This
commit clarifies that usage, and limits the effects to the places
where it is currently necessary.
Fixes#26210.
Transition to the new object lifetime defaults, replacing the old defaults completely.
r? @pnkfelix
This is a [breaking-change] as specified by [RFC 1156][1156] (though all cases that would break should have been receiving warnings starting in Rust 1.2). Types like `&'a Box<Trait>` (or `&'a Rc<Trait>`, etc) will change from being interpreted as `&'a Box<Trait+'a>` to `&'a Box<Trait+'static>`. To restore the old behavior, write the `+'a` explicitly. For example, the function:
```rust
trait Trait { }
fn foo(x: &Box<Trait>) { ... }
```
would be rewritten as:
```rust
trait Trait { }
fn foo(x: &'a Box<Trait+'a>) { ... }
```
if one wanted to preserve the current typing.
[1156]: https://github.com/rust-lang/rfcs/blob/master/text/1156-adjust-default-object-bounds.md
This PR modernizes some names in the type checker. The only remaining snake_case name in ty.rs is `ctxt` which should be resolved by @eddyb's pending refactor. We can bike shed over the names, it would just be nice to bring the type checker inline with modern Rust.
r? @eddyb
cc @nikomatsakis
In a followup to PR #26849, improve one more location for I/O where
we can use `Vec::resize` to ensure better performance when zeroing
buffers.
Use the `vec![elt; n]` macro everywhere we can in the tree. It replaces
`repeat(elt).take(n).collect()` which is more verbose, requires type
hints, and right now produces worse code. `vec![]` is preferable for vector
initialization.
The `vec![]` replacement touches upon one I/O path too, Stdin::read
for windows, and that should be a small improvement.
r? @alexcrichton
The common pattern `iter::repeat(elt).take(n).collect::<Vec<_>>()` is
exactly equivalent to `vec![elt; n]`, do this replacement in the whole
tree.
(Actually, vec![] is smart enough to only call clone n - 1 times, while
the former solution would call clone n times, and this fact is
virtually irrelevant in practice.)
Fixes#23302.
Note that there's an odd situation regarding the following, most likely due to some inadequacy in `const_eval`:
```rust
enum Y {
A = 1usize,
B,
}
```
In this case, `Y::B as usize` might be considered a constant expression in some cases, but not others. (See #23513, for a related problem where there is only one variant, with no discriminant, and it doesn't behave nicely as a constant expression either.)
Most of the complexity in this PR is basically future-proofing, to ensure that when `Y::B as usize` is fully made to be a constant expression, it can't be used to set `Y::A`, and thus indirectly itself.
`MethodCallee` now has no information about the method, other than its `DefId`.
The previous bits of information can be recovered as follows:
```rust
let method_item = tcx.impl_or_trait_item(callee.def_id);
let container = method_item.container();
```
The method is inherent if `container` is a `ty::ImplContainer`:
* the `impl` the method comes from is `container.id()`
The method is a trait method if `container` is a `ty::TraitContainer:
* the `trait` the method is part of is `container.id()`
* a `ty::TraitRef` can be constructed by putting together:
* `container.id()` as the `trait` ID
* `callee.substs.clone().method_to_trait()` as the `trait` substs (including `Self`)
* the above `trait_ref` is a valid `T: Trait<A, B, C>` predicate
* selecting `trait_ref` could result in one of the following:
* `traits::VtableImpl(data)`: static dispatch to `data.impl_def_id`
* `traits::VtableObject(data)`: dynamic dispatch, with the vtable index:
`traits::get_vtable_index_of_object_method(tcx, data, callee.def_id)`
* other variants of `traits::Vtable`: various other `impl` sources