From f5e991bee01104342ade57d8f2ea51527190c50d Mon Sep 17 00:00:00 2001 From: Gabriel Majeri Date: Sun, 9 Sep 2018 14:22:58 +0300 Subject: [PATCH 01/27] Expand the documentation for the std::sync module Provides an overview on why synchronization is required, as well a short summary of what sync primitives are available. --- src/libstd/sync/mod.rs | 123 +++++++++++++++++++++++++++++++++++++++-- 1 file changed, 119 insertions(+), 4 deletions(-) diff --git a/src/libstd/sync/mod.rs b/src/libstd/sync/mod.rs index e12ef8d9eda2..e06e29940693 100644 --- a/src/libstd/sync/mod.rs +++ b/src/libstd/sync/mod.rs @@ -10,10 +10,125 @@ //! Useful synchronization primitives. //! -//! This module contains useful safe and unsafe synchronization primitives. -//! Most of the primitives in this module do not provide any sort of locking -//! and/or blocking at all, but rather provide the necessary tools to build -//! other types of concurrent primitives. +//! ## The need for synchronization +//! +//! On an ideal single-core CPU, the timeline of events happening in a program +//! is linear, consistent with the order of operations in the code. +//! +//! Considering the following code, operating on some global static variables: +//! +//! ```rust +//! # static mut A: u32 = 0; +//! # static mut B: u32 = 0; +//! # static mut C: u32 = 0; +//! # unsafe { +//! A = 3; +//! B = 4; +//! A = A + B; +//! C = B; +//! println!("{} {} {}", A, B, C); +//! C = A; +//! # } +//! ``` +//! +//! It appears _as if_ some variables stored in memory are changed, an addition +//! is performed, result is stored in A and the variable C is modified twice. +//! When only a single thread is involved, the results are as expected: +//! the line `7 4 4` gets printed. +//! +//! As for what happens behind the scenes, when an optimizing compiler is used +//! the final generated machine code might look very different from the code: +//! +//! - first store to `C` might be moved before the store to `A` or `B`, +//! _as if_ we had written `C = 4; A = 3; B = 4;` +//! +//! - last store to `C` might be removed, since we never read from it again. +//! +//! - assignment of `A + B` to `A` might be removed, the sum can be stored in a +//! in a register until it gets printed, and the global variable never gets +//! updated. +//! +//! - the final result could be determined just by looking at the code at compile time, +//! so [constant folding] might turn the whole block into a simple `println!("7 4 4")` +//! +//! The compiler is allowed to perform any combination of these optimizations, as long +//! as the final optimized code, when executed, produces the same results as the one +//! without optimizations. +//! +//! When multiprocessing is involved (either multiple CPU cores, or multiple +//! physical CPUs), access to global variables (which are shared between threads) +//! could lead to nondeterministic results, **even if** compiler optimizations +//! are disabled. +//! +//! Note that thanks to Rust's safety guarantees, accessing global (static) +//! variables requires `unsafe` code, assuming we don't use any of the +//! synchronization primitives in this module. +//! +//! [constant folding]: https://en.wikipedia.org/wiki/Constant_folding +//! +//! ## Out-of-order execution +//! +//! Instructions can execute in a different order from the one we define, due to +//! various reasons: +//! +//! - **Compiler** reordering instructions: if the compiler can issue an +//! instruction at an earlier point, it will try to do so. For example, it +//! might hoist memory loads at the top of a code block, so that the CPU can +//! start [prefetching] the values from memory. +//! +//! In single-threaded scenarios, this can cause issues when writing signal handlers +//! or certain kinds of low-level code. +//! Use [compiler fences] to prevent this reordering. +//! +//! - **Single processor** executing instructions [out-of-order]: modern CPUs are +//! capable of [superscalar] execution, i.e. multiple instructions might be +//! executing at the same time, even though the machine code describes a +//! sequential process. +//! +//! This kind of reordering is handled transparently by the CPU. +//! +//! - **Multiprocessor** system, where multiple hardware threads run at the same time. +//! In multi-threaded scenarios, you can use two kinds of primitives to deal +//! with synchronization: +//! - [memory fences] to ensure memory accesses are made visibile to other +//! CPUs in the right order. +//! - [atomic operations] to ensure simultaneous access to the same memory +//! location doesn't lead to undefined behavior. +//! +//! [prefetching]: https://en.wikipedia.org/wiki/Cache_prefetching +//! [compiler fences]: atomic::compiler_fence +//! [out-of-order]: https://en.wikipedia.org/wiki/Out-of-order_execution +//! [superscalar]: https://en.wikipedia.org/wiki/Superscalar_processor +//! [memory fences]: atomic::fence +//! [atomics operations]: atomic +//! +//! ## Higher-level synchronization objects +//! +//! Most of the low-level synchronization primitives are quite error-prone and +//! inconvenient to use, which is why the standard library also exposes some +//! higher-level synchronization objects. +//! +//! These abstractions can be built out of lower-level primitives. For efficiency, +//! the sync objects in the standard library are usually implemented with help +//! from the operating system's kernel, which is able to reschedule the threads +//! while they are blocked on acquiring a lock. +//! +//! ## Efficiency +//! +//! Higher-level synchronization mechanisms are usually heavy-weight. +//! While most atomic operations can execute instantaneously, acquiring a +//! [`Mutex`] can involve blocking until another thread releases it. +//! For [`RwLock`], while! any number of readers may acquire it without +//! blocking, each writer will have exclusive access. +//! +//! On the other hand, communication over [channels] can provide a fairly +//! high-level interface without sacrificing performance, at the cost of +//! somewhat more memory. +//! +//! The more synchronization exists between CPUs, the smaller the performance +//! gains from multithreading will be. +//! +//! [channels]: mpsc #![stable(feature = "rust1", since = "1.0.0")] From e0df0ae734ec97ad7cc67cf6bed0d142275571b9 Mon Sep 17 00:00:00 2001 From: Gabriel Majeri Date: Sun, 16 Sep 2018 12:56:44 +0300 Subject: [PATCH 02/27] Make example code use global variables Because `fn main()` was added automatically, the variables were actually local statics. --- src/libstd/sync/mod.rs | 27 ++++++++++++++------------- 1 file changed, 14 insertions(+), 13 deletions(-) diff --git a/src/libstd/sync/mod.rs b/src/libstd/sync/mod.rs index e06e29940693..df153561b4b1 100644 --- a/src/libstd/sync/mod.rs +++ b/src/libstd/sync/mod.rs @@ -18,17 +18,20 @@ //! Considering the following code, operating on some global static variables: //! //! ```rust -//! # static mut A: u32 = 0; -//! # static mut B: u32 = 0; -//! # static mut C: u32 = 0; -//! # unsafe { -//! A = 3; -//! B = 4; -//! A = A + B; -//! C = B; -//! println!("{} {} {}", A, B, C); -//! C = A; -//! # } +//! static mut A: u32 = 0; +//! static mut B: u32 = 0; +//! static mut C: u32 = 0; +//! +//! fn main() { +//! unsafe { +//! A = 3; +//! B = 4; +//! A = A + B; +//! C = B; +//! println!("{} {} {}", A, B, C); +//! C = A; +//! } +//! } //! ``` //! //! It appears _as if_ some variables stored in memory are changed, an addition @@ -42,8 +45,6 @@ //! - first store to `C` might be moved before the store to `A` or `B`, //! _as if_ we had written `C = 4; A = 3; B = 4;` //! -//! - last store to `C` might be removed, since we never read from it again. -//! //! - assignment of `A + B` to `A` might be removed, the sum can be stored in a //! in a register until it gets printed, and the global variable never gets //! updated. From f3fdbbfae8646be30d7a19db059b9cdc42fadbc4 Mon Sep 17 00:00:00 2001 From: Gabriel Majeri Date: Thu, 27 Sep 2018 20:25:04 +0300 Subject: [PATCH 03/27] Address review comments Reword the lead paragraph and turn the list items into complete sentences. --- src/libstd/sync/mod.rs | 29 +++++++++++++++-------------- 1 file changed, 15 insertions(+), 14 deletions(-) diff --git a/src/libstd/sync/mod.rs b/src/libstd/sync/mod.rs index df153561b4b1..bdb6e49aabc2 100644 --- a/src/libstd/sync/mod.rs +++ b/src/libstd/sync/mod.rs @@ -12,8 +12,9 @@ //! //! ## The need for synchronization //! -//! On an ideal single-core CPU, the timeline of events happening in a program -//! is linear, consistent with the order of operations in the code. +//! Conceptually, a Rust program is simply a series of operations which will +//! be executed on a computer. The timeline of events happening in the program +//! is consistent with the order of the operations in the code. //! //! Considering the following code, operating on some global static variables: //! @@ -35,22 +36,22 @@ //! ``` //! //! It appears _as if_ some variables stored in memory are changed, an addition -//! is performed, result is stored in A and the variable C is modified twice. +//! is performed, result is stored in `A` and the variable `C` is modified twice. //! When only a single thread is involved, the results are as expected: //! the line `7 4 4` gets printed. //! -//! As for what happens behind the scenes, when an optimizing compiler is used -//! the final generated machine code might look very different from the code: +//! As for what happens behind the scenes, when optimizations are enabled the +//! final generated machine code might look very different from the code: //! -//! - first store to `C` might be moved before the store to `A` or `B`, -//! _as if_ we had written `C = 4; A = 3; B = 4;` +//! - The first store to `C` might be moved before the store to `A` or `B`, +//! _as if_ we had written `C = 4; A = 3; B = 4`. //! -//! - assignment of `A + B` to `A` might be removed, the sum can be stored in a -//! in a register until it gets printed, and the global variable never gets -//! updated. +//! - Assignment of `A + B` to `A` might be removed, since the sum can be stored +//! in a temporary location until it gets printed, with the global variable +//! never getting updated. //! -//! - the final result could be determined just by looking at the code at compile time, -//! so [constant folding] might turn the whole block into a simple `println!("7 4 4")` +//! - The final result could be determined just by looking at the code at compile time, +//! so [constant folding] might turn the whole block into a simple `println!("7 4 4")`. //! //! The compiler is allowed to perform any combination of these optimizations, as long //! as the final optimized code, when executed, produces the same results as the one @@ -77,8 +78,8 @@ //! might hoist memory loads at the top of a code block, so that the CPU can //! start [prefetching] the values from memory. //! -//! In single-threaded scenarios, this can cause issues when writing signal handlers -//! or certain kinds of low-level code. +//! In single-threaded scenarios, this can cause issues when writing +//! signal handlers or certain kinds of low-level code. //! Use [compiler fences] to prevent this reordering. //! //! - **Single processor** executing instructions [out-of-order]: modern CPUs are From bcec6bb525032b48d8d1793854f61892c21fe8af Mon Sep 17 00:00:00 2001 From: Gabriel Majeri Date: Thu, 27 Sep 2018 22:12:09 +0300 Subject: [PATCH 04/27] Fix broken links --- src/libstd/sync/mod.rs | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/src/libstd/sync/mod.rs b/src/libstd/sync/mod.rs index bdb6e49aabc2..5ba569bf7ce5 100644 --- a/src/libstd/sync/mod.rs +++ b/src/libstd/sync/mod.rs @@ -98,11 +98,11 @@ //! location doesn't lead to undefined behavior. //! //! [prefetching]: https://en.wikipedia.org/wiki/Cache_prefetching -//! [compiler fences]: atomic::compiler_fence +//! [compiler fences]: crate::sync::atomic::compiler_fence //! [out-of-order]: https://en.wikipedia.org/wiki/Out-of-order_execution //! [superscalar]: https://en.wikipedia.org/wiki/Superscalar_processor -//! [memory fences]: atomic::fence -//! [atomics operations]: atomic +//! [memory fences]: crate::sync::atomic::fence +//! [atomic operations]: crate::sync::atomic //! //! ## Higher-level synchronization objects //! @@ -120,7 +120,7 @@ //! Higher-level synchronization mechanisms are usually heavy-weight. //! While most atomic operations can execute instantaneously, acquiring a //! [`Mutex`] can involve blocking until another thread releases it. -//! For [`RwLock`], while! any number of readers may acquire it without +//! For [`RwLock`], while any number of readers may acquire it without //! blocking, each writer will have exclusive access. //! //! On the other hand, communication over [channels] can provide a fairly @@ -130,7 +130,9 @@ //! The more synchronization exists between CPUs, the smaller the performance //! gains from multithreading will be. //! -//! [channels]: mpsc +//! [`Mutex`]: crate::sync::Mutex +//! [`RwLock`]: crate::sync::RwLock +//! [channels]: crate::sync::mpsc #![stable(feature = "rust1", since = "1.0.0")] From 7e921aa59090096593cb4fa202041c91a5d1e36b Mon Sep 17 00:00:00 2001 From: Gabriel Majeri Date: Fri, 28 Sep 2018 10:59:45 +0300 Subject: [PATCH 05/27] Rewrite section on concurrency --- src/libstd/sync/mod.rs | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/libstd/sync/mod.rs b/src/libstd/sync/mod.rs index 5ba569bf7ce5..edbed430e386 100644 --- a/src/libstd/sync/mod.rs +++ b/src/libstd/sync/mod.rs @@ -57,16 +57,17 @@ //! as the final optimized code, when executed, produces the same results as the one //! without optimizations. //! -//! When multiprocessing is involved (either multiple CPU cores, or multiple -//! physical CPUs), access to global variables (which are shared between threads) -//! could lead to nondeterministic results, **even if** compiler optimizations -//! are disabled. +//! Due to the [concurrency] involved in modern computers, assumptions about +//! the program's execution order are often wrong. Access to global variables +//! can lead to nondeterministic results, **even if** compiler optimizations +//! are disabled, and it is **still possible** to introduce synchronization bugs. //! //! Note that thanks to Rust's safety guarantees, accessing global (static) //! variables requires `unsafe` code, assuming we don't use any of the //! synchronization primitives in this module. //! //! [constant folding]: https://en.wikipedia.org/wiki/Constant_folding +//! [concurrency]: https://en.wikipedia.org/wiki/Concurrency_(computer_science) //! //! ## Out-of-order execution //! From 4d58821eee014c231c7a8d4802c3f221bbe14890 Mon Sep 17 00:00:00 2001 From: Philipp Hansch Date: Wed, 3 Oct 2018 13:24:44 +0200 Subject: [PATCH 06/27] Add examples to `TyKind::FnDef` and `TyKind::FnPtr` docs --- src/librustc/ty/sty.rs | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/src/librustc/ty/sty.rs b/src/librustc/ty/sty.rs index 8e4819b68a95..4cf4668443fb 100644 --- a/src/librustc/ty/sty.rs +++ b/src/librustc/ty/sty.rs @@ -127,9 +127,26 @@ pub enum TyKind<'tcx> { /// The anonymous type of a function declaration/definition. Each /// function has a unique type. + /// + /// For example the type of `a` here: + /// + /// ```rust + /// fn foo() -> i32 { 1 } + /// + /// fn hello() { + /// let a = foo; + /// } + /// ``` FnDef(DefId, &'tcx Substs<'tcx>), /// A pointer to a function. Written as `fn() -> i32`. + /// + /// For example the type of `a` here: + /// + /// ```rust + /// fn foo() -> i32 { 1 } + /// let a: fn() -> i32 = foo; + /// ``` FnPtr(PolyFnSig<'tcx>), /// A trait, defined with `trait`. From 113141b6f5d10946f8a66442af3e2b0e2f454745 Mon Sep 17 00:00:00 2001 From: varkor Date: Wed, 3 Oct 2018 14:14:11 +0100 Subject: [PATCH 07/27] Only warn about unused `mut` in user-written code --- src/librustc/hir/lowering.rs | 25 ++++++++++++------- src/librustc_borrowck/borrowck/unused.rs | 6 ++++- src/librustc_mir/borrow_check/mod.rs | 6 ++++- src/librustc_mir/shim.rs | 3 ++- .../ui/mut/no-mut-lint-for-desugared-mut.rs | 8 ++++++ 5 files changed, 36 insertions(+), 12 deletions(-) create mode 100644 src/test/ui/mut/no-mut-lint-for-desugared-mut.rs diff --git a/src/librustc/hir/lowering.rs b/src/librustc/hir/lowering.rs index bd8770abb135..821c55a9f4e7 100644 --- a/src/librustc/hir/lowering.rs +++ b/src/librustc/hir/lowering.rs @@ -4058,16 +4058,16 @@ impl<'a> LoweringContext<'a> { // expand let head = self.lower_expr(head); let head_sp = head.span; + let desugared_span = self.allow_internal_unstable( + CompilerDesugaringKind::ForLoop, + head.span, + ); let iter = self.str_to_ident("iter"); let next_ident = self.str_to_ident("__next"); - let next_sp = self.allow_internal_unstable( - CompilerDesugaringKind::ForLoop, - head_sp, - ); let next_pat = self.pat_ident_binding_mode( - next_sp, + desugared_span, next_ident, hir::BindingAnnotation::Mutable, ); @@ -4096,8 +4096,11 @@ impl<'a> LoweringContext<'a> { }; // `mut iter` - let iter_pat = - self.pat_ident_binding_mode(head_sp, iter, hir::BindingAnnotation::Mutable); + let iter_pat = self.pat_ident_binding_mode( + desugared_span, + iter, + hir::BindingAnnotation::Mutable + ); // `match ::std::iter::Iterator::next(&mut iter) { ... }` let match_expr = { @@ -4126,8 +4129,12 @@ impl<'a> LoweringContext<'a> { let next_expr = P(self.expr_ident(head_sp, next_ident, next_pat.id)); // `let mut __next` - let next_let = - self.stmt_let_pat(head_sp, None, next_pat, hir::LocalSource::ForLoopDesugar); + let next_let = self.stmt_let_pat( + desugared_span, + None, + next_pat, + hir::LocalSource::ForLoopDesugar, + ); // `let = __next` let pat = self.lower_pat(pat); diff --git a/src/librustc_borrowck/borrowck/unused.rs b/src/librustc_borrowck/borrowck/unused.rs index f10361cb076b..b1f89ce33fcf 100644 --- a/src/librustc_borrowck/borrowck/unused.rs +++ b/src/librustc_borrowck/borrowck/unused.rs @@ -76,10 +76,14 @@ impl<'a, 'tcx> UnusedMutCx<'a, 'tcx> { } let (hir_id, span) = ids[0]; - let mut_span = tcx.sess.source_map().span_until_non_whitespace(span); + if span.compiler_desugaring_kind().is_some() { + // If the `mut` arises as part of a desugaring, we should ignore it. + continue; + } // Ok, every name wasn't used mutably, so issue a warning that this // didn't need to be mutable. + let mut_span = tcx.sess.source_map().span_until_non_whitespace(span); tcx.struct_span_lint_hir(UNUSED_MUT, hir_id, span, diff --git a/src/librustc_mir/borrow_check/mod.rs b/src/librustc_mir/borrow_check/mod.rs index 06394ee44ccb..67170017a12b 100644 --- a/src/librustc_mir/borrow_check/mod.rs +++ b/src/librustc_mir/borrow_check/mod.rs @@ -316,7 +316,10 @@ fn do_mir_borrowck<'a, 'gcx, 'tcx>( } let span = local_decl.source_info.span; - let mut_span = tcx.sess.source_map().span_until_non_whitespace(span); + if span.compiler_desugaring_kind().is_some() { + // If the `mut` arises as part of a desugaring, we should ignore it. + continue; + } let mut err = tcx.struct_span_lint_node( UNUSED_MUT, @@ -324,6 +327,7 @@ fn do_mir_borrowck<'a, 'gcx, 'tcx>( span, "variable does not need to be mutable", ); + let mut_span = tcx.sess.source_map().span_until_non_whitespace(span); err.span_suggestion_short_with_applicability( mut_span, "remove this `mut`", diff --git a/src/librustc_mir/shim.rs b/src/librustc_mir/shim.rs index a6c039756857..288bc7f4814b 100644 --- a/src/librustc_mir/shim.rs +++ b/src/librustc_mir/shim.rs @@ -140,7 +140,8 @@ enum CallKind { fn temp_decl(mutability: Mutability, ty: Ty, span: Span) -> LocalDecl { let source_info = SourceInfo { scope: OUTERMOST_SOURCE_SCOPE, span }; LocalDecl { - mutability, ty, + mutability, + ty, user_ty: None, name: None, source_info, diff --git a/src/test/ui/mut/no-mut-lint-for-desugared-mut.rs b/src/test/ui/mut/no-mut-lint-for-desugared-mut.rs new file mode 100644 index 000000000000..419d580419f4 --- /dev/null +++ b/src/test/ui/mut/no-mut-lint-for-desugared-mut.rs @@ -0,0 +1,8 @@ +// run-pass + +#![deny(unused_mut)] +#![allow(unreachable_code)] + +fn main() { + for _ in { return (); 0..3 } {} // ok +} From 594655bafa416ba282f80c457fe0b27e80b707d9 Mon Sep 17 00:00:00 2001 From: "Felix S. Klock II" Date: Thu, 4 Oct 2018 13:03:24 +0200 Subject: [PATCH 08/27] Regression test for #32382. --- ...ue-32382-index-assoc-type-with-lifetime.rs | 42 +++++++++++++++++++ 1 file changed, 42 insertions(+) create mode 100644 src/test/ui/nll/issue-32382-index-assoc-type-with-lifetime.rs diff --git a/src/test/ui/nll/issue-32382-index-assoc-type-with-lifetime.rs b/src/test/ui/nll/issue-32382-index-assoc-type-with-lifetime.rs new file mode 100644 index 000000000000..a114d7092ecf --- /dev/null +++ b/src/test/ui/nll/issue-32382-index-assoc-type-with-lifetime.rs @@ -0,0 +1,42 @@ +#![feature(nll)] +// compile-pass + +// rust-lang/rust#32382: Borrow checker used to complain about +// `foobar_3` in the `impl` below, presumably due to some interaction +// between the use of a lifetime in the associated type and the use of +// the overloaded operator[]. This regression test ensures that we do +// not resume complaining about it in the future. + + +use std::marker::PhantomData; +use std::ops::Index; + +pub trait Context: Clone { + type Container: ?Sized; + fn foobar_1( container: &Self::Container ) -> &str; + fn foobar_2( container: &Self::Container ) -> &str; + fn foobar_3( container: &Self::Container ) -> &str; +} + +#[derive(Clone)] +struct Foobar<'a> { + phantom: PhantomData<&'a ()> +} + +impl<'a> Context for Foobar<'a> { + type Container = [&'a str]; + + fn foobar_1<'r>( container: &'r [&'a str] ) -> &'r str { + container[0] + } + + fn foobar_2<'r>( container: &'r Self::Container ) -> &'r str { + container.index( 0 ) + } + + fn foobar_3<'r>( container: &'r Self::Container ) -> &'r str { + container[0] + } +} + +fn main() { } From ea3d8f510dfe18870b8b0b2bb5bf007fe914c262 Mon Sep 17 00:00:00 2001 From: varkor Date: Thu, 4 Oct 2018 14:48:32 +0100 Subject: [PATCH 09/27] Ignore desugarings when comparing duplicate trait error messages --- src/librustc/hir/lowering.rs | 2 +- src/librustc/traits/error_reporting.rs | 22 +++++++++++++++++----- 2 files changed, 18 insertions(+), 6 deletions(-) diff --git a/src/librustc/hir/lowering.rs b/src/librustc/hir/lowering.rs index 821c55a9f4e7..bf421da61e44 100644 --- a/src/librustc/hir/lowering.rs +++ b/src/librustc/hir/lowering.rs @@ -4060,7 +4060,7 @@ impl<'a> LoweringContext<'a> { let head_sp = head.span; let desugared_span = self.allow_internal_unstable( CompilerDesugaringKind::ForLoop, - head.span, + head_sp, ); let iter = self.str_to_ident("iter"); diff --git a/src/librustc/traits/error_reporting.rs b/src/librustc/traits/error_reporting.rs index 6fb5acde72c4..3ba31e229e13 100644 --- a/src/librustc/traits/error_reporting.rs +++ b/src/librustc/traits/error_reporting.rs @@ -46,7 +46,7 @@ use ty::subst::Subst; use ty::SubtypePredicate; use util::nodemap::{FxHashMap, FxHashSet}; -use syntax_pos::{DUMMY_SP, Span}; +use syntax_pos::{DUMMY_SP, Span, ExpnInfo, ExpnFormat}; impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { pub fn report_fulfillment_errors(&self, @@ -68,18 +68,30 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { }).collect(); for (index, error) in errors.iter().enumerate() { - error_map.entry(error.obligation.cause.span).or_default().push( + // We want to ignore desugarings here: spans are equivalent even + // if one is the result of a desugaring and the other is not. + let mut span = error.obligation.cause.span; + if let Some(ExpnInfo { + format: ExpnFormat::CompilerDesugaring(_), + def_site: Some(def_span), + .. + }) = span.ctxt().outer().expn_info() { + span = def_span; + } + + error_map.entry(span).or_default().push( ErrorDescriptor { predicate: error.obligation.predicate.clone(), index: Some(index) - }); + } + ); self.reported_trait_errors.borrow_mut() - .entry(error.obligation.cause.span).or_default() + .entry(span).or_default() .push(error.obligation.predicate.clone()); } - // We do this in 2 passes because we want to display errors in order, tho + // We do this in 2 passes because we want to display errors in order, though // maybe it *is* better to sort errors by span or something. let mut is_suppressed = vec![false; errors.len()]; for (_, error_set) in error_map.iter() { From 769b3832fd984a865358de43dc594d9333193558 Mon Sep 17 00:00:00 2001 From: Philipp Hansch Date: Thu, 4 Oct 2018 20:27:53 +0200 Subject: [PATCH 10/27] Further improve docs for `FnDef` and `FnPtr` --- src/librustc/ty/sty.rs | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/src/librustc/ty/sty.rs b/src/librustc/ty/sty.rs index 4cf4668443fb..90e3f595152d 100644 --- a/src/librustc/ty/sty.rs +++ b/src/librustc/ty/sty.rs @@ -126,26 +126,24 @@ pub enum TyKind<'tcx> { Ref(Region<'tcx>, Ty<'tcx>, hir::Mutability), /// The anonymous type of a function declaration/definition. Each - /// function has a unique type. + /// function has a unique type, which is output (for a function + /// named `foo` returning an `i32`) as `fn() -> i32 {foo}`. /// - /// For example the type of `a` here: + /// For example the type of `bar` here: /// /// ```rust /// fn foo() -> i32 { 1 } - /// - /// fn hello() { - /// let a = foo; - /// } + /// let bar = foo; // bar: fn() -> i32 {foo} /// ``` FnDef(DefId, &'tcx Substs<'tcx>), /// A pointer to a function. Written as `fn() -> i32`. /// - /// For example the type of `a` here: + /// For example the type of `bar` here: /// /// ```rust /// fn foo() -> i32 { 1 } - /// let a: fn() -> i32 = foo; + /// let bar: fn() -> i32 = foo; /// ``` FnPtr(PolyFnSig<'tcx>), From 2feea63b4b4cec6ec7d990368234cf77cb01c5af Mon Sep 17 00:00:00 2001 From: Kazuyoshi Kato Date: Thu, 4 Oct 2018 21:31:16 -0700 Subject: [PATCH 11/27] rustdoc: overflow:auto doesn't work nicely on small screens This property was introduced by 3f92ff34b5, but looks it doesn't overwrap even without the property. Fixes #54672. --- src/librustdoc/html/static/rustdoc.css | 1 - 1 file changed, 1 deletion(-) diff --git a/src/librustdoc/html/static/rustdoc.css b/src/librustdoc/html/static/rustdoc.css index ee811f337923..58ac46d22717 100644 --- a/src/librustdoc/html/static/rustdoc.css +++ b/src/librustdoc/html/static/rustdoc.css @@ -97,7 +97,6 @@ h1, h2, h3:not(.impl):not(.method):not(.type):not(.tymethod):not(.important), h4 h1.fqn { border-bottom: 1px dashed; margin-top: 0; - overflow: auto; } h2, h3:not(.impl):not(.method):not(.type):not(.tymethod), h4:not(.method):not(.type):not(.tymethod):not(.associatedconstant) { border-bottom: 1px solid; From 6ba55847129e9a35b477e43b7a381ca00fd2a339 Mon Sep 17 00:00:00 2001 From: Gabriel Majeri Date: Fri, 5 Oct 2018 08:50:17 +0300 Subject: [PATCH 12/27] Address review comments --- src/libstd/sync/mod.rs | 110 +++++++++++++++++++++++++---------------- 1 file changed, 67 insertions(+), 43 deletions(-) diff --git a/src/libstd/sync/mod.rs b/src/libstd/sync/mod.rs index edbed430e386..d69ebc176227 100644 --- a/src/libstd/sync/mod.rs +++ b/src/libstd/sync/mod.rs @@ -12,11 +12,11 @@ //! //! ## The need for synchronization //! -//! Conceptually, a Rust program is simply a series of operations which will -//! be executed on a computer. The timeline of events happening in the program -//! is consistent with the order of the operations in the code. +//! Conceptually, a Rust program is a series of operations which will +//! be executed on a computer. The timeline of events happening in the +//! program is consistent with the order of the operations in the code. //! -//! Considering the following code, operating on some global static variables: +//! Consider the following code, operating on some global static variables: //! //! ```rust //! static mut A: u32 = 0; @@ -35,8 +35,10 @@ //! } //! ``` //! -//! It appears _as if_ some variables stored in memory are changed, an addition -//! is performed, result is stored in `A` and the variable `C` is modified twice. +//! It appears as if some variables stored in memory are changed, an addition +//! is performed, result is stored in `A` and the variable `C` is +//! modified twice. +//! //! When only a single thread is involved, the results are as expected: //! the line `7 4 4` gets printed. //! @@ -50,17 +52,19 @@ //! in a temporary location until it gets printed, with the global variable //! never getting updated. //! -//! - The final result could be determined just by looking at the code at compile time, -//! so [constant folding] might turn the whole block into a simple `println!("7 4 4")`. +//! - The final result could be determined just by looking at the code +//! at compile time, so [constant folding] might turn the whole +//! block into a simple `println!("7 4 4")`. //! -//! The compiler is allowed to perform any combination of these optimizations, as long -//! as the final optimized code, when executed, produces the same results as the one -//! without optimizations. +//! The compiler is allowed to perform any combination of these +//! optimizations, as long as the final optimized code, when executed, +//! produces the same results as the one without optimizations. //! -//! Due to the [concurrency] involved in modern computers, assumptions about -//! the program's execution order are often wrong. Access to global variables -//! can lead to nondeterministic results, **even if** compiler optimizations -//! are disabled, and it is **still possible** to introduce synchronization bugs. +//! Due to the [concurrency] involved in modern computers, assumptions +//! about the program's execution order are often wrong. Access to +//! global variables can lead to nondeterministic results, **even if** +//! compiler optimizations are disabled, and it is **still possible** +//! to introduce synchronization bugs. //! //! Note that thanks to Rust's safety guarantees, accessing global (static) //! variables requires `unsafe` code, assuming we don't use any of the @@ -74,7 +78,7 @@ //! Instructions can execute in a different order from the one we define, due to //! various reasons: //! -//! - **Compiler** reordering instructions: if the compiler can issue an +//! - The **compiler** reordering instructions: If the compiler can issue an //! instruction at an earlier point, it will try to do so. For example, it //! might hoist memory loads at the top of a code block, so that the CPU can //! start [prefetching] the values from memory. @@ -83,20 +87,20 @@ //! signal handlers or certain kinds of low-level code. //! Use [compiler fences] to prevent this reordering. //! -//! - **Single processor** executing instructions [out-of-order]: modern CPUs are -//! capable of [superscalar] execution, i.e. multiple instructions might be -//! executing at the same time, even though the machine code describes a -//! sequential process. +//! - A **single processor** executing instructions [out-of-order]: +//! Modern CPUs are capable of [superscalar] execution, +//! i.e. multiple instructions might be executing at the same time, +//! even though the machine code describes a sequential process. //! //! This kind of reordering is handled transparently by the CPU. //! -//! - **Multiprocessor** system, where multiple hardware threads run at the same time. -//! In multi-threaded scenarios, you can use two kinds of primitives to deal -//! with synchronization: -//! - [memory fences] to ensure memory accesses are made visibile to other -//! CPUs in the right order. -//! - [atomic operations] to ensure simultaneous access to the same memory -//! location doesn't lead to undefined behavior. +//! - A **multiprocessor** system executing multiple hardware threads +//! at the same time: In multi-threaded scenarios, you can use two +//! kinds of primitives to deal with synchronization: +//! - [memory fences] to ensure memory accesses are made visibile to +//! other CPUs in the right order. +//! - [atomic operations] to ensure simultaneous access to the same +//! memory location doesn't lead to undefined behavior. //! //! [prefetching]: https://en.wikipedia.org/wiki/Cache_prefetching //! [compiler fences]: crate::sync::atomic::compiler_fence @@ -111,29 +115,49 @@ //! inconvenient to use, which is why the standard library also exposes some //! higher-level synchronization objects. //! -//! These abstractions can be built out of lower-level primitives. For efficiency, -//! the sync objects in the standard library are usually implemented with help -//! from the operating system's kernel, which is able to reschedule the threads -//! while they are blocked on acquiring a lock. +//! These abstractions can be built out of lower-level primitives. +//! For efficiency, the sync objects in the standard library are usually +//! implemented with help from the operating system's kernel, which is +//! able to reschedule the threads while they are blocked on acquiring +//! a lock. +//! +//! The following is an overview of the available synchronization +//! objects: +//! +//! - [`Arc`]: Atomically Reference-Counted pointer, which can be used +//! in multithreaded environments to prolong the lifetime of some +//! data until all the threads have finished using it. +//! +//! - [`Barrier`]: Ensures multiple threads will wait for each other +//! to reach a point in the program, before continuing execution all +//! together. +//! +//! - [`Condvar`]: Condition Variable, providing the ability to block +//! a thread while waiting for an event to occur. //! -//! ## Efficiency +//! - [`mpsc`]: Multi-producer, single-consumer queues, used for +//! message-based communication. Can provide a lightweight +//! inter-thread synchronisation mechanism, at the cost of some +//! extra memory. //! -//! Higher-level synchronization mechanisms are usually heavy-weight. -//! While most atomic operations can execute instantaneously, acquiring a -//! [`Mutex`] can involve blocking until another thread releases it. -//! For [`RwLock`], while any number of readers may acquire it without -//! blocking, each writer will have exclusive access. +//! - [`Mutex`]: Mutual Exclusion mechanism, which ensures that at +//! most one thread at a time is able to access some data. //! -//! On the other hand, communication over [channels] can provide a fairly -//! high-level interface without sacrificing performance, at the cost of -//! somewhat more memory. +//! - [`Once`]: Used for thread-safe, one-time initialization of a +//! global variable. //! -//! The more synchronization exists between CPUs, the smaller the performance -//! gains from multithreading will be. +//! - [`RwLock`]: Provides a mutual exclusion mechanism which allows +//! multiple readers at the same time, while allowing only one +//! writer at a time. In some cases, this can be more efficient than +//! a mutex. //! +//! [`Arc`]: crate::sync::Arc +//! [`Barrier`]: crate::sync::Barrier +//! [`Condvar`]: crate::sync::Condvar +//! [`mpsc`]: crate::sync::mpsc //! [`Mutex`]: crate::sync::Mutex +//! [`Once`]: crate::sync::Once //! [`RwLock`]: crate::sync::RwLock -//! [channels]: crate::sync::mpsc #![stable(feature = "rust1", since = "1.0.0")] From 2ff117df5096c23b466992a0a3427edf1af3113d Mon Sep 17 00:00:00 2001 From: ljedrz Date: Mon, 1 Oct 2018 15:26:53 +0200 Subject: [PATCH 13/27] rustc/ty: whitespace fixes --- src/librustc/ty/codec.rs | 28 +++++++++++++------------- src/librustc/ty/context.rs | 27 ++++++++++++------------- src/librustc/ty/query/config.rs | 4 ++-- src/librustc/ty/query/on_disk_cache.rs | 15 ++++++-------- src/librustc/ty/query/plumbing.rs | 14 ++++++------- 5 files changed, 42 insertions(+), 46 deletions(-) diff --git a/src/librustc/ty/codec.rs b/src/librustc/ty/codec.rs index ae87d30ec942..8738f5741482 100644 --- a/src/librustc/ty/codec.rs +++ b/src/librustc/ty/codec.rs @@ -178,19 +178,19 @@ pub fn decode_predicates<'a, 'tcx, D>(decoder: &mut D) Ok(ty::GenericPredicates { parent: Decodable::decode(decoder)?, predicates: (0..decoder.read_usize()?).map(|_| { - // Handle shorthands first, if we have an usize > 0x80. - let predicate = if decoder.positioned_at_shorthand() { - let pos = decoder.read_usize()?; - assert!(pos >= SHORTHAND_OFFSET); - let shorthand = pos - SHORTHAND_OFFSET; - - decoder.with_position(shorthand, ty::Predicate::decode) - } else { - ty::Predicate::decode(decoder) - }?; - Ok((predicate, Decodable::decode(decoder)?)) - }) - .collect::, _>>()?, + // Handle shorthands first, if we have an usize > 0x80. + let predicate = if decoder.positioned_at_shorthand() { + let pos = decoder.read_usize()?; + assert!(pos >= SHORTHAND_OFFSET); + let shorthand = pos - SHORTHAND_OFFSET; + + decoder.with_position(shorthand, ty::Predicate::decode) + } else { + ty::Predicate::decode(decoder) + }?; + Ok((predicate, Decodable::decode(decoder)?)) + }) + .collect::, _>>()?, }) } @@ -267,7 +267,7 @@ pub fn decode_const<'a, 'tcx, D>(decoder: &mut D) #[inline] pub fn decode_allocation<'a, 'tcx, D>(decoder: &mut D) - -> Result<&'tcx Allocation, D::Error> + -> Result<&'tcx Allocation, D::Error> where D: TyDecoder<'a, 'tcx>, 'tcx: 'a, { diff --git a/src/librustc/ty/context.rs b/src/librustc/ty/context.rs index 05b68b34989b..daada8891d7a 100644 --- a/src/librustc/ty/context.rs +++ b/src/librustc/ty/context.rs @@ -190,8 +190,8 @@ impl<'gcx: 'tcx, 'tcx> CtxtInterners<'tcx> { // types/regions in the global interner if local as *const _ as usize == global as *const _ as usize { bug!("Attempted to intern `{:?}` which contains \ - inference types/regions in the global type context", - &ty_struct); + inference types/regions in the global type context", + &ty_struct); } // Don't be &mut TyS. @@ -272,9 +272,9 @@ fn validate_hir_id_for_typeck_tables(local_id_root: Option, bug!("node {} with HirId::owner {:?} cannot be placed in \ TypeckTables with local_id_root {:?}", - tcx.hir.node_to_string(node_id), - DefId::local(hir_id.owner), - local_id_root) + tcx.hir.node_to_string(node_id), + DefId::local(hir_id.owner), + local_id_root) }); } } else { @@ -686,7 +686,7 @@ impl<'tcx> TypeckTables<'tcx> { } pub fn pat_adjustments_mut(&mut self) - -> LocalTableInContextMut<'_, Vec>> { + -> LocalTableInContextMut<'_, Vec>> { LocalTableInContextMut { local_id_root: self.local_id_root, data: &mut self.pat_adjustments, @@ -1199,8 +1199,8 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { let hir_id = hir.node_to_hir_id(k); let map = trait_map.entry(hir_id.owner).or_default(); Lrc::get_mut(map).unwrap() - .insert(hir_id.local_id, - Lrc::new(StableVec::new(v))); + .insert(hir_id.local_id, + Lrc::new(StableVec::new(v))); } let gcx = &GlobalCtxt { @@ -2188,7 +2188,6 @@ macro_rules! sty_debug_print { }; $(let mut $variant = total;)* - for &Interned(t) in tcx.interners.type_.borrow().iter() { let variant = match t.sty { ty::Bool | ty::Char | ty::Int(..) | ty::Uint(..) | @@ -2207,7 +2206,7 @@ macro_rules! sty_debug_print { } println!("Ty interner total ty region both"); $(println!(" {:18}: {uses:6} {usespc:4.1}%, \ -{ty:4.1}% {region:5.1}% {both:4.1}%", + {ty:4.1}% {region:5.1}% {both:4.1}%", stringify!($variant), uses = $variant.total, usespc = $variant.total as f64 * 100.0 / total.total as f64, @@ -2216,7 +2215,7 @@ macro_rules! sty_debug_print { both = $variant.both_infer as f64 * 100.0 / total.total as f64); )* println!(" total {uses:6} \ -{ty:4.1}% {region:5.1}% {both:4.1}%", + {ty:4.1}% {region:5.1}% {both:4.1}%", uses = total.total, ty = total.ty_infer as f64 * 100.0 / total.total as f64, region = total.region_infer as f64 * 100.0 / total.total as f64, @@ -2653,7 +2652,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { } pub fn mk_closure(self, closure_id: DefId, closure_substs: ClosureSubsts<'tcx>) - -> Ty<'tcx> { + -> Ty<'tcx> { self.mk_ty(Closure(closure_id, closure_substs)) } @@ -2686,8 +2685,8 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { } pub fn mk_ty_param(self, - index: u32, - name: InternedString) -> Ty<'tcx> { + index: u32, + name: InternedString) -> Ty<'tcx> { self.mk_ty(Param(ParamTy { idx: index, name: name })) } diff --git a/src/librustc/ty/query/config.rs b/src/librustc/ty/query/config.rs index 66d7541633cd..0e11d6e0eec0 100644 --- a/src/librustc/ty/query/config.rs +++ b/src/librustc/ty/query/config.rs @@ -386,8 +386,8 @@ impl<'tcx> QueryDescription<'tcx> for queries::const_is_rvalue_promotable_to_sta #[inline] fn try_load_from_disk<'a>(tcx: TyCtxt<'a, 'tcx, 'tcx>, - id: SerializedDepNodeIndex) - -> Option { + id: SerializedDepNodeIndex) + -> Option { tcx.queries.on_disk_cache.try_load_query_result(tcx, id) } } diff --git a/src/librustc/ty/query/on_disk_cache.rs b/src/librustc/ty/query/on_disk_cache.rs index bb8778646322..7d3ce7307dc8 100644 --- a/src/librustc/ty/query/on_disk_cache.rs +++ b/src/librustc/ty/query/on_disk_cache.rs @@ -448,9 +448,9 @@ impl<'sess> OnDiskCache<'sess> { }).collect::>(); let map_size = prev_cnums.iter() - .map(|&(cnum, ..)| cnum) - .max() - .unwrap_or(0) + 1; + .map(|&(cnum, ..)| cnum) + .max() + .unwrap_or(0) + 1; let mut map = IndexVec::new(); map.resize(map_size as usize, None); @@ -465,7 +465,6 @@ impl<'sess> OnDiskCache<'sess> { } } - //- DECODING ------------------------------------------------------------------- /// A decoder that can read the incr. comp. cache. It is similar to the one @@ -494,7 +493,7 @@ impl<'a, 'tcx, 'x> CacheDecoder<'a, 'tcx, 'x> { file_index_to_file.borrow_mut().entry(index).or_insert_with(|| { let stable_id = file_index_to_stable_id[&index]; source_map.source_file_by_stable_id(stable_id) - .expect("Failed to lookup SourceFile in new context.") + .expect("Failed to lookup SourceFile in new context.") }).clone() } } @@ -761,7 +760,7 @@ for CacheDecoder<'a, 'tcx, 'x> { struct CacheEncoder<'enc, 'a, 'tcx, E> where E: 'enc + ty_codec::TyEncoder, - 'tcx: 'a, + 'tcx: 'a, { tcx: TyCtxt<'a, 'tcx, 'tcx>, encoder: &'enc mut E, @@ -839,9 +838,7 @@ impl<'enc, 'a, 'tcx, E> SpecializedEncoder for CacheEncoder<'enc, 'a, 'tcx let (file_lo, line_lo, col_lo) = match self.source_map .byte_pos_to_line_and_col(span_data.lo) { Some(pos) => pos, - None => { - return TAG_INVALID_SPAN.encode(self); - } + None => return TAG_INVALID_SPAN.encode(self) }; if !file_lo.contains(span_data.hi) { diff --git a/src/librustc/ty/query/plumbing.rs b/src/librustc/ty/query/plumbing.rs index fbd3a8f69bc4..5f6fdbddf8fe 100644 --- a/src/librustc/ty/query/plumbing.rs +++ b/src/librustc/ty/query/plumbing.rs @@ -449,14 +449,14 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { let prev_dep_node_index = self.dep_graph.prev_dep_node_index_of(dep_node); let result = Q::try_load_from_disk(self.global_tcx(), - prev_dep_node_index); + prev_dep_node_index); // We always expect to find a cached result for things that // can be forced from DepNode. debug_assert!(!dep_node.kind.can_reconstruct_query_key() || - result.is_some(), - "Missing on-disk cache entry for {:?}", - dep_node); + result.is_some(), + "Missing on-disk cache entry for {:?}", + dep_node); result } else { // Some things are never cached on disk. @@ -491,7 +491,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { assert!(Some(self.dep_graph.fingerprint_of(dep_node_index)) == self.dep_graph.prev_fingerprint_of(dep_node), "Fingerprint for green query instance not loaded \ - from cache: {:?}", dep_node); + from cache: {:?}", dep_node); debug!("BEGIN verify_ich({:?})", dep_node); let mut hcx = self.create_stable_hashing_context(); @@ -530,8 +530,8 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { // (see for example #48923) assert!(!self.dep_graph.dep_node_exists(&dep_node), "Forcing query with already existing DepNode.\n\ - - query-key: {:?}\n\ - - dep-node: {:?}", + - query-key: {:?}\n\ + - dep-node: {:?}", key, dep_node); profq_msg!(self, ProfileQueriesMsg::ProviderBegin); From 91fc573172c83f9d443da9b54f0361be5266b53f Mon Sep 17 00:00:00 2001 From: ljedrz Date: Mon, 1 Oct 2018 15:31:27 +0200 Subject: [PATCH 14/27] rustc/ty: use Cow where applicable --- src/librustc/ty/error.rs | 81 +++--- src/librustc/ty/query/config.rs | 423 +++++++++++++++--------------- src/librustc/ty/query/mod.rs | 1 + src/librustc/ty/query/plumbing.rs | 4 +- 4 files changed, 261 insertions(+), 248 deletions(-) diff --git a/src/librustc/ty/error.rs b/src/librustc/ty/error.rs index a1edf67e4755..2367d482ec89 100644 --- a/src/librustc/ty/error.rs +++ b/src/librustc/ty/error.rs @@ -10,6 +10,7 @@ use hir::def_id::DefId; use ty::{self, BoundRegion, Region, Ty, TyCtxt}; +use std::borrow::Cow; use std::fmt; use rustc_target::spec::abi; use syntax::ast; @@ -71,7 +72,7 @@ impl<'tcx> fmt::Display for TypeError<'tcx> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { use self::TypeError::*; fn report_maybe_different(f: &mut fmt::Formatter<'_>, - expected: String, found: String) -> fmt::Result { + expected: &str, found: &str) -> fmt::Result { // A naive approach to making sure that we're not reporting silly errors such as: // (expected closure, found closure). if expected == found { @@ -126,15 +127,15 @@ impl<'tcx> fmt::Display for TypeError<'tcx> { br) } Sorts(values) => ty::tls::with(|tcx| { - report_maybe_different(f, values.expected.sort_string(tcx), - values.found.sort_string(tcx)) + report_maybe_different(f, &values.expected.sort_string(tcx), + &values.found.sort_string(tcx)) }), Traits(values) => ty::tls::with(|tcx| { report_maybe_different(f, - format!("trait `{}`", - tcx.item_path_str(values.expected)), - format!("trait `{}`", - tcx.item_path_str(values.found))) + &format!("trait `{}`", + tcx.item_path_str(values.expected)), + &format!("trait `{}`", + tcx.item_path_str(values.found))) }), IntMismatch(ref values) => { write!(f, "expected `{:?}`, found `{:?}`", @@ -162,8 +163,8 @@ impl<'tcx> fmt::Display for TypeError<'tcx> { values.found) }, ExistentialMismatch(ref values) => { - report_maybe_different(f, format!("trait `{}`", values.expected), - format!("trait `{}`", values.found)) + report_maybe_different(f, &format!("trait `{}`", values.expected), + &format!("trait `{}`", values.found)) } OldStyleLUB(ref err) => { write!(f, "{}", err) @@ -173,22 +174,22 @@ impl<'tcx> fmt::Display for TypeError<'tcx> { } impl<'a, 'gcx, 'lcx, 'tcx> ty::TyS<'tcx> { - pub fn sort_string(&self, tcx: TyCtxt<'a, 'gcx, 'lcx>) -> String { + pub fn sort_string(&self, tcx: TyCtxt<'a, 'gcx, 'lcx>) -> Cow<'static, str> { match self.sty { ty::Bool | ty::Char | ty::Int(_) | - ty::Uint(_) | ty::Float(_) | ty::Str | ty::Never => self.to_string(), - ty::Tuple(ref tys) if tys.is_empty() => self.to_string(), + ty::Uint(_) | ty::Float(_) | ty::Str | ty::Never => self.to_string().into(), + ty::Tuple(ref tys) if tys.is_empty() => self.to_string().into(), - ty::Adt(def, _) => format!("{} `{}`", def.descr(), tcx.item_path_str(def.did)), - ty::Foreign(def_id) => format!("extern type `{}`", tcx.item_path_str(def_id)), + ty::Adt(def, _) => format!("{} `{}`", def.descr(), tcx.item_path_str(def.did)).into(), + ty::Foreign(def_id) => format!("extern type `{}`", tcx.item_path_str(def_id)).into(), ty::Array(_, n) => { match n.assert_usize(tcx) { - Some(n) => format!("array of {} elements", n), - None => "array".to_string(), + Some(n) => format!("array of {} elements", n).into(), + None => "array".into(), } } - ty::Slice(_) => "slice".to_string(), - ty::RawPtr(_) => "*-ptr".to_string(), + ty::Slice(_) => "slice".into(), + ty::RawPtr(_) => "*-ptr".into(), ty::Ref(region, ty, mutbl) => { let tymut = ty::TypeAndMut { ty, mutbl }; let tymut_string = tymut.to_string(); @@ -199,39 +200,39 @@ impl<'a, 'gcx, 'lcx, 'tcx> ty::TyS<'tcx> { format!("{}reference", match mutbl { hir::Mutability::MutMutable => "mutable ", _ => "" - }) + }).into() } else { - format!("&{}", tymut_string) + format!("&{}", tymut_string).into() } } - ty::FnDef(..) => "fn item".to_string(), - ty::FnPtr(_) => "fn pointer".to_string(), + ty::FnDef(..) => "fn item".into(), + ty::FnPtr(_) => "fn pointer".into(), ty::Dynamic(ref inner, ..) => { - inner.principal().map_or_else(|| "trait".to_string(), - |p| format!("trait {}", tcx.item_path_str(p.def_id()))) + inner.principal().map_or_else(|| "trait".into(), + |p| format!("trait {}", tcx.item_path_str(p.def_id())).into()) } - ty::Closure(..) => "closure".to_string(), - ty::Generator(..) => "generator".to_string(), - ty::GeneratorWitness(..) => "generator witness".to_string(), - ty::Tuple(..) => "tuple".to_string(), - ty::Infer(ty::TyVar(_)) => "inferred type".to_string(), - ty::Infer(ty::IntVar(_)) => "integral variable".to_string(), - ty::Infer(ty::FloatVar(_)) => "floating-point variable".to_string(), + ty::Closure(..) => "closure".into(), + ty::Generator(..) => "generator".into(), + ty::GeneratorWitness(..) => "generator witness".into(), + ty::Tuple(..) => "tuple".into(), + ty::Infer(ty::TyVar(_)) => "inferred type".into(), + ty::Infer(ty::IntVar(_)) => "integral variable".into(), + ty::Infer(ty::FloatVar(_)) => "floating-point variable".into(), ty::Infer(ty::CanonicalTy(_)) | - ty::Infer(ty::FreshTy(_)) => "fresh type".to_string(), - ty::Infer(ty::FreshIntTy(_)) => "fresh integral type".to_string(), - ty::Infer(ty::FreshFloatTy(_)) => "fresh floating-point type".to_string(), - ty::Projection(_) => "associated type".to_string(), - ty::UnnormalizedProjection(_) => "non-normalized associated type".to_string(), + ty::Infer(ty::FreshTy(_)) => "fresh type".into(), + ty::Infer(ty::FreshIntTy(_)) => "fresh integral type".into(), + ty::Infer(ty::FreshFloatTy(_)) => "fresh floating-point type".into(), + ty::Projection(_) => "associated type".into(), + ty::UnnormalizedProjection(_) => "non-normalized associated type".into(), ty::Param(ref p) => { if p.is_self() { - "Self".to_string() + "Self".into() } else { - "type parameter".to_string() + "type parameter".into() } } - ty::Opaque(..) => "opaque type".to_string(), - ty::Error => "type error".to_string(), + ty::Opaque(..) => "opaque type".into(), + ty::Error => "type error".into(), } } } diff --git a/src/librustc/ty/query/config.rs b/src/librustc/ty/query/config.rs index 0e11d6e0eec0..79eab3c6f34b 100644 --- a/src/librustc/ty/query/config.rs +++ b/src/librustc/ty/query/config.rs @@ -23,6 +23,7 @@ use ty::query::Query; use ty::query::QueryCache; use util::profiling::ProfileCategory; +use std::borrow::Cow; use std::hash::Hash; use std::fmt::Debug; use syntax_pos::symbol::InternedString; @@ -55,7 +56,7 @@ pub(super) trait QueryAccessors<'tcx>: QueryConfig<'tcx> { } pub(super) trait QueryDescription<'tcx>: QueryAccessors<'tcx> { - fn describe(tcx: TyCtxt<'_, '_, '_>, key: Self::Key) -> String; + fn describe(tcx: TyCtxt<'_, '_, '_>, key: Self::Key) -> Cow<'static, str>; #[inline] fn cache_on_disk(_: Self::Key) -> bool { @@ -70,12 +71,12 @@ pub(super) trait QueryDescription<'tcx>: QueryAccessors<'tcx> { } impl<'tcx, M: QueryAccessors<'tcx, Key=DefId>> QueryDescription<'tcx> for M { - default fn describe(tcx: TyCtxt<'_, '_, '_>, def_id: DefId) -> String { + default fn describe(tcx: TyCtxt<'_, '_, '_>, def_id: DefId) -> Cow<'static, str> { if !tcx.sess.verbose() { - format!("processing `{}`", tcx.item_path_str(def_id)) + format!("processing `{}`", tcx.item_path_str(def_id)).into() } else { let name = unsafe { ::std::intrinsics::type_name::() }; - format!("processing `{}` applied to `{:?}`", name, def_id) + format!("processing `{}` applied to `{:?}`", name, def_id).into() } } } @@ -84,57 +85,59 @@ impl<'tcx> QueryDescription<'tcx> for queries::normalize_projection_ty<'tcx> { fn describe( _tcx: TyCtxt<'_, '_, '_>, goal: CanonicalProjectionGoal<'tcx>, - ) -> String { - format!("normalizing `{:?}`", goal) + ) -> Cow<'static, str> { + format!("normalizing `{:?}`", goal).into() } } impl<'tcx> QueryDescription<'tcx> for queries::implied_outlives_bounds<'tcx> { - fn describe(_tcx: TyCtxt<'_, '_, '_>, goal: CanonicalTyGoal<'tcx>) -> String { - format!("computing implied outlives bounds for `{:?}`", goal) + fn describe(_tcx: TyCtxt<'_, '_, '_>, goal: CanonicalTyGoal<'tcx>) -> Cow<'static, str> { + format!("computing implied outlives bounds for `{:?}`", goal).into() } } impl<'tcx> QueryDescription<'tcx> for queries::dropck_outlives<'tcx> { - fn describe(_tcx: TyCtxt<'_, '_, '_>, goal: CanonicalTyGoal<'tcx>) -> String { - format!("computing dropck types for `{:?}`", goal) + fn describe(_tcx: TyCtxt<'_, '_, '_>, goal: CanonicalTyGoal<'tcx>) -> Cow<'static, str> { + format!("computing dropck types for `{:?}`", goal).into() } } impl<'tcx> QueryDescription<'tcx> for queries::normalize_ty_after_erasing_regions<'tcx> { - fn describe(_tcx: TyCtxt<'_, '_, '_>, goal: ParamEnvAnd<'tcx, Ty<'tcx>>) -> String { - format!("normalizing `{:?}`", goal) + fn describe(_tcx: TyCtxt<'_, '_, '_>, goal: ParamEnvAnd<'tcx, Ty<'tcx>>) -> Cow<'static, str> { + format!("normalizing `{:?}`", goal).into() } } impl<'tcx> QueryDescription<'tcx> for queries::evaluate_obligation<'tcx> { - fn describe(_tcx: TyCtxt<'_, '_, '_>, goal: CanonicalPredicateGoal<'tcx>) -> String { - format!("evaluating trait selection obligation `{}`", goal.value.value) + fn describe(_tcx: TyCtxt<'_, '_, '_>, goal: CanonicalPredicateGoal<'tcx>) -> Cow<'static, str> { + format!("evaluating trait selection obligation `{}`", goal.value.value).into() } } impl<'tcx> QueryDescription<'tcx> for queries::type_op_eq<'tcx> { - fn describe(_tcx: TyCtxt<'_, '_, '_>, goal: CanonicalTypeOpEqGoal<'tcx>) -> String { - format!("evaluating `type_op_eq` `{:?}`", goal) + fn describe(_tcx: TyCtxt<'_, '_, '_>, goal: CanonicalTypeOpEqGoal<'tcx>) -> Cow<'static, str> { + format!("evaluating `type_op_eq` `{:?}`", goal).into() } } impl<'tcx> QueryDescription<'tcx> for queries::type_op_subtype<'tcx> { - fn describe(_tcx: TyCtxt<'_, '_, '_>, goal: CanonicalTypeOpSubtypeGoal<'tcx>) -> String { - format!("evaluating `type_op_subtype` `{:?}`", goal) + fn describe(_tcx: TyCtxt<'_, '_, '_>, goal: CanonicalTypeOpSubtypeGoal<'tcx>) + -> Cow<'static, str> { + format!("evaluating `type_op_subtype` `{:?}`", goal).into() } } impl<'tcx> QueryDescription<'tcx> for queries::type_op_prove_predicate<'tcx> { - fn describe(_tcx: TyCtxt<'_, '_, '_>, goal: CanonicalTypeOpProvePredicateGoal<'tcx>) -> String { - format!("evaluating `type_op_prove_predicate` `{:?}`", goal) + fn describe(_tcx: TyCtxt<'_, '_, '_>, goal: CanonicalTypeOpProvePredicateGoal<'tcx>) + -> Cow<'static, str> { + format!("evaluating `type_op_prove_predicate` `{:?}`", goal).into() } } impl<'tcx> QueryDescription<'tcx> for queries::type_op_normalize_ty<'tcx> { fn describe(_tcx: TyCtxt<'_, '_, '_>, - goal: CanonicalTypeOpNormalizeGoal<'tcx, Ty<'tcx>>) -> String { - format!("normalizing `{:?}`", goal) + goal: CanonicalTypeOpNormalizeGoal<'tcx, Ty<'tcx>>) -> Cow<'static, str> { + format!("normalizing `{:?}`", goal).into() } } @@ -142,8 +145,8 @@ impl<'tcx> QueryDescription<'tcx> for queries::type_op_normalize_predicate<'tcx> fn describe( _tcx: TyCtxt<'_, '_, '_>, goal: CanonicalTypeOpNormalizeGoal<'tcx, ty::Predicate<'tcx>>, - ) -> String { - format!("normalizing `{:?}`", goal) + ) -> Cow<'static, str> { + format!("normalizing `{:?}`", goal).into() } } @@ -151,134 +154,141 @@ impl<'tcx> QueryDescription<'tcx> for queries::type_op_normalize_poly_fn_sig<'tc fn describe( _tcx: TyCtxt<'_, '_, '_>, goal: CanonicalTypeOpNormalizeGoal<'tcx, ty::PolyFnSig<'tcx>>, - ) -> String { - format!("normalizing `{:?}`", goal) + ) -> Cow<'static, str> { + format!("normalizing `{:?}`", goal).into() } } impl<'tcx> QueryDescription<'tcx> for queries::type_op_normalize_fn_sig<'tcx> { fn describe(_tcx: TyCtxt<'_, '_, '_>, - goal: CanonicalTypeOpNormalizeGoal<'tcx, ty::FnSig<'tcx>>) -> String { - format!("normalizing `{:?}`", goal) + goal: CanonicalTypeOpNormalizeGoal<'tcx, ty::FnSig<'tcx>>) -> Cow<'static, str> { + format!("normalizing `{:?}`", goal).into() } } impl<'tcx> QueryDescription<'tcx> for queries::is_copy_raw<'tcx> { - fn describe(_tcx: TyCtxt<'_, '_, '_>, env: ty::ParamEnvAnd<'tcx, Ty<'tcx>>) -> String { - format!("computing whether `{}` is `Copy`", env.value) + fn describe(_tcx: TyCtxt<'_, '_, '_>, env: ty::ParamEnvAnd<'tcx, Ty<'tcx>>) + -> Cow<'static, str> { + format!("computing whether `{}` is `Copy`", env.value).into() } } impl<'tcx> QueryDescription<'tcx> for queries::is_sized_raw<'tcx> { - fn describe(_tcx: TyCtxt<'_, '_, '_>, env: ty::ParamEnvAnd<'tcx, Ty<'tcx>>) -> String { - format!("computing whether `{}` is `Sized`", env.value) + fn describe(_tcx: TyCtxt<'_, '_, '_>, env: ty::ParamEnvAnd<'tcx, Ty<'tcx>>) + -> Cow<'static, str> { + format!("computing whether `{}` is `Sized`", env.value).into() } } impl<'tcx> QueryDescription<'tcx> for queries::is_freeze_raw<'tcx> { - fn describe(_tcx: TyCtxt<'_, '_, '_>, env: ty::ParamEnvAnd<'tcx, Ty<'tcx>>) -> String { - format!("computing whether `{}` is freeze", env.value) + fn describe(_tcx: TyCtxt<'_, '_, '_>, env: ty::ParamEnvAnd<'tcx, Ty<'tcx>>) + -> Cow<'static, str> { + format!("computing whether `{}` is freeze", env.value).into() } } impl<'tcx> QueryDescription<'tcx> for queries::needs_drop_raw<'tcx> { - fn describe(_tcx: TyCtxt<'_, '_, '_>, env: ty::ParamEnvAnd<'tcx, Ty<'tcx>>) -> String { - format!("computing whether `{}` needs drop", env.value) + fn describe(_tcx: TyCtxt<'_, '_, '_>, env: ty::ParamEnvAnd<'tcx, Ty<'tcx>>) + -> Cow<'static, str> { + format!("computing whether `{}` needs drop", env.value).into() } } impl<'tcx> QueryDescription<'tcx> for queries::layout_raw<'tcx> { - fn describe(_tcx: TyCtxt<'_, '_, '_>, env: ty::ParamEnvAnd<'tcx, Ty<'tcx>>) -> String { - format!("computing layout of `{}`", env.value) + fn describe(_tcx: TyCtxt<'_, '_, '_>, env: ty::ParamEnvAnd<'tcx, Ty<'tcx>>) + -> Cow<'static, str> { + format!("computing layout of `{}`", env.value).into() } } impl<'tcx> QueryDescription<'tcx> for queries::super_predicates_of<'tcx> { - fn describe(tcx: TyCtxt<'_, '_, '_>, def_id: DefId) -> String { + fn describe(tcx: TyCtxt<'_, '_, '_>, def_id: DefId) -> Cow<'static, str> { format!("computing the supertraits of `{}`", - tcx.item_path_str(def_id)) + tcx.item_path_str(def_id)).into() } } impl<'tcx> QueryDescription<'tcx> for queries::erase_regions_ty<'tcx> { - fn describe(_tcx: TyCtxt<'_, '_, '_>, ty: Ty<'tcx>) -> String { - format!("erasing regions from `{:?}`", ty) + fn describe(_tcx: TyCtxt<'_, '_, '_>, ty: Ty<'tcx>) -> Cow<'static, str> { + format!("erasing regions from `{:?}`", ty).into() } } impl<'tcx> QueryDescription<'tcx> for queries::type_param_predicates<'tcx> { - fn describe(tcx: TyCtxt<'_, '_, '_>, (_, def_id): (DefId, DefId)) -> String { + fn describe(tcx: TyCtxt<'_, '_, '_>, (_, def_id): (DefId, DefId)) -> Cow<'static, str> { let id = tcx.hir.as_local_node_id(def_id).unwrap(); format!("computing the bounds for type parameter `{}`", - tcx.hir.ty_param_name(id)) + tcx.hir.ty_param_name(id)).into() } } impl<'tcx> QueryDescription<'tcx> for queries::coherent_trait<'tcx> { - fn describe(tcx: TyCtxt<'_, '_, '_>, def_id: DefId) -> String { + fn describe(tcx: TyCtxt<'_, '_, '_>, def_id: DefId) -> Cow<'static, str> { format!("coherence checking all impls of trait `{}`", - tcx.item_path_str(def_id)) + tcx.item_path_str(def_id)).into() } } impl<'tcx> QueryDescription<'tcx> for queries::upstream_monomorphizations<'tcx> { - fn describe(_: TyCtxt<'_, '_, '_>, k: CrateNum) -> String { - format!("collecting available upstream monomorphizations `{:?}`", k) + fn describe(_: TyCtxt<'_, '_, '_>, k: CrateNum) -> Cow<'static, str> { + format!("collecting available upstream monomorphizations `{:?}`", k).into() } } impl<'tcx> QueryDescription<'tcx> for queries::crate_inherent_impls<'tcx> { - fn describe(_: TyCtxt<'_, '_, '_>, k: CrateNum) -> String { - format!("all inherent impls defined in crate `{:?}`", k) + fn describe(_: TyCtxt<'_, '_, '_>, k: CrateNum) -> Cow<'static, str> { + format!("all inherent impls defined in crate `{:?}`", k).into() } } impl<'tcx> QueryDescription<'tcx> for queries::crate_inherent_impls_overlap_check<'tcx> { - fn describe(_: TyCtxt<'_, '_, '_>, _: CrateNum) -> String { - "check for overlap between inherent impls defined in this crate".to_string() + fn describe(_: TyCtxt<'_, '_, '_>, _: CrateNum) -> Cow<'static, str> { + "check for overlap between inherent impls defined in this crate".into() } } impl<'tcx> QueryDescription<'tcx> for queries::crate_variances<'tcx> { - fn describe(_tcx: TyCtxt<'_, '_, '_>, _: CrateNum) -> String { - "computing the variances for items in this crate".to_string() + fn describe(_tcx: TyCtxt<'_, '_, '_>, _: CrateNum) -> Cow<'static, str> { + "computing the variances for items in this crate".into() } } impl<'tcx> QueryDescription<'tcx> for queries::inferred_outlives_crate<'tcx> { - fn describe(_tcx: TyCtxt<'_, '_, '_>, _: CrateNum) -> String { - "computing the inferred outlives predicates for items in this crate".to_string() + fn describe(_tcx: TyCtxt<'_, '_, '_>, _: CrateNum) -> Cow<'static, str> { + "computing the inferred outlives predicates for items in this crate".into() } } impl<'tcx> QueryDescription<'tcx> for queries::mir_shims<'tcx> { - fn describe(tcx: TyCtxt<'_, '_, '_>, def: ty::InstanceDef<'tcx>) -> String { + fn describe(tcx: TyCtxt<'_, '_, '_>, def: ty::InstanceDef<'tcx>) -> Cow<'static, str> { format!("generating MIR shim for `{}`", - tcx.item_path_str(def.def_id())) + tcx.item_path_str(def.def_id())).into() } } impl<'tcx> QueryDescription<'tcx> for queries::privacy_access_levels<'tcx> { - fn describe(_: TyCtxt<'_, '_, '_>, _: CrateNum) -> String { - "privacy access levels".to_string() + fn describe(_: TyCtxt<'_, '_, '_>, _: CrateNum) -> Cow<'static, str> { + "privacy access levels".into() } } impl<'tcx> QueryDescription<'tcx> for queries::typeck_item_bodies<'tcx> { - fn describe(_: TyCtxt<'_, '_, '_>, _: CrateNum) -> String { - "type-checking all item bodies".to_string() + fn describe(_: TyCtxt<'_, '_, '_>, _: CrateNum) -> Cow<'static, str> { + "type-checking all item bodies".into() } } impl<'tcx> QueryDescription<'tcx> for queries::reachable_set<'tcx> { - fn describe(_: TyCtxt<'_, '_, '_>, _: CrateNum) -> String { - "reachability".to_string() + fn describe(_: TyCtxt<'_, '_, '_>, _: CrateNum) -> Cow<'static, str> { + "reachability".into() } } impl<'tcx> QueryDescription<'tcx> for queries::const_eval<'tcx> { - fn describe(tcx: TyCtxt<'_, '_, '_>, key: ty::ParamEnvAnd<'tcx, GlobalId<'tcx>>) -> String { - format!("const-evaluating `{}`", tcx.item_path_str(key.value.instance.def.def_id())) + fn describe(tcx: TyCtxt<'_, '_, '_>, key: ty::ParamEnvAnd<'tcx, GlobalId<'tcx>>) + -> Cow<'static, str> + { + format!("const-evaluating `{}`", tcx.item_path_str(key.value.instance.def.def_id())).into() } #[inline] @@ -295,14 +305,14 @@ impl<'tcx> QueryDescription<'tcx> for queries::const_eval<'tcx> { } impl<'tcx> QueryDescription<'tcx> for queries::mir_keys<'tcx> { - fn describe(_: TyCtxt<'_, '_, '_>, _: CrateNum) -> String { - "getting a list of all mir_keys".to_string() + fn describe(_: TyCtxt<'_, '_, '_>, _: CrateNum) -> Cow<'static, str> { + "getting a list of all mir_keys".into() } } impl<'tcx> QueryDescription<'tcx> for queries::symbol_name<'tcx> { - fn describe(_tcx: TyCtxt<'_, '_, '_>, instance: ty::Instance<'tcx>) -> String { - format!("computing the symbol for `{}`", instance) + fn describe(_tcx: TyCtxt<'_, '_, '_>, instance: ty::Instance<'tcx>) -> Cow<'static, str> { + format!("computing the symbol for `{}`", instance).into() } #[inline] @@ -319,64 +329,64 @@ impl<'tcx> QueryDescription<'tcx> for queries::symbol_name<'tcx> { } impl<'tcx> QueryDescription<'tcx> for queries::describe_def<'tcx> { - fn describe(_: TyCtxt<'_, '_, '_>, _: DefId) -> String { + fn describe(_: TyCtxt<'_, '_, '_>, _: DefId) -> Cow<'static, str> { bug!("describe_def") } } impl<'tcx> QueryDescription<'tcx> for queries::def_span<'tcx> { - fn describe(_: TyCtxt<'_, '_, '_>, _: DefId) -> String { + fn describe(_: TyCtxt<'_, '_, '_>, _: DefId) -> Cow<'static, str> { bug!("def_span") } } impl<'tcx> QueryDescription<'tcx> for queries::lookup_stability<'tcx> { - fn describe(_: TyCtxt<'_, '_, '_>, _: DefId) -> String { + fn describe(_: TyCtxt<'_, '_, '_>, _: DefId) -> Cow<'static, str> { bug!("stability") } } impl<'tcx> QueryDescription<'tcx> for queries::lookup_deprecation_entry<'tcx> { - fn describe(_: TyCtxt<'_, '_, '_>, _: DefId) -> String { + fn describe(_: TyCtxt<'_, '_, '_>, _: DefId) -> Cow<'static, str> { bug!("deprecation") } } impl<'tcx> QueryDescription<'tcx> for queries::item_attrs<'tcx> { - fn describe(_: TyCtxt<'_, '_, '_>, _: DefId) -> String { + fn describe(_: TyCtxt<'_, '_, '_>, _: DefId) -> Cow<'static, str> { bug!("item_attrs") } } impl<'tcx> QueryDescription<'tcx> for queries::is_reachable_non_generic<'tcx> { - fn describe(_: TyCtxt<'_, '_, '_>, _: DefId) -> String { + fn describe(_: TyCtxt<'_, '_, '_>, _: DefId) -> Cow<'static, str> { bug!("is_reachable_non_generic") } } impl<'tcx> QueryDescription<'tcx> for queries::fn_arg_names<'tcx> { - fn describe(_: TyCtxt<'_, '_, '_>, _: DefId) -> String { + fn describe(_: TyCtxt<'_, '_, '_>, _: DefId) -> Cow<'static, str> { bug!("fn_arg_names") } } impl<'tcx> QueryDescription<'tcx> for queries::impl_parent<'tcx> { - fn describe(_: TyCtxt<'_, '_, '_>, _: DefId) -> String { + fn describe(_: TyCtxt<'_, '_, '_>, _: DefId) -> Cow<'static, str> { bug!("impl_parent") } } impl<'tcx> QueryDescription<'tcx> for queries::trait_of_item<'tcx> { - fn describe(_: TyCtxt<'_, '_, '_>, _: DefId) -> String { + fn describe(_: TyCtxt<'_, '_, '_>, _: DefId) -> Cow<'static, str> { bug!("trait_of_item") } } impl<'tcx> QueryDescription<'tcx> for queries::const_is_rvalue_promotable_to_static<'tcx> { - fn describe(tcx: TyCtxt<'_, '_, '_>, def_id: DefId) -> String { + fn describe(tcx: TyCtxt<'_, '_, '_>, def_id: DefId) -> Cow<'static, str> { format!("const checking if rvalue is promotable to static `{}`", - tcx.item_path_str(def_id)) + tcx.item_path_str(def_id)).into() } #[inline] @@ -393,23 +403,24 @@ impl<'tcx> QueryDescription<'tcx> for queries::const_is_rvalue_promotable_to_sta } impl<'tcx> QueryDescription<'tcx> for queries::rvalue_promotable_map<'tcx> { - fn describe(tcx: TyCtxt<'_, '_, '_>, def_id: DefId) -> String { + fn describe(tcx: TyCtxt<'_, '_, '_>, def_id: DefId) -> Cow<'static, str> { format!("checking which parts of `{}` are promotable to static", - tcx.item_path_str(def_id)) + tcx.item_path_str(def_id)).into() } } impl<'tcx> QueryDescription<'tcx> for queries::is_mir_available<'tcx> { - fn describe(tcx: TyCtxt<'_, '_, '_>, def_id: DefId) -> String { + fn describe(tcx: TyCtxt<'_, '_, '_>, def_id: DefId) -> Cow<'static, str> { format!("checking if item is mir available: `{}`", - tcx.item_path_str(def_id)) + tcx.item_path_str(def_id)).into() } } impl<'tcx> QueryDescription<'tcx> for queries::codegen_fulfill_obligation<'tcx> { fn describe(tcx: TyCtxt<'_, '_, '_>, - key: (ty::ParamEnv<'tcx>, ty::PolyTraitRef<'tcx>)) -> String { + key: (ty::ParamEnv<'tcx>, ty::PolyTraitRef<'tcx>)) -> Cow<'static, str> { format!("checking if `{}` fulfills its obligations", tcx.item_path_str(key.1.def_id())) + .into() } #[inline] @@ -426,320 +437,320 @@ impl<'tcx> QueryDescription<'tcx> for queries::codegen_fulfill_obligation<'tcx> } impl<'tcx> QueryDescription<'tcx> for queries::trait_impls_of<'tcx> { - fn describe(tcx: TyCtxt<'_, '_, '_>, def_id: DefId) -> String { - format!("trait impls of `{}`", tcx.item_path_str(def_id)) + fn describe(tcx: TyCtxt<'_, '_, '_>, def_id: DefId) -> Cow<'static, str> { + format!("trait impls of `{}`", tcx.item_path_str(def_id)).into() } } impl<'tcx> QueryDescription<'tcx> for queries::is_object_safe<'tcx> { - fn describe(tcx: TyCtxt<'_, '_, '_>, def_id: DefId) -> String { - format!("determine object safety of trait `{}`", tcx.item_path_str(def_id)) + fn describe(tcx: TyCtxt<'_, '_, '_>, def_id: DefId) -> Cow<'static, str> { + format!("determine object safety of trait `{}`", tcx.item_path_str(def_id)).into() } } impl<'tcx> QueryDescription<'tcx> for queries::is_const_fn_raw<'tcx> { - fn describe(tcx: TyCtxt<'_, '_, '_>, def_id: DefId) -> String { - format!("checking if item is const fn: `{}`", tcx.item_path_str(def_id)) + fn describe(tcx: TyCtxt<'_, '_, '_>, def_id: DefId) -> Cow<'static, str> { + format!("checking if item is const fn: `{}`", tcx.item_path_str(def_id)).into() } } impl<'tcx> QueryDescription<'tcx> for queries::dylib_dependency_formats<'tcx> { - fn describe(_: TyCtxt<'_, '_, '_>, _: CrateNum) -> String { - "dylib dependency formats of crate".to_string() + fn describe(_: TyCtxt<'_, '_, '_>, _: CrateNum) -> Cow<'static, str> { + "dylib dependency formats of crate".into() } } impl<'tcx> QueryDescription<'tcx> for queries::is_panic_runtime<'tcx> { - fn describe(_: TyCtxt<'_, '_, '_>, _: CrateNum) -> String { - "checking if the crate is_panic_runtime".to_string() + fn describe(_: TyCtxt<'_, '_, '_>, _: CrateNum) -> Cow<'static, str> { + "checking if the crate is_panic_runtime".into() } } impl<'tcx> QueryDescription<'tcx> for queries::is_compiler_builtins<'tcx> { - fn describe(_: TyCtxt<'_, '_, '_>, _: CrateNum) -> String { - "checking if the crate is_compiler_builtins".to_string() + fn describe(_: TyCtxt<'_, '_, '_>, _: CrateNum) -> Cow<'static, str> { + "checking if the crate is_compiler_builtins".into() } } impl<'tcx> QueryDescription<'tcx> for queries::has_global_allocator<'tcx> { - fn describe(_: TyCtxt<'_, '_, '_>, _: CrateNum) -> String { - "checking if the crate has_global_allocator".to_string() + fn describe(_: TyCtxt<'_, '_, '_>, _: CrateNum) -> Cow<'static, str> { + "checking if the crate has_global_allocator".into() } } impl<'tcx> QueryDescription<'tcx> for queries::has_panic_handler<'tcx> { - fn describe(_: TyCtxt<'_, '_, '_>, _: CrateNum) -> String { - "checking if the crate has_panic_handler".to_string() + fn describe(_: TyCtxt<'_, '_, '_>, _: CrateNum) -> Cow<'static, str> { + "checking if the crate has_panic_handler".into() } } impl<'tcx> QueryDescription<'tcx> for queries::extern_crate<'tcx> { - fn describe(_: TyCtxt<'_, '_, '_>, _: DefId) -> String { - "getting crate's ExternCrateData".to_string() + fn describe(_: TyCtxt<'_, '_, '_>, _: DefId) -> Cow<'static, str> { + "getting crate's ExternCrateData".into() } } impl<'tcx> QueryDescription<'tcx> for queries::lint_levels<'tcx> { - fn describe(_tcx: TyCtxt<'_, '_, '_>, _: CrateNum) -> String { - "computing the lint levels for items in this crate".to_string() + fn describe(_tcx: TyCtxt<'_, '_, '_>, _: CrateNum) -> Cow<'static, str> { + "computing the lint levels for items in this crate".into() } } impl<'tcx> QueryDescription<'tcx> for queries::specializes<'tcx> { - fn describe(_tcx: TyCtxt<'_, '_, '_>, _: (DefId, DefId)) -> String { - "computing whether impls specialize one another".to_string() + fn describe(_tcx: TyCtxt<'_, '_, '_>, _: (DefId, DefId)) -> Cow<'static, str> { + "computing whether impls specialize one another".into() } } impl<'tcx> QueryDescription<'tcx> for queries::in_scope_traits_map<'tcx> { - fn describe(_tcx: TyCtxt<'_, '_, '_>, _: DefIndex) -> String { - "traits in scope at a block".to_string() + fn describe(_tcx: TyCtxt<'_, '_, '_>, _: DefIndex) -> Cow<'static, str> { + "traits in scope at a block".into() } } impl<'tcx> QueryDescription<'tcx> for queries::is_no_builtins<'tcx> { - fn describe(_tcx: TyCtxt<'_, '_, '_>, _: CrateNum) -> String { - "test whether a crate has #![no_builtins]".to_string() + fn describe(_tcx: TyCtxt<'_, '_, '_>, _: CrateNum) -> Cow<'static, str> { + "test whether a crate has #![no_builtins]".into() } } impl<'tcx> QueryDescription<'tcx> for queries::panic_strategy<'tcx> { - fn describe(_tcx: TyCtxt<'_, '_, '_>, _: CrateNum) -> String { - "query a crate's configured panic strategy".to_string() + fn describe(_tcx: TyCtxt<'_, '_, '_>, _: CrateNum) -> Cow<'static, str> { + "query a crate's configured panic strategy".into() } } impl<'tcx> QueryDescription<'tcx> for queries::is_profiler_runtime<'tcx> { - fn describe(_tcx: TyCtxt<'_, '_, '_>, _: CrateNum) -> String { - "query a crate is #![profiler_runtime]".to_string() + fn describe(_tcx: TyCtxt<'_, '_, '_>, _: CrateNum) -> Cow<'static, str> { + "query a crate is #![profiler_runtime]".into() } } impl<'tcx> QueryDescription<'tcx> for queries::is_sanitizer_runtime<'tcx> { - fn describe(_tcx: TyCtxt<'_, '_, '_>, _: CrateNum) -> String { - "query a crate is #![sanitizer_runtime]".to_string() + fn describe(_tcx: TyCtxt<'_, '_, '_>, _: CrateNum) -> Cow<'static, str> { + "query a crate is #![sanitizer_runtime]".into() } } impl<'tcx> QueryDescription<'tcx> for queries::reachable_non_generics<'tcx> { - fn describe(_tcx: TyCtxt<'_, '_, '_>, _: CrateNum) -> String { - "looking up the exported symbols of a crate".to_string() + fn describe(_tcx: TyCtxt<'_, '_, '_>, _: CrateNum) -> Cow<'static, str> { + "looking up the exported symbols of a crate".into() } } impl<'tcx> QueryDescription<'tcx> for queries::native_libraries<'tcx> { - fn describe(_tcx: TyCtxt<'_, '_, '_>, _: CrateNum) -> String { - "looking up the native libraries of a linked crate".to_string() + fn describe(_tcx: TyCtxt<'_, '_, '_>, _: CrateNum) -> Cow<'static, str> { + "looking up the native libraries of a linked crate".into() } } impl<'tcx> QueryDescription<'tcx> for queries::foreign_modules<'tcx> { - fn describe(_tcx: TyCtxt<'_, '_, '_>, _: CrateNum) -> String { - "looking up the foreign modules of a linked crate".to_string() + fn describe(_tcx: TyCtxt<'_, '_, '_>, _: CrateNum) -> Cow<'static, str> { + "looking up the foreign modules of a linked crate".into() } } impl<'tcx> QueryDescription<'tcx> for queries::plugin_registrar_fn<'tcx> { - fn describe(_tcx: TyCtxt<'_, '_, '_>, _: CrateNum) -> String { - "looking up the plugin registrar for a crate".to_string() + fn describe(_tcx: TyCtxt<'_, '_, '_>, _: CrateNum) -> Cow<'static, str> { + "looking up the plugin registrar for a crate".into() } } impl<'tcx> QueryDescription<'tcx> for queries::derive_registrar_fn<'tcx> { - fn describe(_tcx: TyCtxt<'_, '_, '_>, _: CrateNum) -> String { - "looking up the derive registrar for a crate".to_string() + fn describe(_tcx: TyCtxt<'_, '_, '_>, _: CrateNum) -> Cow<'static, str> { + "looking up the derive registrar for a crate".into() } } impl<'tcx> QueryDescription<'tcx> for queries::crate_disambiguator<'tcx> { - fn describe(_tcx: TyCtxt<'_, '_, '_>, _: CrateNum) -> String { - "looking up the disambiguator a crate".to_string() + fn describe(_tcx: TyCtxt<'_, '_, '_>, _: CrateNum) -> Cow<'static, str> { + "looking up the disambiguator a crate".into() } } impl<'tcx> QueryDescription<'tcx> for queries::crate_hash<'tcx> { - fn describe(_tcx: TyCtxt<'_, '_, '_>, _: CrateNum) -> String { - "looking up the hash a crate".to_string() + fn describe(_tcx: TyCtxt<'_, '_, '_>, _: CrateNum) -> Cow<'static, str> { + "looking up the hash a crate".into() } } impl<'tcx> QueryDescription<'tcx> for queries::original_crate_name<'tcx> { - fn describe(_tcx: TyCtxt<'_, '_, '_>, _: CrateNum) -> String { - "looking up the original name a crate".to_string() + fn describe(_tcx: TyCtxt<'_, '_, '_>, _: CrateNum) -> Cow<'static, str> { + "looking up the original name a crate".into() } } impl<'tcx> QueryDescription<'tcx> for queries::extra_filename<'tcx> { - fn describe(_tcx: TyCtxt<'_, '_, '_>, _: CrateNum) -> String { - "looking up the extra filename for a crate".to_string() + fn describe(_tcx: TyCtxt<'_, '_, '_>, _: CrateNum) -> Cow<'static, str> { + "looking up the extra filename for a crate".into() } } impl<'tcx> QueryDescription<'tcx> for queries::implementations_of_trait<'tcx> { - fn describe(_tcx: TyCtxt<'_, '_, '_>, _: (CrateNum, DefId)) -> String { - "looking up implementations of a trait in a crate".to_string() + fn describe(_tcx: TyCtxt<'_, '_, '_>, _: (CrateNum, DefId)) -> Cow<'static, str> { + "looking up implementations of a trait in a crate".into() } } impl<'tcx> QueryDescription<'tcx> for queries::all_trait_implementations<'tcx> { - fn describe(_tcx: TyCtxt<'_, '_, '_>, _: CrateNum) -> String { - "looking up all (?) trait implementations".to_string() + fn describe(_tcx: TyCtxt<'_, '_, '_>, _: CrateNum) -> Cow<'static, str> { + "looking up all (?) trait implementations".into() } } impl<'tcx> QueryDescription<'tcx> for queries::link_args<'tcx> { - fn describe(_tcx: TyCtxt<'_, '_, '_>, _: CrateNum) -> String { - "looking up link arguments for a crate".to_string() + fn describe(_tcx: TyCtxt<'_, '_, '_>, _: CrateNum) -> Cow<'static, str> { + "looking up link arguments for a crate".into() } } impl<'tcx> QueryDescription<'tcx> for queries::resolve_lifetimes<'tcx> { - fn describe(_tcx: TyCtxt<'_, '_, '_>, _: CrateNum) -> String { - "resolving lifetimes".to_string() + fn describe(_tcx: TyCtxt<'_, '_, '_>, _: CrateNum) -> Cow<'static, str> { + "resolving lifetimes".into() } } impl<'tcx> QueryDescription<'tcx> for queries::named_region_map<'tcx> { - fn describe(_tcx: TyCtxt<'_, '_, '_>, _: DefIndex) -> String { - "looking up a named region".to_string() + fn describe(_tcx: TyCtxt<'_, '_, '_>, _: DefIndex) -> Cow<'static, str> { + "looking up a named region".into() } } impl<'tcx> QueryDescription<'tcx> for queries::is_late_bound_map<'tcx> { - fn describe(_tcx: TyCtxt<'_, '_, '_>, _: DefIndex) -> String { - "testing if a region is late bound".to_string() + fn describe(_tcx: TyCtxt<'_, '_, '_>, _: DefIndex) -> Cow<'static, str> { + "testing if a region is late bound".into() } } impl<'tcx> QueryDescription<'tcx> for queries::object_lifetime_defaults_map<'tcx> { - fn describe(_tcx: TyCtxt<'_, '_, '_>, _: DefIndex) -> String { - "looking up lifetime defaults for a region".to_string() + fn describe(_tcx: TyCtxt<'_, '_, '_>, _: DefIndex) -> Cow<'static, str> { + "looking up lifetime defaults for a region".into() } } impl<'tcx> QueryDescription<'tcx> for queries::dep_kind<'tcx> { - fn describe(_tcx: TyCtxt<'_, '_, '_>, _: CrateNum) -> String { - "fetching what a dependency looks like".to_string() + fn describe(_tcx: TyCtxt<'_, '_, '_>, _: CrateNum) -> Cow<'static, str> { + "fetching what a dependency looks like".into() } } impl<'tcx> QueryDescription<'tcx> for queries::crate_name<'tcx> { - fn describe(_tcx: TyCtxt<'_, '_, '_>, _: CrateNum) -> String { - "fetching what a crate is named".to_string() + fn describe(_tcx: TyCtxt<'_, '_, '_>, _: CrateNum) -> Cow<'static, str> { + "fetching what a crate is named".into() } } impl<'tcx> QueryDescription<'tcx> for queries::get_lib_features<'tcx> { - fn describe(_tcx: TyCtxt<'_, '_, '_>, _: CrateNum) -> String { - format!("calculating the lib features map") + fn describe(_tcx: TyCtxt<'_, '_, '_>, _: CrateNum) -> Cow<'static, str> { + "calculating the lib features map".into() } } impl<'tcx> QueryDescription<'tcx> for queries::defined_lib_features<'tcx> { - fn describe(_tcx: TyCtxt<'_, '_, '_>, _: CrateNum) -> String { - format!("calculating the lib features defined in a crate") + fn describe(_tcx: TyCtxt<'_, '_, '_>, _: CrateNum) -> Cow<'static, str> { + "calculating the lib features defined in a crate".into() } } impl<'tcx> QueryDescription<'tcx> for queries::get_lang_items<'tcx> { - fn describe(_tcx: TyCtxt<'_, '_, '_>, _: CrateNum) -> String { - "calculating the lang items map".to_string() + fn describe(_tcx: TyCtxt<'_, '_, '_>, _: CrateNum) -> Cow<'static, str> { + "calculating the lang items map".into() } } impl<'tcx> QueryDescription<'tcx> for queries::defined_lang_items<'tcx> { - fn describe(_tcx: TyCtxt<'_, '_, '_>, _: CrateNum) -> String { - "calculating the lang items defined in a crate".to_string() + fn describe(_tcx: TyCtxt<'_, '_, '_>, _: CrateNum) -> Cow<'static, str> { + "calculating the lang items defined in a crate".into() } } impl<'tcx> QueryDescription<'tcx> for queries::missing_lang_items<'tcx> { - fn describe(_tcx: TyCtxt<'_, '_, '_>, _: CrateNum) -> String { - "calculating the missing lang items in a crate".to_string() + fn describe(_tcx: TyCtxt<'_, '_, '_>, _: CrateNum) -> Cow<'static, str> { + "calculating the missing lang items in a crate".into() } } impl<'tcx> QueryDescription<'tcx> for queries::visible_parent_map<'tcx> { - fn describe(_tcx: TyCtxt<'_, '_, '_>, _: CrateNum) -> String { - "calculating the visible parent map".to_string() + fn describe(_tcx: TyCtxt<'_, '_, '_>, _: CrateNum) -> Cow<'static, str> { + "calculating the visible parent map".into() } } impl<'tcx> QueryDescription<'tcx> for queries::missing_extern_crate_item<'tcx> { - fn describe(_tcx: TyCtxt<'_, '_, '_>, _: CrateNum) -> String { - "seeing if we're missing an `extern crate` item for this crate".to_string() + fn describe(_tcx: TyCtxt<'_, '_, '_>, _: CrateNum) -> Cow<'static, str> { + "seeing if we're missing an `extern crate` item for this crate".into() } } impl<'tcx> QueryDescription<'tcx> for queries::used_crate_source<'tcx> { - fn describe(_tcx: TyCtxt<'_, '_, '_>, _: CrateNum) -> String { - "looking at the source for a crate".to_string() + fn describe(_tcx: TyCtxt<'_, '_, '_>, _: CrateNum) -> Cow<'static, str> { + "looking at the source for a crate".into() } } impl<'tcx> QueryDescription<'tcx> for queries::postorder_cnums<'tcx> { - fn describe(_tcx: TyCtxt<'_, '_, '_>, _: CrateNum) -> String { - "generating a postorder list of CrateNums".to_string() + fn describe(_tcx: TyCtxt<'_, '_, '_>, _: CrateNum) -> Cow<'static, str> { + "generating a postorder list of CrateNums".into() } } impl<'tcx> QueryDescription<'tcx> for queries::maybe_unused_extern_crates<'tcx> { - fn describe(_tcx: TyCtxt<'_, '_, '_>, _: CrateNum) -> String { - "looking up all possibly unused extern crates".to_string() + fn describe(_tcx: TyCtxt<'_, '_, '_>, _: CrateNum) -> Cow<'static, str> { + "looking up all possibly unused extern crates".into() } } impl<'tcx> QueryDescription<'tcx> for queries::stability_index<'tcx> { - fn describe(_tcx: TyCtxt<'_, '_, '_>, _: CrateNum) -> String { - "calculating the stability index for the local crate".to_string() + fn describe(_tcx: TyCtxt<'_, '_, '_>, _: CrateNum) -> Cow<'static, str> { + "calculating the stability index for the local crate".into() } } impl<'tcx> QueryDescription<'tcx> for queries::all_traits<'tcx> { - fn describe(_tcx: TyCtxt<'_, '_, '_>, _: CrateNum) -> String { - "fetching all foreign and local traits".to_string() + fn describe(_tcx: TyCtxt<'_, '_, '_>, _: CrateNum) -> Cow<'static, str> { + "fetching all foreign and local traits".into() } } impl<'tcx> QueryDescription<'tcx> for queries::all_crate_nums<'tcx> { - fn describe(_tcx: TyCtxt<'_, '_, '_>, _: CrateNum) -> String { - "fetching all foreign CrateNum instances".to_string() + fn describe(_tcx: TyCtxt<'_, '_, '_>, _: CrateNum) -> Cow<'static, str> { + "fetching all foreign CrateNum instances".into() } } impl<'tcx> QueryDescription<'tcx> for queries::exported_symbols<'tcx> { - fn describe(_tcx: TyCtxt<'_, '_, '_>, _: CrateNum) -> String { - "exported_symbols".to_string() + fn describe(_tcx: TyCtxt<'_, '_, '_>, _: CrateNum) -> Cow<'static, str> { + "exported_symbols".into() } } impl<'tcx> QueryDescription<'tcx> for queries::collect_and_partition_mono_items<'tcx> { - fn describe(_tcx: TyCtxt<'_, '_, '_>, _: CrateNum) -> String { - "collect_and_partition_mono_items".to_string() + fn describe(_tcx: TyCtxt<'_, '_, '_>, _: CrateNum) -> Cow<'static, str> { + "collect_and_partition_mono_items".into() } } impl<'tcx> QueryDescription<'tcx> for queries::codegen_unit<'tcx> { - fn describe(_tcx: TyCtxt<'_, '_, '_>, _: InternedString) -> String { - "codegen_unit".to_string() + fn describe(_tcx: TyCtxt<'_, '_, '_>, _: InternedString) -> Cow<'static, str> { + "codegen_unit".into() } } impl<'tcx> QueryDescription<'tcx> for queries::output_filenames<'tcx> { - fn describe(_tcx: TyCtxt<'_, '_, '_>, _: CrateNum) -> String { - "output_filenames".to_string() + fn describe(_tcx: TyCtxt<'_, '_, '_>, _: CrateNum) -> Cow<'static, str> { + "output_filenames".into() } } impl<'tcx> QueryDescription<'tcx> for queries::vtable_methods<'tcx> { - fn describe(tcx: TyCtxt<'_, '_, '_>, key: ty::PolyTraitRef<'tcx> ) -> String { - format!("finding all methods for trait {}", tcx.item_path_str(key.def_id())) + fn describe(tcx: TyCtxt<'_, '_, '_>, key: ty::PolyTraitRef<'tcx> ) -> Cow<'static, str> { + format!("finding all methods for trait {}", tcx.item_path_str(key.def_id())).into() } } impl<'tcx> QueryDescription<'tcx> for queries::features_query<'tcx> { - fn describe(_tcx: TyCtxt<'_, '_, '_>, _: CrateNum) -> String { - "looking up enabled feature gates".to_string() + fn describe(_tcx: TyCtxt<'_, '_, '_>, _: CrateNum) -> Cow<'static, str> { + "looking up enabled feature gates".into() } } @@ -776,20 +787,20 @@ impl<'tcx> QueryDescription<'tcx> for queries::optimized_mir<'tcx> { } impl<'tcx> QueryDescription<'tcx> for queries::substitute_normalize_and_test_predicates<'tcx> { - fn describe(tcx: TyCtxt<'_, '_, '_>, key: (DefId, &'tcx Substs<'tcx>)) -> String { - format!("testing substituted normalized predicates:`{}`", tcx.item_path_str(key.0)) + fn describe(tcx: TyCtxt<'_, '_, '_>, key: (DefId, &'tcx Substs<'tcx>)) -> Cow<'static, str> { + format!("testing substituted normalized predicates:`{}`", tcx.item_path_str(key.0)).into() } } impl<'tcx> QueryDescription<'tcx> for queries::target_features_whitelist<'tcx> { - fn describe(_tcx: TyCtxt<'_, '_, '_>, _: CrateNum) -> String { - "looking up the whitelist of target features".to_string() + fn describe(_tcx: TyCtxt<'_, '_, '_>, _: CrateNum) -> Cow<'static, str> { + "looking up the whitelist of target features".into() } } impl<'tcx> QueryDescription<'tcx> for queries::instance_def_size_estimate<'tcx> { - fn describe(tcx: TyCtxt<'_, '_, '_>, def: ty::InstanceDef<'tcx>) -> String { - format!("estimating size for `{}`", tcx.item_path_str(def.def_id())) + fn describe(tcx: TyCtxt<'_, '_, '_>, def: ty::InstanceDef<'tcx>) -> Cow<'static, str> { + format!("estimating size for `{}`", tcx.item_path_str(def.def_id())).into() } } @@ -809,26 +820,26 @@ impl<'tcx> QueryDescription<'tcx> for queries::generics_of<'tcx> { } impl<'tcx> QueryDescription<'tcx> for queries::program_clauses_for<'tcx> { - fn describe(_tcx: TyCtxt<'_, '_, '_>, _: DefId) -> String { - "generating chalk-style clauses".to_string() + fn describe(_tcx: TyCtxt<'_, '_, '_>, _: DefId) -> Cow<'static, str> { + "generating chalk-style clauses".into() } } impl<'tcx> QueryDescription<'tcx> for queries::program_clauses_for_env<'tcx> { - fn describe(_tcx: TyCtxt<'_, '_, '_>, _: ty::ParamEnv<'tcx>) -> String { - "generating chalk-style clauses for param env".to_string() + fn describe(_tcx: TyCtxt<'_, '_, '_>, _: ty::ParamEnv<'tcx>) -> Cow<'static, str> { + "generating chalk-style clauses for param env".into() } } impl<'tcx> QueryDescription<'tcx> for queries::wasm_import_module_map<'tcx> { - fn describe(_tcx: TyCtxt<'_, '_, '_>, _: CrateNum) -> String { - "wasm import module map".to_string() + fn describe(_tcx: TyCtxt<'_, '_, '_>, _: CrateNum) -> Cow<'static, str> { + "wasm import module map".into() } } impl<'tcx> QueryDescription<'tcx> for queries::dllimport_foreign_items<'tcx> { - fn describe(_tcx: TyCtxt<'_, '_, '_>, _: CrateNum) -> String { - "wasm import module map".to_string() + fn describe(_tcx: TyCtxt<'_, '_, '_>, _: CrateNum) -> Cow<'static, str> { + "wasm import module map".into() } } diff --git a/src/librustc/ty/query/mod.rs b/src/librustc/ty/query/mod.rs index 44c9c55b8a4e..7f5bc35f91f9 100644 --- a/src/librustc/ty/query/mod.rs +++ b/src/librustc/ty/query/mod.rs @@ -56,6 +56,7 @@ use rustc_data_structures::stable_hasher::StableVec; use rustc_data_structures::sync::Lrc; use rustc_target::spec::PanicStrategy; +use std::borrow::Cow; use std::ops::Deref; use std::sync::Arc; use syntax_pos::{Span, DUMMY_SP}; diff --git a/src/librustc/ty/query/plumbing.rs b/src/librustc/ty/query/plumbing.rs index 5f6fdbddf8fe..50eae945a8c4 100644 --- a/src/librustc/ty/query/plumbing.rs +++ b/src/librustc/ty/query/plumbing.rs @@ -733,14 +733,14 @@ macro_rules! define_queries_inner { } } - pub fn describe(&self, tcx: TyCtxt<'_, '_, '_>) -> String { + pub fn describe(&self, tcx: TyCtxt<'_, '_, '_>) -> Cow<'static, str> { let (r, name) = match *self { $(Query::$name(key) => { (queries::$name::describe(tcx, key), stringify!($name)) })* }; if tcx.sess.verbose() { - format!("{} [{}]", r, name) + format!("{} [{}]", r, name).into() } else { r } From 029e2618d007e0aebc1a45f8350f9c89df4d18dc Mon Sep 17 00:00:00 2001 From: ljedrz Date: Mon, 1 Oct 2018 15:37:14 +0200 Subject: [PATCH 15/27] rustc/ty: simplify common patterns --- src/librustc/ty/context.rs | 17 ++++++------- src/librustc/ty/error.rs | 25 +++++++++---------- src/librustc/ty/flags.rs | 4 +-- .../ty/inhabitedness/def_id_forest.rs | 7 +----- src/librustc/ty/query/on_disk_cache.rs | 1 - src/librustc/ty/query/plumbing.rs | 12 +++------ 6 files changed, 25 insertions(+), 41 deletions(-) diff --git a/src/librustc/ty/context.rs b/src/librustc/ty/context.rs index daada8891d7a..46ba5f5ef362 100644 --- a/src/librustc/ty/context.rs +++ b/src/librustc/ty/context.rs @@ -540,16 +540,13 @@ impl<'tcx> TypeckTables<'tcx> { } pub fn node_id_to_type(&self, id: hir::HirId) -> Ty<'tcx> { - match self.node_id_to_type_opt(id) { - Some(ty) => ty, - None => { - bug!("node_id_to_type: no type for node `{}`", - tls::with(|tcx| { - let id = tcx.hir.hir_to_node_id(id); - tcx.hir.node_to_string(id) - })) - } - } + self.node_id_to_type_opt(id).unwrap_or_else(|| + bug!("node_id_to_type: no type for node `{}`", + tls::with(|tcx| { + let id = tcx.hir.hir_to_node_id(id); + tcx.hir.node_to_string(id) + })) + ) } pub fn node_id_to_type_opt(&self, id: hir::HirId) -> Option> { diff --git a/src/librustc/ty/error.rs b/src/librustc/ty/error.rs index 2367d482ec89..3123f0fbe31d 100644 --- a/src/librustc/ty/error.rs +++ b/src/librustc/ty/error.rs @@ -252,20 +252,19 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { db.note("no two closures, even if identical, have the same type"); db.help("consider boxing your closure and/or using it as a trait object"); } - match (&values.found.sty, &values.expected.sty) { // Issue #53280 - (ty::Infer(ty::IntVar(_)), ty::Float(_)) => { - if let Ok(snippet) = self.sess.source_map().span_to_snippet(sp) { - if snippet.chars().all(|c| c.is_digit(10) || c == '-' || c == '_') { - db.span_suggestion_with_applicability( - sp, - "use a float literal", - format!("{}.0", snippet), - Applicability::MachineApplicable - ); - } + if let (ty::Infer(ty::IntVar(_)), ty::Float(_)) = + (&values.found.sty, &values.expected.sty) // Issue #53280 + { + if let Ok(snippet) = self.sess.source_map().span_to_snippet(sp) { + if snippet.chars().all(|c| c.is_digit(10) || c == '-' || c == '_') { + db.span_suggestion_with_applicability( + sp, + "use a float literal", + format!("{}.0", snippet), + Applicability::MachineApplicable + ); } - }, - _ => {} + } } }, OldStyleLUB(err) => { diff --git a/src/librustc/ty/flags.rs b/src/librustc/ty/flags.rs index 3ccc24e73a5c..c3d41873009a 100644 --- a/src/librustc/ty/flags.rs +++ b/src/librustc/ty/flags.rs @@ -62,9 +62,7 @@ impl FlagComputation { let outer_exclusive_binder = computation.outer_exclusive_binder; if outer_exclusive_binder > ty::INNERMOST { self.add_exclusive_binder(outer_exclusive_binder.shifted_out(1)); - } else { - // otherwise, this binder captures nothing - } + } // otherwise, this binder captures nothing } fn add_sty(&mut self, st: &ty::TyKind<'_>) { diff --git a/src/librustc/ty/inhabitedness/def_id_forest.rs b/src/librustc/ty/inhabitedness/def_id_forest.rs index c152c0fb8e94..9c12d736a30e 100644 --- a/src/librustc/ty/inhabitedness/def_id_forest.rs +++ b/src/librustc/ty/inhabitedness/def_id_forest.rs @@ -66,12 +66,7 @@ impl<'a, 'gcx, 'tcx> DefIdForest { tcx: TyCtxt<'a, 'gcx, 'tcx>, id: DefId) -> bool { - for root_id in self.root_ids.iter() { - if tcx.is_descendant_of(id, *root_id) { - return true; - } - } - false + self.root_ids.iter().any(|root_id| tcx.is_descendant_of(id, *root_id)) } /// Calculate the intersection of a collection of forests. diff --git a/src/librustc/ty/query/on_disk_cache.rs b/src/librustc/ty/query/on_disk_cache.rs index 7d3ce7307dc8..66e38fb218a9 100644 --- a/src/librustc/ty/query/on_disk_cache.rs +++ b/src/librustc/ty/query/on_disk_cache.rs @@ -441,7 +441,6 @@ impl<'sess> OnDiskCache<'sess> { tcx.dep_graph.with_ignore(|| { let current_cnums = tcx.all_crate_nums(LOCAL_CRATE).iter().map(|&cnum| { let crate_name = tcx.original_crate_name(cnum) - .as_str() .to_string(); let crate_disambiguator = tcx.crate_disambiguator(cnum); ((crate_name, crate_disambiguator), cnum) diff --git a/src/librustc/ty/query/plumbing.rs b/src/librustc/ty/query/plumbing.rs index 50eae945a8c4..15e692fd984a 100644 --- a/src/librustc/ty/query/plumbing.rs +++ b/src/librustc/ty/query/plumbing.rs @@ -753,9 +753,8 @@ macro_rules! define_queries_inner { } // The def_span query is used to calculate default_span, // so exit to avoid infinite recursion - match *self { - Query::def_span(..) => return span, - _ => () + if let Query::def_span(..) = *self { + return span } match *self { $(Query::$name(key) => key.default_span(tcx),)* @@ -1028,13 +1027,10 @@ pub fn force_from_dep_node<'a, 'gcx, 'lcx>(tcx: TyCtxt<'a, 'gcx, 'lcx>, ) ); - match tcx.force_query::<::ty::query::queries::$query<'_>>( + if let Err(e) = tcx.force_query::<::ty::query::queries::$query<'_>>( $key, DUMMY_SP, *dep_node ) { - Ok(_) => {}, - Err(e) => { - tcx.report_cycle(e).emit(); - } + tcx.report_cycle(e).emit(); } } } From e153103c380c8ac88aea1ab0a200facf1e94aa1a Mon Sep 17 00:00:00 2001 From: ljedrz Date: Mon, 1 Oct 2018 15:39:17 +0200 Subject: [PATCH 16/27] rustc/ty: improve allocations --- .../ty/inhabitedness/def_id_forest.rs | 12 ++----- src/librustc/ty/query/job.rs | 6 ++-- src/librustc/ty/query/on_disk_cache.rs | 31 +++++++++---------- src/librustc/ty/query/plumbing.rs | 21 ++++++++----- 4 files changed, 32 insertions(+), 38 deletions(-) diff --git a/src/librustc/ty/inhabitedness/def_id_forest.rs b/src/librustc/ty/inhabitedness/def_id_forest.rs index 9c12d736a30e..7bc77e1b1a14 100644 --- a/src/librustc/ty/inhabitedness/def_id_forest.rs +++ b/src/librustc/ty/inhabitedness/def_id_forest.rs @@ -87,11 +87,7 @@ impl<'a, 'gcx, 'tcx> DefIdForest { } ret.root_ids.extend(old_ret.drain()); - for id in next_forest.root_ids { - if ret.contains(tcx, id) { - next_ret.push(id); - } - } + next_ret.extend(next_forest.root_ids.into_iter().filter(|&id| ret.contains(tcx, id))); mem::swap(&mut next_ret, &mut ret.root_ids); next_ret.drain(); @@ -107,11 +103,7 @@ impl<'a, 'gcx, 'tcx> DefIdForest { let mut ret = DefIdForest::empty(); let mut next_ret = SmallVec::new(); for next_forest in iter { - for id in ret.root_ids.drain() { - if !next_forest.contains(tcx, id) { - next_ret.push(id); - } - } + next_ret.extend(ret.root_ids.drain().filter(|&id| !next_forest.contains(tcx, id))); for id in next_forest.root_ids { if !next_ret.contains(&id) { diff --git a/src/librustc/ty/query/job.rs b/src/librustc/ty/query/job.rs index d07891fca12a..a1dc4f16ce99 100644 --- a/src/librustc/ty/query/job.rs +++ b/src/librustc/ty/query/job.rs @@ -388,7 +388,7 @@ fn remove_cycle<'tcx>( // Find the queries in the cycle which are // connected to queries outside the cycle - let entry_points: Vec>> = stack.iter().filter_map(|query| { + let entry_points = stack.iter().filter_map(|query| { // Mark all the other queries in the cycle as already visited let mut visited = FxHashSet::from_iter(stack.iter().filter_map(|q| { if q.1.as_ptr() != query.1.as_ptr() { @@ -403,12 +403,12 @@ fn remove_cycle<'tcx>( } else { None } - }).collect(); + }); // Deterministically pick an entry point // FIXME: Sort this instead let mut hcx = tcx.create_stable_hashing_context(); - let entry_point = entry_points.iter().min_by_key(|q| { + let entry_point = entry_points.min_by_key(|q| { let mut stable_hasher = StableHasher::::new(); q.info.query.hash_stable(&mut hcx, &mut stable_hasher); stable_hasher.finish() diff --git a/src/librustc/ty/query/on_disk_cache.rs b/src/librustc/ty/query/on_disk_cache.rs index 66e38fb218a9..ce580c780335 100644 --- a/src/librustc/ty/query/on_disk_cache.rs +++ b/src/librustc/ty/query/on_disk_cache.rs @@ -254,23 +254,19 @@ impl<'sess> OnDiskCache<'sess> { })?; // Encode diagnostics - let diagnostics_index = { - let mut diagnostics_index = EncodedDiagnosticsIndex::new(); - - for (dep_node_index, diagnostics) in self.current_diagnostics - .borrow() - .iter() { - let pos = AbsoluteBytePos::new(encoder.position()); - // Let's make sure we get the expected type here: - let diagnostics: &EncodedDiagnostics = diagnostics; - let dep_node_index = - SerializedDepNodeIndex::new(dep_node_index.index()); - encoder.encode_tagged(dep_node_index, diagnostics)?; - diagnostics_index.push((dep_node_index, pos)); - } - - diagnostics_index - }; + let diagnostics_index: EncodedDiagnosticsIndex = self.current_diagnostics.borrow() + .iter() + .map(|(dep_node_index, diagnostics)| + { + let pos = AbsoluteBytePos::new(encoder.position()); + // Let's make sure we get the expected type here: + let diagnostics: &EncodedDiagnostics = diagnostics; + let dep_node_index = SerializedDepNodeIndex::new(dep_node_index.index()); + encoder.encode_tagged(dep_node_index, diagnostics)?; + + Ok((dep_node_index, pos)) + }) + .collect::>()?; let interpret_alloc_index = { let mut interpret_alloc_index = Vec::new(); @@ -282,6 +278,7 @@ impl<'sess> OnDiskCache<'sess> { // otherwise, abort break; } + interpret_alloc_index.reserve(new_n); for idx in n..new_n { let id = encoder.interpret_allocs_inverse[idx]; let pos = encoder.position() as u32; diff --git a/src/librustc/ty/query/plumbing.rs b/src/librustc/ty/query/plumbing.rs index 15e692fd984a..39a59cf090ea 100644 --- a/src/librustc/ty/query/plumbing.rs +++ b/src/librustc/ty/query/plumbing.rs @@ -709,14 +709,19 @@ macro_rules! define_queries_inner { // We use try_lock here since we are only called from the // deadlock handler, and this shouldn't be locked - $(for v in self.$name.try_lock().unwrap().active.values() { - match *v { - QueryResult::Started(ref job) => jobs.push(job.clone()), - _ => (), - } - })* - - return jobs; + $( + jobs.extend( + self.$name.try_lock().unwrap().active.values().filter_map(|v| + if let QueryResult::Started(ref job) = *v { + Some(job.clone()) + } else { + None + } + ) + ); + )* + + jobs } } From 0ee6b54c2471a68b838bde42bfe48f1e91df1633 Mon Sep 17 00:00:00 2001 From: ljedrz Date: Mon, 1 Oct 2018 15:44:23 +0200 Subject: [PATCH 17/27] rustc/ty: move a faster early return up --- src/librustc/ty/query/job.rs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/librustc/ty/query/job.rs b/src/librustc/ty/query/job.rs index a1dc4f16ce99..321f2a66799c 100644 --- a/src/librustc/ty/query/job.rs +++ b/src/librustc/ty/query/job.rs @@ -324,16 +324,16 @@ fn connected_to_root<'tcx>( query: Lrc>, visited: &mut FxHashSet<*const QueryJob<'tcx>> ) -> bool { - // We already visited this or we're deliberately ignoring it - if visited.contains(&query.as_ptr()) { - return false; - } - // This query is connected to the root (it has no query parent), return true if query.parent.is_none() { return true; } + // We already visited this or we're deliberately ignoring it + if visited.contains(&query.as_ptr()) { + return false; + } + visited.insert(query.as_ptr()); let mut connected = false; From 7ad21a88e6e5016af53ec3b277c32dac65cc8c66 Mon Sep 17 00:00:00 2001 From: ljedrz Date: Mon, 1 Oct 2018 15:47:47 +0200 Subject: [PATCH 18/27] rustc/ty: improve stack shifting and remove related allocations --- src/librustc/ty/query/job.rs | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/src/librustc/ty/query/job.rs b/src/librustc/ty/query/job.rs index 321f2a66799c..d588bc8c0cb5 100644 --- a/src/librustc/ty/query/job.rs +++ b/src/librustc/ty/query/job.rs @@ -123,9 +123,11 @@ impl<'tcx> QueryJob<'tcx> { let mut cycle = Vec::new(); while let Some(job) = current_job { - cycle.insert(0, job.info.clone()); + cycle.push(job.info.clone()); if ptr::eq(&*job, self) { + cycle.reverse(); + // This is the end of the cycle // The span entry we included was for the usage // of the cycle itself, and not part of the cycle @@ -368,13 +370,11 @@ fn remove_cycle<'tcx>( // Reverse the stack so earlier entries require later entries stack.reverse(); - // Extract the spans and queries into separate arrays - let mut spans: Vec<_> = stack.iter().map(|e| e.0).collect(); - let queries = stack.into_iter().map(|e| e.1); + // The stack is a vector of pairs of spans and queries + let (mut spans, queries): (Vec<_>, Vec<_>) = stack.into_iter().unzip(); // Shift the spans so that queries are matched with the span for their waitee - let last = spans.pop().unwrap(); - spans.insert(0, last); + spans.rotate_right(1); // Zip them back together let mut stack: Vec<_> = spans.into_iter().zip(queries).collect(); @@ -414,10 +414,10 @@ fn remove_cycle<'tcx>( stable_hasher.finish() }).unwrap().as_ptr(); - // Shift the stack until our entry point is first - while stack[0].1.as_ptr() != entry_point { - let last = stack.pop().unwrap(); - stack.insert(0, last); + // Shift the stack so that our entry point is first + let entry_point_pos = stack.iter().position(|(_, query)| query.as_ptr() == entry_point); + if let Some(pos) = entry_point_pos { + stack.rotate_right(pos); } // Create the cycle error From 819cbfeb964337af70f48b33cf6ac5bf05aa0d80 Mon Sep 17 00:00:00 2001 From: Takanori Ishibashi Date: Fri, 5 Oct 2018 18:47:37 +0900 Subject: [PATCH 19/27] contast -> contrast --- src/libsyntax/parse/parser.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index 716faaa4e397..3a533fc381a9 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -3800,7 +3800,7 @@ impl<'a> Parser<'a> { } /// A wrapper around `parse_pat` with some special error handling for the - /// "top-level" patterns in a match arm, `for` loop, `let`, &c. (in contast + /// "top-level" patterns in a match arm, `for` loop, `let`, &c. (in contrast /// to subpatterns within such). pub fn parse_top_level_pat(&mut self) -> PResult<'a, P> { let pat = self.parse_pat()?; From 9da428dad8eefa8a821214bc0fe0d4159ba4efed Mon Sep 17 00:00:00 2001 From: Austin Bonander Date: Wed, 3 Oct 2018 14:24:31 -0700 Subject: [PATCH 20/27] make `Parser::parse_foreign_item()` return a foreign item or error closes #54441 --- src/libsyntax/ext/expand.rs | 4 +--- src/libsyntax/parse/parser.rs | 23 ++++++++++----------- src/test/parse-fail/duplicate-visibility.rs | 2 +- src/test/ui/macros/issue-54441.rs | 13 ++++++++++++ src/test/ui/macros/issue-54441.stderr | 14 +++++++++++++ 5 files changed, 40 insertions(+), 16 deletions(-) create mode 100644 src/test/ui/macros/issue-54441.rs create mode 100644 src/test/ui/macros/issue-54441.stderr diff --git a/src/libsyntax/ext/expand.rs b/src/libsyntax/ext/expand.rs index 52322e98d46f..ba70108ea471 100644 --- a/src/libsyntax/ext/expand.rs +++ b/src/libsyntax/ext/expand.rs @@ -1008,9 +1008,7 @@ impl<'a> Parser<'a> { AstFragmentKind::ForeignItems => { let mut items = SmallVec::new(); while self.token != token::Eof { - if let Some(item) = self.parse_foreign_item()? { - items.push(item); - } + items.push(self.parse_foreign_item()?); } AstFragment::ForeignItems(items) } diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index 5571a18b5962..d75a3f3fe9bd 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -6718,10 +6718,9 @@ impl<'a> Parser<'a> { attrs.extend(self.parse_inner_attributes()?); let mut foreign_items = vec![]; - while let Some(item) = self.parse_foreign_item()? { - foreign_items.push(item); + while !self.eat(&token::CloseDelim(token::Brace)) { + foreign_items.push(self.parse_foreign_item()?); } - self.expect(&token::CloseDelim(token::Brace))?; let prev_span = self.prev_span; let m = ast::ForeignMod { @@ -7305,8 +7304,8 @@ impl<'a> Parser<'a> { } /// Parse a foreign item. - crate fn parse_foreign_item(&mut self) -> PResult<'a, Option> { - maybe_whole!(self, NtForeignItem, |ni| Some(ni)); + crate fn parse_foreign_item(&mut self) -> PResult<'a, ForeignItem> { + maybe_whole!(self, NtForeignItem, |ni| ni); let attrs = self.parse_outer_attributes()?; let lo = self.span; @@ -7326,20 +7325,20 @@ impl<'a> Parser<'a> { ).emit(); } self.bump(); // `static` or `const` - return Ok(Some(self.parse_item_foreign_static(visibility, lo, attrs)?)); + return Ok(self.parse_item_foreign_static(visibility, lo, attrs)?); } // FOREIGN FUNCTION ITEM if self.check_keyword(keywords::Fn) { - return Ok(Some(self.parse_item_foreign_fn(visibility, lo, attrs)?)); + return Ok(self.parse_item_foreign_fn(visibility, lo, attrs)?); } // FOREIGN TYPE ITEM if self.check_keyword(keywords::Type) { - return Ok(Some(self.parse_item_foreign_type(visibility, lo, attrs)?)); + return Ok(self.parse_item_foreign_type(visibility, lo, attrs)?); } match self.parse_assoc_macro_invoc("extern", Some(&visibility), &mut false)? { Some(mac) => { - Ok(Some( + Ok( ForeignItem { ident: keywords::Invalid.ident(), span: lo.to(self.prev_span), @@ -7348,14 +7347,14 @@ impl<'a> Parser<'a> { vis: visibility, node: ForeignItemKind::Macro(mac), } - )) + ) } None => { - if !attrs.is_empty() { + if !attrs.is_empty() { self.expected_item_err(&attrs); } - Ok(None) + self.unexpected() } } } diff --git a/src/test/parse-fail/duplicate-visibility.rs b/src/test/parse-fail/duplicate-visibility.rs index 6899caa7153b..cc3286fe7051 100644 --- a/src/test/parse-fail/duplicate-visibility.rs +++ b/src/test/parse-fail/duplicate-visibility.rs @@ -10,7 +10,7 @@ // compile-flags: -Z parse-only -// error-pattern:expected one of `(`, `fn`, `static`, `type`, or `}` here +// error-pattern:expected one of `(`, `fn`, `static`, or `type` extern { pub pub fn foo(); } diff --git a/src/test/ui/macros/issue-54441.rs b/src/test/ui/macros/issue-54441.rs new file mode 100644 index 000000000000..b45aedb549ec --- /dev/null +++ b/src/test/ui/macros/issue-54441.rs @@ -0,0 +1,13 @@ +#![feature(macros_in_extern)] + +macro_rules! m { + () => { + let //~ ERROR expected + }; +} + +extern "C" { + m!(); +} + +fn main() {} diff --git a/src/test/ui/macros/issue-54441.stderr b/src/test/ui/macros/issue-54441.stderr new file mode 100644 index 000000000000..aa1edb2cf893 --- /dev/null +++ b/src/test/ui/macros/issue-54441.stderr @@ -0,0 +1,14 @@ +error: expected one of `crate`, `fn`, `pub`, `static`, or `type`, found `let` + --> $DIR/issue-54441.rs:5:9 + | +LL | #![feature(macros_in_extern)] + | - expected one of `crate`, `fn`, `pub`, `static`, or `type` here +... +LL | let //~ ERROR expected + | ^^^ unexpected token +... +LL | m!(); + | ----- in this macro invocation + +error: aborting due to previous error + From f5db4114102861acd004c8104dde7372010b156e Mon Sep 17 00:00:00 2001 From: Andy Russell Date: Wed, 3 Oct 2018 22:21:05 -0400 Subject: [PATCH 21/27] add suggestion for inverted function parameters Fixes #54065. --- src/libsyntax/parse/parser.rs | 21 ++++++++- src/test/ui/parser/inverted-parameters.rs | 39 +++++++++++++++ src/test/ui/parser/inverted-parameters.stderr | 47 +++++++++++++++++++ 3 files changed, 106 insertions(+), 1 deletion(-) create mode 100644 src/test/ui/parser/inverted-parameters.rs create mode 100644 src/test/ui/parser/inverted-parameters.stderr diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index 5571a18b5962..1825ee6eab88 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -1777,7 +1777,26 @@ impl<'a> Parser<'a> { require_name); let pat = self.parse_pat()?; - self.expect(&token::Colon)?; + if let Err(mut err) = self.expect(&token::Colon) { + // If we find a pattern followed by an identifier, it could be an (incorrect) + // C-style parameter declaration. + if self.check_ident() && self.look_ahead(1, |t| { + *t == token::Comma || *t == token::CloseDelim(token::Paren) + }) { + let ident = self.parse_ident().unwrap(); + let span = pat.span.with_hi(ident.span.hi()); + + err.span_suggestion_with_applicability( + span, + "declare the type after the parameter binding", + String::from(": "), + Applicability::HasPlaceholders, + ); + } + + return Err(err); + } + (pat, self.parse_ty()?) } else { debug!("parse_arg_general ident_to_pat"); diff --git a/src/test/ui/parser/inverted-parameters.rs b/src/test/ui/parser/inverted-parameters.rs new file mode 100644 index 000000000000..a100debbf124 --- /dev/null +++ b/src/test/ui/parser/inverted-parameters.rs @@ -0,0 +1,39 @@ +// Copyright 2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +struct S; + +impl S { + fn foo(&self, &str bar) {} + //~^ ERROR expected one of `:` or `@` + //~| HELP declare the type after the parameter binding + //~| SUGGESTION : +} + +fn baz(S quux, xyzzy: i32) {} +//~^ ERROR expected one of `:` or `@` +//~| HELP declare the type after the parameter binding +//~| SUGGESTION : + +fn one(i32 a b) {} +//~^ ERROR expected one of `:` or `@` + +fn pattern((i32, i32) (a, b)) {} +//~^ ERROR expected `:` + +fn fizz(i32) {} +//~^ ERROR expected one of `:` or `@` + +fn missing_colon(quux S) {} +//~^ ERROR expected one of `:` or `@` +//~| HELP declare the type after the parameter binding +//~| SUGGESTION : + +fn main() {} diff --git a/src/test/ui/parser/inverted-parameters.stderr b/src/test/ui/parser/inverted-parameters.stderr new file mode 100644 index 000000000000..3f4f0615bc8f --- /dev/null +++ b/src/test/ui/parser/inverted-parameters.stderr @@ -0,0 +1,47 @@ +error: expected one of `:` or `@`, found `bar` + --> $DIR/inverted-parameters.rs:14:24 + | +LL | fn foo(&self, &str bar) {} + | -----^^^ + | | | + | | expected one of `:` or `@` here + | help: declare the type after the parameter binding: `: ` + +error: expected one of `:` or `@`, found `quux` + --> $DIR/inverted-parameters.rs:20:10 + | +LL | fn baz(S quux, xyzzy: i32) {} + | --^^^^ + | | | + | | expected one of `:` or `@` here + | help: declare the type after the parameter binding: `: ` + +error: expected one of `:` or `@`, found `a` + --> $DIR/inverted-parameters.rs:25:12 + | +LL | fn one(i32 a b) {} + | ^ expected one of `:` or `@` here + +error: expected `:`, found `(` + --> $DIR/inverted-parameters.rs:28:23 + | +LL | fn pattern((i32, i32) (a, b)) {} + | ^ expected `:` + +error: expected one of `:` or `@`, found `)` + --> $DIR/inverted-parameters.rs:31:12 + | +LL | fn fizz(i32) {} + | ^ expected one of `:` or `@` here + +error: expected one of `:` or `@`, found `S` + --> $DIR/inverted-parameters.rs:34:23 + | +LL | fn missing_colon(quux S) {} + | -----^ + | | | + | | expected one of `:` or `@` here + | help: declare the type after the parameter binding: `: ` + +error: aborting due to 6 previous errors + From 8d81c03b65be85351ec5faefec657d7ea6304bb5 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Fri, 5 Oct 2018 09:15:39 -0700 Subject: [PATCH 22/27] Revert "Add another assert" This reverts commit 21d2a6c9868541ec9829ced9a5bae936b18741c5. --- src/liballoc/collections/vec_deque.rs | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/liballoc/collections/vec_deque.rs b/src/liballoc/collections/vec_deque.rs index c53549ab85d6..7b6693268ae3 100644 --- a/src/liballoc/collections/vec_deque.rs +++ b/src/liballoc/collections/vec_deque.rs @@ -19,7 +19,6 @@ use core::cmp::Ordering; use core::fmt; -use core::isize; use core::iter::{repeat, FromIterator, FusedIterator}; use core::mem; use core::ops::Bound::{Excluded, Included, Unbounded}; @@ -211,9 +210,6 @@ impl VecDeque { /// If so, this function never panics. #[inline] unsafe fn copy_slice(&mut self, src: &[T]) { - /// This is guaranteed by `RawVec`. - debug_assert!(self.capacity() <= isize::MAX as usize); - let expected_new_len = self.len() + src.len(); debug_assert!(self.capacity() >= expected_new_len); From 54441484d13998eef3354780c86e97342776483d Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Fri, 5 Oct 2018 09:15:44 -0700 Subject: [PATCH 23/27] Revert "Fix tidy" This reverts commit 1908892d3f60008f265dfc25ac46db387c0ad6a0. --- src/liballoc/collections/vec_deque.rs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/liballoc/collections/vec_deque.rs b/src/liballoc/collections/vec_deque.rs index 7b6693268ae3..1bd1861db0b2 100644 --- a/src/liballoc/collections/vec_deque.rs +++ b/src/liballoc/collections/vec_deque.rs @@ -1870,8 +1870,7 @@ impl VecDeque { self.copy_slice(src_high); } - // Some values now exist in both `other` and `self` but are made inaccessible - // in`other`. + // Some values now exist in both `other` and `self` but are made inaccessible in `other`. other.tail = other.head; } } From 9a41cfabba83125b212800aa62ebda0c3691ba93 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Fri, 5 Oct 2018 09:15:48 -0700 Subject: [PATCH 24/27] Revert "Add docs and debug asserts" This reverts commit 1a1a7f6167edf18b8a0ab488e651f7748cc2e9d3. --- src/liballoc/collections/vec_deque.rs | 34 +++++++++------------------ 1 file changed, 11 insertions(+), 23 deletions(-) diff --git a/src/liballoc/collections/vec_deque.rs b/src/liballoc/collections/vec_deque.rs index 1bd1861db0b2..7c16258e84ef 100644 --- a/src/liballoc/collections/vec_deque.rs +++ b/src/liballoc/collections/vec_deque.rs @@ -202,17 +202,10 @@ impl VecDeque { len); } - /// Copies all values from `src` to the back of `self`, wrapping around if needed. - /// - /// # Safety - /// - /// The capacity must be sufficient to hold self.len() + src.len() elements. - /// If so, this function never panics. + /// Copies all values from `src` to `self`, wrapping around if needed. + /// Assumes capacity is sufficient. #[inline] unsafe fn copy_slice(&mut self, src: &[T]) { - let expected_new_len = self.len() + src.len(); - debug_assert!(self.capacity() >= expected_new_len); - let dst_high_ptr = self.ptr().add(self.head); let dst_high_len = self.cap() - self.head; @@ -223,7 +216,6 @@ impl VecDeque { ptr::copy_nonoverlapping(src_low.as_ptr(), self.ptr(), src_low.len()); self.head = self.wrap_add(self.head, src.len()); - debug_assert!(self.len() == expected_new_len); } /// Copies a potentially wrapping block of memory len long from src to dest. @@ -1858,21 +1850,17 @@ impl VecDeque { #[inline] #[stable(feature = "append", since = "1.4.0")] pub fn append(&mut self, other: &mut Self) { - unsafe { - // Guarantees there is space in `self` for `other`. - self.reserve(other.len()); - - { - let (src_high, src_low) = other.as_slices(); + // Guarantees there is space in `self` for `other + self.reserve(other.len()); - // This is only safe because copy_slice never panics when capacity is sufficient. - self.copy_slice(src_low); - self.copy_slice(src_high); - } - - // Some values now exist in both `other` and `self` but are made inaccessible in `other`. - other.tail = other.head; + unsafe { + let (src_high, src_low) = other.as_slices(); + self.copy_slice(src_low); + self.copy_slice(src_high); } + + // Some values now exist in both `other` and `self` but are made inaccessible in `other`. + other.tail = other.head; } /// Retains only the elements specified by the predicate. From 90b946912128a08b9b5bd29fbdcc866c83890641 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Fri, 5 Oct 2018 09:15:52 -0700 Subject: [PATCH 25/27] Revert "Optimize VecDeque::append" This reverts commit 11e488b64fed181820280d494d4fcc157ee1adc5. --- src/liballoc/collections/vec_deque.rs | 29 ++------------------------- 1 file changed, 2 insertions(+), 27 deletions(-) diff --git a/src/liballoc/collections/vec_deque.rs b/src/liballoc/collections/vec_deque.rs index 7c16258e84ef..d49cb9857740 100644 --- a/src/liballoc/collections/vec_deque.rs +++ b/src/liballoc/collections/vec_deque.rs @@ -202,22 +202,6 @@ impl VecDeque { len); } - /// Copies all values from `src` to `self`, wrapping around if needed. - /// Assumes capacity is sufficient. - #[inline] - unsafe fn copy_slice(&mut self, src: &[T]) { - let dst_high_ptr = self.ptr().add(self.head); - let dst_high_len = self.cap() - self.head; - - let split = cmp::min(src.len(), dst_high_len); - let (src_high, src_low) = src.split_at(split); - - ptr::copy_nonoverlapping(src_high.as_ptr(), dst_high_ptr, src_high.len()); - ptr::copy_nonoverlapping(src_low.as_ptr(), self.ptr(), src_low.len()); - - self.head = self.wrap_add(self.head, src.len()); - } - /// Copies a potentially wrapping block of memory len long from src to dest. /// (abs(dst - src) + len) must be no larger than cap() (There must be at /// most one continuous overlapping region between src and dest). @@ -1850,17 +1834,8 @@ impl VecDeque { #[inline] #[stable(feature = "append", since = "1.4.0")] pub fn append(&mut self, other: &mut Self) { - // Guarantees there is space in `self` for `other - self.reserve(other.len()); - - unsafe { - let (src_high, src_low) = other.as_slices(); - self.copy_slice(src_low); - self.copy_slice(src_high); - } - - // Some values now exist in both `other` and `self` but are made inaccessible in `other`. - other.tail = other.head; + // naive impl + self.extend(other.drain(..)); } /// Retains only the elements specified by the predicate. From 70ae43fee798ea7af56db31b4e43180ef42a4476 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Fri, 5 Oct 2018 09:15:57 -0700 Subject: [PATCH 26/27] Revert "Slightly refactor VecDeque implementation" This reverts commit 6ce76acae455a32113116cd2f95f8076388fc2d3. --- src/liballoc/collections/vec_deque.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/liballoc/collections/vec_deque.rs b/src/liballoc/collections/vec_deque.rs index d49cb9857740..571f35a2031d 100644 --- a/src/liballoc/collections/vec_deque.rs +++ b/src/liballoc/collections/vec_deque.rs @@ -1024,7 +1024,7 @@ impl VecDeque { iter: Iter { tail: drain_tail, head: drain_head, - ring: unsafe { self.buffer_as_slice() }, + ring: unsafe { self.buffer_as_mut_slice() }, }, } } @@ -2593,8 +2593,8 @@ impl From> for Vec { let mut right_offset = 0; for i in left_edge..right_edge { right_offset = (i - left_edge) % (cap - right_edge); - let src = right_edge + right_offset; - ptr::swap(buf.add(i), buf.add(src)); + let src: isize = (right_edge + right_offset) as isize; + ptr::swap(buf.add(i), buf.offset(src)); } let n_ops = right_edge - left_edge; left_edge += n_ops; From c07b712d2c9cb4559a06cf390f0c447ece758718 Mon Sep 17 00:00:00 2001 From: David Wood Date: Fri, 5 Oct 2018 18:35:23 +0200 Subject: [PATCH 27/27] Simplify test. Removes unnecessary type mismatch error from test that was hiding borrow check error from NLL stderr. --- src/test/ui/issues/issue-13058.nll.stderr | 19 ++++++++----------- src/test/ui/issues/issue-13058.rs | 3 +-- src/test/ui/issues/issue-13058.stderr | 17 ++--------------- 3 files changed, 11 insertions(+), 28 deletions(-) diff --git a/src/test/ui/issues/issue-13058.nll.stderr b/src/test/ui/issues/issue-13058.nll.stderr index 33c0eefbfaa2..0d641ec8e891 100644 --- a/src/test/ui/issues/issue-13058.nll.stderr +++ b/src/test/ui/issues/issue-13058.nll.stderr @@ -1,15 +1,12 @@ -error[E0308]: mismatched types - --> $DIR/issue-13058.rs:36:11 +error[E0621]: explicit lifetime required in the type of `cont` + --> $DIR/issue-13058.rs:24:21 | -LL | check((3, 5)); - | ^^^^^^ - | | - | expected reference, found tuple - | help: consider borrowing here: `&(3, 5)` - | - = note: expected type `&_` - found type `({integer}, {integer})` +LL | fn check<'r, I: Iterator, T: Itble<'r, usize, I>>(cont: &T) -> bool + | -- help: add explicit lifetime `'r` to the type of `cont`: `&'r T` +LL | { +LL | let cont_iter = cont.iter(); + | ^^^^^^^^^^^ lifetime `'r` required error: aborting due to previous error -For more information about this error, try `rustc --explain E0308`. +For more information about this error, try `rustc --explain E0621`. diff --git a/src/test/ui/issues/issue-13058.rs b/src/test/ui/issues/issue-13058.rs index dbcf9998ad93..cabf02194776 100644 --- a/src/test/ui/issues/issue-13058.rs +++ b/src/test/ui/issues/issue-13058.rs @@ -33,6 +33,5 @@ fn check<'r, I: Iterator, T: Itble<'r, usize, I>>(cont: &T) -> bool } fn main() { - check((3, 5)); -//~^ ERROR mismatched types + check(&(3, 5)); } diff --git a/src/test/ui/issues/issue-13058.stderr b/src/test/ui/issues/issue-13058.stderr index 5e8319d26ad3..ee39678736cd 100644 --- a/src/test/ui/issues/issue-13058.stderr +++ b/src/test/ui/issues/issue-13058.stderr @@ -7,19 +7,6 @@ LL | { LL | let cont_iter = cont.iter(); | ^^^^ lifetime `'r` required -error[E0308]: mismatched types - --> $DIR/issue-13058.rs:36:11 - | -LL | check((3, 5)); - | ^^^^^^ - | | - | expected reference, found tuple - | help: consider borrowing here: `&(3, 5)` - | - = note: expected type `&_` - found type `({integer}, {integer})` - -error: aborting due to 2 previous errors +error: aborting due to previous error -Some errors occurred: E0308, E0621. -For more information about an error, try `rustc --explain E0308`. +For more information about this error, try `rustc --explain E0621`.