Auto merge of #97783 - matthiaskrgr:rollup-14t9htt, r=matthiaskrgr
Rollup of 7 pull requests Successful merges: - #90905 (Add empty impl blocks if they have documentation) - #97683 (Fail gracefully when encountering an HRTB in APIT. ) - #97721 (Do `suggest_await_before_try` with infer variables in self, and clean up binders) - #97752 (typo: `-Zcodegen-backend=llvm -Cpasses=list` should work now) - #97759 (Suggest adding `{}` for `'label: non_block_expr`) - #97764 (use strict provenance APIs) - #97765 (Restore a test that was intended to test `as` cast to ptr) Failed merges: r? `@ghost` `@rustbot` modify labels: rollup
This commit is contained in:
commit
e70c60d34b
23 changed files with 420 additions and 83 deletions
|
|
@ -94,6 +94,10 @@ There are a number of supported commands:
|
|||
in the specified file. The number of occurrences must match the given
|
||||
count.
|
||||
|
||||
* `@count PATH XPATH TEXT COUNT` checks for the occurrence of the given XPath
|
||||
with the given text in the specified file. The number of occurrences must
|
||||
match the given count.
|
||||
|
||||
* `@snapshot NAME PATH XPATH` creates a snapshot test named NAME.
|
||||
A snapshot test captures a subtree of the DOM, at the location
|
||||
determined by the XPath, and compares it to a pre-recorded value
|
||||
|
|
@ -382,9 +386,10 @@ def check_tree_attr(tree, path, attr, pat, regexp):
|
|||
return ret
|
||||
|
||||
|
||||
def check_tree_text(tree, path, pat, regexp):
|
||||
# Returns the number of occurences matching the regex (`regexp`) and the text (`pat`).
|
||||
def check_tree_text(tree, path, pat, regexp, stop_at_first):
|
||||
path = normalize_xpath(path)
|
||||
ret = False
|
||||
match_count = 0
|
||||
try:
|
||||
for e in tree.findall(path):
|
||||
try:
|
||||
|
|
@ -392,13 +397,14 @@ def check_tree_text(tree, path, pat, regexp):
|
|||
except KeyError:
|
||||
continue
|
||||
else:
|
||||
ret = check_string(value, pat, regexp)
|
||||
if ret:
|
||||
break
|
||||
if check_string(value, pat, regexp):
|
||||
match_count += 1
|
||||
if stop_at_first:
|
||||
break
|
||||
except Exception:
|
||||
print('Failed to get path "{}"'.format(path))
|
||||
raise
|
||||
return ret
|
||||
return match_count
|
||||
|
||||
|
||||
def get_tree_count(tree, path):
|
||||
|
|
@ -518,6 +524,19 @@ def print_err(lineno, context, err, message=None):
|
|||
stderr("\t{}".format(context))
|
||||
|
||||
|
||||
def get_nb_matching_elements(cache, c, regexp, stop_at_first):
|
||||
tree = cache.get_tree(c.args[0])
|
||||
pat, sep, attr = c.args[1].partition('/@')
|
||||
if sep: # attribute
|
||||
tree = cache.get_tree(c.args[0])
|
||||
return check_tree_attr(tree, pat, attr, c.args[2], False)
|
||||
else: # normalized text
|
||||
pat = c.args[1]
|
||||
if pat.endswith('/text()'):
|
||||
pat = pat[:-7]
|
||||
return check_tree_text(cache.get_tree(c.args[0]), pat, c.args[2], regexp, stop_at_first)
|
||||
|
||||
|
||||
ERR_COUNT = 0
|
||||
|
||||
|
||||
|
|
@ -538,16 +557,7 @@ def check_command(c, cache):
|
|||
ret = check_string(cache.get_file(c.args[0]), c.args[1], regexp)
|
||||
elif len(c.args) == 3: # @has/matches <path> <pat> <match> = XML tree test
|
||||
cerr = "`XPATH PATTERN` did not match"
|
||||
tree = cache.get_tree(c.args[0])
|
||||
pat, sep, attr = c.args[1].partition('/@')
|
||||
if sep: # attribute
|
||||
tree = cache.get_tree(c.args[0])
|
||||
ret = check_tree_attr(tree, pat, attr, c.args[2], regexp)
|
||||
else: # normalized text
|
||||
pat = c.args[1]
|
||||
if pat.endswith('/text()'):
|
||||
pat = pat[:-7]
|
||||
ret = check_tree_text(cache.get_tree(c.args[0]), pat, c.args[2], regexp)
|
||||
ret = get_nb_matching_elements(cache, c, regexp, True) != 0
|
||||
else:
|
||||
raise InvalidCheck('Invalid number of @{} arguments'.format(c.cmd))
|
||||
|
||||
|
|
@ -557,6 +567,11 @@ def check_command(c, cache):
|
|||
found = get_tree_count(cache.get_tree(c.args[0]), c.args[1])
|
||||
cerr = "Expected {} occurrences but found {}".format(expected, found)
|
||||
ret = expected == found
|
||||
elif len(c.args) == 4: # @count <path> <pat> <text> <count> = count test
|
||||
expected = int(c.args[3])
|
||||
found = get_nb_matching_elements(cache, c, False, False)
|
||||
cerr = "Expected {} occurrences but found {}".format(expected, found)
|
||||
ret = found == expected
|
||||
else:
|
||||
raise InvalidCheck('Invalid number of @{} arguments'.format(c.cmd))
|
||||
|
||||
|
|
|
|||
|
|
@ -1600,6 +1600,13 @@ fn render_impl(
|
|||
}
|
||||
|
||||
if let Some(ref dox) = i.impl_item.collapsed_doc_value() {
|
||||
if trait_.is_none() && i.inner_impl().items.is_empty() {
|
||||
w.write_str(
|
||||
"<div class=\"item-info\">\
|
||||
<div class=\"stab empty-impl\">This impl block contains no items.</div>
|
||||
</div>",
|
||||
);
|
||||
}
|
||||
write!(
|
||||
w,
|
||||
"<div class=\"docblock\">{}</div>",
|
||||
|
|
|
|||
|
|
@ -281,9 +281,13 @@ details.undocumented > summary::before {
|
|||
color: #000;
|
||||
}
|
||||
|
||||
/* Created this empty rule to satisfy the theme checks. */
|
||||
.stab.empty-impl {}
|
||||
|
||||
.stab.unstable,
|
||||
.stab.deprecated,
|
||||
.stab.portability {
|
||||
.stab.portability,
|
||||
.stab.empty-impl {
|
||||
color: #c5c5c5;
|
||||
background: #314559 !important;
|
||||
border-style: none !important;
|
||||
|
|
|
|||
|
|
@ -266,6 +266,7 @@ details.undocumented > summary::before {
|
|||
color: #ddd;
|
||||
}
|
||||
|
||||
.stab.empty-impl { background: #FFF5D6; border-color: #FFC600; color: #2f2f2f; }
|
||||
.stab.unstable { background: #FFF5D6; border-color: #FFC600; color: #2f2f2f; }
|
||||
.stab.deprecated { background: #ffc4c4; border-color: #db7b7b; color: #2f2f2f; }
|
||||
.stab.portability { background: #F3DFFF; border-color: #b07bdb; color: #2f2f2f; }
|
||||
|
|
|
|||
|
|
@ -255,6 +255,7 @@ details.undocumented > summary::before {
|
|||
color: #000;
|
||||
}
|
||||
|
||||
.stab.empty-impl { background: #FFF5D6; border-color: #FFC600; }
|
||||
.stab.unstable { background: #FFF5D6; border-color: #FFC600; }
|
||||
.stab.deprecated { background: #ffc4c4; border-color: #db7b7b; }
|
||||
.stab.portability { background: #F3DFFF; border-color: #b07bdb; }
|
||||
|
|
|
|||
|
|
@ -124,8 +124,9 @@ pub(crate) struct ImplStripper<'a> {
|
|||
impl<'a> DocFolder for ImplStripper<'a> {
|
||||
fn fold_item(&mut self, i: Item) -> Option<Item> {
|
||||
if let clean::ImplItem(ref imp) = *i.kind {
|
||||
// emptied none trait impls can be stripped
|
||||
if imp.trait_.is_none() && imp.items.is_empty() {
|
||||
// Impl blocks can be skipped if they are: empty; not a trait impl; and have no
|
||||
// documentation.
|
||||
if imp.trait_.is_none() && imp.items.is_empty() && i.doc_value().is_none() {
|
||||
return None;
|
||||
}
|
||||
if let Some(did) = imp.for_.def_id(self.cache) {
|
||||
|
|
|
|||
20
src/test/rustdoc/empty-impl-block.rs
Normal file
20
src/test/rustdoc/empty-impl-block.rs
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
#![crate_name = "foo"]
|
||||
|
||||
// @has 'foo/struct.Foo.html'
|
||||
pub struct Foo;
|
||||
|
||||
// @has - '//*[@class="docblock"]' 'Hello empty impl block!'
|
||||
// @has - '//*[@class="item-info"]' 'This impl block contains no items.'
|
||||
/// Hello empty impl block!
|
||||
impl Foo {}
|
||||
// We ensure that this empty impl block without doc isn't rendered.
|
||||
// @count - '//*[@class="impl has-srclink"]' 'impl Foo' 1
|
||||
impl Foo {}
|
||||
|
||||
// Just to ensure that empty trait impl blocks are rendered.
|
||||
pub struct Another;
|
||||
pub trait Bar {}
|
||||
|
||||
// @has 'foo/struct.Another.html'
|
||||
// @has - '//h3[@class="code-header in-band"]' 'impl Bar for Another'
|
||||
impl Bar for Another {}
|
||||
|
|
@ -3,5 +3,6 @@ struct Lorem {
|
|||
}
|
||||
|
||||
fn main() {
|
||||
let _foo: *mut Lorem = core::ptr::NonNull::dangling().as_ptr(); // no error here
|
||||
// Testing `as` casts, so deliberately not using `ptr::null`.
|
||||
let _foo: *mut Lorem = 0 as *mut _; // no error here
|
||||
}
|
||||
|
|
|
|||
8
src/test/ui/impl-trait/universal_wrong_hrtb.rs
Normal file
8
src/test/ui/impl-trait/universal_wrong_hrtb.rs
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
trait Trait<'a> {
|
||||
type Assoc;
|
||||
}
|
||||
|
||||
fn test_argument_position(x: impl for<'a> Trait<'a, Assoc = impl Copy + 'a>) {}
|
||||
//~^ ERROR `impl Trait` can only mention lifetimes bound at the fn or impl level
|
||||
|
||||
fn main() {}
|
||||
14
src/test/ui/impl-trait/universal_wrong_hrtb.stderr
Normal file
14
src/test/ui/impl-trait/universal_wrong_hrtb.stderr
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
error: `impl Trait` can only mention lifetimes bound at the fn or impl level
|
||||
--> $DIR/universal_wrong_hrtb.rs:5:73
|
||||
|
|
||||
LL | fn test_argument_position(x: impl for<'a> Trait<'a, Assoc = impl Copy + 'a>) {}
|
||||
| ^^
|
||||
|
|
||||
note: lifetime declared here
|
||||
--> $DIR/universal_wrong_hrtb.rs:5:39
|
||||
|
|
||||
LL | fn test_argument_position(x: impl for<'a> Trait<'a, Assoc = impl Copy + 'a>) {}
|
||||
| ^^
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
|
|
@ -47,6 +47,12 @@ error: expected `while`, `for`, `loop` or `{` after a label
|
|||
|
|
||||
LL | 'l4 0;
|
||||
| ^ expected `while`, `for`, `loop` or `{` after a label
|
||||
|
|
||||
help: consider removing the label
|
||||
|
|
||||
LL - 'l4 0;
|
||||
LL + 0;
|
||||
|
|
||||
|
||||
error: labeled expression must be followed by `:`
|
||||
--> $DIR/labeled-no-colon-expr.rs:8:9
|
||||
|
|
|
|||
27
src/test/ui/parser/recover-labeled-non-block-expr.fixed
Normal file
27
src/test/ui/parser/recover-labeled-non-block-expr.fixed
Normal file
|
|
@ -0,0 +1,27 @@
|
|||
// run-rustfix
|
||||
#![feature(label_break_value)]
|
||||
fn main() {
|
||||
let _ = 1 + 1; //~ ERROR expected `while`, `for`, `loop` or `{` after a label
|
||||
|
||||
match () { () => {}, }; //~ ERROR expected `while`, `for`, `loop` or `{` after a label
|
||||
'label: { match () { () => break 'label, } }; //~ ERROR expected `while`, `for`, `loop` or `{` after a label
|
||||
#[allow(unused_labels)]
|
||||
'label: { match () { () => 'lp: loop { break 'lp 0 }, } }; //~ ERROR expected `while`, `for`, `loop` or `{` after a label
|
||||
|
||||
let x = 1;
|
||||
let _i = 'label: { match x { //~ ERROR expected `while`, `for`, `loop` or `{` after a label
|
||||
0 => 42,
|
||||
1 if false => break 'label 17,
|
||||
1 => {
|
||||
if true {
|
||||
break 'label 13
|
||||
} else {
|
||||
break 'label 0;
|
||||
}
|
||||
}
|
||||
_ => 1,
|
||||
} };
|
||||
|
||||
let other = 3;
|
||||
let _val = 'label: { (1, if other == 3 { break 'label (2, 3) } else { other }) }; //~ ERROR expected `while`, `for`, `loop` or `{` after a label
|
||||
}
|
||||
|
|
@ -1,5 +1,27 @@
|
|||
// run-rustfix
|
||||
#![feature(label_break_value)]
|
||||
fn main() {
|
||||
'label: 1 + 1; //~ ERROR expected `while`, `for`, `loop` or `{` after a label
|
||||
let _ = 'label: 1 + 1; //~ ERROR expected `while`, `for`, `loop` or `{` after a label
|
||||
|
||||
let _recovery_witness: () = 0; //~ ERROR mismatched types
|
||||
'label: match () { () => {}, }; //~ ERROR expected `while`, `for`, `loop` or `{` after a label
|
||||
'label: match () { () => break 'label, }; //~ ERROR expected `while`, `for`, `loop` or `{` after a label
|
||||
#[allow(unused_labels)]
|
||||
'label: match () { () => 'lp: loop { break 'lp 0 }, }; //~ ERROR expected `while`, `for`, `loop` or `{` after a label
|
||||
|
||||
let x = 1;
|
||||
let _i = 'label: match x { //~ ERROR expected `while`, `for`, `loop` or `{` after a label
|
||||
0 => 42,
|
||||
1 if false => break 'label 17,
|
||||
1 => {
|
||||
if true {
|
||||
break 'label 13
|
||||
} else {
|
||||
break 'label 0;
|
||||
}
|
||||
}
|
||||
_ => 1,
|
||||
};
|
||||
|
||||
let other = 3;
|
||||
let _val = 'label: (1, if other == 3 { break 'label (2, 3) } else { other }); //~ ERROR expected `while`, `for`, `loop` or `{` after a label
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,17 +1,75 @@
|
|||
error: expected `while`, `for`, `loop` or `{` after a label
|
||||
--> $DIR/recover-labeled-non-block-expr.rs:2:13
|
||||
--> $DIR/recover-labeled-non-block-expr.rs:4:21
|
||||
|
|
||||
LL | 'label: 1 + 1;
|
||||
| ^ expected `while`, `for`, `loop` or `{` after a label
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/recover-labeled-non-block-expr.rs:4:33
|
||||
LL | let _ = 'label: 1 + 1;
|
||||
| ^ expected `while`, `for`, `loop` or `{` after a label
|
||||
|
|
||||
LL | let _recovery_witness: () = 0;
|
||||
| -- ^ expected `()`, found integer
|
||||
| |
|
||||
| expected due to this
|
||||
help: consider removing the label
|
||||
|
|
||||
LL - let _ = 'label: 1 + 1;
|
||||
LL + let _ = 1 + 1;
|
||||
|
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
error: expected `while`, `for`, `loop` or `{` after a label
|
||||
--> $DIR/recover-labeled-non-block-expr.rs:6:13
|
||||
|
|
||||
LL | 'label: match () { () => {}, };
|
||||
| ^^^^^ expected `while`, `for`, `loop` or `{` after a label
|
||||
|
|
||||
help: consider removing the label
|
||||
|
|
||||
LL - 'label: match () { () => {}, };
|
||||
LL + match () { () => {}, };
|
||||
|
|
||||
|
||||
error: expected `while`, `for`, `loop` or `{` after a label
|
||||
--> $DIR/recover-labeled-non-block-expr.rs:7:13
|
||||
|
|
||||
LL | 'label: match () { () => break 'label, };
|
||||
| ^^^^^ expected `while`, `for`, `loop` or `{` after a label
|
||||
|
|
||||
help: consider enclosing expression in a block
|
||||
|
|
||||
LL | 'label: { match () { () => break 'label, } };
|
||||
| + +
|
||||
|
||||
error: expected `while`, `for`, `loop` or `{` after a label
|
||||
--> $DIR/recover-labeled-non-block-expr.rs:9:13
|
||||
|
|
||||
LL | 'label: match () { () => 'lp: loop { break 'lp 0 }, };
|
||||
| ^^^^^ expected `while`, `for`, `loop` or `{` after a label
|
||||
|
|
||||
help: consider enclosing expression in a block
|
||||
|
|
||||
LL | 'label: { match () { () => 'lp: loop { break 'lp 0 }, } };
|
||||
| + +
|
||||
|
||||
error: expected `while`, `for`, `loop` or `{` after a label
|
||||
--> $DIR/recover-labeled-non-block-expr.rs:12:22
|
||||
|
|
||||
LL | let _i = 'label: match x {
|
||||
| ^^^^^ expected `while`, `for`, `loop` or `{` after a label
|
||||
|
|
||||
help: consider enclosing expression in a block
|
||||
|
|
||||
LL ~ let _i = 'label: { match x {
|
||||
LL | 0 => 42,
|
||||
LL | 1 if false => break 'label 17,
|
||||
LL | 1 => {
|
||||
LL | if true {
|
||||
LL | break 'label 13
|
||||
...
|
||||
|
||||
error: expected `while`, `for`, `loop` or `{` after a label
|
||||
--> $DIR/recover-labeled-non-block-expr.rs:26:24
|
||||
|
|
||||
LL | let _val = 'label: (1, if other == 3 { break 'label (2, 3) } else { other });
|
||||
| ^ expected `while`, `for`, `loop` or `{` after a label
|
||||
|
|
||||
help: consider enclosing expression in a block
|
||||
|
|
||||
LL | let _val = 'label: { (1, if other == 3 { break 'label (2, 3) } else { other }) };
|
||||
| + +
|
||||
|
||||
error: aborting due to 6 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0308`.
|
||||
|
|
|
|||
19
src/test/ui/suggestions/issue-97704.fixed
Normal file
19
src/test/ui/suggestions/issue-97704.fixed
Normal file
|
|
@ -0,0 +1,19 @@
|
|||
// edition:2021
|
||||
// run-rustfix
|
||||
|
||||
#![allow(unused)]
|
||||
|
||||
use std::future::Future;
|
||||
|
||||
async fn foo() -> Result<(), i32> {
|
||||
func(async { Ok::<_, i32>(()) }).await?;
|
||||
//~^ ERROR the `?` operator can only be applied to values that implement `Try`
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
async fn func<T>(fut: impl Future<Output = T>) -> T {
|
||||
fut.await
|
||||
}
|
||||
|
||||
fn main() {}
|
||||
19
src/test/ui/suggestions/issue-97704.rs
Normal file
19
src/test/ui/suggestions/issue-97704.rs
Normal file
|
|
@ -0,0 +1,19 @@
|
|||
// edition:2021
|
||||
// run-rustfix
|
||||
|
||||
#![allow(unused)]
|
||||
|
||||
use std::future::Future;
|
||||
|
||||
async fn foo() -> Result<(), i32> {
|
||||
func(async { Ok::<_, i32>(()) })?;
|
||||
//~^ ERROR the `?` operator can only be applied to values that implement `Try`
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
async fn func<T>(fut: impl Future<Output = T>) -> T {
|
||||
fut.await
|
||||
}
|
||||
|
||||
fn main() {}
|
||||
15
src/test/ui/suggestions/issue-97704.stderr
Normal file
15
src/test/ui/suggestions/issue-97704.stderr
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
error[E0277]: the `?` operator can only be applied to values that implement `Try`
|
||||
--> $DIR/issue-97704.rs:9:5
|
||||
|
|
||||
LL | func(async { Ok::<_, i32>(()) })?;
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the `?` operator cannot be applied to type `impl Future<Output = Result<(), i32>>`
|
||||
|
|
||||
= help: the trait `Try` is not implemented for `impl Future<Output = Result<(), i32>>`
|
||||
help: consider `await`ing on the `Future`
|
||||
|
|
||||
LL | func(async { Ok::<_, i32>(()) }).await?;
|
||||
| ++++++
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0277`.
|
||||
Loading…
Add table
Add a link
Reference in a new issue