From 82684ad30a0929afba9463b89232730a9c6dadf4 Mon Sep 17 00:00:00 2001 From: Josh White Date: Wed, 5 Feb 2020 06:28:31 -0500 Subject: [PATCH 01/18] Added long error description & modifed error_codes.rs --- src/librustc_error_codes/error_codes.rs | 2 +- src/librustc_error_codes/error_codes/E0637.md | 22 +++++++++++++++++++ 2 files changed, 23 insertions(+), 1 deletion(-) create mode 100644 src/librustc_error_codes/error_codes/E0637.md diff --git a/src/librustc_error_codes/error_codes.rs b/src/librustc_error_codes/error_codes.rs index c3d9ed088981d..ba43b29538d50 100644 --- a/src/librustc_error_codes/error_codes.rs +++ b/src/librustc_error_codes/error_codes.rs @@ -353,6 +353,7 @@ E0631: include_str!("./error_codes/E0631.md"), E0633: include_str!("./error_codes/E0633.md"), E0635: include_str!("./error_codes/E0635.md"), E0636: include_str!("./error_codes/E0636.md"), +E0637: include_str!("./error_codes/E0637.md"), E0638: include_str!("./error_codes/E0638.md"), E0639: include_str!("./error_codes/E0639.md"), E0641: include_str!("./error_codes/E0641.md"), @@ -584,7 +585,6 @@ E0746: include_str!("./error_codes/E0746.md"), E0632, // cannot provide explicit generic arguments when `impl Trait` is // used in argument position E0634, // type has conflicting packed representaton hints - E0637, // "'_" is not a valid lifetime bound E0640, // infer outlives requirements // E0645, // trait aliases not finished E0657, // `impl Trait` can only capture lifetimes bound at the fn level diff --git a/src/librustc_error_codes/error_codes/E0637.md b/src/librustc_error_codes/error_codes/E0637.md new file mode 100644 index 0000000000000..4f139b0ec49d6 --- /dev/null +++ b/src/librustc_error_codes/error_codes/E0637.md @@ -0,0 +1,22 @@ +The underscore `_` character has been used as the identifier for a lifetime. + +Erroneous code example: +``` +fn some_function<'_>(x: &'_ str, y: &'_ str) -> &'_ str { + //Some code +} +``` + +Lifetimes are named with 'ident, where ident is the name of the +lifetime or loop. The `_` character, which represents the ignore pattern, +cannot be used because it is a reserved lifetime name. +To fix this, use a single lowercase letter as the +lifetime identifier, such as `'a`. For more information, see [The Rust Book](https://doc.rust-lang.org/stable/book/appendix-02-operators.html#non-operator-symbols). + +Corrected code example: +``` +fn some_function<'a>(x: &'a str, y: &'a str) -> &'a str { + //Some code +} +``` + From 4a1c6ce23547346757fa8b61207aea7eb6997aa3 Mon Sep 17 00:00:00 2001 From: Josh White Date: Wed, 5 Feb 2020 06:28:31 -0500 Subject: [PATCH 02/18] Added long error description & modifed error_codes.rs --- src/librustc_error_codes/error_codes.rs | 2 +- src/librustc_error_codes/error_codes/E0637.md | 22 +++++++++++++++++++ 2 files changed, 23 insertions(+), 1 deletion(-) create mode 100644 src/librustc_error_codes/error_codes/E0637.md diff --git a/src/librustc_error_codes/error_codes.rs b/src/librustc_error_codes/error_codes.rs index c3d9ed088981d..ba43b29538d50 100644 --- a/src/librustc_error_codes/error_codes.rs +++ b/src/librustc_error_codes/error_codes.rs @@ -353,6 +353,7 @@ E0631: include_str!("./error_codes/E0631.md"), E0633: include_str!("./error_codes/E0633.md"), E0635: include_str!("./error_codes/E0635.md"), E0636: include_str!("./error_codes/E0636.md"), +E0637: include_str!("./error_codes/E0637.md"), E0638: include_str!("./error_codes/E0638.md"), E0639: include_str!("./error_codes/E0639.md"), E0641: include_str!("./error_codes/E0641.md"), @@ -584,7 +585,6 @@ E0746: include_str!("./error_codes/E0746.md"), E0632, // cannot provide explicit generic arguments when `impl Trait` is // used in argument position E0634, // type has conflicting packed representaton hints - E0637, // "'_" is not a valid lifetime bound E0640, // infer outlives requirements // E0645, // trait aliases not finished E0657, // `impl Trait` can only capture lifetimes bound at the fn level diff --git a/src/librustc_error_codes/error_codes/E0637.md b/src/librustc_error_codes/error_codes/E0637.md new file mode 100644 index 0000000000000..4f139b0ec49d6 --- /dev/null +++ b/src/librustc_error_codes/error_codes/E0637.md @@ -0,0 +1,22 @@ +The underscore `_` character has been used as the identifier for a lifetime. + +Erroneous code example: +``` +fn some_function<'_>(x: &'_ str, y: &'_ str) -> &'_ str { + //Some code +} +``` + +Lifetimes are named with 'ident, where ident is the name of the +lifetime or loop. The `_` character, which represents the ignore pattern, +cannot be used because it is a reserved lifetime name. +To fix this, use a single lowercase letter as the +lifetime identifier, such as `'a`. For more information, see [The Rust Book](https://doc.rust-lang.org/stable/book/appendix-02-operators.html#non-operator-symbols). + +Corrected code example: +``` +fn some_function<'a>(x: &'a str, y: &'a str) -> &'a str { + //Some code +} +``` + From 201a262ac4a9cb61e4e94d8e841a973fee0edc86 Mon Sep 17 00:00:00 2001 From: Josh White Date: Thu, 6 Feb 2020 16:07:35 -0500 Subject: [PATCH 03/18] Revised error long description --- src/librustc_error_codes/error_codes/E0637.md | 28 +++++++++++++------ 1 file changed, 20 insertions(+), 8 deletions(-) diff --git a/src/librustc_error_codes/error_codes/E0637.md b/src/librustc_error_codes/error_codes/E0637.md index 4f139b0ec49d6..f5da357534e26 100644 --- a/src/librustc_error_codes/error_codes/E0637.md +++ b/src/librustc_error_codes/error_codes/E0637.md @@ -1,22 +1,34 @@ -The underscore `_` character has been used as the identifier for a lifetime. + +An underscore `_` character or a numeric literal `u8`, `i32`, `f64`, etc has +been used as the identifier for a lifetime. Erroneous code example: ``` -fn some_function<'_>(x: &'_ str, y: &'_ str) -> &'_ str { +fn some_function<'_>(string1: &'_ str, string2: &'_ str) -> &'_ str { + //Some code +} +``` +or Erroneous code example 2: +``` +fn some_function<'u8>(string1: &'u8 str, string2: &'u8 str) -> &'u8 str { //Some code } ``` -Lifetimes are named with 'ident, where ident is the name of the -lifetime or loop. The `_` character, which represents the ignore pattern, -cannot be used because it is a reserved lifetime name. -To fix this, use a single lowercase letter as the -lifetime identifier, such as `'a`. For more information, see [The Rust Book](https://doc.rust-lang.org/stable/book/appendix-02-operators.html#non-operator-symbols). +Lifetimes are named with `'ident`, where ident is the name of the lifetime or +loop. The `_` character, which represents the ignore pattern, cannot be used +as the identifier because it is a reserved lifetime name. Numeric literals are +also invalid lifetime identifiers and will cause this error to be thrown. To fix +this, use a series of lowercase letters as the lifetime identifier. Often a +single lowercase letter, such as `'a`, is sufficient. For more information, see +[the book][bk-no]. Corrected code example: ``` -fn some_function<'a>(x: &'a str, y: &'a str) -> &'a str { +fn some_function<'a>(string1: &'a str, string2: &'a str) -> &'a str { //Some code } ``` +[bk-no]: https://doc.rust-lang.org/book/appendix-02-operators.html#non-operator-symbols + From 1923586286dea1a0f8ece43056126fc2ecc89337 Mon Sep 17 00:00:00 2001 From: Josh White Date: Thu, 6 Feb 2020 16:54:24 -0500 Subject: [PATCH 04/18] Edited error description --- src/librustc_error_codes/error_codes/E0637.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/librustc_error_codes/error_codes/E0637.md b/src/librustc_error_codes/error_codes/E0637.md index f5da357534e26..44a365be7e0f7 100644 --- a/src/librustc_error_codes/error_codes/E0637.md +++ b/src/librustc_error_codes/error_codes/E0637.md @@ -2,15 +2,15 @@ An underscore `_` character or a numeric literal `u8`, `i32`, `f64`, etc has been used as the identifier for a lifetime. -Erroneous code example: +Erroneous code example 1: ``` -fn some_function<'_>(string1: &'_ str, string2: &'_ str) -> &'_ str { +fn some_function<'_>(str1: &'_ str, str2: &'_ str) -> &'_ str { //Some code } ``` or Erroneous code example 2: ``` -fn some_function<'u8>(string1: &'u8 str, string2: &'u8 str) -> &'u8 str { +fn some_function<'u8>(str1: &'u8 str, str2: &'u8 str) -> &'u8 str { //Some code } ``` @@ -25,7 +25,7 @@ single lowercase letter, such as `'a`, is sufficient. For more information, see Corrected code example: ``` -fn some_function<'a>(string1: &'a str, string2: &'a str) -> &'a str { +fn some_function<'a>(str1: &'a str, str2: &'a str) -> &'a str { //Some code } ``` From 78df44655aa8547baa25ee9ca49699ad82c7f76d Mon Sep 17 00:00:00 2001 From: Josh White Date: Thu, 6 Feb 2020 17:28:03 -0500 Subject: [PATCH 05/18] Tidied up the long error description --- src/librustc_error_codes/error_codes/E0637.md | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/librustc_error_codes/error_codes/E0637.md b/src/librustc_error_codes/error_codes/E0637.md index 44a365be7e0f7..978cf273c94d3 100644 --- a/src/librustc_error_codes/error_codes/E0637.md +++ b/src/librustc_error_codes/error_codes/E0637.md @@ -1,6 +1,5 @@ - An underscore `_` character or a numeric literal `u8`, `i32`, `f64`, etc has -been used as the identifier for a lifetime. +been used as the identifier for a lifetime. Erroneous code example 1: ``` @@ -29,6 +28,4 @@ fn some_function<'a>(str1: &'a str, str2: &'a str) -> &'a str { //Some code } ``` - [bk-no]: https://doc.rust-lang.org/book/appendix-02-operators.html#non-operator-symbols - From 8b77f8688e9436c6b35d5746e3bb79e20c67567d Mon Sep 17 00:00:00 2001 From: Josh White Date: Fri, 7 Feb 2020 12:44:31 -0500 Subject: [PATCH 06/18] performed --bless of 15 ui tests affected --- src/librustc_error_codes/error_codes/E0637.md | 69 ++++++++++++++----- .../const-param-elided-lifetime.stderr | 1 + src/test/ui/error-codes/E0637.stderr | 1 + ...rrect-explicit-lifetime-name-needed.stderr | 3 +- .../ui/underscore-lifetime/in-binder.stderr | 1 + .../underscore-lifetime-binders.stderr | 3 +- .../underscore-outlives-bounds.stderr | 1 + ...se-inherent-impl-ampersand.rust2015.stderr | 1 + ...se-inherent-impl-ampersand.rust2018.stderr | 1 + ...e-inherent-impl-underscore.rust2015.stderr | 1 + ...e-inherent-impl-underscore.rust2018.stderr | 1 + ...e-clause-trait-impl-region.rust2015.stderr | 1 + ...e-clause-trait-impl-region.rust2018.stderr | 1 + ...ause-trait-impl-underscore.rust2015.stderr | 1 + ...ause-trait-impl-underscore.rust2018.stderr | 1 + .../underscore-lifetime/where-clauses.stderr | 1 + 16 files changed, 67 insertions(+), 21 deletions(-) diff --git a/src/librustc_error_codes/error_codes/E0637.md b/src/librustc_error_codes/error_codes/E0637.md index 978cf273c94d3..ba81e42ce0850 100644 --- a/src/librustc_error_codes/error_codes/E0637.md +++ b/src/librustc_error_codes/error_codes/E0637.md @@ -1,31 +1,62 @@ -An underscore `_` character or a numeric literal `u8`, `i32`, `f64`, etc has -been used as the identifier for a lifetime. +An underscore `_` character has been used as the identifier for a lifetime, +or a const generic has been borrowed without an explicit lifetime. -Erroneous code example 1: +Erroneous example with an underscore: ``` -fn some_function<'_>(str1: &'_ str, str2: &'_ str) -> &'_ str { - //Some code -} +fn foo<'_>(str1: &'_ str, str2: &'_ str) -> &'_ str {} + // ^^ `'_` is a reserved lifetime name +``` +Lifetimes are named with `'ident`, where ident is the name of the lifetime or +loop. The `_` character, which represents the ignore pattern, cannot be used +as the identifier because it is a reserved lifetime name. To fix +this, use a lowercase letter, or a series of lowercase letters as the lifetime +identifier. Often a single lowercase letter, such as `'a`, is sufficient. For +more information, see +[the book][bk-no]. + +Corrected underscore example: +``` +fn <'a>(str1: &'a str, str2: &'a str) -> &'a str {} ``` -or Erroneous code example 2: + +Erroneous example with const generic: ``` -fn some_function<'u8>(str1: &'u8 str, str2: &'u8 str) -> &'u8 str { - //Some code +struct A; +//~^ ERROR `&` without an explicit lifetime name cannot be used here +trait B {} + +impl A { +//~^ ERROR `&` without an explicit lifetime name cannot be used here + fn foo(&self) {} + //~^ ERROR `&` without an explicit lifetime name cannot be used here +} + +impl B for A {} +//~^ ERROR `&` without an explicit lifetime name cannot be used here + +fn bar() {} +//~^ ERROR `&` without an explicit lifetime name cannot be used here } ``` -Lifetimes are named with `'ident`, where ident is the name of the lifetime or -loop. The `_` character, which represents the ignore pattern, cannot be used -as the identifier because it is a reserved lifetime name. Numeric literals are -also invalid lifetime identifiers and will cause this error to be thrown. To fix -this, use a series of lowercase letters as the lifetime identifier. Often a -single lowercase letter, such as `'a`, is sufficient. For more information, see -[the book][bk-no]. +Const generics cannot be borrowed without specifying a lifetime.The +compiler handles memory allocation of constants differently than that of +variables and it cannot infer the lifetime of the borrowed constant. +To fix this, explicitly specify a lifetime for the const generic. -Corrected code example: +Corrected const generic example: ``` -fn some_function<'a>(str1: &'a str, str2: &'a str) -> &'a str { - //Some code +struct A; + +trait B {} + +impl A { + fn foo(&self) {} +} + +impl B for A {} + +fn bar() {} } ``` [bk-no]: https://doc.rust-lang.org/book/appendix-02-operators.html#non-operator-symbols diff --git a/src/test/ui/const-generics/const-param-elided-lifetime.stderr b/src/test/ui/const-generics/const-param-elided-lifetime.stderr index 93133c507fe40..6841d1fdf360b 100644 --- a/src/test/ui/const-generics/const-param-elided-lifetime.stderr +++ b/src/test/ui/const-generics/const-param-elided-lifetime.stderr @@ -38,3 +38,4 @@ LL | #![feature(const_generics)] error: aborting due to 5 previous errors +For more information about this error, try `rustc --explain E0637`. diff --git a/src/test/ui/error-codes/E0637.stderr b/src/test/ui/error-codes/E0637.stderr index 9c3ca87ed7e64..d19ebfd15a52c 100644 --- a/src/test/ui/error-codes/E0637.stderr +++ b/src/test/ui/error-codes/E0637.stderr @@ -18,3 +18,4 @@ LL | impl<'a: '_> Bar<'a> { error: aborting due to 3 previous errors +For more information about this error, try `rustc --explain E0637`. diff --git a/src/test/ui/generics/issue-65285-incorrect-explicit-lifetime-name-needed.stderr b/src/test/ui/generics/issue-65285-incorrect-explicit-lifetime-name-needed.stderr index 8720288b53e58..9f410c0dbbbd2 100644 --- a/src/test/ui/generics/issue-65285-incorrect-explicit-lifetime-name-needed.stderr +++ b/src/test/ui/generics/issue-65285-incorrect-explicit-lifetime-name-needed.stderr @@ -18,4 +18,5 @@ LL | fn bar<'b, L: X<&'b Nested>>(){} error: aborting due to 3 previous errors -For more information about this error, try `rustc --explain E0106`. +Some errors have detailed explanations: E0106, E0637. +For more information about an error, try `rustc --explain E0106`. diff --git a/src/test/ui/underscore-lifetime/in-binder.stderr b/src/test/ui/underscore-lifetime/in-binder.stderr index 1b936dd9aec2f..fcd7eddb57605 100644 --- a/src/test/ui/underscore-lifetime/in-binder.stderr +++ b/src/test/ui/underscore-lifetime/in-binder.stderr @@ -36,3 +36,4 @@ LL | fn foo<'_>() { error: aborting due to 6 previous errors +For more information about this error, try `rustc --explain E0637`. diff --git a/src/test/ui/underscore-lifetime/underscore-lifetime-binders.stderr b/src/test/ui/underscore-lifetime/underscore-lifetime-binders.stderr index c7cda38e47691..ada4551baefff 100644 --- a/src/test/ui/underscore-lifetime/underscore-lifetime-binders.stderr +++ b/src/test/ui/underscore-lifetime/underscore-lifetime-binders.stderr @@ -38,4 +38,5 @@ LL | fn foo2<'a>(_: &'a u8, y: &'a u8) -> &'a u8 { y } error: aborting due to 5 previous errors -For more information about this error, try `rustc --explain E0106`. +Some errors have detailed explanations: E0106, E0637. +For more information about an error, try `rustc --explain E0106`. diff --git a/src/test/ui/underscore-lifetime/underscore-outlives-bounds.stderr b/src/test/ui/underscore-lifetime/underscore-outlives-bounds.stderr index 6fa74d4e31034..4b38a26f957f9 100644 --- a/src/test/ui/underscore-lifetime/underscore-outlives-bounds.stderr +++ b/src/test/ui/underscore-lifetime/underscore-outlives-bounds.stderr @@ -6,3 +6,4 @@ LL | impl<'b: '_> Foo<'b> for i32 {} error: aborting due to previous error +For more information about this error, try `rustc --explain E0637`. diff --git a/src/test/ui/underscore-lifetime/where-clause-inherent-impl-ampersand.rust2015.stderr b/src/test/ui/underscore-lifetime/where-clause-inherent-impl-ampersand.rust2015.stderr index eec8e4b846886..fe726cb49c737 100644 --- a/src/test/ui/underscore-lifetime/where-clause-inherent-impl-ampersand.rust2015.stderr +++ b/src/test/ui/underscore-lifetime/where-clause-inherent-impl-ampersand.rust2015.stderr @@ -6,3 +6,4 @@ LL | T: WithType<&u32> error: aborting due to previous error +For more information about this error, try `rustc --explain E0637`. diff --git a/src/test/ui/underscore-lifetime/where-clause-inherent-impl-ampersand.rust2018.stderr b/src/test/ui/underscore-lifetime/where-clause-inherent-impl-ampersand.rust2018.stderr index eec8e4b846886..fe726cb49c737 100644 --- a/src/test/ui/underscore-lifetime/where-clause-inherent-impl-ampersand.rust2018.stderr +++ b/src/test/ui/underscore-lifetime/where-clause-inherent-impl-ampersand.rust2018.stderr @@ -6,3 +6,4 @@ LL | T: WithType<&u32> error: aborting due to previous error +For more information about this error, try `rustc --explain E0637`. diff --git a/src/test/ui/underscore-lifetime/where-clause-inherent-impl-underscore.rust2015.stderr b/src/test/ui/underscore-lifetime/where-clause-inherent-impl-underscore.rust2015.stderr index d2c3e352045b6..95939fd6b7e03 100644 --- a/src/test/ui/underscore-lifetime/where-clause-inherent-impl-underscore.rust2015.stderr +++ b/src/test/ui/underscore-lifetime/where-clause-inherent-impl-underscore.rust2015.stderr @@ -6,3 +6,4 @@ LL | T: WithRegion<'_> error: aborting due to previous error +For more information about this error, try `rustc --explain E0637`. diff --git a/src/test/ui/underscore-lifetime/where-clause-inherent-impl-underscore.rust2018.stderr b/src/test/ui/underscore-lifetime/where-clause-inherent-impl-underscore.rust2018.stderr index d2c3e352045b6..95939fd6b7e03 100644 --- a/src/test/ui/underscore-lifetime/where-clause-inherent-impl-underscore.rust2018.stderr +++ b/src/test/ui/underscore-lifetime/where-clause-inherent-impl-underscore.rust2018.stderr @@ -6,3 +6,4 @@ LL | T: WithRegion<'_> error: aborting due to previous error +For more information about this error, try `rustc --explain E0637`. diff --git a/src/test/ui/underscore-lifetime/where-clause-trait-impl-region.rust2015.stderr b/src/test/ui/underscore-lifetime/where-clause-trait-impl-region.rust2015.stderr index 586b2b6aeaf28..fbd14de21078b 100644 --- a/src/test/ui/underscore-lifetime/where-clause-trait-impl-region.rust2015.stderr +++ b/src/test/ui/underscore-lifetime/where-clause-trait-impl-region.rust2015.stderr @@ -6,3 +6,4 @@ LL | T: WithType<&u32> error: aborting due to previous error +For more information about this error, try `rustc --explain E0637`. diff --git a/src/test/ui/underscore-lifetime/where-clause-trait-impl-region.rust2018.stderr b/src/test/ui/underscore-lifetime/where-clause-trait-impl-region.rust2018.stderr index 586b2b6aeaf28..fbd14de21078b 100644 --- a/src/test/ui/underscore-lifetime/where-clause-trait-impl-region.rust2018.stderr +++ b/src/test/ui/underscore-lifetime/where-clause-trait-impl-region.rust2018.stderr @@ -6,3 +6,4 @@ LL | T: WithType<&u32> error: aborting due to previous error +For more information about this error, try `rustc --explain E0637`. diff --git a/src/test/ui/underscore-lifetime/where-clause-trait-impl-underscore.rust2015.stderr b/src/test/ui/underscore-lifetime/where-clause-trait-impl-underscore.rust2015.stderr index faabf57a7df40..92caff0dcde99 100644 --- a/src/test/ui/underscore-lifetime/where-clause-trait-impl-underscore.rust2015.stderr +++ b/src/test/ui/underscore-lifetime/where-clause-trait-impl-underscore.rust2015.stderr @@ -6,3 +6,4 @@ LL | T: WithRegion<'_> error: aborting due to previous error +For more information about this error, try `rustc --explain E0637`. diff --git a/src/test/ui/underscore-lifetime/where-clause-trait-impl-underscore.rust2018.stderr b/src/test/ui/underscore-lifetime/where-clause-trait-impl-underscore.rust2018.stderr index faabf57a7df40..92caff0dcde99 100644 --- a/src/test/ui/underscore-lifetime/where-clause-trait-impl-underscore.rust2018.stderr +++ b/src/test/ui/underscore-lifetime/where-clause-trait-impl-underscore.rust2018.stderr @@ -6,3 +6,4 @@ LL | T: WithRegion<'_> error: aborting due to previous error +For more information about this error, try `rustc --explain E0637`. diff --git a/src/test/ui/underscore-lifetime/where-clauses.stderr b/src/test/ui/underscore-lifetime/where-clauses.stderr index 8674a925c110d..1a3ea4af7e12e 100644 --- a/src/test/ui/underscore-lifetime/where-clauses.stderr +++ b/src/test/ui/underscore-lifetime/where-clauses.stderr @@ -12,3 +12,4 @@ LL | impl Foo<'static> for Vec {} error: aborting due to 2 previous errors +For more information about this error, try `rustc --explain E0637`. From 92fc98c695d133ae28fb9d386d22efef57e2fc87 Mon Sep 17 00:00:00 2001 From: Josh White Date: Fri, 7 Feb 2020 23:40:16 -0500 Subject: [PATCH 07/18] Cleaned up long error description --- src/librustc_error_codes/error_codes/E0637.md | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/librustc_error_codes/error_codes/E0637.md b/src/librustc_error_codes/error_codes/E0637.md index ba81e42ce0850..13be503676790 100644 --- a/src/librustc_error_codes/error_codes/E0637.md +++ b/src/librustc_error_codes/error_codes/E0637.md @@ -11,8 +11,7 @@ loop. The `_` character, which represents the ignore pattern, cannot be used as the identifier because it is a reserved lifetime name. To fix this, use a lowercase letter, or a series of lowercase letters as the lifetime identifier. Often a single lowercase letter, such as `'a`, is sufficient. For -more information, see -[the book][bk-no]. +more information, see [the book][bk-no]. Corrected underscore example: ``` From 409146673c38ffeed1a9c93b9d1736be9de3cce4 Mon Sep 17 00:00:00 2001 From: Josh White Date: Sat, 8 Feb 2020 00:22:15 -0500 Subject: [PATCH 08/18] Removed trailing white spaces --- src/librustc_error_codes/error_codes/E0637.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/librustc_error_codes/error_codes/E0637.md b/src/librustc_error_codes/error_codes/E0637.md index 13be503676790..f2ec7fa0b49ef 100644 --- a/src/librustc_error_codes/error_codes/E0637.md +++ b/src/librustc_error_codes/error_codes/E0637.md @@ -24,7 +24,7 @@ struct A; //~^ ERROR `&` without an explicit lifetime name cannot be used here trait B {} -impl A { +impl A { //~^ ERROR `&` without an explicit lifetime name cannot be used here fn foo(&self) {} //~^ ERROR `&` without an explicit lifetime name cannot be used here @@ -38,7 +38,7 @@ fn bar() {} } ``` -Const generics cannot be borrowed without specifying a lifetime.The +Const generics cannot be borrowed without specifying a lifetime.The compiler handles memory allocation of constants differently than that of variables and it cannot infer the lifetime of the borrowed constant. To fix this, explicitly specify a lifetime for the const generic. From 58d0e67f504fb55ccbe1094265d029a10bc168c7 Mon Sep 17 00:00:00 2001 From: Josh White Date: Sat, 8 Feb 2020 06:18:42 -0500 Subject: [PATCH 09/18] Added compiler flags to example code, removed unexpected curly --- src/librustc_error_codes/error_codes/E0637.md | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/librustc_error_codes/error_codes/E0637.md b/src/librustc_error_codes/error_codes/E0637.md index f2ec7fa0b49ef..9b5db8fe733df 100644 --- a/src/librustc_error_codes/error_codes/E0637.md +++ b/src/librustc_error_codes/error_codes/E0637.md @@ -2,7 +2,7 @@ An underscore `_` character has been used as the identifier for a lifetime, or a const generic has been borrowed without an explicit lifetime. Erroneous example with an underscore: -``` +```compile_fail,E0106,E0637 fn foo<'_>(str1: &'_ str, str2: &'_ str) -> &'_ str {} // ^^ `'_` is a reserved lifetime name ``` @@ -19,7 +19,7 @@ fn <'a>(str1: &'a str, str2: &'a str) -> &'a str {} ``` Erroneous example with const generic: -``` +```compile_fail,E0637 struct A; //~^ ERROR `&` without an explicit lifetime name cannot be used here trait B {} @@ -35,7 +35,6 @@ impl B for A {} fn bar() {} //~^ ERROR `&` without an explicit lifetime name cannot be used here -} ``` Const generics cannot be borrowed without specifying a lifetime.The @@ -56,6 +55,5 @@ impl A { impl B for A {} fn bar() {} -} ``` [bk-no]: https://doc.rust-lang.org/book/appendix-02-operators.html#non-operator-symbols From a804d476a670e29f2ac55d97c72ae0bd456b3f84 Mon Sep 17 00:00:00 2001 From: Josh White Date: Sat, 8 Feb 2020 08:14:28 -0500 Subject: [PATCH 10/18] Corrected E0637.md based on test failure --- src/librustc_error_codes/error_codes/E0637.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/librustc_error_codes/error_codes/E0637.md b/src/librustc_error_codes/error_codes/E0637.md index 9b5db8fe733df..a79a2fda1a0e6 100644 --- a/src/librustc_error_codes/error_codes/E0637.md +++ b/src/librustc_error_codes/error_codes/E0637.md @@ -15,11 +15,11 @@ more information, see [the book][bk-no]. Corrected underscore example: ``` -fn <'a>(str1: &'a str, str2: &'a str) -> &'a str {} +fn foo<'a>(str1: &'a str, str2: &'a str) -> &'a str {} ``` Erroneous example with const generic: -```compile_fail,E0637 +```compile_fail,E0261,E0637,E0658 struct A; //~^ ERROR `&` without an explicit lifetime name cannot be used here trait B {} From 8c351182de955b3dea73681a1e3b3eb6afb0edca Mon Sep 17 00:00:00 2001 From: Josh White Date: Sat, 8 Feb 2020 14:24:35 -0500 Subject: [PATCH 11/18] Corrected E0637.md based on test failures --- src/librustc_error_codes/error_codes/E0637.md | 73 ++++++------------- 1 file changed, 23 insertions(+), 50 deletions(-) diff --git a/src/librustc_error_codes/error_codes/E0637.md b/src/librustc_error_codes/error_codes/E0637.md index a79a2fda1a0e6..f21b1749ec735 100644 --- a/src/librustc_error_codes/error_codes/E0637.md +++ b/src/librustc_error_codes/error_codes/E0637.md @@ -1,59 +1,32 @@ -An underscore `_` character has been used as the identifier for a lifetime, -or a const generic has been borrowed without an explicit lifetime. +An underscore `_` character has been used as the identifier for a lifetime. -Erroneous example with an underscore: +Erroneous example: ```compile_fail,E0106,E0637 -fn foo<'_>(str1: &'_ str, str2: &'_ str) -> &'_ str {} - // ^^ `'_` is a reserved lifetime name -``` -Lifetimes are named with `'ident`, where ident is the name of the lifetime or -loop. The `_` character, which represents the ignore pattern, cannot be used -as the identifier because it is a reserved lifetime name. To fix -this, use a lowercase letter, or a series of lowercase letters as the lifetime -identifier. Often a single lowercase letter, such as `'a`, is sufficient. For -more information, see [the book][bk-no]. - -Corrected underscore example: -``` -fn foo<'a>(str1: &'a str, str2: &'a str) -> &'a str {} -``` - -Erroneous example with const generic: -```compile_fail,E0261,E0637,E0658 -struct A; -//~^ ERROR `&` without an explicit lifetime name cannot be used here -trait B {} - -impl A { -//~^ ERROR `&` without an explicit lifetime name cannot be used here - fn foo(&self) {} - //~^ ERROR `&` without an explicit lifetime name cannot be used here +fn longest<'_>(str1: &'_ str, str2: &'_ str) -> &'_ str { + //^^ `'_` is a reserved lifetime name + if str1.len() > str2.len() { + str1 + } else { + str2 + } } - -impl B for A {} -//~^ ERROR `&` without an explicit lifetime name cannot be used here - -fn bar() {} -//~^ ERROR `&` without an explicit lifetime name cannot be used here ``` +`'_`, cannot be used as a lifetime identifier because it is a reserved for the +anonymous lifetime. To fix this, use a lowercase letter such as 'a, or a series +of lowercase letters such as `'foo`. For more information, see [the book][bk-no]. +For more information on using the anonymous lifetime in rust nightly, see [the +nightly book][bk-al]. -Const generics cannot be borrowed without specifying a lifetime.The -compiler handles memory allocation of constants differently than that of -variables and it cannot infer the lifetime of the borrowed constant. -To fix this, explicitly specify a lifetime for the const generic. - -Corrected const generic example: +Corrected example: ``` -struct A; - -trait B {} - -impl A { - fn foo(&self) {} +fn longest<'a>(str1: &'a str, str2: &'a str) -> &'a str { + if str1.len() > str2.len() { + str1 + } else { + str2 + } } - -impl B for A {} - -fn bar() {} ``` + [bk-no]: https://doc.rust-lang.org/book/appendix-02-operators.html#non-operator-symbols +[bk-al]: https://doc.rust-lang.org/nightly/edition-guide/rust-2018/ownership-and-lifetimes/the-anonymous-lifetime.html From 9d54bb28b30d26688f71cff672c68ed4fe00ab1e Mon Sep 17 00:00:00 2001 From: Josh White Date: Sat, 8 Feb 2020 16:26:09 -0500 Subject: [PATCH 12/18] Tidied up E0637.md --- src/librustc_error_codes/error_codes/E0637.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/librustc_error_codes/error_codes/E0637.md b/src/librustc_error_codes/error_codes/E0637.md index f21b1749ec735..e114d3d0f94ae 100644 --- a/src/librustc_error_codes/error_codes/E0637.md +++ b/src/librustc_error_codes/error_codes/E0637.md @@ -13,9 +13,9 @@ fn longest<'_>(str1: &'_ str, str2: &'_ str) -> &'_ str { ``` `'_`, cannot be used as a lifetime identifier because it is a reserved for the anonymous lifetime. To fix this, use a lowercase letter such as 'a, or a series -of lowercase letters such as `'foo`. For more information, see [the book][bk-no]. -For more information on using the anonymous lifetime in rust nightly, see [the -nightly book][bk-al]. +of lowercase letters such as `'foo`. For more information, see [the +book][bk-no]. For more information on using the anonymous lifetime in rust +nightly, see [the nightly book][bk-al]. Corrected example: ``` From a9212b8e9347f4ffa4280977fc1f849cb7a2525d Mon Sep 17 00:00:00 2001 From: Dylan MacKenzie Date: Sat, 8 Feb 2020 21:29:16 -0800 Subject: [PATCH 13/18] Make the ASCII ctype inherent methods const --- src/libcore/char/methods.rs | 30 ++++++++++++++++++++---------- src/libcore/lib.rs | 1 + src/libcore/num/mod.rs | 30 ++++++++++++++++++++---------- 3 files changed, 41 insertions(+), 20 deletions(-) diff --git a/src/libcore/char/methods.rs b/src/libcore/char/methods.rs index c341bb552a1ea..2b52c48cb9077 100644 --- a/src/libcore/char/methods.rs +++ b/src/libcore/char/methods.rs @@ -1072,8 +1072,9 @@ impl char { /// assert!(!esc.is_ascii_alphabetic()); /// ``` #[stable(feature = "ascii_ctype_on_intrinsics", since = "1.24.0")] + #[rustc_const_unstable(feature = "const_ascii_ctype_on_intrinsics", issue = "68983")] #[inline] - pub fn is_ascii_alphabetic(&self) -> bool { + pub const fn is_ascii_alphabetic(&self) -> bool { self.is_ascii() && (*self as u8).is_ascii_alphabetic() } @@ -1104,8 +1105,9 @@ impl char { /// assert!(!esc.is_ascii_uppercase()); /// ``` #[stable(feature = "ascii_ctype_on_intrinsics", since = "1.24.0")] + #[rustc_const_unstable(feature = "const_ascii_ctype_on_intrinsics", issue = "68983")] #[inline] - pub fn is_ascii_uppercase(&self) -> bool { + pub const fn is_ascii_uppercase(&self) -> bool { self.is_ascii() && (*self as u8).is_ascii_uppercase() } @@ -1136,8 +1138,9 @@ impl char { /// assert!(!esc.is_ascii_lowercase()); /// ``` #[stable(feature = "ascii_ctype_on_intrinsics", since = "1.24.0")] + #[rustc_const_unstable(feature = "const_ascii_ctype_on_intrinsics", issue = "68983")] #[inline] - pub fn is_ascii_lowercase(&self) -> bool { + pub const fn is_ascii_lowercase(&self) -> bool { self.is_ascii() && (*self as u8).is_ascii_lowercase() } @@ -1171,8 +1174,9 @@ impl char { /// assert!(!esc.is_ascii_alphanumeric()); /// ``` #[stable(feature = "ascii_ctype_on_intrinsics", since = "1.24.0")] + #[rustc_const_unstable(feature = "const_ascii_ctype_on_intrinsics", issue = "68983")] #[inline] - pub fn is_ascii_alphanumeric(&self) -> bool { + pub const fn is_ascii_alphanumeric(&self) -> bool { self.is_ascii() && (*self as u8).is_ascii_alphanumeric() } @@ -1203,8 +1207,9 @@ impl char { /// assert!(!esc.is_ascii_digit()); /// ``` #[stable(feature = "ascii_ctype_on_intrinsics", since = "1.24.0")] + #[rustc_const_unstable(feature = "const_ascii_ctype_on_intrinsics", issue = "68983")] #[inline] - pub fn is_ascii_digit(&self) -> bool { + pub const fn is_ascii_digit(&self) -> bool { self.is_ascii() && (*self as u8).is_ascii_digit() } @@ -1238,8 +1243,9 @@ impl char { /// assert!(!esc.is_ascii_hexdigit()); /// ``` #[stable(feature = "ascii_ctype_on_intrinsics", since = "1.24.0")] + #[rustc_const_unstable(feature = "const_ascii_ctype_on_intrinsics", issue = "68983")] #[inline] - pub fn is_ascii_hexdigit(&self) -> bool { + pub const fn is_ascii_hexdigit(&self) -> bool { self.is_ascii() && (*self as u8).is_ascii_hexdigit() } @@ -1274,8 +1280,9 @@ impl char { /// assert!(!esc.is_ascii_punctuation()); /// ``` #[stable(feature = "ascii_ctype_on_intrinsics", since = "1.24.0")] + #[rustc_const_unstable(feature = "const_ascii_ctype_on_intrinsics", issue = "68983")] #[inline] - pub fn is_ascii_punctuation(&self) -> bool { + pub const fn is_ascii_punctuation(&self) -> bool { self.is_ascii() && (*self as u8).is_ascii_punctuation() } @@ -1306,8 +1313,9 @@ impl char { /// assert!(!esc.is_ascii_graphic()); /// ``` #[stable(feature = "ascii_ctype_on_intrinsics", since = "1.24.0")] + #[rustc_const_unstable(feature = "const_ascii_ctype_on_intrinsics", issue = "68983")] #[inline] - pub fn is_ascii_graphic(&self) -> bool { + pub const fn is_ascii_graphic(&self) -> bool { self.is_ascii() && (*self as u8).is_ascii_graphic() } @@ -1355,8 +1363,9 @@ impl char { /// assert!(!esc.is_ascii_whitespace()); /// ``` #[stable(feature = "ascii_ctype_on_intrinsics", since = "1.24.0")] + #[rustc_const_unstable(feature = "const_ascii_ctype_on_intrinsics", issue = "68983")] #[inline] - pub fn is_ascii_whitespace(&self) -> bool { + pub const fn is_ascii_whitespace(&self) -> bool { self.is_ascii() && (*self as u8).is_ascii_whitespace() } @@ -1389,8 +1398,9 @@ impl char { /// assert!(esc.is_ascii_control()); /// ``` #[stable(feature = "ascii_ctype_on_intrinsics", since = "1.24.0")] + #[rustc_const_unstable(feature = "const_ascii_ctype_on_intrinsics", issue = "68983")] #[inline] - pub fn is_ascii_control(&self) -> bool { + pub const fn is_ascii_control(&self) -> bool { self.is_ascii() && (*self as u8).is_ascii_control() } } diff --git a/src/libcore/lib.rs b/src/libcore/lib.rs index 1fd70e1a1b049..176c36664a9b1 100644 --- a/src/libcore/lib.rs +++ b/src/libcore/lib.rs @@ -70,6 +70,7 @@ #![feature(bound_cloned)] #![feature(cfg_target_has_atomic)] #![feature(concat_idents)] +#![feature(const_ascii_ctype_on_intrinsics)] #![feature(const_alloc_layout)] #![feature(const_if_match)] #![feature(const_checked_int_methods)] diff --git a/src/libcore/num/mod.rs b/src/libcore/num/mod.rs index ed37b48b3e855..787834b7f4f2c 100644 --- a/src/libcore/num/mod.rs +++ b/src/libcore/num/mod.rs @@ -4448,8 +4448,9 @@ impl u8 { /// assert!(!esc.is_ascii_alphabetic()); /// ``` #[stable(feature = "ascii_ctype_on_intrinsics", since = "1.24.0")] + #[rustc_const_unstable(feature = "const_ascii_ctype_on_intrinsics", issue = "68983")] #[inline] - pub fn is_ascii_alphabetic(&self) -> bool { + pub const fn is_ascii_alphabetic(&self) -> bool { matches!(*self, b'A'..=b'Z' | b'a'..=b'z') } @@ -4480,8 +4481,9 @@ impl u8 { /// assert!(!esc.is_ascii_uppercase()); /// ``` #[stable(feature = "ascii_ctype_on_intrinsics", since = "1.24.0")] + #[rustc_const_unstable(feature = "const_ascii_ctype_on_intrinsics", issue = "68983")] #[inline] - pub fn is_ascii_uppercase(&self) -> bool { + pub const fn is_ascii_uppercase(&self) -> bool { matches!(*self, b'A'..=b'Z') } @@ -4512,8 +4514,9 @@ impl u8 { /// assert!(!esc.is_ascii_lowercase()); /// ``` #[stable(feature = "ascii_ctype_on_intrinsics", since = "1.24.0")] + #[rustc_const_unstable(feature = "const_ascii_ctype_on_intrinsics", issue = "68983")] #[inline] - pub fn is_ascii_lowercase(&self) -> bool { + pub const fn is_ascii_lowercase(&self) -> bool { matches!(*self, b'a'..=b'z') } @@ -4547,8 +4550,9 @@ impl u8 { /// assert!(!esc.is_ascii_alphanumeric()); /// ``` #[stable(feature = "ascii_ctype_on_intrinsics", since = "1.24.0")] + #[rustc_const_unstable(feature = "const_ascii_ctype_on_intrinsics", issue = "68983")] #[inline] - pub fn is_ascii_alphanumeric(&self) -> bool { + pub const fn is_ascii_alphanumeric(&self) -> bool { matches!(*self, b'0'..=b'9' | b'A'..=b'Z' | b'a'..=b'z') } @@ -4579,8 +4583,9 @@ impl u8 { /// assert!(!esc.is_ascii_digit()); /// ``` #[stable(feature = "ascii_ctype_on_intrinsics", since = "1.24.0")] + #[rustc_const_unstable(feature = "const_ascii_ctype_on_intrinsics", issue = "68983")] #[inline] - pub fn is_ascii_digit(&self) -> bool { + pub const fn is_ascii_digit(&self) -> bool { matches!(*self, b'0'..=b'9') } @@ -4614,8 +4619,9 @@ impl u8 { /// assert!(!esc.is_ascii_hexdigit()); /// ``` #[stable(feature = "ascii_ctype_on_intrinsics", since = "1.24.0")] + #[rustc_const_unstable(feature = "const_ascii_ctype_on_intrinsics", issue = "68983")] #[inline] - pub fn is_ascii_hexdigit(&self) -> bool { + pub const fn is_ascii_hexdigit(&self) -> bool { matches!(*self, b'0'..=b'9' | b'A'..=b'F' | b'a'..=b'f') } @@ -4650,8 +4656,9 @@ impl u8 { /// assert!(!esc.is_ascii_punctuation()); /// ``` #[stable(feature = "ascii_ctype_on_intrinsics", since = "1.24.0")] + #[rustc_const_unstable(feature = "const_ascii_ctype_on_intrinsics", issue = "68983")] #[inline] - pub fn is_ascii_punctuation(&self) -> bool { + pub const fn is_ascii_punctuation(&self) -> bool { matches!(*self, b'!'..=b'/' | b':'..=b'@' | b'['..=b'`' | b'{'..=b'~') } @@ -4682,8 +4689,9 @@ impl u8 { /// assert!(!esc.is_ascii_graphic()); /// ``` #[stable(feature = "ascii_ctype_on_intrinsics", since = "1.24.0")] + #[rustc_const_unstable(feature = "const_ascii_ctype_on_intrinsics", issue = "68983")] #[inline] - pub fn is_ascii_graphic(&self) -> bool { + pub const fn is_ascii_graphic(&self) -> bool { matches!(*self, b'!'..=b'~') } @@ -4731,8 +4739,9 @@ impl u8 { /// assert!(!esc.is_ascii_whitespace()); /// ``` #[stable(feature = "ascii_ctype_on_intrinsics", since = "1.24.0")] + #[rustc_const_unstable(feature = "const_ascii_ctype_on_intrinsics", issue = "68983")] #[inline] - pub fn is_ascii_whitespace(&self) -> bool { + pub const fn is_ascii_whitespace(&self) -> bool { matches!(*self, b'\t' | b'\n' | b'\x0C' | b'\r' | b' ') } @@ -4765,8 +4774,9 @@ impl u8 { /// assert!(esc.is_ascii_control()); /// ``` #[stable(feature = "ascii_ctype_on_intrinsics", since = "1.24.0")] + #[rustc_const_unstable(feature = "const_ascii_ctype_on_intrinsics", issue = "68983")] #[inline] - pub fn is_ascii_control(&self) -> bool { + pub const fn is_ascii_control(&self) -> bool { matches!(*self, b'\0'..=b'\x1F' | b'\x7F') } } From ea958422da4f90b7158e007d5c3226c41d0a5f57 Mon Sep 17 00:00:00 2001 From: Dylan MacKenzie Date: Sat, 8 Feb 2020 22:16:13 -0800 Subject: [PATCH 14/18] Test ASCII ctype methods in a const context --- src/test/ui/consts/ascii_ctype.rs | 55 +++++++++++++++++++++++++++++++ 1 file changed, 55 insertions(+) create mode 100644 src/test/ui/consts/ascii_ctype.rs diff --git a/src/test/ui/consts/ascii_ctype.rs b/src/test/ui/consts/ascii_ctype.rs new file mode 100644 index 0000000000000..25b270ee49cae --- /dev/null +++ b/src/test/ui/consts/ascii_ctype.rs @@ -0,0 +1,55 @@ +// run-pass + +#![feature(const_ascii_ctype_on_intrinsics)] + +macro_rules! suite { + ( $( $fn:ident => [$a:ident, $A:ident, $nine:ident, $dot:ident, $space:ident]; )* ) => { + $( + mod $fn { + const CHAR_A_LOWER: bool = 'a'.$fn(); + const CHAR_A_UPPER: bool = 'A'.$fn(); + const CHAR_NINE: bool = '9'.$fn(); + const CHAR_DOT: bool = '.'.$fn(); + const CHAR_SPACE: bool = ' '.$fn(); + + const U8_A_LOWER: bool = b'a'.$fn(); + const U8_A_UPPER: bool = b'A'.$fn(); + const U8_NINE: bool = b'9'.$fn(); + const U8_DOT: bool = b'.'.$fn(); + const U8_SPACE: bool = b' '.$fn(); + + pub fn run() { + assert_eq!(CHAR_A_LOWER, $a); + assert_eq!(CHAR_A_UPPER, $A); + assert_eq!(CHAR_NINE, $nine); + assert_eq!(CHAR_DOT, $dot); + assert_eq!(CHAR_SPACE, $space); + + assert_eq!(U8_A_LOWER, $a); + assert_eq!(U8_A_UPPER, $A); + assert_eq!(U8_NINE, $nine); + assert_eq!(U8_DOT, $dot); + assert_eq!(U8_SPACE, $space); + } + } + )* + + fn main() { + $( $fn::run(); )* + } + } +} + +suite! { + // 'a' 'A' '9' '.' ' ' + is_ascii_alphabetic => [true, true, false, false, false]; + is_ascii_uppercase => [false, true, false, false, false]; + is_ascii_lowercase => [true, false, false, false, false]; + is_ascii_alphanumeric => [true, true, true, false, false]; + is_ascii_digit => [false, false, true, false, false]; + is_ascii_hexdigit => [true, true, true, false, false]; + is_ascii_punctuation => [false, false, false, true, false]; + is_ascii_graphic => [true, true, true, true, false]; + is_ascii_whitespace => [false, false, false, false, true]; + is_ascii_control => [false, false, false, false, false]; +} From 371060b5988158fdaa3b7abd6167a28d95d74b38 Mon Sep 17 00:00:00 2001 From: David Renshaw Date: Sun, 9 Feb 2020 23:01:23 -0500 Subject: [PATCH 15/18] [parser] change an instance of span_bug() to struct_span_err() to avoid ICE --- src/librustc_parse/parser/ty.rs | 5 ++++- src/test/ui/parser/issue-68890.rs | 4 ++++ src/test/ui/parser/issue-68890.stderr | 20 ++++++++++++++++++++ 3 files changed, 28 insertions(+), 1 deletion(-) create mode 100644 src/test/ui/parser/issue-68890.rs create mode 100644 src/test/ui/parser/issue-68890.stderr diff --git a/src/librustc_parse/parser/ty.rs b/src/librustc_parse/parser/ty.rs index 990661bf6b5b9..a573a1ee69976 100644 --- a/src/librustc_parse/parser/ty.rs +++ b/src/librustc_parse/parser/ty.rs @@ -214,7 +214,10 @@ impl<'a> Parser<'a> { let path = match bounds.remove(0) { GenericBound::Trait(pt, ..) => pt.trait_ref.path, GenericBound::Outlives(..) => { - self.span_bug(ty.span, "unexpected lifetime bound") + return Err(self.struct_span_err( + ty.span, + "expected trait bound, not lifetime bound", + )); } }; self.parse_remaining_bounds(Vec::new(), path, lo, true) diff --git a/src/test/ui/parser/issue-68890.rs b/src/test/ui/parser/issue-68890.rs new file mode 100644 index 0000000000000..a7c5a5e13008a --- /dev/null +++ b/src/test/ui/parser/issue-68890.rs @@ -0,0 +1,4 @@ +enum e{A((?'a a+?+l))} +//~^ ERROR `?` may only modify trait bounds, not lifetime bounds +//~| ERROR expected one of `)`, `+`, or `,` +//~| ERROR expected trait bound, not lifetime bound diff --git a/src/test/ui/parser/issue-68890.stderr b/src/test/ui/parser/issue-68890.stderr new file mode 100644 index 0000000000000..9bb8761b67b5f --- /dev/null +++ b/src/test/ui/parser/issue-68890.stderr @@ -0,0 +1,20 @@ +error: `?` may only modify trait bounds, not lifetime bounds + --> $DIR/issue-68890.rs:1:11 + | +LL | enum e{A((?'a a+?+l))} + | ^ + +error: expected one of `)`, `+`, or `,`, found `a` + --> $DIR/issue-68890.rs:1:15 + | +LL | enum e{A((?'a a+?+l))} + | ^ expected one of `)`, `+`, or `,` + +error: expected trait bound, not lifetime bound + --> $DIR/issue-68890.rs:1:11 + | +LL | enum e{A((?'a a+?+l))} + | ^^^ + +error: aborting due to 3 previous errors + From ded629289a4040450396ea83ad9bddc459a9582c Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Sun, 9 Feb 2020 23:11:54 +0100 Subject: [PATCH 16/18] Clean up E0283 explanation --- src/librustc_error_codes/error_codes/E0283.md | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/librustc_error_codes/error_codes/E0283.md b/src/librustc_error_codes/error_codes/E0283.md index 075f8b2e3bb80..6885f9a486d3d 100644 --- a/src/librustc_error_codes/error_codes/E0283.md +++ b/src/librustc_error_codes/error_codes/E0283.md @@ -1,7 +1,6 @@ -This error occurs when the compiler doesn't have enough information -to unambiguously choose an implementation. +An implementation cannot be chosen unambiguously because of lack of information. -For example: +Erroneous code example: ```compile_fail,E0283 trait Generator { @@ -27,7 +26,9 @@ fn main() { } ``` -To resolve this error use the concrete type: +This error can be solved by adding type annotations that provide the missing +information to the compiler. In this case, the solution is to use a concrete +type: ``` trait Generator { From 37e7b461778fab0c9dbe287e4eb3b7096ad6356f Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Thu, 6 Feb 2020 17:53:03 +0100 Subject: [PATCH 17/18] clean up E0275 explanation --- src/librustc_error_codes/error_codes/E0275.md | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/librustc_error_codes/error_codes/E0275.md b/src/librustc_error_codes/error_codes/E0275.md index 836a9a95fa17b..2d12fcea4cafc 100644 --- a/src/librustc_error_codes/error_codes/E0275.md +++ b/src/librustc_error_codes/error_codes/E0275.md @@ -1,8 +1,6 @@ -This error occurs when there was a recursive trait requirement that overflowed -before it could be evaluated. Often this means that there is unbounded -recursion in resolving some type bounds. +An evaluation of a trait requirement overflowed. -For example, in the following code: +Erroneous code example: ```compile_fail,E0275 trait Foo {} @@ -12,6 +10,10 @@ struct Bar(T); impl Foo for T where Bar: Foo {} ``` +This error occurs when there was a recursive trait requirement that overflowed +before it could be evaluated. This often means that there is an unbounded +recursion in resolving some type bounds. + To determine if a `T` is `Foo`, we need to check if `Bar` is `Foo`. However, to do this check, we need to determine that `Bar>` is `Foo`. To determine this, we check if `Bar>>` is `Foo`, and so on. This is From 81dccb1a5c7b67c61cb7eb421150c671d6e1a7de Mon Sep 17 00:00:00 2001 From: Michael Woerister Date: Fri, 7 Feb 2020 15:01:23 +0100 Subject: [PATCH 18/18] self-profile: Support arguments for generic_activities. --- src/librustc/ty/query/on_disk_cache.rs | 6 +- src/librustc_codegen_llvm/back/lto.rs | 57 +++++++----- src/librustc_codegen_llvm/back/write.rs | 69 +++++++------- src/librustc_codegen_ssa/back/link.rs | 2 +- src/librustc_codegen_ssa/back/write.rs | 19 ++-- src/librustc_data_structures/profiling.rs | 107 +++++++++++++++------- src/librustc_lint/early.rs | 6 +- src/librustc_lint/late.rs | 21 ++--- 8 files changed, 169 insertions(+), 118 deletions(-) diff --git a/src/librustc/ty/query/on_disk_cache.rs b/src/librustc/ty/query/on_disk_cache.rs index a81fe33831c96..01f684dc65c30 100644 --- a/src/librustc/ty/query/on_disk_cache.rs +++ b/src/librustc/ty/query/on_disk_cache.rs @@ -1053,8 +1053,10 @@ where Q: super::config::QueryDescription<'tcx, Value: Encodable>, E: 'a + TyEncoder, { - let desc = &format!("encode_query_results_for_{}", ::std::any::type_name::()); - let _timer = tcx.sess.prof.extra_verbose_generic_activity(desc); + let _timer = tcx + .sess + .prof + .extra_verbose_generic_activity("encode_query_results_for", ::std::any::type_name::()); let shards = Q::query_cache(tcx).lock_shards(); assert!(shards.iter().all(|shard| shard.active.is_empty())); diff --git a/src/librustc_codegen_llvm/back/lto.rs b/src/librustc_codegen_llvm/back/lto.rs index b5895b53698dc..76a6ffbb1c5b2 100644 --- a/src/librustc_codegen_llvm/back/lto.rs +++ b/src/librustc_codegen_llvm/back/lto.rs @@ -110,23 +110,21 @@ fn prepare_lto( symbol_white_list.extend(exported_symbols[&cnum].iter().filter_map(symbol_filter)); } - let _timer = cgcx.prof.generic_activity("LLVM_lto_load_upstream_bitcode"); let archive = ArchiveRO::open(&path).expect("wanted an rlib"); let bytecodes = archive .iter() .filter_map(|child| child.ok().and_then(|c| c.name().map(|name| (name, c)))) .filter(|&(name, _)| name.ends_with(RLIB_BYTECODE_EXTENSION)); for (name, data) in bytecodes { + let _timer = + cgcx.prof.generic_activity_with_arg("LLVM_lto_load_upstream_bitcode", name); info!("adding bytecode {}", name); let bc_encoded = data.data(); - let (bc, id) = cgcx - .prof - .extra_verbose_generic_activity(&format!("decode {}", name)) - .run(|| match DecodedBytecode::new(bc_encoded) { - Ok(b) => Ok((b.bytecode(), b.identifier().to_string())), - Err(e) => Err(diag_handler.fatal(&e)), - })?; + let (bc, id) = match DecodedBytecode::new(bc_encoded) { + Ok(b) => Ok((b.bytecode(), b.identifier().to_string())), + Err(e) => Err(diag_handler.fatal(&e)), + }?; let bc = SerializedModule::FromRlib(bc); upstream_modules.push((bc, CString::new(id).unwrap())); } @@ -281,14 +279,14 @@ fn fat_lto( // save and persist everything with the original module. let mut linker = Linker::new(llmod); for (bc_decoded, name) in serialized_modules { - let _timer = cgcx.prof.generic_activity("LLVM_fat_lto_link_module"); + let _timer = cgcx + .prof + .generic_activity_with_arg("LLVM_fat_lto_link_module", format!("{:?}", name)); info!("linking {:?}", name); - cgcx.prof.extra_verbose_generic_activity(&format!("ll link {:?}", name)).run(|| { - let data = bc_decoded.data(); - linker.add(&data).map_err(|()| { - let msg = format!("failed to load bc of {:?}", name); - write::llvm_err(&diag_handler, &msg) - }) + let data = bc_decoded.data(); + linker.add(&data).map_err(|()| { + let msg = format!("failed to load bc of {:?}", name); + write::llvm_err(&diag_handler, &msg) })?; serialized_bitcode.push(bc_decoded); } @@ -577,6 +575,8 @@ pub(crate) fn run_pass_manager( config: &ModuleConfig, thin: bool, ) { + let _timer = cgcx.prof.extra_verbose_generic_activity("LLVM_lto_optimize", &module.name[..]); + // Now we have one massive module inside of llmod. Time to run the // LTO-specific optimization passes that LLVM provides. // @@ -634,9 +634,7 @@ pub(crate) fn run_pass_manager( llvm::LLVMRustAddPass(pm, pass.unwrap()); } - cgcx.prof - .extra_verbose_generic_activity("LTO_passes") - .run(|| llvm::LLVMRunPassManager(pm, module.module_llvm.llmod())); + llvm::LLVMRunPassManager(pm, module.module_llvm.llmod()); llvm::LLVMDisposePassManager(pm); } @@ -760,7 +758,9 @@ pub unsafe fn optimize_thin_module( // Like with "fat" LTO, get some better optimizations if landing pads // are disabled by removing all landing pads. if cgcx.no_landing_pads { - let _timer = cgcx.prof.generic_activity("LLVM_thin_lto_remove_landing_pads"); + let _timer = cgcx + .prof + .generic_activity_with_arg("LLVM_thin_lto_remove_landing_pads", thin_module.name()); llvm::LLVMRustMarkAllFunctionsNounwind(llmod); save_temp_bitcode(&cgcx, &module, "thin-lto-after-nounwind"); } @@ -774,7 +774,8 @@ pub unsafe fn optimize_thin_module( // You can find some more comments about these functions in the LLVM // bindings we've got (currently `PassWrapper.cpp`) { - let _timer = cgcx.prof.generic_activity("LLVM_thin_lto_rename"); + let _timer = + cgcx.prof.generic_activity_with_arg("LLVM_thin_lto_rename", thin_module.name()); if !llvm::LLVMRustPrepareThinLTORename(thin_module.shared.data.0, llmod) { let msg = "failed to prepare thin LTO module"; return Err(write::llvm_err(&diag_handler, msg)); @@ -783,7 +784,9 @@ pub unsafe fn optimize_thin_module( } { - let _timer = cgcx.prof.generic_activity("LLVM_thin_lto_resolve_weak"); + let _timer = cgcx + .prof + .generic_activity_with_arg("LLVM_thin_lto_resolve_weak", thin_module.name()); if !llvm::LLVMRustPrepareThinLTOResolveWeak(thin_module.shared.data.0, llmod) { let msg = "failed to prepare thin LTO module"; return Err(write::llvm_err(&diag_handler, msg)); @@ -792,7 +795,9 @@ pub unsafe fn optimize_thin_module( } { - let _timer = cgcx.prof.generic_activity("LLVM_thin_lto_internalize"); + let _timer = cgcx + .prof + .generic_activity_with_arg("LLVM_thin_lto_internalize", thin_module.name()); if !llvm::LLVMRustPrepareThinLTOInternalize(thin_module.shared.data.0, llmod) { let msg = "failed to prepare thin LTO module"; return Err(write::llvm_err(&diag_handler, msg)); @@ -801,7 +806,8 @@ pub unsafe fn optimize_thin_module( } { - let _timer = cgcx.prof.generic_activity("LLVM_thin_lto_import"); + let _timer = + cgcx.prof.generic_activity_with_arg("LLVM_thin_lto_import", thin_module.name()); if !llvm::LLVMRustPrepareThinLTOImport(thin_module.shared.data.0, llmod) { let msg = "failed to prepare thin LTO module"; return Err(write::llvm_err(&diag_handler, msg)); @@ -839,7 +845,9 @@ pub unsafe fn optimize_thin_module( // so it appears). Hopefully we can remove this once upstream bugs are // fixed in LLVM. { - let _timer = cgcx.prof.generic_activity("LLVM_thin_lto_patch_debuginfo"); + let _timer = cgcx + .prof + .generic_activity_with_arg("LLVM_thin_lto_patch_debuginfo", thin_module.name()); llvm::LLVMRustThinLTOPatchDICompileUnit(llmod, cu1); save_temp_bitcode(cgcx, &module, "thin-lto-after-patch"); } @@ -850,7 +858,6 @@ pub unsafe fn optimize_thin_module( // populate a thin-specific pass manager, which presumably LLVM treats a // little differently. { - let _timer = cgcx.prof.generic_activity("LLVM_thin_lto_optimize"); info!("running thin lto passes over {}", module.name); let config = cgcx.config(module.kind); run_pass_manager(cgcx, &module, config, true); diff --git a/src/librustc_codegen_llvm/back/write.rs b/src/librustc_codegen_llvm/back/write.rs index 4be7b84660d09..7dd57da90c3d6 100644 --- a/src/librustc_codegen_llvm/back/write.rs +++ b/src/librustc_codegen_llvm/back/write.rs @@ -310,7 +310,7 @@ pub(crate) unsafe fn optimize( module: &ModuleCodegen, config: &ModuleConfig, ) -> Result<(), FatalError> { - let _timer = cgcx.prof.generic_activity("LLVM_module_optimize"); + let _timer = cgcx.prof.generic_activity_with_arg("LLVM_module_optimize", &module.name[..]); let llmod = module.module_llvm.llmod(); let llcx = &*module.module_llvm.llcx; @@ -424,23 +424,17 @@ pub(crate) unsafe fn optimize( // Finally, run the actual optimization passes { - let _timer = cgcx.prof.generic_activity("LLVM_module_optimize_function_passes"); - let desc = &format!("llvm function passes [{}]", module_name.unwrap()); - let _timer = if config.time_module { - Some(cgcx.prof.extra_verbose_generic_activity(desc)) - } else { - None - }; + let _timer = cgcx.prof.extra_verbose_generic_activity( + "LLVM_module_optimize_function_passes", + &module.name[..], + ); llvm::LLVMRustRunFunctionPassManager(fpm, llmod); } { - let _timer = cgcx.prof.generic_activity("LLVM_module_optimize_module_passes"); - let desc = &format!("llvm module passes [{}]", module_name.unwrap()); - let _timer = if config.time_module { - Some(cgcx.prof.extra_verbose_generic_activity(desc)) - } else { - None - }; + let _timer = cgcx.prof.extra_verbose_generic_activity( + "LLVM_module_optimize_module_passes", + &module.name[..], + ); llvm::LLVMRunPassManager(mpm, llmod); } @@ -480,7 +474,7 @@ pub(crate) unsafe fn codegen( module: ModuleCodegen, config: &ModuleConfig, ) -> Result { - let _timer = cgcx.prof.generic_activity("LLVM_module_codegen"); + let _timer = cgcx.prof.generic_activity_with_arg("LLVM_module_codegen", &module.name[..]); { let llmod = module.module_llvm.llmod(); let llcx = &*module.module_llvm.llcx; @@ -533,12 +527,17 @@ pub(crate) unsafe fn codegen( let obj_out = cgcx.output_filenames.temp_path(OutputType::Object, module_name); if write_bc || config.emit_bc_compressed || config.embed_bitcode { - let _timer = cgcx.prof.generic_activity("LLVM_module_codegen_make_bitcode"); + let _timer = cgcx + .prof + .generic_activity_with_arg("LLVM_module_codegen_make_bitcode", &module.name[..]); let thin = ThinBuffer::new(llmod); let data = thin.data(); if write_bc { - let _timer = cgcx.prof.generic_activity("LLVM_module_codegen_emit_bitcode"); + let _timer = cgcx.prof.generic_activity_with_arg( + "LLVM_module_codegen_emit_bitcode", + &module.name[..], + ); if let Err(e) = fs::write(&bc_out, data) { let msg = format!("failed to write bytecode to {}: {}", bc_out.display(), e); diag_handler.err(&msg); @@ -546,13 +545,18 @@ pub(crate) unsafe fn codegen( } if config.embed_bitcode { - let _timer = cgcx.prof.generic_activity("LLVM_module_codegen_embed_bitcode"); + let _timer = cgcx.prof.generic_activity_with_arg( + "LLVM_module_codegen_embed_bitcode", + &module.name[..], + ); embed_bitcode(cgcx, llcx, llmod, Some(data)); } if config.emit_bc_compressed { - let _timer = - cgcx.prof.generic_activity("LLVM_module_codegen_emit_compressed_bitcode"); + let _timer = cgcx.prof.generic_activity_with_arg( + "LLVM_module_codegen_emit_compressed_bitcode", + &module.name[..], + ); let dst = bc_out.with_extension(RLIB_BYTECODE_EXTENSION); let data = bytecode::encode(&module.name, data); if let Err(e) = fs::write(&dst, data) { @@ -565,15 +569,10 @@ pub(crate) unsafe fn codegen( } { - let desc = &format!("codegen passes [{}]", module_name.unwrap()); - let _timer = if config.time_module { - Some(cgcx.prof.extra_verbose_generic_activity(desc)) - } else { - None - }; - if config.emit_ir { - let _timer = cgcx.prof.generic_activity("LLVM_module_codegen_emit_ir"); + let _timer = cgcx + .prof + .generic_activity_with_arg("LLVM_module_codegen_emit_ir", &module.name[..]); let out = cgcx.output_filenames.temp_path(OutputType::LlvmAssembly, module_name); let out_c = path_to_c_string(&out); @@ -618,7 +617,9 @@ pub(crate) unsafe fn codegen( } if config.emit_asm || asm_to_obj { - let _timer = cgcx.prof.generic_activity("LLVM_module_codegen_emit_asm"); + let _timer = cgcx + .prof + .generic_activity_with_arg("LLVM_module_codegen_emit_asm", &module.name[..]); let path = cgcx.output_filenames.temp_path(OutputType::Assembly, module_name); // We can't use the same module for asm and binary output, because that triggers @@ -638,7 +639,9 @@ pub(crate) unsafe fn codegen( } if write_obj { - let _timer = cgcx.prof.generic_activity("LLVM_module_codegen_emit_obj"); + let _timer = cgcx + .prof + .generic_activity_with_arg("LLVM_module_codegen_emit_obj", &module.name[..]); with_codegen(tm, llmod, config.no_builtins, |cpm| { write_output_file( diag_handler, @@ -650,7 +653,9 @@ pub(crate) unsafe fn codegen( ) })?; } else if asm_to_obj { - let _timer = cgcx.prof.generic_activity("LLVM_module_codegen_asm_to_obj"); + let _timer = cgcx + .prof + .generic_activity_with_arg("LLVM_module_codegen_asm_to_obj", &module.name[..]); let assembly = cgcx.output_filenames.temp_path(OutputType::Assembly, module_name); run_assembler(cgcx, diag_handler, &assembly, &obj_out); diff --git a/src/librustc_codegen_ssa/back/link.rs b/src/librustc_codegen_ssa/back/link.rs index 4f05aac089867..d3b8f7ea33fab 100644 --- a/src/librustc_codegen_ssa/back/link.rs +++ b/src/librustc_codegen_ssa/back/link.rs @@ -1648,7 +1648,7 @@ fn add_upstream_rust_crates<'a, B: ArchiveBuilder<'a>>( let name = cratepath.file_name().unwrap().to_str().unwrap(); let name = &name[3..name.len() - 5]; // chop off lib/.rlib - sess.prof.extra_verbose_generic_activity(&format!("altering {}.rlib", name)).run(|| { + sess.prof.generic_activity_with_arg("link_altering_rlib", name).run(|| { let mut archive = ::new(sess, &dst, Some(cratepath)); archive.update_symbols(); diff --git a/src/librustc_codegen_ssa/back/write.rs b/src/librustc_codegen_ssa/back/write.rs index 841827d15fef4..9905b3a56c0fa 100644 --- a/src/librustc_codegen_ssa/back/write.rs +++ b/src/librustc_codegen_ssa/back/write.rs @@ -21,6 +21,7 @@ use rustc::session::Session; use rustc::ty::TyCtxt; use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::profiling::SelfProfilerRef; +use rustc_data_structures::profiling::TimingGuard; use rustc_data_structures::profiling::VerboseTimingGuard; use rustc_data_structures::svh::Svh; use rustc_data_structures::sync::Lrc; @@ -691,11 +692,17 @@ impl WorkItem { } } - fn profiling_event_id(&self) -> &'static str { + fn start_profiling<'a>(&self, cgcx: &'a CodegenContext) -> TimingGuard<'a> { match *self { - WorkItem::Optimize(_) => "codegen_module_optimize", - WorkItem::CopyPostLtoArtifacts(_) => "codegen_copy_artifacts_from_incr_cache", - WorkItem::LTO(_) => "codegen_module_perform_lto", + WorkItem::Optimize(ref m) => { + cgcx.prof.generic_activity_with_arg("codegen_module_optimize", &m.name[..]) + } + WorkItem::CopyPostLtoArtifacts(ref m) => cgcx + .prof + .generic_activity_with_arg("codegen_copy_artifacts_from_incr_cache", &m.name[..]), + WorkItem::LTO(ref m) => { + cgcx.prof.generic_activity_with_arg("codegen_module_perform_lto", m.name()) + } } } } @@ -1520,7 +1527,7 @@ fn start_executing_work( llvm_start_time: &mut Option>, ) { if config.time_module && llvm_start_time.is_none() { - *llvm_start_time = Some(prof.extra_verbose_generic_activity("LLVM_passes")); + *llvm_start_time = Some(prof.extra_verbose_generic_activity("LLVM_passes", "crate")); } } } @@ -1575,7 +1582,7 @@ fn spawn_work(cgcx: CodegenContext, work: WorkItem // as a diagnostic was already sent off to the main thread - just // surface that there was an error in this worker. bomb.result = { - let _prof_timer = cgcx.prof.generic_activity(work.profiling_event_id()); + let _prof_timer = work.start_profiling(&cgcx); Some(execute_work_item(&cgcx, work)) }; }); diff --git a/src/librustc_data_structures/profiling.rs b/src/librustc_data_structures/profiling.rs index 90f74328a1d51..debda9f0a0a24 100644 --- a/src/librustc_data_structures/profiling.rs +++ b/src/librustc_data_structures/profiling.rs @@ -83,6 +83,9 @@ use crate::fx::FxHashMap; +use std::borrow::Borrow; +use std::collections::hash_map::Entry; +use std::convert::Into; use std::error::Error; use std::fs; use std::path::Path; @@ -123,11 +126,14 @@ bitflags::bitflags! { const INCR_CACHE_LOADS = 1 << 4; const QUERY_KEYS = 1 << 5; + const FUNCTION_ARGS = 1 << 6; const DEFAULT = Self::GENERIC_ACTIVITIES.bits | Self::QUERY_PROVIDERS.bits | Self::QUERY_BLOCKED.bits | Self::INCR_CACHE_LOADS.bits; + + const ARGS = Self::QUERY_KEYS.bits | Self::FUNCTION_ARGS.bits; } } @@ -142,6 +148,8 @@ const EVENT_FILTERS_BY_NAME: &[(&str, EventFilter)] = &[ ("query-blocked", EventFilter::QUERY_BLOCKED), ("incr-cache-load", EventFilter::INCR_CACHE_LOADS), ("query-keys", EventFilter::QUERY_KEYS), + ("function-args", EventFilter::FUNCTION_ARGS), + ("args", EventFilter::ARGS), ]; /// Something that uniquely identifies a query invocation. @@ -216,43 +224,68 @@ impl SelfProfilerRef { /// VerboseTimingGuard returned from this call is dropped. In addition to recording /// a measureme event, "verbose" generic activities also print a timing entry to /// stdout if the compiler is invoked with -Ztime or -Ztime-passes. - #[inline(always)] pub fn verbose_generic_activity<'a>( &'a self, - event_id: &'static str, + event_label: &'static str, ) -> VerboseTimingGuard<'a> { - VerboseTimingGuard::start( - event_id, - self.print_verbose_generic_activities, - self.generic_activity(event_id), - ) + let message = + if self.print_verbose_generic_activities { Some(event_label.to_owned()) } else { None }; + + VerboseTimingGuard::start(message, self.generic_activity(event_label)) } /// Start profiling a extra verbose generic activity. Profiling continues until the /// VerboseTimingGuard returned from this call is dropped. In addition to recording /// a measureme event, "extra verbose" generic activities also print a timing entry to /// stdout if the compiler is invoked with -Ztime-passes. - #[inline(always)] - pub fn extra_verbose_generic_activity<'a>( + pub fn extra_verbose_generic_activity<'a, A>( &'a self, - event_id: &'a str, - ) -> VerboseTimingGuard<'a> { - // FIXME: This does not yet emit a measureme event - // because callers encode arguments into `event_id`. - VerboseTimingGuard::start( - event_id, - self.print_extra_verbose_generic_activities, - TimingGuard::none(), - ) + event_label: &'static str, + event_arg: A, + ) -> VerboseTimingGuard<'a> + where + A: Borrow + Into, + { + let message = if self.print_extra_verbose_generic_activities { + Some(format!("{}({})", event_label, event_arg.borrow())) + } else { + None + }; + + VerboseTimingGuard::start(message, self.generic_activity_with_arg(event_label, event_arg)) + } + + /// Start profiling a generic activity. Profiling continues until the + /// TimingGuard returned from this call is dropped. + #[inline(always)] + pub fn generic_activity(&self, event_label: &'static str) -> TimingGuard<'_> { + self.exec(EventFilter::GENERIC_ACTIVITIES, |profiler| { + let event_label = profiler.get_or_alloc_cached_string(event_label); + let event_id = EventId::from_label(event_label); + TimingGuard::start(profiler, profiler.generic_activity_event_kind, event_id) + }) } /// Start profiling a generic activity. Profiling continues until the /// TimingGuard returned from this call is dropped. #[inline(always)] - pub fn generic_activity(&self, event_id: &'static str) -> TimingGuard<'_> { + pub fn generic_activity_with_arg( + &self, + event_label: &'static str, + event_arg: A, + ) -> TimingGuard<'_> + where + A: Borrow + Into, + { self.exec(EventFilter::GENERIC_ACTIVITIES, |profiler| { - let event_id = profiler.get_or_alloc_cached_string(event_id); - let event_id = EventId::from_label(event_id); + let builder = EventIdBuilder::new(&profiler.profiler); + let event_label = profiler.get_or_alloc_cached_string(event_label); + let event_id = if profiler.event_filter_mask.contains(EventFilter::FUNCTION_ARGS) { + let event_arg = profiler.get_or_alloc_cached_string(event_arg); + builder.from_label_and_arg(event_label, event_arg) + } else { + builder.from_label(event_label) + }; TimingGuard::start(profiler, profiler.generic_activity_event_kind, event_id) }) } @@ -337,7 +370,7 @@ pub struct SelfProfiler { profiler: Profiler, event_filter_mask: EventFilter, - string_cache: RwLock>, + string_cache: RwLock>, query_event_kind: StringId, generic_activity_event_kind: StringId, @@ -419,13 +452,16 @@ impl SelfProfiler { /// Gets a `StringId` for the given string. This method makes sure that /// any strings going through it will only be allocated once in the /// profiling data. - pub fn get_or_alloc_cached_string(&self, s: &'static str) -> StringId { + pub fn get_or_alloc_cached_string(&self, s: A) -> StringId + where + A: Borrow + Into, + { // Only acquire a read-lock first since we assume that the string is // already present in the common case. { let string_cache = self.string_cache.read(); - if let Some(&id) = string_cache.get(s) { + if let Some(&id) = string_cache.get(s.borrow()) { return id; } } @@ -433,7 +469,13 @@ impl SelfProfiler { let mut string_cache = self.string_cache.write(); // Check if the string has already been added in the small time window // between dropping the read lock and acquiring the write lock. - *string_cache.entry(s).or_insert_with(|| self.profiler.alloc_string(s)) + match string_cache.entry(s.into()) { + Entry::Occupied(e) => *e.get(), + Entry::Vacant(e) => { + let string_id = self.profiler.alloc_string(&e.key()[..]); + *e.insert(string_id) + } + } } pub fn map_query_invocation_id_to_string(&self, from: QueryInvocationId, to: StringId) { @@ -498,18 +540,13 @@ impl<'a> TimingGuard<'a> { #[must_use] pub struct VerboseTimingGuard<'a> { - event_id: &'a str, - start: Option, + start_and_message: Option<(Instant, String)>, _guard: TimingGuard<'a>, } impl<'a> VerboseTimingGuard<'a> { - pub fn start(event_id: &'a str, verbose: bool, _guard: TimingGuard<'a>) -> Self { - VerboseTimingGuard { - event_id, - _guard, - start: if unlikely!(verbose) { Some(Instant::now()) } else { None }, - } + pub fn start(message: Option, _guard: TimingGuard<'a>) -> Self { + VerboseTimingGuard { _guard, start_and_message: message.map(|msg| (Instant::now(), msg)) } } #[inline(always)] @@ -521,7 +558,9 @@ impl<'a> VerboseTimingGuard<'a> { impl Drop for VerboseTimingGuard<'_> { fn drop(&mut self) { - self.start.map(|start| print_time_passes_entry(true, self.event_id, start.elapsed())); + if let Some((start, ref message)) = self.start_and_message { + print_time_passes_entry(true, &message[..], start.elapsed()); + } } } diff --git a/src/librustc_lint/early.rs b/src/librustc_lint/early.rs index 542cbea0c954a..27781eb41d28d 100644 --- a/src/librustc_lint/early.rs +++ b/src/librustc_lint/early.rs @@ -342,10 +342,8 @@ pub fn check_ast_crate( } } else { for pass in &mut passes { - buffered = sess - .prof - .extra_verbose_generic_activity(&format!("running lint: {}", pass.name())) - .run(|| { + buffered = + sess.prof.extra_verbose_generic_activity("run_lint", pass.name()).run(|| { early_lint_crate( sess, lint_store, diff --git a/src/librustc_lint/late.rs b/src/librustc_lint/late.rs index 30a3788377508..b3d5cdf15c933 100644 --- a/src/librustc_lint/late.rs +++ b/src/librustc_lint/late.rs @@ -441,27 +441,20 @@ fn late_lint_crate<'tcx, T: for<'a> LateLintPass<'a, 'tcx>>(tcx: TyCtxt<'tcx>, b late_lint_pass_crate(tcx, builtin_lints); } else { for pass in &mut passes { - tcx.sess - .prof - .extra_verbose_generic_activity(&format!("running late lint: {}", pass.name())) - .run(|| { - late_lint_pass_crate(tcx, LateLintPassObjects { lints: slice::from_mut(pass) }); - }); + tcx.sess.prof.extra_verbose_generic_activity("run_late_lint", pass.name()).run(|| { + late_lint_pass_crate(tcx, LateLintPassObjects { lints: slice::from_mut(pass) }); + }); } let mut passes: Vec<_> = unerased_lint_store(tcx).late_module_passes.iter().map(|pass| (pass)()).collect(); for pass in &mut passes { - tcx.sess - .prof - .extra_verbose_generic_activity(&format!( - "running late module lint: {}", - pass.name() - )) - .run(|| { + tcx.sess.prof.extra_verbose_generic_activity("run_late_module_lint", pass.name()).run( + || { late_lint_pass_crate(tcx, LateLintPassObjects { lints: slice::from_mut(pass) }); - }); + }, + ); } } }