Skip to content

Commit 9a19e76

Browse files
committed
Auto merge of #106914 - matthiaskrgr:rollup-yh0x4gq, r=matthiaskrgr
Rollup of 5 pull requests Successful merges: - #106888 (Add tidy check to ensure that rustdoc GUI tests start with a small description) - #106896 (suggest `is_empty` for collections when casting to `bool`) - #106900 (Fix regression in `unused_braces` with macros) - #106906 (remove redundant clones) - #106909 (Only suggest adding type param if path being resolved was a type) Failed merges: r? `@ghost` `@rustbot` modify labels: rollup
2 parents 9e75ddd + fc78b1e commit 9a19e76

18 files changed

+213
-28
lines changed

compiler/rustc_hir_typeck/src/cast.rs

+45-1
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,9 @@
3131
use super::FnCtxt;
3232

3333
use crate::type_error_struct;
34-
use rustc_errors::{struct_span_err, Applicability, DelayDm, DiagnosticBuilder, ErrorGuaranteed};
34+
use rustc_errors::{
35+
struct_span_err, Applicability, DelayDm, Diagnostic, DiagnosticBuilder, ErrorGuaranteed,
36+
};
3537
use rustc_hir as hir;
3638
use rustc_macros::{TypeFoldable, TypeVisitable};
3739
use rustc_middle::mir::Mutability;
@@ -270,6 +272,9 @@ impl<'a, 'tcx> CastCheck<'tcx> {
270272
}
271273
));
272274
}
275+
276+
self.try_suggest_collection_to_bool(fcx, &mut err);
277+
273278
err.emit();
274279
}
275280
CastError::NeedViaInt => {
@@ -517,6 +522,9 @@ impl<'a, 'tcx> CastCheck<'tcx> {
517522
} else {
518523
err.span_label(self.span, "invalid cast");
519524
}
525+
526+
self.try_suggest_collection_to_bool(fcx, &mut err);
527+
520528
err.emit();
521529
}
522530
CastError::SizedUnsizedCast => {
@@ -1080,4 +1088,40 @@ impl<'a, 'tcx> CastCheck<'tcx> {
10801088
},
10811089
);
10821090
}
1091+
1092+
/// Attempt to suggest using `.is_empty` when trying to cast from a
1093+
/// collection type to a boolean.
1094+
fn try_suggest_collection_to_bool(&self, fcx: &FnCtxt<'a, 'tcx>, err: &mut Diagnostic) {
1095+
if self.cast_ty.is_bool() {
1096+
let derefed = fcx
1097+
.autoderef(self.expr_span, self.expr_ty)
1098+
.silence_errors()
1099+
.find(|t| matches!(t.0.kind(), ty::Str | ty::Slice(..)));
1100+
1101+
if let Some((deref_ty, _)) = derefed {
1102+
// Give a note about what the expr derefs to.
1103+
if deref_ty != self.expr_ty.peel_refs() {
1104+
err.span_note(
1105+
self.expr_span,
1106+
format!(
1107+
"this expression `Deref`s to `{}` which implements `is_empty`",
1108+
fcx.ty_to_string(deref_ty)
1109+
),
1110+
);
1111+
}
1112+
1113+
// Create a multipart suggestion: add `!` and `.is_empty()` in
1114+
// place of the cast.
1115+
let suggestion = vec![
1116+
(self.expr_span.shrink_to_lo(), "!".to_string()),
1117+
(self.span.with_lo(self.expr_span.hi()), ".is_empty()".to_string()),
1118+
];
1119+
1120+
err.multipart_suggestion_verbose(format!(
1121+
"consider using the `is_empty` method on `{}` to determine if it contains anything",
1122+
fcx.ty_to_string(self.expr_ty),
1123+
), suggestion, Applicability::MaybeIncorrect);
1124+
}
1125+
}
1126+
}
10831127
}

compiler/rustc_lint/src/internal.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -187,9 +187,9 @@ impl<'tcx> LateLintPass<'tcx> for TyTyKind {
187187
},
188188
None => cx.emit_spanned_lint(USAGE_OF_TY_TYKIND, path.span, TykindDiag),
189189
}
190-
} else if !ty.span.from_expansion() && path.segments.len() > 1 && let Some(t) = is_ty_or_ty_ctxt(cx, &path) {
190+
} else if !ty.span.from_expansion() && path.segments.len() > 1 && let Some(ty) = is_ty_or_ty_ctxt(cx, &path) {
191191
cx.emit_spanned_lint(USAGE_OF_QUALIFIED_TY, path.span, TyQualified {
192-
ty: t.clone(),
192+
ty,
193193
suggestion: path.span,
194194
});
195195
}

compiler/rustc_lint/src/pass_by_value.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ impl<'tcx> LateLintPass<'tcx> for PassByValue {
3232
cx.emit_spanned_lint(
3333
PASS_BY_VALUE,
3434
ty.span,
35-
PassByValueDiag { ty: t.clone(), suggestion: ty.span },
35+
PassByValueDiag { ty: t, suggestion: ty.span },
3636
);
3737
}
3838
}

compiler/rustc_lint/src/unused.rs

+8-4
Original file line numberDiff line numberDiff line change
@@ -1095,17 +1095,21 @@ impl UnusedDelimLint for UnusedBraces {
10951095
// ```
10961096
// - the block has no attribute and was not created inside a macro
10971097
// - if the block is an `anon_const`, the inner expr must be a literal
1098-
// (do not lint `struct A<const N: usize>; let _: A<{ 2 + 3 }>;`)
1099-
//
1098+
// not created by a macro, i.e. do not lint on:
1099+
// ```
1100+
// struct A<const N: usize>;
1101+
// let _: A<{ 2 + 3 }>;
1102+
// let _: A<{produces_literal!()}>;
1103+
// ```
11001104
// FIXME(const_generics): handle paths when #67075 is fixed.
11011105
if let [stmt] = inner.stmts.as_slice() {
11021106
if let ast::StmtKind::Expr(ref expr) = stmt.kind {
11031107
if !Self::is_expr_delims_necessary(expr, followed_by_block, false)
11041108
&& (ctx != UnusedDelimsCtx::AnonConst
1105-
|| matches!(expr.kind, ast::ExprKind::Lit(_)))
1109+
|| (matches!(expr.kind, ast::ExprKind::Lit(_))
1110+
&& !expr.span.from_expansion()))
11061111
&& !cx.sess().source_map().is_multiline(value.span)
11071112
&& value.attrs.is_empty()
1108-
&& !expr.span.from_expansion()
11091113
&& !value.span.from_expansion()
11101114
&& !inner.span.from_expansion()
11111115
{

compiler/rustc_resolve/src/late.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -3373,7 +3373,7 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
33733373
sugg.to_string(),
33743374
Applicability::MaybeIncorrect,
33753375
))
3376-
} else if res.is_none() {
3376+
} else if res.is_none() && matches!(source, PathSource::Type) {
33773377
this.report_missing_type_error(path)
33783378
} else {
33793379
None

src/tools/tidy/src/lib.rs

+1
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,7 @@ pub mod features;
6262
pub mod mir_opt_tests;
6363
pub mod pal;
6464
pub mod primitive_docs;
65+
pub mod rustdoc_gui_tests;
6566
pub mod style;
6667
pub mod target_specific_tests;
6768
pub mod tests_placement;

src/tools/tidy/src/main.rs

+1
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,7 @@ fn main() {
8080
check!(debug_artifacts, &tests_path);
8181
check!(ui_tests, &tests_path);
8282
check!(mir_opt_tests, &tests_path, bless);
83+
check!(rustdoc_gui_tests, &tests_path);
8384

8485
// Checks that only make sense for the compiler.
8586
check!(error_codes, &root_path, &[&compiler_path, &librustdoc_path], verbose);
+33
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
//! Tidy check to ensure that rustdoc GUI tests start with a small description.
2+
3+
use std::path::Path;
4+
5+
pub fn check(path: &Path, bad: &mut bool) {
6+
crate::walk::walk(
7+
&path.join("rustdoc-gui"),
8+
&mut |p| {
9+
// If there is no extension, it's very likely a folder and we want to go into it.
10+
p.extension().map(|e| e != "goml").unwrap_or(false)
11+
},
12+
&mut |entry, content| {
13+
for line in content.lines() {
14+
if !line.starts_with("// ") {
15+
tidy_error!(
16+
bad,
17+
"{}: rustdoc-gui tests must start with a small description",
18+
entry.path().display(),
19+
);
20+
return;
21+
} else if line.starts_with("// ") {
22+
let parts = line[2..].trim();
23+
// We ignore tidy comments.
24+
if parts.starts_with("// tidy-") {
25+
continue;
26+
}
27+
// All good!
28+
return;
29+
}
30+
}
31+
},
32+
);
33+
}

tests/rustdoc-gui/basic-code.goml

+2
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
// Small test to ensure the "src-line-numbers" element is only present once on
2+
// the page.
13
goto: "file://" + |DOC_PATH| + "/test_docs/index.html"
24
click: ".srclink"
35
wait-for: ".src-line-numbers"

tests/ui/cast/cast-as-bool.rs

+5-1
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,12 @@ fn main() {
22
let u = 5 as bool; //~ ERROR cannot cast as `bool`
33
//~| HELP compare with zero instead
44
//~| SUGGESTION 5 != 0
5+
56
let t = (1 + 2) as bool; //~ ERROR cannot cast as `bool`
67
//~| HELP compare with zero instead
78
//~| SUGGESTION (1 + 2) != 0
8-
let v = "hello" as bool; //~ ERROR casting `&'static str` as `bool` is invalid
9+
10+
let v = "hello" as bool;
11+
//~^ ERROR casting `&'static str` as `bool` is invalid
12+
//~| HELP consider using the `is_empty` method on `&'static str` to determine if it contains anything
913
}

tests/ui/cast/cast-as-bool.stderr

+7-2
Original file line numberDiff line numberDiff line change
@@ -5,16 +5,21 @@ LL | let u = 5 as bool;
55
| ^^^^^^^^^ help: compare with zero instead: `5 != 0`
66

77
error[E0054]: cannot cast as `bool`
8-
--> $DIR/cast-as-bool.rs:5:13
8+
--> $DIR/cast-as-bool.rs:6:13
99
|
1010
LL | let t = (1 + 2) as bool;
1111
| ^^^^^^^^^^^^^^^ help: compare with zero instead: `(1 + 2) != 0`
1212

1313
error[E0606]: casting `&'static str` as `bool` is invalid
14-
--> $DIR/cast-as-bool.rs:8:13
14+
--> $DIR/cast-as-bool.rs:10:13
1515
|
1616
LL | let v = "hello" as bool;
1717
| ^^^^^^^^^^^^^^^
18+
|
19+
help: consider using the `is_empty` method on `&'static str` to determine if it contains anything
20+
|
21+
LL | let v = !"hello".is_empty();
22+
| + ~~~~~~~~~~~
1823

1924
error: aborting due to 3 previous errors
2025

+27
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
use std::ops::Deref;
2+
3+
struct Foo;
4+
5+
impl Deref for Foo {
6+
type Target = [u8];
7+
8+
fn deref(&self) -> &Self::Target {
9+
&[]
10+
}
11+
}
12+
13+
fn main() {
14+
let _ = "foo" as bool;
15+
//~^ ERROR casting `&'static str` as `bool` is invalid [E0606]
16+
17+
let _ = String::from("foo") as bool;
18+
//~^ ERROR non-primitive cast: `String` as `bool` [E0605]
19+
20+
let _ = Foo as bool;
21+
//~^ ERROR non-primitive cast: `Foo` as `bool` [E0605]
22+
}
23+
24+
fn _slice(bar: &[i32]) -> bool {
25+
bar as bool
26+
//~^ ERROR casting `&[i32]` as `bool` is invalid [E0606]
27+
}
+58
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
error[E0606]: casting `&'static str` as `bool` is invalid
2+
--> $DIR/issue-106883-is-empty.rs:14:13
3+
|
4+
LL | let _ = "foo" as bool;
5+
| ^^^^^^^^^^^^^
6+
|
7+
help: consider using the `is_empty` method on `&'static str` to determine if it contains anything
8+
|
9+
LL | let _ = !"foo".is_empty();
10+
| + ~~~~~~~~~~~
11+
12+
error[E0605]: non-primitive cast: `String` as `bool`
13+
--> $DIR/issue-106883-is-empty.rs:17:13
14+
|
15+
LL | let _ = String::from("foo") as bool;
16+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^ an `as` expression can only be used to convert between primitive types or to coerce to a specific trait object
17+
|
18+
note: this expression `Deref`s to `str` which implements `is_empty`
19+
--> $DIR/issue-106883-is-empty.rs:17:13
20+
|
21+
LL | let _ = String::from("foo") as bool;
22+
| ^^^^^^^^^^^^^^^^^^^
23+
help: consider using the `is_empty` method on `String` to determine if it contains anything
24+
|
25+
LL | let _ = !String::from("foo").is_empty();
26+
| + ~~~~~~~~~~~
27+
28+
error[E0605]: non-primitive cast: `Foo` as `bool`
29+
--> $DIR/issue-106883-is-empty.rs:20:13
30+
|
31+
LL | let _ = Foo as bool;
32+
| ^^^^^^^^^^^ an `as` expression can only be used to convert between primitive types or to coerce to a specific trait object
33+
|
34+
note: this expression `Deref`s to `[u8]` which implements `is_empty`
35+
--> $DIR/issue-106883-is-empty.rs:20:13
36+
|
37+
LL | let _ = Foo as bool;
38+
| ^^^
39+
help: consider using the `is_empty` method on `Foo` to determine if it contains anything
40+
|
41+
LL | let _ = !Foo.is_empty();
42+
| + ~~~~~~~~~~~
43+
44+
error[E0606]: casting `&[i32]` as `bool` is invalid
45+
--> $DIR/issue-106883-is-empty.rs:25:5
46+
|
47+
LL | bar as bool
48+
| ^^^^^^^^^^^
49+
|
50+
help: consider using the `is_empty` method on `&[i32]` to determine if it contains anything
51+
|
52+
LL | !bar.is_empty()
53+
| + ~~~~~~~~~~~
54+
55+
error: aborting due to 4 previous errors
56+
57+
Some errors have detailed explanations: E0605, E0606.
58+
For more information about an error, try `rustc --explain E0605`.

tests/ui/lint/unused_braces.fixed

+4
Original file line numberDiff line numberDiff line change
@@ -50,4 +50,8 @@ fn main() {
5050
if { return } {
5151

5252
}
53+
54+
// regression test for https://github.com/rust-lang/rust/issues/106899
55+
return println!("!");
56+
//~^ WARN unnecessary braces
5357
}

tests/ui/lint/unused_braces.rs

+4
Original file line numberDiff line numberDiff line change
@@ -50,4 +50,8 @@ fn main() {
5050
if { return } {
5151

5252
}
53+
54+
// regression test for https://github.com/rust-lang/rust/issues/106899
55+
return { println!("!") };
56+
//~^ WARN unnecessary braces
5357
}

tests/ui/lint/unused_braces.stderr

+13-1
Original file line numberDiff line numberDiff line change
@@ -68,5 +68,17 @@ LL - consume({ 7 });
6868
LL + consume(7);
6969
|
7070

71-
warning: 5 warnings emitted
71+
warning: unnecessary braces around `return` value
72+
--> $DIR/unused_braces.rs:55:12
73+
|
74+
LL | return { println!("!") };
75+
| ^^ ^^
76+
|
77+
help: remove these braces
78+
|
79+
LL - return { println!("!") };
80+
LL + return println!("!");
81+
|
82+
83+
warning: 6 warnings emitted
7284

tests/ui/suggestions/constrain-suggest-ice.stderr

+1-10
Original file line numberDiff line numberDiff line change
@@ -24,16 +24,7 @@ error[E0425]: cannot find value `F` in this scope
2424
--> $DIR/constrain-suggest-ice.rs:6:9
2525
|
2626
LL | F
27-
| ^
28-
|
29-
help: a local variable with a similar name exists
30-
|
31-
LL | x
32-
| ~
33-
help: you might be missing a type parameter
34-
|
35-
LL | struct Bug<S, F>{
36-
| +++
27+
| ^ help: a local variable with a similar name exists: `x`
3728

3829
error: generic `Self` types are currently not permitted in anonymous constants
3930
--> $DIR/constrain-suggest-ice.rs:3:21

tests/ui/typeck/issue-104513-ice.stderr

-5
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,6 @@ error[E0405]: cannot find trait `Oops` in this scope
33
|
44
LL | let _: S<impl Oops> = S;
55
| ^^^^ not found in this scope
6-
|
7-
help: you might be missing a type parameter
8-
|
9-
LL | fn f<Oops>() {
10-
| ++++++
116

127
error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in variable binding
138
--> $DIR/issue-104513-ice.rs:3:14

0 commit comments

Comments
 (0)