Skip to content

Commit bb3afe1

Browse files
committed
Auto merge of rust-lang#82911 - m-ou-se:rollup-rjomgja, r=m-ou-se
Rollup of 11 pull requests Successful merges: - rust-lang#82711 (Add documentation for string->Cow conversions) - rust-lang#82767 (Update minifier dependency version) - rust-lang#82800 (Move rustdoc UI tests into a subdirectory) - rust-lang#82810 (Typo fix in Unstable book: `cargo cov` -> `cargo profdata`) - rust-lang#82829 (Handle negative literals in cast overflow warning) - rust-lang#82854 (Account for `if (let pat = expr) {}`) - rust-lang#82870 (Add note about the `#[doc(no-inline)]` usage) - rust-lang#82874 (Add codegen tests for some issues closed by LLVM 12) - rust-lang#82881 (diagnostics: Be clear about "crate root" and `::foo` paths in resolve diagnostics) - rust-lang#82888 (Grammar Fixes) - rust-lang#82897 ([.mailmap] Add entry for Ramkumar Ramachandra) Failed merges: r? `@ghost` `@rustbot` modify labels: rollup
2 parents eb476b1 + 54add8d commit bb3afe1

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

50 files changed

+540
-258
lines changed

.mailmap

+1
Original file line numberDiff line numberDiff line change
@@ -235,6 +235,7 @@ Philipp Matthias Schäfer <[email protected]>
235235
Przemysław Wesołek <[email protected]> Przemek Wesołek <[email protected]>
236236
Rafael Ávila de Espíndola <[email protected]> Rafael Avila de Espindola <espindola@dream.(none)>
237237
Ralph Giles <[email protected]> Ralph Giles <[email protected]>
238+
Ramkumar Ramachandra <[email protected]> <[email protected]>
238239
Renato Riccieri Santos Zannon <[email protected]>
239240
240241
Rob Arnold <[email protected]>

Cargo.lock

+2-2
Original file line numberDiff line numberDiff line change
@@ -2214,9 +2214,9 @@ dependencies = [
22142214

22152215
[[package]]
22162216
name = "minifier"
2217-
version = "0.0.33"
2217+
version = "0.0.39"
22182218
source = "registry+https://github.com/rust-lang/crates.io-index"
2219-
checksum = "70bf0db2475f5e627787da77ca52fe33c294063f49f4134b8bc662eedb5e7332"
2219+
checksum = "6cdf618de5c9c98d4a7b2e0d1f1e44f82a19196cfd94040bb203621c25d28d98"
22202220
dependencies = [
22212221
"macro-utils",
22222222
]

compiler/rustc_ast/src/ast.rs

+8
Original file line numberDiff line numberDiff line change
@@ -1129,6 +1129,14 @@ impl Expr {
11291129
}
11301130
}
11311131

1132+
pub fn peel_parens(&self) -> &Expr {
1133+
let mut expr = self;
1134+
while let ExprKind::Paren(inner) = &expr.kind {
1135+
expr = &inner;
1136+
}
1137+
expr
1138+
}
1139+
11321140
/// Attempts to reparse as `Ty` (for diagnostic purposes).
11331141
pub fn to_ty(&self) -> Option<P<Ty>> {
11341142
let kind = match &self.kind {

compiler/rustc_ast_lowering/src/expr.rs

+40-2
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,23 @@ impl<'hir> LoweringContext<'_, 'hir> {
9797
ExprKind::Let(ref pat, ref scrutinee) => {
9898
self.lower_expr_if_let(e.span, pat, scrutinee, then, else_opt.as_deref())
9999
}
100+
ExprKind::Paren(ref paren) => match paren.peel_parens().kind {
101+
ExprKind::Let(ref pat, ref scrutinee) => {
102+
// A user has written `if (let Some(x) = foo) {`, we want to avoid
103+
// confusing them with mentions of nightly features.
104+
// If this logic is changed, you will also likely need to touch
105+
// `unused::UnusedParens::check_expr`.
106+
self.if_let_expr_with_parens(cond, &paren.peel_parens());
107+
self.lower_expr_if_let(
108+
e.span,
109+
pat,
110+
scrutinee,
111+
then,
112+
else_opt.as_deref(),
113+
)
114+
}
115+
_ => self.lower_expr_if(cond, then, else_opt.as_deref()),
116+
},
100117
_ => self.lower_expr_if(cond, then, else_opt.as_deref()),
101118
},
102119
ExprKind::While(ref cond, ref body, opt_label) => self
@@ -346,6 +363,25 @@ impl<'hir> LoweringContext<'_, 'hir> {
346363
hir::ExprKind::Call(f, self.lower_exprs(&real_args))
347364
}
348365

366+
fn if_let_expr_with_parens(&mut self, cond: &Expr, paren: &Expr) {
367+
let start = cond.span.until(paren.span);
368+
let end = paren.span.shrink_to_hi().until(cond.span.shrink_to_hi());
369+
self.sess
370+
.struct_span_err(
371+
vec![start, end],
372+
"invalid parentheses around `let` expression in `if let`",
373+
)
374+
.multipart_suggestion(
375+
"`if let` needs to be written without parentheses",
376+
vec![(start, String::new()), (end, String::new())],
377+
rustc_errors::Applicability::MachineApplicable,
378+
)
379+
.emit();
380+
// Ideally, we'd remove the feature gating of a `let` expression since we are already
381+
// complaining about it here, but `feature_gate::check_crate` has already run by now:
382+
// self.sess.parse_sess.gated_spans.ungate_last(sym::let_chains, paren.span);
383+
}
384+
349385
/// Emit an error and lower `ast::ExprKind::Let(pat, scrutinee)` into:
350386
/// ```rust
351387
/// match scrutinee { pats => true, _ => false }
@@ -356,8 +392,10 @@ impl<'hir> LoweringContext<'_, 'hir> {
356392
if self.sess.opts.unstable_features.is_nightly_build() {
357393
self.sess
358394
.struct_span_err(span, "`let` expressions are not supported here")
359-
.note("only supported directly in conditions of `if`- and `while`-expressions")
360-
.note("as well as when nested within `&&` and parenthesis in those conditions")
395+
.note(
396+
"only supported directly without parentheses in conditions of `if`- and \
397+
`while`-expressions, as well as in `let` chains within parentheses",
398+
)
361399
.emit();
362400
} else {
363401
self.sess

compiler/rustc_ast_passes/src/feature_gate.rs

+10-2
Original file line numberDiff line numberDiff line change
@@ -638,8 +638,16 @@ pub fn check_crate(krate: &ast::Crate, sess: &Session) {
638638
}
639639
};
640640
}
641-
gate_all!(if_let_guard, "`if let` guards are experimental");
642-
gate_all!(let_chains, "`let` expressions in this position are experimental");
641+
gate_all!(
642+
if_let_guard,
643+
"`if let` guards are experimental",
644+
"you can write `if matches!(<expr>, <pattern>)` instead of `if let <pattern> = <expr>`"
645+
);
646+
gate_all!(
647+
let_chains,
648+
"`let` expressions in this position are experimental",
649+
"you can write `matches!(<expr>, <pattern>)` instead of `let <pattern> = <expr>`"
650+
);
643651
gate_all!(
644652
async_closure,
645653
"async closures are unstable",

compiler/rustc_lint/src/types.rs

+21-6
Original file line numberDiff line numberDiff line change
@@ -217,7 +217,11 @@ fn report_bin_hex_error(
217217
cx.struct_span_lint(OVERFLOWING_LITERALS, expr.span, |lint| {
218218
let (t, actually) = match ty {
219219
attr::IntType::SignedInt(t) => {
220-
let actually = size.sign_extend(val) as i128;
220+
let actually = if negative {
221+
-(size.sign_extend(val) as i128)
222+
} else {
223+
size.sign_extend(val) as i128
224+
};
221225
(t.name_str(), actually.to_string())
222226
}
223227
attr::IntType::UnsignedInt(t) => {
@@ -226,11 +230,22 @@ fn report_bin_hex_error(
226230
}
227231
};
228232
let mut err = lint.build(&format!("literal out of range for `{}`", t));
229-
err.note(&format!(
230-
"the literal `{}` (decimal `{}`) does not fit into \
231-
the type `{}` and will become `{}{}`",
232-
repr_str, val, t, actually, t
233-
));
233+
if negative {
234+
// If the value is negative,
235+
// emits a note about the value itself, apart from the literal.
236+
err.note(&format!(
237+
"the literal `{}` (decimal `{}`) does not fit into \
238+
the type `{}`",
239+
repr_str, val, t
240+
));
241+
err.note(&format!("and the value `-{}` will become `{}{}`", repr_str, actually, t));
242+
} else {
243+
err.note(&format!(
244+
"the literal `{}` (decimal `{}`) does not fit into \
245+
the type `{}` and will become `{}{}`",
246+
repr_str, val, t, actually, t
247+
));
248+
}
234249
if let Some(sugg_ty) =
235250
get_type_suggestion(&cx.typeck_results().node_type(expr.hir_id), val, negative)
236251
{

compiler/rustc_lint/src/unused.rs

+28-3
Original file line numberDiff line numberDiff line change
@@ -602,7 +602,7 @@ trait UnusedDelimLint {
602602
use rustc_ast::ExprKind::*;
603603
let (value, ctx, followed_by_block, left_pos, right_pos) = match e.kind {
604604
// Do not lint `unused_braces` in `if let` expressions.
605-
If(ref cond, ref block, ..)
605+
If(ref cond, ref block, _)
606606
if !matches!(cond.kind, Let(_, _)) || Self::LINT_EXPR_IN_PATTERN_MATCHING_CTX =>
607607
{
608608
let left = e.span.lo() + rustc_span::BytePos(2);
@@ -816,8 +816,33 @@ impl UnusedParens {
816816

817817
impl EarlyLintPass for UnusedParens {
818818
fn check_expr(&mut self, cx: &EarlyContext<'_>, e: &ast::Expr) {
819-
if let ExprKind::Let(ref pat, ..) | ExprKind::ForLoop(ref pat, ..) = e.kind {
820-
self.check_unused_parens_pat(cx, pat, false, false);
819+
match e.kind {
820+
ExprKind::Let(ref pat, _) | ExprKind::ForLoop(ref pat, ..) => {
821+
self.check_unused_parens_pat(cx, pat, false, false);
822+
}
823+
// We ignore parens in cases like `if (((let Some(0) = Some(1))))` because we already
824+
// handle a hard error for them during AST lowering in `lower_expr_mut`, but we still
825+
// want to complain about things like `if let 42 = (42)`.
826+
ExprKind::If(ref cond, ref block, ref else_)
827+
if matches!(cond.peel_parens().kind, ExprKind::Let(..)) =>
828+
{
829+
self.check_unused_delims_expr(
830+
cx,
831+
cond.peel_parens(),
832+
UnusedDelimsCtx::LetScrutineeExpr,
833+
true,
834+
None,
835+
None,
836+
);
837+
for stmt in &block.stmts {
838+
<Self as UnusedDelimLint>::check_stmt(self, cx, stmt);
839+
}
840+
if let Some(e) = else_ {
841+
<Self as UnusedDelimLint>::check_expr(self, cx, e);
842+
}
843+
return;
844+
}
845+
_ => {}
821846
}
822847

823848
<Self as UnusedDelimLint>::check_expr(self, cx, e)

compiler/rustc_resolve/src/late/diagnostics.rs

+11-1
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ use rustc_hir::def::{self, CtorKind, CtorOf, DefKind};
1616
use rustc_hir::def_id::{DefId, CRATE_DEF_INDEX, LOCAL_CRATE};
1717
use rustc_hir::PrimTy;
1818
use rustc_session::parse::feature_err;
19+
use rustc_span::edition::Edition;
1920
use rustc_span::hygiene::MacroKind;
2021
use rustc_span::lev_distance::find_best_match_for_name;
2122
use rustc_span::symbol::{kw, sym, Ident, Symbol};
@@ -133,7 +134,7 @@ impl<'a: 'ast, 'ast> LateResolutionVisitor<'a, '_, 'ast> {
133134
let is_enum_variant = &|res| matches!(res, Res::Def(DefKind::Variant, _));
134135

135136
// Make the base error.
136-
let expected = source.descr_expected();
137+
let mut expected = source.descr_expected();
137138
let path_str = Segment::names_to_string(path);
138139
let item_str = path.last().unwrap().ident;
139140
let (base_msg, fallback_label, base_span, could_be_expr) = if let Some(res) = res {
@@ -166,6 +167,15 @@ impl<'a: 'ast, 'ast> LateResolutionVisitor<'a, '_, 'ast> {
166167
let (mod_prefix, mod_str) = if path.len() == 1 {
167168
(String::new(), "this scope".to_string())
168169
} else if path.len() == 2 && path[0].ident.name == kw::PathRoot {
170+
if self.r.session.edition() > Edition::Edition2015 {
171+
// In edition 2018 onwards, the `::foo` syntax may only pull from the extern prelude
172+
// which overrides all other expectations of item type
173+
expected = "crate";
174+
(String::new(), "the list of imported crates".to_string())
175+
} else {
176+
(String::new(), "the crate root".to_string())
177+
}
178+
} else if path.len() == 2 && path[0].ident.name == kw::Crate {
169179
(String::new(), "the crate root".to_string())
170180
} else {
171181
let mod_path = &path[..path.len() - 1];

compiler/rustc_resolve/src/lib.rs

+13-5
Original file line numberDiff line numberDiff line change
@@ -2433,8 +2433,10 @@ impl<'a> Resolver<'a> {
24332433
Applicability::MaybeIncorrect,
24342434
)),
24352435
)
2436-
} else {
2436+
} else if self.session.edition() == Edition::Edition2015 {
24372437
(format!("maybe a missing crate `{}`?", ident), None)
2438+
} else {
2439+
(format!("could not find `{}` in the crate root", ident), None)
24382440
}
24392441
} else if i == 0 {
24402442
if ident
@@ -2450,10 +2452,16 @@ impl<'a> Resolver<'a> {
24502452
}
24512453
} else {
24522454
let parent = path[i - 1].ident.name;
2453-
let parent = if parent == kw::PathRoot {
2454-
"crate root".to_owned()
2455-
} else {
2456-
format!("`{}`", parent)
2455+
let parent = match parent {
2456+
// ::foo is mounted at the crate root for 2015, and is the extern
2457+
// prelude for 2018+
2458+
kw::PathRoot if self.session.edition() > Edition::Edition2015 => {
2459+
"the list of imported crates".to_owned()
2460+
}
2461+
kw::PathRoot | kw::Crate => "the crate root".to_owned(),
2462+
_ => {
2463+
format!("`{}`", parent)
2464+
}
24572465
};
24582466

24592467
let mut msg = format!("could not find `{}` in {}", ident, parent);

library/alloc/src/string.rs

+33
Original file line numberDiff line numberDiff line change
@@ -2352,6 +2352,16 @@ impl<'a> From<Cow<'a, str>> for String {
23522352

23532353
#[stable(feature = "rust1", since = "1.0.0")]
23542354
impl<'a> From<&'a str> for Cow<'a, str> {
2355+
/// Converts a string slice into a Borrowed variant.
2356+
/// No heap allocation is performed, and the string
2357+
/// is not copied.
2358+
///
2359+
/// # Example
2360+
///
2361+
/// ```
2362+
/// # use std::borrow::Cow;
2363+
/// assert_eq!(Cow::from("eggplant"), Cow::Borrowed("eggplant"));
2364+
/// ```
23552365
#[inline]
23562366
fn from(s: &'a str) -> Cow<'a, str> {
23572367
Cow::Borrowed(s)
@@ -2360,6 +2370,18 @@ impl<'a> From<&'a str> for Cow<'a, str> {
23602370

23612371
#[stable(feature = "rust1", since = "1.0.0")]
23622372
impl<'a> From<String> for Cow<'a, str> {
2373+
/// Converts a String into an Owned variant.
2374+
/// No heap allocation is performed, and the string
2375+
/// is not copied.
2376+
///
2377+
/// # Example
2378+
///
2379+
/// ```
2380+
/// # use std::borrow::Cow;
2381+
/// let s = "eggplant".to_string();
2382+
/// let s2 = "eggplant".to_string();
2383+
/// assert_eq!(Cow::from(s), Cow::<'static, str>::Owned(s2));
2384+
/// ```
23632385
#[inline]
23642386
fn from(s: String) -> Cow<'a, str> {
23652387
Cow::Owned(s)
@@ -2368,6 +2390,17 @@ impl<'a> From<String> for Cow<'a, str> {
23682390

23692391
#[stable(feature = "cow_from_string_ref", since = "1.28.0")]
23702392
impl<'a> From<&'a String> for Cow<'a, str> {
2393+
/// Converts a String reference into a Borrowed variant.
2394+
/// No heap allocation is performed, and the string
2395+
/// is not copied.
2396+
///
2397+
/// # Example
2398+
///
2399+
/// ```
2400+
/// # use std::borrow::Cow;
2401+
/// let s = "eggplant".to_string();
2402+
/// assert_eq!(Cow::from(&s), Cow::Borrowed("eggplant"));
2403+
/// ```
23712404
#[inline]
23722405
fn from(s: &'a String) -> Cow<'a, str> {
23732406
Cow::Borrowed(s.as_str())

library/core/src/array/mod.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ pub fn from_mut<T>(s: &mut T) -> &mut [T; 1] {
4242
/// without causing much metadata bloat.
4343
///
4444
/// The trait is marked unsafe in order to restrict implementors to fixed-size
45-
/// arrays. User of this trait can assume that implementors have the exact
45+
/// arrays. A user of this trait can assume that implementors have the exact
4646
/// layout in memory of a fixed size array (for example, for unsafe
4747
/// initialization).
4848
///
@@ -489,7 +489,7 @@ impl<T, const N: usize> [T; N] {
489489
/// ```
490490
///
491491
/// This method is particularly useful if combined with other methods, like
492-
/// [`map`](#method.map). This way, you can can avoid moving the original
492+
/// [`map`](#method.map). This way, you can avoid moving the original
493493
/// array if its elements are not `Copy`.
494494
///
495495
/// ```
@@ -564,7 +564,7 @@ where
564564
/// yields fewer than `N` items, `None` is returned and all already yielded
565565
/// items are dropped.
566566
///
567-
/// Since the iterator is passed as mutable reference and this function calls
567+
/// Since the iterator is passed as a mutable reference and this function calls
568568
/// `next` at most `N` times, the iterator can still be used afterwards to
569569
/// retrieve the remaining items.
570570
///

library/std/src/lib.rs

+5-1
Original file line numberDiff line numberDiff line change
@@ -395,7 +395,11 @@ pub use alloc_crate::vec;
395395
#[stable(feature = "rust1", since = "1.0.0")]
396396
pub use core::any;
397397
#[stable(feature = "simd_arch", since = "1.27.0")]
398-
#[doc(no_inline)]
398+
// The `no_inline`-attribute is required to make the documentation of all
399+
// targets available.
400+
// See https://github.com/rust-lang/rust/pull/57808#issuecomment-457390549 for
401+
// more information.
402+
#[doc(no_inline)] // Note (#82861): required for correct documentation
399403
pub use core::arch;
400404
#[stable(feature = "core_array", since = "1.36.0")]
401405
pub use core::array;

src/doc/unstable-book/src/compiler-flags/source-based-code-coverage.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -128,7 +128,7 @@ $ cargo profdata -- --help # note the additional "--" preceding the tool-specif
128128

129129
## Creating coverage reports
130130

131-
Raw profiles have to be indexed before they can be used to generate coverage reports. This is done using [`llvm-profdata merge`] (or `cargo cov -- merge`), which can combine multiple raw profiles and index them at the same time:
131+
Raw profiles have to be indexed before they can be used to generate coverage reports. This is done using [`llvm-profdata merge`] (or `cargo profdata -- merge`), which can combine multiple raw profiles and index them at the same time:
132132

133133
```shell
134134
$ llvm-profdata merge -sparse formatjson5.profraw -o formatjson5.profdata

src/librustdoc/Cargo.toml

+1-1
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ path = "lib.rs"
1010
[dependencies]
1111
arrayvec = { version = "0.5.1", default-features = false }
1212
pulldown-cmark = { version = "0.8", default-features = false }
13-
minifier = "0.0.33"
13+
minifier = "0.0.39"
1414
rayon = { version = "0.3.0", package = "rustc-rayon" }
1515
serde = { version = "1.0", features = ["derive"] }
1616
serde_json = "1.0"

0 commit comments

Comments
 (0)