From e3a048c3c9da3ad6faa2b576de044cc52dee2c62 Mon Sep 17 00:00:00 2001 From: Aaron Hill Date: Fri, 31 Dec 2021 16:55:34 -0500 Subject: [PATCH 01/21] Ensure that early-bound function lifetimes are always 'local' During borrowchecking, we treat any free (early-bound) regions on the 'defining type' as `RegionClassification::External`. According to the doc comments, we should only have 'external' regions when checking a closure/generator. However, a plain function can also have some if its regions be considered 'early bound' - this occurs when the region is constrained by an argument, appears in a `where` clause, or in an opaque type. This was causing us to incorrectly mark these regions as 'external', which caused some diagnostic code to act as if we were referring to a 'parent' region from inside a closure. This PR marks all instantiated region variables as 'local' when we're borrow-checking something other than a closure/generator/inline-const. --- .../rustc_borrowck/src/universal_regions.rs | 41 +++++++++++-------- .../nll/named_lifetimes_basic.use_x.nll.0.mir | 4 +- src/test/ui/c-variadic/variadic-ffi-4.stderr | 2 +- ...d-bounds-unnorm-associated-type.nll.stderr | 2 +- src/test/ui/issues/issue-16683.nll.stderr | 13 ++---- src/test/ui/issues/issue-17758.nll.stderr | 13 ++---- src/test/ui/issues/issue-52213.nll.stderr | 2 +- .../match/match-ref-mut-invariance.nll.stderr | 2 +- .../match-ref-mut-let-invariance.nll.stderr | 2 +- src/test/ui/nll/issue-52113.stderr | 2 +- src/test/ui/nll/issue-55394.nll.stderr | 2 +- src/test/ui/nll/issue-67007-escaping-data.rs | 2 +- .../ui/nll/issue-67007-escaping-data.stderr | 13 ++---- src/test/ui/nll/mir_check_cast_closure.stderr | 2 +- .../ui/nll/outlives-suggestion-more.stderr | 6 +-- src/test/ui/nll/outlives-suggestion-simple.rs | 2 +- .../ui/nll/outlives-suggestion-simple.stderr | 22 ++++------ .../ui/nll/type-alias-free-regions.nll.stderr | 4 +- .../nll/type-check-pointer-coercions.stderr | 14 +++---- .../nll/user-annotations/wf-self-type.stderr | 2 +- ...object-lifetime-default-elision.nll.stderr | 2 +- .../region-object-lifetime-2.nll.stderr | 2 +- ...ion-object-lifetime-in-coercion.nll.stderr | 2 +- ...hod-type-parameters-trait-bound.nll.stderr | 14 ++----- src/test/ui/regions/regions-bounds.nll.stderr | 4 +- ...se-over-type-parameter-multiple.nll.stderr | 2 +- .../regions-creating-enums4.nll.stderr | 2 +- ...egions-early-bound-error-method.nll.stderr | 2 +- ...-free-region-ordering-incorrect.nll.stderr | 2 +- .../regions-infer-not-param.nll.stderr | 4 +- .../regions-trait-object-subtyping.nll.stderr | 4 +- ...riance-contravariant-arg-object.nll.stderr | 4 +- .../variance-covariant-arg-object.nll.stderr | 4 +- .../variance-invariant-arg-object.nll.stderr | 4 +- ...ance-use-contravariant-struct-1.nll.stderr | 2 +- ...variance-use-covariant-struct-1.nll.stderr | 2 +- ...variance-use-invariant-struct-1.nll.stderr | 4 +- src/test/ui/wf/wf-static-method.nll.stderr | 10 ++--- 38 files changed, 98 insertions(+), 124 deletions(-) diff --git a/compiler/rustc_borrowck/src/universal_regions.rs b/compiler/rustc_borrowck/src/universal_regions.rs index b986df403f9f3..16a903d5e593f 100644 --- a/compiler/rustc_borrowck/src/universal_regions.rs +++ b/compiler/rustc_borrowck/src/universal_regions.rs @@ -180,8 +180,9 @@ pub enum RegionClassification { /// anywhere. There is only one, `'static`. Global, - /// An **external** region is only relevant for closures. In that - /// case, it refers to regions that are free in the closure type + /// An **external** region is only relevant for + /// closures, generators, and inline consts. In that + /// case, it refers to regions that are free in the type /// -- basically, something bound in the surrounding context. /// /// Consider this example: @@ -198,8 +199,8 @@ pub enum RegionClassification { /// Here, the lifetimes `'a` and `'b` would be **external** to the /// closure. /// - /// If we are not analyzing a closure, there are no external - /// lifetimes. + /// If we are not analyzing a closure/generator/inline-const, + /// there are no external lifetimes. External, /// A **local** lifetime is one about which we know the full set @@ -424,22 +425,30 @@ impl<'cx, 'tcx> UniversalRegionsBuilder<'cx, 'tcx> { let typeck_root_def_id = self.infcx.tcx.typeck_root_def_id(self.mir_def.did.to_def_id()); - // If this is a closure or generator, then the late-bound regions from the enclosing - // function are actually external regions to us. For example, here, 'a is not local - // to the closure c (although it is local to the fn foo): - // fn foo<'a>() { - // let c = || { let x: &'a u32 = ...; } - // } - if self.mir_def.did.to_def_id() != typeck_root_def_id { + // If this is is a 'root' body (not a closure/generator/inline const), then + // there are no extern regions, so the local regions start at the same + // position as the (empty) sub-list of extern regions + let first_local_index = if self.mir_def.did.to_def_id() == typeck_root_def_id { + first_extern_index + } else { + // If this is a closure, generator, or inline-const, then the late-bound regions from the enclosing + // function are actually external regions to us. For example, here, 'a is not local + // to the closure c (although it is local to the fn foo): + // fn foo<'a>() { + // let c = || { let x: &'a u32 = ...; } + // } self.infcx - .replace_late_bound_regions_with_nll_infer_vars(self.mir_def.did, &mut indices) - } - - let bound_inputs_and_output = self.compute_inputs_and_output(&indices, defining_ty); + .replace_late_bound_regions_with_nll_infer_vars(self.mir_def.did, &mut indices); + // Any regions created during the execution of `defining_ty` or during the above + // late-bound region replacement are all considered 'extern' regions + self.infcx.num_region_vars() + }; // "Liberate" the late-bound regions. These correspond to // "local" free regions. - let first_local_index = self.infcx.num_region_vars(); + + let bound_inputs_and_output = self.compute_inputs_and_output(&indices, defining_ty); + let inputs_and_output = self.infcx.replace_bound_regions_with_nll_infer_vars( FR, self.mir_def.did, diff --git a/src/test/mir-opt/nll/named_lifetimes_basic.use_x.nll.0.mir b/src/test/mir-opt/nll/named_lifetimes_basic.use_x.nll.0.mir index bfc85e98786b8..975e2ffbf01e7 100644 --- a/src/test/mir-opt/nll/named_lifetimes_basic.use_x.nll.0.mir +++ b/src/test/mir-opt/nll/named_lifetimes_basic.use_x.nll.0.mir @@ -2,8 +2,8 @@ | Free Region Mapping | '_#0r | Global | ['_#2r, '_#1r, '_#0r, '_#4r, '_#3r] -| '_#1r | External | ['_#1r, '_#4r] -| '_#2r | External | ['_#2r, '_#1r, '_#4r] +| '_#1r | Local | ['_#1r, '_#4r] +| '_#2r | Local | ['_#2r, '_#1r, '_#4r] | '_#3r | Local | ['_#4r, '_#3r] | '_#4r | Local | ['_#4r] | diff --git a/src/test/ui/c-variadic/variadic-ffi-4.stderr b/src/test/ui/c-variadic/variadic-ffi-4.stderr index 4b03fe1549413..ff4da5251a9b2 100644 --- a/src/test/ui/c-variadic/variadic-ffi-4.stderr +++ b/src/test/ui/c-variadic/variadic-ffi-4.stderr @@ -20,7 +20,7 @@ LL | pub unsafe extern "C" fn no_escape0<'f>(_: usize, ap: ...) -> VaListImpl<'f | | | lifetime `'f` defined here LL | ap - | ^^ returning this value requires that `'1` must outlive `'f` + | ^^ function was supposed to return data with lifetime `'f` but it is returning data with lifetime `'1` | = note: requirement occurs because of the type VaListImpl<'_>, which makes the generic argument '_ invariant = note: the struct VaListImpl<'f> is invariant over the parameter 'f diff --git a/src/test/ui/fn/implied-bounds-unnorm-associated-type.nll.stderr b/src/test/ui/fn/implied-bounds-unnorm-associated-type.nll.stderr index e37ec7f26651c..8096f08385c8c 100644 --- a/src/test/ui/fn/implied-bounds-unnorm-associated-type.nll.stderr +++ b/src/test/ui/fn/implied-bounds-unnorm-associated-type.nll.stderr @@ -6,7 +6,7 @@ LL | fn f<'a, 'b>(s: &'b str, _: <&'a &'b () as Trait>::Type) -> &'a str { | | | lifetime `'a` defined here LL | s - | ^ returning this value requires that `'b` must outlive `'a` + | ^ function was supposed to return data with lifetime `'a` but it is returning data with lifetime `'b` | = help: consider adding the following bound: `'b: 'a` diff --git a/src/test/ui/issues/issue-16683.nll.stderr b/src/test/ui/issues/issue-16683.nll.stderr index 0e8f520353fba..fff681b2e0b76 100644 --- a/src/test/ui/issues/issue-16683.nll.stderr +++ b/src/test/ui/issues/issue-16683.nll.stderr @@ -1,20 +1,13 @@ -error[E0521]: borrowed data escapes outside of associated function +error: lifetime may not live long enough --> $DIR/issue-16683.rs:4:9 | LL | trait T<'a> { | -- lifetime `'a` defined here LL | fn a(&'a self) -> &'a bool; LL | fn b(&self) { - | ----- - | | - | `self` is a reference that is only valid in the associated function body - | let's call the lifetime of this reference `'1` + | - let's call the lifetime of this reference `'1` LL | self.a(); - | ^^^^^^^^ - | | - | `self` escapes the associated function body here - | argument requires that `'1` must outlive `'a` + | ^^^^^^^^ argument requires that `'1` must outlive `'a` error: aborting due to previous error -For more information about this error, try `rustc --explain E0521`. diff --git a/src/test/ui/issues/issue-17758.nll.stderr b/src/test/ui/issues/issue-17758.nll.stderr index b929fdbf3687a..613ef6b907c54 100644 --- a/src/test/ui/issues/issue-17758.nll.stderr +++ b/src/test/ui/issues/issue-17758.nll.stderr @@ -1,20 +1,13 @@ -error[E0521]: borrowed data escapes outside of associated function +error: lifetime may not live long enough --> $DIR/issue-17758.rs:7:9 | LL | trait Foo<'a> { | -- lifetime `'a` defined here LL | fn foo(&'a self); LL | fn bar(&self) { - | ----- - | | - | `self` is a reference that is only valid in the associated function body - | let's call the lifetime of this reference `'1` + | - let's call the lifetime of this reference `'1` LL | self.foo(); - | ^^^^^^^^^^ - | | - | `self` escapes the associated function body here - | argument requires that `'1` must outlive `'a` + | ^^^^^^^^^^ argument requires that `'1` must outlive `'a` error: aborting due to previous error -For more information about this error, try `rustc --explain E0521`. diff --git a/src/test/ui/issues/issue-52213.nll.stderr b/src/test/ui/issues/issue-52213.nll.stderr index 359f91309d4f3..da31bcd547507 100644 --- a/src/test/ui/issues/issue-52213.nll.stderr +++ b/src/test/ui/issues/issue-52213.nll.stderr @@ -7,7 +7,7 @@ LL | fn transmute_lifetime<'a, 'b, T>(t: &'a (T,)) -> &'b T { | lifetime `'a` defined here LL | match (&t,) { LL | ((u,),) => u, - | ^ returning this value requires that `'a` must outlive `'b` + | ^ function was supposed to return data with lifetime `'b` but it is returning data with lifetime `'a` | = help: consider adding the following bound: `'a: 'b` diff --git a/src/test/ui/match/match-ref-mut-invariance.nll.stderr b/src/test/ui/match/match-ref-mut-invariance.nll.stderr index 1dc29d2088cea..c8a7876dc54c2 100644 --- a/src/test/ui/match/match-ref-mut-invariance.nll.stderr +++ b/src/test/ui/match/match-ref-mut-invariance.nll.stderr @@ -6,7 +6,7 @@ LL | impl<'b> S<'b> { LL | fn bar<'a>(&'a mut self) -> &'a mut &'a i32 { | -- lifetime `'a` defined here LL | match self.0 { ref mut x => x } - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ returning this value requires that `'a` must outlive `'b` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ associated function was supposed to return data with lifetime `'b` but it is returning data with lifetime `'a` | = help: consider adding the following bound: `'a: 'b` = note: requirement occurs because of a mutable reference to &i32 diff --git a/src/test/ui/match/match-ref-mut-let-invariance.nll.stderr b/src/test/ui/match/match-ref-mut-let-invariance.nll.stderr index 8b87c3da28b02..11ddf1487dd7a 100644 --- a/src/test/ui/match/match-ref-mut-let-invariance.nll.stderr +++ b/src/test/ui/match/match-ref-mut-let-invariance.nll.stderr @@ -7,7 +7,7 @@ LL | fn bar<'a>(&'a mut self) -> &'a mut &'a i32 { | -- lifetime `'a` defined here LL | let ref mut x = self.0; LL | x - | ^ returning this value requires that `'a` must outlive `'b` + | ^ associated function was supposed to return data with lifetime `'b` but it is returning data with lifetime `'a` | = help: consider adding the following bound: `'a: 'b` = note: requirement occurs because of a mutable reference to &i32 diff --git a/src/test/ui/nll/issue-52113.stderr b/src/test/ui/nll/issue-52113.stderr index dcf0338673483..f70ae2edd7fac 100644 --- a/src/test/ui/nll/issue-52113.stderr +++ b/src/test/ui/nll/issue-52113.stderr @@ -7,7 +7,7 @@ LL | fn produce_err<'a, 'b: 'a>(data: &'b mut Vec<&'b u32>, value: &'a u32) -> i | lifetime `'a` defined here ... LL | x - | ^ returning this value requires that `'a` must outlive `'b` + | ^ function was supposed to return data with lifetime `'b` but it is returning data with lifetime `'a` | = help: consider adding the following bound: `'a: 'b` diff --git a/src/test/ui/nll/issue-55394.nll.stderr b/src/test/ui/nll/issue-55394.nll.stderr index d0723047ac08c..24b8c84b4a96a 100644 --- a/src/test/ui/nll/issue-55394.nll.stderr +++ b/src/test/ui/nll/issue-55394.nll.stderr @@ -6,7 +6,7 @@ LL | fn new(bar: &mut Bar) -> Self { | | | let's call the lifetime of this reference `'1` LL | Foo { bar } - | ^^^^^^^^^^^ returning this value requires that `'1` must outlive `'2` + | ^^^^^^^^^^^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1` error: aborting due to previous error diff --git a/src/test/ui/nll/issue-67007-escaping-data.rs b/src/test/ui/nll/issue-67007-escaping-data.rs index 8c21737e05fe8..99b6d512261b8 100644 --- a/src/test/ui/nll/issue-67007-escaping-data.rs +++ b/src/test/ui/nll/issue-67007-escaping-data.rs @@ -14,7 +14,7 @@ struct Consumer<'tcx>(&'tcx ()); impl<'tcx> Consumer<'tcx> { fn bad_method<'a>(&self, fcx: &FnCtxt<'a, 'tcx>) { - let other = self.use_fcx(fcx); //~ ERROR borrowed data + let other = self.use_fcx(fcx); //~ ERROR lifetime may not live long enough fcx.use_it(other); } diff --git a/src/test/ui/nll/issue-67007-escaping-data.stderr b/src/test/ui/nll/issue-67007-escaping-data.stderr index 2834d6fb0d214..ce067e23aa34a 100644 --- a/src/test/ui/nll/issue-67007-escaping-data.stderr +++ b/src/test/ui/nll/issue-67007-escaping-data.stderr @@ -1,21 +1,14 @@ -error[E0521]: borrowed data escapes outside of associated function +error: lifetime may not live long enough --> $DIR/issue-67007-escaping-data.rs:17:21 | LL | impl<'tcx> Consumer<'tcx> { | ---- lifetime `'tcx` defined here LL | fn bad_method<'a>(&self, fcx: &FnCtxt<'a, 'tcx>) { - | -- ----- --- `fcx` is a reference that is only valid in the associated function body - | | | - | | `self` declared here, outside of the associated function body - | lifetime `'a` defined here + | -- lifetime `'a` defined here LL | let other = self.use_fcx(fcx); - | ^^^^^^^^^^^^^^^^^ - | | - | `fcx` escapes the associated function body here - | argument requires that `'a` must outlive `'tcx` + | ^^^^^^^^^^^^^^^^^ argument requires that `'a` must outlive `'tcx` | = help: consider adding the following bound: `'a: 'tcx` error: aborting due to previous error -For more information about this error, try `rustc --explain E0521`. diff --git a/src/test/ui/nll/mir_check_cast_closure.stderr b/src/test/ui/nll/mir_check_cast_closure.stderr index 113e220e5137e..f34cafe308d3e 100644 --- a/src/test/ui/nll/mir_check_cast_closure.stderr +++ b/src/test/ui/nll/mir_check_cast_closure.stderr @@ -7,7 +7,7 @@ LL | fn bar<'a, 'b>() -> fn(&'a u32, &'b u32) -> &'a u32 { | lifetime `'a` defined here LL | let g: fn(_, _) -> _ = |_x, y| y; LL | g - | ^ returning this value requires that `'b` must outlive `'a` + | ^ function was supposed to return data with lifetime `'a` but it is returning data with lifetime `'b` | = help: consider adding the following bound: `'b: 'a` diff --git a/src/test/ui/nll/outlives-suggestion-more.stderr b/src/test/ui/nll/outlives-suggestion-more.stderr index a80e59d4822fb..7f98aa5801d07 100644 --- a/src/test/ui/nll/outlives-suggestion-more.stderr +++ b/src/test/ui/nll/outlives-suggestion-more.stderr @@ -6,7 +6,7 @@ LL | fn foo1<'a, 'b, 'c, 'd>(x: &'a usize, y: &'b usize) -> (&'c usize, &'d usiz | | | lifetime `'a` defined here LL | (x, y) - | ^^^^^^ returning this value requires that `'a` must outlive `'c` + | ^^^^^^ function was supposed to return data with lifetime `'c` but it is returning data with lifetime `'a` | = help: consider adding the following bound: `'a: 'c` @@ -18,7 +18,7 @@ LL | fn foo1<'a, 'b, 'c, 'd>(x: &'a usize, y: &'b usize) -> (&'c usize, &'d usiz | | | lifetime `'b` defined here LL | (x, y) - | ^^^^^^ returning this value requires that `'b` must outlive `'d` + | ^^^^^^ function was supposed to return data with lifetime `'d` but it is returning data with lifetime `'b` | = help: consider adding the following bound: `'b: 'd` @@ -35,7 +35,7 @@ LL | fn foo2<'a, 'b, 'c>(x: &'a usize, y: &'b usize) -> (&'c usize, &'static usi | | | lifetime `'a` defined here LL | (x, y) - | ^^^^^^ returning this value requires that `'a` must outlive `'c` + | ^^^^^^ function was supposed to return data with lifetime `'c` but it is returning data with lifetime `'a` | = help: consider adding the following bound: `'a: 'c` diff --git a/src/test/ui/nll/outlives-suggestion-simple.rs b/src/test/ui/nll/outlives-suggestion-simple.rs index 41e4d83aa9213..496cf92400c54 100644 --- a/src/test/ui/nll/outlives-suggestion-simple.rs +++ b/src/test/ui/nll/outlives-suggestion-simple.rs @@ -70,7 +70,7 @@ pub struct Foo2<'a> { impl<'a> Foo2<'a> { // should not produce outlives suggestions to name 'self fn get_bar(&self) -> Bar2 { - Bar2::new(&self) //~ERROR borrowed data escapes outside of associated function + Bar2::new(&self) //~ERROR lifetime may not live long enough } } diff --git a/src/test/ui/nll/outlives-suggestion-simple.stderr b/src/test/ui/nll/outlives-suggestion-simple.stderr index 3b2017d2d03a1..8e6e4f1a47623 100644 --- a/src/test/ui/nll/outlives-suggestion-simple.stderr +++ b/src/test/ui/nll/outlives-suggestion-simple.stderr @@ -6,7 +6,7 @@ LL | fn foo1<'a, 'b>(x: &'a usize) -> &'b usize { | | | lifetime `'a` defined here LL | x - | ^ returning this value requires that `'a` must outlive `'b` + | ^ function was supposed to return data with lifetime `'b` but it is returning data with lifetime `'a` | = help: consider adding the following bound: `'a: 'b` @@ -53,7 +53,7 @@ LL | fn foo4<'a, 'b, 'c>(x: &'a usize) -> (&'b usize, &'c usize) { | lifetime `'a` defined here ... LL | (x, x) - | ^^^^^^ returning this value requires that `'a` must outlive `'b` + | ^^^^^^ function was supposed to return data with lifetime `'b` but it is returning data with lifetime `'a` | = help: consider adding the following bound: `'a: 'b` @@ -73,7 +73,7 @@ LL | impl<'a> Bar<'a> { LL | pub fn get<'b>(&self) -> &'b usize { | -- lifetime `'b` defined here LL | self.x - | ^^^^^^ returning this value requires that `'a` must outlive `'b` + | ^^^^^^ associated function was supposed to return data with lifetime `'b` but it is returning data with lifetime `'a` | = help: consider adding the following bound: `'a: 'b` @@ -85,28 +85,20 @@ LL | impl<'a> Baz<'a> { LL | fn get<'b>(&'b self) -> &'a i32 { | -- lifetime `'b` defined here LL | self.x - | ^^^^^^ returning this value requires that `'b` must outlive `'a` + | ^^^^^^ associated function was supposed to return data with lifetime `'a` but it is returning data with lifetime `'b` | = help: consider adding the following bound: `'b: 'a` -error[E0521]: borrowed data escapes outside of associated function +error: lifetime may not live long enough --> $DIR/outlives-suggestion-simple.rs:73:9 | LL | impl<'a> Foo2<'a> { | -- lifetime `'a` defined here LL | // should not produce outlives suggestions to name 'self LL | fn get_bar(&self) -> Bar2 { - | ----- - | | - | `self` declared here, outside of the associated function body - | `self` is a reference that is only valid in the associated function body - | let's call the lifetime of this reference `'1` + | - let's call the lifetime of this reference `'1` LL | Bar2::new(&self) - | ^^^^^^^^^^^^^^^^ - | | - | `self` escapes the associated function body here - | argument requires that `'1` must outlive `'a` + | ^^^^^^^^^^^^^^^^ argument requires that `'1` must outlive `'a` error: aborting due to 9 previous errors -For more information about this error, try `rustc --explain E0521`. diff --git a/src/test/ui/nll/type-alias-free-regions.nll.stderr b/src/test/ui/nll/type-alias-free-regions.nll.stderr index bde73b0589416..45fd5a2f1d657 100644 --- a/src/test/ui/nll/type-alias-free-regions.nll.stderr +++ b/src/test/ui/nll/type-alias-free-regions.nll.stderr @@ -6,7 +6,7 @@ LL | impl<'a> FromBox<'a> for C<'a> { LL | fn from_box(b: Box) -> Self { | - has type `Box>` LL | C { f: b } - | ^^^^^^^^^^ returning this value requires that `'1` must outlive `'a` + | ^^^^^^^^^^ associated function was supposed to return data with lifetime `'a` but it is returning data with lifetime `'1` error: lifetime may not live long enough --> $DIR/type-alias-free-regions.rs:27:9 @@ -16,7 +16,7 @@ LL | impl<'a> FromTuple<'a> for C<'a> { LL | fn from_tuple(b: (B,)) -> Self { | - has type `(Box<&'1 isize>,)` LL | C { f: Box::new(b.0) } - | ^^^^^^^^^^^^^^^^^^^^^^ returning this value requires that `'1` must outlive `'a` + | ^^^^^^^^^^^^^^^^^^^^^^ associated function was supposed to return data with lifetime `'a` but it is returning data with lifetime `'1` error: aborting due to 2 previous errors diff --git a/src/test/ui/nll/type-check-pointer-coercions.stderr b/src/test/ui/nll/type-check-pointer-coercions.stderr index ccb3d33ac4064..b392c2007d398 100644 --- a/src/test/ui/nll/type-check-pointer-coercions.stderr +++ b/src/test/ui/nll/type-check-pointer-coercions.stderr @@ -6,7 +6,7 @@ LL | fn shared_to_const<'a, 'b>(x: &&'a i32) -> *const &'b i32 { | | | lifetime `'a` defined here LL | x - | ^ returning this value requires that `'a` must outlive `'b` + | ^ function was supposed to return data with lifetime `'b` but it is returning data with lifetime `'a` | = help: consider adding the following bound: `'a: 'b` @@ -18,7 +18,7 @@ LL | fn unique_to_const<'a, 'b>(x: &mut &'a i32) -> *const &'b i32 { | | | lifetime `'a` defined here LL | x - | ^ returning this value requires that `'a` must outlive `'b` + | ^ function was supposed to return data with lifetime `'b` but it is returning data with lifetime `'a` | = help: consider adding the following bound: `'a: 'b` @@ -47,7 +47,7 @@ LL | fn unique_to_mut<'a, 'b>(x: &mut &'a i32) -> *mut &'b i32 { | lifetime `'a` defined here LL | // Two errors because *mut is invariant LL | x - | ^ returning this value requires that `'a` must outlive `'b` + | ^ function was supposed to return data with lifetime `'b` but it is returning data with lifetime `'a` | = help: consider adding the following bound: `'a: 'b` = note: requirement occurs because of a mutable pointer to &i32 @@ -64,7 +64,7 @@ LL | fn mut_to_const<'a, 'b>(x: *mut &'a i32) -> *const &'b i32 { | | | lifetime `'a` defined here LL | x - | ^ returning this value requires that `'a` must outlive `'b` + | ^ function was supposed to return data with lifetime `'b` but it is returning data with lifetime `'a` | = help: consider adding the following bound: `'a: 'b` @@ -77,7 +77,7 @@ LL | fn array_elem<'a, 'b>(x: &'a i32) -> *const &'b i32 { | lifetime `'a` defined here ... LL | y - | ^ returning this value requires that `'a` must outlive `'b` + | ^ function was supposed to return data with lifetime `'b` but it is returning data with lifetime `'a` | = help: consider adding the following bound: `'a: 'b` @@ -90,7 +90,7 @@ LL | fn array_coerce<'a, 'b>(x: &'a i32) -> *const [&'b i32; 3] { | lifetime `'a` defined here ... LL | y - | ^ returning this value requires that `'a` must outlive `'b` + | ^ function was supposed to return data with lifetime `'b` but it is returning data with lifetime `'a` | = help: consider adding the following bound: `'a: 'b` @@ -103,7 +103,7 @@ LL | fn nested_array<'a, 'b>(x: &'a i32) -> *const [&'b i32; 2] { | lifetime `'a` defined here ... LL | y - | ^ returning this value requires that `'a` must outlive `'b` + | ^ function was supposed to return data with lifetime `'b` but it is returning data with lifetime `'a` | = help: consider adding the following bound: `'a: 'b` diff --git a/src/test/ui/nll/user-annotations/wf-self-type.stderr b/src/test/ui/nll/user-annotations/wf-self-type.stderr index 33bb1c519b16e..902b4c687554a 100644 --- a/src/test/ui/nll/user-annotations/wf-self-type.stderr +++ b/src/test/ui/nll/user-annotations/wf-self-type.stderr @@ -6,7 +6,7 @@ LL | pub fn foo<'a, 'b>(u: &'b ()) -> &'a () { | | | lifetime `'a` defined here LL | Foo::xmute(u) - | ^^^^^^^^^^^^^ returning this value requires that `'b` must outlive `'a` + | ^^^^^^^^^^^^^ function was supposed to return data with lifetime `'a` but it is returning data with lifetime `'b` | = help: consider adding the following bound: `'b: 'a` diff --git a/src/test/ui/object-lifetime/object-lifetime-default-elision.nll.stderr b/src/test/ui/object-lifetime/object-lifetime-default-elision.nll.stderr index 900cdfca24438..61e96f59fed91 100644 --- a/src/test/ui/object-lifetime/object-lifetime-default-elision.nll.stderr +++ b/src/test/ui/object-lifetime/object-lifetime-default-elision.nll.stderr @@ -7,7 +7,7 @@ LL | fn load3<'a,'b>(ss: &'a dyn SomeTrait) -> &'b dyn SomeTrait { | lifetime `'a` defined here ... LL | ss - | ^^ returning this value requires that `'a` must outlive `'b` + | ^^ function was supposed to return data with lifetime `'b` but it is returning data with lifetime `'a` | = help: consider adding the following bound: `'a: 'b` diff --git a/src/test/ui/regions/region-object-lifetime-2.nll.stderr b/src/test/ui/regions/region-object-lifetime-2.nll.stderr index db45a03ad18fb..d95289f3f9def 100644 --- a/src/test/ui/regions/region-object-lifetime-2.nll.stderr +++ b/src/test/ui/regions/region-object-lifetime-2.nll.stderr @@ -6,7 +6,7 @@ LL | fn borrowed_receiver_different_lifetimes<'a,'b>(x: &'a dyn Foo) -> &'b () { | | | lifetime `'a` defined here LL | x.borrowed() - | ^^^^^^^^^^^^ returning this value requires that `'a` must outlive `'b` + | ^^^^^^^^^^^^ function was supposed to return data with lifetime `'b` but it is returning data with lifetime `'a` | = help: consider adding the following bound: `'a: 'b` diff --git a/src/test/ui/regions/region-object-lifetime-in-coercion.nll.stderr b/src/test/ui/regions/region-object-lifetime-in-coercion.nll.stderr index 7e8f78067e08a..92588819076d3 100644 --- a/src/test/ui/regions/region-object-lifetime-in-coercion.nll.stderr +++ b/src/test/ui/regions/region-object-lifetime-in-coercion.nll.stderr @@ -31,7 +31,7 @@ LL | fn d<'a,'b>(v: &'a [u8]) -> Box { | | | lifetime `'a` defined here LL | Box::new(v) - | ^^^^^^^^^^^ returning this value requires that `'a` must outlive `'b` + | ^^^^^^^^^^^ function was supposed to return data with lifetime `'b` but it is returning data with lifetime `'a` | = help: consider adding the following bound: `'a: 'b` diff --git a/src/test/ui/regions/regions-bounded-method-type-parameters-trait-bound.nll.stderr b/src/test/ui/regions/regions-bounded-method-type-parameters-trait-bound.nll.stderr index 62032bcb6092c..246b6483c21a8 100644 --- a/src/test/ui/regions/regions-bounded-method-type-parameters-trait-bound.nll.stderr +++ b/src/test/ui/regions/regions-bounded-method-type-parameters-trait-bound.nll.stderr @@ -1,18 +1,13 @@ -error[E0521]: borrowed data escapes outside of function +error: lifetime may not live long enough --> $DIR/regions-bounded-method-type-parameters-trait-bound.rs:20:5 | LL | fn caller2<'a,'b,F:Foo<'a>>(a: Inv<'a>, b: Inv<'b>, f: F) { - | -- -- - - `b` is a reference that is only valid in the function body - | | | | - | | | `a` declared here, outside of the function body - | | lifetime `'b` defined here + | -- -- lifetime `'b` defined here + | | | lifetime `'a` defined here LL | // Here the value provided for 'y is 'b, and hence 'b:'a does not hold. LL | f.method(b); - | ^^^^^^^^^^^ - | | - | `b` escapes the function body here - | argument requires that `'b` must outlive `'a` + | ^^^^^^^^^^^ argument requires that `'b` must outlive `'a` | = help: consider adding the following bound: `'b: 'a` = note: requirement occurs because of the type Inv<'_>, which makes the generic argument '_ invariant @@ -21,4 +16,3 @@ LL | f.method(b); error: aborting due to previous error -For more information about this error, try `rustc --explain E0521`. diff --git a/src/test/ui/regions/regions-bounds.nll.stderr b/src/test/ui/regions/regions-bounds.nll.stderr index dd702755c7e7b..84226a5755319 100644 --- a/src/test/ui/regions/regions-bounds.nll.stderr +++ b/src/test/ui/regions/regions-bounds.nll.stderr @@ -6,7 +6,7 @@ LL | fn a_fn1<'a,'b>(e: TupleStruct<'a>) -> TupleStruct<'b> { | | | lifetime `'a` defined here LL | return e; - | ^ returning this value requires that `'a` must outlive `'b` + | ^ function was supposed to return data with lifetime `'b` but it is returning data with lifetime `'a` | = help: consider adding the following bound: `'a: 'b` @@ -18,7 +18,7 @@ LL | fn a_fn3<'a,'b>(e: Struct<'a>) -> Struct<'b> { | | | lifetime `'a` defined here LL | return e; - | ^ returning this value requires that `'a` must outlive `'b` + | ^ function was supposed to return data with lifetime `'b` but it is returning data with lifetime `'a` | = help: consider adding the following bound: `'a: 'b` diff --git a/src/test/ui/regions/regions-close-over-type-parameter-multiple.nll.stderr b/src/test/ui/regions/regions-close-over-type-parameter-multiple.nll.stderr index c2bd3bbf823d2..25566742099c2 100644 --- a/src/test/ui/regions/regions-close-over-type-parameter-multiple.nll.stderr +++ b/src/test/ui/regions/regions-close-over-type-parameter-multiple.nll.stderr @@ -7,7 +7,7 @@ LL | fn make_object_bad<'a,'b,'c,A:SomeTrait+'a+'b>(v: A) -> Box - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ returning this value requires that `'a` must outlive `'c` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ function was supposed to return data with lifetime `'c` but it is returning data with lifetime `'a` | = help: consider adding the following bound: `'a: 'c` diff --git a/src/test/ui/regions/regions-creating-enums4.nll.stderr b/src/test/ui/regions/regions-creating-enums4.nll.stderr index dda374c90d937..91cf57e099df9 100644 --- a/src/test/ui/regions/regions-creating-enums4.nll.stderr +++ b/src/test/ui/regions/regions-creating-enums4.nll.stderr @@ -6,7 +6,7 @@ LL | fn mk_add_bad2<'a,'b>(x: &'a Ast<'a>, y: &'a Ast<'a>, z: &Ast) -> Ast<'b> { | | | lifetime `'a` defined here LL | Ast::Add(x, y) - | ^^^^^^^^^^^^^^ returning this value requires that `'a` must outlive `'b` + | ^^^^^^^^^^^^^^ function was supposed to return data with lifetime `'b` but it is returning data with lifetime `'a` | = help: consider adding the following bound: `'a: 'b` diff --git a/src/test/ui/regions/regions-early-bound-error-method.nll.stderr b/src/test/ui/regions/regions-early-bound-error-method.nll.stderr index 4957bcf3f7371..7f10c051f2998 100644 --- a/src/test/ui/regions/regions-early-bound-error-method.nll.stderr +++ b/src/test/ui/regions/regions-early-bound-error-method.nll.stderr @@ -6,7 +6,7 @@ LL | impl<'a> Box<'a> { LL | fn or<'b,G:GetRef<'b>>(&self, g2: G) -> &'a isize { | -- lifetime `'b` defined here LL | g2.get() - | ^^^^^^^^ returning this value requires that `'b` must outlive `'a` + | ^^^^^^^^ associated function was supposed to return data with lifetime `'a` but it is returning data with lifetime `'b` | = help: consider adding the following bound: `'b: 'a` diff --git a/src/test/ui/regions/regions-free-region-ordering-incorrect.nll.stderr b/src/test/ui/regions/regions-free-region-ordering-incorrect.nll.stderr index 106d3df274435..f7c75033c0486 100644 --- a/src/test/ui/regions/regions-free-region-ordering-incorrect.nll.stderr +++ b/src/test/ui/regions/regions-free-region-ordering-incorrect.nll.stderr @@ -9,7 +9,7 @@ LL | / match self.next { LL | | Some(ref next) => next.get(), LL | | None => &self.val LL | | } - | |_________^ returning this value requires that `'a` must outlive `'b` + | |_________^ associated function was supposed to return data with lifetime `'b` but it is returning data with lifetime `'a` | = help: consider adding the following bound: `'a: 'b` diff --git a/src/test/ui/regions/regions-infer-not-param.nll.stderr b/src/test/ui/regions/regions-infer-not-param.nll.stderr index e211f9d1391f9..3183aee23d936 100644 --- a/src/test/ui/regions/regions-infer-not-param.nll.stderr +++ b/src/test/ui/regions/regions-infer-not-param.nll.stderr @@ -2,7 +2,7 @@ error: lifetime may not live long enough --> $DIR/regions-infer-not-param.rs:15:54 | LL | fn take_direct<'a,'b>(p: Direct<'a>) -> Direct<'b> { p } - | -- -- lifetime `'b` defined here ^ returning this value requires that `'a` must outlive `'b` + | -- -- lifetime `'b` defined here ^ function was supposed to return data with lifetime `'b` but it is returning data with lifetime `'a` | | | lifetime `'a` defined here | @@ -25,7 +25,7 @@ error: lifetime may not live long enough --> $DIR/regions-infer-not-param.rs:19:63 | LL | fn take_indirect2<'a,'b>(p: Indirect2<'a>) -> Indirect2<'b> { p } - | -- -- lifetime `'b` defined here ^ returning this value requires that `'a` must outlive `'b` + | -- -- lifetime `'b` defined here ^ function was supposed to return data with lifetime `'b` but it is returning data with lifetime `'a` | | | lifetime `'a` defined here | diff --git a/src/test/ui/regions/regions-trait-object-subtyping.nll.stderr b/src/test/ui/regions/regions-trait-object-subtyping.nll.stderr index bf325d5601348..26f0fcae638d0 100644 --- a/src/test/ui/regions/regions-trait-object-subtyping.nll.stderr +++ b/src/test/ui/regions/regions-trait-object-subtyping.nll.stderr @@ -7,7 +7,7 @@ LL | fn foo3<'a,'b>(x: &'a mut dyn Dummy) -> &'b mut dyn Dummy { | lifetime `'a` defined here LL | // Without knowing 'a:'b, we can't coerce LL | x - | ^ returning this value requires that `'a` must outlive `'b` + | ^ function was supposed to return data with lifetime `'b` but it is returning data with lifetime `'a` | = help: consider adding the following bound: `'a: 'b` = note: requirement occurs because of a mutable reference to dyn Dummy @@ -23,7 +23,7 @@ LL | fn foo4<'a:'b,'b>(x: Wrapper<&'a mut dyn Dummy>) -> Wrapper<&'b mut dyn Dum | lifetime `'a` defined here LL | // We can't coerce because it is packed in `Wrapper` LL | x - | ^ returning this value requires that `'b` must outlive `'a` + | ^ function was supposed to return data with lifetime `'a` but it is returning data with lifetime `'b` | = help: consider adding the following bound: `'b: 'a` = note: requirement occurs because of a mutable reference to dyn Dummy diff --git a/src/test/ui/variance/variance-contravariant-arg-object.nll.stderr b/src/test/ui/variance/variance-contravariant-arg-object.nll.stderr index 91d4fd2e971fa..3315eaaf1c006 100644 --- a/src/test/ui/variance/variance-contravariant-arg-object.nll.stderr +++ b/src/test/ui/variance/variance-contravariant-arg-object.nll.stderr @@ -7,7 +7,7 @@ LL | fn get_min_from_max<'min, 'max>(v: Box>) | lifetime `'min` defined here ... LL | v - | ^ returning this value requires that `'min` must outlive `'max` + | ^ function was supposed to return data with lifetime `'max` but it is returning data with lifetime `'min` | = help: consider adding the following bound: `'min: 'max` @@ -20,7 +20,7 @@ LL | fn get_max_from_min<'min, 'max, G>(v: Box>) | lifetime `'min` defined here ... LL | v - | ^ returning this value requires that `'min` must outlive `'max` + | ^ function was supposed to return data with lifetime `'max` but it is returning data with lifetime `'min` | = help: consider adding the following bound: `'min: 'max` diff --git a/src/test/ui/variance/variance-covariant-arg-object.nll.stderr b/src/test/ui/variance/variance-covariant-arg-object.nll.stderr index 37fdea960be7c..b116b8e263fd2 100644 --- a/src/test/ui/variance/variance-covariant-arg-object.nll.stderr +++ b/src/test/ui/variance/variance-covariant-arg-object.nll.stderr @@ -7,7 +7,7 @@ LL | fn get_min_from_max<'min, 'max>(v: Box>) | lifetime `'min` defined here ... LL | v - | ^ returning this value requires that `'min` must outlive `'max` + | ^ function was supposed to return data with lifetime `'max` but it is returning data with lifetime `'min` | = help: consider adding the following bound: `'min: 'max` @@ -20,7 +20,7 @@ LL | fn get_max_from_min<'min, 'max, G>(v: Box>) | lifetime `'min` defined here ... LL | v - | ^ returning this value requires that `'min` must outlive `'max` + | ^ function was supposed to return data with lifetime `'max` but it is returning data with lifetime `'min` | = help: consider adding the following bound: `'min: 'max` diff --git a/src/test/ui/variance/variance-invariant-arg-object.nll.stderr b/src/test/ui/variance/variance-invariant-arg-object.nll.stderr index f6265980af7da..303c7f3388a74 100644 --- a/src/test/ui/variance/variance-invariant-arg-object.nll.stderr +++ b/src/test/ui/variance/variance-invariant-arg-object.nll.stderr @@ -7,7 +7,7 @@ LL | fn get_min_from_max<'min, 'max>(v: Box>) | lifetime `'min` defined here ... LL | v - | ^ returning this value requires that `'min` must outlive `'max` + | ^ function was supposed to return data with lifetime `'max` but it is returning data with lifetime `'min` | = help: consider adding the following bound: `'min: 'max` @@ -20,7 +20,7 @@ LL | fn get_max_from_min<'min, 'max, G>(v: Box>) | lifetime `'min` defined here ... LL | v - | ^ returning this value requires that `'min` must outlive `'max` + | ^ function was supposed to return data with lifetime `'max` but it is returning data with lifetime `'min` | = help: consider adding the following bound: `'min: 'max` diff --git a/src/test/ui/variance/variance-use-contravariant-struct-1.nll.stderr b/src/test/ui/variance/variance-use-contravariant-struct-1.nll.stderr index eddd4b217c088..837c70ca31367 100644 --- a/src/test/ui/variance/variance-use-contravariant-struct-1.nll.stderr +++ b/src/test/ui/variance/variance-use-contravariant-struct-1.nll.stderr @@ -7,7 +7,7 @@ LL | fn foo<'min,'max>(v: SomeStruct<&'max ()>) | lifetime `'min` defined here ... LL | v - | ^ returning this value requires that `'min` must outlive `'max` + | ^ function was supposed to return data with lifetime `'max` but it is returning data with lifetime `'min` | = help: consider adding the following bound: `'min: 'max` diff --git a/src/test/ui/variance/variance-use-covariant-struct-1.nll.stderr b/src/test/ui/variance/variance-use-covariant-struct-1.nll.stderr index a86c1b93a73b8..bab858c5acb37 100644 --- a/src/test/ui/variance/variance-use-covariant-struct-1.nll.stderr +++ b/src/test/ui/variance/variance-use-covariant-struct-1.nll.stderr @@ -7,7 +7,7 @@ LL | fn foo<'min,'max>(v: SomeStruct<&'min ()>) | lifetime `'min` defined here ... LL | v - | ^ returning this value requires that `'min` must outlive `'max` + | ^ function was supposed to return data with lifetime `'max` but it is returning data with lifetime `'min` | = help: consider adding the following bound: `'min: 'max` diff --git a/src/test/ui/variance/variance-use-invariant-struct-1.nll.stderr b/src/test/ui/variance/variance-use-invariant-struct-1.nll.stderr index 6890cb115c398..f1df2a88b6bab 100644 --- a/src/test/ui/variance/variance-use-invariant-struct-1.nll.stderr +++ b/src/test/ui/variance/variance-use-invariant-struct-1.nll.stderr @@ -7,7 +7,7 @@ LL | fn foo<'min,'max>(v: SomeStruct<&'max ()>) | lifetime `'min` defined here ... LL | v - | ^ returning this value requires that `'min` must outlive `'max` + | ^ function was supposed to return data with lifetime `'max` but it is returning data with lifetime `'min` | = help: consider adding the following bound: `'min: 'max` = note: requirement occurs because of the type SomeStruct<&()>, which makes the generic argument &() invariant @@ -23,7 +23,7 @@ LL | fn bar<'min,'max>(v: SomeStruct<&'min ()>) | lifetime `'min` defined here ... LL | v - | ^ returning this value requires that `'min` must outlive `'max` + | ^ function was supposed to return data with lifetime `'max` but it is returning data with lifetime `'min` | = help: consider adding the following bound: `'min: 'max` = note: requirement occurs because of the type SomeStruct<&()>, which makes the generic argument &() invariant diff --git a/src/test/ui/wf/wf-static-method.nll.stderr b/src/test/ui/wf/wf-static-method.nll.stderr index 9c066a7bdb06c..265043111956a 100644 --- a/src/test/ui/wf/wf-static-method.nll.stderr +++ b/src/test/ui/wf/wf-static-method.nll.stderr @@ -7,7 +7,7 @@ LL | impl<'a, 'b> Foo<'a, 'b, Evil<'a, 'b>> for () { | lifetime `'a` defined here ... LL | u - | ^ returning this value requires that `'b` must outlive `'a` + | ^ associated function was supposed to return data with lifetime `'a` but it is returning data with lifetime `'b` | = help: consider adding the following bound: `'b: 'a` @@ -33,7 +33,7 @@ LL | impl<'a, 'b> Evil<'a, 'b> { | lifetime `'a` defined here LL | fn inherent_evil(u: &'b u32) -> &'a u32 { LL | u - | ^ returning this value requires that `'b` must outlive `'a` + | ^ associated function was supposed to return data with lifetime `'a` but it is returning data with lifetime `'b` | = help: consider adding the following bound: `'b: 'a` @@ -45,7 +45,7 @@ LL | fn evil<'a, 'b>(b: &'b u32) -> &'a u32 { | | | lifetime `'a` defined here LL | <()>::static_evil(b) - | ^^^^^^^^^^^^^^^^^^^^ returning this value requires that `'b` must outlive `'a` + | ^^^^^^^^^^^^^^^^^^^^ function was supposed to return data with lifetime `'a` but it is returning data with lifetime `'b` | = help: consider adding the following bound: `'b: 'a` @@ -57,7 +57,7 @@ LL | fn indirect_evil<'a, 'b>(b: &'b u32) -> &'a u32 { | | | lifetime `'a` defined here LL | ::static_evil(b) - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ returning this value requires that `'b` must outlive `'a` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ function was supposed to return data with lifetime `'a` but it is returning data with lifetime `'b` | = help: consider adding the following bound: `'b: 'a` @@ -69,7 +69,7 @@ LL | fn inherent_evil<'a, 'b>(b: &'b u32) -> &'a u32 { | | | lifetime `'a` defined here LL | ::inherent_evil(b) - | ^^^^^^^^^^^^^^^^^^^^^^^^ returning this value requires that `'b` must outlive `'a` + | ^^^^^^^^^^^^^^^^^^^^^^^^ function was supposed to return data with lifetime `'a` but it is returning data with lifetime `'b` | = help: consider adding the following bound: `'b: 'a` From 90330b5330954d0e60b44c934e14f6323a759e1d Mon Sep 17 00:00:00 2001 From: Ivor Wanders Date: Wed, 12 Jan 2022 19:04:16 -0500 Subject: [PATCH 02/21] Improve error message for cfg arguments. This provides the user with a helpful error message in case a key="value" message was specified but couldn't be parsed. --- compiler/rustc_interface/src/interface.rs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/compiler/rustc_interface/src/interface.rs b/compiler/rustc_interface/src/interface.rs index 3804e10030733..8fa1e18df3c35 100644 --- a/compiler/rustc_interface/src/interface.rs +++ b/compiler/rustc_interface/src/interface.rs @@ -124,7 +124,10 @@ pub fn parse_cfgspecs(cfgspecs: Vec) -> FxHashSet<(String, Option errs.into_iter().for_each(|mut err| err.cancel()), } - error!(r#"expected `key` or `key="value"`"#); + error!(concat!( + r#"expected `key` or `key="value"`, ensure escaping is appropriate"#, + r#" for your shell, try 'key="value"' or key=\"value\""# + )); }) .collect::(); cfg.into_iter().map(|(a, b)| (a.to_string(), b.map(|b| b.to_string()))).collect() From db56c6d53adef72067f83f3d34b2881afe6b5d74 Mon Sep 17 00:00:00 2001 From: Ivor Wanders Date: Wed, 12 Jan 2022 19:50:04 -0500 Subject: [PATCH 03/21] Update unit tests to accomodate for improved error. --- src/test/ui/conditional-compilation/cfg-arg-invalid-1.rs | 2 +- src/test/ui/conditional-compilation/cfg-arg-invalid-1.stderr | 2 +- src/test/ui/conditional-compilation/cfg-arg-invalid-2.rs | 2 +- src/test/ui/conditional-compilation/cfg-arg-invalid-2.stderr | 2 +- src/test/ui/conditional-compilation/cfg-arg-invalid-4.rs | 2 +- src/test/ui/conditional-compilation/cfg-arg-invalid-4.stderr | 2 +- src/test/ui/conditional-compilation/cfg-arg-invalid-6.rs | 2 +- src/test/ui/conditional-compilation/cfg-arg-invalid-6.stderr | 2 +- src/test/ui/conditional-compilation/cfg-arg-invalid-8.rs | 2 +- src/test/ui/conditional-compilation/cfg-arg-invalid-8.stderr | 2 +- src/test/ui/conditional-compilation/cfg-empty-codemap.rs | 2 +- src/test/ui/conditional-compilation/cfg-empty-codemap.stderr | 2 +- 12 files changed, 12 insertions(+), 12 deletions(-) diff --git a/src/test/ui/conditional-compilation/cfg-arg-invalid-1.rs b/src/test/ui/conditional-compilation/cfg-arg-invalid-1.rs index 36dd78dd2b19a..d20e79b9db338 100644 --- a/src/test/ui/conditional-compilation/cfg-arg-invalid-1.rs +++ b/src/test/ui/conditional-compilation/cfg-arg-invalid-1.rs @@ -1,3 +1,3 @@ // compile-flags: --cfg a(b=c) -// error-pattern: invalid `--cfg` argument: `a(b=c)` (expected `key` or `key="value"`) +// error-pattern: invalid `--cfg` argument: `a(b=c)` (expected `key` or `key="value"`, ensure escaping is appropriate for your shell, try 'key="value"' or key=\"value\") fn main() {} diff --git a/src/test/ui/conditional-compilation/cfg-arg-invalid-1.stderr b/src/test/ui/conditional-compilation/cfg-arg-invalid-1.stderr index 1e7922a9ff155..3a12e97868000 100644 --- a/src/test/ui/conditional-compilation/cfg-arg-invalid-1.stderr +++ b/src/test/ui/conditional-compilation/cfg-arg-invalid-1.stderr @@ -1,2 +1,2 @@ -error: invalid `--cfg` argument: `a(b=c)` (expected `key` or `key="value"`) +error: invalid `--cfg` argument: `a(b=c)` (expected `key` or `key="value"`, ensure escaping is appropriate for your shell, try 'key="value"' or key=\"value\") diff --git a/src/test/ui/conditional-compilation/cfg-arg-invalid-2.rs b/src/test/ui/conditional-compilation/cfg-arg-invalid-2.rs index 48d656a4a28d9..660d5d1b1ea90 100644 --- a/src/test/ui/conditional-compilation/cfg-arg-invalid-2.rs +++ b/src/test/ui/conditional-compilation/cfg-arg-invalid-2.rs @@ -1,3 +1,3 @@ // compile-flags: --cfg a{b} -// error-pattern: invalid `--cfg` argument: `a{b}` (expected `key` or `key="value"`) +// error-pattern: invalid `--cfg` argument: `a{b}` (expected `key` or `key="value"`, ensure escaping is appropriate for your shell, try 'key="value"' or key=\"value\") fn main() {} diff --git a/src/test/ui/conditional-compilation/cfg-arg-invalid-2.stderr b/src/test/ui/conditional-compilation/cfg-arg-invalid-2.stderr index b92e1fd3d97cf..2e141137129dc 100644 --- a/src/test/ui/conditional-compilation/cfg-arg-invalid-2.stderr +++ b/src/test/ui/conditional-compilation/cfg-arg-invalid-2.stderr @@ -1,2 +1,2 @@ -error: invalid `--cfg` argument: `a{b}` (expected `key` or `key="value"`) +error: invalid `--cfg` argument: `a{b}` (expected `key` or `key="value"`, ensure escaping is appropriate for your shell, try 'key="value"' or key=\"value\") diff --git a/src/test/ui/conditional-compilation/cfg-arg-invalid-4.rs b/src/test/ui/conditional-compilation/cfg-arg-invalid-4.rs index e7dfa17b4b6c4..d8b3c0284cca6 100644 --- a/src/test/ui/conditional-compilation/cfg-arg-invalid-4.rs +++ b/src/test/ui/conditional-compilation/cfg-arg-invalid-4.rs @@ -1,3 +1,3 @@ // compile-flags: --cfg a(b) -// error-pattern: invalid `--cfg` argument: `a(b)` (expected `key` or `key="value"`) +// error-pattern: invalid `--cfg` argument: `a(b)` (expected `key` or `key="value"`, ensure escaping is appropriate for your shell, try 'key="value"' or key=\"value\") fn main() {} diff --git a/src/test/ui/conditional-compilation/cfg-arg-invalid-4.stderr b/src/test/ui/conditional-compilation/cfg-arg-invalid-4.stderr index 6853a69b9eb22..52685d7b4a233 100644 --- a/src/test/ui/conditional-compilation/cfg-arg-invalid-4.stderr +++ b/src/test/ui/conditional-compilation/cfg-arg-invalid-4.stderr @@ -1,2 +1,2 @@ -error: invalid `--cfg` argument: `a(b)` (expected `key` or `key="value"`) +error: invalid `--cfg` argument: `a(b)` (expected `key` or `key="value"`, ensure escaping is appropriate for your shell, try 'key="value"' or key=\"value\") diff --git a/src/test/ui/conditional-compilation/cfg-arg-invalid-6.rs b/src/test/ui/conditional-compilation/cfg-arg-invalid-6.rs index 9fa726f93e3ea..4a0d116e644b5 100644 --- a/src/test/ui/conditional-compilation/cfg-arg-invalid-6.rs +++ b/src/test/ui/conditional-compilation/cfg-arg-invalid-6.rs @@ -1,3 +1,3 @@ // compile-flags: --cfg a{ -// error-pattern: invalid `--cfg` argument: `a{` (expected `key` or `key="value"`) +// error-pattern: invalid `--cfg` argument: `a{` (expected `key` or `key="value"`, ensure escaping is appropriate for your shell, try 'key="value"' or key=\"value\") fn main() {} diff --git a/src/test/ui/conditional-compilation/cfg-arg-invalid-6.stderr b/src/test/ui/conditional-compilation/cfg-arg-invalid-6.stderr index 7d2087b4b71f7..618d12aba68e9 100644 --- a/src/test/ui/conditional-compilation/cfg-arg-invalid-6.stderr +++ b/src/test/ui/conditional-compilation/cfg-arg-invalid-6.stderr @@ -1,2 +1,2 @@ -error: invalid `--cfg` argument: `a{` (expected `key` or `key="value"`) +error: invalid `--cfg` argument: `a{` (expected `key` or `key="value"`, ensure escaping is appropriate for your shell, try 'key="value"' or key=\"value\") diff --git a/src/test/ui/conditional-compilation/cfg-arg-invalid-8.rs b/src/test/ui/conditional-compilation/cfg-arg-invalid-8.rs index 1d7fa7885348e..7c5531606fa34 100644 --- a/src/test/ui/conditional-compilation/cfg-arg-invalid-8.rs +++ b/src/test/ui/conditional-compilation/cfg-arg-invalid-8.rs @@ -1,3 +1,3 @@ // compile-flags: --cfg ) -// error-pattern: invalid `--cfg` argument: `)` (expected `key` or `key="value"`) +// error-pattern: invalid `--cfg` argument: `)` (expected `key` or `key="value"`, ensure escaping is appropriate for your shell, try 'key="value"' or key=\"value\") fn main() {} diff --git a/src/test/ui/conditional-compilation/cfg-arg-invalid-8.stderr b/src/test/ui/conditional-compilation/cfg-arg-invalid-8.stderr index 7bb1814127b29..16bb552f0d999 100644 --- a/src/test/ui/conditional-compilation/cfg-arg-invalid-8.stderr +++ b/src/test/ui/conditional-compilation/cfg-arg-invalid-8.stderr @@ -1,2 +1,2 @@ -error: invalid `--cfg` argument: `)` (expected `key` or `key="value"`) +error: invalid `--cfg` argument: `)` (expected `key` or `key="value"`, ensure escaping is appropriate for your shell, try 'key="value"' or key=\"value\") diff --git a/src/test/ui/conditional-compilation/cfg-empty-codemap.rs b/src/test/ui/conditional-compilation/cfg-empty-codemap.rs index 9e34cacf74d2a..c23d2cee924b7 100644 --- a/src/test/ui/conditional-compilation/cfg-empty-codemap.rs +++ b/src/test/ui/conditional-compilation/cfg-empty-codemap.rs @@ -2,7 +2,7 @@ // compile-flags: --cfg "" -// error-pattern: invalid `--cfg` argument: `""` (expected `key` or `key="value"`) +// error-pattern: invalid `--cfg` argument: `""` (expected `key` or `key="value"`, ensure escaping is appropriate for your shell, try 'key="value"' or key=\"value\") pub fn main() { } diff --git a/src/test/ui/conditional-compilation/cfg-empty-codemap.stderr b/src/test/ui/conditional-compilation/cfg-empty-codemap.stderr index 128e3cd730680..55e3dc131ae9f 100644 --- a/src/test/ui/conditional-compilation/cfg-empty-codemap.stderr +++ b/src/test/ui/conditional-compilation/cfg-empty-codemap.stderr @@ -1,2 +1,2 @@ -error: invalid `--cfg` argument: `""` (expected `key` or `key="value"`) +error: invalid `--cfg` argument: `""` (expected `key` or `key="value"`, ensure escaping is appropriate for your shell, try 'key="value"' or key=\"value\") From 2835ace4ca1901b60678484ece129a4f60bd1887 Mon Sep 17 00:00:00 2001 From: Noah Lev Date: Wed, 12 Jan 2022 22:04:39 -0800 Subject: [PATCH 04/21] Improve suggestions for type errors with string concatenation Now, multipart suggestions are used instead of `span_to_snippet`, which improves code quality, makes the suggestion work even without access to source code, and, most importantly, improves the rendering of the suggestion. --- compiler/rustc_typeck/src/check/op.rs | 78 +++++++------------ src/test/ui/issues/issue-47377.stderr | 2 +- src/test/ui/issues/issue-47380.stderr | 2 +- src/test/ui/span/issue-39018.stderr | 26 ++++--- .../ui/str/str-concat-on-double-ref.stderr | 2 +- ...non-1-width-unicode-multiline-label.stderr | 2 +- 6 files changed, 47 insertions(+), 65 deletions(-) diff --git a/compiler/rustc_typeck/src/check/op.rs b/compiler/rustc_typeck/src/check/op.rs index 8ebfcdd539b67..838f8b0a61d17 100644 --- a/compiler/rustc_typeck/src/check/op.rs +++ b/compiler/rustc_typeck/src/check/op.rs @@ -549,7 +549,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { is_assign: IsAssign, op: hir::BinOp, ) -> bool { - let source_map = self.tcx.sess.source_map(); let remove_borrow_msg = "String concatenation appends the string on the right to the \ string on the left and may require reallocation. This \ requires ownership of the string on the left"; @@ -574,31 +573,22 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { ) => { if let IsAssign::No = is_assign { // Do not supply this message if `&str += &str` - err.span_label( - op.span, - "`+` cannot be used to concatenate two `&str` strings", - ); - match source_map.span_to_snippet(lhs_expr.span) { - Ok(lstring) => { - err.span_suggestion( - lhs_expr.span, - if lstring.starts_with('&') { - remove_borrow_msg - } else { - msg - }, - if let Some(stripped) = lstring.strip_prefix('&') { - // let a = String::new(); - // let _ = &a + "bar"; - stripped.to_string() - } else { - format!("{}.to_owned()", lstring) - }, - Applicability::MachineApplicable, - ) - } - _ => err.help(msg), - }; + err.span_label(op.span, "`+` cannot be used to concatenate two `&str` strings"); + if let hir::ExprKind::AddrOf(_,_,lhs_inner_expr) = lhs_expr.kind { + err.span_suggestion( + lhs_expr.span.until(lhs_inner_expr.span), + remove_borrow_msg, + "".to_owned(), + Applicability::MachineApplicable + ); + } else { + err.span_suggestion( + lhs_expr.span.shrink_to_hi(), + msg, + ".to_owned()".to_owned(), + Applicability::MachineApplicable + ); + } } true } @@ -609,32 +599,22 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { op.span, "`+` cannot be used to concatenate a `&str` with a `String`", ); - match ( - source_map.span_to_snippet(lhs_expr.span), - source_map.span_to_snippet(rhs_expr.span), - is_assign, - ) { - (Ok(l), Ok(r), IsAssign::No) => { - let to_string = if let Some(stripped) = l.strip_prefix('&') { - // let a = String::new(); let b = String::new(); - // let _ = &a + b; - stripped.to_string() - } else { - format!("{}.to_owned()", l) - }; - err.multipart_suggestion( - msg, - vec![ - (lhs_expr.span, to_string), - (rhs_expr.span, format!("&{}", r)), - ], - Applicability::MachineApplicable, - ); + match is_assign { + IsAssign::No => { + let suggestions = vec![ + if let hir::ExprKind::AddrOf(_, _, lhs_inner_expr) = lhs_expr.kind { + (lhs_expr.span.until(lhs_inner_expr.span), "".to_owned()) + } else { + (lhs_expr.span.shrink_to_hi(), ".to_owned()".to_owned()) + }, + (rhs_expr.span.shrink_to_lo(), "&".to_owned()), + ]; + err.multipart_suggestion(msg, suggestions, Applicability::MachineApplicable); } - _ => { + IsAssign::Yes => { err.help(msg); } - }; + } true } _ => false, diff --git a/src/test/ui/issues/issue-47377.stderr b/src/test/ui/issues/issue-47377.stderr index a7b8b1ca86167..2c17a19779f8f 100644 --- a/src/test/ui/issues/issue-47377.stderr +++ b/src/test/ui/issues/issue-47377.stderr @@ -10,7 +10,7 @@ LL | let _a = b + ", World!"; help: `to_owned()` can be used to create an owned `String` from a string reference. String concatenation appends the string on the right to the string on the left and may require reallocation. This requires ownership of the string on the left | LL | let _a = b.to_owned() + ", World!"; - | ~~~~~~~~~~~~ + | +++++++++++ error: aborting due to previous error diff --git a/src/test/ui/issues/issue-47380.stderr b/src/test/ui/issues/issue-47380.stderr index f6222c77e2e25..417206e6cc4fb 100644 --- a/src/test/ui/issues/issue-47380.stderr +++ b/src/test/ui/issues/issue-47380.stderr @@ -10,7 +10,7 @@ LL | println!("🦀🦀🦀🦀🦀"); let _a = b + ", World!"; help: `to_owned()` can be used to create an owned `String` from a string reference. String concatenation appends the string on the right to the string on the left and may require reallocation. This requires ownership of the string on the left | LL | println!("🦀🦀🦀🦀🦀"); let _a = b.to_owned() + ", World!"; - | ~~~~~~~~~~~~ + | +++++++++++ error: aborting due to previous error diff --git a/src/test/ui/span/issue-39018.stderr b/src/test/ui/span/issue-39018.stderr index 92e86bf5d6c91..444d037571e18 100644 --- a/src/test/ui/span/issue-39018.stderr +++ b/src/test/ui/span/issue-39018.stderr @@ -10,7 +10,7 @@ LL | let x = "Hello " + "World!"; help: `to_owned()` can be used to create an owned `String` from a string reference. String concatenation appends the string on the right to the string on the left and may require reallocation. This requires ownership of the string on the left | LL | let x = "Hello ".to_owned() + "World!"; - | ~~~~~~~~~~~~~~~~~~~ + | +++++++++++ error[E0369]: cannot add `World` to `World` --> $DIR/issue-39018.rs:8:26 @@ -49,7 +49,7 @@ LL | let x = "Hello " + "World!".to_owned(); help: `to_owned()` can be used to create an owned `String` from a string reference. String concatenation appends the string on the right to the string on the left and may require reallocation. This requires ownership of the string on the left | LL | let x = "Hello ".to_owned() + &"World!".to_owned(); - | ~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~ + | +++++++++++ + error[E0369]: cannot add `&String` to `&String` --> $DIR/issue-39018.rs:26:16 @@ -62,8 +62,9 @@ LL | let _ = &a + &b; | help: String concatenation appends the string on the right to the string on the left and may require reallocation. This requires ownership of the string on the left | -LL | let _ = a + &b; - | ~ +LL - let _ = &a + &b; +LL + let _ = a + &b; + | error[E0369]: cannot add `String` to `&String` --> $DIR/issue-39018.rs:27:16 @@ -76,8 +77,9 @@ LL | let _ = &a + b; | help: `to_owned()` can be used to create an owned `String` from a string reference. String concatenation appends the string on the right to the string on the left and may require reallocation. This requires ownership of the string on the left | -LL | let _ = a + &b; - | ~ ~~ +LL - let _ = &a + b; +LL + let _ = a + &b; + | error[E0308]: mismatched types --> $DIR/issue-39018.rs:29:17 @@ -100,7 +102,7 @@ LL | let _ = e + b; help: `to_owned()` can be used to create an owned `String` from a string reference. String concatenation appends the string on the right to the string on the left and may require reallocation. This requires ownership of the string on the left | LL | let _ = e.to_owned() + &b; - | ~~~~~~~~~~~~ ~~ + | +++++++++++ + error[E0369]: cannot add `&String` to `&String` --> $DIR/issue-39018.rs:31:15 @@ -114,7 +116,7 @@ LL | let _ = e + &b; help: `to_owned()` can be used to create an owned `String` from a string reference. String concatenation appends the string on the right to the string on the left and may require reallocation. This requires ownership of the string on the left | LL | let _ = e.to_owned() + &b; - | ~~~~~~~~~~~~ + | +++++++++++ error[E0369]: cannot add `&str` to `&String` --> $DIR/issue-39018.rs:32:15 @@ -128,7 +130,7 @@ LL | let _ = e + d; help: `to_owned()` can be used to create an owned `String` from a string reference. String concatenation appends the string on the right to the string on the left and may require reallocation. This requires ownership of the string on the left | LL | let _ = e.to_owned() + d; - | ~~~~~~~~~~~~ + | +++++++++++ error[E0369]: cannot add `&&str` to `&String` --> $DIR/issue-39018.rs:33:15 @@ -142,7 +144,7 @@ LL | let _ = e + &d; help: `to_owned()` can be used to create an owned `String` from a string reference. String concatenation appends the string on the right to the string on the left and may require reallocation. This requires ownership of the string on the left | LL | let _ = e.to_owned() + &d; - | ~~~~~~~~~~~~ + | +++++++++++ error[E0369]: cannot add `&&str` to `&&str` --> $DIR/issue-39018.rs:34:16 @@ -172,7 +174,7 @@ LL | let _ = c + &d; help: `to_owned()` can be used to create an owned `String` from a string reference. String concatenation appends the string on the right to the string on the left and may require reallocation. This requires ownership of the string on the left | LL | let _ = c.to_owned() + &d; - | ~~~~~~~~~~~~ + | +++++++++++ error[E0369]: cannot add `&str` to `&str` --> $DIR/issue-39018.rs:37:15 @@ -186,7 +188,7 @@ LL | let _ = c + d; help: `to_owned()` can be used to create an owned `String` from a string reference. String concatenation appends the string on the right to the string on the left and may require reallocation. This requires ownership of the string on the left | LL | let _ = c.to_owned() + d; - | ~~~~~~~~~~~~ + | +++++++++++ error: aborting due to 14 previous errors diff --git a/src/test/ui/str/str-concat-on-double-ref.stderr b/src/test/ui/str/str-concat-on-double-ref.stderr index dee28897f4ddd..cc9456be90169 100644 --- a/src/test/ui/str/str-concat-on-double-ref.stderr +++ b/src/test/ui/str/str-concat-on-double-ref.stderr @@ -10,7 +10,7 @@ LL | let c = a + b; help: `to_owned()` can be used to create an owned `String` from a string reference. String concatenation appends the string on the right to the string on the left and may require reallocation. This requires ownership of the string on the left | LL | let c = a.to_owned() + b; - | ~~~~~~~~~~~~ + | +++++++++++ error: aborting due to previous error diff --git a/src/test/ui/terminal-width/non-1-width-unicode-multiline-label.stderr b/src/test/ui/terminal-width/non-1-width-unicode-multiline-label.stderr index 480f442fedd28..2da3db4a7fa81 100644 --- a/src/test/ui/terminal-width/non-1-width-unicode-multiline-label.stderr +++ b/src/test/ui/terminal-width/non-1-width-unicode-multiline-label.stderr @@ -10,7 +10,7 @@ LL | ...ཽཾཿ྄ཱྀྀྂྃ྅྆྇ྈྉྊྋྌྍྎྏྐྑྒྒྷྔ help: `to_owned()` can be used to create an owned `String` from a string reference. String concatenation appends the string on the right to the string on the left and may require reallocation. This requires ownership of the string on the left | LL | let _ = "ༀ༁༂༃༄༅༆༇༈༉༊་༌།༎༏༐༑༒༓༔༕༖༗༘༙༚༛༜༝༞༟༠༡༢༣༤༥༦༧༨༩༪༫༬༭༮༯༰༱༲༳༴༵༶༷༸༹༺༻༼༽༾༿ཀཁགགྷངཅཆཇ཈ཉཊཋཌཌྷཎཏཐདདྷནཔཕབབྷམཙཚཛཛྷཝཞཟའཡརལཤཥསཧཨཀྵཪཫཬ཭཮཯཰ཱཱཱིིུུྲྀཷླྀཹེཻོཽཾཿ྄ཱྀྀྂྃ྅྆྇ྈྉྊྋྌྍྎྏྐྑྒྒྷྔྕྖྗ྘ྙྚྛྜྜྷྞྟྠྡྡྷྣྤྥྦྦྷྨྩྪྫྫྷྭྮྯྰྱྲླྴྵྶྷྸྐྵྺྻྼ྽྾྿࿀࿁࿂࿃࿄࿅࿆࿇࿈࿉࿊࿋࿌࿍࿎࿏࿐࿑࿒࿓࿔࿕࿖࿗࿘࿙࿚"; let _a = unicode_is_fun.to_owned() + " really fun!"; - | ~~~~~~~~~~~~~~~~~~~~~~~~~ + | +++++++++++ error: aborting due to previous error From 69db5e2c8c8bca8bc513cbe4ffa37dff234ad508 Mon Sep 17 00:00:00 2001 From: Noah Lev Date: Wed, 12 Jan 2022 22:20:13 -0800 Subject: [PATCH 05/21] Split up very long message This should make it easier to read. --- compiler/rustc_typeck/src/check/op.rs | 37 ++++++++++--------- src/test/ui/issues/issue-47377.stderr | 3 +- src/test/ui/issues/issue-47380.stderr | 3 +- src/test/ui/span/issue-39018.stderr | 31 +++++++++------- .../ui/str/str-concat-on-double-ref.stderr | 3 +- ...non-1-width-unicode-multiline-label.stderr | 3 +- 6 files changed, 44 insertions(+), 36 deletions(-) diff --git a/compiler/rustc_typeck/src/check/op.rs b/compiler/rustc_typeck/src/check/op.rs index 838f8b0a61d17..8bb0613f456f7 100644 --- a/compiler/rustc_typeck/src/check/op.rs +++ b/compiler/rustc_typeck/src/check/op.rs @@ -549,15 +549,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { is_assign: IsAssign, op: hir::BinOp, ) -> bool { - let remove_borrow_msg = "String concatenation appends the string on the right to the \ - string on the left and may require reallocation. This \ - requires ownership of the string on the left"; - - let msg = "`to_owned()` can be used to create an owned `String` \ - from a string reference. String concatenation \ - appends the string on the right to the string \ - on the left and may require reallocation. This \ - requires ownership of the string on the left"; + let str_concat_note = "String concatenation appends the string on the right to the \ + string on the left and may require reallocation. This \ + requires ownership of the string on the left."; + let rm_borrow_msg = "remove the borrow to obtain an owned `String`"; + let to_owned_msg = "use `to_owned()` to create an owned `String` from a string reference"; let string_type = self.tcx.get_diagnostic_item(sym::String); let is_std_string = |ty: Ty<'tcx>| match ty.ty_adt_def() { @@ -574,17 +570,18 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { { if let IsAssign::No = is_assign { // Do not supply this message if `&str += &str` err.span_label(op.span, "`+` cannot be used to concatenate two `&str` strings"); + err.note(str_concat_note); if let hir::ExprKind::AddrOf(_,_,lhs_inner_expr) = lhs_expr.kind { err.span_suggestion( lhs_expr.span.until(lhs_inner_expr.span), - remove_borrow_msg, + rm_borrow_msg, "".to_owned(), Applicability::MachineApplicable ); } else { err.span_suggestion( lhs_expr.span.shrink_to_hi(), - msg, + to_owned_msg, ".to_owned()".to_owned(), Applicability::MachineApplicable ); @@ -601,18 +598,22 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { ); match is_assign { IsAssign::No => { + let sugg_msg; + let lhs_sugg = if let hir::ExprKind::AddrOf(_, _, lhs_inner_expr) = lhs_expr.kind { + sugg_msg = "remove the borrow on the left and add one on the right"; + (lhs_expr.span.until(lhs_inner_expr.span), "".to_owned()) + } else { + sugg_msg = "call `.to_owned()` on the left and add a borrow on the right"; + (lhs_expr.span.shrink_to_hi(), ".to_owned()".to_owned()) + }; let suggestions = vec![ - if let hir::ExprKind::AddrOf(_, _, lhs_inner_expr) = lhs_expr.kind { - (lhs_expr.span.until(lhs_inner_expr.span), "".to_owned()) - } else { - (lhs_expr.span.shrink_to_hi(), ".to_owned()".to_owned()) - }, + lhs_sugg, (rhs_expr.span.shrink_to_lo(), "&".to_owned()), ]; - err.multipart_suggestion(msg, suggestions, Applicability::MachineApplicable); + err.multipart_suggestion(sugg_msg, suggestions, Applicability::MachineApplicable); } IsAssign::Yes => { - err.help(msg); + err.note(str_concat_note); } } true diff --git a/src/test/ui/issues/issue-47377.stderr b/src/test/ui/issues/issue-47377.stderr index 2c17a19779f8f..2e00de840870e 100644 --- a/src/test/ui/issues/issue-47377.stderr +++ b/src/test/ui/issues/issue-47377.stderr @@ -7,7 +7,8 @@ LL | let _a = b + ", World!"; | | `+` cannot be used to concatenate two `&str` strings | &str | -help: `to_owned()` can be used to create an owned `String` from a string reference. String concatenation appends the string on the right to the string on the left and may require reallocation. This requires ownership of the string on the left + = note: String concatenation appends the string on the right to the string on the left and may require reallocation. This requires ownership of the string on the left. +help: use `to_owned()` to create an owned `String` from a string reference | LL | let _a = b.to_owned() + ", World!"; | +++++++++++ diff --git a/src/test/ui/issues/issue-47380.stderr b/src/test/ui/issues/issue-47380.stderr index 417206e6cc4fb..fec64009444cb 100644 --- a/src/test/ui/issues/issue-47380.stderr +++ b/src/test/ui/issues/issue-47380.stderr @@ -7,7 +7,8 @@ LL | println!("🦀🦀🦀🦀🦀"); let _a = b + ", World!"; | | `+` cannot be used to concatenate two `&str` strings | &str | -help: `to_owned()` can be used to create an owned `String` from a string reference. String concatenation appends the string on the right to the string on the left and may require reallocation. This requires ownership of the string on the left + = note: String concatenation appends the string on the right to the string on the left and may require reallocation. This requires ownership of the string on the left. +help: use `to_owned()` to create an owned `String` from a string reference | LL | println!("🦀🦀🦀🦀🦀"); let _a = b.to_owned() + ", World!"; | +++++++++++ diff --git a/src/test/ui/span/issue-39018.stderr b/src/test/ui/span/issue-39018.stderr index 444d037571e18..9054dd931ca29 100644 --- a/src/test/ui/span/issue-39018.stderr +++ b/src/test/ui/span/issue-39018.stderr @@ -7,7 +7,8 @@ LL | let x = "Hello " + "World!"; | | `+` cannot be used to concatenate two `&str` strings | &str | -help: `to_owned()` can be used to create an owned `String` from a string reference. String concatenation appends the string on the right to the string on the left and may require reallocation. This requires ownership of the string on the left + = note: String concatenation appends the string on the right to the string on the left and may require reallocation. This requires ownership of the string on the left. +help: use `to_owned()` to create an owned `String` from a string reference | LL | let x = "Hello ".to_owned() + "World!"; | +++++++++++ @@ -46,7 +47,7 @@ LL | let x = "Hello " + "World!".to_owned(); | | `+` cannot be used to concatenate a `&str` with a `String` | &str | -help: `to_owned()` can be used to create an owned `String` from a string reference. String concatenation appends the string on the right to the string on the left and may require reallocation. This requires ownership of the string on the left +help: call `.to_owned()` on the left and add a borrow on the right | LL | let x = "Hello ".to_owned() + &"World!".to_owned(); | +++++++++++ + @@ -59,12 +60,9 @@ LL | let _ = &a + &b; | | | | | `+` cannot be used to concatenate two `&str` strings | &String + | help: remove the borrow to obtain an owned `String` | -help: String concatenation appends the string on the right to the string on the left and may require reallocation. This requires ownership of the string on the left - | -LL - let _ = &a + &b; -LL + let _ = a + &b; - | + = note: String concatenation appends the string on the right to the string on the left and may require reallocation. This requires ownership of the string on the left. error[E0369]: cannot add `String` to `&String` --> $DIR/issue-39018.rs:27:16 @@ -75,7 +73,7 @@ LL | let _ = &a + b; | | `+` cannot be used to concatenate a `&str` with a `String` | &String | -help: `to_owned()` can be used to create an owned `String` from a string reference. String concatenation appends the string on the right to the string on the left and may require reallocation. This requires ownership of the string on the left +help: remove the borrow on the left and add one on the right | LL - let _ = &a + b; LL + let _ = a + &b; @@ -99,7 +97,7 @@ LL | let _ = e + b; | | `+` cannot be used to concatenate a `&str` with a `String` | &String | -help: `to_owned()` can be used to create an owned `String` from a string reference. String concatenation appends the string on the right to the string on the left and may require reallocation. This requires ownership of the string on the left +help: call `.to_owned()` on the left and add a borrow on the right | LL | let _ = e.to_owned() + &b; | +++++++++++ + @@ -113,7 +111,8 @@ LL | let _ = e + &b; | | `+` cannot be used to concatenate two `&str` strings | &String | -help: `to_owned()` can be used to create an owned `String` from a string reference. String concatenation appends the string on the right to the string on the left and may require reallocation. This requires ownership of the string on the left + = note: String concatenation appends the string on the right to the string on the left and may require reallocation. This requires ownership of the string on the left. +help: use `to_owned()` to create an owned `String` from a string reference | LL | let _ = e.to_owned() + &b; | +++++++++++ @@ -127,7 +126,8 @@ LL | let _ = e + d; | | `+` cannot be used to concatenate two `&str` strings | &String | -help: `to_owned()` can be used to create an owned `String` from a string reference. String concatenation appends the string on the right to the string on the left and may require reallocation. This requires ownership of the string on the left + = note: String concatenation appends the string on the right to the string on the left and may require reallocation. This requires ownership of the string on the left. +help: use `to_owned()` to create an owned `String` from a string reference | LL | let _ = e.to_owned() + d; | +++++++++++ @@ -141,7 +141,8 @@ LL | let _ = e + &d; | | `+` cannot be used to concatenate two `&str` strings | &String | -help: `to_owned()` can be used to create an owned `String` from a string reference. String concatenation appends the string on the right to the string on the left and may require reallocation. This requires ownership of the string on the left + = note: String concatenation appends the string on the right to the string on the left and may require reallocation. This requires ownership of the string on the left. +help: use `to_owned()` to create an owned `String` from a string reference | LL | let _ = e.to_owned() + &d; | +++++++++++ @@ -171,7 +172,8 @@ LL | let _ = c + &d; | | `+` cannot be used to concatenate two `&str` strings | &str | -help: `to_owned()` can be used to create an owned `String` from a string reference. String concatenation appends the string on the right to the string on the left and may require reallocation. This requires ownership of the string on the left + = note: String concatenation appends the string on the right to the string on the left and may require reallocation. This requires ownership of the string on the left. +help: use `to_owned()` to create an owned `String` from a string reference | LL | let _ = c.to_owned() + &d; | +++++++++++ @@ -185,7 +187,8 @@ LL | let _ = c + d; | | `+` cannot be used to concatenate two `&str` strings | &str | -help: `to_owned()` can be used to create an owned `String` from a string reference. String concatenation appends the string on the right to the string on the left and may require reallocation. This requires ownership of the string on the left + = note: String concatenation appends the string on the right to the string on the left and may require reallocation. This requires ownership of the string on the left. +help: use `to_owned()` to create an owned `String` from a string reference | LL | let _ = c.to_owned() + d; | +++++++++++ diff --git a/src/test/ui/str/str-concat-on-double-ref.stderr b/src/test/ui/str/str-concat-on-double-ref.stderr index cc9456be90169..e8b5c2bbd8517 100644 --- a/src/test/ui/str/str-concat-on-double-ref.stderr +++ b/src/test/ui/str/str-concat-on-double-ref.stderr @@ -7,7 +7,8 @@ LL | let c = a + b; | | `+` cannot be used to concatenate two `&str` strings | &String | -help: `to_owned()` can be used to create an owned `String` from a string reference. String concatenation appends the string on the right to the string on the left and may require reallocation. This requires ownership of the string on the left + = note: String concatenation appends the string on the right to the string on the left and may require reallocation. This requires ownership of the string on the left. +help: use `to_owned()` to create an owned `String` from a string reference | LL | let c = a.to_owned() + b; | +++++++++++ diff --git a/src/test/ui/terminal-width/non-1-width-unicode-multiline-label.stderr b/src/test/ui/terminal-width/non-1-width-unicode-multiline-label.stderr index 2da3db4a7fa81..72005a889800b 100644 --- a/src/test/ui/terminal-width/non-1-width-unicode-multiline-label.stderr +++ b/src/test/ui/terminal-width/non-1-width-unicode-multiline-label.stderr @@ -7,7 +7,8 @@ LL | ...ཽཾཿ྄ཱྀྀྂྃ྅྆྇ྈྉྊྋྌྍྎྏྐྑྒྒྷྔ | | `+` cannot be used to concatenate two `&str` strings | &str | -help: `to_owned()` can be used to create an owned `String` from a string reference. String concatenation appends the string on the right to the string on the left and may require reallocation. This requires ownership of the string on the left + = note: String concatenation appends the string on the right to the string on the left and may require reallocation. This requires ownership of the string on the left. +help: use `to_owned()` to create an owned `String` from a string reference | LL | let _ = "ༀ༁༂༃༄༅༆༇༈༉༊་༌།༎༏༐༑༒༓༔༕༖༗༘༙༚༛༜༝༞༟༠༡༢༣༤༥༦༧༨༩༪༫༬༭༮༯༰༱༲༳༴༵༶༷༸༹༺༻༼༽༾༿ཀཁགགྷངཅཆཇ཈ཉཊཋཌཌྷཎཏཐདདྷནཔཕབབྷམཙཚཛཛྷཝཞཟའཡརལཤཥསཧཨཀྵཪཫཬ཭཮཯཰ཱཱཱིིུུྲྀཷླྀཹེཻོཽཾཿ྄ཱྀྀྂྃ྅྆྇ྈྉྊྋྌྍྎྏྐྑྒྒྷྔྕྖྗ྘ྙྚྛྜྜྷྞྟྠྡྡྷྣྤྥྦྦྷྨྩྪྫྫྷྭྮྯྰྱྲླྴྵྶྷྸྐྵྺྻྼ྽྾྿࿀࿁࿂࿃࿄࿅࿆࿇࿈࿉࿊࿋࿌࿍࿎࿏࿐࿑࿒࿓࿔࿕࿖࿗࿘࿙࿚"; let _a = unicode_is_fun.to_owned() + " really fun!"; | +++++++++++ From 935a99a4d1abfb517dfadf11fa29500348cc2b1c Mon Sep 17 00:00:00 2001 From: Noah Lev Date: Wed, 12 Jan 2022 22:23:56 -0800 Subject: [PATCH 06/21] Add line breaks to make message easier to read --- compiler/rustc_typeck/src/check/op.rs | 6 ++-- src/test/ui/issues/issue-47377.stderr | 4 ++- src/test/ui/issues/issue-47380.stderr | 4 ++- src/test/ui/span/issue-39018.stderr | 28 ++++++++++++++----- .../ui/str/str-concat-on-double-ref.stderr | 4 ++- ...non-1-width-unicode-multiline-label.stderr | 4 ++- 6 files changed, 36 insertions(+), 14 deletions(-) diff --git a/compiler/rustc_typeck/src/check/op.rs b/compiler/rustc_typeck/src/check/op.rs index 8bb0613f456f7..be1b01ae2949a 100644 --- a/compiler/rustc_typeck/src/check/op.rs +++ b/compiler/rustc_typeck/src/check/op.rs @@ -549,9 +549,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { is_assign: IsAssign, op: hir::BinOp, ) -> bool { - let str_concat_note = "String concatenation appends the string on the right to the \ - string on the left and may require reallocation. This \ - requires ownership of the string on the left."; + let str_concat_note = "String concatenation appends the string on the right to the +string on the left and may require reallocation. +This requires ownership of the string on the left."; let rm_borrow_msg = "remove the borrow to obtain an owned `String`"; let to_owned_msg = "use `to_owned()` to create an owned `String` from a string reference"; diff --git a/src/test/ui/issues/issue-47377.stderr b/src/test/ui/issues/issue-47377.stderr index 2e00de840870e..97fbb53bd0256 100644 --- a/src/test/ui/issues/issue-47377.stderr +++ b/src/test/ui/issues/issue-47377.stderr @@ -7,7 +7,9 @@ LL | let _a = b + ", World!"; | | `+` cannot be used to concatenate two `&str` strings | &str | - = note: String concatenation appends the string on the right to the string on the left and may require reallocation. This requires ownership of the string on the left. + = note: String concatenation appends the string on the right to the + string on the left and may require reallocation. + This requires ownership of the string on the left. help: use `to_owned()` to create an owned `String` from a string reference | LL | let _a = b.to_owned() + ", World!"; diff --git a/src/test/ui/issues/issue-47380.stderr b/src/test/ui/issues/issue-47380.stderr index fec64009444cb..7a73d41a0351b 100644 --- a/src/test/ui/issues/issue-47380.stderr +++ b/src/test/ui/issues/issue-47380.stderr @@ -7,7 +7,9 @@ LL | println!("🦀🦀🦀🦀🦀"); let _a = b + ", World!"; | | `+` cannot be used to concatenate two `&str` strings | &str | - = note: String concatenation appends the string on the right to the string on the left and may require reallocation. This requires ownership of the string on the left. + = note: String concatenation appends the string on the right to the + string on the left and may require reallocation. + This requires ownership of the string on the left. help: use `to_owned()` to create an owned `String` from a string reference | LL | println!("🦀🦀🦀🦀🦀"); let _a = b.to_owned() + ", World!"; diff --git a/src/test/ui/span/issue-39018.stderr b/src/test/ui/span/issue-39018.stderr index 9054dd931ca29..9e466f3a9a053 100644 --- a/src/test/ui/span/issue-39018.stderr +++ b/src/test/ui/span/issue-39018.stderr @@ -7,7 +7,9 @@ LL | let x = "Hello " + "World!"; | | `+` cannot be used to concatenate two `&str` strings | &str | - = note: String concatenation appends the string on the right to the string on the left and may require reallocation. This requires ownership of the string on the left. + = note: String concatenation appends the string on the right to the + string on the left and may require reallocation. + This requires ownership of the string on the left. help: use `to_owned()` to create an owned `String` from a string reference | LL | let x = "Hello ".to_owned() + "World!"; @@ -62,7 +64,9 @@ LL | let _ = &a + &b; | &String | help: remove the borrow to obtain an owned `String` | - = note: String concatenation appends the string on the right to the string on the left and may require reallocation. This requires ownership of the string on the left. + = note: String concatenation appends the string on the right to the + string on the left and may require reallocation. + This requires ownership of the string on the left. error[E0369]: cannot add `String` to `&String` --> $DIR/issue-39018.rs:27:16 @@ -111,7 +115,9 @@ LL | let _ = e + &b; | | `+` cannot be used to concatenate two `&str` strings | &String | - = note: String concatenation appends the string on the right to the string on the left and may require reallocation. This requires ownership of the string on the left. + = note: String concatenation appends the string on the right to the + string on the left and may require reallocation. + This requires ownership of the string on the left. help: use `to_owned()` to create an owned `String` from a string reference | LL | let _ = e.to_owned() + &b; @@ -126,7 +132,9 @@ LL | let _ = e + d; | | `+` cannot be used to concatenate two `&str` strings | &String | - = note: String concatenation appends the string on the right to the string on the left and may require reallocation. This requires ownership of the string on the left. + = note: String concatenation appends the string on the right to the + string on the left and may require reallocation. + This requires ownership of the string on the left. help: use `to_owned()` to create an owned `String` from a string reference | LL | let _ = e.to_owned() + d; @@ -141,7 +149,9 @@ LL | let _ = e + &d; | | `+` cannot be used to concatenate two `&str` strings | &String | - = note: String concatenation appends the string on the right to the string on the left and may require reallocation. This requires ownership of the string on the left. + = note: String concatenation appends the string on the right to the + string on the left and may require reallocation. + This requires ownership of the string on the left. help: use `to_owned()` to create an owned `String` from a string reference | LL | let _ = e.to_owned() + &d; @@ -172,7 +182,9 @@ LL | let _ = c + &d; | | `+` cannot be used to concatenate two `&str` strings | &str | - = note: String concatenation appends the string on the right to the string on the left and may require reallocation. This requires ownership of the string on the left. + = note: String concatenation appends the string on the right to the + string on the left and may require reallocation. + This requires ownership of the string on the left. help: use `to_owned()` to create an owned `String` from a string reference | LL | let _ = c.to_owned() + &d; @@ -187,7 +199,9 @@ LL | let _ = c + d; | | `+` cannot be used to concatenate two `&str` strings | &str | - = note: String concatenation appends the string on the right to the string on the left and may require reallocation. This requires ownership of the string on the left. + = note: String concatenation appends the string on the right to the + string on the left and may require reallocation. + This requires ownership of the string on the left. help: use `to_owned()` to create an owned `String` from a string reference | LL | let _ = c.to_owned() + d; diff --git a/src/test/ui/str/str-concat-on-double-ref.stderr b/src/test/ui/str/str-concat-on-double-ref.stderr index e8b5c2bbd8517..d239ec0d9fcc9 100644 --- a/src/test/ui/str/str-concat-on-double-ref.stderr +++ b/src/test/ui/str/str-concat-on-double-ref.stderr @@ -7,7 +7,9 @@ LL | let c = a + b; | | `+` cannot be used to concatenate two `&str` strings | &String | - = note: String concatenation appends the string on the right to the string on the left and may require reallocation. This requires ownership of the string on the left. + = note: String concatenation appends the string on the right to the + string on the left and may require reallocation. + This requires ownership of the string on the left. help: use `to_owned()` to create an owned `String` from a string reference | LL | let c = a.to_owned() + b; diff --git a/src/test/ui/terminal-width/non-1-width-unicode-multiline-label.stderr b/src/test/ui/terminal-width/non-1-width-unicode-multiline-label.stderr index 72005a889800b..55e993db3d3d4 100644 --- a/src/test/ui/terminal-width/non-1-width-unicode-multiline-label.stderr +++ b/src/test/ui/terminal-width/non-1-width-unicode-multiline-label.stderr @@ -7,7 +7,9 @@ LL | ...ཽཾཿ྄ཱྀྀྂྃ྅྆྇ྈྉྊྋྌྍྎྏྐྑྒྒྷྔ | | `+` cannot be used to concatenate two `&str` strings | &str | - = note: String concatenation appends the string on the right to the string on the left and may require reallocation. This requires ownership of the string on the left. + = note: String concatenation appends the string on the right to the + string on the left and may require reallocation. + This requires ownership of the string on the left. help: use `to_owned()` to create an owned `String` from a string reference | LL | let _ = "ༀ༁༂༃༄༅༆༇༈༉༊་༌།༎༏༐༑༒༓༔༕༖༗༘༙༚༛༜༝༞༟༠༡༢༣༤༥༦༧༨༩༪༫༬༭༮༯༰༱༲༳༴༵༶༷༸༹༺༻༼༽༾༿ཀཁགགྷངཅཆཇ཈ཉཊཋཌཌྷཎཏཐདདྷནཔཕབབྷམཙཚཛཛྷཝཞཟའཡརལཤཥསཧཨཀྵཪཫཬ཭཮཯཰ཱཱཱིིུུྲྀཷླྀཹེཻོཽཾཿ྄ཱྀྀྂྃ྅྆྇ྈྉྊྋྌྍྎྏྐྑྒྒྷྔྕྖྗ྘ྙྚྛྜྜྷྞྟྠྡྡྷྣྤྥྦྦྷྨྩྪྫྫྷྭྮྯྰྱྲླྴྵྶྷྸྐྵྺྻྼ྽྾྿࿀࿁࿂࿃࿄࿅࿆࿇࿈࿉࿊࿋࿌࿍࿎࿏࿐࿑࿒࿓࿔࿕࿖࿗࿘࿙࿚"; let _a = unicode_is_fun.to_owned() + " really fun!"; From 6e42bc378fe2225c21d13957c1299ee349fcdfaf Mon Sep 17 00:00:00 2001 From: Noah Lev Date: Wed, 12 Jan 2022 22:25:53 -0800 Subject: [PATCH 07/21] Fix formatting This code is sufficiently complex -- I'm guessing due to the very long `match` guards -- that rustfmt doesn't format it. --- compiler/rustc_typeck/src/check/op.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/rustc_typeck/src/check/op.rs b/compiler/rustc_typeck/src/check/op.rs index be1b01ae2949a..c7bb66f339c14 100644 --- a/compiler/rustc_typeck/src/check/op.rs +++ b/compiler/rustc_typeck/src/check/op.rs @@ -571,7 +571,7 @@ This requires ownership of the string on the left."; if let IsAssign::No = is_assign { // Do not supply this message if `&str += &str` err.span_label(op.span, "`+` cannot be used to concatenate two `&str` strings"); err.note(str_concat_note); - if let hir::ExprKind::AddrOf(_,_,lhs_inner_expr) = lhs_expr.kind { + if let hir::ExprKind::AddrOf(_, _, lhs_inner_expr) = lhs_expr.kind { err.span_suggestion( lhs_expr.span.until(lhs_inner_expr.span), rm_borrow_msg, From 5296baeab13658b307c782e9464cfa6f2027a4ec Mon Sep 17 00:00:00 2001 From: Scott Mabin Date: Wed, 5 Jan 2022 13:13:25 +0000 Subject: [PATCH 08/21] Set the allocation MIN_ALIGN for espidf to 4. --- library/std/src/sys/common/alloc.rs | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/library/std/src/sys/common/alloc.rs b/library/std/src/sys/common/alloc.rs index 9665d1fa89243..e06eaf6db1a77 100644 --- a/library/std/src/sys/common/alloc.rs +++ b/library/std/src/sys/common/alloc.rs @@ -14,8 +14,8 @@ use crate::ptr; target_arch = "asmjs", target_arch = "wasm32", target_arch = "hexagon", - target_arch = "riscv32", - target_arch = "xtensa" + all(target_arch = "riscv32", not(target_os = "espidf")), + all(target_arch = "xtensa", not(target_os = "espidf")), )))] pub const MIN_ALIGN: usize = 8; #[cfg(all(any( @@ -28,6 +28,12 @@ pub const MIN_ALIGN: usize = 8; target_arch = "wasm64", )))] pub const MIN_ALIGN: usize = 16; +// The allocator on the esp-idf platform guarentees 4 byte alignment. +#[cfg(all(any( + all(target_arch = "riscv32", target_os = "espidf"), + all(target_arch = "xtensa", target_os = "espidf"), +)))] +pub const MIN_ALIGN: usize = 4; pub unsafe fn realloc_fallback( alloc: &System, From 32be3489a52271520e6bc6c6653ce7457292c48b Mon Sep 17 00:00:00 2001 From: Ivor Wanders Date: Sun, 16 Jan 2022 11:04:11 -0500 Subject: [PATCH 09/21] Add unit test for cfg-arg without quotes. --- src/test/ui/conditional-compilation/cfg-arg-invalid-9.rs | 3 +++ src/test/ui/conditional-compilation/cfg-arg-invalid-9.stderr | 2 ++ 2 files changed, 5 insertions(+) create mode 100644 src/test/ui/conditional-compilation/cfg-arg-invalid-9.rs create mode 100644 src/test/ui/conditional-compilation/cfg-arg-invalid-9.stderr diff --git a/src/test/ui/conditional-compilation/cfg-arg-invalid-9.rs b/src/test/ui/conditional-compilation/cfg-arg-invalid-9.rs new file mode 100644 index 0000000000000..51d8c4b885cad --- /dev/null +++ b/src/test/ui/conditional-compilation/cfg-arg-invalid-9.rs @@ -0,0 +1,3 @@ +// compile-flags: --cfg key=value +// error-pattern: invalid `--cfg` argument: `key=value` (expected `key` or `key="value"`, ensure escaping is appropriate for your shell, try 'key="value"' or key=\"value\") +fn main() {} diff --git a/src/test/ui/conditional-compilation/cfg-arg-invalid-9.stderr b/src/test/ui/conditional-compilation/cfg-arg-invalid-9.stderr new file mode 100644 index 0000000000000..985b525225839 --- /dev/null +++ b/src/test/ui/conditional-compilation/cfg-arg-invalid-9.stderr @@ -0,0 +1,2 @@ +error: invalid `--cfg` argument: `key=value` (expected `key` or `key="value"`, ensure escaping is appropriate for your shell, try 'key="value"' or key=\"value\") + From 1531d26fa3896869818b40d6771d8b3cdaf2f6eb Mon Sep 17 00:00:00 2001 From: Ivor Wanders Date: Sun, 16 Jan 2022 11:43:16 -0500 Subject: [PATCH 10/21] Limit scope of the hint about escaping. --- compiler/rustc_interface/src/interface.rs | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/compiler/rustc_interface/src/interface.rs b/compiler/rustc_interface/src/interface.rs index 8fa1e18df3c35..263435619590e 100644 --- a/compiler/rustc_interface/src/interface.rs +++ b/compiler/rustc_interface/src/interface.rs @@ -124,10 +124,16 @@ pub fn parse_cfgspecs(cfgspecs: Vec) -> FxHashSet<(String, Option errs.into_iter().for_each(|mut err| err.cancel()), } - error!(concat!( - r#"expected `key` or `key="value"`, ensure escaping is appropriate"#, - r#" for your shell, try 'key="value"' or key=\"value\""# - )); + // If the user tried to use a key="value" flag, but is missing the quotes, provide + // a hint about how to resolve this. + if s.contains("=") && !s.contains("=\"") && !s.ends_with("\"") { + error!(concat!( + r#"expected `key` or `key="value"`, ensure escaping is appropriate"#, + r#" for your shell, try 'key="value"' or key=\"value\""# + )); + } else { + error!(r#"expected `key` or `key="value"`"#); + } }) .collect::(); cfg.into_iter().map(|(a, b)| (a.to_string(), b.map(|b| b.to_string()))).collect() From af87248037a8c86f580c469ce7d2a10c0b12f2fd Mon Sep 17 00:00:00 2001 From: Ivor Wanders Date: Sun, 16 Jan 2022 11:44:10 -0500 Subject: [PATCH 11/21] Update unit tests to match more limited hint about escaping. --- src/test/ui/conditional-compilation/cfg-arg-invalid-2.rs | 2 +- src/test/ui/conditional-compilation/cfg-arg-invalid-2.stderr | 2 +- src/test/ui/conditional-compilation/cfg-arg-invalid-4.rs | 2 +- src/test/ui/conditional-compilation/cfg-arg-invalid-4.stderr | 2 +- src/test/ui/conditional-compilation/cfg-arg-invalid-6.rs | 2 +- src/test/ui/conditional-compilation/cfg-arg-invalid-6.stderr | 2 +- src/test/ui/conditional-compilation/cfg-arg-invalid-8.rs | 2 +- src/test/ui/conditional-compilation/cfg-arg-invalid-8.stderr | 2 +- src/test/ui/conditional-compilation/cfg-arg-invalid-9.rs | 1 + src/test/ui/conditional-compilation/cfg-empty-codemap.rs | 2 +- src/test/ui/conditional-compilation/cfg-empty-codemap.stderr | 2 +- 11 files changed, 11 insertions(+), 10 deletions(-) diff --git a/src/test/ui/conditional-compilation/cfg-arg-invalid-2.rs b/src/test/ui/conditional-compilation/cfg-arg-invalid-2.rs index 660d5d1b1ea90..48d656a4a28d9 100644 --- a/src/test/ui/conditional-compilation/cfg-arg-invalid-2.rs +++ b/src/test/ui/conditional-compilation/cfg-arg-invalid-2.rs @@ -1,3 +1,3 @@ // compile-flags: --cfg a{b} -// error-pattern: invalid `--cfg` argument: `a{b}` (expected `key` or `key="value"`, ensure escaping is appropriate for your shell, try 'key="value"' or key=\"value\") +// error-pattern: invalid `--cfg` argument: `a{b}` (expected `key` or `key="value"`) fn main() {} diff --git a/src/test/ui/conditional-compilation/cfg-arg-invalid-2.stderr b/src/test/ui/conditional-compilation/cfg-arg-invalid-2.stderr index 2e141137129dc..b92e1fd3d97cf 100644 --- a/src/test/ui/conditional-compilation/cfg-arg-invalid-2.stderr +++ b/src/test/ui/conditional-compilation/cfg-arg-invalid-2.stderr @@ -1,2 +1,2 @@ -error: invalid `--cfg` argument: `a{b}` (expected `key` or `key="value"`, ensure escaping is appropriate for your shell, try 'key="value"' or key=\"value\") +error: invalid `--cfg` argument: `a{b}` (expected `key` or `key="value"`) diff --git a/src/test/ui/conditional-compilation/cfg-arg-invalid-4.rs b/src/test/ui/conditional-compilation/cfg-arg-invalid-4.rs index d8b3c0284cca6..e7dfa17b4b6c4 100644 --- a/src/test/ui/conditional-compilation/cfg-arg-invalid-4.rs +++ b/src/test/ui/conditional-compilation/cfg-arg-invalid-4.rs @@ -1,3 +1,3 @@ // compile-flags: --cfg a(b) -// error-pattern: invalid `--cfg` argument: `a(b)` (expected `key` or `key="value"`, ensure escaping is appropriate for your shell, try 'key="value"' or key=\"value\") +// error-pattern: invalid `--cfg` argument: `a(b)` (expected `key` or `key="value"`) fn main() {} diff --git a/src/test/ui/conditional-compilation/cfg-arg-invalid-4.stderr b/src/test/ui/conditional-compilation/cfg-arg-invalid-4.stderr index 52685d7b4a233..6853a69b9eb22 100644 --- a/src/test/ui/conditional-compilation/cfg-arg-invalid-4.stderr +++ b/src/test/ui/conditional-compilation/cfg-arg-invalid-4.stderr @@ -1,2 +1,2 @@ -error: invalid `--cfg` argument: `a(b)` (expected `key` or `key="value"`, ensure escaping is appropriate for your shell, try 'key="value"' or key=\"value\") +error: invalid `--cfg` argument: `a(b)` (expected `key` or `key="value"`) diff --git a/src/test/ui/conditional-compilation/cfg-arg-invalid-6.rs b/src/test/ui/conditional-compilation/cfg-arg-invalid-6.rs index 4a0d116e644b5..9fa726f93e3ea 100644 --- a/src/test/ui/conditional-compilation/cfg-arg-invalid-6.rs +++ b/src/test/ui/conditional-compilation/cfg-arg-invalid-6.rs @@ -1,3 +1,3 @@ // compile-flags: --cfg a{ -// error-pattern: invalid `--cfg` argument: `a{` (expected `key` or `key="value"`, ensure escaping is appropriate for your shell, try 'key="value"' or key=\"value\") +// error-pattern: invalid `--cfg` argument: `a{` (expected `key` or `key="value"`) fn main() {} diff --git a/src/test/ui/conditional-compilation/cfg-arg-invalid-6.stderr b/src/test/ui/conditional-compilation/cfg-arg-invalid-6.stderr index 618d12aba68e9..7d2087b4b71f7 100644 --- a/src/test/ui/conditional-compilation/cfg-arg-invalid-6.stderr +++ b/src/test/ui/conditional-compilation/cfg-arg-invalid-6.stderr @@ -1,2 +1,2 @@ -error: invalid `--cfg` argument: `a{` (expected `key` or `key="value"`, ensure escaping is appropriate for your shell, try 'key="value"' or key=\"value\") +error: invalid `--cfg` argument: `a{` (expected `key` or `key="value"`) diff --git a/src/test/ui/conditional-compilation/cfg-arg-invalid-8.rs b/src/test/ui/conditional-compilation/cfg-arg-invalid-8.rs index 7c5531606fa34..1d7fa7885348e 100644 --- a/src/test/ui/conditional-compilation/cfg-arg-invalid-8.rs +++ b/src/test/ui/conditional-compilation/cfg-arg-invalid-8.rs @@ -1,3 +1,3 @@ // compile-flags: --cfg ) -// error-pattern: invalid `--cfg` argument: `)` (expected `key` or `key="value"`, ensure escaping is appropriate for your shell, try 'key="value"' or key=\"value\") +// error-pattern: invalid `--cfg` argument: `)` (expected `key` or `key="value"`) fn main() {} diff --git a/src/test/ui/conditional-compilation/cfg-arg-invalid-8.stderr b/src/test/ui/conditional-compilation/cfg-arg-invalid-8.stderr index 16bb552f0d999..7bb1814127b29 100644 --- a/src/test/ui/conditional-compilation/cfg-arg-invalid-8.stderr +++ b/src/test/ui/conditional-compilation/cfg-arg-invalid-8.stderr @@ -1,2 +1,2 @@ -error: invalid `--cfg` argument: `)` (expected `key` or `key="value"`, ensure escaping is appropriate for your shell, try 'key="value"' or key=\"value\") +error: invalid `--cfg` argument: `)` (expected `key` or `key="value"`) diff --git a/src/test/ui/conditional-compilation/cfg-arg-invalid-9.rs b/src/test/ui/conditional-compilation/cfg-arg-invalid-9.rs index 51d8c4b885cad..628b335c87302 100644 --- a/src/test/ui/conditional-compilation/cfg-arg-invalid-9.rs +++ b/src/test/ui/conditional-compilation/cfg-arg-invalid-9.rs @@ -1,3 +1,4 @@ +// Test for missing quotes around value, issue #66450. // compile-flags: --cfg key=value // error-pattern: invalid `--cfg` argument: `key=value` (expected `key` or `key="value"`, ensure escaping is appropriate for your shell, try 'key="value"' or key=\"value\") fn main() {} diff --git a/src/test/ui/conditional-compilation/cfg-empty-codemap.rs b/src/test/ui/conditional-compilation/cfg-empty-codemap.rs index c23d2cee924b7..9e34cacf74d2a 100644 --- a/src/test/ui/conditional-compilation/cfg-empty-codemap.rs +++ b/src/test/ui/conditional-compilation/cfg-empty-codemap.rs @@ -2,7 +2,7 @@ // compile-flags: --cfg "" -// error-pattern: invalid `--cfg` argument: `""` (expected `key` or `key="value"`, ensure escaping is appropriate for your shell, try 'key="value"' or key=\"value\") +// error-pattern: invalid `--cfg` argument: `""` (expected `key` or `key="value"`) pub fn main() { } diff --git a/src/test/ui/conditional-compilation/cfg-empty-codemap.stderr b/src/test/ui/conditional-compilation/cfg-empty-codemap.stderr index 55e3dc131ae9f..128e3cd730680 100644 --- a/src/test/ui/conditional-compilation/cfg-empty-codemap.stderr +++ b/src/test/ui/conditional-compilation/cfg-empty-codemap.stderr @@ -1,2 +1,2 @@ -error: invalid `--cfg` argument: `""` (expected `key` or `key="value"`, ensure escaping is appropriate for your shell, try 'key="value"' or key=\"value\") +error: invalid `--cfg` argument: `""` (expected `key` or `key="value"`) From ef46e38c2bc9c86dcc48b511885630ed9f842a55 Mon Sep 17 00:00:00 2001 From: threadexception Date: Fri, 14 Jan 2022 16:03:46 +0100 Subject: [PATCH 12/21] Implement tuple array diagnostic Co-authored-by: David Wood --- compiler/rustc_typeck/src/check/callee.rs | 34 +++++++++++++++++++++- src/test/ui/issues/issue-5100.stderr | 6 ++-- src/test/ui/tuple/array-diagnostics.rs | 7 +++++ src/test/ui/tuple/array-diagnostics.stderr | 9 ++++++ 4 files changed, 51 insertions(+), 5 deletions(-) create mode 100644 src/test/ui/tuple/array-diagnostics.rs create mode 100644 src/test/ui/tuple/array-diagnostics.stderr diff --git a/compiler/rustc_typeck/src/check/callee.rs b/compiler/rustc_typeck/src/check/callee.rs index eea8f40635d74..0fea0afb572c9 100644 --- a/compiler/rustc_typeck/src/check/callee.rs +++ b/compiler/rustc_typeck/src/check/callee.rs @@ -307,6 +307,36 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } } + /// Give appropriate suggestion when encountering `[("a", 0) ("b", 1)]`, where the + /// likely intention is to create an array containing tuples. + fn maybe_suggest_bad_array_definition( + &self, + err: &mut DiagnosticBuilder<'a>, + call_expr: &'tcx hir::Expr<'tcx>, + callee_expr: &'tcx hir::Expr<'tcx>, + ) -> bool { + let hir_id = self.tcx.hir().get_parent_node(call_expr.hir_id); + let parent_node = self.tcx.hir().get(hir_id); + if let ( + hir::Node::Expr(hir::Expr { kind: hir::ExprKind::Array(_), .. }), + hir::ExprKind::Tup(exp), + hir::ExprKind::Call(_, args), + ) = (parent_node, &callee_expr.kind, &call_expr.kind) + { + if args.len() == exp.len() { + let start = callee_expr.span.shrink_to_hi(); + err.span_suggestion( + start, + "consider separating array elements with a comma", + ",".to_string(), + Applicability::MaybeIncorrect, + ); + return true; + } + } + false + } + fn confirm_builtin_call( &self, call_expr: &'tcx hir::Expr<'tcx>, @@ -422,7 +452,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { _ => Res::Err, }; - err.span_label(call_expr.span, "call expression requires function"); + if !self.maybe_suggest_bad_array_definition(&mut err, call_expr, callee_expr) { + err.span_label(call_expr.span, "call expression requires function"); + } if let Some(span) = self.tcx.hir().res_span(def) { let callee_ty = callee_ty.to_string(); diff --git a/src/test/ui/issues/issue-5100.stderr b/src/test/ui/issues/issue-5100.stderr index de71e1d1a6666..c87a3e348a2e9 100644 --- a/src/test/ui/issues/issue-5100.stderr +++ b/src/test/ui/issues/issue-5100.stderr @@ -59,10 +59,8 @@ LL | &(true, false) => () error[E0618]: expected function, found `(char, char)` --> $DIR/issue-5100.rs:48:14 | -LL | let v = [('a', 'b') - | ______________-^^^^^^^^^ -LL | | ('c', 'd'), - | |_______________________- call expression requires function +LL | let v = [('a', 'b') + | ^^^^^^^^^^- help: consider separating array elements with a comma: `,` error[E0308]: mismatched types --> $DIR/issue-5100.rs:55:19 diff --git a/src/test/ui/tuple/array-diagnostics.rs b/src/test/ui/tuple/array-diagnostics.rs new file mode 100644 index 0000000000000..1929dab073169 --- /dev/null +++ b/src/test/ui/tuple/array-diagnostics.rs @@ -0,0 +1,7 @@ +fn main() { + let _tmp = [ + ("C200B40A82", 3), + ("C200B40A83", 4) //~ ERROR: expected function, found `(&'static str, {integer})` [E0618] + ("C200B40A8537", 5), + ]; +} diff --git a/src/test/ui/tuple/array-diagnostics.stderr b/src/test/ui/tuple/array-diagnostics.stderr new file mode 100644 index 0000000000000..a10d7af470c7c --- /dev/null +++ b/src/test/ui/tuple/array-diagnostics.stderr @@ -0,0 +1,9 @@ +error[E0618]: expected function, found `(&'static str, {integer})` + --> $DIR/array-diagnostics.rs:4:9 + | +LL | ("C200B40A83", 4) + | ^^^^^^^^^^^^^^^^^- help: consider separating array elements with a comma: `,` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0618`. From b2dd1377c7b2624391d82b0eee2c988e090dd311 Mon Sep 17 00:00:00 2001 From: est31 Date: Tue, 18 Jan 2022 20:26:13 +0100 Subject: [PATCH 13/21] Use let_else in even more places --- .../src/debuginfo/metadata.rs | 2 +- compiler/rustc_codegen_llvm/src/lib.rs | 1 + compiler/rustc_interface/src/lib.rs | 1 + compiler/rustc_interface/src/util.rs | 92 +++++++++---------- .../rustc_mir_build/src/build/matches/mod.rs | 31 +++---- .../rustc_mir_build/src/build/matches/test.rs | 7 +- .../rustc_resolve/src/late/diagnostics.rs | 4 +- compiler/rustc_resolve/src/late/lifetimes.rs | 75 ++++++++------- .../src/traits/error_reporting/suggestions.rs | 55 ++++++----- 9 files changed, 131 insertions(+), 137 deletions(-) diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs b/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs index 3d5fd2f354e55..c90e43a4060f7 100644 --- a/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs +++ b/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs @@ -1493,7 +1493,7 @@ fn generator_layout_and_saved_local_names<'tcx>( let state_arg = mir::Local::new(1); for var in &body.var_debug_info { - let place = if let mir::VarDebugInfoContents::Place(p) = var.value { p } else { continue }; + let mir::VarDebugInfoContents::Place(place) = &var.value else { continue }; if place.local != state_arg { continue; } diff --git a/compiler/rustc_codegen_llvm/src/lib.rs b/compiler/rustc_codegen_llvm/src/lib.rs index cea4595fbbfed..f0612eaba8089 100644 --- a/compiler/rustc_codegen_llvm/src/lib.rs +++ b/compiler/rustc_codegen_llvm/src/lib.rs @@ -7,6 +7,7 @@ #![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")] #![feature(bool_to_option)] #![feature(crate_visibility_modifier)] +#![feature(let_else)] #![feature(extern_types)] #![feature(nll)] #![recursion_limit = "256"] diff --git a/compiler/rustc_interface/src/lib.rs b/compiler/rustc_interface/src/lib.rs index 2fc3759968fd3..b911b108a735d 100644 --- a/compiler/rustc_interface/src/lib.rs +++ b/compiler/rustc_interface/src/lib.rs @@ -1,5 +1,6 @@ #![feature(bool_to_option)] #![feature(box_patterns)] +#![feature(let_else)] #![feature(internal_output_capture)] #![feature(thread_spawn_unchecked)] #![feature(nll)] diff --git a/compiler/rustc_interface/src/util.rs b/compiler/rustc_interface/src/util.rs index 3921187baa55e..6d9183eda9d32 100644 --- a/compiler/rustc_interface/src/util.rs +++ b/compiler/rustc_interface/src/util.rs @@ -717,57 +717,57 @@ impl<'a, 'b> ReplaceBodyWithLoop<'a, 'b> { } fn should_ignore_fn(ret_ty: &ast::FnRetTy) -> bool { - if let ast::FnRetTy::Ty(ref ty) = ret_ty { - fn involves_impl_trait(ty: &ast::Ty) -> bool { - match ty.kind { - ast::TyKind::ImplTrait(..) => true, - ast::TyKind::Slice(ref subty) - | ast::TyKind::Array(ref subty, _) - | ast::TyKind::Ptr(ast::MutTy { ty: ref subty, .. }) - | ast::TyKind::Rptr(_, ast::MutTy { ty: ref subty, .. }) - | ast::TyKind::Paren(ref subty) => involves_impl_trait(subty), - ast::TyKind::Tup(ref tys) => any_involves_impl_trait(tys.iter()), - ast::TyKind::Path(_, ref path) => { - path.segments.iter().any(|seg| match seg.args.as_deref() { - None => false, - Some(&ast::GenericArgs::AngleBracketed(ref data)) => { - data.args.iter().any(|arg| match arg { - ast::AngleBracketedArg::Arg(arg) => match arg { - ast::GenericArg::Type(ty) => involves_impl_trait(ty), - ast::GenericArg::Lifetime(_) - | ast::GenericArg::Const(_) => false, - }, - ast::AngleBracketedArg::Constraint(c) => match c.kind { - ast::AssocConstraintKind::Bound { .. } => true, - ast::AssocConstraintKind::Equality { ref term } => { - match term { - Term::Ty(ty) => involves_impl_trait(ty), - // FIXME(...): This should check if the constant - // involves a trait impl, but for now ignore. - Term::Const(_) => false, - } + let ast::FnRetTy::Ty(ref ty) = ret_ty else { + return false; + }; + fn involves_impl_trait(ty: &ast::Ty) -> bool { + match ty.kind { + ast::TyKind::ImplTrait(..) => true, + ast::TyKind::Slice(ref subty) + | ast::TyKind::Array(ref subty, _) + | ast::TyKind::Ptr(ast::MutTy { ty: ref subty, .. }) + | ast::TyKind::Rptr(_, ast::MutTy { ty: ref subty, .. }) + | ast::TyKind::Paren(ref subty) => involves_impl_trait(subty), + ast::TyKind::Tup(ref tys) => any_involves_impl_trait(tys.iter()), + ast::TyKind::Path(_, ref path) => { + path.segments.iter().any(|seg| match seg.args.as_deref() { + None => false, + Some(&ast::GenericArgs::AngleBracketed(ref data)) => { + data.args.iter().any(|arg| match arg { + ast::AngleBracketedArg::Arg(arg) => match arg { + ast::GenericArg::Type(ty) => involves_impl_trait(ty), + ast::GenericArg::Lifetime(_) | ast::GenericArg::Const(_) => { + false + } + }, + ast::AngleBracketedArg::Constraint(c) => match c.kind { + ast::AssocConstraintKind::Bound { .. } => true, + ast::AssocConstraintKind::Equality { ref term } => { + match term { + Term::Ty(ty) => involves_impl_trait(ty), + // FIXME(...): This should check if the constant + // involves a trait impl, but for now ignore. + Term::Const(_) => false, } - }, - }) - } - Some(&ast::GenericArgs::Parenthesized(ref data)) => { - any_involves_impl_trait(data.inputs.iter()) - || ReplaceBodyWithLoop::should_ignore_fn(&data.output) - } - }) - } - _ => false, + } + }, + }) + } + Some(&ast::GenericArgs::Parenthesized(ref data)) => { + any_involves_impl_trait(data.inputs.iter()) + || ReplaceBodyWithLoop::should_ignore_fn(&data.output) + } + }) } + _ => false, } + } - fn any_involves_impl_trait<'a, I: Iterator>>(mut it: I) -> bool { - it.any(|subty| involves_impl_trait(subty)) - } - - involves_impl_trait(ty) - } else { - false + fn any_involves_impl_trait<'a, I: Iterator>>(mut it: I) -> bool { + it.any(|subty| involves_impl_trait(subty)) } + + involves_impl_trait(ty) } fn is_sig_const(sig: &ast::FnSig) -> bool { diff --git a/compiler/rustc_mir_build/src/build/matches/mod.rs b/compiler/rustc_mir_build/src/build/matches/mod.rs index e3a05e01ea8f0..e0b79ae4742c3 100644 --- a/compiler/rustc_mir_build/src/build/matches/mod.rs +++ b/compiler/rustc_mir_build/src/build/matches/mod.rs @@ -1328,23 +1328,22 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { let mut otherwise = None; for match_pair in match_pairs { - if let PatKind::Or { ref pats } = *match_pair.pattern.kind { - let or_span = match_pair.pattern.span; - let place = match_pair.place; - - first_candidate.visit_leaves(|leaf_candidate| { - self.test_or_pattern( - leaf_candidate, - &mut otherwise, - pats, - or_span, - place.clone(), - fake_borrows, - ); - }); - } else { + let PatKind::Or { ref pats } = &*match_pair.pattern.kind else { bug!("Or-patterns should have been sorted to the end"); - } + }; + let or_span = match_pair.pattern.span; + let place = match_pair.place; + + first_candidate.visit_leaves(|leaf_candidate| { + self.test_or_pattern( + leaf_candidate, + &mut otherwise, + pats, + or_span, + place.clone(), + fake_borrows, + ); + }); } let remainder_start = otherwise.unwrap_or_else(|| self.cfg.start_new_block()); diff --git a/compiler/rustc_mir_build/src/build/matches/test.rs b/compiler/rustc_mir_build/src/build/matches/test.rs index 7ed5d1d67ab12..f4bf28bfa5ce2 100644 --- a/compiler/rustc_mir_build/src/build/matches/test.rs +++ b/compiler/rustc_mir_build/src/build/matches/test.rs @@ -88,11 +88,8 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { switch_ty: Ty<'tcx>, options: &mut FxIndexMap<&'tcx ty::Const<'tcx>, u128>, ) -> bool { - let match_pair = match candidate.match_pairs.iter().find(|mp| mp.place == *test_place) { - Some(match_pair) => match_pair, - _ => { - return false; - } + let Some(match_pair) = candidate.match_pairs.iter().find(|mp| mp.place == *test_place) else { + return false; }; match *match_pair.pattern.kind { diff --git a/compiler/rustc_resolve/src/late/diagnostics.rs b/compiler/rustc_resolve/src/late/diagnostics.rs index 4cd1b34bedc95..5988d0664586c 100644 --- a/compiler/rustc_resolve/src/late/diagnostics.rs +++ b/compiler/rustc_resolve/src/late/diagnostics.rs @@ -1162,9 +1162,7 @@ impl<'a: 'ast, 'ast> LateResolutionVisitor<'a, '_, 'ast> { ident: Symbol, kind: &AssocItemKind, ) -> Option { - let module = if let Some((module, _)) = self.current_trait_ref { - module - } else { + let Some((module, _)) = &self.current_trait_ref else { return None; }; if ident == kw::Underscore { diff --git a/compiler/rustc_resolve/src/late/lifetimes.rs b/compiler/rustc_resolve/src/late/lifetimes.rs index b077a5c9144c5..4c7bdb33fb87a 100644 --- a/compiler/rustc_resolve/src/late/lifetimes.rs +++ b/compiler/rustc_resolve/src/late/lifetimes.rs @@ -1000,46 +1000,45 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> { // `fn foo<'a>() -> MyAnonTy<'a> { ... }` // ^ ^this gets resolved in the current scope for lifetime in lifetimes { - if let hir::GenericArg::Lifetime(lifetime) = lifetime { - self.visit_lifetime(lifetime); + let hir::GenericArg::Lifetime(lifetime) = lifetime else { + continue + }; + self.visit_lifetime(lifetime); + + // Check for predicates like `impl for<'a> Trait>` + // and ban them. Type variables instantiated inside binders aren't + // well-supported at the moment, so this doesn't work. + // In the future, this should be fixed and this error should be removed. + let def = self.map.defs.get(&lifetime.hir_id).cloned(); + let Some(Region::LateBound(_, _, def_id, _)) = def else { + continue + }; + let Some(def_id) = def_id.as_local() else { + continue + }; + let hir_id = self.tcx.hir().local_def_id_to_hir_id(def_id); + // Ensure that the parent of the def is an item, not HRTB + let parent_id = self.tcx.hir().get_parent_node(hir_id); + // FIXME(cjgillot) Can this check be replaced by + // `let parent_is_item = parent_id.is_owner();`? + let parent_is_item = if let Some(parent_def_id) = parent_id.as_owner() { + matches!(self.tcx.hir().krate().owners.get(parent_def_id), Some(Some(_)),) + } else { + false + }; - // Check for predicates like `impl for<'a> Trait>` - // and ban them. Type variables instantiated inside binders aren't - // well-supported at the moment, so this doesn't work. - // In the future, this should be fixed and this error should be removed. - let def = self.map.defs.get(&lifetime.hir_id).cloned(); - if let Some(Region::LateBound(_, _, def_id, _)) = def { - if let Some(def_id) = def_id.as_local() { - let hir_id = self.tcx.hir().local_def_id_to_hir_id(def_id); - // Ensure that the parent of the def is an item, not HRTB - let parent_id = self.tcx.hir().get_parent_node(hir_id); - // FIXME(cjgillot) Can this check be replaced by - // `let parent_is_item = parent_id.is_owner();`? - let parent_is_item = - if let Some(parent_def_id) = parent_id.as_owner() { - matches!( - self.tcx.hir().krate().owners.get(parent_def_id), - Some(Some(_)), - ) - } else { - false - }; - - if !parent_is_item { - if !self.trait_definition_only { - struct_span_err!( - self.tcx.sess, - lifetime.span, - E0657, - "`impl Trait` can only capture lifetimes \ - bound at the fn or impl level" - ) - .emit(); - } - self.uninsert_lifetime_on_error(lifetime, def.unwrap()); - } - } + if !parent_is_item { + if !self.trait_definition_only { + struct_span_err!( + self.tcx.sess, + lifetime.span, + E0657, + "`impl Trait` can only capture lifetimes \ + bound at the fn or impl level" + ) + .emit(); } + self.uninsert_lifetime_on_error(lifetime, def.unwrap()); } } diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs index da0b691a958e1..f64c56487f24c 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs @@ -840,39 +840,38 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { }; for refs_remaining in 0..refs_number { - if let ty::Ref(_, inner_ty, _) = suggested_ty.kind() { - suggested_ty = inner_ty; + let ty::Ref(_, inner_ty, _) = suggested_ty.kind() else { + break; + }; + suggested_ty = inner_ty; - let new_obligation = self.mk_trait_obligation_with_new_self_ty( - obligation.param_env, - trait_ref, - suggested_ty, - ); + let new_obligation = self.mk_trait_obligation_with_new_self_ty( + obligation.param_env, + trait_ref, + suggested_ty, + ); - if self.predicate_may_hold(&new_obligation) { - let sp = self - .tcx - .sess - .source_map() - .span_take_while(span, |c| c.is_whitespace() || *c == '&'); + if self.predicate_may_hold(&new_obligation) { + let sp = self + .tcx + .sess + .source_map() + .span_take_while(span, |c| c.is_whitespace() || *c == '&'); - let remove_refs = refs_remaining + 1; + let remove_refs = refs_remaining + 1; - let msg = if remove_refs == 1 { - "consider removing the leading `&`-reference".to_string() - } else { - format!("consider removing {} leading `&`-references", remove_refs) - }; + let msg = if remove_refs == 1 { + "consider removing the leading `&`-reference".to_string() + } else { + format!("consider removing {} leading `&`-references", remove_refs) + }; - err.span_suggestion_short( - sp, - &msg, - String::new(), - Applicability::MachineApplicable, - ); - break; - } - } else { + err.span_suggestion_short( + sp, + &msg, + String::new(), + Applicability::MachineApplicable, + ); break; } } From 7507fb6306d540a6f07f6f325d25925311b037a2 Mon Sep 17 00:00:00 2001 From: Noah Lev Date: Tue, 18 Jan 2022 16:32:58 -0800 Subject: [PATCH 14/21] Shorten and improve messages --- compiler/rustc_typeck/src/check/op.rs | 8 +- src/test/ui/issues/issue-47377.stderr | 15 +-- src/test/ui/issues/issue-47380.stderr | 15 +-- src/test/ui/span/issue-39018.stderr | 98 +++++++------------ .../ui/str/str-concat-on-double-ref.stderr | 15 +-- ...non-1-width-unicode-multiline-label.stderr | 19 ++-- 6 files changed, 58 insertions(+), 112 deletions(-) diff --git a/compiler/rustc_typeck/src/check/op.rs b/compiler/rustc_typeck/src/check/op.rs index c7bb66f339c14..82da66c09e4de 100644 --- a/compiler/rustc_typeck/src/check/op.rs +++ b/compiler/rustc_typeck/src/check/op.rs @@ -549,11 +549,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { is_assign: IsAssign, op: hir::BinOp, ) -> bool { - let str_concat_note = "String concatenation appends the string on the right to the -string on the left and may require reallocation. -This requires ownership of the string on the left."; + let str_concat_note = "string concatenation requires an owned `String` on the left"; let rm_borrow_msg = "remove the borrow to obtain an owned `String`"; - let to_owned_msg = "use `to_owned()` to create an owned `String` from a string reference"; + let to_owned_msg = "create an owned `String` from a string reference"; let string_type = self.tcx.get_diagnostic_item(sym::String); let is_std_string = |ty: Ty<'tcx>| match ty.ty_adt_def() { @@ -603,7 +601,7 @@ This requires ownership of the string on the left."; sugg_msg = "remove the borrow on the left and add one on the right"; (lhs_expr.span.until(lhs_inner_expr.span), "".to_owned()) } else { - sugg_msg = "call `.to_owned()` on the left and add a borrow on the right"; + sugg_msg = "create an owned `String` on the left and add a borrow on the right"; (lhs_expr.span.shrink_to_hi(), ".to_owned()".to_owned()) }; let suggestions = vec![ diff --git a/src/test/ui/issues/issue-47377.stderr b/src/test/ui/issues/issue-47377.stderr index 97fbb53bd0256..e4b907070a681 100644 --- a/src/test/ui/issues/issue-47377.stderr +++ b/src/test/ui/issues/issue-47377.stderr @@ -2,18 +2,13 @@ error[E0369]: cannot add `&str` to `&str` --> $DIR/issue-47377.rs:4:14 | LL | let _a = b + ", World!"; - | - ^ ---------- &str - | | | - | | `+` cannot be used to concatenate two `&str` strings + | --^ ---------- &str + | ||| + | ||`+` cannot be used to concatenate two `&str` strings + | |help: create an owned `String` from a string reference: `.to_owned()` | &str | - = note: String concatenation appends the string on the right to the - string on the left and may require reallocation. - This requires ownership of the string on the left. -help: use `to_owned()` to create an owned `String` from a string reference - | -LL | let _a = b.to_owned() + ", World!"; - | +++++++++++ + = note: string concatenation requires an owned `String` on the left error: aborting due to previous error diff --git a/src/test/ui/issues/issue-47380.stderr b/src/test/ui/issues/issue-47380.stderr index 7a73d41a0351b..7ad369fcd0e74 100644 --- a/src/test/ui/issues/issue-47380.stderr +++ b/src/test/ui/issues/issue-47380.stderr @@ -2,18 +2,13 @@ error[E0369]: cannot add `&str` to `&str` --> $DIR/issue-47380.rs:3:35 | LL | println!("🦀🦀🦀🦀🦀"); let _a = b + ", World!"; - | - ^ ---------- &str - | | | - | | `+` cannot be used to concatenate two `&str` strings + | --^ ---------- &str + | ||| + | ||`+` cannot be used to concatenate two `&str` strings + | |help: create an owned `String` from a string reference: `.to_owned()` | &str | - = note: String concatenation appends the string on the right to the - string on the left and may require reallocation. - This requires ownership of the string on the left. -help: use `to_owned()` to create an owned `String` from a string reference - | -LL | println!("🦀🦀🦀🦀🦀"); let _a = b.to_owned() + ", World!"; - | +++++++++++ + = note: string concatenation requires an owned `String` on the left error: aborting due to previous error diff --git a/src/test/ui/span/issue-39018.stderr b/src/test/ui/span/issue-39018.stderr index 9e466f3a9a053..9cfb015e753f8 100644 --- a/src/test/ui/span/issue-39018.stderr +++ b/src/test/ui/span/issue-39018.stderr @@ -2,18 +2,13 @@ error[E0369]: cannot add `&str` to `&str` --> $DIR/issue-39018.rs:2:22 | LL | let x = "Hello " + "World!"; - | -------- ^ -------- &str - | | | - | | `+` cannot be used to concatenate two `&str` strings + | ---------^ -------- &str + | | || + | | |`+` cannot be used to concatenate two `&str` strings + | | help: create an owned `String` from a string reference: `.to_owned()` | &str | - = note: String concatenation appends the string on the right to the - string on the left and may require reallocation. - This requires ownership of the string on the left. -help: use `to_owned()` to create an owned `String` from a string reference - | -LL | let x = "Hello ".to_owned() + "World!"; - | +++++++++++ + = note: string concatenation requires an owned `String` on the left error[E0369]: cannot add `World` to `World` --> $DIR/issue-39018.rs:8:26 @@ -49,7 +44,7 @@ LL | let x = "Hello " + "World!".to_owned(); | | `+` cannot be used to concatenate a `&str` with a `String` | &str | -help: call `.to_owned()` on the left and add a borrow on the right +help: create an owned `String` on the left and add a borrow on the right | LL | let x = "Hello ".to_owned() + &"World!".to_owned(); | +++++++++++ + @@ -64,9 +59,7 @@ LL | let _ = &a + &b; | &String | help: remove the borrow to obtain an owned `String` | - = note: String concatenation appends the string on the right to the - string on the left and may require reallocation. - This requires ownership of the string on the left. + = note: string concatenation requires an owned `String` on the left error[E0369]: cannot add `String` to `&String` --> $DIR/issue-39018.rs:27:16 @@ -101,7 +94,7 @@ LL | let _ = e + b; | | `+` cannot be used to concatenate a `&str` with a `String` | &String | -help: call `.to_owned()` on the left and add a borrow on the right +help: create an owned `String` on the left and add a borrow on the right | LL | let _ = e.to_owned() + &b; | +++++++++++ + @@ -110,52 +103,37 @@ error[E0369]: cannot add `&String` to `&String` --> $DIR/issue-39018.rs:31:15 | LL | let _ = e + &b; - | - ^ -- &String - | | | - | | `+` cannot be used to concatenate two `&str` strings + | --^ -- &String + | ||| + | ||`+` cannot be used to concatenate two `&str` strings + | |help: create an owned `String` from a string reference: `.to_owned()` | &String | - = note: String concatenation appends the string on the right to the - string on the left and may require reallocation. - This requires ownership of the string on the left. -help: use `to_owned()` to create an owned `String` from a string reference - | -LL | let _ = e.to_owned() + &b; - | +++++++++++ + = note: string concatenation requires an owned `String` on the left error[E0369]: cannot add `&str` to `&String` --> $DIR/issue-39018.rs:32:15 | LL | let _ = e + d; - | - ^ - &str - | | | - | | `+` cannot be used to concatenate two `&str` strings + | --^ - &str + | ||| + | ||`+` cannot be used to concatenate two `&str` strings + | |help: create an owned `String` from a string reference: `.to_owned()` | &String | - = note: String concatenation appends the string on the right to the - string on the left and may require reallocation. - This requires ownership of the string on the left. -help: use `to_owned()` to create an owned `String` from a string reference - | -LL | let _ = e.to_owned() + d; - | +++++++++++ + = note: string concatenation requires an owned `String` on the left error[E0369]: cannot add `&&str` to `&String` --> $DIR/issue-39018.rs:33:15 | LL | let _ = e + &d; - | - ^ -- &&str - | | | - | | `+` cannot be used to concatenate two `&str` strings + | --^ -- &&str + | ||| + | ||`+` cannot be used to concatenate two `&str` strings + | |help: create an owned `String` from a string reference: `.to_owned()` | &String | - = note: String concatenation appends the string on the right to the - string on the left and may require reallocation. - This requires ownership of the string on the left. -help: use `to_owned()` to create an owned `String` from a string reference - | -LL | let _ = e.to_owned() + &d; - | +++++++++++ + = note: string concatenation requires an owned `String` on the left error[E0369]: cannot add `&&str` to `&&str` --> $DIR/issue-39018.rs:34:16 @@ -177,35 +155,25 @@ error[E0369]: cannot add `&&str` to `&str` --> $DIR/issue-39018.rs:36:15 | LL | let _ = c + &d; - | - ^ -- &&str - | | | - | | `+` cannot be used to concatenate two `&str` strings + | --^ -- &&str + | ||| + | ||`+` cannot be used to concatenate two `&str` strings + | |help: create an owned `String` from a string reference: `.to_owned()` | &str | - = note: String concatenation appends the string on the right to the - string on the left and may require reallocation. - This requires ownership of the string on the left. -help: use `to_owned()` to create an owned `String` from a string reference - | -LL | let _ = c.to_owned() + &d; - | +++++++++++ + = note: string concatenation requires an owned `String` on the left error[E0369]: cannot add `&str` to `&str` --> $DIR/issue-39018.rs:37:15 | LL | let _ = c + d; - | - ^ - &str - | | | - | | `+` cannot be used to concatenate two `&str` strings + | --^ - &str + | ||| + | ||`+` cannot be used to concatenate two `&str` strings + | |help: create an owned `String` from a string reference: `.to_owned()` | &str | - = note: String concatenation appends the string on the right to the - string on the left and may require reallocation. - This requires ownership of the string on the left. -help: use `to_owned()` to create an owned `String` from a string reference - | -LL | let _ = c.to_owned() + d; - | +++++++++++ + = note: string concatenation requires an owned `String` on the left error: aborting due to 14 previous errors diff --git a/src/test/ui/str/str-concat-on-double-ref.stderr b/src/test/ui/str/str-concat-on-double-ref.stderr index d239ec0d9fcc9..251bc7ac0ead7 100644 --- a/src/test/ui/str/str-concat-on-double-ref.stderr +++ b/src/test/ui/str/str-concat-on-double-ref.stderr @@ -2,18 +2,13 @@ error[E0369]: cannot add `&str` to `&String` --> $DIR/str-concat-on-double-ref.rs:4:15 | LL | let c = a + b; - | - ^ - &str - | | | - | | `+` cannot be used to concatenate two `&str` strings + | --^ - &str + | ||| + | ||`+` cannot be used to concatenate two `&str` strings + | |help: create an owned `String` from a string reference: `.to_owned()` | &String | - = note: String concatenation appends the string on the right to the - string on the left and may require reallocation. - This requires ownership of the string on the left. -help: use `to_owned()` to create an owned `String` from a string reference - | -LL | let c = a.to_owned() + b; - | +++++++++++ + = note: string concatenation requires an owned `String` on the left error: aborting due to previous error diff --git a/src/test/ui/terminal-width/non-1-width-unicode-multiline-label.stderr b/src/test/ui/terminal-width/non-1-width-unicode-multiline-label.stderr index 55e993db3d3d4..a97ecc4ce1591 100644 --- a/src/test/ui/terminal-width/non-1-width-unicode-multiline-label.stderr +++ b/src/test/ui/terminal-width/non-1-width-unicode-multiline-label.stderr @@ -1,19 +1,14 @@ error[E0369]: cannot add `&str` to `&str` --> $DIR/non-1-width-unicode-multiline-label.rs:5:260 | -LL | ...ཽཾཿ྄ཱྀྀྂྃ྅྆྇ྈྉྊྋྌྍྎྏྐྑྒྒྷྔྕྖྗ྘ྙྚྛྜྜྷྞྟྠྡྡྷྣྤྥྦྦྷྨྩྪྫྫྷྭྮྯྰྱྲླྴྵྶྷྸྐྵྺྻྼ྽྾྿࿀࿁࿂࿃࿄࿅࿆࿇...࿋࿌࿍࿎࿏࿐࿑࿒࿓࿔࿕࿖࿗࿘࿙࿚"; let _a = unicode_is_fun + " really fun!"; - | -------------- ^ -------------- &str - | | | - | | `+` cannot be used to concatenate two `&str` strings - | &str +LL | ...྅྆྇ྈྉྊྋྌྍྎྏྐྑྒྒྷྔྕྖྗ྘ྙྚྛྜྜྷྞྟྠྡྡྷྣྤྥྦྦྷྨྩྪྫྫྷྭྮྯྰྱྲླྴྵྶྷྸྐྵྺྻྼ྽྾྿࿀࿁࿂࿃࿄࿅࿆࿇࿈࿉࿊࿋࿌࿍࿎...࿒࿓࿔࿕࿖࿗࿘࿙࿚"; let _a = unicode_is_fun + " really fun!"; + | ---------------^ -------------- &str + | | || + | | |`+` cannot be used to concatenate two `&str` strings + | | help: create an owned `String` from a string reference: `.to_owned()` + | &str | - = note: String concatenation appends the string on the right to the - string on the left and may require reallocation. - This requires ownership of the string on the left. -help: use `to_owned()` to create an owned `String` from a string reference - | -LL | let _ = "ༀ༁༂༃༄༅༆༇༈༉༊་༌།༎༏༐༑༒༓༔༕༖༗༘༙༚༛༜༝༞༟༠༡༢༣༤༥༦༧༨༩༪༫༬༭༮༯༰༱༲༳༴༵༶༷༸༹༺༻༼༽༾༿ཀཁགགྷངཅཆཇ཈ཉཊཋཌཌྷཎཏཐདདྷནཔཕབབྷམཙཚཛཛྷཝཞཟའཡརལཤཥསཧཨཀྵཪཫཬ཭཮཯཰ཱཱཱིིུུྲྀཷླྀཹེཻོཽཾཿ྄ཱྀྀྂྃ྅྆྇ྈྉྊྋྌྍྎྏྐྑྒྒྷྔྕྖྗ྘ྙྚྛྜྜྷྞྟྠྡྡྷྣྤྥྦྦྷྨྩྪྫྫྷྭྮྯྰྱྲླྴྵྶྷྸྐྵྺྻྼ྽྾྿࿀࿁࿂࿃࿄࿅࿆࿇࿈࿉࿊࿋࿌࿍࿎࿏࿐࿑࿒࿓࿔࿕࿖࿗࿘࿙࿚"; let _a = unicode_is_fun.to_owned() + " really fun!"; - | +++++++++++ + = note: string concatenation requires an owned `String` on the left error: aborting due to previous error From 7c4eca06871f83257f9f503c3a91a8946026133a Mon Sep 17 00:00:00 2001 From: Noah Lev Date: Tue, 18 Jan 2022 16:38:06 -0800 Subject: [PATCH 15/21] Make suggestions verbose --- compiler/rustc_typeck/src/check/op.rs | 10 ++- src/test/ui/issues/issue-47377.stderr | 11 +-- src/test/ui/issues/issue-47380.stderr | 11 +-- src/test/ui/span/issue-39018.stderr | 72 ++++++++++++------- .../ui/str/str-concat-on-double-ref.stderr | 11 +-- ...non-1-width-unicode-multiline-label.stderr | 15 ++-- 6 files changed, 84 insertions(+), 46 deletions(-) diff --git a/compiler/rustc_typeck/src/check/op.rs b/compiler/rustc_typeck/src/check/op.rs index 82da66c09e4de..81662b752b7b0 100644 --- a/compiler/rustc_typeck/src/check/op.rs +++ b/compiler/rustc_typeck/src/check/op.rs @@ -570,14 +570,14 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { err.span_label(op.span, "`+` cannot be used to concatenate two `&str` strings"); err.note(str_concat_note); if let hir::ExprKind::AddrOf(_, _, lhs_inner_expr) = lhs_expr.kind { - err.span_suggestion( + err.span_suggestion_verbose( lhs_expr.span.until(lhs_inner_expr.span), rm_borrow_msg, "".to_owned(), Applicability::MachineApplicable ); } else { - err.span_suggestion( + err.span_suggestion_verbose( lhs_expr.span.shrink_to_hi(), to_owned_msg, ".to_owned()".to_owned(), @@ -608,7 +608,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { lhs_sugg, (rhs_expr.span.shrink_to_lo(), "&".to_owned()), ]; - err.multipart_suggestion(sugg_msg, suggestions, Applicability::MachineApplicable); + err.multipart_suggestion_verbose( + sugg_msg, + suggestions, + Applicability::MachineApplicable, + ); } IsAssign::Yes => { err.note(str_concat_note); diff --git a/src/test/ui/issues/issue-47377.stderr b/src/test/ui/issues/issue-47377.stderr index e4b907070a681..4f0fd948e7604 100644 --- a/src/test/ui/issues/issue-47377.stderr +++ b/src/test/ui/issues/issue-47377.stderr @@ -2,13 +2,16 @@ error[E0369]: cannot add `&str` to `&str` --> $DIR/issue-47377.rs:4:14 | LL | let _a = b + ", World!"; - | --^ ---------- &str - | ||| - | ||`+` cannot be used to concatenate two `&str` strings - | |help: create an owned `String` from a string reference: `.to_owned()` + | - ^ ---------- &str + | | | + | | `+` cannot be used to concatenate two `&str` strings | &str | = note: string concatenation requires an owned `String` on the left +help: create an owned `String` from a string reference + | +LL | let _a = b.to_owned() + ", World!"; + | +++++++++++ error: aborting due to previous error diff --git a/src/test/ui/issues/issue-47380.stderr b/src/test/ui/issues/issue-47380.stderr index 7ad369fcd0e74..b04ac5536c41f 100644 --- a/src/test/ui/issues/issue-47380.stderr +++ b/src/test/ui/issues/issue-47380.stderr @@ -2,13 +2,16 @@ error[E0369]: cannot add `&str` to `&str` --> $DIR/issue-47380.rs:3:35 | LL | println!("🦀🦀🦀🦀🦀"); let _a = b + ", World!"; - | --^ ---------- &str - | ||| - | ||`+` cannot be used to concatenate two `&str` strings - | |help: create an owned `String` from a string reference: `.to_owned()` + | - ^ ---------- &str + | | | + | | `+` cannot be used to concatenate two `&str` strings | &str | = note: string concatenation requires an owned `String` on the left +help: create an owned `String` from a string reference + | +LL | println!("🦀🦀🦀🦀🦀"); let _a = b.to_owned() + ", World!"; + | +++++++++++ error: aborting due to previous error diff --git a/src/test/ui/span/issue-39018.stderr b/src/test/ui/span/issue-39018.stderr index 9cfb015e753f8..e2e7ce1ed18e7 100644 --- a/src/test/ui/span/issue-39018.stderr +++ b/src/test/ui/span/issue-39018.stderr @@ -2,13 +2,16 @@ error[E0369]: cannot add `&str` to `&str` --> $DIR/issue-39018.rs:2:22 | LL | let x = "Hello " + "World!"; - | ---------^ -------- &str - | | || - | | |`+` cannot be used to concatenate two `&str` strings - | | help: create an owned `String` from a string reference: `.to_owned()` + | -------- ^ -------- &str + | | | + | | `+` cannot be used to concatenate two `&str` strings | &str | = note: string concatenation requires an owned `String` on the left +help: create an owned `String` from a string reference + | +LL | let x = "Hello ".to_owned() + "World!"; + | +++++++++++ error[E0369]: cannot add `World` to `World` --> $DIR/issue-39018.rs:8:26 @@ -57,9 +60,13 @@ LL | let _ = &a + &b; | | | | | `+` cannot be used to concatenate two `&str` strings | &String - | help: remove the borrow to obtain an owned `String` | = note: string concatenation requires an owned `String` on the left +help: remove the borrow to obtain an owned `String` + | +LL - let _ = &a + &b; +LL + let _ = a + &b; + | error[E0369]: cannot add `String` to `&String` --> $DIR/issue-39018.rs:27:16 @@ -103,37 +110,46 @@ error[E0369]: cannot add `&String` to `&String` --> $DIR/issue-39018.rs:31:15 | LL | let _ = e + &b; - | --^ -- &String - | ||| - | ||`+` cannot be used to concatenate two `&str` strings - | |help: create an owned `String` from a string reference: `.to_owned()` + | - ^ -- &String + | | | + | | `+` cannot be used to concatenate two `&str` strings | &String | = note: string concatenation requires an owned `String` on the left +help: create an owned `String` from a string reference + | +LL | let _ = e.to_owned() + &b; + | +++++++++++ error[E0369]: cannot add `&str` to `&String` --> $DIR/issue-39018.rs:32:15 | LL | let _ = e + d; - | --^ - &str - | ||| - | ||`+` cannot be used to concatenate two `&str` strings - | |help: create an owned `String` from a string reference: `.to_owned()` + | - ^ - &str + | | | + | | `+` cannot be used to concatenate two `&str` strings | &String | = note: string concatenation requires an owned `String` on the left +help: create an owned `String` from a string reference + | +LL | let _ = e.to_owned() + d; + | +++++++++++ error[E0369]: cannot add `&&str` to `&String` --> $DIR/issue-39018.rs:33:15 | LL | let _ = e + &d; - | --^ -- &&str - | ||| - | ||`+` cannot be used to concatenate two `&str` strings - | |help: create an owned `String` from a string reference: `.to_owned()` + | - ^ -- &&str + | | | + | | `+` cannot be used to concatenate two `&str` strings | &String | = note: string concatenation requires an owned `String` on the left +help: create an owned `String` from a string reference + | +LL | let _ = e.to_owned() + &d; + | +++++++++++ error[E0369]: cannot add `&&str` to `&&str` --> $DIR/issue-39018.rs:34:16 @@ -155,25 +171,31 @@ error[E0369]: cannot add `&&str` to `&str` --> $DIR/issue-39018.rs:36:15 | LL | let _ = c + &d; - | --^ -- &&str - | ||| - | ||`+` cannot be used to concatenate two `&str` strings - | |help: create an owned `String` from a string reference: `.to_owned()` + | - ^ -- &&str + | | | + | | `+` cannot be used to concatenate two `&str` strings | &str | = note: string concatenation requires an owned `String` on the left +help: create an owned `String` from a string reference + | +LL | let _ = c.to_owned() + &d; + | +++++++++++ error[E0369]: cannot add `&str` to `&str` --> $DIR/issue-39018.rs:37:15 | LL | let _ = c + d; - | --^ - &str - | ||| - | ||`+` cannot be used to concatenate two `&str` strings - | |help: create an owned `String` from a string reference: `.to_owned()` + | - ^ - &str + | | | + | | `+` cannot be used to concatenate two `&str` strings | &str | = note: string concatenation requires an owned `String` on the left +help: create an owned `String` from a string reference + | +LL | let _ = c.to_owned() + d; + | +++++++++++ error: aborting due to 14 previous errors diff --git a/src/test/ui/str/str-concat-on-double-ref.stderr b/src/test/ui/str/str-concat-on-double-ref.stderr index 251bc7ac0ead7..bd354679f7888 100644 --- a/src/test/ui/str/str-concat-on-double-ref.stderr +++ b/src/test/ui/str/str-concat-on-double-ref.stderr @@ -2,13 +2,16 @@ error[E0369]: cannot add `&str` to `&String` --> $DIR/str-concat-on-double-ref.rs:4:15 | LL | let c = a + b; - | --^ - &str - | ||| - | ||`+` cannot be used to concatenate two `&str` strings - | |help: create an owned `String` from a string reference: `.to_owned()` + | - ^ - &str + | | | + | | `+` cannot be used to concatenate two `&str` strings | &String | = note: string concatenation requires an owned `String` on the left +help: create an owned `String` from a string reference + | +LL | let c = a.to_owned() + b; + | +++++++++++ error: aborting due to previous error diff --git a/src/test/ui/terminal-width/non-1-width-unicode-multiline-label.stderr b/src/test/ui/terminal-width/non-1-width-unicode-multiline-label.stderr index a97ecc4ce1591..bf277362dbab2 100644 --- a/src/test/ui/terminal-width/non-1-width-unicode-multiline-label.stderr +++ b/src/test/ui/terminal-width/non-1-width-unicode-multiline-label.stderr @@ -1,14 +1,17 @@ error[E0369]: cannot add `&str` to `&str` --> $DIR/non-1-width-unicode-multiline-label.rs:5:260 | -LL | ...྅྆྇ྈྉྊྋྌྍྎྏྐྑྒྒྷྔྕྖྗ྘ྙྚྛྜྜྷྞྟྠྡྡྷྣྤྥྦྦྷྨྩྪྫྫྷྭྮྯྰྱྲླྴྵྶྷྸྐྵྺྻྼ྽྾྿࿀࿁࿂࿃࿄࿅࿆࿇࿈࿉࿊࿋࿌࿍࿎...࿒࿓࿔࿕࿖࿗࿘࿙࿚"; let _a = unicode_is_fun + " really fun!"; - | ---------------^ -------------- &str - | | || - | | |`+` cannot be used to concatenate two `&str` strings - | | help: create an owned `String` from a string reference: `.to_owned()` - | &str +LL | ...ཽཾཿ྄ཱྀྀྂྃ྅྆྇ྈྉྊྋྌྍྎྏྐྑྒྒྷྔྕྖྗ྘ྙྚྛྜྜྷྞྟྠྡྡྷྣྤྥྦྦྷྨྩྪྫྫྷྭྮྯྰྱྲླྴྵྶྷྸྐྵྺྻྼ྽྾྿࿀࿁࿂࿃࿄࿅࿆࿇...࿋࿌࿍࿎࿏࿐࿑࿒࿓࿔࿕࿖࿗࿘࿙࿚"; let _a = unicode_is_fun + " really fun!"; + | -------------- ^ -------------- &str + | | | + | | `+` cannot be used to concatenate two `&str` strings + | &str | = note: string concatenation requires an owned `String` on the left +help: create an owned `String` from a string reference + | +LL | let _ = "ༀ༁༂༃༄༅༆༇༈༉༊་༌།༎༏༐༑༒༓༔༕༖༗༘༙༚༛༜༝༞༟༠༡༢༣༤༥༦༧༨༩༪༫༬༭༮༯༰༱༲༳༴༵༶༷༸༹༺༻༼༽༾༿ཀཁགགྷངཅཆཇ཈ཉཊཋཌཌྷཎཏཐདདྷནཔཕབབྷམཙཚཛཛྷཝཞཟའཡརལཤཥསཧཨཀྵཪཫཬ཭཮཯཰ཱཱཱིིུུྲྀཷླྀཹེཻོཽཾཿ྄ཱྀྀྂྃ྅྆྇ྈྉྊྋྌྍྎྏྐྑྒྒྷྔྕྖྗ྘ྙྚྛྜྜྷྞྟྠྡྡྷྣྤྥྦྦྷྨྩྪྫྫྷྭྮྯྰྱྲླྴྵྶྷྸྐྵྺྻྼ྽྾྿࿀࿁࿂࿃࿄࿅࿆࿇࿈࿉࿊࿋࿌࿍࿎࿏࿐࿑࿒࿓࿔࿕࿖࿗࿘࿙࿚"; let _a = unicode_is_fun.to_owned() + " really fun!"; + | +++++++++++ error: aborting due to previous error From 7bc47cfd92eefa54a88d20a6dff9d7445a7996df Mon Sep 17 00:00:00 2001 From: Jakob Degen Date: Thu, 20 Jan 2022 04:54:03 -0500 Subject: [PATCH 16/21] Correct docs in `Arc` and `Rc`. A number of trait implementations incorrectly claimed to be zero cost. --- library/std/src/ffi/c_str.rs | 6 ++++-- library/std/src/ffi/os_str.rs | 6 ++++-- library/std/src/path.rs | 8 +++++--- 3 files changed, 13 insertions(+), 7 deletions(-) diff --git a/library/std/src/ffi/c_str.rs b/library/std/src/ffi/c_str.rs index d859bff1a45fa..66fee2fe54837 100644 --- a/library/std/src/ffi/c_str.rs +++ b/library/std/src/ffi/c_str.rs @@ -973,7 +973,8 @@ impl<'a> From<&'a CString> for Cow<'a, CStr> { #[stable(feature = "shared_from_slice2", since = "1.24.0")] impl From for Arc { - /// Converts a [`CString`] into an [Arc]<[CStr]> without copying or allocating. + /// Converts a [`CString`] into an [Arc]<[CStr]> by moving the [`CString`] + /// data into a new [`Arc`] buffer. #[inline] fn from(s: CString) -> Arc { let arc: Arc<[u8]> = Arc::from(s.into_inner()); @@ -992,7 +993,8 @@ impl From<&CStr> for Arc { #[stable(feature = "shared_from_slice2", since = "1.24.0")] impl From for Rc { - /// Converts a [`CString`] into an [Rc]<[CStr]> without copying or allocating. + /// Converts a [`CString`] into an [Rc]<[CStr]> by moving the [`CString`] + /// data into a new [`Arc`] buffer. #[inline] fn from(s: CString) -> Rc { let rc: Rc<[u8]> = Rc::from(s.into_inner()); diff --git a/library/std/src/ffi/os_str.rs b/library/std/src/ffi/os_str.rs index 982ad1898788e..81f72e34d9388 100644 --- a/library/std/src/ffi/os_str.rs +++ b/library/std/src/ffi/os_str.rs @@ -989,7 +989,8 @@ impl Clone for Box { #[stable(feature = "shared_from_slice2", since = "1.24.0")] impl From for Arc { - /// Converts an [`OsString`] into an [Arc]<[OsStr]> without copying or allocating. + /// Converts an [`OsString`] into an [Arc]<[OsStr]> by moving the [`OsString`] + /// data into a new [`Arc`] buffer. #[inline] fn from(s: OsString) -> Arc { let arc = s.inner.into_arc(); @@ -1008,7 +1009,8 @@ impl From<&OsStr> for Arc { #[stable(feature = "shared_from_slice2", since = "1.24.0")] impl From for Rc { - /// Converts an [`OsString`] into an [Rc]<[OsStr]> without copying or allocating. + /// Converts an [`OsString`] into an [Rc]<[OsStr]> by moving the [`OsString`] + /// data into a new [`Rc`] buffer. #[inline] fn from(s: OsString) -> Rc { let rc = s.inner.into_rc(); diff --git a/library/std/src/path.rs b/library/std/src/path.rs index f509403fe2e43..558333518f1d4 100644 --- a/library/std/src/path.rs +++ b/library/std/src/path.rs @@ -1766,7 +1766,8 @@ impl<'a> From> for PathBuf { #[stable(feature = "shared_from_slice2", since = "1.24.0")] impl From for Arc { - /// Converts a [`PathBuf`] into an [`Arc`] by moving the [`PathBuf`] data into a new [`Arc`] buffer. + /// Converts a [`PathBuf`] into an [Arc]<[Path]> by moving the [`PathBuf`] data + /// into a new [`Arc`] buffer. #[inline] fn from(s: PathBuf) -> Arc { let arc: Arc = Arc::from(s.into_os_string()); @@ -1786,7 +1787,8 @@ impl From<&Path> for Arc { #[stable(feature = "shared_from_slice2", since = "1.24.0")] impl From for Rc { - /// Converts a [`PathBuf`] into an [`Rc`] by moving the [`PathBuf`] data into a new `Rc` buffer. + /// Converts a [`PathBuf`] into an [Rc]<[Path]> by moving the [`PathBuf`] data into + /// a new [`Rc`] buffer. #[inline] fn from(s: PathBuf) -> Rc { let rc: Rc = Rc::from(s.into_os_string()); @@ -1796,7 +1798,7 @@ impl From for Rc { #[stable(feature = "shared_from_slice2", since = "1.24.0")] impl From<&Path> for Rc { - /// Converts a [`Path`] into an [`Rc`] by copying the [`Path`] data into a new `Rc` buffer. + /// Converts a [`Path`] into an [`Rc`] by copying the [`Path`] data into a new [`Rc`] buffer. #[inline] fn from(s: &Path) -> Rc { let rc: Rc = Rc::from(s.as_os_str()); From 4de76184aa7b8257d44b7a9abf5f140727c84b48 Mon Sep 17 00:00:00 2001 From: Jakob Degen Date: Thu, 20 Jan 2022 05:36:19 -0500 Subject: [PATCH 17/21] Remove unnecessary unsafe code in `Arc` deferred initialization examples. --- library/alloc/src/rc.rs | 50 ++++++++++++++++----------------------- library/alloc/src/sync.rs | 50 ++++++++++++++++----------------------- 2 files changed, 42 insertions(+), 58 deletions(-) diff --git a/library/alloc/src/rc.rs b/library/alloc/src/rc.rs index 33bee4324fd38..bf5fcfdcbf5fa 100644 --- a/library/alloc/src/rc.rs +++ b/library/alloc/src/rc.rs @@ -451,12 +451,10 @@ impl Rc { /// /// let mut five = Rc::::new_uninit(); /// - /// let five = unsafe { - /// // Deferred initialization: - /// Rc::get_mut_unchecked(&mut five).as_mut_ptr().write(5); + /// // Deferred initialization: + /// Rc::get_mut(&mut five).unwrap().write(5); /// - /// five.assume_init() - /// }; + /// let five = unsafe { five.assume_init() }; /// /// assert_eq!(*five, 5) /// ``` @@ -543,12 +541,10 @@ impl Rc { /// /// let mut five = Rc::::try_new_uninit()?; /// - /// let five = unsafe { - /// // Deferred initialization: - /// Rc::get_mut_unchecked(&mut five).as_mut_ptr().write(5); + /// // Deferred initialization: + /// Rc::get_mut(&mut five).unwrap().write(5); /// - /// five.assume_init() - /// }; + /// let five = unsafe { five.assume_init() }; /// /// assert_eq!(*five, 5); /// # Ok::<(), std::alloc::AllocError>(()) @@ -660,14 +656,13 @@ impl Rc<[T]> { /// /// let mut values = Rc::<[u32]>::new_uninit_slice(3); /// - /// let values = unsafe { - /// // Deferred initialization: - /// Rc::get_mut_unchecked(&mut values)[0].as_mut_ptr().write(1); - /// Rc::get_mut_unchecked(&mut values)[1].as_mut_ptr().write(2); - /// Rc::get_mut_unchecked(&mut values)[2].as_mut_ptr().write(3); + /// // Deferred initialization: + /// let data = Rc::get_mut(&mut values).unwrap(); + /// data[0].write(1); + /// data[1].write(2); + /// data[2].write(3); /// - /// values.assume_init() - /// }; + /// let values = unsafe { values.assume_init() }; /// /// assert_eq!(*values, [1, 2, 3]) /// ``` @@ -738,12 +733,10 @@ impl Rc> { /// /// let mut five = Rc::::new_uninit(); /// - /// let five = unsafe { - /// // Deferred initialization: - /// Rc::get_mut_unchecked(&mut five).as_mut_ptr().write(5); + /// // Deferred initialization: + /// Rc::get_mut(&mut five).unwrap().write(5); /// - /// five.assume_init() - /// }; + /// let five = unsafe { five.assume_init() }; /// /// assert_eq!(*five, 5) /// ``` @@ -777,14 +770,13 @@ impl Rc<[mem::MaybeUninit]> { /// /// let mut values = Rc::<[u32]>::new_uninit_slice(3); /// - /// let values = unsafe { - /// // Deferred initialization: - /// Rc::get_mut_unchecked(&mut values)[0].as_mut_ptr().write(1); - /// Rc::get_mut_unchecked(&mut values)[1].as_mut_ptr().write(2); - /// Rc::get_mut_unchecked(&mut values)[2].as_mut_ptr().write(3); + /// // Deferred initialization: + /// let data = Rc::get_mut(&mut values).unwrap(); + /// data[0].write(1); + /// data[1].write(2); + /// data[2].write(3); /// - /// values.assume_init() - /// }; + /// let values = unsafe { values.assume_init() }; /// /// assert_eq!(*values, [1, 2, 3]) /// ``` diff --git a/library/alloc/src/sync.rs b/library/alloc/src/sync.rs index 7c065f37d1fa8..ab8a44b214743 100644 --- a/library/alloc/src/sync.rs +++ b/library/alloc/src/sync.rs @@ -437,12 +437,10 @@ impl Arc { /// /// let mut five = Arc::::new_uninit(); /// - /// let five = unsafe { - /// // Deferred initialization: - /// Arc::get_mut_unchecked(&mut five).as_mut_ptr().write(5); + /// // Deferred initialization: + /// Arc::get_mut(&mut five).unwrap().write(5); /// - /// five.assume_init() - /// }; + /// let five = unsafe { five.assume_init() }; /// /// assert_eq!(*five, 5) /// ``` @@ -545,12 +543,10 @@ impl Arc { /// /// let mut five = Arc::::try_new_uninit()?; /// - /// let five = unsafe { - /// // Deferred initialization: - /// Arc::get_mut_unchecked(&mut five).as_mut_ptr().write(5); + /// // Deferred initialization: + /// Arc::get_mut(&mut five).unwrap().write(5); /// - /// five.assume_init() - /// }; + /// let five = unsafe { five.assume_init() }; /// /// assert_eq!(*five, 5); /// # Ok::<(), std::alloc::AllocError>(()) @@ -652,14 +648,13 @@ impl Arc<[T]> { /// /// let mut values = Arc::<[u32]>::new_uninit_slice(3); /// - /// let values = unsafe { - /// // Deferred initialization: - /// Arc::get_mut_unchecked(&mut values)[0].as_mut_ptr().write(1); - /// Arc::get_mut_unchecked(&mut values)[1].as_mut_ptr().write(2); - /// Arc::get_mut_unchecked(&mut values)[2].as_mut_ptr().write(3); + /// // Deferred initialization: + /// let data = Arc::get_mut(&mut values).unwrap(); + /// data[0].write(1); + /// data[1].write(2); + /// data[2].write(3); /// - /// values.assume_init() - /// }; + /// let values = unsafe { values.assume_init() }; /// /// assert_eq!(*values, [1, 2, 3]) /// ``` @@ -730,12 +725,10 @@ impl Arc> { /// /// let mut five = Arc::::new_uninit(); /// - /// let five = unsafe { - /// // Deferred initialization: - /// Arc::get_mut_unchecked(&mut five).as_mut_ptr().write(5); + /// // Deferred initialization: + /// Arc::get_mut(&mut five).unwrap().write(5); /// - /// five.assume_init() - /// }; + /// let five = unsafe { five.assume_init() }; /// /// assert_eq!(*five, 5) /// ``` @@ -770,14 +763,13 @@ impl Arc<[mem::MaybeUninit]> { /// /// let mut values = Arc::<[u32]>::new_uninit_slice(3); /// - /// let values = unsafe { - /// // Deferred initialization: - /// Arc::get_mut_unchecked(&mut values)[0].as_mut_ptr().write(1); - /// Arc::get_mut_unchecked(&mut values)[1].as_mut_ptr().write(2); - /// Arc::get_mut_unchecked(&mut values)[2].as_mut_ptr().write(3); + /// // Deferred initialization: + /// let data = Arc::get_mut(&mut values).unwrap(); + /// data[0].write(1); + /// data[1].write(2); + /// data[2].write(3); /// - /// values.assume_init() - /// }; + /// let values = unsafe { values.assume_init() }; /// /// assert_eq!(*values, [1, 2, 3]) /// ``` From fdf930ce0193d0b3fe1ad711a07061ba29f8072a Mon Sep 17 00:00:00 2001 From: Taylor Yu Date: Thu, 20 Jan 2022 15:37:44 -0600 Subject: [PATCH 18/21] delete `Stdin::split` forwarder --- library/std/src/io/stdio.rs | 25 +------------------------ 1 file changed, 1 insertion(+), 24 deletions(-) diff --git a/library/std/src/io/stdio.rs b/library/std/src/io/stdio.rs index c072f0cafe47b..3d6de20d86091 100644 --- a/library/std/src/io/stdio.rs +++ b/library/std/src/io/stdio.rs @@ -7,7 +7,7 @@ use crate::io::prelude::*; use crate::cell::{Cell, RefCell}; use crate::fmt; -use crate::io::{self, BufReader, IoSlice, IoSliceMut, LineWriter, Lines, Split}; +use crate::io::{self, BufReader, IoSlice, IoSliceMut, LineWriter, Lines}; use crate::lazy::SyncOnceCell; use crate::pin::Pin; use crate::sync::atomic::{AtomicBool, Ordering}; @@ -465,29 +465,6 @@ impl Stdin { pub fn lines(self) -> Lines> { self.into_locked().lines() } - - /// Consumes this handle and returns an iterator over input bytes, - /// split at the specified byte value. - /// - /// For detailed semantics of this method, see the documentation on - /// [`BufRead::split`]. - /// - /// # Examples - /// - /// ```no_run - /// #![feature(stdin_forwarders)] - /// use std::io; - /// - /// let splits = io::stdin().split(b'-'); - /// for split in splits { - /// println!("got a chunk: {}", String::from_utf8_lossy(&split.unwrap())); - /// } - /// ``` - #[must_use = "`self` will be dropped if the result is not used"] - #[unstable(feature = "stdin_forwarders", issue = "87096")] - pub fn split(self, byte: u8) -> Split> { - self.into_locked().split(byte) - } } #[stable(feature = "std_debug", since = "1.16.0")] From 9d178e5e8d7943da8f1b4b645911f300178f5070 Mon Sep 17 00:00:00 2001 From: Jacob Hoffman-Andrews Date: Thu, 20 Jan 2022 14:47:26 -0800 Subject: [PATCH 19/21] rustdoc: fix overflow-wrap for table layouts For all table layouts, set overflow-wrap: break-word. --- src/librustdoc/html/static/css/rustdoc.css | 30 +++++++++++--- src/test/rustdoc-gui/src/lib2/lib.rs | 39 ++++++++++++------- .../rustdoc-gui/type-declation-overflow.goml | 4 ++ 3 files changed, 54 insertions(+), 19 deletions(-) diff --git a/src/librustdoc/html/static/css/rustdoc.css b/src/librustdoc/html/static/css/rustdoc.css index 44a9a571fa1f8..a6bc719d6a1bb 100644 --- a/src/librustdoc/html/static/css/rustdoc.css +++ b/src/librustdoc/html/static/css/rustdoc.css @@ -675,7 +675,6 @@ nav.sub { margin: .5em 0; width: calc(100% - 2px); overflow-x: auto; - overflow-wrap: normal; display: block; } @@ -862,6 +861,31 @@ h2.small-section-header > .anchor { .block a.current.crate { font-weight: 500; } +/* In most contexts we use `overflow-wrap: anywhere` to ensure that we can wrap + as much as needed on mobile (see + src/test/rustdoc-gui/type-declaration-overflow.goml for an example of why + this matters). The `anywhere` value means: + + "Soft wrap opportunities introduced by the word break are considered when + calculating min-content intrinsic sizes." + + https://developer.mozilla.org/en-US/docs/Web/CSS/overflow-wrap#values + + For table layouts, that becomes a problem: the browser tries to make each + column as narrow as possible, and `overflow-wrap: anywhere` means it can do + so by breaking words - even if some other column could be shrunk without + breaking words! This shows up, for instance, in the `Structs` / `Modules` / + `Functions` (etcetera) sections of a module page, and when a docblock + contains a table. + + So, for table layouts, override the default with break-word, which does + _not_ affect min-content intrinsic sizes. +*/ +table, +.item-table { + overflow-wrap: break-word; +} + .item-table { display: table; } @@ -2040,10 +2064,6 @@ details.rustdoc-toggle[open] > summary.hideme::after { overflow-wrap: anywhere; } - .docblock table code { - overflow-wrap: normal; - } - .sub-container { flex-direction: column; } diff --git a/src/test/rustdoc-gui/src/lib2/lib.rs b/src/test/rustdoc-gui/src/lib2/lib.rs index 79354ec874507..73013c9778f64 100644 --- a/src/test/rustdoc-gui/src/lib2/lib.rs +++ b/src/test/rustdoc-gui/src/lib2/lib.rs @@ -39,7 +39,6 @@ impl Trait for Foo { const Y: u32 = 0; } - impl implementors::Whatever for Foo { type Foo = u32; } @@ -58,8 +57,10 @@ pub mod sub_mod { pub mod long_trait { use std::ops::DerefMut; - pub trait ALongNameBecauseItHelpsTestingTheCurrentProblem: DerefMut - + From + Send + Sync + AsRef + 'static {} + pub trait ALongNameBecauseItHelpsTestingTheCurrentProblem: + DerefMut + From + Send + Sync + AsRef + 'static + { + } } pub mod long_table { @@ -88,18 +89,28 @@ pub mod summary_table { } pub mod too_long { -pub type ReallyLongTypeNameLongLongLong = Option *const u8>; - -pub const ReallyLongTypeNameLongLongLongConstBecauseWhyNotAConstRightGigaGigaSupraLong: u32 = 0; - -pub struct SuperIncrediblyLongLongLongLongLongLongLongGigaGigaGigaMegaLongLongLongStructName { - pub a: u32, -} + pub type ReallyLongTypeNameLongLongLong = + Option *const u8>; + + pub const ReallyLongTypeNameLongLongLongConstBecauseWhyNotAConstRightGigaGigaSupraLong: u32 = 0; + + /// This also has a really long doccomment. Lorem ipsum dolor sit amet, + /// consectetur adipiscing elit. Suspendisse id nibh malesuada, hendrerit + /// massa vel, tincidunt est. Nulla interdum, sem ac efficitur ornare, arcu + /// nunc dignissim nibh, at rutrum diam augue ac mauris. Fusce tincidunt et + /// ligula sed viverra. Aenean sed facilisis dui, non volutpat felis. In + /// vitae est dui. Donec felis nibh, blandit at nibh eu, tempor suscipit + /// nisl. Vestibulum ornare porta libero, eu faucibus purus iaculis ut. Ut + /// quis tincidunt nunc, in mollis purus. Nulla sed interdum quam. Nunc + /// vitae cursus ex. + pub struct SuperIncrediblyLongLongLongLongLongLongLongGigaGigaGigaMegaLongLongLongStructName { + pub a: u32, + } -impl SuperIncrediblyLongLongLongLongLongLongLongGigaGigaGigaMegaLongLongLongStructName { - /// ``` - /// let x = SuperIncrediblyLongLongLongLongLongLongLongGigaGigaGigaMegaLongLongLongStructName { a: 0 }; - /// ``` + impl SuperIncrediblyLongLongLongLongLongLongLongGigaGigaGigaMegaLongLongLongStructName { + /// ``` + /// let x = SuperIncrediblyLongLongLongLongLongLongLongGigaGigaGigaMegaLongLongLongStructName { a: 0 }; + /// ``` pub fn foo(&self) {} } } diff --git a/src/test/rustdoc-gui/type-declation-overflow.goml b/src/test/rustdoc-gui/type-declation-overflow.goml index 21874f786f1ad..c35b38747dfaf 100644 --- a/src/test/rustdoc-gui/type-declation-overflow.goml +++ b/src/test/rustdoc-gui/type-declation-overflow.goml @@ -7,6 +7,10 @@ assert-property: ("body", {"scrollWidth": "1100"}) // However, since there is overflow in the type declaration, its scroll width is bigger. assert-property: (".item-decl pre", {"scrollWidth": "1324"}) +// In the table-ish view on the module index, the name should not be wrapped more than necessary. +goto: file://|DOC_PATH|/lib2/too_long/index.html +assert-property: (".item-table .struct", {"offsetWidth": "684"}) + // We now make the same check on type declaration... goto: file://|DOC_PATH|/lib2/too_long/type.ReallyLongTypeNameLongLongLong.html assert-property: ("body", {"scrollWidth": "1100"}) From b27d59d083a97e7253bcc8a040bc606ae0725fc4 Mon Sep 17 00:00:00 2001 From: Pietro Albini Date: Wed, 15 Dec 2021 12:50:06 +0100 Subject: [PATCH 20/21] replace paths in PathSet with a dedicated TaskPath struct --- src/bootstrap/builder.rs | 42 ++++++++++++++++++++++++++-------------- 1 file changed, 28 insertions(+), 14 deletions(-) diff --git a/src/bootstrap/builder.rs b/src/bootstrap/builder.rs index 6ccf8b1d5221c..c20177c92309d 100644 --- a/src/bootstrap/builder.rs +++ b/src/bootstrap/builder.rs @@ -107,6 +107,18 @@ struct StepDescription { name: &'static str, } +#[derive(Debug, Clone, PartialOrd, Ord, PartialEq, Eq)] +pub struct TaskPath { + pub path: PathBuf, + pub module: Option, +} + +impl TaskPath { + pub fn parse(path: impl Into) -> TaskPath { + TaskPath { path: path.into(), module: None } + } +} + /// Collection of paths used to match a task rule. #[derive(Debug, Clone, PartialOrd, Ord, PartialEq, Eq)] pub enum PathSet { @@ -115,14 +127,14 @@ pub enum PathSet { /// These are generally matched as a path suffix. For example, a /// command-line value of `libstd` will match if `src/libstd` is in the /// set. - Set(BTreeSet), + Set(BTreeSet), /// A "suite" of paths. /// /// These can match as a path suffix (like `Set`), or as a prefix. For /// example, a command-line value of `src/test/ui/abi/variadic-ffi.rs` /// will match `src/test/ui`. A command-line value of `ui` would also /// match `src/test/ui`. - Suite(PathBuf), + Suite(TaskPath), } impl PathSet { @@ -132,21 +144,23 @@ impl PathSet { fn one>(path: P) -> PathSet { let mut set = BTreeSet::new(); - set.insert(path.into()); + set.insert(TaskPath::parse(path)); PathSet::Set(set) } fn has(&self, needle: &Path) -> bool { match self { - PathSet::Set(set) => set.iter().any(|p| p.ends_with(needle)), - PathSet::Suite(suite) => suite.ends_with(needle), + PathSet::Set(set) => set.iter().any(|p| p.path.ends_with(needle)), + PathSet::Suite(suite) => suite.path.ends_with(needle), } } fn path(&self, builder: &Builder<'_>) -> PathBuf { match self { - PathSet::Set(set) => set.iter().next().unwrap_or(&builder.build.src).to_path_buf(), - PathSet::Suite(path) => PathBuf::from(path), + PathSet::Set(set) => { + set.iter().next().map(|p| &p.path).unwrap_or(&builder.build.src).clone() + } + PathSet::Suite(path) => path.path.clone(), } } } @@ -293,7 +307,7 @@ impl<'a> ShouldRun<'a> { let mut set = BTreeSet::new(); for krate in self.builder.in_tree_crates(name, None) { let path = krate.local_path(self.builder); - set.insert(path); + set.insert(TaskPath::parse(path)); } self.paths.insert(PathSet::Set(set)); self @@ -318,19 +332,19 @@ impl<'a> ShouldRun<'a> { // multiple aliases for the same job pub fn paths(mut self, paths: &[&str]) -> Self { - self.paths.insert(PathSet::Set(paths.iter().map(PathBuf::from).collect())); + self.paths.insert(PathSet::Set(paths.iter().map(|p| TaskPath::parse(p)).collect())); self } pub fn is_suite_path(&self, path: &Path) -> Option<&PathSet> { self.paths.iter().find(|pathset| match pathset { - PathSet::Suite(p) => path.starts_with(p), + PathSet::Suite(p) => path.starts_with(&p.path), PathSet::Set(_) => false, }) } pub fn suite_path(mut self, suite: &str) -> Self { - self.paths.insert(PathSet::Suite(PathBuf::from(suite))); + self.paths.insert(PathSet::Suite(TaskPath::parse(suite))); self } @@ -552,11 +566,11 @@ impl<'a> Builder<'a> { match pathset { PathSet::Set(set) => { for path in set { - add_path(&path); + add_path(&path.path); } } PathSet::Suite(path) => { - add_path(&path.join("...")); + add_path(&path.path.join("...")); } } } @@ -1648,7 +1662,7 @@ impl<'a> Builder<'a> { for path in &self.paths { if should_run.paths.iter().any(|s| s.has(path)) - && !desc.is_excluded(self, &PathSet::Suite(path.clone())) + && !desc.is_excluded(self, &PathSet::Suite(TaskPath::parse(path))) { return true; } From b3ad40532db231cd3ca55bc37047aa50fb1a1a71 Mon Sep 17 00:00:00 2001 From: Pietro Albini Date: Wed, 15 Dec 2021 12:51:26 +0100 Subject: [PATCH 21/21] allow excluding paths only from a single module x.py has support for excluding some steps from the invocation, but unfortunately that's not granular enough: some steps have the same name in different modules, and that prevents excluding only *some* of them. As a practical example, let's say you need to run everything in `./x.py test` except for the standard library tests, as those tests require IPv6 and need to be executed on a separate machine. Before this commit, if you were to just run this: ./x.py test --exclude library/std ...the execution would fail, as that would not only exclude running the tests for the standard library, it would also exclude generating its documentation (breaking linkchecker). This commit adds support for an optional module annotation in --exclude paths, allowing the user to choose which module to exclude from: ./x.py test --exclude test::library/std This maintains backward compatibility, but also allows for more ganular exclusion. More examples on how this works: | `--exclude` | Docs | Tests | | ------------------- | ------- | ------- | | `library/std` | Skipped | Skipped | | `doc::library/std` | Skipped | Run | | `test::library/std` | Run | Skipped | Note that the new behavior only works in the `--exclude` flag, and not in other x.py arguments or flags yet. --- src/bootstrap/builder.rs | 148 ++++++++++++++++++++++++++------- src/bootstrap/builder/tests.rs | 4 +- src/bootstrap/config.rs | 5 +- src/bootstrap/dist.rs | 4 +- src/bootstrap/doc.rs | 8 +- 5 files changed, 128 insertions(+), 41 deletions(-) diff --git a/src/bootstrap/builder.rs b/src/bootstrap/builder.rs index c20177c92309d..5cab3e8be1039 100644 --- a/src/bootstrap/builder.rs +++ b/src/bootstrap/builder.rs @@ -7,7 +7,7 @@ use std::fmt::Debug; use std::fs; use std::hash::Hash; use std::ops::Deref; -use std::path::{Path, PathBuf}; +use std::path::{Component, Path, PathBuf}; use std::process::Command; use std::time::{Duration, Instant}; @@ -105,17 +105,43 @@ struct StepDescription { should_run: fn(ShouldRun<'_>) -> ShouldRun<'_>, make_run: fn(RunConfig<'_>), name: &'static str, + kind: Kind, } -#[derive(Debug, Clone, PartialOrd, Ord, PartialEq, Eq)] +#[derive(Clone, PartialOrd, Ord, PartialEq, Eq)] pub struct TaskPath { pub path: PathBuf, - pub module: Option, + pub kind: Option, } impl TaskPath { pub fn parse(path: impl Into) -> TaskPath { - TaskPath { path: path.into(), module: None } + let mut kind = None; + let mut path = path.into(); + + let mut components = path.components(); + if let Some(Component::Normal(os_str)) = components.next() { + if let Some(str) = os_str.to_str() { + if let Some((found_kind, found_prefix)) = str.split_once("::") { + if found_kind.is_empty() { + panic!("empty kind in task path {}", path.display()); + } + kind = Some(Kind::parse(found_kind)); + path = Path::new(found_prefix).join(components.as_path()); + } + } + } + + TaskPath { path, kind } + } +} + +impl Debug for TaskPath { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + if let Some(kind) = &self.kind { + write!(f, "{}::", kind.as_str())?; + } + write!(f, "{}", self.path.display()) } } @@ -142,16 +168,24 @@ impl PathSet { PathSet::Set(BTreeSet::new()) } - fn one>(path: P) -> PathSet { + fn one>(path: P, kind: Kind) -> PathSet { let mut set = BTreeSet::new(); - set.insert(TaskPath::parse(path)); + set.insert(TaskPath { path: path.into(), kind: Some(kind.into()) }); PathSet::Set(set) } - fn has(&self, needle: &Path) -> bool { + fn has(&self, needle: &Path, module: Option) -> bool { + let check = |p: &TaskPath| { + if let (Some(p_kind), Some(kind)) = (&p.kind, module) { + p.path.ends_with(needle) && *p_kind == kind + } else { + p.path.ends_with(needle) + } + }; + match self { - PathSet::Set(set) => set.iter().any(|p| p.path.ends_with(needle)), - PathSet::Suite(suite) => suite.path.ends_with(needle), + PathSet::Set(set) => set.iter().any(check), + PathSet::Suite(suite) => check(suite), } } @@ -166,13 +200,14 @@ impl PathSet { } impl StepDescription { - fn from() -> StepDescription { + fn from(kind: Kind) -> StepDescription { StepDescription { default: S::DEFAULT, only_hosts: S::ONLY_HOSTS, should_run: S::should_run, make_run: S::make_run, name: std::any::type_name::(), + kind, } } @@ -191,7 +226,7 @@ impl StepDescription { } fn is_excluded(&self, builder: &Builder<'_>, pathset: &PathSet) -> bool { - if builder.config.exclude.iter().any(|e| pathset.has(e)) { + if builder.config.exclude.iter().any(|e| pathset.has(&e.path, e.kind)) { eprintln!("Skipping {:?} because it is excluded", pathset); return true; } @@ -206,8 +241,10 @@ impl StepDescription { } fn run(v: &[StepDescription], builder: &Builder<'_>, paths: &[PathBuf]) { - let should_runs = - v.iter().map(|desc| (desc.should_run)(ShouldRun::new(builder))).collect::>(); + let should_runs = v + .iter() + .map(|desc| (desc.should_run)(ShouldRun::new(builder, desc.kind))) + .collect::>(); // sanity checks on rules for (desc, should_run) in v.iter().zip(&should_runs) { @@ -240,7 +277,7 @@ impl StepDescription { if let Some(suite) = should_run.is_suite_path(path) { attempted_run = true; desc.maybe_run(builder, suite); - } else if let Some(pathset) = should_run.pathset_for_path(path) { + } else if let Some(pathset) = should_run.pathset_for_path(path, desc.kind) { attempted_run = true; desc.maybe_run(builder, pathset); } @@ -260,6 +297,8 @@ enum ReallyDefault<'a> { pub struct ShouldRun<'a> { pub builder: &'a Builder<'a>, + kind: Kind, + // use a BTreeSet to maintain sort order paths: BTreeSet, @@ -269,9 +308,10 @@ pub struct ShouldRun<'a> { } impl<'a> ShouldRun<'a> { - fn new(builder: &'a Builder<'_>) -> ShouldRun<'a> { + fn new(builder: &'a Builder<'_>, kind: Kind) -> ShouldRun<'a> { ShouldRun { builder, + kind, paths: BTreeSet::new(), is_really_default: ReallyDefault::Bool(true), // by default no additional conditions } @@ -307,7 +347,7 @@ impl<'a> ShouldRun<'a> { let mut set = BTreeSet::new(); for krate in self.builder.in_tree_crates(name, None) { let path = krate.local_path(self.builder); - set.insert(TaskPath::parse(path)); + set.insert(TaskPath { path, kind: Some(self.kind) }); } self.paths.insert(PathSet::Set(set)); self @@ -320,7 +360,7 @@ impl<'a> ShouldRun<'a> { pub fn krate(mut self, name: &str) -> Self { for krate in self.builder.in_tree_crates(name, None) { let path = krate.local_path(self.builder); - self.paths.insert(PathSet::one(path)); + self.paths.insert(PathSet::one(path, self.kind)); } self } @@ -332,7 +372,12 @@ impl<'a> ShouldRun<'a> { // multiple aliases for the same job pub fn paths(mut self, paths: &[&str]) -> Self { - self.paths.insert(PathSet::Set(paths.iter().map(|p| TaskPath::parse(p)).collect())); + self.paths.insert(PathSet::Set( + paths + .iter() + .map(|p| TaskPath { path: p.into(), kind: Some(self.kind.into()) }) + .collect(), + )); self } @@ -344,7 +389,8 @@ impl<'a> ShouldRun<'a> { } pub fn suite_path(mut self, suite: &str) -> Self { - self.paths.insert(PathSet::Suite(TaskPath::parse(suite))); + self.paths + .insert(PathSet::Suite(TaskPath { path: suite.into(), kind: Some(self.kind.into()) })); self } @@ -354,12 +400,12 @@ impl<'a> ShouldRun<'a> { self } - fn pathset_for_path(&self, path: &Path) -> Option<&PathSet> { - self.paths.iter().find(|pathset| pathset.has(path)) + fn pathset_for_path(&self, path: &Path, kind: Kind) -> Option<&PathSet> { + self.paths.iter().find(|pathset| pathset.has(path, Some(kind))) } } -#[derive(Copy, Clone, PartialEq, Eq, Debug)] +#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Debug)] pub enum Kind { Build, Check, @@ -373,11 +419,44 @@ pub enum Kind { Run, } +impl Kind { + fn parse(string: &str) -> Kind { + match string { + "build" => Kind::Build, + "check" => Kind::Check, + "clippy" => Kind::Clippy, + "fix" => Kind::Fix, + "test" => Kind::Test, + "bench" => Kind::Bench, + "dist" => Kind::Dist, + "doc" => Kind::Doc, + "install" => Kind::Install, + "run" => Kind::Run, + other => panic!("unknown kind: {}", other), + } + } + + fn as_str(&self) -> &'static str { + match self { + Kind::Build => "build", + Kind::Check => "check", + Kind::Clippy => "clippy", + Kind::Fix => "fix", + Kind::Test => "test", + Kind::Bench => "bench", + Kind::Dist => "dist", + Kind::Doc => "doc", + Kind::Install => "install", + Kind::Run => "run", + } + } +} + impl<'a> Builder<'a> { fn get_step_descriptions(kind: Kind) -> Vec { macro_rules! describe { ($($rule:ty),+ $(,)?) => {{ - vec![$(StepDescription::from::<$rule>()),+] + vec![$(StepDescription::from::<$rule>(kind)),+] }}; } match kind { @@ -554,8 +633,11 @@ impl<'a> Builder<'a> { let builder = Self::new_internal(build, kind, vec![]); let builder = &builder; - let mut should_run = ShouldRun::new(builder); + // The "build" kind here is just a placeholder, it will be replaced with something else in + // the following statement. + let mut should_run = ShouldRun::new(builder, Kind::Build); for desc in Builder::get_step_descriptions(builder.kind) { + should_run.kind = desc.kind; should_run = (desc.should_run)(should_run); } let mut help = String::from("Available paths:\n"); @@ -1640,9 +1722,10 @@ impl<'a> Builder<'a> { pub(crate) fn ensure_if_default>>( &'a self, step: S, + kind: Kind, ) -> S::Output { - let desc = StepDescription::from::(); - let should_run = (desc.should_run)(ShouldRun::new(self)); + let desc = StepDescription::from::(kind); + let should_run = (desc.should_run)(ShouldRun::new(self, desc.kind)); // Avoid running steps contained in --exclude for pathset in &should_run.paths { @@ -1656,13 +1739,16 @@ impl<'a> Builder<'a> { } /// Checks if any of the "should_run" paths is in the `Builder` paths. - pub(crate) fn was_invoked_explicitly(&'a self) -> bool { - let desc = StepDescription::from::(); - let should_run = (desc.should_run)(ShouldRun::new(self)); + pub(crate) fn was_invoked_explicitly(&'a self, kind: Kind) -> bool { + let desc = StepDescription::from::(kind); + let should_run = (desc.should_run)(ShouldRun::new(self, desc.kind)); for path in &self.paths { - if should_run.paths.iter().any(|s| s.has(path)) - && !desc.is_excluded(self, &PathSet::Suite(TaskPath::parse(path))) + if should_run.paths.iter().any(|s| s.has(path, Some(desc.kind))) + && !desc.is_excluded( + self, + &PathSet::Suite(TaskPath { path: path.clone(), kind: Some(desc.kind.into()) }), + ) { return true; } diff --git a/src/bootstrap/builder/tests.rs b/src/bootstrap/builder/tests.rs index bb3ea04d4ace9..bc71034496968 100644 --- a/src/bootstrap/builder/tests.rs +++ b/src/bootstrap/builder/tests.rs @@ -499,7 +499,7 @@ mod dist { let host = TargetSelection::from_user("A"); builder.run_step_descriptions( - &[StepDescription::from::()], + &[StepDescription::from::(Kind::Test)], &["library/std".into()], ); @@ -520,7 +520,7 @@ mod dist { #[test] fn test_exclude() { let mut config = configure(&["A"], &["A"]); - config.exclude = vec!["src/tools/tidy".into()]; + config.exclude = vec![TaskPath::parse("src/tools/tidy")]; config.cmd = Subcommand::Test { paths: Vec::new(), test_args: Vec::new(), diff --git a/src/bootstrap/config.rs b/src/bootstrap/config.rs index 5af9248583cae..683cfc630e771 100644 --- a/src/bootstrap/config.rs +++ b/src/bootstrap/config.rs @@ -12,6 +12,7 @@ use std::fs; use std::path::{Path, PathBuf}; use std::str::FromStr; +use crate::builder::TaskPath; use crate::cache::{Interned, INTERNER}; use crate::channel::GitInfo; pub use crate::flags::Subcommand; @@ -62,7 +63,7 @@ pub struct Config { pub sanitizers: bool, pub profiler: bool, pub ignore_git: bool, - pub exclude: Vec, + pub exclude: Vec, pub include_default_paths: bool, pub rustc_error_format: Option, pub json_output: bool, @@ -635,7 +636,7 @@ impl Config { let flags = Flags::parse(&args); let mut config = Config::default_opts(); - config.exclude = flags.exclude; + config.exclude = flags.exclude.into_iter().map(|path| TaskPath::parse(path)).collect(); config.include_default_paths = flags.include_default_paths; config.rustc_error_format = flags.rustc_error_format; config.json_output = flags.json_output; diff --git a/src/bootstrap/dist.rs b/src/bootstrap/dist.rs index a46a4e63714c2..66b63cd1278c5 100644 --- a/src/bootstrap/dist.rs +++ b/src/bootstrap/dist.rs @@ -16,7 +16,7 @@ use std::process::Command; use build_helper::{output, t}; -use crate::builder::{Builder, RunConfig, ShouldRun, Step}; +use crate::builder::{Builder, Kind, RunConfig, ShouldRun, Step}; use crate::cache::{Interned, INTERNER}; use crate::compile; use crate::config::TargetSelection; @@ -1368,7 +1368,7 @@ impl Step for Extended { let mut built_tools = HashSet::new(); macro_rules! add_component { ($name:expr => $step:expr) => { - if let Some(tarball) = builder.ensure_if_default($step) { + if let Some(tarball) = builder.ensure_if_default($step, Kind::Dist) { tarballs.push(tarball); built_tools.insert($name); } diff --git a/src/bootstrap/doc.rs b/src/bootstrap/doc.rs index f0f31c447bda4..23b5ddcd47a0e 100644 --- a/src/bootstrap/doc.rs +++ b/src/bootstrap/doc.rs @@ -15,7 +15,7 @@ use std::path::{Path, PathBuf}; use crate::Mode; use build_helper::{t, up_to_date}; -use crate::builder::{Builder, Compiler, RunConfig, ShouldRun, Step}; +use crate::builder::{Builder, Compiler, Kind, RunConfig, ShouldRun, Step}; use crate::cache::{Interned, INTERNER}; use crate::compile; use crate::config::{Config, TargetSelection}; @@ -240,7 +240,7 @@ impl Step for TheBook { invoke_rustdoc(builder, compiler, target, path); } - if builder.was_invoked_explicitly::() { + if builder.was_invoked_explicitly::(Kind::Doc) { let out = builder.doc_out(target); let index = out.join("book").join("index.html"); open(builder, &index); @@ -400,7 +400,7 @@ impl Step for Standalone { // We open doc/index.html as the default if invoked as `x.py doc --open` // with no particular explicit doc requested (e.g. library/core). - if builder.paths.is_empty() || builder.was_invoked_explicitly::() { + if builder.paths.is_empty() || builder.was_invoked_explicitly::(Kind::Doc) { let index = out.join("index.html"); open(builder, &index); } @@ -902,7 +902,7 @@ impl Step for RustcBook { name: INTERNER.intern_str("rustc"), src: INTERNER.intern_path(out_base), }); - if builder.was_invoked_explicitly::() { + if builder.was_invoked_explicitly::(Kind::Doc) { let out = builder.doc_out(self.target); let index = out.join("rustc").join("index.html"); open(builder, &index);