Auto merge of #65454 - tmandry:rollup-0k6jiik, r=tmandry
Rollup of 14 pull requests
Successful merges:
- #64603 (Reducing spurious unused lifetime warnings.)
- #64623 (Remove last uses of gensyms)
- #65235 (don't assume we can *always* find a return type hint in async fn)
- #65242 (Fix suggestion to constrain trait for method to be found)
- #65265 (Cleanup librustc mir err codes)
- #65293 (Optimize `try_expand_impl_trait_type`)
- #65307 (Try fix incorrect "explicit lifetime name needed")
- #65308 (Add long error explanation for E0574)
- #65353 (save-analysis: Don't ICE when resolving qualified type paths in struct members)
- #65389 (Return `false` from `needs_drop` for all zero-sized arrays.)
- #65402 (Add troubleshooting section to PGO chapter in rustc book.)
- #65425 (Optimize `BitIter`)
- #65438 (Organize `never_type` tests)
- #65444 (Implement AsRef<[T]> for List<T>)
Failed merges:
- #65390 (Add long error explanation for E0576)
r? @ghost
diff --git a/src/doc/rustc/src/profile-guided-optimization.md b/src/doc/rustc/src/profile-guided-optimization.md
index 38be07a..d066f4a 100644
--- a/src/doc/rustc/src/profile-guided-optimization.md
+++ b/src/doc/rustc/src/profile-guided-optimization.md
@@ -125,6 +125,17 @@
cargo build --release --target=x86_64-unknown-linux-gnu
```
+### Troubleshooting
+
+- It is recommended to pass `-Cllvm-args=-pgo-warn-missing-function` during the
+ `-Cprofile-use` phase. LLVM by default does not warn if it cannot find
+ profiling data for a given function. Enabling this warning will make it
+ easier to spot errors in your setup.
+
+- There is a [known issue](https://github.com/rust-lang/cargo/issues/7416) in
+ Cargo prior to version 1.39 that will prevent PGO from working correctly. Be
+ sure to use Cargo 1.39 or newer when doing PGO.
+
## Further Reading
`rustc`'s PGO support relies entirely on LLVM's implementation of the feature
diff --git a/src/librustc/hir/lowering.rs b/src/librustc/hir/lowering.rs
index ab5a3c0..e9788a5 100644
--- a/src/librustc/hir/lowering.rs
+++ b/src/librustc/hir/lowering.rs
@@ -3291,10 +3291,14 @@
let id = self.sess.next_node_id();
self.new_named_lifetime(id, span, hir::LifetimeName::Error)
}
- // This is the normal case.
- AnonymousLifetimeMode::PassThrough => self.new_implicit_lifetime(span),
-
- AnonymousLifetimeMode::ReportError => self.new_error_lifetime(None, span),
+ // `PassThrough` is the normal case.
+ // `new_error_lifetime`, which would usually be used in the case of `ReportError`,
+ // is unsuitable here, as these can occur from missing lifetime parameters in a
+ // `PathSegment`, for which there is no associated `'_` or `&T` with no explicit
+ // lifetime. Instead, we simply create an implicit lifetime, which will be checked
+ // later, at which point a suitable error will be emitted.
+ | AnonymousLifetimeMode::PassThrough
+ | AnonymousLifetimeMode::ReportError => self.new_implicit_lifetime(span),
}
}
diff --git a/src/librustc/middle/resolve_lifetime.rs b/src/librustc/middle/resolve_lifetime.rs
index 31d250f..a122d84 100644
--- a/src/librustc/middle/resolve_lifetime.rs
+++ b/src/librustc/middle/resolve_lifetime.rs
@@ -708,15 +708,22 @@
match param.kind {
GenericParamKind::Lifetime { .. } => {
let (name, reg) = Region::early(&self.tcx.hir(), &mut index, ¶m);
+ let def_id = if let Region::EarlyBound(_ ,def_id , _) = reg {
+ def_id
+ } else {
+ bug!();
+ };
if let hir::ParamName::Plain(param_name) = name {
if param_name.name == kw::UnderscoreLifetime {
// Pick the elided lifetime "definition" if one exists
// and use it to make an elision scope.
+ self.lifetime_uses.insert(def_id.clone(), LifetimeUseSet::Many);
elision = Some(reg);
} else {
lifetimes.insert(name, reg);
}
} else {
+ self.lifetime_uses.insert(def_id.clone(), LifetimeUseSet::Many);
lifetimes.insert(name, reg);
}
}
@@ -1615,7 +1622,6 @@
_ => None,
} {
debug!("id = {:?} span = {:?} name = {:?}", id, span, name);
-
if name.name == kw::UnderscoreLifetime {
continue;
}
diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs
index 00b5fa2..65aea7b 100644
--- a/src/librustc/ty/mod.rs
+++ b/src/librustc/ty/mod.rs
@@ -701,6 +701,13 @@
type Target = [T];
#[inline(always)]
fn deref(&self) -> &[T] {
+ self.as_ref()
+ }
+}
+
+impl<T> AsRef<[T]> for List<T> {
+ #[inline(always)]
+ fn as_ref(&self) -> &[T] {
unsafe {
slice::from_raw_parts(self.data.as_ptr(), self.len)
}
diff --git a/src/librustc/ty/print/pretty.rs b/src/librustc/ty/print/pretty.rs
index c4967f8..363109a 100644
--- a/src/librustc/ty/print/pretty.rs
+++ b/src/librustc/ty/print/pretty.rs
@@ -1483,7 +1483,7 @@
}
// Replace any anonymous late-bound regions with named
- // variants, using gensym'd identifiers, so that we can
+ // variants, using new unique identifiers, so that we can
// clearly differentiate between named and unnamed regions in
// the output. We'll probably want to tweak this over time to
// decide just how much information to give.
diff --git a/src/librustc/ty/util.rs b/src/librustc/ty/util.rs
index 5ddf153..e1eab2c 100644
--- a/src/librustc/ty/util.rs
+++ b/src/librustc/ty/util.rs
@@ -697,6 +697,9 @@
// that type, and when we finish expanding that type we remove the
// its DefId.
seen_opaque_tys: FxHashSet<DefId>,
+ // Cache of all expansions we've seen so far. This is a critical
+ // optimization for some large types produced by async fn trees.
+ expanded_cache: FxHashMap<(DefId, SubstsRef<'tcx>), Ty<'tcx>>,
primary_def_id: DefId,
found_recursion: bool,
tcx: TyCtxt<'tcx>,
@@ -713,9 +716,16 @@
}
let substs = substs.fold_with(self);
if self.seen_opaque_tys.insert(def_id) {
- let generic_ty = self.tcx.type_of(def_id);
- let concrete_ty = generic_ty.subst(self.tcx, substs);
- let expanded_ty = self.fold_ty(concrete_ty);
+ let expanded_ty = match self.expanded_cache.get(&(def_id, substs)) {
+ Some(expanded_ty) => expanded_ty,
+ None => {
+ let generic_ty = self.tcx.type_of(def_id);
+ let concrete_ty = generic_ty.subst(self.tcx, substs);
+ let expanded_ty = self.fold_ty(concrete_ty);
+ self.expanded_cache.insert((def_id, substs), expanded_ty);
+ expanded_ty
+ }
+ };
self.seen_opaque_tys.remove(&def_id);
Some(expanded_ty)
} else {
@@ -735,14 +745,17 @@
fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> {
if let ty::Opaque(def_id, substs) = t.kind {
self.expand_opaque_ty(def_id, substs).unwrap_or(t)
- } else {
+ } else if t.has_projections() {
t.super_fold_with(self)
+ } else {
+ t
}
}
}
let mut visitor = OpaqueTypeExpander {
seen_opaque_tys: FxHashSet::default(),
+ expanded_cache: FxHashMap::default(),
primary_def_id: def_id,
found_recursion: false,
tcx: self,
@@ -1096,6 +1109,9 @@
ty::UnnormalizedProjection(..) => bug!("only used with chalk-engine"),
+ // Zero-length arrays never contain anything to drop.
+ ty::Array(_, len) if len.try_eval_usize(tcx, param_env) == Some(0) => false,
+
// Structural recursion.
ty::Array(ty, _) | ty::Slice(ty) => needs_drop(ty),
diff --git a/src/librustc_index/bit_set.rs b/src/librustc_index/bit_set.rs
index 8c49e0d..d8c6e4c 100644
--- a/src/librustc_index/bit_set.rs
+++ b/src/librustc_index/bit_set.rs
@@ -168,11 +168,7 @@
/// Iterates over the indices of set bits in a sorted order.
#[inline]
pub fn iter(&self) -> BitIter<'_, T> {
- BitIter {
- cur: None,
- iter: self.words.iter().enumerate(),
- marker: PhantomData,
- }
+ BitIter::new(&self.words)
}
/// Duplicates the set as a hybrid set.
@@ -291,26 +287,55 @@
}
pub struct BitIter<'a, T: Idx> {
- cur: Option<(Word, usize)>,
- iter: iter::Enumerate<slice::Iter<'a, Word>>,
+ /// A copy of the current word, but with any already-visited bits cleared.
+ /// (This lets us use `trailing_zeros()` to find the next set bit.) When it
+ /// is reduced to 0, we move onto the next word.
+ word: Word,
+
+ /// The offset (measured in bits) of the current word.
+ offset: usize,
+
+ /// Underlying iterator over the words.
+ iter: slice::Iter<'a, Word>,
+
marker: PhantomData<T>
}
+impl<'a, T: Idx> BitIter<'a, T> {
+ #[inline]
+ fn new(words: &'a [Word]) -> BitIter<'a, T> {
+ // We initialize `word` and `offset` to degenerate values. On the first
+ // call to `next()` we will fall through to getting the first word from
+ // `iter`, which sets `word` to the first word (if there is one) and
+ // `offset` to 0. Doing it this way saves us from having to maintain
+ // additional state about whether we have started.
+ BitIter {
+ word: 0,
+ offset: std::usize::MAX - (WORD_BITS - 1),
+ iter: words.iter(),
+ marker: PhantomData,
+ }
+ }
+}
+
impl<'a, T: Idx> Iterator for BitIter<'a, T> {
type Item = T;
fn next(&mut self) -> Option<T> {
loop {
- if let Some((ref mut word, offset)) = self.cur {
- let bit_pos = word.trailing_zeros() as usize;
- if bit_pos != WORD_BITS {
- let bit = 1 << bit_pos;
- *word ^= bit;
- return Some(T::new(bit_pos + offset))
- }
+ if self.word != 0 {
+ // Get the position of the next set bit in the current word,
+ // then clear the bit.
+ let bit_pos = self.word.trailing_zeros() as usize;
+ let bit = 1 << bit_pos;
+ self.word ^= bit;
+ return Some(T::new(bit_pos + self.offset))
}
- let (i, word) = self.iter.next()?;
- self.cur = Some((*word, WORD_BITS * i));
+ // Move onto the next word. `wrapping_add()` is needed to handle
+ // the degenerate initial value given to `offset` in `new()`.
+ let word = self.iter.next()?;
+ self.word = *word;
+ self.offset = self.offset.wrapping_add(WORD_BITS);
}
}
}
@@ -851,11 +876,7 @@
pub fn iter(&self, row: R) -> BitIter<'_, C> {
assert!(row.index() < self.num_rows);
let (start, end) = self.range(row);
- BitIter {
- cur: None,
- iter: self.words[start..end].iter().enumerate(),
- marker: PhantomData,
- }
+ BitIter::new(&self.words[start..end])
}
/// Returns the number of elements in `row`.
diff --git a/src/librustc_mir/dataflow/impls/indirect_mutation.rs b/src/librustc_mir/dataflow/impls/indirect_mutation.rs
index 990425c..bc09e32 100644
--- a/src/librustc_mir/dataflow/impls/indirect_mutation.rs
+++ b/src/librustc_mir/dataflow/impls/indirect_mutation.rs
@@ -104,25 +104,16 @@
kind: mir::BorrowKind,
borrowed_place: &mir::Place<'tcx>,
) -> bool {
- let borrowed_ty = borrowed_place.ty(self.body, self.tcx).ty;
-
- // Zero-sized types cannot be mutated, since there is nothing inside to mutate.
- //
- // FIXME: For now, we only exempt arrays of length zero. We need to carefully
- // consider the effects before extending this to all ZSTs.
- if let ty::Array(_, len) = borrowed_ty.kind {
- if len.try_eval_usize(self.tcx, self.param_env) == Some(0) {
- return false;
- }
- }
-
match kind {
mir::BorrowKind::Mut { .. } => true,
| mir::BorrowKind::Shared
| mir::BorrowKind::Shallow
| mir::BorrowKind::Unique
- => !borrowed_ty.is_freeze(self.tcx, self.param_env, DUMMY_SP),
+ => !borrowed_place
+ .ty(self.body, self.tcx)
+ .ty
+ .is_freeze(self.tcx, self.param_env, DUMMY_SP),
}
}
}
diff --git a/src/librustc_mir/error_codes.rs b/src/librustc_mir/error_codes.rs
index 77853ff..419c905 100644
--- a/src/librustc_mir/error_codes.rs
+++ b/src/librustc_mir/error_codes.rs
@@ -64,7 +64,9 @@
This error indicates that the compiler cannot guarantee a matching pattern for
one or more possible inputs to a match expression. Guaranteed matches are
required in order to assign values to match expressions, or alternatively,
-determine the flow of execution. Erroneous code example:
+determine the flow of execution.
+
+Erroneous code example:
```compile_fail,E0004
enum Terminator {
@@ -109,7 +111,9 @@
E0005: r##"
Patterns used to bind names must be irrefutable, that is, they must guarantee
-that a name will be extracted in all cases. Erroneous code example:
+that a name will be extracted in all cases.
+
+Erroneous code example:
```compile_fail,E0005
let x = Some(1);
@@ -145,6 +149,8 @@
moved into a variable called `op_string` while simultaneously requiring the
inner `String` to be moved into a variable called `s`.
+Erroneous code example:
+
```compile_fail,E0007
let x = Some("s".to_string());
@@ -208,15 +214,130 @@
```
"##,
+E0010: r##"
+The value of statics and constants must be known at compile time, and they live
+for the entire lifetime of a program. Creating a boxed value allocates memory on
+the heap at runtime, and therefore cannot be done at compile time.
+
+Erroneous code example:
+
+```compile_fail,E0010
+#![feature(box_syntax)]
+
+const CON : Box<i32> = box 0;
+```
+"##,
+
+E0013: r##"
+Static and const variables can refer to other const variables. But a const
+variable cannot refer to a static variable.
+
+Erroneous code example:
+
+```compile_fail,E0013
+static X: i32 = 42;
+const Y: i32 = X;
+```
+
+In this example, `Y` cannot refer to `X` here. To fix this, the value can be
+extracted as a const and then used:
+
+```
+const A: i32 = 42;
+static X: i32 = A;
+const Y: i32 = A;
+```
+"##,
+
+// FIXME(#57563) Change the language here when const fn stabilizes
+E0015: r##"
+The only functions that can be called in static or constant expressions are
+`const` functions, and struct/enum constructors. `const` functions are only
+available on a nightly compiler. Rust currently does not support more general
+compile-time function execution.
+
+```
+const FOO: Option<u8> = Some(1); // enum constructor
+struct Bar {x: u8}
+const BAR: Bar = Bar {x: 1}; // struct constructor
+```
+
+See [RFC 911] for more details on the design of `const fn`s.
+
+[RFC 911]: https://github.com/rust-lang/rfcs/blob/master/text/0911-const-fn.md
+"##,
+
+E0017: r##"
+References in statics and constants may only refer to immutable values.
+
+Erroneous code example:
+
+```compile_fail,E0017
+static X: i32 = 1;
+const C: i32 = 2;
+
+// these three are not allowed:
+const CR: &mut i32 = &mut C;
+static STATIC_REF: &'static mut i32 = &mut X;
+static CONST_REF: &'static mut i32 = &mut C;
+```
+
+Statics are shared everywhere, and if they refer to mutable data one might
+violate memory safety since holding multiple mutable references to shared data
+is not allowed.
+
+If you really want global mutable state, try using `static mut` or a global
+`UnsafeCell`.
+"##,
+
+E0019: r##"
+A function call isn't allowed in the const's initialization expression
+because the expression's value must be known at compile-time.
+
+Erroneous code example:
+
+```compile_fail,E0019
+#![feature(box_syntax)]
+
+fn main() {
+ struct MyOwned;
+
+ static STATIC11: Box<MyOwned> = box MyOwned; // error!
+}
+```
+
+Remember: you can't use a function call inside a const's initialization
+expression! However, you can totally use it anywhere else:
+
+```
+enum Test {
+ V1
+}
+
+impl Test {
+ fn func(&self) -> i32 {
+ 12
+ }
+}
+
+fn main() {
+ const FOO: Test = Test::V1;
+
+ FOO.func(); // here is good
+ let x = FOO.func(); // or even here!
+}
+```
+"##,
+
E0030: r##"
When matching against a range, the compiler verifies that the range is
-non-empty. Range patterns include both end-points, so this is equivalent to
+non-empty. Range patterns include both end-points, so this is equivalent to
requiring the start of the range to be less than or equal to the end of the
range.
-For example:
+Erroneous code example:
-```compile_fail
+```compile_fail,E0030
match 5u32 {
// This range is ok, albeit pointless.
1 ..= 1 => {}
@@ -226,7 +347,61 @@
```
"##,
+E0133: r##"
+Unsafe code was used outside of an unsafe function or block.
+
+Erroneous code example:
+
+```compile_fail,E0133
+unsafe fn f() { return; } // This is the unsafe code
+
+fn main() {
+ f(); // error: call to unsafe function requires unsafe function or block
+}
+```
+
+Using unsafe functionality is potentially dangerous and disallowed by safety
+checks. Examples:
+
+* Dereferencing raw pointers
+* Calling functions via FFI
+* Calling functions marked unsafe
+
+These safety checks can be relaxed for a section of the code by wrapping the
+unsafe instructions with an `unsafe` block. For instance:
+
+```
+unsafe fn f() { return; }
+
+fn main() {
+ unsafe { f(); } // ok!
+}
+```
+
+See also https://doc.rust-lang.org/book/ch19-01-unsafe-rust.html
+"##,
+
E0158: r##"
+An associated const has been referenced in a pattern.
+
+Erroneous code example:
+
+```compile_fail,E0158
+enum EFoo { A, B, C, D }
+
+trait Foo {
+ const X: EFoo;
+}
+
+fn test<A: Foo>(arg: EFoo) {
+ match arg {
+ A::X => { // error!
+ println!("A::X");
+ }
+ }
+}
+```
+
`const` and `static` mean different things. A `const` is a compile-time
constant, an alias for a literal value. This property means you can match it
directly within a pattern.
@@ -247,6 +422,39 @@
```
"##,
+E0161: r##"
+A value was moved. However, its size was not known at compile time, and only
+values of a known size can be moved.
+
+Erroneous code example:
+
+```compile_fail,E0161
+#![feature(box_syntax)]
+
+fn main() {
+ let array: &[isize] = &[1, 2, 3];
+ let _x: Box<[isize]> = box *array;
+ // error: cannot move a value of type [isize]: the size of [isize] cannot
+ // be statically determined
+}
+```
+
+In Rust, you can only move a value when its size is known at compile time.
+
+To work around this restriction, consider "hiding" the value behind a reference:
+either `&x` or `&mut x`. Since a reference has a fixed size, this lets you move
+it around as usual. Example:
+
+```
+#![feature(box_syntax)]
+
+fn main() {
+ let array: &[isize] = &[1, 2, 3];
+ let _x: Box<&[isize]> = box array; // ok!
+}
+```
+"##,
+
E0162: r##"
#### Note: this error code is no longer emitted by the compiler.
@@ -468,158 +676,6 @@
See also https://github.com/rust-lang/rust/issues/14587
"##,
-E0010: r##"
-The value of statics and constants must be known at compile time, and they live
-for the entire lifetime of a program. Creating a boxed value allocates memory on
-the heap at runtime, and therefore cannot be done at compile time. Erroneous
-code example:
-
-```compile_fail,E0010
-#![feature(box_syntax)]
-
-const CON : Box<i32> = box 0;
-```
-"##,
-
-E0013: r##"
-Static and const variables can refer to other const variables. But a const
-variable cannot refer to a static variable. For example, `Y` cannot refer to
-`X` here:
-
-```compile_fail,E0013
-static X: i32 = 42;
-const Y: i32 = X;
-```
-
-To fix this, the value can be extracted as a const and then used:
-
-```
-const A: i32 = 42;
-static X: i32 = A;
-const Y: i32 = A;
-```
-"##,
-
-// FIXME(#57563) Change the language here when const fn stabilizes
-E0015: r##"
-The only functions that can be called in static or constant expressions are
-`const` functions, and struct/enum constructors. `const` functions are only
-available on a nightly compiler. Rust currently does not support more general
-compile-time function execution.
-
-```
-const FOO: Option<u8> = Some(1); // enum constructor
-struct Bar {x: u8}
-const BAR: Bar = Bar {x: 1}; // struct constructor
-```
-
-See [RFC 911] for more details on the design of `const fn`s.
-
-[RFC 911]: https://github.com/rust-lang/rfcs/blob/master/text/0911-const-fn.md
-"##,
-
-E0017: r##"
-References in statics and constants may only refer to immutable values.
-Erroneous code example:
-
-```compile_fail,E0017
-static X: i32 = 1;
-const C: i32 = 2;
-
-// these three are not allowed:
-const CR: &mut i32 = &mut C;
-static STATIC_REF: &'static mut i32 = &mut X;
-static CONST_REF: &'static mut i32 = &mut C;
-```
-
-Statics are shared everywhere, and if they refer to mutable data one might
-violate memory safety since holding multiple mutable references to shared data
-is not allowed.
-
-If you really want global mutable state, try using `static mut` or a global
-`UnsafeCell`.
-"##,
-
-E0019: r##"
-A function call isn't allowed in the const's initialization expression
-because the expression's value must be known at compile-time. Erroneous code
-example:
-
-```compile_fail
-enum Test {
- V1
-}
-
-impl Test {
- fn test(&self) -> i32 {
- 12
- }
-}
-
-fn main() {
- const FOO: Test = Test::V1;
-
- const A: i32 = FOO.test(); // You can't call Test::func() here!
-}
-```
-
-Remember: you can't use a function call inside a const's initialization
-expression! However, you can totally use it anywhere else:
-
-```
-enum Test {
- V1
-}
-
-impl Test {
- fn func(&self) -> i32 {
- 12
- }
-}
-
-fn main() {
- const FOO: Test = Test::V1;
-
- FOO.func(); // here is good
- let x = FOO.func(); // or even here!
-}
-```
-"##,
-
-E0133: r##"
-Unsafe code was used outside of an unsafe function or block.
-
-Erroneous code example:
-
-```compile_fail,E0133
-unsafe fn f() { return; } // This is the unsafe code
-
-fn main() {
- f(); // error: call to unsafe function requires unsafe function or block
-}
-```
-
-Using unsafe functionality is potentially dangerous and disallowed by safety
-checks. Examples:
-
-* Dereferencing raw pointers
-* Calling functions via FFI
-* Calling functions marked unsafe
-
-These safety checks can be relaxed for a section of the code by wrapping the
-unsafe instructions with an `unsafe` block. For instance:
-
-```
-unsafe fn f() { return; }
-
-fn main() {
- unsafe { f(); } // ok!
-}
-```
-
-See also https://doc.rust-lang.org/book/ch19-01-unsafe-rust.html
-"##,
-
E0373: r##"
This error occurs when an attempt is made to use data captured by a closure,
when that data may no longer exist. It's most commonly seen when attempting to
@@ -672,7 +728,9 @@
"##,
E0381: r##"
-It is not allowed to use or capture an uninitialized variable. For example:
+It is not allowed to use or capture an uninitialized variable.
+
+Erroneous code example:
```compile_fail,E0381
fn main() {
@@ -694,7 +752,9 @@
E0382: r##"
This error occurs when an attempt is made to use a variable after its contents
-have been moved elsewhere. For example:
+have been moved elsewhere.
+
+Erroneous code example:
```compile_fail,E0382
struct MyStruct { s: u32 }
@@ -842,7 +902,8 @@
E0384: r##"
This error occurs when an attempt is made to reassign an immutable variable.
-For example:
+
+Erroneous code example:
```compile_fail,E0384
fn main() {
@@ -862,13 +923,15 @@
```
"##,
-/*E0386: r##"
+E0386: r##"
+#### Note: this error code is no longer emitted by the compiler.
+
This error occurs when an attempt is made to mutate the target of a mutable
reference stored inside an immutable container.
For example, this can happen when storing a `&mut` inside an immutable `Box`:
-```compile_fail,E0386
+```
let mut x: i64 = 1;
let y: Box<_> = Box::new(&mut x);
**y = 2; // error, cannot assign to data in an immutable container
@@ -892,13 +955,15 @@
let y: Box<Cell<_>> = Box::new(Cell::new(x));
y.set(2);
```
-"##,*/
+"##,
E0387: r##"
#### Note: this error code is no longer emitted by the compiler.
This error occurs when an attempt is made to mutate or mutably reference data
-that a closure has captured immutably. Examples of this error are shown below:
+that a closure has captured immutably.
+
+Erroneous code example:
```compile_fail
// Accepts a function or a closure that captures its environment immutably.
@@ -963,7 +1028,7 @@
commonly occurs when attempting to assign to a non-mutable reference of a
mutable reference (`&(&mut T)`).
-Example of erroneous code:
+Erroneous code example:
```compile_fail
struct FancyNum {
@@ -1022,43 +1087,11 @@
```
"##,
-E0161: r##"
-A value was moved. However, its size was not known at compile time, and only
-values of a known size can be moved.
+E0492: r##"
+A borrow of a constant containing interior mutability was attempted.
Erroneous code example:
-```compile_fail
-#![feature(box_syntax)]
-
-fn main() {
- let array: &[isize] = &[1, 2, 3];
- let _x: Box<[isize]> = box *array;
- // error: cannot move a value of type [isize]: the size of [isize] cannot
- // be statically determined
-}
-```
-
-In Rust, you can only move a value when its size is known at compile time.
-
-To work around this restriction, consider "hiding" the value behind a reference:
-either `&x` or `&mut x`. Since a reference has a fixed size, this lets you move
-it around as usual. Example:
-
-```
-#![feature(box_syntax)]
-
-fn main() {
- let array: &[isize] = &[1, 2, 3];
- let _x: Box<&[isize]> = box array; // ok!
-}
-```
-"##,
-
-E0492: r##"
-A borrow of a constant containing interior mutability was attempted. Erroneous
-code example:
-
```compile_fail,E0492
use std::sync::atomic::AtomicUsize;
@@ -1174,7 +1207,9 @@
"##,
E0499: r##"
-A variable was borrowed as mutable more than once. Erroneous code example:
+A variable was borrowed as mutable more than once.
+
+Erroneous code example:
```compile_fail,E0499
let mut i = 0;
@@ -1205,7 +1240,9 @@
"##,
E0500: r##"
-A borrowed variable was used by a closure. Example of erroneous code:
+A borrowed variable was used by a closure.
+
+Erroneous code example:
```compile_fail,E0500
fn you_know_nothing(jon_snow: &mut i32) {
@@ -1256,7 +1293,7 @@
http://rustbyexample.com/fn/closures/capture.html for more information about
capturing.
-Example of erroneous code:
+Erroneous code example:
```compile_fail,E0501
fn inside_closure(x: &mut i32) {
@@ -1329,7 +1366,7 @@
This error indicates that you are trying to borrow a variable as mutable when it
has already been borrowed as immutable.
-Example of erroneous code:
+Erroneous code example:
```compile_fail,E0502
fn bar(x: &mut i32) {}
@@ -1360,7 +1397,7 @@
E0503: r##"
A value was used after it was mutably borrowed.
-Example of erroneous code:
+Erroneous code example:
```compile_fail,E0503
fn main() {
@@ -1418,7 +1455,7 @@
This error occurs when an attempt is made to move a borrowed variable into a
closure.
-Example of erroneous code:
+Erroneous code example:
```compile_fail
struct FancyNum {
@@ -1609,7 +1646,7 @@
E0506: r##"
This error occurs when an attempt is made to assign to a borrowed value.
-Example of erroneous code:
+Erroneous code example:
```compile_fail,E0506
struct FancyNum {
@@ -1827,7 +1864,7 @@
E0508: r##"
A value was moved out of a non-copy fixed-size array.
-Example of erroneous code:
+Erroneous code example:
```compile_fail,E0508
struct NonCopy;
@@ -1872,7 +1909,7 @@
This error occurs when an attempt is made to move out of a value whose type
implements the `Drop` trait.
-Example of erroneous code:
+Erroneous code example:
```compile_fail,E0509
struct FancyNum {
@@ -1982,30 +2019,14 @@
to go "back in time" to the `None` arm.
"##,
-E0579: r##"
-When matching against an exclusive range, the compiler verifies that the range
-is non-empty. Exclusive range patterns include the start point but not the end
-point, so this is equivalent to requiring the start of the range to be less
-than the end of the range.
-
-For example:
-
-```compile_fail
-match 5u32 {
- // This range is ok, albeit pointless.
- 1 .. 2 => {}
- // This range is empty, and the compiler can tell.
- 5 .. 5 => {}
-}
-```
-"##,
-
E0515: r##"
Cannot return value that references local variable
Local variables, function parameters and temporaries are all dropped before the
end of the function body. So a reference to them cannot be returned.
+Erroneous code example:
+
```compile_fail,E0515
fn get_dangling_reference() -> &'static i32 {
let x = 0;
@@ -2101,6 +2122,28 @@
```
"##,
+E0579: r##"
+When matching against an exclusive range, the compiler verifies that the range
+is non-empty. Exclusive range patterns include the start point but not the end
+point, so this is equivalent to requiring the start of the range to be less
+than the end of the range.
+
+Erroneous code example:
+
+```compile_fail,E0579
+#![feature(exclusive_range_pattern)]
+
+fn main() {
+ match 5u32 {
+ // This range is ok, albeit pointless.
+ 1 .. 2 => {}
+ // This range is empty, and the compiler can tell.
+ 5 .. 5 => {} // error!
+ }
+}
+```
+"##,
+
E0595: r##"
#### Note: this error code is no longer emitted by the compiler.
@@ -2124,7 +2167,7 @@
E0596: r##"
This error occurs because you tried to mutably borrow a non-mutable variable.
-Example of erroneous code:
+Erroneous code example:
```compile_fail,E0596
let x = 1;
@@ -2143,7 +2186,7 @@
E0597: r##"
This error occurs because a value was dropped while it was still borrowed
-Example of erroneous code:
+Erroneous code example:
```compile_fail,E0597
struct Foo<'a> {
@@ -2180,6 +2223,8 @@
This error occurs because a borrow in a generator persists across a
yield point.
+Erroneous code example:
+
```compile_fail,E0626
# #![feature(generators, generator_trait, pin)]
# use std::ops::Generator;
@@ -2271,7 +2316,7 @@
This error occurs because a borrow of a thread-local variable was made inside a
function which outlived the lifetime of the function.
-Example of erroneous code:
+Erroneous code example:
```compile_fail,E0712
#![feature(thread_local)]
@@ -2293,7 +2338,7 @@
This error occurs when an attempt is made to borrow state past the end of the
lifetime of a type that implements the `Drop` trait.
-Example of erroneous code:
+Erroneous code example:
```compile_fail,E0713
#![feature(nll)]
diff --git a/src/librustc_resolve/build_reduced_graph.rs b/src/librustc_resolve/build_reduced_graph.rs
index 1f86aaf..0d5361f 100644
--- a/src/librustc_resolve/build_reduced_graph.rs
+++ b/src/librustc_resolve/build_reduced_graph.rs
@@ -94,7 +94,8 @@
where T: ToNameBinding<'a>,
{
let binding = def.to_name_binding(self.arenas);
- if let Err(old_binding) = self.try_define(parent, ident, ns, binding) {
+ let key = self.new_key(ident, ns);
+ if let Err(old_binding) = self.try_define(parent, key, binding) {
self.report_conflict(parent, ident, ns, old_binding, &binding);
}
}
@@ -349,9 +350,12 @@
self.r.indeterminate_imports.push(directive);
match directive.subclass {
+ // Don't add unresolved underscore imports to modules
+ SingleImport { target: Ident { name: kw::Underscore, .. }, .. } => {}
SingleImport { target, type_ns_only, .. } => {
self.r.per_ns(|this, ns| if !type_ns_only || ns == TypeNS {
- let mut resolution = this.resolution(current_module, target, ns).borrow_mut();
+ let key = this.new_key(target, ns);
+ let mut resolution = this.resolution(current_module, key).borrow_mut();
resolution.add_single_import(directive);
});
}
@@ -407,7 +411,7 @@
};
match use_tree.kind {
ast::UseTreeKind::Simple(rename, ..) => {
- let mut ident = use_tree.ident().gensym_if_underscore();
+ let mut ident = use_tree.ident();
let mut module_path = prefix;
let mut source = module_path.pop().unwrap();
let mut type_ns_only = false;
@@ -585,7 +589,7 @@
let parent_scope = &self.parent_scope;
let parent = parent_scope.module;
let expansion = parent_scope.expansion;
- let ident = item.ident.gensym_if_underscore();
+ let ident = item.ident;
let sp = item.span;
let vis = self.resolve_visibility(&item.vis);
@@ -851,10 +855,6 @@
fn build_reduced_graph_for_external_crate_res(&mut self, child: Export<NodeId>) {
let parent = self.parent_scope.module;
let Export { ident, res, vis, span } = child;
- // FIXME: We shouldn't create the gensym here, it should come from metadata,
- // but metadata cannot encode gensyms currently, so we create it here.
- // This is only a guess, two equivalent idents may incorrectly get different gensyms here.
- let ident = ident.gensym_if_underscore();
let expansion = ExpnId::root(); // FIXME(jseyfried) intercrate hygiene
// Record primary definitions.
match res {
diff --git a/src/librustc_resolve/diagnostics.rs b/src/librustc_resolve/diagnostics.rs
index d713315d..de87580 100644
--- a/src/librustc_resolve/diagnostics.rs
+++ b/src/librustc_resolve/diagnostics.rs
@@ -80,11 +80,11 @@
names: &mut Vec<TypoSuggestion>,
filter_fn: &impl Fn(Res) -> bool,
) {
- for (&(ident, _), resolution) in self.resolutions(module).borrow().iter() {
+ for (key, resolution) in self.resolutions(module).borrow().iter() {
if let Some(binding) = resolution.borrow().binding {
let res = binding.res();
if filter_fn(res) {
- names.push(TypoSuggestion::from_res(ident.name, res));
+ names.push(TypoSuggestion::from_res(key.ident.name, res));
}
}
}
@@ -849,7 +849,7 @@
}
let resolutions = self.r.resolutions(crate_module).borrow();
- let resolution = resolutions.get(&(ident, MacroNS))?;
+ let resolution = resolutions.get(&self.r.new_key(ident, MacroNS))?;
let binding = resolution.borrow().binding()?;
if let Res::Def(DefKind::Macro(MacroKind::Bang), _) = binding.res() {
let module_name = crate_module.kind.name().unwrap();
diff --git a/src/librustc_resolve/error_codes.rs b/src/librustc_resolve/error_codes.rs
index 4734677..1e65cba 100644
--- a/src/librustc_resolve/error_codes.rs
+++ b/src/librustc_resolve/error_codes.rs
@@ -1611,6 +1611,56 @@
```
"##,
+E0574: r##"
+Something other than a struct, variant or union has been used when one was
+expected.
+
+Erroneous code example:
+
+```compile_fail,E0574
+mod Mordor {}
+
+let sauron = Mordor { x: () }; // error!
+
+enum Jak {
+ Daxter { i: isize },
+}
+
+let eco = Jak::Daxter { i: 1 };
+match eco {
+ Jak { i } => {} // error!
+}
+```
+
+In all these errors, a type was expected. For example, in the first error,
+we tried to instantiate the `Mordor` module, which is impossible. If you want
+to instantiate a type inside a module, you can do it as follow:
+
+```
+mod Mordor {
+ pub struct TheRing {
+ pub x: usize,
+ }
+}
+
+let sauron = Mordor::TheRing { x: 1 }; // ok!
+```
+
+In the second error, we tried to bind the `Jak` enum directly, which is not
+possible: you can only bind one of its variants. To do so:
+
+```
+enum Jak {
+ Daxter { i: isize },
+}
+
+let eco = Jak::Daxter { i: 1 };
+match eco {
+ Jak::Daxter { i } => {} // ok!
+}
+```
+"##,
+
E0603: r##"
A private item was used outside its scope.
@@ -1739,7 +1789,6 @@
// E0467, removed
// E0470, removed
E0573,
- E0574,
E0575,
E0576,
E0577,
diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs
index 5f77bcf..e5b0ef8 100644
--- a/src/librustc_resolve/lib.rs
+++ b/src/librustc_resolve/lib.rs
@@ -432,7 +432,22 @@
}
}
-type Resolutions<'a> = RefCell<FxIndexMap<(Ident, Namespace), &'a RefCell<NameResolution<'a>>>>;
+/// A key that identifies a binding in a given `Module`.
+///
+/// Multiple bindings in the same module can have the same key (in a valid
+/// program) if all but one of them come from glob imports.
+#[derive(Copy, Clone, PartialEq, Eq, Hash)]
+struct BindingKey {
+ /// The identifier for the binding, aways the `modern` version of the
+ /// identifier.
+ ident: Ident,
+ ns: Namespace,
+ /// 0 if ident is not `_`, otherwise a value that's unique to the specific
+ /// `_` in the expanded AST that introduced this binding.
+ disambiguator: u32,
+}
+
+type Resolutions<'a> = RefCell<FxIndexMap<BindingKey, &'a RefCell<NameResolution<'a>>>>;
/// One node in the tree of modules.
pub struct ModuleData<'a> {
@@ -492,8 +507,8 @@
fn for_each_child<R, F>(&'a self, resolver: &mut R, mut f: F)
where R: AsMut<Resolver<'a>>, F: FnMut(&mut R, Ident, Namespace, &'a NameBinding<'a>)
{
- for (&(ident, ns), name_resolution) in resolver.as_mut().resolutions(self).borrow().iter() {
- name_resolution.borrow().binding.map(|binding| f(resolver, ident, ns, binding));
+ for (key, name_resolution) in resolver.as_mut().resolutions(self).borrow().iter() {
+ name_resolution.borrow().binding.map(|binding| f(resolver, key.ident, key.ns, binding));
}
}
@@ -882,6 +897,7 @@
module_map: FxHashMap<DefId, Module<'a>>,
extern_module_map: FxHashMap<DefId, Module<'a>>,
binding_parent_modules: FxHashMap<PtrKey<'a, NameBinding<'a>>, Module<'a>>,
+ underscore_disambiguator: u32,
/// Maps glob imports to the names of items actually imported.
pub glob_map: GlobMap,
@@ -1160,6 +1176,7 @@
extern_crate_map: Default::default(),
export_map: FxHashMap::default(),
trait_map: Default::default(),
+ underscore_disambiguator: 0,
empty_module,
module_map,
block_map: Default::default(),
@@ -1284,6 +1301,17 @@
self.arenas.alloc_module(module)
}
+ fn new_key(&mut self, ident: Ident, ns: Namespace) -> BindingKey {
+ let ident = ident.modern();
+ let disambiguator = if ident.name == kw::Underscore {
+ self.underscore_disambiguator += 1;
+ self.underscore_disambiguator
+ } else {
+ 0
+ };
+ BindingKey { ident, ns, disambiguator }
+ }
+
fn resolutions(&mut self, module: Module<'a>) -> &'a Resolutions<'a> {
if module.populate_on_access.get() {
module.populate_on_access.set(false);
@@ -1292,9 +1320,9 @@
&module.lazy_resolutions
}
- fn resolution(&mut self, module: Module<'a>, ident: Ident, ns: Namespace)
+ fn resolution(&mut self, module: Module<'a>, key: BindingKey)
-> &'a RefCell<NameResolution<'a>> {
- *self.resolutions(module).borrow_mut().entry((ident.modern(), ns))
+ *self.resolutions(module).borrow_mut().entry(key)
.or_insert_with(|| self.arenas.alloc_name_resolution())
}
diff --git a/src/librustc_resolve/resolve_imports.rs b/src/librustc_resolve/resolve_imports.rs
index 3603431..56fd2da 100644
--- a/src/librustc_resolve/resolve_imports.rs
+++ b/src/librustc_resolve/resolve_imports.rs
@@ -7,7 +7,7 @@
use crate::Determinacy::{self, *};
use crate::Namespace::{self, TypeNS, MacroNS};
use crate::{NameBinding, NameBindingKind, ToNameBinding, PathResult, PrivacyError};
-use crate::{Resolver, ResolutionError, Segment, ModuleKind};
+use crate::{Resolver, ResolutionError, BindingKey, Segment, ModuleKind};
use crate::{names_to_string, module_to_string};
use crate::diagnostics::Suggestion;
@@ -235,7 +235,8 @@
}
};
- let resolution = self.resolution(module, ident, ns)
+ let key = self.new_key(ident, ns);
+ let resolution = self.resolution(module, key)
.try_borrow_mut()
.map_err(|_| (Determined, Weak::No))?; // This happens when there is a cycle of imports.
@@ -447,17 +448,16 @@
}
// Define the name or return the existing binding if there is a collision.
- pub fn try_define(
+ crate fn try_define(
&mut self,
module: Module<'a>,
- ident: Ident,
- ns: Namespace,
+ key: BindingKey,
binding: &'a NameBinding<'a>,
) -> Result<(), &'a NameBinding<'a>> {
let res = binding.res();
- self.check_reserved_macro_name(ident, res);
+ self.check_reserved_macro_name(key.ident, res);
self.set_binding_parent_module(binding, module);
- self.update_resolution(module, ident, ns, |this, resolution| {
+ self.update_resolution(module, key, |this, resolution| {
if let Some(old_binding) = resolution.binding {
if res == Res::Err {
// Do not override real bindings with `Res::Err`s from error recovery.
@@ -479,8 +479,9 @@
} else {
(binding, old_binding)
};
- if glob_binding.res() != nonglob_binding.res() &&
- ns == MacroNS && nonglob_binding.expansion != ExpnId::root() {
+ if glob_binding.res() != nonglob_binding.res()
+ && key.ns == MacroNS && nonglob_binding.expansion != ExpnId::root()
+ {
resolution.binding = Some(this.ambiguity(
AmbiguityKind::GlobVsExpanded,
nonglob_binding,
@@ -499,9 +500,9 @@
DUPLICATE_MACRO_EXPORTS,
CRATE_NODE_ID,
binding.span,
- &format!("a macro named `{}` has already been exported", ident),
+ &format!("a macro named `{}` has already been exported", key.ident),
BuiltinLintDiagnostics::DuplicatedMacroExports(
- ident, old_binding.span, binding.span));
+ key.ident, old_binding.span, binding.span));
resolution.binding = Some(binding);
} else {
@@ -531,9 +532,9 @@
// Use `f` to mutate the resolution of the name in the module.
// If the resolution becomes a success, define it in the module's glob importers.
fn update_resolution<T, F>(
- &mut self, module: Module<'a>,
- ident: Ident,
- ns: Namespace,
+ &mut self,
+ module: Module<'a>,
+ key: BindingKey,
f: F,
) -> T
where F: FnOnce(&mut Resolver<'a>, &mut NameResolution<'a>) -> T
@@ -541,7 +542,7 @@
// Ensure that `resolution` isn't borrowed when defining in the module's glob importers,
// during which the resolution might end up getting re-defined via a glob cycle.
let (binding, t) = {
- let resolution = &mut *self.resolution(module, ident, ns).borrow_mut();
+ let resolution = &mut *self.resolution(module, key).borrow_mut();
let old_binding = resolution.binding();
let t = f(self, resolution);
@@ -558,7 +559,7 @@
// Define `binding` in `module`s glob importers.
for directive in module.glob_importers.borrow_mut().iter() {
- let mut ident = ident.modern();
+ let mut ident = key.ident;
let scope = match ident.span.reverse_glob_adjust(module.expansion, directive.span) {
Some(Some(def)) => self.macro_def_scope(def),
Some(None) => directive.parent_scope.module,
@@ -566,7 +567,8 @@
};
if self.is_accessible_from(binding.vis, scope) {
let imported_binding = self.import(binding, directive);
- let _ = self.try_define(directive.parent_scope.module, ident, ns, imported_binding);
+ let key = BindingKey { ident, ..key };
+ let _ = self.try_define(directive.parent_scope.module, key, imported_binding);
}
}
@@ -580,7 +582,8 @@
let dummy_binding = self.dummy_binding;
let dummy_binding = self.import(dummy_binding, directive);
self.per_ns(|this, ns| {
- let _ = this.try_define(directive.parent_scope.module, target, ns, dummy_binding);
+ let key = this.new_key(target, ns);
+ let _ = this.try_define(directive.parent_scope.module, key, dummy_binding);
// Consider erroneous imports used to avoid duplicate diagnostics.
this.record_use(target, ns, dummy_binding, false);
});
@@ -820,8 +823,11 @@
let parent = directive.parent_scope.module;
match source_bindings[ns].get() {
Err(Undetermined) => indeterminate = true,
+ // Don't update the resolution, because it was never added.
+ Err(Determined) if target.name == kw::Underscore => {}
Err(Determined) => {
- this.update_resolution(parent, target, ns, |_, resolution| {
+ let key = this.new_key(target, ns);
+ this.update_resolution(parent, key, |_, resolution| {
resolution.single_imports.remove(&PtrKey(directive));
});
}
@@ -1052,7 +1058,7 @@
_ => None,
};
let resolutions = resolutions.as_ref().into_iter().flat_map(|r| r.iter());
- let names = resolutions.filter_map(|(&(ref i, _), resolution)| {
+ let names = resolutions.filter_map(|(BindingKey { ident: i, .. }, resolution)| {
if *i == ident { return None; } // Never suggest the same name
match *resolution.borrow() {
NameResolution { binding: Some(name_binding), .. } => {
@@ -1301,19 +1307,18 @@
// Ensure that `resolutions` isn't borrowed during `try_define`,
// since it might get updated via a glob cycle.
- let bindings = self.r.resolutions(module).borrow().iter().filter_map(|(ident, resolution)| {
- resolution.borrow().binding().map(|binding| (*ident, binding))
+ let bindings = self.r.resolutions(module).borrow().iter().filter_map(|(key, resolution)| {
+ resolution.borrow().binding().map(|binding| (*key, binding))
}).collect::<Vec<_>>();
- for ((mut ident, ns), binding) in bindings {
- let scope = match ident.span.reverse_glob_adjust(module.expansion, directive.span) {
+ for (mut key, binding) in bindings {
+ let scope = match key.ident.span.reverse_glob_adjust(module.expansion, directive.span) {
Some(Some(def)) => self.r.macro_def_scope(def),
Some(None) => directive.parent_scope.module,
None => continue,
};
if self.r.is_accessible_from(binding.pseudo_vis(), scope) {
let imported_binding = self.r.import(binding, directive);
- let _ =
- self.r.try_define(directive.parent_scope.module, ident, ns, imported_binding);
+ let _ = self.r.try_define(directive.parent_scope.module, key, imported_binding);
}
}
@@ -1329,29 +1334,23 @@
let mut reexports = Vec::new();
- for (&(ident, ns), resolution) in self.r.resolutions(module).borrow().iter() {
- let resolution = &mut *resolution.borrow_mut();
- let binding = match resolution.binding {
- Some(binding) => binding,
- None => continue,
- };
-
+ module.for_each_child(self.r, |this, ident, ns, binding| {
// Filter away ambiguous imports and anything that has def-site
// hygiene.
// FIXME: Implement actual cross-crate hygiene.
let is_good_import = binding.is_import() && !binding.is_ambiguity()
- && !ident.span.modern().from_expansion();
+ && !ident.span.from_expansion();
if is_good_import || binding.is_macro_def() {
let res = binding.res();
if res != Res::Err {
if let Some(def_id) = res.opt_def_id() {
if !def_id.is_local() {
- self.r.cstore.export_macros_untracked(def_id.krate);
+ this.cstore.export_macros_untracked(def_id.krate);
}
}
reexports.push(Export {
- ident: ident.modern(),
- res: res,
+ ident,
+ res,
span: binding.span,
vis: binding.vis,
});
@@ -1360,7 +1359,7 @@
if let NameBindingKind::Import { binding: orig_binding, directive, .. } = binding.kind {
if ns == TypeNS && orig_binding.is_variant() &&
- !orig_binding.vis.is_at_least(binding.vis, &*self) {
+ !orig_binding.vis.is_at_least(binding.vis, &*this) {
let msg = match directive.subclass {
ImportDirectiveSubclass::SingleImport { .. } => {
format!("variant `{}` is private and cannot be re-exported",
@@ -1372,33 +1371,34 @@
let error_id = (DiagnosticMessageId::ErrorId(0), // no code?!
Some(binding.span),
msg.clone());
- let fresh = self.r.session.one_time_diagnostics
+ let fresh = this.session.one_time_diagnostics
.borrow_mut().insert(error_id);
if !fresh {
- continue;
+ return;
}
msg
},
ref s @ _ => bug!("unexpected import subclass {:?}", s)
};
- let mut err = self.r.session.struct_span_err(binding.span, &msg);
+ let mut err = this.session.struct_span_err(binding.span, &msg);
let imported_module = match directive.imported_module.get() {
Some(ModuleOrUniformRoot::Module(module)) => module,
_ => bug!("module should exist"),
};
let parent_module = imported_module.parent.expect("parent should exist");
- let resolutions = self.r.resolutions(parent_module).borrow();
+ let resolutions = this.resolutions(parent_module).borrow();
let enum_path_segment_index = directive.module_path.len() - 1;
let enum_ident = directive.module_path[enum_path_segment_index].ident;
- let enum_resolution = resolutions.get(&(enum_ident, TypeNS))
+ let key = this.new_key(enum_ident, TypeNS);
+ let enum_resolution = resolutions.get(&key)
.expect("resolution should exist");
let enum_span = enum_resolution.borrow()
.binding.expect("binding should exist")
.span;
- let enum_def_span = self.r.session.source_map().def_span(enum_span);
- let enum_def_snippet = self.r.session.source_map()
+ let enum_def_span = this.session.source_map().def_span(enum_span);
+ let enum_def_snippet = this.session.source_map()
.span_to_snippet(enum_def_span).expect("snippet should exist");
// potentially need to strip extant `crate`/`pub(path)` for suggestion
let after_vis_index = enum_def_snippet.find("enum")
@@ -1406,7 +1406,7 @@
let suggestion = format!("pub {}",
&enum_def_snippet[after_vis_index..]);
- self.r.session
+ this.session
.diag_span_suggestion_once(&mut err,
DiagnosticMessageId::ErrorId(0),
enum_def_span,
@@ -1415,7 +1415,7 @@
err.emit();
}
}
- }
+ });
if reexports.len() > 0 {
if let Some(def_id) = module.def_id() {
diff --git a/src/librustc_save_analysis/dump_visitor.rs b/src/librustc_save_analysis/dump_visitor.rs
index edd2db3..502ae33 100644
--- a/src/librustc_save_analysis/dump_visitor.rs
+++ b/src/librustc_save_analysis/dump_visitor.rs
@@ -115,15 +115,17 @@
F: FnOnce(&mut Self),
{
let item_def_id = self.tcx.hir().local_def_id_from_node_id(item_id);
- if self.tcx.has_typeck_tables(item_def_id) {
- let tables = self.tcx.typeck_tables_of(item_def_id);
- let old_tables = self.save_ctxt.tables;
- self.save_ctxt.tables = tables;
- f(self);
- self.save_ctxt.tables = old_tables;
+
+ let tables = if self.tcx.has_typeck_tables(item_def_id) {
+ self.tcx.typeck_tables_of(item_def_id)
} else {
- f(self);
- }
+ self.save_ctxt.empty_tables
+ };
+
+ let old_tables = self.save_ctxt.tables;
+ self.save_ctxt.tables = tables;
+ f(self);
+ self.save_ctxt.tables = old_tables;
}
fn span_from_span(&self, span: Span) -> SpanData {
@@ -530,12 +532,14 @@
);
}
- for field in def.fields() {
- self.process_struct_field_def(field, item.id);
- self.visit_ty(&field.ty);
- }
+ self.nest_tables(item.id, |v| {
+ for field in def.fields() {
+ v.process_struct_field_def(field, item.id);
+ v.visit_ty(&field.ty);
+ }
- self.process_generic_params(ty_params, &qualname, item.id);
+ v.process_generic_params(ty_params, &qualname, item.id);
+ });
}
fn process_enum(
diff --git a/src/librustc_save_analysis/lib.rs b/src/librustc_save_analysis/lib.rs
index 70b508d..1cfb84b 100644
--- a/src/librustc_save_analysis/lib.rs
+++ b/src/librustc_save_analysis/lib.rs
@@ -48,6 +48,9 @@
pub struct SaveContext<'l, 'tcx> {
tcx: TyCtxt<'tcx>,
tables: &'l ty::TypeckTables<'tcx>,
+ /// Used as a fallback when nesting the typeck tables during item processing
+ /// (if these are not available for that item, e.g. don't own a body)
+ empty_tables: &'l ty::TypeckTables<'tcx>,
access_levels: &'l AccessLevels,
span_utils: SpanUtils<'tcx>,
config: Config,
@@ -1114,6 +1117,7 @@
let save_ctxt = SaveContext {
tcx,
tables: &ty::TypeckTables::empty(None),
+ empty_tables: &ty::TypeckTables::empty(None),
access_levels: &access_levels,
span_utils: SpanUtils::new(&tcx.sess),
config: find_config(config),
diff --git a/src/librustc_typeck/check/closure.rs b/src/librustc_typeck/check/closure.rs
index 8b97bf6..4f41339 100644
--- a/src/librustc_typeck/check/closure.rs
+++ b/src/librustc_typeck/check/closure.rs
@@ -611,6 +611,16 @@
Some(hir::GeneratorKind::Async(hir::AsyncGeneratorKind::Fn)) => {
debug!("supplied_sig_of_closure: closure is async fn body");
self.deduce_future_output_from_obligations(expr_def_id)
+ .unwrap_or_else(|| {
+ // AFAIK, deducing the future output
+ // always succeeds *except* in error cases
+ // like #65159. I'd like to return Error
+ // here, but I can't because I can't
+ // easily (and locally) prove that we
+ // *have* reported an
+ // error. --nikomatsakis
+ astconv.ty_infer(None, decl.output.span())
+ })
}
_ => astconv.ty_infer(None, decl.output.span()),
@@ -645,7 +655,7 @@
fn deduce_future_output_from_obligations(
&self,
expr_def_id: DefId,
- ) -> Ty<'tcx> {
+ ) -> Option<Ty<'tcx>> {
debug!("deduce_future_output_from_obligations(expr_def_id={:?})", expr_def_id);
let ret_coercion =
@@ -688,8 +698,7 @@
} else {
None
}
- })
- .unwrap();
+ });
debug!("deduce_future_output_from_obligations: output_ty={:?}", output_ty);
output_ty
diff --git a/src/librustc_typeck/check/method/suggest.rs b/src/librustc_typeck/check/method/suggest.rs
index 96cc5aa..f2d001e 100644
--- a/src/librustc_typeck/check/method/suggest.rs
+++ b/src/librustc_typeck/check/method/suggest.rs
@@ -777,7 +777,7 @@
} else {
"items from traits can only be used if the trait is implemented and in scope"
});
- let mut msg = format!(
+ let message = |action| format!(
"the following {traits_define} an item `{name}`, perhaps you need to {action} \
{one_of_them}:",
traits_define = if candidates.len() == 1 {
@@ -785,11 +785,7 @@
} else {
"traits define"
},
- action = if let Some(param) = param_type {
- format!("restrict type parameter `{}` with", param)
- } else {
- "implement".to_string()
- },
+ action = action,
one_of_them = if candidates.len() == 1 {
"it"
} else {
@@ -809,50 +805,81 @@
// Get the `hir::Param` to verify whether it already has any bounds.
// We do this to avoid suggesting code that ends up as `T: FooBar`,
// instead we suggest `T: Foo + Bar` in that case.
- let mut has_bounds = None;
- let mut impl_trait = false;
- if let Node::GenericParam(ref param) = hir.get(id) {
- let kind = ¶m.kind;
- if let hir::GenericParamKind::Type { synthetic: Some(_), .. } = kind {
- // We've found `fn foo(x: impl Trait)` instead of
- // `fn foo<T>(x: T)`. We want to suggest the correct
- // `fn foo(x: impl Trait + TraitBound)` instead of
- // `fn foo<T: TraitBound>(x: T)`. (See #63706.)
- impl_trait = true;
- has_bounds = param.bounds.get(1);
- } else {
- has_bounds = param.bounds.get(0);
+ match hir.get(id) {
+ Node::GenericParam(ref param) => {
+ let mut impl_trait = false;
+ let has_bounds = if let hir::GenericParamKind::Type {
+ synthetic: Some(_), ..
+ } = ¶m.kind {
+ // We've found `fn foo(x: impl Trait)` instead of
+ // `fn foo<T>(x: T)`. We want to suggest the correct
+ // `fn foo(x: impl Trait + TraitBound)` instead of
+ // `fn foo<T: TraitBound>(x: T)`. (#63706)
+ impl_trait = true;
+ param.bounds.get(1)
+ } else {
+ param.bounds.get(0)
+ };
+ let sp = hir.span(id);
+ let sp = if let Some(first_bound) = has_bounds {
+ // `sp` only covers `T`, change it so that it covers
+ // `T:` when appropriate
+ sp.until(first_bound.span())
+ } else {
+ sp
+ };
+ // FIXME: contrast `t.def_id` against `param.bounds` to not suggest
+ // traits already there. That can happen when the cause is that
+ // we're in a const scope or associated function used as a method.
+ err.span_suggestions(
+ sp,
+ &message(format!(
+ "restrict type parameter `{}` with",
+ param.name.ident().as_str(),
+ )),
+ candidates.iter().map(|t| format!(
+ "{}{} {}{}",
+ param.name.ident().as_str(),
+ if impl_trait { " +" } else { ":" },
+ self.tcx.def_path_str(t.def_id),
+ if has_bounds.is_some() { " + "} else { "" },
+ )),
+ Applicability::MaybeIncorrect,
+ );
+ suggested = true;
}
+ Node::Item(hir::Item {
+ kind: hir::ItemKind::Trait(.., bounds, _), ident, ..
+ }) => {
+ let (sp, sep, article) = if bounds.is_empty() {
+ (ident.span.shrink_to_hi(), ":", "a")
+ } else {
+ (bounds.last().unwrap().span().shrink_to_hi(), " +", "another")
+ };
+ err.span_suggestions(
+ sp,
+ &message(format!("add {} supertrait for", article)),
+ candidates.iter().map(|t| format!(
+ "{} {}",
+ sep,
+ self.tcx.def_path_str(t.def_id),
+ )),
+ Applicability::MaybeIncorrect,
+ );
+ suggested = true;
+ }
+ _ => {}
}
- let sp = hir.span(id);
- // `sp` only covers `T`, change it so that it covers `T:` when appropriate.
- let sp = if let Some(first_bound) = has_bounds {
- sp.until(first_bound.span())
- } else {
- sp
- };
-
- // FIXME: contrast `t.def_id` against `param.bounds` to not suggest traits
- // already there. That can happen when the cause is that we're in a const
- // scope or associated function used as a method.
- err.span_suggestions(
- sp,
- &msg[..],
- candidates.iter().map(|t| format!(
- "{}{} {}{}",
- param,
- if impl_trait { " +" } else { ":" },
- self.tcx.def_path_str(t.def_id),
- if has_bounds.is_some() { " + " } else { "" },
- )),
- Applicability::MaybeIncorrect,
- );
- suggested = true;
}
};
}
if !suggested {
+ let mut msg = message(if let Some(param) = param_type {
+ format!("restrict type parameter `{}` with", param)
+ } else {
+ "implement".to_string()
+ });
for (i, trait_info) in candidates.iter().enumerate() {
msg.push_str(&format!(
"\ncandidate #{}: `{}`",
diff --git a/src/libsyntax/ext/proc_macro_server.rs b/src/libsyntax/ext/proc_macro_server.rs
index 300523c..e0e1a1c 100644
--- a/src/libsyntax/ext/proc_macro_server.rs
+++ b/src/libsyntax/ext/proc_macro_server.rs
@@ -334,8 +334,7 @@
if !Self::is_valid(&string) {
panic!("`{:?}` is not a valid identifier", string)
}
- // Get rid of gensyms to conservatively check rawness on the string contents only.
- if is_raw && !sym.as_interned_str().as_symbol().can_be_raw() {
+ if is_raw && !sym.can_be_raw() {
panic!("`{}` cannot be a raw identifier", string);
}
Ident { sym, is_raw, span }
diff --git a/src/libsyntax_pos/symbol.rs b/src/libsyntax_pos/symbol.rs
index 8298edb..8845b66 100644
--- a/src/libsyntax_pos/symbol.rs
+++ b/src/libsyntax_pos/symbol.rs
@@ -808,25 +808,13 @@
Ident::new(self.name, self.span.modern_and_legacy())
}
- /// Transforms an underscore identifier into one with the same name, but
- /// gensymed. Leaves non-underscore identifiers unchanged.
- pub fn gensym_if_underscore(self) -> Ident {
- if self.name == kw::Underscore {
- let name = with_interner(|interner| interner.gensymed(self.name));
- Ident::new(name, self.span)
- } else {
- self
- }
- }
-
/// Convert the name to a `LocalInternedString`. This is a slowish
/// operation because it requires locking the symbol interner.
pub fn as_str(self) -> LocalInternedString {
self.name.as_str()
}
- /// Convert the name to an `InternedString`. This is a slowish operation
- /// because it requires locking the symbol interner.
+ /// Convert the name to an `InternedString`.
pub fn as_interned_str(self) -> InternedString {
self.name.as_interned_str()
}
@@ -881,26 +869,9 @@
}
}
-/// A symbol is an interned or gensymed string. A gensym is a symbol that is
-/// never equal to any other symbol.
+/// An interned string.
///
-/// Conceptually, a gensym can be thought of as a normal symbol with an
-/// invisible unique suffix. Gensyms are useful when creating new identifiers
-/// that must not match any existing identifiers, e.g. during macro expansion
-/// and syntax desugaring. Because gensyms should always be identifiers, all
-/// gensym operations are on `Ident` rather than `Symbol`. (Indeed, in the
-/// future the gensym-ness may be moved from `Symbol` to hygiene data.)
-///
-/// Examples:
-/// ```
-/// assert_eq!(Ident::from_str("_"), Ident::from_str("_"))
-/// assert_ne!(Ident::from_str("_").gensym_if_underscore(), Ident::from_str("_"))
-/// assert_ne!(
-/// Ident::from_str("_").gensym_if_underscore(),
-/// Ident::from_str("_").gensym_if_underscore(),
-/// )
-/// ```
-/// Internally, a symbol is implemented as an index, and all operations
+/// Internally, a `Symbol` is implemented as an index, and all operations
/// (including hashing, equality, and ordering) operate on that index. The use
/// of `rustc_index::newtype_index!` means that `Option<Symbol>` only takes up 4 bytes,
/// because `rustc_index::newtype_index!` reserves the last 256 values for tagging purposes.
@@ -951,12 +922,9 @@
})
}
- /// Convert to an `InternedString`. This is a slowish operation because it
- /// requires locking the symbol interner.
+ /// Convert to an `InternedString`.
pub fn as_interned_str(self) -> InternedString {
- with_interner(|interner| InternedString {
- symbol: interner.interned(self)
- })
+ InternedString { symbol: self }
}
pub fn as_u32(self) -> u32 {
@@ -966,12 +934,7 @@
impl fmt::Debug for Symbol {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
- let is_gensymed = with_interner(|interner| interner.is_gensymed(*self));
- if is_gensymed {
- write!(f, "{}({:?})", self, self.0)
- } else {
- write!(f, "{}", self)
- }
+ fmt::Display::fmt(self, f)
}
}
@@ -994,15 +957,11 @@
}
// The `&'static str`s in this type actually point into the arena.
-//
-// Note that normal symbols are indexed upward from 0, and gensyms are indexed
-// downward from SymbolIndex::MAX_AS_U32.
#[derive(Default)]
pub struct Interner {
arena: DroplessArena,
names: FxHashMap<&'static str, Symbol>,
strings: Vec<&'static str>,
- gensyms: Vec<Symbol>,
}
impl Interner {
@@ -1035,34 +994,10 @@
self.names.insert(string, name);
name
}
-
- fn interned(&self, symbol: Symbol) -> Symbol {
- if (symbol.0.as_usize()) < self.strings.len() {
- symbol
- } else {
- self.gensyms[(SymbolIndex::MAX_AS_U32 - symbol.0.as_u32()) as usize]
- }
- }
-
- fn gensymed(&mut self, symbol: Symbol) -> Symbol {
- self.gensyms.push(symbol);
- Symbol::new(SymbolIndex::MAX_AS_U32 - self.gensyms.len() as u32 + 1)
- }
-
- fn is_gensymed(&mut self, symbol: Symbol) -> bool {
- symbol.0.as_usize() >= self.strings.len()
- }
-
// Get the symbol as a string. `Symbol::as_str()` should be used in
// preference to this function.
pub fn get(&self, symbol: Symbol) -> &str {
- match self.strings.get(symbol.0.as_usize()) {
- Some(string) => string,
- None => {
- let symbol = self.gensyms[(SymbolIndex::MAX_AS_U32 - symbol.0.as_u32()) as usize];
- self.strings[symbol.0.as_usize()]
- }
- }
+ self.strings[symbol.0.as_usize()]
}
}
@@ -1223,19 +1158,12 @@
}
}
-/// An alternative to `Symbol` that is focused on string contents. It has two
-/// main differences to `Symbol`.
+/// An alternative to `Symbol` that is focused on string contents.
///
-/// First, its implementations of `Hash`, `PartialOrd` and `Ord` work with the
+/// Its implementations of `Hash`, `PartialOrd` and `Ord` work with the
/// string chars rather than the symbol integer. This is useful when hash
/// stability is required across compile sessions, or a guaranteed sort
/// ordering is required.
-///
-/// Second, gensym-ness is irrelevant. E.g.:
-/// ```
-/// assert_ne!(Symbol::gensym("x"), Symbol::gensym("x"))
-/// assert_eq!(Symbol::gensym("x").as_interned_str(), Symbol::gensym("x").as_interned_str())
-/// ```
#[derive(Clone, Copy, PartialEq, Eq)]
pub struct InternedString {
symbol: Symbol,
diff --git a/src/libsyntax_pos/symbol/tests.rs b/src/libsyntax_pos/symbol/tests.rs
index 1b91c9b..f74b9a0 100644
--- a/src/libsyntax_pos/symbol/tests.rs
+++ b/src/libsyntax_pos/symbol/tests.rs
@@ -14,13 +14,6 @@
assert_eq!(i.intern("cat"), Symbol::new(1));
// dog is still at zero
assert_eq!(i.intern("dog"), Symbol::new(0));
- let z = i.intern("zebra");
- assert_eq!(i.gensymed(z), Symbol::new(SymbolIndex::MAX_AS_U32));
- // gensym of same string gets new number:
- assert_eq!(i.gensymed(z), Symbol::new(SymbolIndex::MAX_AS_U32 - 1));
- // gensym of *existing* string gets new number:
- let d = i.intern("dog");
- assert_eq!(i.gensymed(d), Symbol::new(SymbolIndex::MAX_AS_U32 - 2));
}
#[test]
diff --git a/src/test/ui/async-await/issues/issue-65159.rs b/src/test/ui/async-await/issues/issue-65159.rs
new file mode 100644
index 0000000..b5fee06
--- /dev/null
+++ b/src/test/ui/async-await/issues/issue-65159.rs
@@ -0,0 +1,10 @@
+// Regression test for #65159. We used to ICE.
+//
+// edition:2018
+
+async fn copy() -> Result<()> //~ ERROR wrong number of type arguments
+{
+ Ok(())
+}
+
+fn main() { }
diff --git a/src/test/ui/async-await/issues/issue-65159.stderr b/src/test/ui/async-await/issues/issue-65159.stderr
new file mode 100644
index 0000000..56d2c38
--- /dev/null
+++ b/src/test/ui/async-await/issues/issue-65159.stderr
@@ -0,0 +1,9 @@
+error[E0107]: wrong number of type arguments: expected 2, found 1
+ --> $DIR/issue-65159.rs:5:20
+ |
+LL | async fn copy() -> Result<()>
+ | ^^^^^^^^^^ expected 2 type arguments
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0107`.
diff --git a/src/test/ui/async-await/unused-lifetime.rs b/src/test/ui/async-await/unused-lifetime.rs
new file mode 100644
index 0000000..1cf546b
--- /dev/null
+++ b/src/test/ui/async-await/unused-lifetime.rs
@@ -0,0 +1,42 @@
+// edition:2018
+
+// Avoid spurious warnings of unused lifetime. The below async functions
+// are desugered to have an unused lifetime
+// but we don't want to warn about that as there's nothing they can do about it.
+
+#![deny(unused_lifetimes)]
+#![allow(dead_code)]
+
+pub async fn october(s: &str) {
+ println!("{}", s);
+}
+
+pub async fn async_fn(&mut ref s: &mut[i32]) {
+ println!("{:?}", s);
+}
+
+macro_rules! foo_macro {
+ () => {
+ pub async fn async_fn_in_macro(&mut ref _s: &mut[i32]) {}
+ };
+}
+
+foo_macro!();
+
+pub async fn func_with_unused_lifetime<'a>(s: &'a str) {
+ //~^ ERROR lifetime parameter `'a` never used
+ println!("{}", s);
+}
+
+pub async fn func_with_two_unused_lifetime<'a, 'b>(s: &'a str, t: &'b str) {
+ //~^ ERROR lifetime parameter `'a` never used
+ //~^^ ERROR lifetime parameter `'b` never used
+ println!("{}", s);
+}
+
+pub async fn func_with_unused_lifetime_in_two_params<'c>(s: &'c str, t: &'c str) {
+ //~^ ERROR lifetime parameter `'c` never used
+ println!("{}", s);
+}
+
+fn main() {}
diff --git a/src/test/ui/async-await/unused-lifetime.stderr b/src/test/ui/async-await/unused-lifetime.stderr
new file mode 100644
index 0000000..885cdc0
--- /dev/null
+++ b/src/test/ui/async-await/unused-lifetime.stderr
@@ -0,0 +1,32 @@
+error: lifetime parameter `'a` never used
+ --> $DIR/unused-lifetime.rs:26:40
+ |
+LL | pub async fn func_with_unused_lifetime<'a>(s: &'a str) {
+ | ^^
+ |
+note: lint level defined here
+ --> $DIR/unused-lifetime.rs:7:9
+ |
+LL | #![deny(unused_lifetimes)]
+ | ^^^^^^^^^^^^^^^^
+
+error: lifetime parameter `'a` never used
+ --> $DIR/unused-lifetime.rs:31:44
+ |
+LL | pub async fn func_with_two_unused_lifetime<'a, 'b>(s: &'a str, t: &'b str) {
+ | ^^
+
+error: lifetime parameter `'b` never used
+ --> $DIR/unused-lifetime.rs:31:48
+ |
+LL | pub async fn func_with_two_unused_lifetime<'a, 'b>(s: &'a str, t: &'b str) {
+ | ^^
+
+error: lifetime parameter `'c` never used
+ --> $DIR/unused-lifetime.rs:37:54
+ |
+LL | pub async fn func_with_unused_lifetime_in_two_params<'c>(s: &'c str, t: &'c str) {
+ | ^^
+
+error: aborting due to 4 previous errors
+
diff --git a/src/test/ui/coercion/coerce-issue-49593-box-never.rs b/src/test/ui/coercion/coerce-issue-49593-box-never.rs
index f005245..5038eb3 100644
--- a/src/test/ui/coercion/coerce-issue-49593-box-never.rs
+++ b/src/test/ui/coercion/coerce-issue-49593-box-never.rs
@@ -1,4 +1,4 @@
-// build-pass (FIXME(62277): could be check-pass?)
+// check-pass
#![feature(never_type)]
#![allow(unreachable_code)]
diff --git a/src/test/ui/consts/issue-65348.rs b/src/test/ui/consts/issue-65348.rs
new file mode 100644
index 0000000..5eafa83
--- /dev/null
+++ b/src/test/ui/consts/issue-65348.rs
@@ -0,0 +1,23 @@
+// check-pass
+
+struct Generic<T>(T);
+
+impl<T> Generic<T> {
+ const ARRAY: [T; 0] = [];
+ const NEWTYPE_ARRAY: Generic<[T; 0]> = Generic([]);
+ const ARRAY_FIELD: Generic<(i32, [T; 0])> = Generic((0, []));
+}
+
+pub const fn array<T>() -> &'static T {
+ &Generic::<T>::ARRAY[0]
+}
+
+pub const fn newtype_array<T>() -> &'static T {
+ &Generic::<T>::NEWTYPE_ARRAY.0[0]
+}
+
+pub const fn array_field<T>() -> &'static T {
+ &(Generic::<T>::ARRAY_FIELD.0).1[0]
+}
+
+fn main() {}
diff --git a/src/test/ui/feature-gates/feature-gate-exhaustive-patterns.rs b/src/test/ui/feature-gates/feature-gate-exhaustive-patterns.rs
index 27ff5ac..f0cc9ea 100644
--- a/src/test/ui/feature-gates/feature-gate-exhaustive-patterns.rs
+++ b/src/test/ui/feature-gates/feature-gate-exhaustive-patterns.rs
@@ -1,4 +1,5 @@
#![feature(never_type)]
+
fn foo() -> Result<u32, !> {
Ok(123)
}
diff --git a/src/test/ui/feature-gates/feature-gate-exhaustive-patterns.stderr b/src/test/ui/feature-gates/feature-gate-exhaustive-patterns.stderr
index d77fbc1..08c36ce 100644
--- a/src/test/ui/feature-gates/feature-gate-exhaustive-patterns.stderr
+++ b/src/test/ui/feature-gates/feature-gate-exhaustive-patterns.stderr
@@ -1,5 +1,5 @@
error[E0005]: refutable pattern in local binding: `Err(_)` not covered
- --> $DIR/feature-gate-exhaustive-patterns.rs:7:9
+ --> $DIR/feature-gate-exhaustive-patterns.rs:8:9
|
LL | let Ok(_x) = foo();
| ^^^^^^ pattern `Err(_)` not covered
diff --git a/src/test/ui/for-loop-while/loop-break-value.rs b/src/test/ui/for-loop-while/loop-break-value.rs
index e1edbbb..d7209fc 100644
--- a/src/test/ui/for-loop-while/loop-break-value.rs
+++ b/src/test/ui/for-loop-while/loop-break-value.rs
@@ -1,4 +1,5 @@
// run-pass
+
#![allow(unreachable_code)]
#![feature(never_type)]
diff --git a/src/test/ui/generics/issue-65285-incorrect-explicit-lifetime-name-needed.rs b/src/test/ui/generics/issue-65285-incorrect-explicit-lifetime-name-needed.rs
new file mode 100644
index 0000000..54b483f
--- /dev/null
+++ b/src/test/ui/generics/issue-65285-incorrect-explicit-lifetime-name-needed.rs
@@ -0,0 +1,14 @@
+#![crate_type="lib"]
+
+struct Nested<K>(K);
+
+fn should_error<T>() where T : Into<&u32> {}
+//~^ ERROR `&` without an explicit lifetime name cannot be used here [E0637]
+
+trait X<'a, K: 'a> {
+ fn foo<'b, L: X<&'b Nested<K>>>();
+ //~^ ERROR missing lifetime specifier [E0106]
+}
+
+fn bar<'b, L: X<&'b Nested<i32>>>(){}
+//~^ ERROR missing lifetime specifier [E0106]
diff --git a/src/test/ui/generics/issue-65285-incorrect-explicit-lifetime-name-needed.stderr b/src/test/ui/generics/issue-65285-incorrect-explicit-lifetime-name-needed.stderr
new file mode 100644
index 0000000..8720288
--- /dev/null
+++ b/src/test/ui/generics/issue-65285-incorrect-explicit-lifetime-name-needed.stderr
@@ -0,0 +1,21 @@
+error[E0637]: `&` without an explicit lifetime name cannot be used here
+ --> $DIR/issue-65285-incorrect-explicit-lifetime-name-needed.rs:5:37
+ |
+LL | fn should_error<T>() where T : Into<&u32> {}
+ | ^ explicit lifetime name needed here
+
+error[E0106]: missing lifetime specifier
+ --> $DIR/issue-65285-incorrect-explicit-lifetime-name-needed.rs:9:19
+ |
+LL | fn foo<'b, L: X<&'b Nested<K>>>();
+ | ^^^^^^^^^^^^^^^^ expected lifetime parameter
+
+error[E0106]: missing lifetime specifier
+ --> $DIR/issue-65285-incorrect-explicit-lifetime-name-needed.rs:13:15
+ |
+LL | fn bar<'b, L: X<&'b Nested<i32>>>(){}
+ | ^^^^^^^^^^^^^^^^^^ expected lifetime parameter
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0106`.
diff --git a/src/test/ui/issues/issue-17001.stderr b/src/test/ui/issues/issue-17001.stderr
index 2374e82..d7e6069 100644
--- a/src/test/ui/issues/issue-17001.stderr
+++ b/src/test/ui/issues/issue-17001.stderr
@@ -6,3 +6,4 @@
error: aborting due to previous error
+For more information about this error, try `rustc --explain E0574`.
diff --git a/src/test/ui/issues/issue-17405.stderr b/src/test/ui/issues/issue-17405.stderr
index 4b5678a..37274e2 100644
--- a/src/test/ui/issues/issue-17405.stderr
+++ b/src/test/ui/issues/issue-17405.stderr
@@ -6,3 +6,4 @@
error: aborting due to previous error
+For more information about this error, try `rustc --explain E0574`.
diff --git a/src/test/ui/issues/issue-21449.stderr b/src/test/ui/issues/issue-21449.stderr
index 21de1ea..ecaf6fa 100644
--- a/src/test/ui/issues/issue-21449.stderr
+++ b/src/test/ui/issues/issue-21449.stderr
@@ -6,3 +6,4 @@
error: aborting due to previous error
+For more information about this error, try `rustc --explain E0574`.
diff --git a/src/test/ui/issues/issue-23189.stderr b/src/test/ui/issues/issue-23189.stderr
index 50c09f1..ed06521 100644
--- a/src/test/ui/issues/issue-23189.stderr
+++ b/src/test/ui/issues/issue-23189.stderr
@@ -6,3 +6,4 @@
error: aborting due to previous error
+For more information about this error, try `rustc --explain E0574`.
diff --git a/src/test/ui/issues/issue-26459.stderr b/src/test/ui/issues/issue-26459.stderr
index c7909a1..1873692 100644
--- a/src/test/ui/issues/issue-26459.stderr
+++ b/src/test/ui/issues/issue-26459.stderr
@@ -6,3 +6,4 @@
error: aborting due to previous error
+For more information about this error, try `rustc --explain E0574`.
diff --git a/src/test/ui/issues/issue-27815.stderr b/src/test/ui/issues/issue-27815.stderr
index 1d68e3b..43f78cc 100644
--- a/src/test/ui/issues/issue-27815.stderr
+++ b/src/test/ui/issues/issue-27815.stderr
@@ -24,3 +24,4 @@
error: aborting due to 4 previous errors
+For more information about this error, try `rustc --explain E0574`.
diff --git a/src/test/ui/lexical-scopes.stderr b/src/test/ui/lexical-scopes.stderr
index e990f70..38c7393 100644
--- a/src/test/ui/lexical-scopes.stderr
+++ b/src/test/ui/lexical-scopes.stderr
@@ -16,4 +16,5 @@
error: aborting due to 2 previous errors
-For more information about this error, try `rustc --explain E0599`.
+Some errors have detailed explanations: E0574, E0599.
+For more information about an error, try `rustc --explain E0574`.
diff --git a/src/test/ui/lint/must_use-unit.rs b/src/test/ui/lint/must_use-unit.rs
index 9256825..4dd4798 100644
--- a/src/test/ui/lint/must_use-unit.rs
+++ b/src/test/ui/lint/must_use-unit.rs
@@ -1,5 +1,4 @@
#![feature(never_type)]
-
#![deny(unused_must_use)]
#[must_use]
diff --git a/src/test/ui/lint/must_use-unit.stderr b/src/test/ui/lint/must_use-unit.stderr
index f6229c0..0a9939b 100644
--- a/src/test/ui/lint/must_use-unit.stderr
+++ b/src/test/ui/lint/must_use-unit.stderr
@@ -1,17 +1,17 @@
error: unused return value of `foo` that must be used
- --> $DIR/must_use-unit.rs:14:5
+ --> $DIR/must_use-unit.rs:13:5
|
LL | foo();
| ^^^^^^
|
note: lint level defined here
- --> $DIR/must_use-unit.rs:3:9
+ --> $DIR/must_use-unit.rs:2:9
|
LL | #![deny(unused_must_use)]
| ^^^^^^^^^^^^^^^
error: unused return value of `bar` that must be used
- --> $DIR/must_use-unit.rs:16:5
+ --> $DIR/must_use-unit.rs:15:5
|
LL | bar();
| ^^^^^^
diff --git a/src/test/run-fail/adjust_never.rs b/src/test/ui/never_type/adjust_never.rs
similarity index 93%
rename from src/test/run-fail/adjust_never.rs
rename to src/test/ui/never_type/adjust_never.rs
index 8661a2f..3aa5866 100644
--- a/src/test/run-fail/adjust_never.rs
+++ b/src/test/ui/never_type/adjust_never.rs
@@ -1,5 +1,6 @@
// Test that a variable of type ! can coerce to another type.
+// run-fail
// error-pattern:explicit
#![feature(never_type)]
diff --git a/src/test/ui/call-fn-never-arg-wrong-type.rs b/src/test/ui/never_type/call-fn-never-arg-wrong-type.rs
similarity index 100%
rename from src/test/ui/call-fn-never-arg-wrong-type.rs
rename to src/test/ui/never_type/call-fn-never-arg-wrong-type.rs
diff --git a/src/test/ui/call-fn-never-arg-wrong-type.stderr b/src/test/ui/never_type/call-fn-never-arg-wrong-type.stderr
similarity index 100%
rename from src/test/ui/call-fn-never-arg-wrong-type.stderr
rename to src/test/ui/never_type/call-fn-never-arg-wrong-type.stderr
diff --git a/src/test/run-fail/call-fn-never-arg.rs b/src/test/ui/never_type/call-fn-never-arg.rs
similarity index 94%
rename from src/test/run-fail/call-fn-never-arg.rs
rename to src/test/ui/never_type/call-fn-never-arg.rs
index f5b2cfa..6218572 100644
--- a/src/test/run-fail/call-fn-never-arg.rs
+++ b/src/test/ui/never_type/call-fn-never-arg.rs
@@ -1,5 +1,6 @@
// Test that we can use a ! for an argument of type !
+// run-fail
// error-pattern:wowzers!
#![feature(never_type)]
diff --git a/src/test/run-fail/cast-never.rs b/src/test/ui/never_type/cast-never.rs
similarity index 93%
rename from src/test/run-fail/cast-never.rs
rename to src/test/ui/never_type/cast-never.rs
index 0b05a4b..46072e1 100644
--- a/src/test/run-fail/cast-never.rs
+++ b/src/test/ui/never_type/cast-never.rs
@@ -1,5 +1,6 @@
// Test that we can explicitly cast ! to another type
+// run-fail
// error-pattern:explicit
#![feature(never_type)]
diff --git a/src/test/ui/defaulted-never-note.rs b/src/test/ui/never_type/defaulted-never-note.rs
similarity index 100%
rename from src/test/ui/defaulted-never-note.rs
rename to src/test/ui/never_type/defaulted-never-note.rs
diff --git a/src/test/ui/defaulted-never-note.stderr b/src/test/ui/never_type/defaulted-never-note.stderr
similarity index 100%
rename from src/test/ui/defaulted-never-note.stderr
rename to src/test/ui/never_type/defaulted-never-note.stderr
diff --git a/src/test/ui/dispatch_from_dyn_zst.rs b/src/test/ui/never_type/dispatch_from_dyn_zst.rs
similarity index 100%
rename from src/test/ui/dispatch_from_dyn_zst.rs
rename to src/test/ui/never_type/dispatch_from_dyn_zst.rs
diff --git a/src/test/ui/diverging-fallback-control-flow.rs b/src/test/ui/never_type/diverging-fallback-control-flow.rs
similarity index 99%
rename from src/test/ui/diverging-fallback-control-flow.rs
rename to src/test/ui/never_type/diverging-fallback-control-flow.rs
index 0f0f787..c68e636 100644
--- a/src/test/ui/diverging-fallback-control-flow.rs
+++ b/src/test/ui/never_type/diverging-fallback-control-flow.rs
@@ -4,6 +4,7 @@
#![allow(unused_assignments)]
#![allow(unused_variables)]
#![allow(unreachable_code)]
+
// Test various cases where we permit an unconstrained variable
// to fallback based on control-flow.
//
diff --git a/src/test/ui/impl-for-never.rs b/src/test/ui/never_type/impl-for-never.rs
similarity index 99%
rename from src/test/ui/impl-for-never.rs
rename to src/test/ui/never_type/impl-for-never.rs
index c5f1298..9423f08 100644
--- a/src/test/ui/impl-for-never.rs
+++ b/src/test/ui/never_type/impl-for-never.rs
@@ -1,8 +1,9 @@
// run-pass
-// Test that we can call static methods on ! both directly and when it appears in a generic
#![feature(never_type)]
+// Test that we can call static methods on ! both directly and when it appears in a generic
+
trait StringifyType {
fn stringify_type() -> &'static str;
}
diff --git a/src/test/ui/issues/issue-13352.rs b/src/test/ui/never_type/issue-13352.rs
similarity index 100%
rename from src/test/ui/issues/issue-13352.rs
rename to src/test/ui/never_type/issue-13352.rs
diff --git a/src/test/ui/issues/issue-13352.stderr b/src/test/ui/never_type/issue-13352.stderr
similarity index 100%
rename from src/test/ui/issues/issue-13352.stderr
rename to src/test/ui/never_type/issue-13352.stderr
diff --git a/src/test/ui/issues/issue-2149.rs b/src/test/ui/never_type/issue-2149.rs
similarity index 100%
rename from src/test/ui/issues/issue-2149.rs
rename to src/test/ui/never_type/issue-2149.rs
diff --git a/src/test/ui/issues/issue-2149.stderr b/src/test/ui/never_type/issue-2149.stderr
similarity index 100%
rename from src/test/ui/issues/issue-2149.stderr
rename to src/test/ui/never_type/issue-2149.stderr
diff --git a/src/test/ui/issues/issue-44402.rs b/src/test/ui/never_type/issue-44402.rs
similarity index 90%
rename from src/test/ui/issues/issue-44402.rs
rename to src/test/ui/never_type/issue-44402.rs
index 29b7eb5..699e480 100644
--- a/src/test/ui/issues/issue-44402.rs
+++ b/src/test/ui/never_type/issue-44402.rs
@@ -1,4 +1,5 @@
-// build-pass (FIXME(62277): could be check-pass?)
+// check-pass
+
#![allow(dead_code)]
#![feature(never_type)]
#![feature(exhaustive_patterns)]
diff --git a/src/test/ui/never-assign-dead-code.rs b/src/test/ui/never_type/never-assign-dead-code.rs
similarity index 82%
rename from src/test/ui/never-assign-dead-code.rs
rename to src/test/ui/never_type/never-assign-dead-code.rs
index fd5fbc3..7bb7c87 100644
--- a/src/test/ui/never-assign-dead-code.rs
+++ b/src/test/ui/never_type/never-assign-dead-code.rs
@@ -1,9 +1,9 @@
// Test that an assignment of type ! makes the rest of the block dead code.
-#![feature(never_type)]
-// build-pass (FIXME(62277): could be check-pass?)
-#![warn(unused)]
+// check-pass
+#![feature(never_type)]
+#![warn(unused)]
fn main() {
let x: ! = panic!("aah"); //~ WARN unused
diff --git a/src/test/ui/never-assign-dead-code.stderr b/src/test/ui/never_type/never-assign-dead-code.stderr
similarity index 92%
rename from src/test/ui/never-assign-dead-code.stderr
rename to src/test/ui/never_type/never-assign-dead-code.stderr
index b887d58..1860150 100644
--- a/src/test/ui/never-assign-dead-code.stderr
+++ b/src/test/ui/never_type/never-assign-dead-code.stderr
@@ -7,7 +7,7 @@
| ^^^^^^^^ unreachable statement
|
note: lint level defined here
- --> $DIR/never-assign-dead-code.rs:5:9
+ --> $DIR/never-assign-dead-code.rs:6:9
|
LL | #![warn(unused)]
| ^^^^^^
@@ -29,7 +29,7 @@
| ^ help: consider prefixing with an underscore: `_x`
|
note: lint level defined here
- --> $DIR/never-assign-dead-code.rs:5:9
+ --> $DIR/never-assign-dead-code.rs:6:9
|
LL | #![warn(unused)]
| ^^^^^^
diff --git a/src/test/ui/never-assign-wrong-type.rs b/src/test/ui/never_type/never-assign-wrong-type.rs
similarity index 100%
rename from src/test/ui/never-assign-wrong-type.rs
rename to src/test/ui/never_type/never-assign-wrong-type.rs
diff --git a/src/test/ui/never-assign-wrong-type.stderr b/src/test/ui/never_type/never-assign-wrong-type.stderr
similarity index 100%
rename from src/test/ui/never-assign-wrong-type.stderr
rename to src/test/ui/never_type/never-assign-wrong-type.stderr
diff --git a/src/test/run-fail/never-associated-type.rs b/src/test/ui/never_type/never-associated-type.rs
similarity index 95%
rename from src/test/run-fail/never-associated-type.rs
rename to src/test/ui/never_type/never-associated-type.rs
index 587f0f7..7f0a3fe 100644
--- a/src/test/run-fail/never-associated-type.rs
+++ b/src/test/ui/never_type/never-associated-type.rs
@@ -1,5 +1,6 @@
// Test that we can use ! as an associated type.
+// run-fail
// error-pattern:kapow!
#![feature(never_type)]
diff --git a/src/test/ui/never-from-impl-is-reserved.rs b/src/test/ui/never_type/never-from-impl-is-reserved.rs
similarity index 100%
rename from src/test/ui/never-from-impl-is-reserved.rs
rename to src/test/ui/never_type/never-from-impl-is-reserved.rs
diff --git a/src/test/ui/never-from-impl-is-reserved.stderr b/src/test/ui/never_type/never-from-impl-is-reserved.stderr
similarity index 100%
rename from src/test/ui/never-from-impl-is-reserved.stderr
rename to src/test/ui/never_type/never-from-impl-is-reserved.stderr
diff --git a/src/test/ui/never-result.rs b/src/test/ui/never_type/never-result.rs
similarity index 99%
rename from src/test/ui/never-result.rs
rename to src/test/ui/never_type/never-result.rs
index 98ce326..35af379 100644
--- a/src/test/ui/never-result.rs
+++ b/src/test/ui/never_type/never-result.rs
@@ -2,6 +2,7 @@
#![allow(unused_variables)]
#![allow(unreachable_code)]
+
// Test that we can extract a ! through pattern matching then use it as several different types.
#![feature(never_type)]
diff --git a/src/test/run-fail/never-type-arg.rs b/src/test/ui/never_type/never-type-arg.rs
similarity index 95%
rename from src/test/run-fail/never-type-arg.rs
rename to src/test/ui/never_type/never-type-arg.rs
index 1747e96..a82d351 100644
--- a/src/test/run-fail/never-type-arg.rs
+++ b/src/test/ui/never_type/never-type-arg.rs
@@ -1,5 +1,6 @@
// Test that we can use ! as an argument to a trait impl.
+// run-fail
// error-pattern:oh no!
#![feature(never_type)]
diff --git a/src/test/ui/never-type-rvalues.rs b/src/test/ui/never_type/never-type-rvalues.rs
similarity index 100%
rename from src/test/ui/never-type-rvalues.rs
rename to src/test/ui/never_type/never-type-rvalues.rs
diff --git a/src/test/ui/never_coercions.rs b/src/test/ui/never_type/never_coercions.rs
similarity index 100%
rename from src/test/ui/never_coercions.rs
rename to src/test/ui/never_type/never_coercions.rs
diff --git a/src/test/ui/never_transmute_never.rs b/src/test/ui/never_type/never_transmute_never.rs
similarity index 87%
rename from src/test/ui/never_transmute_never.rs
rename to src/test/ui/never_type/never_transmute_never.rs
index 5bad756..fce3ced 100644
--- a/src/test/ui/never_transmute_never.rs
+++ b/src/test/ui/never_type/never_transmute_never.rs
@@ -1,4 +1,4 @@
-// build-pass (FIXME(62277): could be check-pass?)
+// check-pass
#![crate_type="lib"]
diff --git a/src/test/ui/panic-uninitialized-zeroed.rs b/src/test/ui/never_type/panic-uninitialized-zeroed.rs
similarity index 100%
rename from src/test/ui/panic-uninitialized-zeroed.rs
rename to src/test/ui/never_type/panic-uninitialized-zeroed.rs
diff --git a/src/test/ui/try_from.rs b/src/test/ui/never_type/try_from.rs
similarity index 100%
rename from src/test/ui/try_from.rs
rename to src/test/ui/never_type/try_from.rs
diff --git a/src/test/ui/unreachable/auxiliary/unreachable_variant.rs b/src/test/ui/reachable/auxiliary/unreachable_variant.rs
similarity index 100%
rename from src/test/ui/unreachable/auxiliary/unreachable_variant.rs
rename to src/test/ui/reachable/auxiliary/unreachable_variant.rs
diff --git a/src/test/ui/unreachable/unreachable-arm.rs b/src/test/ui/reachable/unreachable-arm.rs
similarity index 100%
rename from src/test/ui/unreachable/unreachable-arm.rs
rename to src/test/ui/reachable/unreachable-arm.rs
diff --git a/src/test/ui/unreachable/unreachable-arm.stderr b/src/test/ui/reachable/unreachable-arm.stderr
similarity index 100%
rename from src/test/ui/unreachable/unreachable-arm.stderr
rename to src/test/ui/reachable/unreachable-arm.stderr
diff --git a/src/test/ui/unreachable/unreachable-code.rs b/src/test/ui/reachable/unreachable-code.rs
similarity index 100%
rename from src/test/ui/unreachable/unreachable-code.rs
rename to src/test/ui/reachable/unreachable-code.rs
diff --git a/src/test/ui/unreachable/unreachable-code.stderr b/src/test/ui/reachable/unreachable-code.stderr
similarity index 100%
rename from src/test/ui/unreachable/unreachable-code.stderr
rename to src/test/ui/reachable/unreachable-code.stderr
diff --git a/src/test/ui/unreachable/unreachable-in-call.rs b/src/test/ui/reachable/unreachable-in-call.rs
similarity index 100%
rename from src/test/ui/unreachable/unreachable-in-call.rs
rename to src/test/ui/reachable/unreachable-in-call.rs
diff --git a/src/test/ui/unreachable/unreachable-in-call.stderr b/src/test/ui/reachable/unreachable-in-call.stderr
similarity index 100%
rename from src/test/ui/unreachable/unreachable-in-call.stderr
rename to src/test/ui/reachable/unreachable-in-call.stderr
diff --git a/src/test/ui/unreachable/unreachable-loop-patterns.rs b/src/test/ui/reachable/unreachable-loop-patterns.rs
similarity index 95%
rename from src/test/ui/unreachable/unreachable-loop-patterns.rs
rename to src/test/ui/reachable/unreachable-loop-patterns.rs
index 56ab1a2..6f1d2ef 100644
--- a/src/test/ui/unreachable/unreachable-loop-patterns.rs
+++ b/src/test/ui/reachable/unreachable-loop-patterns.rs
@@ -1,5 +1,3 @@
-// compile-fail
-
#![feature(never_type)]
#![feature(exhaustive_patterns)]
diff --git a/src/test/ui/unreachable/unreachable-loop-patterns.stderr b/src/test/ui/reachable/unreachable-loop-patterns.stderr
similarity index 73%
rename from src/test/ui/unreachable/unreachable-loop-patterns.stderr
rename to src/test/ui/reachable/unreachable-loop-patterns.stderr
index 254d117..bb51033 100644
--- a/src/test/ui/unreachable/unreachable-loop-patterns.stderr
+++ b/src/test/ui/reachable/unreachable-loop-patterns.stderr
@@ -1,17 +1,17 @@
error: unreachable pattern
- --> $DIR/unreachable-loop-patterns.rs:20:9
+ --> $DIR/unreachable-loop-patterns.rs:18:9
|
LL | for _ in unimplemented!() as Void {}
| ^
|
note: lint level defined here
- --> $DIR/unreachable-loop-patterns.rs:7:9
+ --> $DIR/unreachable-loop-patterns.rs:5:9
|
LL | #![deny(unreachable_patterns)]
| ^^^^^^^^^^^^^^^^^^^^
error: unreachable pattern
- --> $DIR/unreachable-loop-patterns.rs:20:14
+ --> $DIR/unreachable-loop-patterns.rs:18:14
|
LL | for _ in unimplemented!() as Void {}
| ^^^^^^^^^^^^^^^^^^^^^^^^
diff --git a/src/test/ui/unreachable/unreachable-try-pattern.rs b/src/test/ui/reachable/unreachable-try-pattern.rs
similarity index 93%
rename from src/test/ui/unreachable/unreachable-try-pattern.rs
rename to src/test/ui/reachable/unreachable-try-pattern.rs
index cbc5fce..23360e7 100644
--- a/src/test/ui/unreachable/unreachable-try-pattern.rs
+++ b/src/test/ui/reachable/unreachable-try-pattern.rs
@@ -1,4 +1,4 @@
-// build-pass (FIXME(62277): could be check-pass?)
+// check-pass
#![feature(never_type, exhaustive_patterns)]
#![warn(unreachable_code)]
#![warn(unreachable_patterns)]
diff --git a/src/test/ui/unreachable/unreachable-try-pattern.stderr b/src/test/ui/reachable/unreachable-try-pattern.stderr
similarity index 100%
rename from src/test/ui/unreachable/unreachable-try-pattern.stderr
rename to src/test/ui/reachable/unreachable-try-pattern.stderr
diff --git a/src/test/ui/unreachable/unreachable-variant.rs b/src/test/ui/reachable/unreachable-variant.rs
similarity index 100%
rename from src/test/ui/unreachable/unreachable-variant.rs
rename to src/test/ui/reachable/unreachable-variant.rs
diff --git a/src/test/ui/unreachable/unreachable-variant.stderr b/src/test/ui/reachable/unreachable-variant.stderr
similarity index 100%
rename from src/test/ui/unreachable/unreachable-variant.stderr
rename to src/test/ui/reachable/unreachable-variant.stderr
diff --git a/src/test/ui/unreachable/unwarned-match-on-never.rs b/src/test/ui/reachable/unwarned-match-on-never.rs
similarity index 100%
rename from src/test/ui/unreachable/unwarned-match-on-never.rs
rename to src/test/ui/reachable/unwarned-match-on-never.rs
diff --git a/src/test/ui/unreachable/unwarned-match-on-never.stderr b/src/test/ui/reachable/unwarned-match-on-never.stderr
similarity index 100%
rename from src/test/ui/unreachable/unwarned-match-on-never.stderr
rename to src/test/ui/reachable/unwarned-match-on-never.stderr
diff --git a/src/test/ui/resolve/issue-16058.stderr b/src/test/ui/resolve/issue-16058.stderr
index 64177ac..9766f8f 100644
--- a/src/test/ui/resolve/issue-16058.stderr
+++ b/src/test/ui/resolve/issue-16058.stderr
@@ -14,3 +14,4 @@
error: aborting due to previous error
+For more information about this error, try `rustc --explain E0574`.
diff --git a/src/test/ui/save-analysis/issue-64659.rs b/src/test/ui/save-analysis/issue-64659.rs
new file mode 100644
index 0000000..a3d88a2
--- /dev/null
+++ b/src/test/ui/save-analysis/issue-64659.rs
@@ -0,0 +1,10 @@
+// check-pass
+// compile-flags: -Zsave-analysis
+
+trait Trait { type Assoc; }
+
+fn main() {
+ struct Data<T: Trait> {
+ x: T::Assoc,
+ }
+}
diff --git a/src/test/ui/suggestions/constrain-trait.fixed b/src/test/ui/suggestions/constrain-trait.fixed
new file mode 100644
index 0000000..dda9e93
--- /dev/null
+++ b/src/test/ui/suggestions/constrain-trait.fixed
@@ -0,0 +1,47 @@
+// run-rustfix
+// check-only
+
+#[derive(Debug)]
+struct Demo {
+ a: String
+}
+
+trait GetString {
+ fn get_a(&self) -> &String;
+}
+
+trait UseString: std::fmt::Debug + GetString {
+ fn use_string(&self) {
+ println!("{:?}", self.get_a()); //~ ERROR no method named `get_a` found for type `&Self`
+ }
+}
+
+trait UseString2: GetString {
+ fn use_string(&self) {
+ println!("{:?}", self.get_a()); //~ ERROR no method named `get_a` found for type `&Self`
+ }
+}
+
+impl GetString for Demo {
+ fn get_a(&self) -> &String {
+ &self.a
+ }
+}
+
+impl UseString for Demo {}
+impl UseString2 for Demo {}
+
+
+#[cfg(test)]
+mod tests {
+ use crate::{Demo, UseString};
+
+ #[test]
+ fn it_works() {
+ let d = Demo { a: "test".to_string() };
+ d.use_string();
+ }
+}
+
+
+fn main() {}
diff --git a/src/test/ui/suggestions/constrain-trait.rs b/src/test/ui/suggestions/constrain-trait.rs
new file mode 100644
index 0000000..4ef0eff
--- /dev/null
+++ b/src/test/ui/suggestions/constrain-trait.rs
@@ -0,0 +1,47 @@
+// run-rustfix
+// check-only
+
+#[derive(Debug)]
+struct Demo {
+ a: String
+}
+
+trait GetString {
+ fn get_a(&self) -> &String;
+}
+
+trait UseString: std::fmt::Debug {
+ fn use_string(&self) {
+ println!("{:?}", self.get_a()); //~ ERROR no method named `get_a` found for type `&Self`
+ }
+}
+
+trait UseString2 {
+ fn use_string(&self) {
+ println!("{:?}", self.get_a()); //~ ERROR no method named `get_a` found for type `&Self`
+ }
+}
+
+impl GetString for Demo {
+ fn get_a(&self) -> &String {
+ &self.a
+ }
+}
+
+impl UseString for Demo {}
+impl UseString2 for Demo {}
+
+
+#[cfg(test)]
+mod tests {
+ use crate::{Demo, UseString};
+
+ #[test]
+ fn it_works() {
+ let d = Demo { a: "test".to_string() };
+ d.use_string();
+ }
+}
+
+
+fn main() {}
diff --git a/src/test/ui/suggestions/constrain-trait.stderr b/src/test/ui/suggestions/constrain-trait.stderr
new file mode 100644
index 0000000..3cc351a
--- /dev/null
+++ b/src/test/ui/suggestions/constrain-trait.stderr
@@ -0,0 +1,27 @@
+error[E0599]: no method named `get_a` found for type `&Self` in the current scope
+ --> $DIR/constrain-trait.rs:15:31
+ |
+LL | println!("{:?}", self.get_a());
+ | ^^^^^ method not found in `&Self`
+ |
+ = help: items from traits can only be used if the type parameter is bounded by the trait
+help: the following trait defines an item `get_a`, perhaps you need to add another supertrait for it:
+ |
+LL | trait UseString: std::fmt::Debug + GetString {
+ | ^^^^^^^^^^^
+
+error[E0599]: no method named `get_a` found for type `&Self` in the current scope
+ --> $DIR/constrain-trait.rs:21:31
+ |
+LL | println!("{:?}", self.get_a());
+ | ^^^^^ method not found in `&Self`
+ |
+ = help: items from traits can only be used if the type parameter is bounded by the trait
+help: the following trait defines an item `get_a`, perhaps you need to add a supertrait for it:
+ |
+LL | trait UseString2: GetString {
+ | ^^^^^^^^^^^
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0599`.
diff --git a/src/test/ui/traits/trait-as-struct-constructor.stderr b/src/test/ui/traits/trait-as-struct-constructor.stderr
index 434dcbc..e1d54fb 100644
--- a/src/test/ui/traits/trait-as-struct-constructor.stderr
+++ b/src/test/ui/traits/trait-as-struct-constructor.stderr
@@ -6,3 +6,4 @@
error: aborting due to previous error
+For more information about this error, try `rustc --explain E0574`.
diff --git a/src/test/ui/try-block/try-block-in-edition2015.stderr b/src/test/ui/try-block/try-block-in-edition2015.stderr
index 7034cdc..c94e431 100644
--- a/src/test/ui/try-block/try-block-in-edition2015.stderr
+++ b/src/test/ui/try-block/try-block-in-edition2015.stderr
@@ -21,3 +21,4 @@
error: aborting due to 2 previous errors
+For more information about this error, try `rustc --explain E0574`.
diff --git a/src/test/ui/underscore-imports/hygiene-2.rs b/src/test/ui/underscore-imports/hygiene-2.rs
new file mode 100644
index 0000000..bea61ea
--- /dev/null
+++ b/src/test/ui/underscore-imports/hygiene-2.rs
@@ -0,0 +1,33 @@
+// Make sure that underscore imports with different contexts can exist in the
+// same scope.
+
+// check-pass
+
+#![feature(decl_macro)]
+
+mod x {
+ pub use std::ops::Deref as _;
+}
+
+macro n() {
+ pub use crate::x::*;
+}
+
+#[macro_export]
+macro_rules! p {
+ () => { pub use crate::x::*; }
+}
+
+macro m($y:ident) {
+ mod $y {
+ crate::n!(); // Reexport of `Deref` should not be imported in `main`
+ crate::p!(); // Reexport of `Deref` should be imported into `main`
+ }
+}
+
+m!(y);
+
+fn main() {
+ use crate::y::*;
+ (&()).deref();
+}
diff --git a/src/test/ui/underscore-imports/hygiene.rs b/src/test/ui/underscore-imports/hygiene.rs
new file mode 100644
index 0000000..a254f6e
--- /dev/null
+++ b/src/test/ui/underscore-imports/hygiene.rs
@@ -0,0 +1,40 @@
+// Make sure that underscore imports have the same hygiene considerations as
+// other imports.
+
+#![feature(decl_macro)]
+
+mod x {
+ pub use std::ops::Deref as _;
+}
+
+
+macro glob_import() {
+ pub use crate::x::*;
+}
+
+macro underscore_import() {
+ use std::ops::DerefMut as _;
+}
+
+mod y {
+ crate::glob_import!();
+ crate::underscore_import!();
+}
+
+macro create_module($y:ident) {
+ mod $y {
+ crate::glob_import!();
+ crate::underscore_import!();
+ }
+}
+
+create_module!(z);
+
+fn main() {
+ use crate::y::*;
+ use crate::z::*;
+ glob_import!();
+ underscore_import!();
+ (&()).deref(); //~ ERROR no method named `deref`
+ (&mut ()).deref_mut(); //~ ERROR no method named `deref_mut`
+}
diff --git a/src/test/ui/underscore-imports/hygiene.stderr b/src/test/ui/underscore-imports/hygiene.stderr
new file mode 100644
index 0000000..44cfc5c
--- /dev/null
+++ b/src/test/ui/underscore-imports/hygiene.stderr
@@ -0,0 +1,27 @@
+error[E0599]: no method named `deref` found for type `&()` in the current scope
+ --> $DIR/hygiene.rs:38:11
+ |
+LL | (&()).deref();
+ | ^^^^^ method not found in `&()`
+ |
+ = help: items from traits can only be used if the trait is in scope
+help: the following trait is implemented but not in scope; perhaps add a `use` for it:
+ |
+LL | use std::ops::Deref;
+ |
+
+error[E0599]: no method named `deref_mut` found for type `&mut ()` in the current scope
+ --> $DIR/hygiene.rs:39:15
+ |
+LL | (&mut ()).deref_mut();
+ | ^^^^^^^^^ method not found in `&mut ()`
+ |
+ = help: items from traits can only be used if the trait is in scope
+help: the following trait is implemented but not in scope; perhaps add a `use` for it:
+ |
+LL | use std::ops::DerefMut;
+ |
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0599`.
diff --git a/src/test/ui/underscore-imports/macro-expanded.rs b/src/test/ui/underscore-imports/macro-expanded.rs
new file mode 100644
index 0000000..43f527b
--- /dev/null
+++ b/src/test/ui/underscore-imports/macro-expanded.rs
@@ -0,0 +1,45 @@
+// Check that macro expanded underscore imports behave as expected
+
+// check-pass
+
+#![feature(decl_macro, rustc_attrs)]
+
+mod x {
+ pub use std::ops::Not as _;
+}
+
+macro m() {
+ mod w {
+ mod y {
+ pub use std::ops::Deref as _;
+ }
+ use crate::x::*;
+ use self::y::*;
+ use std::ops::DerefMut as _;
+ fn f() {
+ false.not();
+ (&()).deref();
+ (&mut ()).deref_mut();
+ }
+ }
+}
+
+#[rustc_macro_transparency = "transparent"]
+macro n() {
+ mod z {
+ pub use std::ops::Deref as _;
+ }
+ use crate::x::*;
+ use crate::z::*;
+ use std::ops::DerefMut as _;
+ fn f() {
+ false.not();
+ (&()).deref();
+ (&mut ()).deref_mut();
+ }
+}
+
+m!();
+n!();
+
+fn main() {}
diff --git a/src/test/ui/always-inhabited-union-ref.rs b/src/test/ui/uninhabited/always-inhabited-union-ref.rs
similarity index 100%
rename from src/test/ui/always-inhabited-union-ref.rs
rename to src/test/ui/uninhabited/always-inhabited-union-ref.rs
diff --git a/src/test/ui/always-inhabited-union-ref.stderr b/src/test/ui/uninhabited/always-inhabited-union-ref.stderr
similarity index 100%
rename from src/test/ui/always-inhabited-union-ref.stderr
rename to src/test/ui/uninhabited/always-inhabited-union-ref.stderr
diff --git a/src/test/ui/use/issue-18986.stderr b/src/test/ui/use/issue-18986.stderr
index 14e1bb6..6c23178 100644
--- a/src/test/ui/use/issue-18986.stderr
+++ b/src/test/ui/use/issue-18986.stderr
@@ -6,3 +6,4 @@
error: aborting due to previous error
+For more information about this error, try `rustc --explain E0574`.