From 1798d51da67835618079f034d0b552be342af5d2 Mon Sep 17 00:00:00 2001 From: Corey Farwell Date: Sun, 25 Nov 2018 11:35:38 -0500 Subject: [PATCH 01/17] Add grammar for {f32,f64}::from_str, mention known bug. - Original bug about documenting grammar - https://github.com/rust-lang/rust/issues/32243 - Known bug with parsing - https://github.com/rust-lang/rust/issues/31407 --- src/libcore/num/dec2flt/mod.rs | 26 +++++++++++++++++++++++++- 1 file changed, 25 insertions(+), 1 deletion(-) diff --git a/src/libcore/num/dec2flt/mod.rs b/src/libcore/num/dec2flt/mod.rs index f93564c2849f5..64ac69946d10d 100644 --- a/src/libcore/num/dec2flt/mod.rs +++ b/src/libcore/num/dec2flt/mod.rs @@ -122,11 +122,35 @@ macro_rules! from_str_float_impl { /// * '2.5E10', or equivalently, '2.5e10' /// * '2.5E-10' /// * '5.' - /// * '.5', or, equivalently, '0.5' + /// * '.5', or, equivalently, '0.5' /// * 'inf', '-inf', 'NaN' /// /// Leading and trailing whitespace represent an error. /// + /// # Grammar + /// + /// All strings that adhere to the following regular expression + /// will result in an [`Ok`] being returned: + /// + /// ```txt + /// (\+|-)? + /// (inf| + /// NaN| + /// ([0-9]+| + /// [0-9]+\.[0-9]*| + /// [0-9]*\.[0-9]+) + /// ((e|E) + /// (\+|-)? + /// [0-9]+)?) + /// ``` + /// + /// # Known bugs + /// + /// * [#31407]: Some strings that adhere to the regular expression + /// above will incorrectly return an [`Err`]. + /// + /// [#31407]: https://github.com/rust-lang/rust/issues/31407 + /// /// # Arguments /// /// * src - A string From 694b18d973e3c45d0dcc0221813fd0daefaf367f Mon Sep 17 00:00:00 2001 From: Corey Farwell Date: Mon, 3 Dec 2018 12:28:56 -0800 Subject: [PATCH 02/17] tweak 'known issues' wording --- src/libcore/num/dec2flt/mod.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/libcore/num/dec2flt/mod.rs b/src/libcore/num/dec2flt/mod.rs index 64ac69946d10d..759c2e8c953e0 100644 --- a/src/libcore/num/dec2flt/mod.rs +++ b/src/libcore/num/dec2flt/mod.rs @@ -146,8 +146,8 @@ macro_rules! from_str_float_impl { /// /// # Known bugs /// - /// * [#31407]: Some strings that adhere to the regular expression - /// above will incorrectly return an [`Err`]. + /// In some situations, some strings that should create a valid float + /// instead return an error. See [issue #31407] for details. /// /// [#31407]: https://github.com/rust-lang/rust/issues/31407 /// From 15f79d890522028e88a60992b76c0fce26024a8f Mon Sep 17 00:00:00 2001 From: Corey Farwell Date: Mon, 3 Dec 2018 12:29:28 -0800 Subject: [PATCH 03/17] ...and fix a link --- src/libcore/num/dec2flt/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libcore/num/dec2flt/mod.rs b/src/libcore/num/dec2flt/mod.rs index 759c2e8c953e0..1926d84d0439f 100644 --- a/src/libcore/num/dec2flt/mod.rs +++ b/src/libcore/num/dec2flt/mod.rs @@ -149,7 +149,7 @@ macro_rules! from_str_float_impl { /// In some situations, some strings that should create a valid float /// instead return an error. See [issue #31407] for details. /// - /// [#31407]: https://github.com/rust-lang/rust/issues/31407 + /// [issue #31407]: https://github.com/rust-lang/rust/issues/31407 /// /// # Arguments /// From 1027dc16b941e04611213c7b7e2a6e9de523868a Mon Sep 17 00:00:00 2001 From: Corey Farwell Date: Sat, 22 Dec 2018 09:34:22 -0500 Subject: [PATCH 04/17] Update regex to EBNF --- src/libcore/num/dec2flt/mod.rs | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) diff --git a/src/libcore/num/dec2flt/mod.rs b/src/libcore/num/dec2flt/mod.rs index 1926d84d0439f..804e5f5e52158 100644 --- a/src/libcore/num/dec2flt/mod.rs +++ b/src/libcore/num/dec2flt/mod.rs @@ -129,19 +129,17 @@ macro_rules! from_str_float_impl { /// /// # Grammar /// - /// All strings that adhere to the following regular expression + /// All strings that adhere to the following EBNF grammar /// will result in an [`Ok`] being returned: /// /// ```txt - /// (\+|-)? - /// (inf| - /// NaN| - /// ([0-9]+| - /// [0-9]+\.[0-9]*| - /// [0-9]*\.[0-9]+) - /// ((e|E) - /// (\+|-)? - /// [0-9]+)?) + /// Float ::= Sign? ( 'inf' | 'NaN' | Number ) + /// Number ::= ( Digit+ | + /// Digit+ '.' Digit* | + /// Digit* '.' Digit+ ) Exp? + /// Exp ::= [eE] Sign? Digit+ + /// Sign ::= [+-] + /// Digit ::= [0-9] /// ``` /// /// # Known bugs From 55be692eb8c2facf78892cdafbb898c375be0b94 Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Sat, 22 Dec 2018 09:43:47 -0500 Subject: [PATCH 05/17] Update src/libcore/num/dec2flt/mod.rs Co-Authored-By: frewsxcv --- src/libcore/num/dec2flt/mod.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/libcore/num/dec2flt/mod.rs b/src/libcore/num/dec2flt/mod.rs index 804e5f5e52158..8bde41fefd5b1 100644 --- a/src/libcore/num/dec2flt/mod.rs +++ b/src/libcore/num/dec2flt/mod.rs @@ -129,7 +129,9 @@ macro_rules! from_str_float_impl { /// /// # Grammar /// - /// All strings that adhere to the following EBNF grammar + /// [EBNF]: https://www.w3.org/TR/REC-xml/#sec-notation + /// + /// All strings that adhere to the following [EBNF] grammar /// will result in an [`Ok`] being returned: /// /// ```txt From a6294b762859b3bb86b2a94c6857ae39beea9aeb Mon Sep 17 00:00:00 2001 From: mark Date: Tue, 15 Jan 2019 19:38:02 -0600 Subject: [PATCH 06/17] update/remove some old readmes --- .../infer/lexical_region_resolve/README.md | 4 + .../infer/region_constraints/README.md | 76 +---------------- .../obligation_forest/README.md | 81 ------------------ .../obligation_forest/mod.rs | 85 +++++++++++++++++-- 4 files changed, 85 insertions(+), 161 deletions(-) delete mode 100644 src/librustc_data_structures/obligation_forest/README.md diff --git a/src/librustc/infer/lexical_region_resolve/README.md b/src/librustc/infer/lexical_region_resolve/README.md index 4483e522f3a1f..56320636a6743 100644 --- a/src/librustc/infer/lexical_region_resolve/README.md +++ b/src/librustc/infer/lexical_region_resolve/README.md @@ -2,8 +2,12 @@ > WARNING: This README is obsolete and will be removed soon! For > more info on how the current borrowck works, see the [rustc guide]. +> +> As of edition 2018, region inference is done using Non-lexical lifetimes, +> which is described in the guide and [this RFC]. [rustc guide]: https://rust-lang.github.io/rustc-guide/mir/borrowck.html +[this RFC]: https://github.com/rust-lang/rfcs/blob/master/text/2094-nll.md ## Terminology diff --git a/src/librustc/infer/region_constraints/README.md b/src/librustc/infer/region_constraints/README.md index 775bbf955b830..ea7fffe9dc1c6 100644 --- a/src/librustc/infer/region_constraints/README.md +++ b/src/librustc/infer/region_constraints/README.md @@ -1,77 +1,3 @@ -# Region constraint collection - -> WARNING: This README is obsolete and will be removed soon! For -> more info on how the current borrowck works, see the [rustc guide]. +For info on how the current borrowck works, see the [rustc guide]. [rustc guide]: https://rust-lang.github.io/rustc-guide/mir/borrowck.html - -## Terminology - -Note that we use the terms region and lifetime interchangeably. - -## Introduction - -As described in the rustc guide [chapter on type inference][ti], and unlike -normal type inference, which is similar in spirit to H-M and thus -works progressively, the region type inference works by accumulating -constraints over the course of a function. Finally, at the end of -processing a function, we process and solve the constraints all at -once. - -[ti]: https://rust-lang.github.io/rustc-guide/type-inference.html - -The constraints are always of one of three possible forms: - -- `ConstrainVarSubVar(Ri, Rj)` states that region variable Ri must be - a subregion of Rj -- `ConstrainRegSubVar(R, Ri)` states that the concrete region R (which - must not be a variable) must be a subregion of the variable Ri -- `ConstrainVarSubReg(Ri, R)` states the variable Ri should be less - than the concrete region R. This is kind of deprecated and ought to - be replaced with a verify (they essentially play the same role). - -In addition to constraints, we also gather up a set of "verifys" -(what, you don't think Verify is a noun? Get used to it my -friend!). These represent relations that must hold but which don't -influence inference proper. These take the form of: - -- `VerifyRegSubReg(Ri, Rj)` indicates that Ri <= Rj must hold, - where Rj is not an inference variable (and Ri may or may not contain - one). This doesn't influence inference because we will already have - inferred Ri to be as small as possible, so then we just test whether - that result was less than Rj or not. -- `VerifyGenericBound(R, Vb)` is a more complex expression which tests - that the region R must satisfy the bound `Vb`. The bounds themselves - may have structure like "must outlive one of the following regions" - or "must outlive ALL of the following regions. These bounds arise - from constraints like `T: 'a` -- if we know that `T: 'b` and `T: 'c` - (say, from where clauses), then we can conclude that `T: 'a` if `'b: - 'a` *or* `'c: 'a`. - -## Building up the constraints - -Variables and constraints are created using the following methods: - -- `new_region_var()` creates a new, unconstrained region variable; -- `make_subregion(Ri, Rj)` states that Ri is a subregion of Rj -- `lub_regions(Ri, Rj) -> Rk` returns a region Rk which is - the smallest region that is greater than both Ri and Rj -- `glb_regions(Ri, Rj) -> Rk` returns a region Rk which is - the greatest region that is smaller than both Ri and Rj - -The actual region resolution algorithm is not entirely -obvious, though it is also not overly complex. - -## Snapshotting - -It is also permitted to try (and rollback) changes to the graph. This -is done by invoking `start_snapshot()`, which returns a value. Then -later you can call `rollback_to()` which undoes the work. -Alternatively, you can call `commit()` which ends all snapshots. -Snapshots can be recursive---so you can start a snapshot when another -is in progress, but only the root snapshot can "commit". - -## Skolemization - -For a discussion on skolemization and higher-ranked subtyping, please -see the module `middle::infer::higher_ranked::doc`. diff --git a/src/librustc_data_structures/obligation_forest/README.md b/src/librustc_data_structures/obligation_forest/README.md deleted file mode 100644 index 982a2bacce164..0000000000000 --- a/src/librustc_data_structures/obligation_forest/README.md +++ /dev/null @@ -1,81 +0,0 @@ -The `ObligationForest` is a utility data structure used in trait -matching to track the set of outstanding obligations (those not yet -resolved to success or error). It also tracks the "backtrace" of each -pending obligation (why we are trying to figure this out in the first -place). - -### External view - -`ObligationForest` supports two main public operations (there are a -few others not discussed here): - -1. Add a new root obligations (`push_tree`). -2. Process the pending obligations (`process_obligations`). - -When a new obligation `N` is added, it becomes the root of an -obligation tree. This tree can also carry some per-tree state `T`, -which is given at the same time. This tree is a singleton to start, so -`N` is both the root and the only leaf. Each time the -`process_obligations` method is called, it will invoke its callback -with every pending obligation (so that will include `N`, the first -time). The callback also receives a (mutable) reference to the -per-tree state `T`. The callback should process the obligation `O` -that it is given and return one of three results: - -- `Ok(None)` -> ambiguous result. Obligation was neither a success - nor a failure. It is assumed that further attempts to process the - obligation will yield the same result unless something in the - surrounding environment changes. -- `Ok(Some(C))` - the obligation was *shallowly successful*. The - vector `C` is a list of subobligations. The meaning of this is that - `O` was successful on the assumption that all the obligations in `C` - are also successful. Therefore, `O` is only considered a "true" - success if `C` is empty. Otherwise, `O` is put into a suspended - state and the obligations in `C` become the new pending - obligations. They will be processed the next time you call - `process_obligations`. -- `Err(E)` -> obligation failed with error `E`. We will collect this - error and return it from `process_obligations`, along with the - "backtrace" of obligations (that is, the list of obligations up to - and including the root of the failed obligation). No further - obligations from that same tree will be processed, since the tree is - now considered to be in error. - -When the call to `process_obligations` completes, you get back an `Outcome`, -which includes three bits of information: - -- `completed`: a list of obligations where processing was fully - completed without error (meaning that all transitive subobligations - have also been completed). So, for example, if the callback from - `process_obligations` returns `Ok(Some(C))` for some obligation `O`, - then `O` will be considered completed right away if `C` is the - empty vector. Otherwise it will only be considered completed once - all the obligations in `C` have been found completed. -- `errors`: a list of errors that occurred and associated backtraces - at the time of error, which can be used to give context to the user. -- `stalled`: if true, then none of the existing obligations were - *shallowly successful* (that is, no callback returned `Ok(Some(_))`). - This implies that all obligations were either errors or returned an - ambiguous result, which means that any further calls to - `process_obligations` would simply yield back further ambiguous - results. This is used by the `FulfillmentContext` to decide when it - has reached a steady state. - -#### Snapshots - -The `ObligationForest` supports a limited form of snapshots; see -`start_snapshot`; `commit_snapshot`; and `rollback_snapshot`. In -particular, you can use a snapshot to roll back new root -obligations. However, it is an error to attempt to -`process_obligations` during a snapshot. - -### Implementation details - -For the most part, comments specific to the implementation are in the -code. This file only contains a very high-level overview. Basically, -the forest is stored in a vector. Each element of the vector is a node -in some tree. Each node in the vector has the index of an (optional) -parent and (for convenience) its root (which may be itself). It also -has a current state, described by `NodeState`. After each -processing step, we compress the vector to remove completed and error -nodes, which aren't needed anymore. diff --git a/src/librustc_data_structures/obligation_forest/mod.rs b/src/librustc_data_structures/obligation_forest/mod.rs index 59497f0df18e9..9dd7d204f0373 100644 --- a/src/librustc_data_structures/obligation_forest/mod.rs +++ b/src/librustc_data_structures/obligation_forest/mod.rs @@ -1,9 +1,84 @@ //! The `ObligationForest` is a utility data structure used in trait -//! matching to track the set of outstanding obligations (those not -//! yet resolved to success or error). It also tracks the "backtrace" -//! of each pending obligation (why we are trying to figure this out -//! in the first place). See README.md for a general overview of how -//! to use this class. +//! matching to track the set of outstanding obligations (those not yet +//! resolved to success or error). It also tracks the "backtrace" of each +//! pending obligation (why we are trying to figure this out in the first +//! place). +//! +//! ### External view +//! +//! `ObligationForest` supports two main public operations (there are a +//! few others not discussed here): +//! +//! 1. Add a new root obligations (`push_tree`). +//! 2. Process the pending obligations (`process_obligations`). +//! +//! When a new obligation `N` is added, it becomes the root of an +//! obligation tree. This tree can also carry some per-tree state `T`, +//! which is given at the same time. This tree is a singleton to start, so +//! `N` is both the root and the only leaf. Each time the +//! `process_obligations` method is called, it will invoke its callback +//! with every pending obligation (so that will include `N`, the first +//! time). The callback also receives a (mutable) reference to the +//! per-tree state `T`. The callback should process the obligation `O` +//! that it is given and return one of three results: +//! +//! - `Ok(None)` -> ambiguous result. Obligation was neither a success +//! nor a failure. It is assumed that further attempts to process the +//! obligation will yield the same result unless something in the +//! surrounding environment changes. +//! - `Ok(Some(C))` - the obligation was *shallowly successful*. The +//! vector `C` is a list of subobligations. The meaning of this is that +//! `O` was successful on the assumption that all the obligations in `C` +//! are also successful. Therefore, `O` is only considered a "true" +//! success if `C` is empty. Otherwise, `O` is put into a suspended +//! state and the obligations in `C` become the new pending +//! obligations. They will be processed the next time you call +//! `process_obligations`. +//! - `Err(E)` -> obligation failed with error `E`. We will collect this +//! error and return it from `process_obligations`, along with the +//! "backtrace" of obligations (that is, the list of obligations up to +//! and including the root of the failed obligation). No further +//! obligations from that same tree will be processed, since the tree is +//! now considered to be in error. +//! +//! When the call to `process_obligations` completes, you get back an `Outcome`, +//! which includes three bits of information: +//! +//! - `completed`: a list of obligations where processing was fully +//! completed without error (meaning that all transitive subobligations +//! have also been completed). So, for example, if the callback from +//! `process_obligations` returns `Ok(Some(C))` for some obligation `O`, +//! then `O` will be considered completed right away if `C` is the +//! empty vector. Otherwise it will only be considered completed once +//! all the obligations in `C` have been found completed. +//! - `errors`: a list of errors that occurred and associated backtraces +//! at the time of error, which can be used to give context to the user. +//! - `stalled`: if true, then none of the existing obligations were +//! *shallowly successful* (that is, no callback returned `Ok(Some(_))`). +//! This implies that all obligations were either errors or returned an +//! ambiguous result, which means that any further calls to +//! `process_obligations` would simply yield back further ambiguous +//! results. This is used by the `FulfillmentContext` to decide when it +//! has reached a steady state. +//! +//! #### Snapshots +//! +//! The `ObligationForest` supports a limited form of snapshots; see +//! `start_snapshot`; `commit_snapshot`; and `rollback_snapshot`. In +//! particular, you can use a snapshot to roll back new root +//! obligations. However, it is an error to attempt to +//! `process_obligations` during a snapshot. +//! +//! ### Implementation details +//! +//! For the most part, comments specific to the implementation are in the +//! code. This file only contains a very high-level overview. Basically, +//! the forest is stored in a vector. Each element of the vector is a node +//! in some tree. Each node in the vector has the index of an (optional) +//! parent and (for convenience) its root (which may be itself). It also +//! has a current state, described by `NodeState`. After each +//! processing step, we compress the vector to remove completed and error +//! nodes, which aren't needed anymore. use fx::{FxHashMap, FxHashSet}; From 228969c696b380716ad7547e87c4b52f3df50c96 Mon Sep 17 00:00:00 2001 From: mark Date: Tue, 15 Jan 2019 19:48:37 -0600 Subject: [PATCH 07/17] remove link to removed readme --- src/README.md | 1 - 1 file changed, 1 deletion(-) diff --git a/src/README.md b/src/README.md index 65228915866ea..14e773286bc6a 100644 --- a/src/README.md +++ b/src/README.md @@ -8,7 +8,6 @@ For more information on how various parts of the compiler work, see the [rustc g There is also useful content in the following READMEs, which are gradually being moved over to the guide: - https://github.com/rust-lang/rust/tree/master/src/librustc/ty/query - https://github.com/rust-lang/rust/tree/master/src/librustc/dep_graph -- https://github.com/rust-lang/rust/blob/master/src/librustc/infer/region_constraints - https://github.com/rust-lang/rust/tree/master/src/librustc/infer/higher_ranked - https://github.com/rust-lang/rust/tree/master/src/librustc/infer/lexical_region_resolve From dcd56d11da6e1d7cb8874d27d1fbb4f6a94a71de Mon Sep 17 00:00:00 2001 From: mark Date: Fri, 18 Jan 2019 14:10:45 -0600 Subject: [PATCH 08/17] remove more old readmes --- src/librustc/infer/higher_ranked/README.md | 407 +-------------------- src/librustc/ty/query/README.md | 303 +-------------- 2 files changed, 8 insertions(+), 702 deletions(-) diff --git a/src/librustc/infer/higher_ranked/README.md b/src/librustc/infer/higher_ranked/README.md index b1ac8bae4fb98..e7afaa5beb0a7 100644 --- a/src/librustc/infer/higher_ranked/README.md +++ b/src/librustc/infer/higher_ranked/README.md @@ -1,403 +1,8 @@ -# Skolemization and functions +To learn more about how Higher-ranked trait bounds work in the _old_ trait +solver, see [this chapter][oldhrtb] of the rustc-guide. -One of the trickiest and most subtle aspects of regions is dealing -with higher-ranked things which include bound region variables, such -as function types. I strongly suggest that if you want to understand -the situation, you read this paper (which is, admittedly, very long, -but you don't have to read the whole thing): +To learn more about how they work in the _new_ trait solver, see [this +chapter][newhrtb]. -http://research.microsoft.com/en-us/um/people/simonpj/papers/higher-rank/ - -Although my explanation will never compete with SPJ's (for one thing, -his is approximately 100 pages), I will attempt to explain the basic -problem and also how we solve it. Note that the paper only discusses -subtyping, not the computation of LUB/GLB. - -The problem we are addressing is that there is a kind of subtyping -between functions with bound region parameters. Consider, for -example, whether the following relation holds: - - for<'a> fn(&'a isize) <: for<'b> fn(&'b isize)? (Yes, a => b) - -The answer is that of course it does. These two types are basically -the same, except that in one we used the name `a` and one we used -the name `b`. - -In the examples that follow, it becomes very important to know whether -a lifetime is bound in a function type (that is, is a lifetime -parameter) or appears free (is defined in some outer scope). -Therefore, from now on I will always write the bindings explicitly, -using the Rust syntax `for<'a> fn(&'a isize)` to indicate that `a` is a -lifetime parameter. - -Now let's consider two more function types. Here, we assume that the -`'b` lifetime is defined somewhere outside and hence is not a lifetime -parameter bound by the function type (it "appears free"): - - for<'a> fn(&'a isize) <: fn(&'b isize)? (Yes, a => b) - -This subtyping relation does in fact hold. To see why, you have to -consider what subtyping means. One way to look at `T1 <: T2` is to -say that it means that it is always ok to treat an instance of `T1` as -if it had the type `T2`. So, with our functions, it is always ok to -treat a function that can take pointers with any lifetime as if it -were a function that can only take a pointer with the specific -lifetime `'b`. After all, `'b` is a lifetime, after all, and -the function can take values of any lifetime. - -You can also look at subtyping as the *is a* relationship. This amounts -to the same thing: a function that accepts pointers with any lifetime -*is a* function that accepts pointers with some specific lifetime. - -So, what if we reverse the order of the two function types, like this: - - fn(&'b isize) <: for<'a> fn(&'a isize)? (No) - -Does the subtyping relationship still hold? The answer of course is -no. In this case, the function accepts *only the lifetime `'b`*, -so it is not reasonable to treat it as if it were a function that -accepted any lifetime. - -What about these two examples: - - for<'a,'b> fn(&'a isize, &'b isize) <: for<'a> fn(&'a isize, &'a isize)? (Yes) - for<'a> fn(&'a isize, &'a isize) <: for<'a,'b> fn(&'a isize, &'b isize)? (No) - -Here, it is true that functions which take two pointers with any two -lifetimes can be treated as if they only accepted two pointers with -the same lifetime, but not the reverse. - -## The algorithm - -Here is the algorithm we use to perform the subtyping check: - -1. Replace all bound regions in the subtype with new variables -2. Replace all bound regions in the supertype with placeholder - equivalents. A "placeholder" region is just a new fresh region - name. -3. Check that the parameter and return types match as normal -4. Ensure that no placeholder regions 'leak' into region variables - visible from "the outside" - -Let's walk through some examples and see how this algorithm plays out. - -#### First example - -We'll start with the first example, which was: - - 1. for<'a> fn(&'a T) <: for<'b> fn(&'b T)? Yes: a -> b - -After steps 1 and 2 of the algorithm we will have replaced the types -like so: - - 1. fn(&'A T) <: fn(&'x T)? - -Here the upper case `&A` indicates a *region variable*, that is, a -region whose value is being inferred by the system. I also replaced -`&b` with `&x`---I'll use letters late in the alphabet (`x`, `y`, `z`) -to indicate placeholder region names. We can assume they don't appear -elsewhere. Note that neither the sub- nor the supertype bind any -region names anymore (as indicated by the absence of `<` and `>`). - -The next step is to check that the parameter types match. Because -parameters are contravariant, this means that we check whether: - - &'x T <: &'A T - -Region pointers are contravariant so this implies that - - &A <= &x - -must hold, where `<=` is the subregion relationship. Processing -*this* constrain simply adds a constraint into our graph that `&A <= -&x` and is considered successful (it can, for example, be satisfied by -choosing the value `&x` for `&A`). - -So far we have encountered no error, so the subtype check succeeds. - -#### The third example - -Now let's look first at the third example, which was: - - 3. fn(&'a T) <: for<'b> fn(&'b T)? No! - -After steps 1 and 2 of the algorithm we will have replaced the types -like so: - - 3. fn(&'a T) <: fn(&'x T)? - -This looks pretty much the same as before, except that on the LHS -`'a` was not bound, and hence was left as-is and not replaced with -a variable. The next step is again to check that the parameter types -match. This will ultimately require (as before) that `'a` <= `&x` -must hold: but this does not hold. `self` and `x` are both distinct -free regions. So the subtype check fails. - -#### Checking for placeholder leaks - -You may be wondering about that mysterious last step in the algorithm. -So far it has not been relevant. The purpose of that last step is to -catch something like *this*: - - for<'a> fn() -> fn(&'a T) <: fn() -> for<'b> fn(&'b T)? No. - -Here the function types are the same but for where the binding occurs. -The subtype returns a function that expects a value in precisely one -region. The supertype returns a function that expects a value in any -region. If we allow an instance of the subtype to be used where the -supertype is expected, then, someone could call the fn and think that -the return value has type `fn(&'b T)` when it really has type -`fn(&'a T)` (this is case #3, above). Bad. - -So let's step through what happens when we perform this subtype check. -We first replace the bound regions in the subtype (the supertype has -no bound regions). This gives us: - - fn() -> fn(&'A T) <: fn() -> for<'b> fn(&'b T)? - -Now we compare the return types, which are covariant, and hence we have: - - fn(&'A T) <: for<'b> fn(&'b T)? - -Here we replace the bound region in the supertype with a placeholder to yield: - - fn(&'A T) <: fn(&'x T)? - -And then proceed to compare the argument types: - - &'x T <: &'A T - 'A <= 'x - -Finally, this is where it gets interesting! This is where an error -*should* be reported. But in fact this will not happen. The reason why -is that `A` is a variable: we will infer that its value is the fresh -region `x` and think that everything is happy. In fact, this behavior -is *necessary*, it was key to the first example we walked through. - -The difference between this example and the first one is that the variable -`A` already existed at the point where the placeholders were added. In -the first example, you had two functions: - - for<'a> fn(&'a T) <: for<'b> fn(&'b T) - -and hence `&A` and `&x` were created "together". In general, the -intention of the placeholder names is that they are supposed to be -fresh names that could never be equal to anything from the outside. -But when inference comes into play, we might not be respecting this -rule. - -So the way we solve this is to add a fourth step that examines the -constraints that refer to placeholder names. Basically, consider a -non-directed version of the constraint graph. Let `Tainted(x)` be the -set of all things reachable from a placeholder variable `x`. -`Tainted(x)` should not contain any regions that existed before the -step at which the placeholders were created. So this case here -would fail because `&x` was created alone, but is relatable to `&A`. - -## Computing the LUB and GLB - -The paper I pointed you at is written for Haskell. It does not -therefore considering subtyping and in particular does not consider -LUB or GLB computation. We have to consider this. Here is the -algorithm I implemented. - -First though, let's discuss what we are trying to compute in more -detail. The LUB is basically the "common supertype" and the GLB is -"common subtype"; one catch is that the LUB should be the -*most-specific* common supertype and the GLB should be *most general* -common subtype (as opposed to any common supertype or any common -subtype). - -Anyway, to help clarify, here is a table containing some function -pairs and their LUB/GLB (for conciseness, in this table, I'm just -including the lifetimes here, not the rest of the types, and I'm -writing `fn<>` instead of `for<> fn`): - -``` -Type 1 Type 2 LUB GLB -fn<'a>('a) fn('X) fn('X) fn<'a>('a) -fn('a) fn('X) -- fn<'a>('a) -fn<'a,'b>('a, 'b) fn<'x>('x, 'x) fn<'a>('a, 'a) fn<'a,'b>('a, 'b) -fn<'a,'b>('a, 'b, 'a) fn<'x,'y>('x, 'y, 'y) fn<'a>('a, 'a, 'a) fn<'a,'b,'c>('a,'b,'c) -``` - -### Conventions - -I use lower-case letters (e.g., `&a`) for bound regions and upper-case -letters for free regions (`&A`). Region variables written with a -dollar-sign (e.g., `$a`). I will try to remember to enumerate the -bound-regions on the fn type as well (e.g., `for<'a> fn(&a)`). - -### High-level summary - -Both the LUB and the GLB algorithms work in a similar fashion. They -begin by replacing all bound regions (on both sides) with fresh region -inference variables. Therefore, both functions are converted to types -that contain only free regions. We can then compute the LUB/GLB in a -straightforward way, as described in `combine.rs`. This results in an -interim type T. The algorithms then examine the regions that appear -in T and try to, in some cases, replace them with bound regions to -yield the final result. - -To decide whether to replace a region `R` that appears in `T` with -a bound region, the algorithms make use of two bits of -information. First is a set `V` that contains all region -variables created as part of the LUB/GLB computation (roughly; see -`region_vars_confined_to_snapshot()` for full details). `V` will -contain the region variables created to replace the bound regions -in the input types, but it also contains 'intermediate' variables -created to represent the LUB/GLB of individual regions. -Basically, when asked to compute the LUB/GLB of a region variable -with another region, the inferencer cannot oblige immediately -since the values of that variables are not known. Therefore, it -creates a new variable that is related to the two regions. For -example, the LUB of two variables `$x` and `$y` is a fresh -variable `$z` that is constrained such that `$x <= $z` and `$y <= -$z`. So `V` will contain these intermediate variables as well. - -The other important factor in deciding how to replace a region in T is -the function `Tainted($r)` which, for a region variable, identifies -all regions that the region variable is related to in some way -(`Tainted()` made an appearance in the subtype computation as well). - -### LUB - -The LUB algorithm proceeds in three steps: - -1. Replace all bound regions (on both sides) with fresh region - inference variables. -2. Compute the LUB "as normal", meaning compute the GLB of each - pair of argument types and the LUB of the return types and - so forth. Combine those to a new function type `F`. -3. Replace each region `R` that appears in `F` as follows: - - Let `V` be the set of variables created during the LUB - computational steps 1 and 2, as described in the previous section. - - If `R` is not in `V`, replace `R` with itself. - - If `Tainted(R)` contains a region that is not in `V`, - replace `R` with itself. - - Otherwise, select the earliest variable in `Tainted(R)` that originates - from the left-hand side and replace `R` with the bound region that - this variable was a replacement for. - -So, let's work through the simplest example: `fn(&A)` and `for<'a> fn(&a)`. -In this case, `&a` will be replaced with `$a` and the interim LUB type -`fn($b)` will be computed, where `$b=GLB(&A,$a)`. Therefore, `V = -{$a, $b}` and `Tainted($b) = { $b, $a, &A }`. When we go to replace -`$b`, we find that since `&A \in Tainted($b)` is not a member of `V`, -we leave `$b` as is. When region inference happens, `$b` will be -resolved to `&A`, as we wanted. - -Let's look at a more complex one: `fn(&a, &b)` and `fn(&x, &x)`. In -this case, we'll end up with a (pre-replacement) LUB type of `fn(&g, -&h)` and a graph that looks like: - -``` - $a $b *--$x - \ \ / / - \ $h-* / - $g-----------* -``` - -Here `$g` and `$h` are fresh variables that are created to represent -the LUB/GLB of things requiring inference. This means that `V` and -`Tainted` will look like: - -``` -V = {$a, $b, $g, $h, $x} -Tainted($g) = Tainted($h) = { $a, $b, $h, $g, $x } -``` - -Therefore we replace both `$g` and `$h` with `$a`, and end up -with the type `fn(&a, &a)`. - -### GLB - -The procedure for computing the GLB is similar. The difference lies -in computing the replacements for the various variables. For each -region `R` that appears in the type `F`, we again compute `Tainted(R)` -and examine the results: - -1. If `R` is not in `V`, it is not replaced. -2. Else, if `Tainted(R)` contains only variables in `V`, and it - contains exactly one variable from the LHS and one variable from - the RHS, then `R` can be mapped to the bound version of the - variable from the LHS. -3. Else, if `Tainted(R)` contains no variable from the LHS and no - variable from the RHS, then `R` can be mapped to itself. -4. Else, `R` is mapped to a fresh bound variable. - -These rules are pretty complex. Let's look at some examples to see -how they play out. - -Out first example was `fn(&a)` and `fn(&X)`. In this case, `&a` will -be replaced with `$a` and we will ultimately compute a -(pre-replacement) GLB type of `fn($g)` where `$g=LUB($a,&X)`. -Therefore, `V={$a,$g}` and `Tainted($g)={$g,$a,&X}. To find the -replacement for `$g` we consult the rules above: -- Rule (1) does not apply because `$g \in V` -- Rule (2) does not apply because `&X \in Tainted($g)` -- Rule (3) does not apply because `$a \in Tainted($g)` -- Hence, by rule (4), we replace `$g` with a fresh bound variable `&z`. -So our final result is `fn(&z)`, which is correct. - -The next example is `fn(&A)` and `fn(&Z)`. In this case, we will again -have a (pre-replacement) GLB of `fn(&g)`, where `$g = LUB(&A,&Z)`. -Therefore, `V={$g}` and `Tainted($g) = {$g, &A, &Z}`. In this case, -by rule (3), `$g` is mapped to itself, and hence the result is -`fn($g)`. This result is correct (in this case, at least), but it is -indicative of a case that *can* lead us into concluding that there is -no GLB when in fact a GLB does exist. See the section "Questionable -Results" below for more details. - -The next example is `fn(&a, &b)` and `fn(&c, &c)`. In this case, as -before, we'll end up with `F=fn($g, $h)` where `Tainted($g) = -Tainted($h) = {$g, $h, $a, $b, $c}`. Only rule (4) applies and hence -we'll select fresh bound variables `y` and `z` and wind up with -`fn(&y, &z)`. - -For the last example, let's consider what may seem trivial, but is -not: `fn(&a, &a)` and `fn(&b, &b)`. In this case, we'll get `F=fn($g, -$h)` where `Tainted($g) = {$g, $a, $x}` and `Tainted($h) = {$h, $a, -$x}`. Both of these sets contain exactly one bound variable from each -side, so we'll map them both to `&a`, resulting in `fn(&a, &a)`, which -is the desired result. - -### Shortcomings and correctness - -You may be wondering whether this algorithm is correct. The answer is -"sort of". There are definitely cases where they fail to compute a -result even though a correct result exists. I believe, though, that -if they succeed, then the result is valid, and I will attempt to -convince you. The basic argument is that the "pre-replacement" step -computes a set of constraints. The replacements, then, attempt to -satisfy those constraints, using bound identifiers where needed. - -For now I will briefly go over the cases for LUB/GLB and identify -their intent: - -- LUB: - - The region variables that are substituted in place of bound regions - are intended to collect constraints on those bound regions. - - If Tainted(R) contains only values in V, then this region is unconstrained - and can therefore be generalized, otherwise it cannot. -- GLB: - - The region variables that are substituted in place of bound regions - are intended to collect constraints on those bound regions. - - If Tainted(R) contains exactly one variable from each side, and - only variables in V, that indicates that those two bound regions - must be equated. - - Otherwise, if Tainted(R) references any variables from left or right - side, then it is trying to combine a bound region with a free one or - multiple bound regions, so we need to select fresh bound regions. - -Sorry this is more of a shorthand to myself. I will try to write up something -more convincing in the future. - -#### Where are the algorithms wrong? - -- The pre-replacement computation can fail even though using a - bound-region would have succeeded. -- We will compute GLB(fn(fn($a)), fn(fn($b))) as fn($c) where $c is the - GLB of $a and $b. But if inference finds that $a and $b must be mapped - to regions without a GLB, then this is effectively a failure to compute - the GLB. However, the result `fn<$c>(fn($c))` is a valid GLB. +[oldhrtb]: https://rust-lang.github.io/rustc-guide/traits/hrtb.html +[newhrtb]: https://rust-lang.github.io/rustc-guide/borrow_check/region_inference.html#placeholders-and-universes diff --git a/src/librustc/ty/query/README.md b/src/librustc/ty/query/README.md index 0fcaef5de54c2..4b5e08cecd99c 100644 --- a/src/librustc/ty/query/README.md +++ b/src/librustc/ty/query/README.md @@ -1,302 +1,3 @@ -# The Rust Compiler Query System - -The Compiler Query System is the key to our new demand-driven -organization. The idea is pretty simple. You have various queries -that compute things about the input -- for example, there is a query -called `type_of(def_id)` that, given the def-id of some item, will -compute the type of that item and return it to you. - -Query execution is **memoized** -- so the first time you invoke a -query, it will go do the computation, but the next time, the result is -returned from a hashtable. Moreover, query execution fits nicely into -**incremental computation**; the idea is roughly that, when you do a -query, the result **may** be returned to you by loading stored data -from disk (but that's a separate topic we won't discuss further here). - -The overall vision is that, eventually, the entire compiler -control-flow will be query driven. There will effectively be one -top-level query ("compile") that will run compilation on a crate; this -will in turn demand information about that crate, starting from the -*end*. For example: - -- This "compile" query might demand to get a list of codegen-units - (i.e., modules that need to be compiled by LLVM). -- But computing the list of codegen-units would invoke some subquery - that returns the list of all modules defined in the Rust source. -- That query in turn would invoke something asking for the HIR. -- This keeps going further and further back until we wind up doing the - actual parsing. - -However, that vision is not fully realized. Still, big chunks of the -compiler (for example, generating MIR) work exactly like this. - -### Invoking queries - -To invoke a query is simple. The tcx ("type context") offers a method -for each defined query. So, for example, to invoke the `type_of` -query, you would just do this: - -```rust -let ty = tcx.type_of(some_def_id); -``` - -### Cycles between queries - -Currently, cycles during query execution should always result in a -compilation error. Typically, they arise because of illegal programs -that contain cyclic references they shouldn't (though sometimes they -arise because of compiler bugs, in which case we need to factor our -queries in a more fine-grained fashion to avoid them). - -However, it is nonetheless often useful to *recover* from a cycle -(after reporting an error, say) and try to soldier on, so as to give a -better user experience. In order to recover from a cycle, you don't -get to use the nice method-call-style syntax. Instead, you invoke -using the `try_get` method, which looks roughly like this: - -```rust -use ty::query::queries; -... -match queries::type_of::try_get(tcx, DUMMY_SP, self.did) { - Ok(result) => { - // no cycle occurred! You can use `result` - } - Err(err) => { - // A cycle occurred! The error value `err` is a `DiagnosticBuilder`, - // meaning essentially an "in-progress", not-yet-reported error message. - // See below for more details on what to do here. - } -} -``` - -So, if you get back an `Err` from `try_get`, then a cycle *did* occur. This means that -you must ensure that a compiler error message is reported. You can do that in two ways: - -The simplest is to invoke `err.emit()`. This will emit the cycle error to the user. - -However, often cycles happen because of an illegal program, and you -know at that point that an error either already has been reported or -will be reported due to this cycle by some other bit of code. In that -case, you can invoke `err.cancel()` to not emit any error. It is -traditional to then invoke: - -``` -tcx.sess.delay_span_bug(some_span, "some message") -``` - -`delay_span_bug()` is a helper that says: we expect a compilation -error to have happened or to happen in the future; so, if compilation -ultimately succeeds, make an ICE with the message `"some -message"`. This is basically just a precaution in case you are wrong. - -### How the compiler executes a query - -So you may be wondering what happens when you invoke a query -method. The answer is that, for each query, the compiler maintains a -cache -- if your query has already been executed, then, the answer is -simple: we clone the return value out of the cache and return it -(therefore, you should try to ensure that the return types of queries -are cheaply cloneable; insert a `Rc` if necessary). - -#### Providers - -If, however, the query is *not* in the cache, then the compiler will -try to find a suitable **provider**. A provider is a function that has -been defined and linked into the compiler somewhere that contains the -code to compute the result of the query. - -**Providers are defined per-crate.** The compiler maintains, -internally, a table of providers for every crate, at least -conceptually. Right now, there are really two sets: the providers for -queries about the **local crate** (that is, the one being compiled) -and providers for queries about **external crates** (that is, -dependencies of the local crate). Note that what determines the crate -that a query is targeting is not the *kind* of query, but the *key*. -For example, when you invoke `tcx.type_of(def_id)`, that could be a -local query or an external query, depending on what crate the `def_id` -is referring to (see the `self::keys::Key` trait for more information -on how that works). - -Providers always have the same signature: - -```rust -fn provider<'cx, 'tcx>(tcx: TyCtxt<'cx, 'tcx, 'tcx>, - key: QUERY_KEY) - -> QUERY_RESULT -{ - ... -} -``` - -Providers take two arguments: the `tcx` and the query key. Note also -that they take the *global* tcx (i.e., they use the `'tcx` lifetime -twice), rather than taking a tcx with some active inference context. -They return the result of the query. - -#### How providers are setup - -When the tcx is created, it is given the providers by its creator using -the `Providers` struct. This struct is generate by the macros here, but it -is basically a big list of function pointers: - -```rust -struct Providers { - type_of: for<'cx, 'tcx> fn(TyCtxt<'cx, 'tcx, 'tcx>, DefId) -> Ty<'tcx>, - ... -} -``` - -At present, we have one copy of the struct for local crates, and one -for external crates, though the plan is that we may eventually have -one per crate. - -These `Provider` structs are ultimately created and populated by -`librustc_driver`, but it does this by distributing the work -throughout the other `rustc_*` crates. This is done by invoking -various `provide` functions. These functions tend to look something -like this: - -```rust -pub fn provide(providers: &mut Providers) { - *providers = Providers { - type_of, - ..*providers - }; -} -``` - -That is, they take an `&mut Providers` and mutate it in place. Usually -we use the formulation above just because it looks nice, but you could -as well do `providers.type_of = type_of`, which would be equivalent. -(Here, `type_of` would be a top-level function, defined as we saw -before.) So, if we want to add a provider for some other query, -let's call it `fubar`, into the crate above, we might modify the `provide()` -function like so: - -```rust -pub fn provide(providers: &mut Providers) { - *providers = Providers { - type_of, - fubar, - ..*providers - }; -} - -fn fubar<'cx, 'tcx>(tcx: TyCtxt<'cx, 'tcx>, key: DefId) -> Fubar<'tcx> { .. } -``` - -NB. Most of the `rustc_*` crates only provide **local -providers**. Almost all **extern providers** wind up going through the -`rustc_metadata` crate, which loads the information from the crate -metadata. But in some cases there are crates that provide queries for -*both* local and external crates, in which case they define both a -`provide` and a `provide_extern` function that `rustc_driver` can -invoke. - -### Adding a new kind of query - -So suppose you want to add a new kind of query, how do you do so? -Well, defining a query takes place in two steps: - -1. first, you have to specify the query name and arguments; and then, -2. you have to supply query providers where needed. - -To specify the query name and arguments, you simply add an entry -to the big macro invocation in `mod.rs`. This will probably have changed -by the time you read this README, but at present it looks something -like: - -``` -define_queries! { <'tcx> - /// Records the type of every item. - [] fn type_of: TypeOfItem(DefId) -> Ty<'tcx>, - - ... -} -``` - -Each line of the macro defines one query. The name is broken up like this: - -``` -[] fn type_of: TypeOfItem(DefId) -> Ty<'tcx>, -^^ ^^^^^^^ ^^^^^^^^^^ ^^^^^ ^^^^^^^^ -| | | | | -| | | | result type of query -| | | query key type -| | dep-node constructor -| name of query -query flags -``` - -Let's go over them one by one: - -- **Query flags:** these are largely unused right now, but the intention - is that we'll be able to customize various aspects of how the query is - processed. -- **Name of query:** the name of the query method - (`tcx.type_of(..)`). Also used as the name of a struct - (`ty::query::queries::type_of`) that will be generated to represent - this query. -- **Dep-node constructor:** indicates the constructor function that - connects this query to incremental compilation. Typically, this is a - `DepNode` variant, which can be added by modifying the - `define_dep_nodes!` macro invocation in - `librustc/dep_graph/dep_node.rs`. - - However, sometimes we use a custom function, in which case the - name will be in snake case and the function will be defined at the - bottom of the file. This is typically used when the query key is - not a def-id, or just not the type that the dep-node expects. -- **Query key type:** the type of the argument to this query. - This type must implement the `ty::query::keys::Key` trait, which - defines (for example) how to map it to a crate, and so forth. -- **Result type of query:** the type produced by this query. This type - should (a) not use `RefCell` or other interior mutability and (b) be - cheaply cloneable. Interning or using `Rc` or `Arc` is recommended for - non-trivial data types. - - The one exception to those rules is the `ty::steal::Steal` type, - which is used to cheaply modify MIR in place. See the definition - of `Steal` for more details. New uses of `Steal` should **not** be - added without alerting `@rust-lang/compiler`. - -So, to add a query: - -- Add an entry to `define_queries!` using the format above. -- Possibly add a corresponding entry to the dep-node macro. -- Link the provider by modifying the appropriate `provide` method; - or add a new one if needed and ensure that `rustc_driver` is invoking it. - -#### Query structs and descriptions - -For each kind, the `define_queries` macro will generate a "query struct" -named after the query. This struct is a kind of a place-holder -describing the query. Each such struct implements the -`self::config::QueryConfig` trait, which has associated types for the -key/value of that particular query. Basically the code generated looks something -like this: - -```rust -// Dummy struct representing a particular kind of query: -pub struct type_of<'tcx> { phantom: PhantomData<&'tcx ()> } - -impl<'tcx> QueryConfig for type_of<'tcx> { - type Key = DefId; - type Value = Ty<'tcx>; -} -``` - -There is an additional trait that you may wish to implement called -`self::config::QueryDescription`. This trait is used during cycle -errors to give a "human readable" name for the query, so that we can -summarize what was happening when the cycle occurred. Implementing -this trait is optional if the query key is `DefId`, but if you *don't* -implement it, you get a pretty generic error ("processing `foo`..."). -You can put new impls into the `config` module. They look something like this: - -```rust -impl<'tcx> QueryDescription for queries::type_of<'tcx> { - fn describe(tcx: TyCtxt<'_, '_, '_>, key: DefId) -> String { - format!("computing the type of `{}`", tcx.item_path_str(key)) - } -} -``` +For more information about how the query system works, see the [rustc guide]. +[rustc guide]: https://rust-lang.github.io/rustc-guide/query.html From 1db42756f7fec98d3705a0f975a1c92d10e88cd7 Mon Sep 17 00:00:00 2001 From: David Wood Date: Mon, 21 Jan 2019 13:25:15 +0100 Subject: [PATCH 09/17] Print visible name for types as well as modules. This commit extends previous work in #55007 where the name from the visible parent was used for modules. Now, we also print the name from the visible parent for types. --- src/librustc/ty/item_path.rs | 28 ++++++++++----------- src/test/ui/issues/auxiliary/issue-56943.rs | 3 +++ src/test/ui/issues/issue-56943.rs | 8 ++++++ src/test/ui/issues/issue-56943.stderr | 12 +++++++++ 4 files changed, 37 insertions(+), 14 deletions(-) create mode 100644 src/test/ui/issues/auxiliary/issue-56943.rs create mode 100644 src/test/ui/issues/issue-56943.rs create mode 100644 src/test/ui/issues/issue-56943.stderr diff --git a/src/librustc/ty/item_path.rs b/src/librustc/ty/item_path.rs index 9328de4f6a0a1..0ddc5ae87208d 100644 --- a/src/librustc/ty/item_path.rs +++ b/src/librustc/ty/item_path.rs @@ -210,12 +210,12 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { let visible_parent = visible_parent_map.get(&cur_def).cloned(); let actual_parent = self.parent(cur_def); - debug!( - "try_push_visible_item_path: visible_parent={:?} actual_parent={:?}", - visible_parent, actual_parent, - ); let data = cur_def_key.disambiguated_data.data; + debug!( + "try_push_visible_item_path: data={:?} visible_parent={:?} actual_parent={:?}", + data, visible_parent, actual_parent, + ); let symbol = match data { // In order to output a path that could actually be imported (valid and visible), // we need to handle re-exports correctly. @@ -248,16 +248,16 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { // the children of the visible parent (as was done when computing // `visible_parent_map`), looking for the specific child we currently have and then // have access to the re-exported name. - DefPathData::Module(module_name) if visible_parent != actual_parent => { - let mut name: Option = None; - if let Some(visible_parent) = visible_parent { - for child in self.item_children(visible_parent).iter() { - if child.def.def_id() == cur_def { - name = Some(child.ident); - } - } - } - name.map(|n| n.as_str()).unwrap_or(module_name.as_str()) + DefPathData::Module(actual_name) | + DefPathData::TypeNs(actual_name) if visible_parent != actual_parent => { + visible_parent + .and_then(|parent| { + self.item_children(parent) + .iter() + .find(|child| child.def.def_id() == cur_def) + .map(|child| child.ident.as_str()) + }) + .unwrap_or_else(|| actual_name.as_str()) }, _ => { data.get_opt_name().map(|n| n.as_str()).unwrap_or_else(|| { diff --git a/src/test/ui/issues/auxiliary/issue-56943.rs b/src/test/ui/issues/auxiliary/issue-56943.rs new file mode 100644 index 0000000000000..65b9beb91f90c --- /dev/null +++ b/src/test/ui/issues/auxiliary/issue-56943.rs @@ -0,0 +1,3 @@ +pub struct S; +mod m { pub struct S; } +pub use crate::m::S as S2; diff --git a/src/test/ui/issues/issue-56943.rs b/src/test/ui/issues/issue-56943.rs new file mode 100644 index 0000000000000..8fc77abdbf588 --- /dev/null +++ b/src/test/ui/issues/issue-56943.rs @@ -0,0 +1,8 @@ +// aux-build:issue-56943.rs + +extern crate issue_56943; + +fn main() { + let _: issue_56943::S = issue_56943::S2; + //~^ ERROR mismatched types [E0308] +} diff --git a/src/test/ui/issues/issue-56943.stderr b/src/test/ui/issues/issue-56943.stderr new file mode 100644 index 0000000000000..27202051524c9 --- /dev/null +++ b/src/test/ui/issues/issue-56943.stderr @@ -0,0 +1,12 @@ +error[E0308]: mismatched types + --> $DIR/issue-56943.rs:6:29 + | +LL | let _: issue_56943::S = issue_56943::S2; + | ^^^^^^^^^^^^^^^ expected struct `issue_56943::S`, found struct `issue_56943::S2` + | + = note: expected type `issue_56943::S` + found type `issue_56943::S2` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. From 8af02faab8434d63b6eedb7b5e8f47d0ff0b5e6c Mon Sep 17 00:00:00 2001 From: Corey Farwell Date: Tue, 22 Jan 2019 22:51:33 -0500 Subject: [PATCH 10/17] reposition markdown hyperlink reference --- src/libcore/num/dec2flt/mod.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/libcore/num/dec2flt/mod.rs b/src/libcore/num/dec2flt/mod.rs index 8bde41fefd5b1..c137986e684a5 100644 --- a/src/libcore/num/dec2flt/mod.rs +++ b/src/libcore/num/dec2flt/mod.rs @@ -129,8 +129,6 @@ macro_rules! from_str_float_impl { /// /// # Grammar /// - /// [EBNF]: https://www.w3.org/TR/REC-xml/#sec-notation - /// /// All strings that adhere to the following [EBNF] grammar /// will result in an [`Ok`] being returned: /// @@ -144,6 +142,8 @@ macro_rules! from_str_float_impl { /// Digit ::= [0-9] /// ``` /// + /// [EBNF]: https://www.w3.org/TR/REC-xml/#sec-notation + /// /// # Known bugs /// /// In some situations, some strings that should create a valid float From fc0c8839f7a4b5a4f8ee4c9c8177fb0ecfb0e5de Mon Sep 17 00:00:00 2001 From: Aaron Hill Date: Wed, 23 Jan 2019 16:32:59 -0500 Subject: [PATCH 11/17] Don't ICE when logging unusual types MonoItemExt#to_string is used for both debug logging and LLVM symbol name generation. When debugging, we want to print out any type we encounter, even if it's something weird like GeneratorWitness. However, during codegen, we still want to error if we encounter an unexpected type when generating a name. To resolve this issue, this commit introduces a new 'debug' parameter to the relevant methods. When set to 'true', it allows any type to be printed - when set to 'false', it 'bug!'s when encountering an unexpected type. This prevents an ICE when enabling debug logging (via RUST_LOG) while running rustc on generator-related code. --- src/librustc_codegen_llvm/type_of.rs | 2 +- src/librustc_codegen_ssa/mono_item.rs | 8 +-- src/librustc_mir/monomorphize/collector.rs | 4 +- src/librustc_mir/monomorphize/item.rs | 56 ++++++++++++------- src/librustc_mir/monomorphize/partitioning.rs | 4 +- 5 files changed, 44 insertions(+), 30 deletions(-) diff --git a/src/librustc_codegen_llvm/type_of.rs b/src/librustc_codegen_llvm/type_of.rs index 97128c2d2a2ce..afaeb352cd992 100644 --- a/src/librustc_codegen_llvm/type_of.rs +++ b/src/librustc_codegen_llvm/type_of.rs @@ -55,7 +55,7 @@ fn uncached_llvm_type<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, ty::Str => { let mut name = String::with_capacity(32); let printer = DefPathBasedNames::new(cx.tcx, true, true); - printer.push_type_name(layout.ty, &mut name); + printer.push_type_name(layout.ty, &mut name, false); if let (&ty::Adt(def, _), &layout::Variants::Single { index }) = (&layout.ty.sty, &layout.variants) { diff --git a/src/librustc_codegen_ssa/mono_item.rs b/src/librustc_codegen_ssa/mono_item.rs index 21e0044759a5a..8488ab2ae862f 100644 --- a/src/librustc_codegen_ssa/mono_item.rs +++ b/src/librustc_codegen_ssa/mono_item.rs @@ -13,7 +13,7 @@ pub use rustc_mir::monomorphize::item::MonoItemExt as BaseMonoItemExt; pub trait MonoItemExt<'a, 'tcx: 'a>: fmt::Debug + BaseMonoItemExt<'a, 'tcx> { fn define>(&self, cx: &'a Bx::CodegenCx) { debug!("BEGIN IMPLEMENTING '{} ({})' in cgu {}", - self.to_string(cx.tcx()), + self.to_string(cx.tcx(), true), self.to_raw_string(), cx.codegen_unit().name()); @@ -45,7 +45,7 @@ pub trait MonoItemExt<'a, 'tcx: 'a>: fmt::Debug + BaseMonoItemExt<'a, 'tcx> { } debug!("END IMPLEMENTING '{} ({})' in cgu {}", - self.to_string(cx.tcx()), + self.to_string(cx.tcx(), true), self.to_raw_string(), cx.codegen_unit().name()); } @@ -57,7 +57,7 @@ pub trait MonoItemExt<'a, 'tcx: 'a>: fmt::Debug + BaseMonoItemExt<'a, 'tcx> { visibility: Visibility ) { debug!("BEGIN PREDEFINING '{} ({})' in cgu {}", - self.to_string(cx.tcx()), + self.to_string(cx.tcx(), true), self.to_raw_string(), cx.codegen_unit().name()); @@ -76,7 +76,7 @@ pub trait MonoItemExt<'a, 'tcx: 'a>: fmt::Debug + BaseMonoItemExt<'a, 'tcx> { } debug!("END PREDEFINING '{} ({})' in cgu {}", - self.to_string(cx.tcx()), + self.to_string(cx.tcx(), true), self.to_raw_string(), cx.codegen_unit().name()); } diff --git a/src/librustc_mir/monomorphize/collector.rs b/src/librustc_mir/monomorphize/collector.rs index eb49547e9bf52..bc63f8b6ac854 100644 --- a/src/librustc_mir/monomorphize/collector.rs +++ b/src/librustc_mir/monomorphize/collector.rs @@ -355,7 +355,7 @@ fn collect_items_rec<'a, 'tcx: 'a>(tcx: TyCtxt<'a, 'tcx, 'tcx>, // We've been here already, no need to search again. return; } - debug!("BEGIN collect_items_rec({})", starting_point.to_string(tcx)); + debug!("BEGIN collect_items_rec({})", starting_point.to_string(tcx, true)); let mut neighbors = Vec::new(); let recursion_depth_reset; @@ -409,7 +409,7 @@ fn collect_items_rec<'a, 'tcx: 'a>(tcx: TyCtxt<'a, 'tcx, 'tcx>, recursion_depths.insert(def_id, depth); } - debug!("END collect_items_rec({})", starting_point.to_string(tcx)); + debug!("END collect_items_rec({})", starting_point.to_string(tcx, true)); } fn record_accesses<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, diff --git a/src/librustc_mir/monomorphize/item.rs b/src/librustc_mir/monomorphize/item.rs index c831cbd98299c..431cc0d52b4c8 100644 --- a/src/librustc_mir/monomorphize/item.rs +++ b/src/librustc_mir/monomorphize/item.rs @@ -159,14 +159,14 @@ pub trait MonoItemExt<'a, 'tcx>: fmt::Debug { tcx.substitute_normalize_and_test_predicates((def_id, &substs)) } - fn to_string(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>) -> String { + fn to_string(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, debug: bool) -> String { return match *self.as_mono_item() { MonoItem::Fn(instance) => { - to_string_internal(tcx, "fn ", instance) + to_string_internal(tcx, "fn ", instance, debug) }, MonoItem::Static(def_id) => { let instance = Instance::new(def_id, tcx.intern_substs(&[])); - to_string_internal(tcx, "static ", instance) + to_string_internal(tcx, "static ", instance, debug) }, MonoItem::GlobalAsm(..) => { "global_asm".to_string() @@ -175,12 +175,13 @@ pub trait MonoItemExt<'a, 'tcx>: fmt::Debug { fn to_string_internal<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, prefix: &str, - instance: Instance<'tcx>) + instance: Instance<'tcx>, + debug: bool) -> String { let mut result = String::with_capacity(32); result.push_str(prefix); let printer = DefPathBasedNames::new(tcx, false, false); - printer.push_instance_as_string(instance, &mut result); + printer.push_instance_as_string(instance, &mut result, debug); result } } @@ -238,7 +239,13 @@ impl<'a, 'tcx> DefPathBasedNames<'a, 'tcx> { } } - pub fn push_type_name(&self, t: Ty<'tcx>, output: &mut String) { + // Pushes the type name of the specified type to the provided string. + // If 'debug' is true, printing normally unprintable types is allowed + // (e.g. ty::GeneratorWitness). This parameter should only be set when + // this method is being used for logging purposes (e.g. with debug! or info!) + // When being used for codegen purposes, 'debug' should be set to 'false' + // in order to catch unexpected types that should never end up in a type name + pub fn push_type_name(&self, t: Ty<'tcx>, output: &mut String, debug: bool) { match t.sty { ty::Bool => output.push_str("bool"), ty::Char => output.push_str("char"), @@ -260,12 +267,12 @@ impl<'a, 'tcx> DefPathBasedNames<'a, 'tcx> { ty::Float(ast::FloatTy::F64) => output.push_str("f64"), ty::Adt(adt_def, substs) => { self.push_def_path(adt_def.did, output); - self.push_type_params(substs, iter::empty(), output); + self.push_type_params(substs, iter::empty(), output, debug); }, ty::Tuple(component_types) => { output.push('('); for &component_type in component_types { - self.push_type_name(component_type, output); + self.push_type_name(component_type, output, debug); output.push_str(", "); } if !component_types.is_empty() { @@ -281,7 +288,7 @@ impl<'a, 'tcx> DefPathBasedNames<'a, 'tcx> { hir::MutMutable => output.push_str("mut "), } - self.push_type_name(inner_type, output); + self.push_type_name(inner_type, output, debug); }, ty::Ref(_, inner_type, mutbl) => { output.push('&'); @@ -289,17 +296,17 @@ impl<'a, 'tcx> DefPathBasedNames<'a, 'tcx> { output.push_str("mut "); } - self.push_type_name(inner_type, output); + self.push_type_name(inner_type, output, debug); }, ty::Array(inner_type, len) => { output.push('['); - self.push_type_name(inner_type, output); + self.push_type_name(inner_type, output, debug); write!(output, "; {}", len.unwrap_usize(self.tcx)).unwrap(); output.push(']'); }, ty::Slice(inner_type) => { output.push('['); - self.push_type_name(inner_type, output); + self.push_type_name(inner_type, output, debug); output.push(']'); }, ty::Dynamic(ref trait_data, ..) => { @@ -309,6 +316,7 @@ impl<'a, 'tcx> DefPathBasedNames<'a, 'tcx> { principal.skip_binder().substs, trait_data.projection_bounds(), output, + debug ); } else { output.push_str("dyn '_"); @@ -338,7 +346,7 @@ impl<'a, 'tcx> DefPathBasedNames<'a, 'tcx> { if !sig.inputs().is_empty() { for ¶meter_type in sig.inputs() { - self.push_type_name(parameter_type, output); + self.push_type_name(parameter_type, output, debug); output.push_str(", "); } output.pop(); @@ -357,7 +365,7 @@ impl<'a, 'tcx> DefPathBasedNames<'a, 'tcx> { if !sig.output().is_unit() { output.push_str(" -> "); - self.push_type_name(sig.output(), output); + self.push_type_name(sig.output(), output, debug); } }, ty::Generator(def_id, GeneratorSubsts { ref substs }, _) | @@ -365,7 +373,7 @@ impl<'a, 'tcx> DefPathBasedNames<'a, 'tcx> { self.push_def_path(def_id, output); let generics = self.tcx.generics_of(self.tcx.closure_base_def_id(def_id)); let substs = substs.truncate_to(self.tcx, generics); - self.push_type_params(substs, iter::empty(), output); + self.push_type_params(substs, iter::empty(), output, debug); } ty::Error | ty::Bound(..) | @@ -376,8 +384,12 @@ impl<'a, 'tcx> DefPathBasedNames<'a, 'tcx> { ty::Param(_) | ty::GeneratorWitness(_) | ty::Opaque(..) => { - bug!("DefPathBasedNames: Trying to create type name for \ + if debug { + output.push_str(&format!("`{:?}`", t)); + } else { + bug!("DefPathBasedNames: Trying to create type name for \ unexpected type: {:?}", t); + } } } } @@ -412,7 +424,8 @@ impl<'a, 'tcx> DefPathBasedNames<'a, 'tcx> { fn push_type_params(&self, substs: &Substs<'tcx>, projections: I, - output: &mut String) + output: &mut String, + debug: bool) where I: Iterator> { let mut projections = projections.peekable(); @@ -423,7 +436,7 @@ impl<'a, 'tcx> DefPathBasedNames<'a, 'tcx> { output.push('<'); for type_parameter in substs.types() { - self.push_type_name(type_parameter, output); + self.push_type_name(type_parameter, output, debug); output.push_str(", "); } @@ -432,7 +445,7 @@ impl<'a, 'tcx> DefPathBasedNames<'a, 'tcx> { let name = &self.tcx.associated_item(projection.item_def_id).ident.as_str(); output.push_str(name); output.push_str("="); - self.push_type_name(projection.ty, output); + self.push_type_name(projection.ty, output, debug); output.push_str(", "); } @@ -444,8 +457,9 @@ impl<'a, 'tcx> DefPathBasedNames<'a, 'tcx> { pub fn push_instance_as_string(&self, instance: Instance<'tcx>, - output: &mut String) { + output: &mut String, + debug: bool) { self.push_def_path(instance.def_id(), output); - self.push_type_params(instance.substs, iter::empty(), output); + self.push_type_params(instance.substs, iter::empty(), output, debug); } } diff --git a/src/librustc_mir/monomorphize/partitioning.rs b/src/librustc_mir/monomorphize/partitioning.rs index c3613fbf04c1b..569e4c828f601 100644 --- a/src/librustc_mir/monomorphize/partitioning.rs +++ b/src/librustc_mir/monomorphize/partitioning.rs @@ -879,7 +879,7 @@ fn debug_dump<'a, 'b, 'tcx, I>(tcx: TyCtxt<'a, 'tcx, 'tcx>, .unwrap_or(""); debug!(" - {} [{:?}] [{}]", - mono_item.to_string(tcx), + mono_item.to_string(tcx, true), linkage, symbol_hash); } @@ -971,7 +971,7 @@ fn collect_and_partition_mono_items<'a, 'tcx>( let mut item_keys: Vec<_> = items .iter() .map(|i| { - let mut output = i.to_string(tcx); + let mut output = i.to_string(tcx, false); output.push_str(" @@"); let mut empty = Vec::new(); let cgus = item_to_cgus.get_mut(i).unwrap_or(&mut empty); From 5e9c8d7369ce2901d327ed2c1849417886ba7a86 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Wed, 2 Jan 2019 16:43:08 -0800 Subject: [PATCH 12/17] When using value after move, point at span of local When trying to use a value after move, instead of using a note, point at the local declaration that has a type that doesn't implement `Copy` trait. --- .../borrow_check/error_reporting.rs | 34 +++++++++++++------ src/test/ui/borrowck/borrowck-asm.mir.stderr | 10 +++--- .../borrowck/borrowck-drop-from-guard.stderr | 5 +-- .../ui/borrowck/borrowck-issue-48962.stderr | 8 ++--- ...k-move-moved-value-into-closure.mir.stderr | 5 +-- src/test/ui/borrowck/borrowck-reinit.stderr | 5 +-- src/test/ui/borrowck/issue-41962.stderr | 5 ++- ...-mutation-of-moved-out-with-mut.nll.stderr | 12 +++---- ...499-field-mutation-of-moved-out.nll.stderr | 12 +++---- ...e-27282-move-match-input-into-guard.stderr | 5 +-- src/test/ui/issues/issue-29723.stderr | 5 +-- .../ui/moves/moves-based-on-type-tuple.stderr | 4 +-- src/test/ui/nll/closure-access-spans.stderr | 16 ++++----- src/test/ui/nll/closure-move-spans.stderr | 12 +++---- src/test/ui/nll/closures-in-loops.stderr | 5 +-- ...1232-partial-init-and-erroneous-use.stderr | 8 ++--- .../issue-21232-partial-init-and-use.stderr | 34 ++++++++++--------- src/test/ui/nll/issue-51512.stderr | 4 +-- src/test/ui/nll/issue-52669.stderr | 5 +-- .../try-block/try-block-bad-lifetime.stderr | 5 +-- .../try-block-maybe-bad-lifetime.stderr | 5 +-- 21 files changed, 116 insertions(+), 88 deletions(-) diff --git a/src/librustc_mir/borrow_check/error_reporting.rs b/src/librustc_mir/borrow_check/error_reporting.rs index 233db12b03001..cbcf8c90fee41 100644 --- a/src/librustc_mir/borrow_check/error_reporting.rs +++ b/src/librustc_mir/borrow_check/error_reporting.rs @@ -198,19 +198,31 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { let place = &self.move_data.move_paths[mpi].place; let ty = place.ty(self.mir, self.infcx.tcx).to_ty(self.infcx.tcx); - let note_msg = match self.describe_place_with_options( - place, - IncludingDowncast(true), - ) { - Some(name) => format!("`{}`", name), + let opt_name = self.describe_place_with_options(place, IncludingDowncast(true)); + let note_msg = match opt_name { + Some(ref name) => format!("`{}`", name), None => "value".to_owned(), }; - - err.note(&format!( - "move occurs because {} has type `{}`, \ - which does not implement the `Copy` trait", - note_msg, ty - )); + let mut note = true; + for decl in &self.mir.local_decls { + if decl.ty == ty && decl.name.map(|x| x.to_string()) == opt_name { + err.span_label( + decl.source_info.span, + format!( + "move occurs because {} has type `{}`, \ + which does not implement the `Copy` trait", + note_msg, ty, + )); + note = false; + } + } + if note { + err.note(&format!( + "move occurs because {} has type `{}`, \ + which does not implement the `Copy` trait", + note_msg, ty + )); + } } if let Some((_, mut old_err)) = self.move_error_reported diff --git a/src/test/ui/borrowck/borrowck-asm.mir.stderr b/src/test/ui/borrowck/borrowck-asm.mir.stderr index 9c47845a52830..86e4832b3873c 100644 --- a/src/test/ui/borrowck/borrowck-asm.mir.stderr +++ b/src/test/ui/borrowck/borrowck-asm.mir.stderr @@ -1,13 +1,14 @@ error[E0382]: use of moved value: `x` --> $DIR/borrowck-asm.rs:27:17 | +LL | let x = &mut 0isize; + | - move occurs because `x` has type `&mut isize`, which does not implement the `Copy` trait +LL | unsafe { LL | asm!("nop" : : "r"(x)); | - value moved here LL | } LL | let z = x; //[ast]~ ERROR use of moved value: `x` | ^ value used here after move - | - = note: move occurs because `x` has type `&mut isize`, which does not implement the `Copy` trait error[E0503]: cannot use `x` because it was mutably borrowed --> $DIR/borrowck-asm.rs:35:32 @@ -66,12 +67,13 @@ LL | let z = y; error[E0382]: use of moved value: `x` --> $DIR/borrowck-asm.rs:86:40 | +LL | let x = &mut 2; + | - move occurs because `x` has type `&mut i32`, which does not implement the `Copy` trait +LL | unsafe { LL | asm!("nop" : : "r"(x), "r"(x) ); //[ast]~ ERROR use of moved value | - ^ value used here after move | | | value moved here - | - = note: move occurs because `x` has type `&mut i32`, which does not implement the `Copy` trait error: aborting due to 7 previous errors diff --git a/src/test/ui/borrowck/borrowck-drop-from-guard.stderr b/src/test/ui/borrowck/borrowck-drop-from-guard.stderr index d395b7734f9b7..07b597f480feb 100644 --- a/src/test/ui/borrowck/borrowck-drop-from-guard.stderr +++ b/src/test/ui/borrowck/borrowck-drop-from-guard.stderr @@ -1,13 +1,14 @@ error[E0382]: use of moved value: `my_str` --> $DIR/borrowck-drop-from-guard.rs:11:23 | +LL | let my_str = "hello".to_owned(); + | ------ move occurs because `my_str` has type `std::string::String`, which does not implement the `Copy` trait +LL | match Some(42) { LL | Some(_) if { drop(my_str); false } => {} | ------ value moved here LL | Some(_) => {} LL | None => { foo(my_str); } //~ ERROR [E0382] | ^^^^^^ value used here after move - | - = note: move occurs because `my_str` has type `std::string::String`, which does not implement the `Copy` trait error: aborting due to previous error diff --git a/src/test/ui/borrowck/borrowck-issue-48962.stderr b/src/test/ui/borrowck/borrowck-issue-48962.stderr index 9d53d82265eca..de4894d5b526b 100644 --- a/src/test/ui/borrowck/borrowck-issue-48962.stderr +++ b/src/test/ui/borrowck/borrowck-issue-48962.stderr @@ -1,22 +1,22 @@ error[E0382]: use of moved value: `src` --> $DIR/borrowck-issue-48962.rs:16:5 | +LL | let mut src = &mut node; + | ------- move occurs because `src` has type `&mut Node`, which does not implement the `Copy` trait LL | {src}; | --- value moved here LL | src.next = None; //~ ERROR use of moved value: `src` [E0382] | ^^^^^^^^ value used here after move - | - = note: move occurs because `src` has type `&mut Node`, which does not implement the `Copy` trait error[E0382]: use of moved value: `src` --> $DIR/borrowck-issue-48962.rs:22:5 | +LL | let mut src = &mut (22, 44); + | ------- move occurs because `src` has type `&mut (i32, i32)`, which does not implement the `Copy` trait LL | {src}; | --- value moved here LL | src.0 = 66; //~ ERROR use of moved value: `src` [E0382] | ^^^^^^^^^^ value used here after move - | - = note: move occurs because `src` has type `&mut (i32, i32)`, which does not implement the `Copy` trait error: aborting due to 2 previous errors diff --git a/src/test/ui/borrowck/borrowck-move-moved-value-into-closure.mir.stderr b/src/test/ui/borrowck/borrowck-move-moved-value-into-closure.mir.stderr index 24b9b4338a58c..0789926563ce7 100644 --- a/src/test/ui/borrowck/borrowck-move-moved-value-into-closure.mir.stderr +++ b/src/test/ui/borrowck/borrowck-move-moved-value-into-closure.mir.stderr @@ -1,6 +1,9 @@ error[E0382]: use of moved value: `t` --> $DIR/borrowck-move-moved-value-into-closure.rs:14:12 | +LL | let t: Box<_> = box 3; + | - move occurs because `t` has type `std::boxed::Box`, which does not implement the `Copy` trait +LL | LL | call_f(move|| { *t + 1 }); | ------ - variable moved due to use in closure | | @@ -9,8 +12,6 @@ LL | call_f(move|| { *t + 1 }); //[ast]~ ERROR capture of moved value | ^^^^^^ - use occurs due to use in closure | | | value used here after move - | - = note: move occurs because `t` has type `std::boxed::Box`, which does not implement the `Copy` trait error: aborting due to previous error diff --git a/src/test/ui/borrowck/borrowck-reinit.stderr b/src/test/ui/borrowck/borrowck-reinit.stderr index 918452726a06c..96f3981ac2fe6 100644 --- a/src/test/ui/borrowck/borrowck-reinit.stderr +++ b/src/test/ui/borrowck/borrowck-reinit.stderr @@ -11,12 +11,13 @@ LL | let _ = (1,x); //~ ERROR use of moved value: `x` (Ast) error[E0382]: use of moved value: `x` (Mir) --> $DIR/borrowck-reinit.rs:8:16 | +LL | let mut x = Box::new(0); + | ----- move occurs because `x` has type `std::boxed::Box`, which does not implement the `Copy` trait +... LL | drop(x); | - value moved here LL | let _ = (1,x); //~ ERROR use of moved value: `x` (Ast) | ^ value used here after move - | - = note: move occurs because `x` has type `std::boxed::Box`, which does not implement the `Copy` trait error: aborting due to 2 previous errors diff --git a/src/test/ui/borrowck/issue-41962.stderr b/src/test/ui/borrowck/issue-41962.stderr index fd4d318b5ddf1..3c0071f6b3745 100644 --- a/src/test/ui/borrowck/issue-41962.stderr +++ b/src/test/ui/borrowck/issue-41962.stderr @@ -19,10 +19,13 @@ LL | if let Some(thing) = maybe { error[E0382]: use of moved value (Mir) --> $DIR/issue-41962.rs:7:21 | +LL | let maybe = Some(vec![true, true]); + | ---------------- move occurs because value has type `std::vec::Vec`, which does not implement the `Copy` trait +... LL | if let Some(thing) = maybe { | ^^^^^ value moved here, in previous iteration of loop | - = note: move occurs because value has type `std::vec::Vec`, which does not implement the `Copy` trait + = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) error: aborting due to 3 previous errors diff --git a/src/test/ui/borrowck/issue-54499-field-mutation-of-moved-out-with-mut.nll.stderr b/src/test/ui/borrowck/issue-54499-field-mutation-of-moved-out-with-mut.nll.stderr index 7861087ad02eb..42aa038170238 100644 --- a/src/test/ui/borrowck/issue-54499-field-mutation-of-moved-out-with-mut.nll.stderr +++ b/src/test/ui/borrowck/issue-54499-field-mutation-of-moved-out-with-mut.nll.stderr @@ -1,32 +1,32 @@ error[E0382]: assign to part of moved value: `t` --> $DIR/issue-54499-field-mutation-of-moved-out-with-mut.rs:23:9 | +LL | let mut t: Tuple = (S(0), 0); + | ----- move occurs because `t` has type `(S, i32)`, which does not implement the `Copy` trait LL | drop(t); | - value moved here LL | t.0 = S(1); | ^^^^^^^^^^ value partially assigned here after move - | - = note: move occurs because `t` has type `(S, i32)`, which does not implement the `Copy` trait error[E0382]: assign to part of moved value: `u` --> $DIR/issue-54499-field-mutation-of-moved-out-with-mut.rs:34:9 | +LL | let mut u: Tpair = Tpair(S(0), 0); + | ----- move occurs because `u` has type `Tpair`, which does not implement the `Copy` trait LL | drop(u); | - value moved here LL | u.0 = S(1); | ^^^^^^^^^^ value partially assigned here after move - | - = note: move occurs because `u` has type `Tpair`, which does not implement the `Copy` trait error[E0382]: assign to part of moved value: `v` --> $DIR/issue-54499-field-mutation-of-moved-out-with-mut.rs:45:9 | +LL | let mut v: Spair = Spair { x: S(0), y: 0 }; + | ----- move occurs because `v` has type `Spair`, which does not implement the `Copy` trait LL | drop(v); | - value moved here LL | v.x = S(1); | ^^^^^^^^^^ value partially assigned here after move - | - = note: move occurs because `v` has type `Spair`, which does not implement the `Copy` trait error: aborting due to 3 previous errors diff --git a/src/test/ui/borrowck/issue-54499-field-mutation-of-moved-out.nll.stderr b/src/test/ui/borrowck/issue-54499-field-mutation-of-moved-out.nll.stderr index d35d0058027d4..1184907f307cb 100644 --- a/src/test/ui/borrowck/issue-54499-field-mutation-of-moved-out.nll.stderr +++ b/src/test/ui/borrowck/issue-54499-field-mutation-of-moved-out.nll.stderr @@ -10,12 +10,12 @@ LL | t.0 = S(1); error[E0382]: assign to part of moved value: `t` --> $DIR/issue-54499-field-mutation-of-moved-out.rs:23:9 | +LL | let t: Tuple = (S(0), 0); + | - move occurs because `t` has type `(S, i32)`, which does not implement the `Copy` trait LL | drop(t); | - value moved here LL | t.0 = S(1); | ^^^^^^^^^^ value partially assigned here after move - | - = note: move occurs because `t` has type `(S, i32)`, which does not implement the `Copy` trait error[E0594]: cannot assign to `t.1`, as `t` is not declared as mutable --> $DIR/issue-54499-field-mutation-of-moved-out.rs:27:9 @@ -38,12 +38,12 @@ LL | u.0 = S(1); error[E0382]: assign to part of moved value: `u` --> $DIR/issue-54499-field-mutation-of-moved-out.rs:38:9 | +LL | let u: Tpair = Tpair(S(0), 0); + | - move occurs because `u` has type `Tpair`, which does not implement the `Copy` trait LL | drop(u); | - value moved here LL | u.0 = S(1); | ^^^^^^^^^^ value partially assigned here after move - | - = note: move occurs because `u` has type `Tpair`, which does not implement the `Copy` trait error[E0594]: cannot assign to `u.1`, as `u` is not declared as mutable --> $DIR/issue-54499-field-mutation-of-moved-out.rs:42:9 @@ -66,12 +66,12 @@ LL | v.x = S(1); error[E0382]: assign to part of moved value: `v` --> $DIR/issue-54499-field-mutation-of-moved-out.rs:53:9 | +LL | let v: Spair = Spair { x: S(0), y: 0 }; + | - move occurs because `v` has type `Spair`, which does not implement the `Copy` trait LL | drop(v); | - value moved here LL | v.x = S(1); | ^^^^^^^^^^ value partially assigned here after move - | - = note: move occurs because `v` has type `Spair`, which does not implement the `Copy` trait error[E0594]: cannot assign to `v.y`, as `v` is not declared as mutable --> $DIR/issue-54499-field-mutation-of-moved-out.rs:57:9 diff --git a/src/test/ui/issues/issue-27282-move-match-input-into-guard.stderr b/src/test/ui/issues/issue-27282-move-match-input-into-guard.stderr index 8ea2bdb693d31..6993419326c8e 100644 --- a/src/test/ui/issues/issue-27282-move-match-input-into-guard.stderr +++ b/src/test/ui/issues/issue-27282-move-match-input-into-guard.stderr @@ -1,6 +1,9 @@ error[E0382]: use of moved value: `b` --> $DIR/issue-27282-move-match-input-into-guard.rs:18:14 | +LL | let b = &mut true; + | - move occurs because `b` has type `&mut bool`, which does not implement the `Copy` trait +... LL | _ if { (|| { let bar = b; *bar = false; })(); | -- - variable moved due to use in closure | | @@ -8,8 +11,6 @@ LL | _ if { (|| { let bar = b; *bar = false; })(); LL | false } => { }, LL | &mut true => { println!("You might think we should get here"); }, | ^^^^ value used here after move - | - = note: move occurs because `b` has type `&mut bool`, which does not implement the `Copy` trait error: aborting due to previous error diff --git a/src/test/ui/issues/issue-29723.stderr b/src/test/ui/issues/issue-29723.stderr index de858aec881f7..7928af5d5a5cd 100644 --- a/src/test/ui/issues/issue-29723.stderr +++ b/src/test/ui/issues/issue-29723.stderr @@ -1,13 +1,14 @@ error[E0382]: use of moved value: `s` --> $DIR/issue-29723.rs:12:13 | +LL | let s = String::new(); + | - move occurs because `s` has type `std::string::String`, which does not implement the `Copy` trait +LL | let _s = match 0 { LL | 0 if { drop(s); false } => String::from("oops"), | - value moved here ... LL | s | ^ value used here after move - | - = note: move occurs because `s` has type `std::string::String`, which does not implement the `Copy` trait error: aborting due to previous error diff --git a/src/test/ui/moves/moves-based-on-type-tuple.stderr b/src/test/ui/moves/moves-based-on-type-tuple.stderr index 2d2c0a15a002a..c49dbdab40210 100644 --- a/src/test/ui/moves/moves-based-on-type-tuple.stderr +++ b/src/test/ui/moves/moves-based-on-type-tuple.stderr @@ -11,12 +11,12 @@ LL | box (x, x) error[E0382]: use of moved value: `x` (Mir) --> $DIR/moves-based-on-type-tuple.rs:6:13 | +LL | fn dup(x: Box) -> Box<(Box,Box)> { + | - move occurs because `x` has type `std::boxed::Box`, which does not implement the `Copy` trait LL | box (x, x) | - ^ value used here after move | | | value moved here - | - = note: move occurs because `x` has type `std::boxed::Box`, which does not implement the `Copy` trait error: aborting due to 2 previous errors diff --git a/src/test/ui/nll/closure-access-spans.stderr b/src/test/ui/nll/closure-access-spans.stderr index efe4c15240d20..3ca0aefb592e0 100644 --- a/src/test/ui/nll/closure-access-spans.stderr +++ b/src/test/ui/nll/closure-access-spans.stderr @@ -59,50 +59,50 @@ LL | r.use_ref(); error[E0382]: borrow of moved value: `x` --> $DIR/closure-access-spans.rs:37:5 | +LL | fn closure_imm_capture_moved(mut x: String) { + | ----- move occurs because `x` has type `std::string::String`, which does not implement the `Copy` trait LL | let r = x; | - value moved here LL | || x.len(); //~ ERROR | ^^ - borrow occurs due to use in closure | | | value borrowed here after move - | - = note: move occurs because `x` has type `std::string::String`, which does not implement the `Copy` trait error[E0382]: borrow of moved value: `x` --> $DIR/closure-access-spans.rs:42:5 | +LL | fn closure_mut_capture_moved(mut x: String) { + | ----- move occurs because `x` has type `std::string::String`, which does not implement the `Copy` trait LL | let r = x; | - value moved here LL | || x = String::new(); //~ ERROR | ^^ - borrow occurs due to use in closure | | | value borrowed here after move - | - = note: move occurs because `x` has type `std::string::String`, which does not implement the `Copy` trait error[E0382]: borrow of moved value: `x` --> $DIR/closure-access-spans.rs:47:5 | +LL | fn closure_unique_capture_moved(x: &mut String) { + | - move occurs because `x` has type `&mut std::string::String`, which does not implement the `Copy` trait LL | let r = x; | - value moved here LL | || *x = String::new(); //~ ERROR | ^^ - borrow occurs due to use in closure | | | value borrowed here after move - | - = note: move occurs because `x` has type `&mut std::string::String`, which does not implement the `Copy` trait error[E0382]: use of moved value: `x` --> $DIR/closure-access-spans.rs:52:5 | +LL | fn closure_move_capture_moved(x: &mut String) { + | - move occurs because `x` has type `&mut std::string::String`, which does not implement the `Copy` trait LL | let r = x; | - value moved here LL | || x; //~ ERROR | ^^ - use occurs due to use in closure | | | value used here after move - | - = note: move occurs because `x` has type `&mut std::string::String`, which does not implement the `Copy` trait error: aborting due to 9 previous errors diff --git a/src/test/ui/nll/closure-move-spans.stderr b/src/test/ui/nll/closure-move-spans.stderr index 3ae1912eb10bf..6750c4047601a 100644 --- a/src/test/ui/nll/closure-move-spans.stderr +++ b/src/test/ui/nll/closure-move-spans.stderr @@ -1,38 +1,38 @@ error[E0382]: use of moved value: `x` --> $DIR/closure-move-spans.rs:7:13 | +LL | fn move_after_move(x: String) { + | - move occurs because `x` has type `std::string::String`, which does not implement the `Copy` trait LL | || x; | -- - variable moved due to use in closure | | | value moved into closure here LL | let y = x; //~ ERROR | ^ value used here after move - | - = note: move occurs because `x` has type `std::string::String`, which does not implement the `Copy` trait error[E0382]: borrow of moved value: `x` --> $DIR/closure-move-spans.rs:12:13 | +LL | fn borrow_after_move(x: String) { + | - move occurs because `x` has type `std::string::String`, which does not implement the `Copy` trait LL | || x; | -- - variable moved due to use in closure | | | value moved into closure here LL | let y = &x; //~ ERROR | ^^ value borrowed here after move - | - = note: move occurs because `x` has type `std::string::String`, which does not implement the `Copy` trait error[E0382]: borrow of moved value: `x` --> $DIR/closure-move-spans.rs:17:13 | +LL | fn borrow_mut_after_move(mut x: String) { + | ----- move occurs because `x` has type `std::string::String`, which does not implement the `Copy` trait LL | || x; | -- - variable moved due to use in closure | | | value moved into closure here LL | let y = &mut x; //~ ERROR | ^^^^^^ value borrowed here after move - | - = note: move occurs because `x` has type `std::string::String`, which does not implement the `Copy` trait error: aborting due to 3 previous errors diff --git a/src/test/ui/nll/closures-in-loops.stderr b/src/test/ui/nll/closures-in-loops.stderr index 93e095d663cc2..6c9e1639f88dd 100644 --- a/src/test/ui/nll/closures-in-loops.stderr +++ b/src/test/ui/nll/closures-in-loops.stderr @@ -1,12 +1,13 @@ error[E0382]: use of moved value: `x` --> $DIR/closures-in-loops.rs:8:9 | +LL | fn repreated_move(x: String) { + | - move occurs because `x` has type `std::string::String`, which does not implement the `Copy` trait +LL | for i in 0..10 { LL | || x; //~ ERROR | ^^ - use occurs due to use in closure | | | value moved into closure here, in previous iteration of loop - | - = note: move occurs because `x` has type `std::string::String`, which does not implement the `Copy` trait error[E0499]: cannot borrow `x` as mutable more than once at a time --> $DIR/closures-in-loops.rs:15:16 diff --git a/src/test/ui/nll/issue-21232-partial-init-and-erroneous-use.stderr b/src/test/ui/nll/issue-21232-partial-init-and-erroneous-use.stderr index e29c44760a987..54c728e3d2783 100644 --- a/src/test/ui/nll/issue-21232-partial-init-and-erroneous-use.stderr +++ b/src/test/ui/nll/issue-21232-partial-init-and-erroneous-use.stderr @@ -13,12 +13,12 @@ LL | d.x = 10; error[E0382]: assign of moved value: `d` --> $DIR/issue-21232-partial-init-and-erroneous-use.rs:43:5 | +LL | let mut d = D { x: 0, s: S{ y: 0, z: 0 } }; + | ----- move occurs because `d` has type `D`, which does not implement the `Copy` trait LL | drop(d); | - value moved here LL | d.x = 10; | ^^^^^^^^ value assigned here after move - | - = note: move occurs because `d` has type `D`, which does not implement the `Copy` trait error[E0381]: assign to part of possibly uninitialized variable: `d` --> $DIR/issue-21232-partial-init-and-erroneous-use.rs:49:5 @@ -35,12 +35,12 @@ LL | d.s.y = 20; error[E0382]: assign to part of moved value: `d` --> $DIR/issue-21232-partial-init-and-erroneous-use.rs:62:5 | +LL | let mut d = D { x: 0, s: S{ y: 0, z: 0} }; + | ----- move occurs because `d` has type `D`, which does not implement the `Copy` trait LL | drop(d); | - value moved here LL | d.s.y = 20; | ^^^^^^^^^^ value partially assigned here after move - | - = note: move occurs because `d` has type `D`, which does not implement the `Copy` trait error: aborting due to 6 previous errors diff --git a/src/test/ui/nll/issue-21232-partial-init-and-use.stderr b/src/test/ui/nll/issue-21232-partial-init-and-use.stderr index aec7f676fcebd..23da533252cb9 100644 --- a/src/test/ui/nll/issue-21232-partial-init-and-use.stderr +++ b/src/test/ui/nll/issue-21232-partial-init-and-use.stderr @@ -14,21 +14,21 @@ error[E0382]: assign to part of moved value: `s` --> $DIR/issue-21232-partial-init-and-use.rs:113:5 | LL | let mut s: S = S::new(); drop(s); - | - value moved here + | ----- - value moved here + | | + | move occurs because `s` has type `S>`, which does not implement the `Copy` trait LL | s.x = 10; s.y = Box::new(20); | ^^^^^^^^ value partially assigned here after move - | - = note: move occurs because `s` has type `S>`, which does not implement the `Copy` trait error[E0382]: assign to part of moved value: `t` --> $DIR/issue-21232-partial-init-and-use.rs:120:5 | LL | let mut t: T = (0, Box::new(0)); drop(t); - | - value moved here + | ----- - value moved here + | | + | move occurs because `t` has type `(u32, std::boxed::Box)`, which does not implement the `Copy` trait LL | t.0 = 10; t.1 = Box::new(20); | ^^^^^^^^ value partially assigned here after move - | - = note: move occurs because `t` has type `(u32, std::boxed::Box)`, which does not implement the `Copy` trait error[E0381]: assign to part of possibly uninitialized variable: `s` --> $DIR/issue-21232-partial-init-and-use.rs:127:5 @@ -46,21 +46,21 @@ error[E0382]: assign to part of moved value: `s` --> $DIR/issue-21232-partial-init-and-use.rs:141:5 | LL | let mut s: S = S::new(); drop(s); - | - value moved here + | ----- - value moved here + | | + | move occurs because `s` has type `S>`, which does not implement the `Copy` trait LL | s.x = 10; | ^^^^^^^^ value partially assigned here after move - | - = note: move occurs because `s` has type `S>`, which does not implement the `Copy` trait error[E0382]: assign to part of moved value: `t` --> $DIR/issue-21232-partial-init-and-use.rs:148:5 | LL | let mut t: T = (0, Box::new(0)); drop(t); - | - value moved here + | ----- - value moved here + | | + | move occurs because `t` has type `(u32, std::boxed::Box)`, which does not implement the `Copy` trait LL | t.0 = 10; | ^^^^^^^^ value partially assigned here after move - | - = note: move occurs because `t` has type `(u32, std::boxed::Box)`, which does not implement the `Copy` trait error[E0381]: assign to part of possibly uninitialized variable: `s` --> $DIR/issue-21232-partial-init-and-use.rs:155:5 @@ -153,22 +153,24 @@ LL | q.r.f.0 = 10; error[E0382]: assign to part of moved value: `c` --> $DIR/issue-21232-partial-init-and-use.rs:259:13 | +LL | let mut c = (1, "".to_owned()); + | ----- move occurs because `c` has type `(i32, std::string::String)`, which does not implement the `Copy` trait +LL | match c { LL | c2 => { | -- value moved here LL | c.0 = 2; //~ ERROR assign to part of moved value | ^^^^^^^ value partially assigned here after move - | - = note: move occurs because `c` has type `(i32, std::string::String)`, which does not implement the `Copy` trait error[E0382]: assign to part of moved value: `c` --> $DIR/issue-21232-partial-init-and-use.rs:269:13 | +LL | let mut c = (1, (1, "".to_owned())); + | ----- move occurs because `c` has type `(i32, (i32, std::string::String))`, which does not implement the `Copy` trait +LL | match c { LL | c2 => { | -- value moved here LL | (c.1).0 = 2; //~ ERROR assign to part of moved value | ^^^^^^^^^^^ value partially assigned here after move - | - = note: move occurs because `c` has type `(i32, (i32, std::string::String))`, which does not implement the `Copy` trait error[E0382]: assign to part of moved value: `c.1` --> $DIR/issue-21232-partial-init-and-use.rs:277:13 diff --git a/src/test/ui/nll/issue-51512.stderr b/src/test/ui/nll/issue-51512.stderr index 4717935e4b9f9..a84a236ca7772 100644 --- a/src/test/ui/nll/issue-51512.stderr +++ b/src/test/ui/nll/issue-51512.stderr @@ -1,12 +1,12 @@ error[E0382]: use of moved value: `range` --> $DIR/issue-51512.rs:7:13 | +LL | let range = 0..1; + | ----- move occurs because `range` has type `std::ops::Range`, which does not implement the `Copy` trait LL | let r = range; | ----- value moved here LL | let x = range.start; | ^^^^^^^^^^^ value used here after move - | - = note: move occurs because `range` has type `std::ops::Range`, which does not implement the `Copy` trait error: aborting due to previous error diff --git a/src/test/ui/nll/issue-52669.stderr b/src/test/ui/nll/issue-52669.stderr index e1fb76c6bc242..f51768c3859e4 100644 --- a/src/test/ui/nll/issue-52669.stderr +++ b/src/test/ui/nll/issue-52669.stderr @@ -1,12 +1,13 @@ error[E0382]: borrow of moved value: `a.b` --> $DIR/issue-52669.rs:15:5 | +LL | fn bar(mut a: A) -> B { + | ----- move occurs because `a` has type `A`, which does not implement the `Copy` trait +LL | a.b = B; LL | foo(a); | - value moved here LL | a.b.clone() | ^^^ value borrowed here after move - | - = note: move occurs because `a` has type `A`, which does not implement the `Copy` trait error: aborting due to previous error diff --git a/src/test/ui/try-block/try-block-bad-lifetime.stderr b/src/test/ui/try-block/try-block-bad-lifetime.stderr index 5bb0b099b977b..b1b925d694ff9 100644 --- a/src/test/ui/try-block/try-block-bad-lifetime.stderr +++ b/src/test/ui/try-block/try-block-bad-lifetime.stderr @@ -25,13 +25,14 @@ LL | ::std::mem::drop(k); //~ ERROR use of moved value: `k` error[E0382]: use of moved value: `k` --> $DIR/try-block-bad-lifetime.rs:31:26 | +LL | let k = &mut i; + | - move occurs because `k` has type `&mut i32`, which does not implement the `Copy` trait +LL | let mut j: Result<(), &mut i32> = try { LL | Err(k) ?; | - value moved here ... LL | ::std::mem::drop(k); //~ ERROR use of moved value: `k` | ^ value used here after move - | - = note: move occurs because `k` has type `&mut i32`, which does not implement the `Copy` trait error[E0506]: cannot assign to `i` because it is borrowed --> $DIR/try-block-bad-lifetime.rs:32:9 diff --git a/src/test/ui/try-block/try-block-maybe-bad-lifetime.stderr b/src/test/ui/try-block/try-block-maybe-bad-lifetime.stderr index f96c7146d18d0..dafbde6a5150b 100644 --- a/src/test/ui/try-block/try-block-maybe-bad-lifetime.stderr +++ b/src/test/ui/try-block/try-block-maybe-bad-lifetime.stderr @@ -13,13 +13,14 @@ LL | do_something_with(x); error[E0382]: borrow of moved value: `x` --> $DIR/try-block-maybe-bad-lifetime.rs:28:24 | +LL | let x = String::new(); + | - move occurs because `x` has type `std::string::String`, which does not implement the `Copy` trait +... LL | ::std::mem::drop(x); | - value moved here LL | }; LL | println!("{}", x); //~ ERROR borrow of moved value: `x` | ^ value borrowed here after move - | - = note: move occurs because `x` has type `std::string::String`, which does not implement the `Copy` trait error[E0506]: cannot assign to `i` because it is borrowed --> $DIR/try-block-maybe-bad-lifetime.rs:40:9 From e0a606c6a9a7f65840afae38feaf2fe178974c45 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Wed, 2 Jan 2019 16:56:45 -0800 Subject: [PATCH 13/17] Add test for #34721 --- src/test/ui/issues/issue-34721.rs | 34 +++++++++++++++++++++++++++ src/test/ui/issues/issue-34721.stderr | 18 ++++++++++++++ 2 files changed, 52 insertions(+) create mode 100644 src/test/ui/issues/issue-34721.rs create mode 100644 src/test/ui/issues/issue-34721.stderr diff --git a/src/test/ui/issues/issue-34721.rs b/src/test/ui/issues/issue-34721.rs new file mode 100644 index 0000000000000..226c21446b1ed --- /dev/null +++ b/src/test/ui/issues/issue-34721.rs @@ -0,0 +1,34 @@ +#![feature(nll)] + +pub trait Foo { + fn zero(self) -> Self; +} + +impl Foo for u32 { + fn zero(self) -> u32 { 0u32 } +} + +pub mod bar { + pub use Foo; + pub fn bar(x: T) -> T { + x.zero() + } +} + +mod baz { + use bar; + use Foo; + pub fn baz(x: T) -> T { + if 0 == 1 { + bar::bar(x.zero()) + } else { + x.zero() + }; + x.zero() + //~^ ERROR use of moved value + } +} + +fn main() { + let _ = baz::baz(0u32); +} diff --git a/src/test/ui/issues/issue-34721.stderr b/src/test/ui/issues/issue-34721.stderr new file mode 100644 index 0000000000000..b4e274b1c7019 --- /dev/null +++ b/src/test/ui/issues/issue-34721.stderr @@ -0,0 +1,18 @@ +error[E0382]: use of moved value: `x` + --> $DIR/issue-34721.rs:27:9 + | +LL | pub fn baz(x: T) -> T { + | - move occurs because `x` has type `T`, which does not implement the `Copy` trait +LL | if 0 == 1 { +LL | bar::bar(x.zero()) + | - value moved here +LL | } else { +LL | x.zero() + | - value moved here +LL | }; +LL | x.zero() + | ^ value used here after move + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0382`. From f6e29babc03d1554469d5f8cc49aec7dba162f42 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Fri, 4 Jan 2019 13:47:35 -0800 Subject: [PATCH 14/17] break eagerly from loop --- src/librustc_mir/borrow_check/error_reporting.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/librustc_mir/borrow_check/error_reporting.rs b/src/librustc_mir/borrow_check/error_reporting.rs index cbcf8c90fee41..e3fc591bda847 100644 --- a/src/librustc_mir/borrow_check/error_reporting.rs +++ b/src/librustc_mir/borrow_check/error_reporting.rs @@ -214,6 +214,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { note_msg, ty, )); note = false; + break; } } if note { From 0e2d6e017592753089a9238c7fe269e45d32d459 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Sun, 6 Jan 2019 15:23:30 -0800 Subject: [PATCH 15/17] Point at type argument suggesting adding `Copy` constraint --- src/librustc_mir/borrow_check/error_reporting.rs | 11 +++++++++++ .../ui/borrowck/two-phase-nonrecv-autoref.nll.stderr | 2 ++ src/test/ui/issues/issue-34721.stderr | 4 +++- 3 files changed, 16 insertions(+), 1 deletion(-) diff --git a/src/librustc_mir/borrow_check/error_reporting.rs b/src/librustc_mir/borrow_check/error_reporting.rs index e3fc591bda847..d8a3cf9947024 100644 --- a/src/librustc_mir/borrow_check/error_reporting.rs +++ b/src/librustc_mir/borrow_check/error_reporting.rs @@ -217,6 +217,17 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { break; } } + if let ty::TyKind::Param(param_ty) = ty.sty { + let tcx = self.infcx.tcx; + let generics = tcx.generics_of(self.mir_def_id); + let def_id = generics.type_param(¶m_ty, tcx).def_id; + if let Some(sp) = tcx.hir().span_if_local(def_id) { + err.span_label( + sp, + "consider adding a `Copy` constraint to this type argument", + ); + } + } if note { err.note(&format!( "move occurs because {} has type `{}`, \ diff --git a/src/test/ui/borrowck/two-phase-nonrecv-autoref.nll.stderr b/src/test/ui/borrowck/two-phase-nonrecv-autoref.nll.stderr index 0e99e158eda02..d026f81b7aad6 100644 --- a/src/test/ui/borrowck/two-phase-nonrecv-autoref.nll.stderr +++ b/src/test/ui/borrowck/two-phase-nonrecv-autoref.nll.stderr @@ -10,6 +10,8 @@ LL | f(f(10)); error[E0382]: use of moved value: `*f` --> $DIR/two-phase-nonrecv-autoref.rs:69:11 | +LL | fn twice_ten_so i32>(f: Box) { + | - consider adding a `Copy` constraint to this type argument LL | f(f(10)); | - ^ value used here after move | | diff --git a/src/test/ui/issues/issue-34721.stderr b/src/test/ui/issues/issue-34721.stderr index b4e274b1c7019..2ed7b543e713c 100644 --- a/src/test/ui/issues/issue-34721.stderr +++ b/src/test/ui/issues/issue-34721.stderr @@ -2,7 +2,9 @@ error[E0382]: use of moved value: `x` --> $DIR/issue-34721.rs:27:9 | LL | pub fn baz(x: T) -> T { - | - move occurs because `x` has type `T`, which does not implement the `Copy` trait + | - - move occurs because `x` has type `T`, which does not implement the `Copy` trait + | | + | consider adding a `Copy` constraint to this type argument LL | if 0 == 1 { LL | bar::bar(x.zero()) | - value moved here From 29e8e63c84a597886c10eef6d4f04a462238133a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Fri, 18 Jan 2019 15:47:25 -0800 Subject: [PATCH 16/17] review comments --- .../borrow_check/error_reporting.rs | 25 ++++++++----------- src/test/ui/borrowck/issue-41962.stderr | 5 +--- 2 files changed, 11 insertions(+), 19 deletions(-) diff --git a/src/librustc_mir/borrow_check/error_reporting.rs b/src/librustc_mir/borrow_check/error_reporting.rs index d8a3cf9947024..56b87feb82b2c 100644 --- a/src/librustc_mir/borrow_check/error_reporting.rs +++ b/src/librustc_mir/borrow_check/error_reporting.rs @@ -203,20 +203,6 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { Some(ref name) => format!("`{}`", name), None => "value".to_owned(), }; - let mut note = true; - for decl in &self.mir.local_decls { - if decl.ty == ty && decl.name.map(|x| x.to_string()) == opt_name { - err.span_label( - decl.source_info.span, - format!( - "move occurs because {} has type `{}`, \ - which does not implement the `Copy` trait", - note_msg, ty, - )); - note = false; - break; - } - } if let ty::TyKind::Param(param_ty) = ty.sty { let tcx = self.infcx.tcx; let generics = tcx.generics_of(self.mir_def_id); @@ -228,7 +214,16 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { ); } } - if note { + if let Place::Local(local) = place { + let decl = &self.mir.local_decls[*local]; + err.span_label( + decl.source_info.span, + format!( + "move occurs because {} has type `{}`, \ + which does not implement the `Copy` trait", + note_msg, ty, + )); + } else { err.note(&format!( "move occurs because {} has type `{}`, \ which does not implement the `Copy` trait", diff --git a/src/test/ui/borrowck/issue-41962.stderr b/src/test/ui/borrowck/issue-41962.stderr index 3c0071f6b3745..fd4d318b5ddf1 100644 --- a/src/test/ui/borrowck/issue-41962.stderr +++ b/src/test/ui/borrowck/issue-41962.stderr @@ -19,13 +19,10 @@ LL | if let Some(thing) = maybe { error[E0382]: use of moved value (Mir) --> $DIR/issue-41962.rs:7:21 | -LL | let maybe = Some(vec![true, true]); - | ---------------- move occurs because value has type `std::vec::Vec`, which does not implement the `Copy` trait -... LL | if let Some(thing) = maybe { | ^^^^^ value moved here, in previous iteration of loop | - = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) + = note: move occurs because value has type `std::vec::Vec`, which does not implement the `Copy` trait error: aborting due to 3 previous errors From baa0828ee35475987fd825d8eaf77e009dca2bbe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Thu, 24 Jan 2019 10:53:43 -0800 Subject: [PATCH 17/17] Fix --compare-mode=nll tests --- .../ui/binop/binop-consume-args.nll.stderr | 253 ++++++++++++++++++ .../ui/binop/binop-move-semantics.nll.stderr | 12 +- .../ui/borrowck/borrowck-asm.ast.nll.stderr | 10 +- .../borrowck-consume-unsize-vec.nll.stderr | 13 + .../borrowck-consume-upcast-box.nll.stderr | 4 +- .../borrowck-loan-in-overloaded-op.nll.stderr | 4 +- ...ve-moved-value-into-closure.ast.nll.stderr | 5 +- .../borrowck-multiple-captures.nll.stderr | 12 +- .../borrowck-overloaded-call.nll.stderr | 5 +- ...wck-overloaded-index-move-index.nll.stderr | 5 +- .../borrowck-partial-reinit-1.nll.stderr | 10 +- .../borrowck-partial-reinit-2.nll.stderr | 4 +- .../borrowck-unboxed-closures.nll.stderr | 6 +- .../borrowck-union-move-assign.nll.stderr | 4 +- .../borrowck/borrowck-union-move.nll.stderr | 24 +- .../two-phase-nonrecv-autoref.ast.nll.stderr | 2 + src/test/ui/codemap_tests/tab_3.nll.stderr | 4 +- src/test/ui/issues/issue-17385.nll.stderr | 8 +- src/test/ui/issues/issue-24357.nll.stderr | 4 +- src/test/ui/issues/issue-25700.nll.stderr | 13 + src/test/ui/issues/issue-42796.nll.stderr | 4 +- .../liveness-move-call-arg.nll.stderr | 5 +- .../liveness/liveness-move-in-loop.nll.stderr | 5 +- .../liveness-move-in-while.nll.stderr | 5 +- .../liveness-use-after-move.nll.stderr | 4 +- .../liveness-use-after-send.nll.stderr | 4 +- .../moves/move-guard-same-consts.nll.stderr | 14 + src/test/ui/moves/move-in-guard-1.nll.stderr | 14 + src/test/ui/moves/move-in-guard-2.nll.stderr | 5 +- .../moves/move-into-dead-array-2.nll.stderr | 4 +- ...s-based-on-type-access-to-field.nll.stderr | 4 +- ...ased-on-type-capture-clause-bad.nll.stderr | 4 +- ...type-distribute-copy-over-paren.nll.stderr | 8 +- .../moves-based-on-type-exprs.nll.stderr | 49 ++-- ...type-no-recursive-stack-closure.nll.stderr | 6 +- src/test/ui/no-capture-arc.nll.stderr | 5 +- src/test/ui/no-reuse-move-arc.nll.stderr | 5 +- .../once-cant-call-twice-on-heap.nll.stderr | 15 ++ src/test/ui/ref-suggestion.nll.stderr | 8 +- .../dbg-macro-move-semantics.nll.stderr | 3 +- ...nion-borrow-move-parent-sibling.nll.stderr | 12 +- src/test/ui/unop-move-semantics.nll.stderr | 6 +- .../borrow-after-move.nll.stderr | 8 +- .../ui/unsized-locals/double-move.nll.stderr | 12 +- .../use-after-move-based-on-type.nll.stderr | 4 +- ...r-move-implicity-coerced-object.nll.stderr | 5 +- ...e-after-move-self-based-on-type.nll.stderr | 4 +- .../ui/use/use-after-move-self.nll.stderr | 4 +- .../ui/walk-struct-literal-with.nll.stderr | 4 +- 49 files changed, 493 insertions(+), 139 deletions(-) create mode 100644 src/test/ui/binop/binop-consume-args.nll.stderr create mode 100644 src/test/ui/borrowck/borrowck-consume-unsize-vec.nll.stderr create mode 100644 src/test/ui/issues/issue-25700.nll.stderr create mode 100644 src/test/ui/moves/move-guard-same-consts.nll.stderr create mode 100644 src/test/ui/moves/move-in-guard-1.nll.stderr create mode 100644 src/test/ui/once-cant-call-twice-on-heap.nll.stderr diff --git a/src/test/ui/binop/binop-consume-args.nll.stderr b/src/test/ui/binop/binop-consume-args.nll.stderr new file mode 100644 index 0000000000000..59b5aba93cad4 --- /dev/null +++ b/src/test/ui/binop/binop-consume-args.nll.stderr @@ -0,0 +1,253 @@ +error[E0382]: use of moved value: `lhs` + --> $DIR/binop-consume-args.rs:7:10 + | +LL | fn add, B>(lhs: A, rhs: B) { + | - --- move occurs because `lhs` has type `A`, which does not implement the `Copy` trait + | | + | consider adding a `Copy` constraint to this type argument +LL | lhs + rhs; + | --- value moved here +LL | drop(lhs); //~ ERROR use of moved value: `lhs` + | ^^^ value used here after move + +error[E0382]: use of moved value: `rhs` + --> $DIR/binop-consume-args.rs:8:10 + | +LL | fn add, B>(lhs: A, rhs: B) { + | - --- move occurs because `rhs` has type `B`, which does not implement the `Copy` trait + | | + | consider adding a `Copy` constraint to this type argument +LL | lhs + rhs; + | --- value moved here +LL | drop(lhs); //~ ERROR use of moved value: `lhs` +LL | drop(rhs); //~ ERROR use of moved value: `rhs` + | ^^^ value used here after move + +error[E0382]: use of moved value: `lhs` + --> $DIR/binop-consume-args.rs:13:10 + | +LL | fn sub, B>(lhs: A, rhs: B) { + | - --- move occurs because `lhs` has type `A`, which does not implement the `Copy` trait + | | + | consider adding a `Copy` constraint to this type argument +LL | lhs - rhs; + | --- value moved here +LL | drop(lhs); //~ ERROR use of moved value: `lhs` + | ^^^ value used here after move + +error[E0382]: use of moved value: `rhs` + --> $DIR/binop-consume-args.rs:14:10 + | +LL | fn sub, B>(lhs: A, rhs: B) { + | - --- move occurs because `rhs` has type `B`, which does not implement the `Copy` trait + | | + | consider adding a `Copy` constraint to this type argument +LL | lhs - rhs; + | --- value moved here +LL | drop(lhs); //~ ERROR use of moved value: `lhs` +LL | drop(rhs); //~ ERROR use of moved value: `rhs` + | ^^^ value used here after move + +error[E0382]: use of moved value: `lhs` + --> $DIR/binop-consume-args.rs:19:10 + | +LL | fn mul, B>(lhs: A, rhs: B) { + | - --- move occurs because `lhs` has type `A`, which does not implement the `Copy` trait + | | + | consider adding a `Copy` constraint to this type argument +LL | lhs * rhs; + | --- value moved here +LL | drop(lhs); //~ ERROR use of moved value: `lhs` + | ^^^ value used here after move + +error[E0382]: use of moved value: `rhs` + --> $DIR/binop-consume-args.rs:20:10 + | +LL | fn mul, B>(lhs: A, rhs: B) { + | - --- move occurs because `rhs` has type `B`, which does not implement the `Copy` trait + | | + | consider adding a `Copy` constraint to this type argument +LL | lhs * rhs; + | --- value moved here +LL | drop(lhs); //~ ERROR use of moved value: `lhs` +LL | drop(rhs); //~ ERROR use of moved value: `rhs` + | ^^^ value used here after move + +error[E0382]: use of moved value: `lhs` + --> $DIR/binop-consume-args.rs:25:10 + | +LL | fn div, B>(lhs: A, rhs: B) { + | - --- move occurs because `lhs` has type `A`, which does not implement the `Copy` trait + | | + | consider adding a `Copy` constraint to this type argument +LL | lhs / rhs; + | --- value moved here +LL | drop(lhs); //~ ERROR use of moved value: `lhs` + | ^^^ value used here after move + +error[E0382]: use of moved value: `rhs` + --> $DIR/binop-consume-args.rs:26:10 + | +LL | fn div, B>(lhs: A, rhs: B) { + | - --- move occurs because `rhs` has type `B`, which does not implement the `Copy` trait + | | + | consider adding a `Copy` constraint to this type argument +LL | lhs / rhs; + | --- value moved here +LL | drop(lhs); //~ ERROR use of moved value: `lhs` +LL | drop(rhs); //~ ERROR use of moved value: `rhs` + | ^^^ value used here after move + +error[E0382]: use of moved value: `lhs` + --> $DIR/binop-consume-args.rs:31:10 + | +LL | fn rem, B>(lhs: A, rhs: B) { + | - --- move occurs because `lhs` has type `A`, which does not implement the `Copy` trait + | | + | consider adding a `Copy` constraint to this type argument +LL | lhs % rhs; + | --- value moved here +LL | drop(lhs); //~ ERROR use of moved value: `lhs` + | ^^^ value used here after move + +error[E0382]: use of moved value: `rhs` + --> $DIR/binop-consume-args.rs:32:10 + | +LL | fn rem, B>(lhs: A, rhs: B) { + | - --- move occurs because `rhs` has type `B`, which does not implement the `Copy` trait + | | + | consider adding a `Copy` constraint to this type argument +LL | lhs % rhs; + | --- value moved here +LL | drop(lhs); //~ ERROR use of moved value: `lhs` +LL | drop(rhs); //~ ERROR use of moved value: `rhs` + | ^^^ value used here after move + +error[E0382]: use of moved value: `lhs` + --> $DIR/binop-consume-args.rs:37:10 + | +LL | fn bitand, B>(lhs: A, rhs: B) { + | - --- move occurs because `lhs` has type `A`, which does not implement the `Copy` trait + | | + | consider adding a `Copy` constraint to this type argument +LL | lhs & rhs; + | --- value moved here +LL | drop(lhs); //~ ERROR use of moved value: `lhs` + | ^^^ value used here after move + +error[E0382]: use of moved value: `rhs` + --> $DIR/binop-consume-args.rs:38:10 + | +LL | fn bitand, B>(lhs: A, rhs: B) { + | - --- move occurs because `rhs` has type `B`, which does not implement the `Copy` trait + | | + | consider adding a `Copy` constraint to this type argument +LL | lhs & rhs; + | --- value moved here +LL | drop(lhs); //~ ERROR use of moved value: `lhs` +LL | drop(rhs); //~ ERROR use of moved value: `rhs` + | ^^^ value used here after move + +error[E0382]: use of moved value: `lhs` + --> $DIR/binop-consume-args.rs:43:10 + | +LL | fn bitor, B>(lhs: A, rhs: B) { + | - --- move occurs because `lhs` has type `A`, which does not implement the `Copy` trait + | | + | consider adding a `Copy` constraint to this type argument +LL | lhs | rhs; + | --- value moved here +LL | drop(lhs); //~ ERROR use of moved value: `lhs` + | ^^^ value used here after move + +error[E0382]: use of moved value: `rhs` + --> $DIR/binop-consume-args.rs:44:10 + | +LL | fn bitor, B>(lhs: A, rhs: B) { + | - --- move occurs because `rhs` has type `B`, which does not implement the `Copy` trait + | | + | consider adding a `Copy` constraint to this type argument +LL | lhs | rhs; + | --- value moved here +LL | drop(lhs); //~ ERROR use of moved value: `lhs` +LL | drop(rhs); //~ ERROR use of moved value: `rhs` + | ^^^ value used here after move + +error[E0382]: use of moved value: `lhs` + --> $DIR/binop-consume-args.rs:49:10 + | +LL | fn bitxor, B>(lhs: A, rhs: B) { + | - --- move occurs because `lhs` has type `A`, which does not implement the `Copy` trait + | | + | consider adding a `Copy` constraint to this type argument +LL | lhs ^ rhs; + | --- value moved here +LL | drop(lhs); //~ ERROR use of moved value: `lhs` + | ^^^ value used here after move + +error[E0382]: use of moved value: `rhs` + --> $DIR/binop-consume-args.rs:50:10 + | +LL | fn bitxor, B>(lhs: A, rhs: B) { + | - --- move occurs because `rhs` has type `B`, which does not implement the `Copy` trait + | | + | consider adding a `Copy` constraint to this type argument +LL | lhs ^ rhs; + | --- value moved here +LL | drop(lhs); //~ ERROR use of moved value: `lhs` +LL | drop(rhs); //~ ERROR use of moved value: `rhs` + | ^^^ value used here after move + +error[E0382]: use of moved value: `lhs` + --> $DIR/binop-consume-args.rs:55:10 + | +LL | fn shl, B>(lhs: A, rhs: B) { + | - --- move occurs because `lhs` has type `A`, which does not implement the `Copy` trait + | | + | consider adding a `Copy` constraint to this type argument +LL | lhs << rhs; + | --- value moved here +LL | drop(lhs); //~ ERROR use of moved value: `lhs` + | ^^^ value used here after move + +error[E0382]: use of moved value: `rhs` + --> $DIR/binop-consume-args.rs:56:10 + | +LL | fn shl, B>(lhs: A, rhs: B) { + | - --- move occurs because `rhs` has type `B`, which does not implement the `Copy` trait + | | + | consider adding a `Copy` constraint to this type argument +LL | lhs << rhs; + | --- value moved here +LL | drop(lhs); //~ ERROR use of moved value: `lhs` +LL | drop(rhs); //~ ERROR use of moved value: `rhs` + | ^^^ value used here after move + +error[E0382]: use of moved value: `lhs` + --> $DIR/binop-consume-args.rs:61:10 + | +LL | fn shr, B>(lhs: A, rhs: B) { + | - --- move occurs because `lhs` has type `A`, which does not implement the `Copy` trait + | | + | consider adding a `Copy` constraint to this type argument +LL | lhs >> rhs; + | --- value moved here +LL | drop(lhs); //~ ERROR use of moved value: `lhs` + | ^^^ value used here after move + +error[E0382]: use of moved value: `rhs` + --> $DIR/binop-consume-args.rs:62:10 + | +LL | fn shr, B>(lhs: A, rhs: B) { + | - --- move occurs because `rhs` has type `B`, which does not implement the `Copy` trait + | | + | consider adding a `Copy` constraint to this type argument +LL | lhs >> rhs; + | --- value moved here +LL | drop(lhs); //~ ERROR use of moved value: `lhs` +LL | drop(rhs); //~ ERROR use of moved value: `rhs` + | ^^^ value used here after move + +error: aborting due to 20 previous errors + +For more information about this error, try `rustc --explain E0382`. diff --git a/src/test/ui/binop/binop-move-semantics.nll.stderr b/src/test/ui/binop/binop-move-semantics.nll.stderr index 950772dc75c9e..7c84e8833a9e6 100644 --- a/src/test/ui/binop/binop-move-semantics.nll.stderr +++ b/src/test/ui/binop/binop-move-semantics.nll.stderr @@ -1,24 +1,28 @@ error[E0382]: use of moved value: `x` --> $DIR/binop-move-semantics.rs:8:5 | +LL | fn double_move>(x: T) { + | - - move occurs because `x` has type `T`, which does not implement the `Copy` trait + | | + | consider adding a `Copy` constraint to this type argument LL | x | - value moved here LL | + LL | x; //~ ERROR: use of moved value | ^ value used here after move - | - = note: move occurs because `x` has type `T`, which does not implement the `Copy` trait error[E0382]: borrow of moved value: `x` --> $DIR/binop-move-semantics.rs:14:5 | +LL | fn move_then_borrow + Clone>(x: T) { + | - - move occurs because `x` has type `T`, which does not implement the `Copy` trait + | | + | consider adding a `Copy` constraint to this type argument LL | x | - value moved here LL | + LL | x.clone(); //~ ERROR: use of moved value | ^ value borrowed here after move - | - = note: move occurs because `x` has type `T`, which does not implement the `Copy` trait error[E0505]: cannot move out of `x` because it is borrowed --> $DIR/binop-move-semantics.rs:21:5 diff --git a/src/test/ui/borrowck/borrowck-asm.ast.nll.stderr b/src/test/ui/borrowck/borrowck-asm.ast.nll.stderr index 9c47845a52830..86e4832b3873c 100644 --- a/src/test/ui/borrowck/borrowck-asm.ast.nll.stderr +++ b/src/test/ui/borrowck/borrowck-asm.ast.nll.stderr @@ -1,13 +1,14 @@ error[E0382]: use of moved value: `x` --> $DIR/borrowck-asm.rs:27:17 | +LL | let x = &mut 0isize; + | - move occurs because `x` has type `&mut isize`, which does not implement the `Copy` trait +LL | unsafe { LL | asm!("nop" : : "r"(x)); | - value moved here LL | } LL | let z = x; //[ast]~ ERROR use of moved value: `x` | ^ value used here after move - | - = note: move occurs because `x` has type `&mut isize`, which does not implement the `Copy` trait error[E0503]: cannot use `x` because it was mutably borrowed --> $DIR/borrowck-asm.rs:35:32 @@ -66,12 +67,13 @@ LL | let z = y; error[E0382]: use of moved value: `x` --> $DIR/borrowck-asm.rs:86:40 | +LL | let x = &mut 2; + | - move occurs because `x` has type `&mut i32`, which does not implement the `Copy` trait +LL | unsafe { LL | asm!("nop" : : "r"(x), "r"(x) ); //[ast]~ ERROR use of moved value | - ^ value used here after move | | | value moved here - | - = note: move occurs because `x` has type `&mut i32`, which does not implement the `Copy` trait error: aborting due to 7 previous errors diff --git a/src/test/ui/borrowck/borrowck-consume-unsize-vec.nll.stderr b/src/test/ui/borrowck/borrowck-consume-unsize-vec.nll.stderr new file mode 100644 index 0000000000000..ea7683a91adfe --- /dev/null +++ b/src/test/ui/borrowck/borrowck-consume-unsize-vec.nll.stderr @@ -0,0 +1,13 @@ +error[E0382]: use of moved value: `b` + --> $DIR/borrowck-consume-unsize-vec.rs:8:13 + | +LL | fn foo(b: Box<[i32;5]>) { + | - move occurs because `b` has type `std::boxed::Box<[i32; 5]>`, which does not implement the `Copy` trait +LL | consume(b); + | - value moved here +LL | consume(b); //~ ERROR use of moved value + | ^ value used here after move + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0382`. diff --git a/src/test/ui/borrowck/borrowck-consume-upcast-box.nll.stderr b/src/test/ui/borrowck/borrowck-consume-upcast-box.nll.stderr index 7357d0973dbc0..15cf359326be9 100644 --- a/src/test/ui/borrowck/borrowck-consume-upcast-box.nll.stderr +++ b/src/test/ui/borrowck/borrowck-consume-upcast-box.nll.stderr @@ -1,12 +1,12 @@ error[E0382]: use of moved value: `b` --> $DIR/borrowck-consume-upcast-box.rs:10:13 | +LL | fn foo(b: Box) { + | - move occurs because `b` has type `std::boxed::Box`, which does not implement the `Copy` trait LL | consume(b); | - value moved here LL | consume(b); //~ ERROR use of moved value | ^ value used here after move - | - = note: move occurs because `b` has type `std::boxed::Box`, which does not implement the `Copy` trait error: aborting due to previous error diff --git a/src/test/ui/borrowck/borrowck-loan-in-overloaded-op.nll.stderr b/src/test/ui/borrowck/borrowck-loan-in-overloaded-op.nll.stderr index 72d2d1fe59f66..095ae7f56b22e 100644 --- a/src/test/ui/borrowck/borrowck-loan-in-overloaded-op.nll.stderr +++ b/src/test/ui/borrowck/borrowck-loan-in-overloaded-op.nll.stderr @@ -1,12 +1,12 @@ error[E0382]: borrow of moved value: `x` --> $DIR/borrowck-loan-in-overloaded-op.rs:21:20 | +LL | let x = Foo(box 3); + | - move occurs because `x` has type `Foo`, which does not implement the `Copy` trait LL | let _y = {x} + x.clone(); // the `{x}` forces a move to occur | - ^ value borrowed here after move | | | value moved here - | - = note: move occurs because `x` has type `Foo`, which does not implement the `Copy` trait error: aborting due to previous error diff --git a/src/test/ui/borrowck/borrowck-move-moved-value-into-closure.ast.nll.stderr b/src/test/ui/borrowck/borrowck-move-moved-value-into-closure.ast.nll.stderr index 24b9b4338a58c..0789926563ce7 100644 --- a/src/test/ui/borrowck/borrowck-move-moved-value-into-closure.ast.nll.stderr +++ b/src/test/ui/borrowck/borrowck-move-moved-value-into-closure.ast.nll.stderr @@ -1,6 +1,9 @@ error[E0382]: use of moved value: `t` --> $DIR/borrowck-move-moved-value-into-closure.rs:14:12 | +LL | let t: Box<_> = box 3; + | - move occurs because `t` has type `std::boxed::Box`, which does not implement the `Copy` trait +LL | LL | call_f(move|| { *t + 1 }); | ------ - variable moved due to use in closure | | @@ -9,8 +12,6 @@ LL | call_f(move|| { *t + 1 }); //[ast]~ ERROR capture of moved value | ^^^^^^ - use occurs due to use in closure | | | value used here after move - | - = note: move occurs because `t` has type `std::boxed::Box`, which does not implement the `Copy` trait error: aborting due to previous error diff --git a/src/test/ui/borrowck/borrowck-multiple-captures.nll.stderr b/src/test/ui/borrowck/borrowck-multiple-captures.nll.stderr index 6f4cad2a01e48..d0065a2e7dc3d 100644 --- a/src/test/ui/borrowck/borrowck-multiple-captures.nll.stderr +++ b/src/test/ui/borrowck/borrowck-multiple-captures.nll.stderr @@ -29,6 +29,8 @@ LL | borrow(&*p2); error[E0382]: use of moved value: `x1` --> $DIR/borrowck-multiple-captures.rs:25:19 | +LL | let x1: Box<_> = box 1; + | -- move occurs because `x1` has type `std::boxed::Box`, which does not implement the `Copy` trait LL | drop(x1); | -- value moved here ... @@ -36,12 +38,12 @@ LL | thread::spawn(move|| { | ^^^^^^ value used here after move LL | drop(x1); //~ ERROR capture of moved value: `x1` | -- use occurs due to use in closure - | - = note: move occurs because `x1` has type `std::boxed::Box`, which does not implement the `Copy` trait error[E0382]: use of moved value: `x2` --> $DIR/borrowck-multiple-captures.rs:25:19 | +LL | let x2: Box<_> = box 2; + | -- move occurs because `x2` has type `std::boxed::Box`, which does not implement the `Copy` trait LL | drop(x2); | -- value moved here LL | thread::spawn(move|| { @@ -49,8 +51,6 @@ LL | thread::spawn(move|| { LL | drop(x1); //~ ERROR capture of moved value: `x1` LL | drop(x2); //~ ERROR capture of moved value: `x2` | -- use occurs due to use in closure - | - = note: move occurs because `x2` has type `std::boxed::Box`, which does not implement the `Copy` trait error[E0382]: use of moved value: `x` --> $DIR/borrowck-multiple-captures.rs:36:14 @@ -88,14 +88,14 @@ LL | drop(x); //~ ERROR use of moved value: `x` error[E0382]: use of moved value: `x` --> $DIR/borrowck-multiple-captures.rs:44:19 | +LL | let x: Box<_> = box 1; + | - move occurs because `x` has type `std::boxed::Box`, which does not implement the `Copy` trait LL | drop(x); | - value moved here LL | thread::spawn(move|| { | ^^^^^^ value used here after move LL | drop(x); //~ ERROR capture of moved value: `x` | - use occurs due to use in closure - | - = note: move occurs because `x` has type `std::boxed::Box`, which does not implement the `Copy` trait error: aborting due to 8 previous errors diff --git a/src/test/ui/borrowck/borrowck-overloaded-call.nll.stderr b/src/test/ui/borrowck/borrowck-overloaded-call.nll.stderr index 1b4a6610ab1a4..c5a4c4e005aa7 100644 --- a/src/test/ui/borrowck/borrowck-overloaded-call.nll.stderr +++ b/src/test/ui/borrowck/borrowck-overloaded-call.nll.stderr @@ -20,12 +20,13 @@ LL | s(3); //~ ERROR cannot borrow immutable local variable `s` as mutable error[E0382]: use of moved value: `s` --> $DIR/borrowck-overloaded-call.rs:75:5 | +LL | let s = SFnOnce { + | - move occurs because `s` has type `SFnOnce`, which does not implement the `Copy` trait +... LL | s(" world".to_string()); | - value moved here LL | s(" world".to_string()); //~ ERROR use of moved value: `s` | ^ value used here after move - | - = note: move occurs because `s` has type `SFnOnce`, which does not implement the `Copy` trait error: aborting due to 3 previous errors diff --git a/src/test/ui/borrowck/borrowck-overloaded-index-move-index.nll.stderr b/src/test/ui/borrowck/borrowck-overloaded-index-move-index.nll.stderr index a19baa167de91..de60067f1a613 100644 --- a/src/test/ui/borrowck/borrowck-overloaded-index-move-index.nll.stderr +++ b/src/test/ui/borrowck/borrowck-overloaded-index-move-index.nll.stderr @@ -25,13 +25,14 @@ LL | use_mut(rs); error[E0382]: use of moved value: `s` --> $DIR/borrowck-overloaded-index-move-index.rs:53:7 | +LL | let mut s = "hello".to_string(); + | ----- move occurs because `s` has type `std::string::String`, which does not implement the `Copy` trait +... LL | println!("{}", f[s]); | - value moved here ... LL | f[s] = 10; | ^ value used here after move - | - = note: move occurs because `s` has type `std::string::String`, which does not implement the `Copy` trait error: aborting due to 3 previous errors diff --git a/src/test/ui/borrowck/borrowck-partial-reinit-1.nll.stderr b/src/test/ui/borrowck/borrowck-partial-reinit-1.nll.stderr index 09a85bd7c13a9..65f2bd6cfbda9 100644 --- a/src/test/ui/borrowck/borrowck-partial-reinit-1.nll.stderr +++ b/src/test/ui/borrowck/borrowck-partial-reinit-1.nll.stderr @@ -1,22 +1,24 @@ error[E0382]: assign of moved value: `t` --> $DIR/borrowck-partial-reinit-1.rs:27:5 | +LL | let mut t = Test2 { b: None }; + | ----- move occurs because `t` has type `Test2`, which does not implement the `Copy` trait +LL | let u = Test; LL | drop(t); | - value moved here LL | t.b = Some(u); | ^^^ value assigned here after move - | - = note: move occurs because `t` has type `Test2`, which does not implement the `Copy` trait error[E0382]: assign of moved value: `t` --> $DIR/borrowck-partial-reinit-1.rs:33:5 | +LL | let mut t = Test3(None); + | ----- move occurs because `t` has type `Test3`, which does not implement the `Copy` trait +LL | let u = Test; LL | drop(t); | - value moved here LL | t.0 = Some(u); | ^^^ value assigned here after move - | - = note: move occurs because `t` has type `Test3`, which does not implement the `Copy` trait error: aborting due to 2 previous errors diff --git a/src/test/ui/borrowck/borrowck-partial-reinit-2.nll.stderr b/src/test/ui/borrowck/borrowck-partial-reinit-2.nll.stderr index 03608a1b99d24..36a871fbb12a1 100644 --- a/src/test/ui/borrowck/borrowck-partial-reinit-2.nll.stderr +++ b/src/test/ui/borrowck/borrowck-partial-reinit-2.nll.stderr @@ -1,12 +1,12 @@ error[E0382]: assign of moved value: `t` --> $DIR/borrowck-partial-reinit-2.rs:15:5 | +LL | let mut t = Test { a: 1, b: None}; + | ----- move occurs because `t` has type `Test`, which does not implement the `Copy` trait LL | let mut u = Test { a: 2, b: Some(Box::new(t))}; | - value moved here LL | t.b = Some(Box::new(u)); | ^^^ value assigned here after move - | - = note: move occurs because `t` has type `Test`, which does not implement the `Copy` trait error: aborting due to previous error diff --git a/src/test/ui/borrowck/borrowck-unboxed-closures.nll.stderr b/src/test/ui/borrowck/borrowck-unboxed-closures.nll.stderr index 86baa0db96121..363a5a69a07e3 100644 --- a/src/test/ui/borrowck/borrowck-unboxed-closures.nll.stderr +++ b/src/test/ui/borrowck/borrowck-unboxed-closures.nll.stderr @@ -19,12 +19,14 @@ LL | f(1, 2); //~ ERROR cannot borrow immutable argument error[E0382]: use of moved value: `f` --> $DIR/borrowck-unboxed-closures.rs:12:5 | +LL | fn c isize>(f: F) { + | - - move occurs because `f` has type `F`, which does not implement the `Copy` trait + | | + | consider adding a `Copy` constraint to this type argument LL | f(1, 2); | - value moved here LL | f(1, 2); //~ ERROR use of moved value | ^ value used here after move - | - = note: move occurs because `f` has type `F`, which does not implement the `Copy` trait error: aborting due to 3 previous errors diff --git a/src/test/ui/borrowck/borrowck-union-move-assign.nll.stderr b/src/test/ui/borrowck/borrowck-union-move-assign.nll.stderr index bf0d0a45fcff7..e59fef2dc0d2f 100644 --- a/src/test/ui/borrowck/borrowck-union-move-assign.nll.stderr +++ b/src/test/ui/borrowck/borrowck-union-move-assign.nll.stderr @@ -1,12 +1,12 @@ error[E0382]: use of moved value: `u` --> $DIR/borrowck-union-move-assign.rs:17:21 | +LL | let mut u = U { a: A }; + | ----- move occurs because `u` has type `U`, which does not implement the `Copy` trait LL | let a = u.a; | --- value moved here LL | let a = u.a; //~ ERROR use of moved value: `u.a` | ^^^ value used here after move - | - = note: move occurs because `u` has type `U`, which does not implement the `Copy` trait error: aborting due to previous error diff --git a/src/test/ui/borrowck/borrowck-union-move.nll.stderr b/src/test/ui/borrowck/borrowck-union-move.nll.stderr index fd90fc47a218d..1392a7931c30a 100644 --- a/src/test/ui/borrowck/borrowck-union-move.nll.stderr +++ b/src/test/ui/borrowck/borrowck-union-move.nll.stderr @@ -1,62 +1,62 @@ error[E0382]: use of moved value: `u` --> $DIR/borrowck-union-move.rs:26:21 | +LL | let mut u = Unn { n1: NonCopy }; + | ----- move occurs because `u` has type `Unn`, which does not implement the `Copy` trait LL | let a = u.n1; | ---- value moved here LL | let a = u.n1; //~ ERROR use of moved value: `u.n1` | ^^^^ value used here after move - | - = note: move occurs because `u` has type `Unn`, which does not implement the `Copy` trait error[E0382]: use of moved value: `u` --> $DIR/borrowck-union-move.rs:31:21 | +LL | let mut u = Unn { n1: NonCopy }; + | ----- move occurs because `u` has type `Unn`, which does not implement the `Copy` trait LL | let a = u.n1; | ---- value moved here LL | let a = u; //~ ERROR use of partially moved value: `u` | ^ value used here after move - | - = note: move occurs because `u` has type `Unn`, which does not implement the `Copy` trait error[E0382]: use of moved value: `u` --> $DIR/borrowck-union-move.rs:36:21 | +LL | let mut u = Unn { n1: NonCopy }; + | ----- move occurs because `u` has type `Unn`, which does not implement the `Copy` trait LL | let a = u.n1; | ---- value moved here LL | let a = u.n2; //~ ERROR use of moved value: `u.n2` | ^^^^ value used here after move - | - = note: move occurs because `u` has type `Unn`, which does not implement the `Copy` trait error[E0382]: use of moved value: `u` --> $DIR/borrowck-union-move.rs:63:21 | +LL | let mut u = Ucn { c: Copy }; + | ----- move occurs because `u` has type `Ucn`, which does not implement the `Copy` trait LL | let a = u.n; | --- value moved here LL | let a = u.n; //~ ERROR use of moved value: `u.n` | ^^^ value used here after move - | - = note: move occurs because `u` has type `Ucn`, which does not implement the `Copy` trait error[E0382]: use of moved value: `u` --> $DIR/borrowck-union-move.rs:68:21 | +LL | let mut u = Ucn { c: Copy }; + | ----- move occurs because `u` has type `Ucn`, which does not implement the `Copy` trait LL | let a = u.n; | --- value moved here LL | let a = u.c; //~ ERROR use of moved value: `u.c` | ^^^ value used here after move - | - = note: move occurs because `u` has type `Ucn`, which does not implement the `Copy` trait error[E0382]: use of moved value: `u` --> $DIR/borrowck-union-move.rs:83:21 | +LL | let mut u = Ucn { c: Copy }; + | ----- move occurs because `u` has type `Ucn`, which does not implement the `Copy` trait LL | let a = u.n; | --- value moved here LL | let a = u; //~ ERROR use of partially moved value: `u` | ^ value used here after move - | - = note: move occurs because `u` has type `Ucn`, which does not implement the `Copy` trait error: aborting due to 6 previous errors diff --git a/src/test/ui/borrowck/two-phase-nonrecv-autoref.ast.nll.stderr b/src/test/ui/borrowck/two-phase-nonrecv-autoref.ast.nll.stderr index 0e99e158eda02..d026f81b7aad6 100644 --- a/src/test/ui/borrowck/two-phase-nonrecv-autoref.ast.nll.stderr +++ b/src/test/ui/borrowck/two-phase-nonrecv-autoref.ast.nll.stderr @@ -10,6 +10,8 @@ LL | f(f(10)); error[E0382]: use of moved value: `*f` --> $DIR/two-phase-nonrecv-autoref.rs:69:11 | +LL | fn twice_ten_so i32>(f: Box) { + | - consider adding a `Copy` constraint to this type argument LL | f(f(10)); | - ^ value used here after move | | diff --git a/src/test/ui/codemap_tests/tab_3.nll.stderr b/src/test/ui/codemap_tests/tab_3.nll.stderr index 55117ff2b1876..3b8507a067ded 100644 --- a/src/test/ui/codemap_tests/tab_3.nll.stderr +++ b/src/test/ui/codemap_tests/tab_3.nll.stderr @@ -1,13 +1,13 @@ error[E0382]: borrow of moved value: `some_vec` --> $DIR/tab_3.rs:7:20 | +LL | let some_vec = vec!["hi"]; + | -------- move occurs because `some_vec` has type `std::vec::Vec<&str>`, which does not implement the `Copy` trait LL | some_vec.into_iter(); | -------- value moved here LL | { LL | println!("{:?}", some_vec); //~ ERROR use of moved | ^^^^^^^^ value borrowed here after move - | - = note: move occurs because `some_vec` has type `std::vec::Vec<&str>`, which does not implement the `Copy` trait error: aborting due to previous error diff --git a/src/test/ui/issues/issue-17385.nll.stderr b/src/test/ui/issues/issue-17385.nll.stderr index 24080a3b387f2..20198f19dd5f5 100644 --- a/src/test/ui/issues/issue-17385.nll.stderr +++ b/src/test/ui/issues/issue-17385.nll.stderr @@ -1,23 +1,23 @@ error[E0382]: use of moved value: `foo` --> $DIR/issue-17385.rs:19:11 | +LL | let foo = X(1); + | --- move occurs because `foo` has type `X`, which does not implement the `Copy` trait LL | drop(foo); | --- value moved here LL | match foo { //~ ERROR use of moved value LL | X(1) => (), | ^ value used here after move - | - = note: move occurs because `foo` has type `X`, which does not implement the `Copy` trait error[E0382]: use of moved value: `e` --> $DIR/issue-17385.rs:25:11 | +LL | let e = Enum::Variant2; + | - move occurs because `e` has type `Enum`, which does not implement the `Copy` trait LL | drop(e); | - value moved here LL | match e { //~ ERROR use of moved value | ^ value used here after move - | - = note: move occurs because `e` has type `Enum`, which does not implement the `Copy` trait error: aborting due to 2 previous errors diff --git a/src/test/ui/issues/issue-24357.nll.stderr b/src/test/ui/issues/issue-24357.nll.stderr index 06de9537af031..310535434cd08 100644 --- a/src/test/ui/issues/issue-24357.nll.stderr +++ b/src/test/ui/issues/issue-24357.nll.stderr @@ -1,6 +1,8 @@ error[E0382]: use of moved value: `x` --> $DIR/issue-24357.rs:6:12 | +LL | let x = NoCopy; + | - move occurs because `x` has type `NoCopy`, which does not implement the `Copy` trait LL | let f = move || { let y = x; }; | ------- - variable moved due to use in closure | | @@ -8,8 +10,6 @@ LL | let f = move || { let y = x; }; LL | //~^ NOTE value moved (into closure) here LL | let z = x; | ^ value used here after move - | - = note: move occurs because `x` has type `NoCopy`, which does not implement the `Copy` trait error: aborting due to previous error diff --git a/src/test/ui/issues/issue-25700.nll.stderr b/src/test/ui/issues/issue-25700.nll.stderr new file mode 100644 index 0000000000000..ba5403cca4d06 --- /dev/null +++ b/src/test/ui/issues/issue-25700.nll.stderr @@ -0,0 +1,13 @@ +error[E0382]: use of moved value: `t` + --> $DIR/issue-25700.rs:13:10 + | +LL | let t = S::<()>(None); + | - move occurs because `t` has type `S<()>`, which does not implement the `Copy` trait +LL | drop(t); + | - value moved here +LL | drop(t); //~ ERROR use of moved value + | ^ value used here after move + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0382`. diff --git a/src/test/ui/issues/issue-42796.nll.stderr b/src/test/ui/issues/issue-42796.nll.stderr index 19c6a1fd557b4..23cc88bab52d5 100644 --- a/src/test/ui/issues/issue-42796.nll.stderr +++ b/src/test/ui/issues/issue-42796.nll.stderr @@ -1,13 +1,13 @@ error[E0382]: borrow of moved value: `s` --> $DIR/issue-42796.rs:18:20 | +LL | let s = "Hello!".to_owned(); + | - move occurs because `s` has type `std::string::String`, which does not implement the `Copy` trait LL | let mut s_copy = s; | - value moved here ... LL | println!("{}", s); //~ ERROR use of moved value | ^ value borrowed here after move - | - = note: move occurs because `s` has type `std::string::String`, which does not implement the `Copy` trait error: aborting due to previous error diff --git a/src/test/ui/liveness/liveness-move-call-arg.nll.stderr b/src/test/ui/liveness/liveness-move-call-arg.nll.stderr index 3aa89ac8a9b71..521304d560554 100644 --- a/src/test/ui/liveness/liveness-move-call-arg.nll.stderr +++ b/src/test/ui/liveness/liveness-move-call-arg.nll.stderr @@ -1,10 +1,11 @@ error[E0382]: use of moved value: `x` --> $DIR/liveness-move-call-arg.rs:9:14 | +LL | let x: Box = box 25; + | - move occurs because `x` has type `std::boxed::Box`, which does not implement the `Copy` trait +LL | loop { LL | take(x); //~ ERROR use of moved value: `x` | ^ value moved here, in previous iteration of loop - | - = note: move occurs because `x` has type `std::boxed::Box`, which does not implement the `Copy` trait error: aborting due to previous error diff --git a/src/test/ui/liveness/liveness-move-in-loop.nll.stderr b/src/test/ui/liveness/liveness-move-in-loop.nll.stderr index 8a5a18f3316c7..b7e973bc9140d 100644 --- a/src/test/ui/liveness/liveness-move-in-loop.nll.stderr +++ b/src/test/ui/liveness/liveness-move-in-loop.nll.stderr @@ -1,10 +1,11 @@ error[E0382]: use of moved value: `y` --> $DIR/liveness-move-in-loop.rs:11:25 | +LL | let y: Box = box 42; + | - move occurs because `y` has type `std::boxed::Box`, which does not implement the `Copy` trait +... LL | x = y; //~ ERROR use of moved value | ^ value moved here, in previous iteration of loop - | - = note: move occurs because `y` has type `std::boxed::Box`, which does not implement the `Copy` trait error: aborting due to previous error diff --git a/src/test/ui/liveness/liveness-move-in-while.nll.stderr b/src/test/ui/liveness/liveness-move-in-while.nll.stderr index 081983d8bf016..167dcc6b64372 100644 --- a/src/test/ui/liveness/liveness-move-in-while.nll.stderr +++ b/src/test/ui/liveness/liveness-move-in-while.nll.stderr @@ -1,12 +1,13 @@ error[E0382]: borrow of moved value: `y` --> $DIR/liveness-move-in-while.rs:7:24 | +LL | let y: Box = box 42; + | - move occurs because `y` has type `std::boxed::Box`, which does not implement the `Copy` trait +... LL | println!("{}", y); //~ ERROR use of moved value: `y` | ^ value borrowed here after move LL | while true { while true { while true { x = y; x.clone(); } } } | - value moved here, in previous iteration of loop - | - = note: move occurs because `y` has type `std::boxed::Box`, which does not implement the `Copy` trait error: aborting due to previous error diff --git a/src/test/ui/liveness/liveness-use-after-move.nll.stderr b/src/test/ui/liveness/liveness-use-after-move.nll.stderr index 45fd43687f39b..36c25882ccd4f 100644 --- a/src/test/ui/liveness/liveness-use-after-move.nll.stderr +++ b/src/test/ui/liveness/liveness-use-after-move.nll.stderr @@ -1,12 +1,12 @@ error[E0382]: borrow of moved value: `x` --> $DIR/liveness-use-after-move.rs:6:20 | +LL | let x: Box<_> = box 5; + | - move occurs because `x` has type `std::boxed::Box`, which does not implement the `Copy` trait LL | let y = x; | - value moved here LL | println!("{}", *x); //~ ERROR use of moved value: `*x` | ^^ value borrowed here after move - | - = note: move occurs because `x` has type `std::boxed::Box`, which does not implement the `Copy` trait error: aborting due to previous error diff --git a/src/test/ui/liveness/liveness-use-after-send.nll.stderr b/src/test/ui/liveness/liveness-use-after-send.nll.stderr index 2b55b5d59732b..d9367c871165a 100644 --- a/src/test/ui/liveness/liveness-use-after-send.nll.stderr +++ b/src/test/ui/liveness/liveness-use-after-send.nll.stderr @@ -1,12 +1,12 @@ error[E0382]: borrow of moved value: `message` --> $DIR/liveness-use-after-send.rs:16:20 | +LL | fn test00_start(ch: Chan>, message: Box, _count: Box) { + | ------- move occurs because `message` has type `std::boxed::Box`, which does not implement the `Copy` trait LL | send(ch, message); | ------- value moved here LL | println!("{}", message); //~ ERROR use of moved value: `message` | ^^^^^^^ value borrowed here after move - | - = note: move occurs because `message` has type `std::boxed::Box`, which does not implement the `Copy` trait error: aborting due to previous error diff --git a/src/test/ui/moves/move-guard-same-consts.nll.stderr b/src/test/ui/moves/move-guard-same-consts.nll.stderr new file mode 100644 index 0000000000000..43f99cabcae94 --- /dev/null +++ b/src/test/ui/moves/move-guard-same-consts.nll.stderr @@ -0,0 +1,14 @@ +error[E0382]: use of moved value: `x` + --> $DIR/move-guard-same-consts.rs:20:24 + | +LL | let x: Box<_> = box 1; + | - move occurs because `x` has type `std::boxed::Box`, which does not implement the `Copy` trait +... +LL | (1, 2) if take(x) => (), + | - value moved here +LL | (1, 2) if take(x) => (), //~ ERROR use of moved value: `x` + | ^ value used here after move + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0382`. diff --git a/src/test/ui/moves/move-in-guard-1.nll.stderr b/src/test/ui/moves/move-in-guard-1.nll.stderr new file mode 100644 index 0000000000000..41abe6fa72a57 --- /dev/null +++ b/src/test/ui/moves/move-in-guard-1.nll.stderr @@ -0,0 +1,14 @@ +error[E0382]: use of moved value: `x` + --> $DIR/move-in-guard-1.rs:10:24 + | +LL | let x: Box<_> = box 1; + | - move occurs because `x` has type `std::boxed::Box`, which does not implement the `Copy` trait +... +LL | (1, _) if take(x) => (), + | - value moved here +LL | (_, 2) if take(x) => (), //~ ERROR use of moved value: `x` + | ^ value used here after move + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0382`. diff --git a/src/test/ui/moves/move-in-guard-2.nll.stderr b/src/test/ui/moves/move-in-guard-2.nll.stderr index 2d93944384609..0b14c1620d3cf 100644 --- a/src/test/ui/moves/move-in-guard-2.nll.stderr +++ b/src/test/ui/moves/move-in-guard-2.nll.stderr @@ -1,10 +1,11 @@ error[E0382]: use of moved value: `x` --> $DIR/move-in-guard-2.rs:10:24 | +LL | let x: Box<_> = box 1; + | - move occurs because `x` has type `std::boxed::Box`, which does not implement the `Copy` trait +... LL | (_, 2) if take(x) => (), //~ ERROR use of moved value: `x` | ^ value moved here, in previous iteration of loop - | - = note: move occurs because `x` has type `std::boxed::Box`, which does not implement the `Copy` trait error: aborting due to previous error diff --git a/src/test/ui/moves/move-into-dead-array-2.nll.stderr b/src/test/ui/moves/move-into-dead-array-2.nll.stderr index 5b2e1bed0c7bf..20bfdc2bbac72 100644 --- a/src/test/ui/moves/move-into-dead-array-2.nll.stderr +++ b/src/test/ui/moves/move-into-dead-array-2.nll.stderr @@ -1,12 +1,12 @@ error[E0382]: use of moved value: `a` --> $DIR/move-into-dead-array-2.rs:14:5 | +LL | fn foo(mut a: [D; 4], i: usize) { + | ----- move occurs because `a` has type `[D; 4]`, which does not implement the `Copy` trait LL | drop(a); | - value moved here LL | a[i] = d(); //~ ERROR use of moved value: `a` | ^^^^ value used here after move - | - = note: move occurs because `a` has type `[D; 4]`, which does not implement the `Copy` trait error: aborting due to previous error diff --git a/src/test/ui/moves/moves-based-on-type-access-to-field.nll.stderr b/src/test/ui/moves/moves-based-on-type-access-to-field.nll.stderr index 22968b329695f..6ad9a2d414c77 100644 --- a/src/test/ui/moves/moves-based-on-type-access-to-field.nll.stderr +++ b/src/test/ui/moves/moves-based-on-type-access-to-field.nll.stderr @@ -1,12 +1,12 @@ error[E0382]: borrow of moved value: `x` --> $DIR/moves-based-on-type-access-to-field.rs:11:12 | +LL | let x = vec!["hi".to_string()]; + | - move occurs because `x` has type `std::vec::Vec`, which does not implement the `Copy` trait LL | consume(x.into_iter().next().unwrap()); | - value moved here LL | touch(&x[0]); //~ ERROR use of moved value: `x` | ^ value borrowed here after move - | - = note: move occurs because `x` has type `std::vec::Vec`, which does not implement the `Copy` trait error: aborting due to previous error diff --git a/src/test/ui/moves/moves-based-on-type-capture-clause-bad.nll.stderr b/src/test/ui/moves/moves-based-on-type-capture-clause-bad.nll.stderr index 061e871c78a73..bed0ae7275cc5 100644 --- a/src/test/ui/moves/moves-based-on-type-capture-clause-bad.nll.stderr +++ b/src/test/ui/moves/moves-based-on-type-capture-clause-bad.nll.stderr @@ -1,6 +1,8 @@ error[E0382]: borrow of moved value: `x` --> $DIR/moves-based-on-type-capture-clause-bad.rs:8:20 | +LL | let x = "Hello world!".to_string(); + | - move occurs because `x` has type `std::string::String`, which does not implement the `Copy` trait LL | thread::spawn(move|| { | ------ value moved into closure here LL | println!("{}", x); @@ -8,8 +10,6 @@ LL | println!("{}", x); LL | }); LL | println!("{}", x); //~ ERROR use of moved value | ^ value borrowed here after move - | - = note: move occurs because `x` has type `std::string::String`, which does not implement the `Copy` trait error: aborting due to previous error diff --git a/src/test/ui/moves/moves-based-on-type-distribute-copy-over-paren.nll.stderr b/src/test/ui/moves/moves-based-on-type-distribute-copy-over-paren.nll.stderr index 10593a6078e3b..07f40274f9e31 100644 --- a/src/test/ui/moves/moves-based-on-type-distribute-copy-over-paren.nll.stderr +++ b/src/test/ui/moves/moves-based-on-type-distribute-copy-over-paren.nll.stderr @@ -1,24 +1,24 @@ error[E0382]: borrow of moved value: `x` --> $DIR/moves-based-on-type-distribute-copy-over-paren.rs:11:11 | +LL | let x = "hi".to_string(); + | - move occurs because `x` has type `std::string::String`, which does not implement the `Copy` trait LL | let _y = Foo { f:x }; | - value moved here LL | //~^ NOTE value moved here LL | touch(&x); //~ ERROR use of moved value: `x` | ^^ value borrowed here after move - | - = note: move occurs because `x` has type `std::string::String`, which does not implement the `Copy` trait error[E0382]: borrow of moved value: `x` --> $DIR/moves-based-on-type-distribute-copy-over-paren.rs:20:11 | +LL | let x = "hi".to_string(); + | - move occurs because `x` has type `std::string::String`, which does not implement the `Copy` trait LL | let _y = Foo { f:(((x))) }; | ------- value moved here LL | //~^ NOTE value moved here LL | touch(&x); //~ ERROR use of moved value: `x` | ^^ value borrowed here after move - | - = note: move occurs because `x` has type `std::string::String`, which does not implement the `Copy` trait error: aborting due to 2 previous errors diff --git a/src/test/ui/moves/moves-based-on-type-exprs.nll.stderr b/src/test/ui/moves/moves-based-on-type-exprs.nll.stderr index fe44803e2734b..162aec45f5f57 100644 --- a/src/test/ui/moves/moves-based-on-type-exprs.nll.stderr +++ b/src/test/ui/moves/moves-based-on-type-exprs.nll.stderr @@ -1,117 +1,122 @@ error[E0382]: borrow of moved value: `x` --> $DIR/moves-based-on-type-exprs.rs:12:11 | +LL | let x = "hi".to_string(); + | - move occurs because `x` has type `std::string::String`, which does not implement the `Copy` trait LL | let _y = Foo { f:x }; | - value moved here LL | touch(&x); //~ ERROR use of moved value: `x` | ^^ value borrowed here after move - | - = note: move occurs because `x` has type `std::string::String`, which does not implement the `Copy` trait error[E0382]: borrow of moved value: `x` --> $DIR/moves-based-on-type-exprs.rs:18:11 | +LL | let x = "hi".to_string(); + | - move occurs because `x` has type `std::string::String`, which does not implement the `Copy` trait LL | let _y = (x, 3); | - value moved here LL | touch(&x); //~ ERROR use of moved value: `x` | ^^ value borrowed here after move - | - = note: move occurs because `x` has type `std::string::String`, which does not implement the `Copy` trait error[E0382]: borrow of moved value: `x` --> $DIR/moves-based-on-type-exprs.rs:35:11 | +LL | let x = "hi".to_string(); + | - move occurs because `x` has type `std::string::String`, which does not implement the `Copy` trait +... LL | x | - value moved here ... LL | touch(&x); //~ ERROR use of moved value: `x` | ^^ value borrowed here after move - | - = note: move occurs because `x` has type `std::string::String`, which does not implement the `Copy` trait error[E0382]: borrow of moved value: `y` --> $DIR/moves-based-on-type-exprs.rs:36:11 | +LL | let y = "ho".to_string(); + | - move occurs because `y` has type `std::string::String`, which does not implement the `Copy` trait +... LL | y | - value moved here ... LL | touch(&y); //~ ERROR use of moved value: `y` | ^^ value borrowed here after move - | - = note: move occurs because `y` has type `std::string::String`, which does not implement the `Copy` trait error[E0382]: borrow of moved value: `x` --> $DIR/moves-based-on-type-exprs.rs:46:11 | +LL | let x = "hi".to_string(); + | - move occurs because `x` has type `std::string::String`, which does not implement the `Copy` trait +... LL | true => x, | - value moved here ... LL | touch(&x); //~ ERROR use of moved value: `x` | ^^ value borrowed here after move - | - = note: move occurs because `x` has type `std::string::String`, which does not implement the `Copy` trait error[E0382]: borrow of moved value: `y` --> $DIR/moves-based-on-type-exprs.rs:47:11 | +LL | let y = "ho".to_string(); + | - move occurs because `y` has type `std::string::String`, which does not implement the `Copy` trait +... LL | false => y | - value moved here ... LL | touch(&y); //~ ERROR use of moved value: `y` | ^^ value borrowed here after move - | - = note: move occurs because `y` has type `std::string::String`, which does not implement the `Copy` trait error[E0382]: borrow of moved value: `x` --> $DIR/moves-based-on-type-exprs.rs:58:11 | +LL | let x = "hi".to_string(); + | - move occurs because `x` has type `std::string::String`, which does not implement the `Copy` trait +... LL | _ if guard(x) => 10, | - value moved here ... LL | touch(&x); //~ ERROR use of moved value: `x` | ^^ value borrowed here after move - | - = note: move occurs because `x` has type `std::string::String`, which does not implement the `Copy` trait error[E0382]: borrow of moved value: `x` --> $DIR/moves-based-on-type-exprs.rs:65:11 | +LL | let x = "hi".to_string(); + | - move occurs because `x` has type `std::string::String`, which does not implement the `Copy` trait LL | let _y = [x]; | - value moved here LL | touch(&x); //~ ERROR use of moved value: `x` | ^^ value borrowed here after move - | - = note: move occurs because `x` has type `std::string::String`, which does not implement the `Copy` trait error[E0382]: borrow of moved value: `x` --> $DIR/moves-based-on-type-exprs.rs:71:11 | +LL | let x = "hi".to_string(); + | - move occurs because `x` has type `std::string::String`, which does not implement the `Copy` trait LL | let _y = vec![x]; | - value moved here LL | touch(&x); //~ ERROR use of moved value: `x` | ^^ value borrowed here after move - | - = note: move occurs because `x` has type `std::string::String`, which does not implement the `Copy` trait error[E0382]: borrow of moved value: `x` --> $DIR/moves-based-on-type-exprs.rs:77:11 | +LL | let x = vec!["hi".to_string()]; + | - move occurs because `x` has type `std::vec::Vec`, which does not implement the `Copy` trait LL | let _y = x.into_iter().next().unwrap(); | - value moved here LL | touch(&x); //~ ERROR use of moved value: `x` | ^^ value borrowed here after move - | - = note: move occurs because `x` has type `std::vec::Vec`, which does not implement the `Copy` trait error[E0382]: borrow of moved value: `x` --> $DIR/moves-based-on-type-exprs.rs:83:11 | +LL | let x = vec!["hi".to_string()]; + | - move occurs because `x` has type `std::vec::Vec`, which does not implement the `Copy` trait LL | let _y = [x.into_iter().next().unwrap(); 1]; | - value moved here LL | touch(&x); //~ ERROR use of moved value: `x` | ^^ value borrowed here after move - | - = note: move occurs because `x` has type `std::vec::Vec`, which does not implement the `Copy` trait error: aborting due to 11 previous errors diff --git a/src/test/ui/moves/moves-based-on-type-no-recursive-stack-closure.nll.stderr b/src/test/ui/moves/moves-based-on-type-no-recursive-stack-closure.nll.stderr index 03a23420bbc9e..391dd67dbf60a 100644 --- a/src/test/ui/moves/moves-based-on-type-no-recursive-stack-closure.nll.stderr +++ b/src/test/ui/moves/moves-based-on-type-no-recursive-stack-closure.nll.stderr @@ -10,12 +10,14 @@ LL | (f.c)(f, true); error[E0382]: borrow of moved value: `f` --> $DIR/moves-based-on-type-no-recursive-stack-closure.rs:32:5 | +LL | fn conspirator(mut f: F) where F: FnMut(&mut R, bool) { + | - ----- move occurs because `f` has type `F`, which does not implement the `Copy` trait + | | + | consider adding a `Copy` constraint to this type argument LL | let mut r = R {c: Box::new(f)}; | - value moved here LL | f(&mut r, false) //~ ERROR use of moved value | ^ value borrowed here after move - | - = note: move occurs because `f` has type `F`, which does not implement the `Copy` trait error: aborting due to 2 previous errors diff --git a/src/test/ui/no-capture-arc.nll.stderr b/src/test/ui/no-capture-arc.nll.stderr index a3bb56024c454..476b6f75abb46 100644 --- a/src/test/ui/no-capture-arc.nll.stderr +++ b/src/test/ui/no-capture-arc.nll.stderr @@ -1,6 +1,9 @@ error[E0382]: borrow of moved value: `arc_v` --> $DIR/no-capture-arc.rs:14:18 | +LL | let arc_v = Arc::new(v); + | ----- move occurs because `arc_v` has type `std::sync::Arc>`, which does not implement the `Copy` trait +LL | LL | thread::spawn(move|| { | ------ value moved into closure here LL | assert_eq!((*arc_v)[3], 4); @@ -8,8 +11,6 @@ LL | assert_eq!((*arc_v)[3], 4); ... LL | assert_eq!((*arc_v)[2], 3); | ^^^^^ value borrowed here after move - | - = note: move occurs because `arc_v` has type `std::sync::Arc>`, which does not implement the `Copy` trait error: aborting due to previous error diff --git a/src/test/ui/no-reuse-move-arc.nll.stderr b/src/test/ui/no-reuse-move-arc.nll.stderr index e24edc5e8e3ca..0b14f65a77073 100644 --- a/src/test/ui/no-reuse-move-arc.nll.stderr +++ b/src/test/ui/no-reuse-move-arc.nll.stderr @@ -1,6 +1,9 @@ error[E0382]: borrow of moved value: `arc_v` --> $DIR/no-reuse-move-arc.rs:12:18 | +LL | let arc_v = Arc::new(v); + | ----- move occurs because `arc_v` has type `std::sync::Arc>`, which does not implement the `Copy` trait +LL | LL | thread::spawn(move|| { | ------ value moved into closure here LL | assert_eq!((*arc_v)[3], 4); @@ -8,8 +11,6 @@ LL | assert_eq!((*arc_v)[3], 4); ... LL | assert_eq!((*arc_v)[2], 3); //~ ERROR use of moved value: `arc_v` | ^^^^^ value borrowed here after move - | - = note: move occurs because `arc_v` has type `std::sync::Arc>`, which does not implement the `Copy` trait error: aborting due to previous error diff --git a/src/test/ui/once-cant-call-twice-on-heap.nll.stderr b/src/test/ui/once-cant-call-twice-on-heap.nll.stderr new file mode 100644 index 0000000000000..ea53abc1b0f2d --- /dev/null +++ b/src/test/ui/once-cant-call-twice-on-heap.nll.stderr @@ -0,0 +1,15 @@ +error[E0382]: use of moved value: `blk` + --> $DIR/once-cant-call-twice-on-heap.rs:9:5 + | +LL | fn foo(blk: F) { + | - --- move occurs because `blk` has type `F`, which does not implement the `Copy` trait + | | + | consider adding a `Copy` constraint to this type argument +LL | blk(); + | --- value moved here +LL | blk(); //~ ERROR use of moved value + | ^^^ value used here after move + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0382`. diff --git a/src/test/ui/ref-suggestion.nll.stderr b/src/test/ui/ref-suggestion.nll.stderr index 7c00461c900a2..bef8dcca921e6 100644 --- a/src/test/ui/ref-suggestion.nll.stderr +++ b/src/test/ui/ref-suggestion.nll.stderr @@ -1,22 +1,22 @@ error[E0382]: use of moved value: `x` --> $DIR/ref-suggestion.rs:4:5 | +LL | let x = vec![1]; + | - move occurs because `x` has type `std::vec::Vec`, which does not implement the `Copy` trait LL | let y = x; | - value moved here LL | x; //~ ERROR use of moved value | ^ value used here after move - | - = note: move occurs because `x` has type `std::vec::Vec`, which does not implement the `Copy` trait error[E0382]: use of moved value: `x` --> $DIR/ref-suggestion.rs:8:5 | +LL | let x = vec![1]; + | - move occurs because `x` has type `std::vec::Vec`, which does not implement the `Copy` trait LL | let mut y = x; | - value moved here LL | x; //~ ERROR use of moved value | ^ value used here after move - | - = note: move occurs because `x` has type `std::vec::Vec`, which does not implement the `Copy` trait error[E0382]: use of moved value: `x` --> $DIR/ref-suggestion.rs:16:5 diff --git a/src/test/ui/rfc-2361-dbg-macro/dbg-macro-move-semantics.nll.stderr b/src/test/ui/rfc-2361-dbg-macro/dbg-macro-move-semantics.nll.stderr index 0b3f59fd7e452..5a730ad2be42c 100644 --- a/src/test/ui/rfc-2361-dbg-macro/dbg-macro-move-semantics.nll.stderr +++ b/src/test/ui/rfc-2361-dbg-macro/dbg-macro-move-semantics.nll.stderr @@ -1,12 +1,13 @@ error[E0382]: use of moved value: `a` --> $DIR/dbg-macro-move-semantics.rs:9:18 | +LL | let a = NoCopy(0); + | - move occurs because `a` has type `NoCopy`, which does not implement the `Copy` trait LL | let _ = dbg!(a); | ------- value moved here LL | let _ = dbg!(a); //~ ERROR use of moved value | ^ value used here after move | - = note: move occurs because `a` has type `NoCopy`, which does not implement the `Copy` trait = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) error: aborting due to previous error diff --git a/src/test/ui/union/union-borrow-move-parent-sibling.nll.stderr b/src/test/ui/union/union-borrow-move-parent-sibling.nll.stderr index 848c3d9bdb017..29d161fe150e7 100644 --- a/src/test/ui/union/union-borrow-move-parent-sibling.nll.stderr +++ b/src/test/ui/union/union-borrow-move-parent-sibling.nll.stderr @@ -13,12 +13,12 @@ LL | use_borrow(a); error[E0382]: use of moved value: `u` --> $DIR/union-borrow-move-parent-sibling.rs:22:13 | +LL | let u = U { x: ((Vec::new(), Vec::new()), Vec::new()) }; + | - move occurs because `u` has type `U`, which does not implement the `Copy` trait LL | let a = u.x.0; | ----- value moved here LL | let b = u.y; //~ ERROR use of moved value: `u.y` | ^^^ value used here after move - | - = note: move occurs because `u` has type `U`, which does not implement the `Copy` trait error[E0502]: cannot borrow `u` (via `u.y`) as immutable because it is also borrowed as mutable (via `u.x.0.0`) --> $DIR/union-borrow-move-parent-sibling.rs:28:13 @@ -35,12 +35,12 @@ LL | use_borrow(a); error[E0382]: use of moved value: `u` --> $DIR/union-borrow-move-parent-sibling.rs:35:13 | +LL | let u = U { x: ((Vec::new(), Vec::new()), Vec::new()) }; + | - move occurs because `u` has type `U`, which does not implement the `Copy` trait LL | let a = (u.x.0).0; | --------- value moved here LL | let b = u.y; //~ ERROR use of moved value: `u.y` | ^^^ value used here after move - | - = note: move occurs because `u` has type `U`, which does not implement the `Copy` trait error[E0502]: cannot borrow `u` (via `u.x`) as immutable because it is also borrowed as mutable (via `*u.y`) --> $DIR/union-borrow-move-parent-sibling.rs:41:13 @@ -57,12 +57,12 @@ LL | use_borrow(a); error[E0382]: use of moved value: `u` --> $DIR/union-borrow-move-parent-sibling.rs:48:13 | +LL | let u = U { x: ((Vec::new(), Vec::new()), Vec::new()) }; + | - move occurs because `u` has type `U`, which does not implement the `Copy` trait LL | let a = *u.y; | ---- value moved here LL | let b = u.x; //~ ERROR use of moved value: `u.x` | ^^^ value used here after move - | - = note: move occurs because `u` has type `U`, which does not implement the `Copy` trait error: aborting due to 6 previous errors diff --git a/src/test/ui/unop-move-semantics.nll.stderr b/src/test/ui/unop-move-semantics.nll.stderr index 333a4734a4e5f..58953d55b1fba 100644 --- a/src/test/ui/unop-move-semantics.nll.stderr +++ b/src/test/ui/unop-move-semantics.nll.stderr @@ -1,13 +1,15 @@ error[E0382]: borrow of moved value: `x` --> $DIR/unop-move-semantics.rs:8:5 | +LL | fn move_then_borrow + Clone>(x: T) { + | - - move occurs because `x` has type `T`, which does not implement the `Copy` trait + | | + | consider adding a `Copy` constraint to this type argument LL | !x; | - value moved here LL | LL | x.clone(); //~ ERROR: use of moved value | ^ value borrowed here after move - | - = note: move occurs because `x` has type `T`, which does not implement the `Copy` trait error[E0505]: cannot move out of `x` because it is borrowed --> $DIR/unop-move-semantics.rs:15:6 diff --git a/src/test/ui/unsized-locals/borrow-after-move.nll.stderr b/src/test/ui/unsized-locals/borrow-after-move.nll.stderr index 18cba2047356a..0e6a6f6369a15 100644 --- a/src/test/ui/unsized-locals/borrow-after-move.nll.stderr +++ b/src/test/ui/unsized-locals/borrow-after-move.nll.stderr @@ -12,13 +12,13 @@ LL | println!("{}", &x); error[E0382]: borrow of moved value: `y` --> $DIR/borrow-after-move.rs:22:24 | +LL | let y = *x; + | - move occurs because `y` has type `str`, which does not implement the `Copy` trait LL | drop_unsized(y); | - value moved here ... LL | println!("{}", &y); | ^^ value borrowed here after move - | - = note: move occurs because `y` has type `str`, which does not implement the `Copy` trait error[E0382]: borrow of moved value: `x` --> $DIR/borrow-after-move.rs:30:24 @@ -34,13 +34,13 @@ LL | println!("{}", &x); error[E0382]: borrow of moved value: `y` --> $DIR/borrow-after-move.rs:32:24 | +LL | let y = *x; + | - move occurs because `y` has type `str`, which does not implement the `Copy` trait LL | y.foo(); | - value moved here ... LL | println!("{}", &y); | ^^ value borrowed here after move - | - = note: move occurs because `y` has type `str`, which does not implement the `Copy` trait error[E0382]: borrow of moved value: `x` --> $DIR/borrow-after-move.rs:39:24 diff --git a/src/test/ui/unsized-locals/double-move.nll.stderr b/src/test/ui/unsized-locals/double-move.nll.stderr index bbe6da70fb112..e40289af5ad3d 100644 --- a/src/test/ui/unsized-locals/double-move.nll.stderr +++ b/src/test/ui/unsized-locals/double-move.nll.stderr @@ -1,12 +1,12 @@ error[E0382]: use of moved value: `y` --> $DIR/double-move.rs:20:22 | +LL | let y = *x; + | - move occurs because `y` has type `str`, which does not implement the `Copy` trait LL | drop_unsized(y); | - value moved here LL | drop_unsized(y); //~ERROR use of moved value | ^ value used here after move - | - = note: move occurs because `y` has type `str`, which does not implement the `Copy` trait error[E0382]: use of moved value: `x` --> $DIR/double-move.rs:26:22 @@ -21,22 +21,22 @@ LL | drop_unsized(x); //~ERROR use of moved value error[E0382]: use of moved value: `*x` --> $DIR/double-move.rs:32:18 | +LL | let x = "hello".to_owned().into_boxed_str(); + | - move occurs because `x` has type `std::boxed::Box`, which does not implement the `Copy` trait LL | drop_unsized(x); | - value moved here LL | let _y = *x; //~ERROR use of moved value | ^^ value used here after move - | - = note: move occurs because `x` has type `std::boxed::Box`, which does not implement the `Copy` trait error[E0382]: use of moved value: `y` --> $DIR/double-move.rs:39:9 | +LL | let y = *x; + | - move occurs because `y` has type `str`, which does not implement the `Copy` trait LL | y.foo(); | - value moved here LL | y.foo(); //~ERROR use of moved value | ^ value used here after move - | - = note: move occurs because `y` has type `str`, which does not implement the `Copy` trait error[E0382]: use of moved value: `*x` --> $DIR/double-move.rs:45:9 diff --git a/src/test/ui/use/use-after-move-based-on-type.nll.stderr b/src/test/ui/use/use-after-move-based-on-type.nll.stderr index 6f5b23b201333..8160ada9d62ea 100644 --- a/src/test/ui/use/use-after-move-based-on-type.nll.stderr +++ b/src/test/ui/use/use-after-move-based-on-type.nll.stderr @@ -1,12 +1,12 @@ error[E0382]: borrow of moved value: `x` --> $DIR/use-after-move-based-on-type.rs:4:20 | +LL | let x = "Hello!".to_string(); + | - move occurs because `x` has type `std::string::String`, which does not implement the `Copy` trait LL | let _y = x; | - value moved here LL | println!("{}", x); //~ ERROR use of moved value | ^ value borrowed here after move - | - = note: move occurs because `x` has type `std::string::String`, which does not implement the `Copy` trait error: aborting due to previous error diff --git a/src/test/ui/use/use-after-move-implicity-coerced-object.nll.stderr b/src/test/ui/use/use-after-move-implicity-coerced-object.nll.stderr index 308134774efb3..e16bca380679f 100644 --- a/src/test/ui/use/use-after-move-implicity-coerced-object.nll.stderr +++ b/src/test/ui/use/use-after-move-implicity-coerced-object.nll.stderr @@ -1,12 +1,13 @@ error[E0382]: borrow of moved value: `n` --> $DIR/use-after-move-implicity-coerced-object.rs:28:13 | +LL | let n: Box<_> = box Number { n: 42 }; + | - move occurs because `n` has type `std::boxed::Box`, which does not implement the `Copy` trait +LL | let mut l: Box<_> = box List { list: Vec::new() }; LL | l.push(n); | - value moved here LL | let x = n.to_string(); | ^ value borrowed here after move - | - = note: move occurs because `n` has type `std::boxed::Box`, which does not implement the `Copy` trait error: aborting due to previous error diff --git a/src/test/ui/use/use-after-move-self-based-on-type.nll.stderr b/src/test/ui/use/use-after-move-self-based-on-type.nll.stderr index d7f7c3c30f6cd..4119741d805cd 100644 --- a/src/test/ui/use/use-after-move-self-based-on-type.nll.stderr +++ b/src/test/ui/use/use-after-move-self-based-on-type.nll.stderr @@ -1,12 +1,12 @@ error[E0382]: use of moved value: `self` --> $DIR/use-after-move-self-based-on-type.rs:12:16 | +LL | pub fn foo(self) -> isize { + | ---- move occurs because `self` has type `S`, which does not implement the `Copy` trait LL | self.bar(); | ---- value moved here LL | return self.x; //~ ERROR use of moved value: `self.x` | ^^^^^^ value used here after move - | - = note: move occurs because `self` has type `S`, which does not implement the `Copy` trait error: aborting due to previous error diff --git a/src/test/ui/use/use-after-move-self.nll.stderr b/src/test/ui/use/use-after-move-self.nll.stderr index 3e11e94e993f5..e2ce3690cb904 100644 --- a/src/test/ui/use/use-after-move-self.nll.stderr +++ b/src/test/ui/use/use-after-move-self.nll.stderr @@ -1,12 +1,12 @@ error[E0382]: use of moved value: `self` --> $DIR/use-after-move-self.rs:10:16 | +LL | pub fn foo(self) -> isize { + | ---- move occurs because `self` has type `S`, which does not implement the `Copy` trait LL | self.bar(); | ---- value moved here LL | return *self.x; //~ ERROR use of moved value: `*self.x` | ^^^^^^^ value used here after move - | - = note: move occurs because `self` has type `S`, which does not implement the `Copy` trait error: aborting due to previous error diff --git a/src/test/ui/walk-struct-literal-with.nll.stderr b/src/test/ui/walk-struct-literal-with.nll.stderr index 22ad3b1e2f2e7..2263747607b9c 100644 --- a/src/test/ui/walk-struct-literal-with.nll.stderr +++ b/src/test/ui/walk-struct-literal-with.nll.stderr @@ -1,12 +1,12 @@ error[E0382]: borrow of moved value: `start` --> $DIR/walk-struct-literal-with.rs:16:20 | +LL | let start = Mine{test:"Foo".to_string(), other_val:0}; + | ----- move occurs because `start` has type `Mine`, which does not implement the `Copy` trait LL | let end = Mine{other_val:1, ..start.make_string_bar()}; | ----- value moved here LL | println!("{}", start.test); //~ ERROR use of moved value: `start.test` | ^^^^^^^^^^ value borrowed here after move - | - = note: move occurs because `start` has type `Mine`, which does not implement the `Copy` trait error: aborting due to previous error