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

File tree

18 files changed

+213
-28
lines changed

18 files changed

+213
-28
lines changed

compiler/rustc_hir_typeck/src/cast.rs

Lines changed: 45 additions & 1 deletion
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

Lines changed: 2 additions & 2 deletions
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

Lines changed: 1 addition & 1 deletion
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

Lines changed: 8 additions & 4 deletions
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

Lines changed: 1 addition & 1 deletion
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

Lines changed: 1 addition & 0 deletions
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

Lines changed: 1 addition & 0 deletions
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);
Lines changed: 33 additions & 0 deletions
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

Lines changed: 2 additions & 0 deletions
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

Lines changed: 5 additions & 1 deletion
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
}

0 commit comments

Comments
 (0)