Warn when an import list is empty
For a given file
```rust
use std::*;
use std::{};
```
output the following warnings
```
warning: unused import: `use std::{};`, #[warn(unused_imports)] on by default
--> file.rs:2:1
|
2 | use std::{};
| ^^^^^^^^^^^^
warning: unused import: `std::*;`, #[warn(unused_imports)] on by default
--> file.rs:1:5
|
1 | use std::*;
| ^^^^^^^
```
For a given file
```rust
use std::*;
use std::{};
```
output the following warnings
```
warning: unused import: `use std::{};`, #[warn(unused_imports)] on by default
--> file.rs:2:1
|
2 | use std::{};
| ^^^^^^^^^^^^
warning: unused import: `std::*;`, #[warn(unused_imports)] on by default
--> file.rs:1:5
|
1 | use std::*;
| ^^^^^^^
```
Point arg num mismatch errors back to their definition
This PR updates the arg num errors (like E0061) to point back at the function definition where they were defined.
Before:
```
error[E0061]: this function takes 2 parameters but 1 parameter was supplied
--> E0061.rs:18:7
|
18 | f(0);
| ^
|
= note: the following parameter types were expected:
= note: u16, &str
```
Now:
```
error[E0061]: this function takes 2 parameters but 1 parameter was supplied
--> E0061.rs:18:7
|
11 | fn f(a: u16, b: &str) {}
| ------------------------ defined here
...
18 | f(0);
| ^ expected 2 parameters
```
This is an incremental improvement. We probably want to underline only the function name and also have support for functions defined in crates outside of the current crate.
r? @nikomatsakis
fix stack overflow by enum and cont issue #36163
some paths were skipped while checking for recursion.
I fixed bug reproduces on win64 cargo test. In previous PR #36458 time complexity was exponential in case of linked const values. Now it's linear.
r? @alexcrichton
Add new #[target_feature = "..."] attribute.
This commit adds a new attribute that instructs the compiler to emit
target specific code for a single function. For example, the following
function is permitted to use instructions that are part of SSE 4.2:
#[target_feature = "+sse4.2"]
fn foo() { ... }
In particular, use of this attribute does not require setting the
-C target-feature or -C target-cpu options on rustc.
This attribute does not have any protections built into it. For example,
nothing stops one from calling the above `foo` function on hosts without
SSE 4.2 support. Doing so may result in a SIGILL.
I've also expanded the x86 target feature whitelist.
Refactor TraitObject to Slice<ExistentialPredicate>
For reference, the primary types changes in this PR are shown below. They may add in the understanding of what is discussed below, though they should not be required.
We change `TraitObject` into a list of `ExistentialPredicate`s to allow for a couple of things:
- Principal (ExistentialPredicate::Trait) is now optional.
- Region bounds are moved out of `TraitObject` into `TyDynamic`. This permits wrapping only the `ExistentialPredicate` list in `Binder`.
- `BuiltinBounds` and `BuiltinBound` are removed entirely from the codebase, to permit future non-constrained auto traits. These are replaced with `ExistentialPredicate::AutoTrait`, which only requires a `DefId`. For the time being, only `Send` and `Sync` are supported; this constraint can be lifted in a future pull request.
- Binder-related logic is extracted from `ExistentialPredicate` into the parent (`Binder<Slice<EP>>`), so `PolyX`s are inside `TraitObject` are replaced with `X`.
The code requires a sorting order for `ExistentialPredicate`s in the interned `Slice`. The sort order is asserted to be correct during interning, but the slices are not sorted at that point.
1. `ExistentialPredicate::Trait` are defined as always equal; **This may be wrong; should we be comparing them and sorting them in some way?**
1. `ExistentialPredicate::Projection`: Compared by `ExistentialProjection::sort_key`.
1. `ExistentialPredicate::AutoTrait`: Compared by `TraitDef.def_path_hash`.
Construction of `ExistentialPredicate`s is conducted through `TyCtxt::mk_existential_predicates`, which interns a passed iterator as a `Slice`. There are no convenience functions to construct from a set of separate iterators; callers must pass an iterator chain. The lack of convenience functions is primarily due to few uses and the relative difficulty in defining a nice API due to optional parts and difficulty in recognizing which argument goes where. It is also true that the current situation isn't significantly better than 4 arguments to a constructor function; but the extra work is deemed unnecessary as of this time.
```rust
// before this PR
struct TraitObject<'tcx> {
pub principal: PolyExistentialTraitRef<'tcx>,
pub region_bound: &'tcx ty::Region,
pub builtin_bounds: BuiltinBounds,
pub projection_bounds: Vec<PolyExistentialProjection<'tcx>>,
}
// after
pub enum ExistentialPredicate<'tcx> {
// e.g. Iterator
Trait(ExistentialTraitRef<'tcx>),
// e.g. Iterator::Item = T
Projection(ExistentialProjection<'tcx>),
// e.g. Send
AutoTrait(DefId),
}
```
This commit adds a new attribute that instructs the compiler to emit
target specific code for a single function. For example, the following
function is permitted to use instructions that are part of SSE 4.2:
#[target_feature = "+sse4.2"]
fn foo() { ... }
In particular, use of this attribute does not require setting the
-C target-feature or -C target-cpu options on rustc.
This attribute does not have any protections built into it. For example,
nothing stops one from calling the above `foo` function on hosts without
SSE 4.2 support. Doing so may result in a SIGILL.
This commit also expands the target feature whitelist to include lzcnt,
popcnt and sse4a. Namely, lzcnt and popcnt have their own CPUID bits,
but were introduced with SSE4.
Support `?Sized` in where clauses
Implemented as described in https://github.com/rust-lang/rust/issues/20503#issuecomment-258677026 - `?Trait` bounds are moved on type parameter definitions when possible, reported as errors otherwise.
(It'd be nice to unify bounds and where clauses in HIR, but this is mostly blocked by rustdoc now - it needs to render bounds in pleasant way and the best way to do it so far is to mirror what was written in source code.)
Fixes https://github.com/rust-lang/rust/issues/20503
r? @nikomatsakis
Provide hint when cast needs a dereference
For a given code:
``` rust
vec![0.0].iter().map(|s| s as i16).collect::<Vec<i16>>();
```
display:
``` nocode
error: casting `&f64` as `i16` is invalid
--> file3.rs:2:35
|
2 | vec![0.0].iter().map(|s| s as i16).collect::<Vec<i16>>();
| - ^^^
| |
| did you mean `*s`?
```
instead of:
``` nocode
error: casting `&f64` as `i16` is invalid
--> <anon>:2:30
|
2 | vec![0.0].iter().map(|s| s as i16).collect();
| ^^^^^^^^
|
= help: cast through a raw pointer first
```
Fixes#37338.
Implement the `loop_break_value` feature.
This implements RFC 1624, tracking issue #37339.
- `FnCtxt` (in typeck) gets a stack of `LoopCtxt`s, which store the
currently deduced type of that loop, the desired type, and a list of
break expressions currently seen. `loop` loops get a fresh type
variable as their initial type (this logic is stolen from that for
arrays). `while` loops get `()`.
- `break {expr}` looks up the broken loop, and unifies the type of
`expr` with the type of the loop.
- `break` with no expr unifies the loop's type with `()`.
- When building MIR, loops no longer construct a `()` value at
termination of the loop; rather, the `break` expression assigns the
result of the loop.
- ~~I have also changed the loop scoping in MIR-building so that the test
of a while loop is not considered to be part of that loop. This makes
the rules consistent with #37360. The new loop scopes in typeck also
follow this rule. That means that `loop { while (break) {} }` now
terminates instead of looping forever. This is technically a breaking
change.~~
- ~~On that note, expressions like `while break {}` and `if break {}` no
longer parse because `{}` is interpreted as an expression argument to
`break`. But no code except compiler test cases should do that anyway
because it makes no sense.~~
- The RFC did not make it clear, but I chose to make `break ()` inside
of a `while` loop illegal, just in case we wanted to do anything with
that design space in the future.
This is my first time dealing with this part of rustc so I'm sure
there's plenty of problems to pick on here ^_^
This implements RFC 1624, tracking issue #37339.
- `FnCtxt` (in typeck) gets a stack of `LoopCtxt`s, which store the
currently deduced type of that loop, the desired type, and a list of
break expressions currently seen. `loop` loops get a fresh type
variable as their initial type (this logic is stolen from that for
arrays). `while` loops get `()`.
- `break {expr}` looks up the broken loop, and unifies the type of
`expr` with the type of the loop.
- `break` with no expr unifies the loop's type with `()`.
- When building MIR, `loop` loops no longer construct a `()` value at
termination of the loop; rather, the `break` expression assigns the
result of the loop. `while` loops are unchanged.
- `break` respects contexts in which expressions may not end with braced
blocks. That is, `while break { break-value } { while-body }` is
illegal; this preserves backwards compatibility.
- The RFC did not make it clear, but I chose to make `break ()` inside
of a `while` loop illegal, just in case we wanted to do anything with
that design space in the future.
This is my first time dealing with this part of rustc so I'm sure
there's plenty of problems to pick on here ^_^
For a given code:
```rust
vec![0.0].iter().map(|s| s as i16).collect::<Vec<i16>>();
```
display:
```nocode
error: casting `&f64` as `i16` is invalid
--> foo.rs:2:35
|
2 | vec![0.0].iter().map(|s| s as i16).collect::<Vec<i16>>();
| - ^^^ cannot cast `&f64` as `i16`
| |
| did you mean `*s`?
```
instead of:
```nocode
error: casting `&f64` as `i16` is invalid
--> <anon>:2:30
|
2 | vec![0.0].iter().map(|s| s as i16).collect();
| ^^^^^^^^
|
= help: cast through a raw pointer first
```
Separate impl items from the parent impl
This change separates impl item bodies out of the impl itself. This gives incremental more resolution. In so doing, it refactors how the visitors work, and cleans up a bit of the collect/check logic (mostly by moving things out of collect that didn't really belong there, because they were just checking conditions).
However, this is not as effective as I expected, for a kind of frustrating reason. In particular, when invoking `foo.bar()` you still wind up with dependencies on private items. The problem is that the method resolution code scans that list for methods with the name `bar` -- and this winds up touching *all* the methods, even private ones.
I can imagine two obvious ways to fix this:
- separating fn bodies from fn sigs (#35078, currently being pursued by @flodiebold)
- a more aggressive model of incremental that @michaelwoerister has been advocating, in which we hash the intermediate results (e.g., the outputs of collect) so that we can see that the intermediate result hasn't changed, even if a particular impl item has changed.
So all in all I'm not quite sure whether to land this or not. =) It still seems like it has to be a win in some cases, but not with the test cases we have just now. I can try to gin up some test cases, but I'm not sure if they will be totally realistic. On the other hand, some of the early refactorings to the visitor trait seem worthwhile to me regardless.
cc #36349 -- well, this is basically a fix for that issue, I guess
r? @michaelwoerister
NB: Based atop of @eddyb's PR https://github.com/rust-lang/rust/pull/37402; don't land until that lands.
Improved error reporting when target sysroot is missing.
Attempts to resolve#37131.
This is my first pull request on rust, so I would greatly appreciate any feedback you have on this.
Thanks!
Add semicolon to "perhaps add a `use` for one of them" help
Similar to pull request #37430, this makes the message more copy-paste
friendly and aligns it with other messages like:
help: you can import it into scope: use foo::Bar;
r? @eddyb
coherence: skip impls with an erroneous trait ref
Impls with a erroneous trait ref are already ignored in the first part
of coherence, so ignore them in the second part too. This avoids
cascading coherence errors when 1 impl of a trait has an error.
r? @nikomatsakis
Support `use`ing externally defined macros behind `#![feature(use_extern_macros)]`
With `#![feature(use_extern_macros)]`,
- A name collision between macros from different upstream crates is much less of an issue since we can `use` the macros in different submodules or rename with `as`.
- We can reexport macros with `pub use`, so `#![feature(macro_reexport)]` is no longer needed.
- These reexports are allowed in any module, so crates can expose a macro-modular interface.
If a macro invocation can resolve to both a `use` import and a `macro_rules!` or `#[macro_use]`, it is an ambiguity error.
r? @nrc