Skip to content

Commit 35dfc67

Browse files
committedMar 17, 2024·
Auto merge of rust-lang#122637 - matthiaskrgr:rollup-bczj5bp, r=matthiaskrgr
Rollup of 3 pull requests Successful merges: - rust-lang#121236 (Don't show suggestion if slice pattern is not top-level) - rust-lang#121787 (run change tracker even when config parse fails) - rust-lang#122633 (avoid unnecessary collect()) r? `@ghost` `@rustbot` modify labels: rollup
2 parents a0c20d5 + 1213746 commit 35dfc67

File tree

9 files changed

+137
-31
lines changed

9 files changed

+137
-31
lines changed
 

‎compiler/rustc_hir_analysis/src/astconv/errors.rs

+1-4
Original file line numberDiff line numberDiff line change
@@ -408,10 +408,7 @@ impl<'tcx> dyn AstConv<'tcx> + '_ {
408408
traits with associated type `{name}`, you could use the \
409409
fully-qualified path",
410410
),
411-
traits
412-
.iter()
413-
.map(|trait_str| format!("<Example as {trait_str}>::{name}"))
414-
.collect::<Vec<_>>(),
411+
traits.iter().map(|trait_str| format!("<Example as {trait_str}>::{name}")),
415412
Applicability::HasPlaceholders,
416413
);
417414
}

‎compiler/rustc_hir_typeck/src/pat.rs

+27-13
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,9 @@ struct PatInfo<'tcx, 'a> {
8383
binding_mode: BindingMode,
8484
top_info: TopInfo<'tcx>,
8585
decl_origin: Option<DeclOrigin<'a>>,
86+
87+
/// The depth of current pattern
88+
current_depth: u32,
8689
}
8790

8891
impl<'tcx> FnCtxt<'_, 'tcx> {
@@ -152,7 +155,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
152155
decl_origin: Option<DeclOrigin<'tcx>>,
153156
) {
154157
let info = TopInfo { expected, origin_expr, span };
155-
let pat_info = PatInfo { binding_mode: INITIAL_BM, top_info: info, decl_origin };
158+
let pat_info =
159+
PatInfo { binding_mode: INITIAL_BM, top_info: info, decl_origin, current_depth: 0 };
156160
self.check_pat(pat, expected, pat_info);
157161
}
158162

@@ -163,7 +167,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
163167
/// Conversely, inside this module, `check_pat_top` should never be used.
164168
#[instrument(level = "debug", skip(self, pat_info))]
165169
fn check_pat(&self, pat: &'tcx Pat<'tcx>, expected: Ty<'tcx>, pat_info: PatInfo<'tcx, '_>) {
166-
let PatInfo { binding_mode: def_bm, top_info: ti, .. } = pat_info;
170+
let PatInfo { binding_mode: def_bm, top_info: ti, current_depth, .. } = pat_info;
171+
167172
let path_res = match &pat.kind {
168173
PatKind::Path(qpath) => Some(
169174
self.resolve_ty_and_res_fully_qualified_call(qpath, pat.hir_id, pat.span, None),
@@ -172,8 +177,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
172177
};
173178
let adjust_mode = self.calc_adjust_mode(pat, path_res.map(|(res, ..)| res));
174179
let (expected, def_bm) = self.calc_default_binding_mode(pat, expected, def_bm, adjust_mode);
175-
let pat_info =
176-
PatInfo { binding_mode: def_bm, top_info: ti, decl_origin: pat_info.decl_origin };
180+
let pat_info = PatInfo {
181+
binding_mode: def_bm,
182+
top_info: ti,
183+
decl_origin: pat_info.decl_origin,
184+
current_depth: current_depth + 1,
185+
};
177186

178187
let ty = match pat.kind {
179188
PatKind::Wild | PatKind::Err(_) => expected,
@@ -1046,14 +1055,14 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
10461055
expected: Ty<'tcx>,
10471056
pat_info: PatInfo<'tcx, '_>,
10481057
) -> Ty<'tcx> {
1049-
let PatInfo { binding_mode: def_bm, top_info: ti, decl_origin } = pat_info;
1058+
let PatInfo { binding_mode: def_bm, top_info: ti, decl_origin, current_depth } = pat_info;
10501059
let tcx = self.tcx;
10511060
let on_error = |e| {
10521061
for pat in subpats {
10531062
self.check_pat(
10541063
pat,
10551064
Ty::new_error(tcx, e),
1056-
PatInfo { binding_mode: def_bm, top_info: ti, decl_origin },
1065+
PatInfo { binding_mode: def_bm, top_info: ti, decl_origin, current_depth },
10571066
);
10581067
}
10591068
};
@@ -1120,7 +1129,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
11201129
self.check_pat(
11211130
subpat,
11221131
field_ty,
1123-
PatInfo { binding_mode: def_bm, top_info: ti, decl_origin },
1132+
PatInfo { binding_mode: def_bm, top_info: ti, decl_origin, current_depth },
11241133
);
11251134

11261135
self.tcx.check_stability(
@@ -2134,7 +2143,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
21342143
// The expected type must be an array or slice, but was neither, so error.
21352144
_ => {
21362145
let guar = expected.error_reported().err().unwrap_or_else(|| {
2137-
self.error_expected_array_or_slice(span, expected, pat_info.top_info)
2146+
self.error_expected_array_or_slice(span, expected, pat_info)
21382147
});
21392148
let err = Ty::new_error(self.tcx, guar);
21402149
(err, Some(err), err)
@@ -2273,8 +2282,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
22732282
&self,
22742283
span: Span,
22752284
expected_ty: Ty<'tcx>,
2276-
ti: TopInfo<'tcx>,
2285+
pat_info: PatInfo<'tcx, '_>,
22772286
) -> ErrorGuaranteed {
2287+
let PatInfo { top_info: ti, current_depth, .. } = pat_info;
2288+
22782289
let mut err = struct_span_code_err!(
22792290
self.dcx(),
22802291
span,
@@ -2292,9 +2303,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
22922303
&& let Some(_) = ti.origin_expr
22932304
&& let Ok(snippet) = self.tcx.sess.source_map().span_to_snippet(span)
22942305
{
2295-
let ty = self.resolve_vars_if_possible(ti.expected);
2296-
let is_slice_or_array_or_vector = self.is_slice_or_array_or_vector(ty);
2297-
match is_slice_or_array_or_vector.1.kind() {
2306+
let resolved_ty = self.resolve_vars_if_possible(ti.expected);
2307+
let (is_slice_or_array_or_vector, resolved_ty) =
2308+
self.is_slice_or_array_or_vector(resolved_ty);
2309+
match resolved_ty.kind() {
22982310
ty::Adt(adt_def, _)
22992311
if self.tcx.is_diagnostic_item(sym::Option, adt_def.did())
23002312
|| self.tcx.is_diagnostic_item(sym::Result, adt_def.did()) =>
@@ -2309,7 +2321,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
23092321
}
23102322
_ => (),
23112323
}
2312-
if is_slice_or_array_or_vector.0 {
2324+
2325+
let is_top_level = current_depth <= 1;
2326+
if is_slice_or_array_or_vector && is_top_level {
23132327
err.span_suggestion(
23142328
span,
23152329
"consider slicing here",

‎src/bootstrap/src/bin/main.rs

+3-9
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,8 @@ use std::{
1515
};
1616

1717
use bootstrap::{
18-
find_recent_config_change_ids, t, Build, Config, Subcommand, CONFIG_CHANGE_HISTORY,
18+
find_recent_config_change_ids, human_readable_changes, t, Build, Config, Subcommand,
19+
CONFIG_CHANGE_HISTORY,
1920
};
2021

2122
fn main() {
@@ -164,14 +165,7 @@ fn check_version(config: &Config) -> Option<String> {
164165
}
165166

166167
msg.push_str("There have been changes to x.py since you last updated:\n");
167-
168-
for change in changes {
169-
msg.push_str(&format!(" [{}] {}\n", change.severity, change.summary));
170-
msg.push_str(&format!(
171-
" - PR Link https://github.com/rust-lang/rust/pull/{}\n",
172-
change.change_id
173-
));
174-
}
168+
msg.push_str(&human_readable_changes(&changes));
175169

176170
msg.push_str("NOTE: to silence this warning, ");
177171
msg.push_str(&format!(

‎src/bootstrap/src/core/config/config.rs

+28-3
Original file line numberDiff line numberDiff line change
@@ -606,7 +606,8 @@ impl Target {
606606
#[serde(deny_unknown_fields, rename_all = "kebab-case")]
607607
pub(crate) struct TomlConfig {
608608
changelog_seen: Option<usize>, // FIXME: Deprecated field. Remove it at 2024.
609-
change_id: Option<usize>,
609+
#[serde(flatten)]
610+
change_id: ChangeIdWrapper,
610611
build: Option<Build>,
611612
install: Option<Install>,
612613
llvm: Option<Llvm>,
@@ -616,6 +617,16 @@ pub(crate) struct TomlConfig {
616617
profile: Option<String>,
617618
}
618619

620+
/// Since we use `#[serde(deny_unknown_fields)]` on `TomlConfig`, we need a wrapper type
621+
/// for the "change-id" field to parse it even if other fields are invalid. This ensures
622+
/// that if deserialization fails due to other fields, we can still provide the changelogs
623+
/// to allow developers to potentially find the reason for the failure in the logs..
624+
#[derive(Deserialize, Default)]
625+
pub(crate) struct ChangeIdWrapper {
626+
#[serde(alias = "change-id")]
627+
pub(crate) inner: Option<usize>,
628+
}
629+
619630
/// Describes how to handle conflicts in merging two [`TomlConfig`]
620631
#[derive(Copy, Clone, Debug)]
621632
enum ReplaceOpt {
@@ -657,7 +668,7 @@ impl Merge for TomlConfig {
657668
}
658669
}
659670
self.changelog_seen.merge(changelog_seen, replace);
660-
self.change_id.merge(change_id, replace);
671+
self.change_id.inner.merge(change_id.inner, replace);
661672
do_merge(&mut self.build, build, replace);
662673
do_merge(&mut self.install, install, replace);
663674
do_merge(&mut self.llvm, llvm, replace);
@@ -1210,6 +1221,20 @@ impl Config {
12101221
toml::from_str(&contents)
12111222
.and_then(|table: toml::Value| TomlConfig::deserialize(table))
12121223
.unwrap_or_else(|err| {
1224+
if let Ok(Some(changes)) = toml::from_str(&contents)
1225+
.and_then(|table: toml::Value| ChangeIdWrapper::deserialize(table))
1226+
.and_then(|change_id| {
1227+
Ok(change_id.inner.map(|id| crate::find_recent_config_change_ids(id)))
1228+
})
1229+
{
1230+
if !changes.is_empty() {
1231+
println!(
1232+
"WARNING: There have been changes to x.py since you last updated:\n{}",
1233+
crate::human_readable_changes(&changes)
1234+
);
1235+
}
1236+
}
1237+
12131238
eprintln!("failed to parse TOML configuration '{}': {err}", file.display());
12141239
exit!(2);
12151240
})
@@ -1376,7 +1401,7 @@ impl Config {
13761401
toml.merge(override_toml, ReplaceOpt::Override);
13771402

13781403
config.changelog_seen = toml.changelog_seen;
1379-
config.change_id = toml.change_id;
1404+
config.change_id = toml.change_id.inner;
13801405

13811406
let Build {
13821407
build,

‎src/bootstrap/src/core/config/tests.rs

+18-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use super::{flags::Flags, Config};
1+
use super::{flags::Flags, ChangeIdWrapper, Config};
22
use crate::core::config::{LldMode, TomlConfig};
33

44
use clap::CommandFactory;
@@ -237,3 +237,20 @@ fn rust_lld() {
237237
assert!(matches!(parse("rust.use-lld = true").lld_mode, LldMode::External));
238238
assert!(matches!(parse("rust.use-lld = false").lld_mode, LldMode::Unused));
239239
}
240+
241+
#[test]
242+
#[should_panic]
243+
fn parse_config_with_unknown_field() {
244+
parse("unknown-key = 1");
245+
}
246+
247+
#[test]
248+
fn parse_change_id_with_unknown_field() {
249+
let config = r#"
250+
change-id = 3461
251+
unknown-key = 1
252+
"#;
253+
254+
let change_id_wrapper: ChangeIdWrapper = toml::from_str(config).unwrap();
255+
assert_eq!(change_id_wrapper.inner, Some(3461));
256+
}

‎src/bootstrap/src/lib.rs

+3-1
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,9 @@ mod utils;
5050
pub use core::builder::PathSet;
5151
pub use core::config::flags::Subcommand;
5252
pub use core::config::Config;
53-
pub use utils::change_tracker::{find_recent_config_change_ids, CONFIG_CHANGE_HISTORY};
53+
pub use utils::change_tracker::{
54+
find_recent_config_change_ids, human_readable_changes, CONFIG_CHANGE_HISTORY,
55+
};
5456

5557
const LLVM_TOOLS: &[&str] = &[
5658
"llvm-cov", // used to generate coverage report

‎src/bootstrap/src/utils/change_tracker.rs

+14
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,20 @@ pub fn find_recent_config_change_ids(current_id: usize) -> Vec<ChangeInfo> {
6060
.collect()
6161
}
6262

63+
pub fn human_readable_changes(changes: &[ChangeInfo]) -> String {
64+
let mut message = String::new();
65+
66+
for change in changes {
67+
message.push_str(&format!(" [{}] {}\n", change.severity, change.summary));
68+
message.push_str(&format!(
69+
" - PR Link https://github.com/rust-lang/rust/pull/{}\n",
70+
change.change_id
71+
));
72+
}
73+
74+
message
75+
}
76+
6377
/// Keeps track of major changes made to the bootstrap configuration.
6478
///
6579
/// If you make any major changes (such as adding new values or changing default values),
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
pub struct Struct {
2+
a: Vec<Struct>,
3+
}
4+
5+
impl Struct {
6+
pub fn test(&self) {
7+
if let [Struct { a: [] }] = &self.a {
8+
//~^ ERROR expected an array or slice
9+
//~| ERROR expected an array or slice
10+
println!("matches!")
11+
}
12+
13+
if let [Struct { a: [] }] = &self.a[..] {
14+
//~^ ERROR expected an array or slice
15+
println!("matches!")
16+
}
17+
}
18+
}
19+
20+
fn main() {}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
error[E0529]: expected an array or slice, found `Vec<Struct>`
2+
--> $DIR/suppress-consider-slicing-issue-120605.rs:7:16
3+
|
4+
LL | if let [Struct { a: [] }] = &self.a {
5+
| ^^^^^^^^^^^^^^^^^^ ------- help: consider slicing here: `&self.a[..]`
6+
| |
7+
| pattern cannot match with input type `Vec<Struct>`
8+
9+
error[E0529]: expected an array or slice, found `Vec<Struct>`
10+
--> $DIR/suppress-consider-slicing-issue-120605.rs:7:29
11+
|
12+
LL | if let [Struct { a: [] }] = &self.a {
13+
| ^^ pattern cannot match with input type `Vec<Struct>`
14+
15+
error[E0529]: expected an array or slice, found `Vec<Struct>`
16+
--> $DIR/suppress-consider-slicing-issue-120605.rs:13:29
17+
|
18+
LL | if let [Struct { a: [] }] = &self.a[..] {
19+
| ^^ pattern cannot match with input type `Vec<Struct>`
20+
21+
error: aborting due to 3 previous errors
22+
23+
For more information about this error, try `rustc --explain E0529`.

0 commit comments

Comments
 (0)
Please sign in to comment.