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 diff --git a/src/libcore/num/dec2flt/mod.rs b/src/libcore/num/dec2flt/mod.rs index 58b196a6eac3d..14a912872be35 100644 --- a/src/libcore/num/dec2flt/mod.rs +++ b/src/libcore/num/dec2flt/mod.rs @@ -112,11 +112,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 [EBNF] grammar + /// will result in an [`Ok`] being returned: + /// + /// ```txt + /// Float ::= Sign? ( 'inf' | 'NaN' | Number ) + /// Number ::= ( Digit+ | + /// Digit+ '.' Digit* | + /// Digit* '.' Digit+ ) Exp? + /// Exp ::= [eE] Sign? Digit+ + /// Sign ::= [+-] + /// 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 + /// instead return an error. See [issue #31407] for details. + /// + /// [issue #31407]: https://github.com/rust-lang/rust/issues/31407 + /// /// # Arguments /// /// * src - A string 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/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/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/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 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_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}; diff --git a/src/librustc_mir/borrow_check/error_reporting.rs b/src/librustc_mir/borrow_check/error_reporting.rs index 233db12b03001..56b87feb82b2c 100644 --- a/src/librustc_mir/borrow_check/error_reporting.rs +++ b/src/librustc_mir/borrow_check/error_reporting.rs @@ -198,19 +198,38 @@ 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 - )); + 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 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", + note_msg, ty + )); + } } if let Some((_, mut old_err)) = self.move_error_reported 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); 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-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-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-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-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-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-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-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/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/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/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/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/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/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-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-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/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..2ed7b543e713c --- /dev/null +++ b/src/test/ui/issues/issue-34721.stderr @@ -0,0 +1,20 @@ +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 + | | + | consider adding a `Copy` constraint to this type argument +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`. 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/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`. 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/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/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/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 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