Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit 19f42cb

Browse files
committedMar 28, 2025·
Auto merge of #139054 - matthiaskrgr:rollup-2bk2fb4, r=matthiaskrgr
Rollup of 7 pull requests Successful merges: - #137889 (update outdated doc with new example) - #138104 (Greatly simplify doctest parsing and information extraction) - #138678 (rustc_resolve: fix instability in lib.rmeta contents) - #138986 (feat(config): Add ChangeId enum for suppressing warnings) - #139038 (Update target maintainers for thumb targets to reflect new REWG Arm team name) - #139045 (bootstrap: update `test_find` test) - #139047 (Remove ScopeDepth) Failed merges: - #139044 (bootstrap: Avoid cloning `change-id` list) r? `@ghost` `@rustbot` modify labels: rollup
2 parents 2a06022 + 310bebc commit 19f42cb

File tree

30 files changed

+431
-473
lines changed

30 files changed

+431
-473
lines changed
 

‎Cargo.lock

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4300,6 +4300,7 @@ name = "rustc_resolve"
43004300
version = "0.0.0"
43014301
dependencies = [
43024302
"bitflags",
4303+
"itertools",
43034304
"pulldown-cmark 0.11.3",
43044305
"rustc_arena",
43054306
"rustc_ast",

‎bootstrap.example.toml

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,8 +28,9 @@
2828
# - A new option
2929
# - A change in the default values
3030
#
31-
# If `change-id` does not match the version that is currently running,
32-
# `x.py` will inform you about the changes made on bootstrap.
31+
# If the change-id does not match the version currently in use, x.py will
32+
# display the changes made to the bootstrap.
33+
# To suppress these warnings, you can set change-id = "ignore".
3334
#change-id = <latest change id in src/bootstrap/src/utils/change_tracker.rs>
3435

3536
# =============================================================================

‎compiler/rustc_hir_analysis/src/check/region.rs

Lines changed: 14 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -23,18 +23,11 @@ use tracing::debug;
2323

2424
#[derive(Debug, Copy, Clone)]
2525
struct Context {
26-
/// The scope that contains any new variables declared, plus its depth in
27-
/// the scope tree.
26+
/// The scope that contains any new variables declared.
2827
var_parent: Option<Scope>,
2928

30-
/// Region parent of expressions, etc., plus its depth in the scope tree.
31-
parent: Option<(Scope, ScopeDepth)>,
32-
}
33-
34-
impl Context {
35-
fn set_var_parent(&mut self) {
36-
self.var_parent = self.parent.map(|(p, _)| p);
37-
}
29+
/// Region parent of expressions, etc.
30+
parent: Option<Scope>,
3831
}
3932

4033
struct ScopeResolutionVisitor<'tcx> {
@@ -119,7 +112,7 @@ fn resolve_block<'tcx>(visitor: &mut ScopeResolutionVisitor<'tcx>, blk: &'tcx hi
119112
// itself has returned.
120113

121114
visitor.enter_node_scope_with_dtor(blk.hir_id.local_id);
122-
visitor.cx.set_var_parent();
115+
visitor.cx.var_parent = visitor.cx.parent;
123116

124117
{
125118
// This block should be kept approximately in sync with
@@ -138,7 +131,7 @@ fn resolve_block<'tcx>(visitor: &mut ScopeResolutionVisitor<'tcx>, blk: &'tcx hi
138131
local_id: blk.hir_id.local_id,
139132
data: ScopeData::Remainder(FirstStatementIndex::new(i)),
140133
});
141-
visitor.cx.set_var_parent();
134+
visitor.cx.var_parent = visitor.cx.parent;
142135
visitor.visit_stmt(statement);
143136
// We need to back out temporarily to the last enclosing scope
144137
// for the `else` block, so that even the temporaries receiving
@@ -163,7 +156,7 @@ fn resolve_block<'tcx>(visitor: &mut ScopeResolutionVisitor<'tcx>, blk: &'tcx hi
163156
local_id: blk.hir_id.local_id,
164157
data: ScopeData::Remainder(FirstStatementIndex::new(i)),
165158
});
166-
visitor.cx.set_var_parent();
159+
visitor.cx.var_parent = visitor.cx.parent;
167160
visitor.visit_stmt(statement)
168161
}
169162
hir::StmtKind::Item(..) => {
@@ -213,7 +206,7 @@ fn resolve_arm<'tcx>(visitor: &mut ScopeResolutionVisitor<'tcx>, arm: &'tcx hir:
213206
visitor.terminating_scopes.insert(arm.hir_id.local_id);
214207

215208
visitor.enter_node_scope_with_dtor(arm.hir_id.local_id);
216-
visitor.cx.set_var_parent();
209+
visitor.cx.var_parent = visitor.cx.parent;
217210

218211
if let Some(expr) = arm.guard
219212
&& !has_let_expr(expr)
@@ -490,7 +483,7 @@ fn resolve_expr<'tcx>(visitor: &mut ScopeResolutionVisitor<'tcx>, expr: &'tcx hi
490483
ScopeData::IfThen
491484
};
492485
visitor.enter_scope(Scope { local_id: then.hir_id.local_id, data });
493-
visitor.cx.set_var_parent();
486+
visitor.cx.var_parent = visitor.cx.parent;
494487
visitor.visit_expr(cond);
495488
visitor.visit_expr(then);
496489
visitor.cx = expr_cx;
@@ -505,7 +498,7 @@ fn resolve_expr<'tcx>(visitor: &mut ScopeResolutionVisitor<'tcx>, expr: &'tcx hi
505498
ScopeData::IfThen
506499
};
507500
visitor.enter_scope(Scope { local_id: then.hir_id.local_id, data });
508-
visitor.cx.set_var_parent();
501+
visitor.cx.var_parent = visitor.cx.parent;
509502
visitor.visit_expr(cond);
510503
visitor.visit_expr(then);
511504
visitor.cx = expr_cx;
@@ -545,7 +538,7 @@ fn resolve_expr<'tcx>(visitor: &mut ScopeResolutionVisitor<'tcx>, expr: &'tcx hi
545538
// Keep traversing up while we can.
546539
match visitor.scope_tree.parent_map.get(&scope) {
547540
// Don't cross from closure bodies to their parent.
548-
Some(&(superscope, _)) => match superscope.data {
541+
Some(&superscope) => match superscope.data {
549542
ScopeData::CallSite => break,
550543
_ => scope = superscope,
551544
},
@@ -781,20 +774,16 @@ fn resolve_local<'tcx>(
781774

782775
impl<'tcx> ScopeResolutionVisitor<'tcx> {
783776
/// Records the current parent (if any) as the parent of `child_scope`.
784-
/// Returns the depth of `child_scope`.
785-
fn record_child_scope(&mut self, child_scope: Scope) -> ScopeDepth {
777+
fn record_child_scope(&mut self, child_scope: Scope) {
786778
let parent = self.cx.parent;
787779
self.scope_tree.record_scope_parent(child_scope, parent);
788-
// If `child_scope` has no parent, it must be the root node, and so has
789-
// a depth of 1. Otherwise, its depth is one more than its parent's.
790-
parent.map_or(1, |(_p, d)| d + 1)
791780
}
792781

793782
/// Records the current parent (if any) as the parent of `child_scope`,
794783
/// and sets `child_scope` as the new current parent.
795784
fn enter_scope(&mut self, child_scope: Scope) {
796-
let child_depth = self.record_child_scope(child_scope);
797-
self.cx.parent = Some((child_scope, child_depth));
785+
self.record_child_scope(child_scope);
786+
self.cx.parent = Some(child_scope);
798787
}
799788

800789
fn enter_node_scope_with_dtor(&mut self, id: hir::ItemLocalId) {
@@ -855,7 +844,7 @@ impl<'tcx> Visitor<'tcx> for ScopeResolutionVisitor<'tcx> {
855844
self.enter_body(body.value.hir_id, |this| {
856845
if this.tcx.hir_body_owner_kind(owner_id).is_fn_or_closure() {
857846
// The arguments and `self` are parented to the fn.
858-
this.cx.set_var_parent();
847+
this.cx.var_parent = this.cx.parent;
859848
for param in body.params {
860849
this.visit_pat(param.pat);
861850
}

‎compiler/rustc_hir_analysis/src/check/wfcheck.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -188,10 +188,10 @@ fn check_well_formed(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Result<(), ErrorGua
188188
/// definition itself. For example, this definition would be illegal:
189189
///
190190
/// ```rust
191-
/// struct Ref<'a, T> { x: &'a T }
191+
/// struct StaticRef<T> { x: &'static T }
192192
/// ```
193193
///
194-
/// because the type did not declare that `T:'a`.
194+
/// because the type did not declare that `T: 'static`.
195195
///
196196
/// We do this check as a pre-pass before checking fn bodies because if these constraints are
197197
/// not included it frequently leads to confusing errors in fn bodies. So it's better to check

‎compiler/rustc_middle/src/middle/region.rs

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -199,8 +199,6 @@ impl Scope {
199199
}
200200
}
201201

202-
pub type ScopeDepth = u32;
203-
204202
/// The region scope tree encodes information about region relationships.
205203
#[derive(Default, Debug, HashStable)]
206204
pub struct ScopeTree {
@@ -213,7 +211,7 @@ pub struct ScopeTree {
213211
/// conditional expression or repeating block. (Note that the
214212
/// enclosing scope ID for the block associated with a closure is
215213
/// the closure itself.)
216-
pub parent_map: FxIndexMap<Scope, (Scope, ScopeDepth)>,
214+
pub parent_map: FxIndexMap<Scope, Scope>,
217215

218216
/// Maps from a variable or binding ID to the block in which that
219217
/// variable is declared.
@@ -328,7 +326,7 @@ pub struct YieldData {
328326
}
329327

330328
impl ScopeTree {
331-
pub fn record_scope_parent(&mut self, child: Scope, parent: Option<(Scope, ScopeDepth)>) {
329+
pub fn record_scope_parent(&mut self, child: Scope, parent: Option<Scope>) {
332330
debug!("{:?}.parent = {:?}", child, parent);
333331

334332
if let Some(p) = parent {
@@ -353,7 +351,7 @@ impl ScopeTree {
353351

354352
/// Returns the narrowest scope that encloses `id`, if any.
355353
pub fn opt_encl_scope(&self, id: Scope) -> Option<Scope> {
356-
self.parent_map.get(&id).cloned().map(|(p, _)| p)
354+
self.parent_map.get(&id).cloned()
357355
}
358356

359357
/// Returns the lifetime of the local variable `var_id`, if any.

‎compiler/rustc_middle/src/ty/rvalue_scopes.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ impl RvalueScopes {
3838
let mut id = Scope { local_id: expr_id, data: ScopeData::Node };
3939
let mut backwards_incompatible = None;
4040

41-
while let Some(&(p, _)) = region_scope_tree.parent_map.get(&id) {
41+
while let Some(&p) = region_scope_tree.parent_map.get(&id) {
4242
match p.data {
4343
ScopeData::Destruction => {
4444
debug!("temporary_scope({expr_id:?}) = {id:?} [enclosing]");

‎compiler/rustc_resolve/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ edition = "2024"
66
[dependencies]
77
# tidy-alphabetical-start
88
bitflags = "2.4.1"
9+
itertools = "0.12"
910
pulldown-cmark = { version = "0.11", features = ["html"], default-features = false }
1011
rustc_arena = { path = "../rustc_arena" }
1112
rustc_ast = { path = "../rustc_ast" }

‎compiler/rustc_resolve/src/rustdoc.rs

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,15 @@
11
use std::mem;
22
use std::ops::Range;
33

4+
use itertools::Itertools;
45
use pulldown_cmark::{
56
BrokenLink, BrokenLinkCallback, CowStr, Event, LinkType, Options, Parser, Tag,
67
};
78
use rustc_ast as ast;
89
use rustc_ast::attr::AttributeExt;
910
use rustc_ast::util::comments::beautify_doc_string;
10-
use rustc_data_structures::fx::{FxHashSet, FxIndexMap};
11+
use rustc_data_structures::fx::FxIndexMap;
12+
use rustc_data_structures::unord::UnordSet;
1113
use rustc_middle::ty::TyCtxt;
1214
use rustc_span::def_id::DefId;
1315
use rustc_span::{DUMMY_SP, InnerSpan, Span, Symbol, kw, sym};
@@ -422,7 +424,7 @@ fn parse_links<'md>(doc: &'md str) -> Vec<Box<str>> {
422424
);
423425
let mut links = Vec::new();
424426

425-
let mut refids = FxHashSet::default();
427+
let mut refids = UnordSet::default();
426428

427429
while let Some(event) = event_iter.next() {
428430
match event {
@@ -454,7 +456,7 @@ fn parse_links<'md>(doc: &'md str) -> Vec<Box<str>> {
454456
}
455457
}
456458

457-
for (label, refdef) in event_iter.reference_definitions().iter() {
459+
for (label, refdef) in event_iter.reference_definitions().iter().sorted_by_key(|x| x.0) {
458460
if !refids.contains(label) {
459461
links.push(preprocess_link(&refdef.dest));
460462
}

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

Lines changed: 41 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,8 @@ use std::str::FromStr;
1111
use std::{env, process};
1212

1313
use bootstrap::{
14-
Build, CONFIG_CHANGE_HISTORY, Config, Flags, Subcommand, debug, find_recent_config_change_ids,
15-
human_readable_changes, t,
14+
Build, CONFIG_CHANGE_HISTORY, ChangeId, Config, Flags, Subcommand, debug,
15+
find_recent_config_change_ids, human_readable_changes, t,
1616
};
1717
#[cfg(feature = "tracing")]
1818
use tracing::instrument;
@@ -155,50 +155,52 @@ fn check_version(config: &Config) -> Option<String> {
155155
let latest_change_id = CONFIG_CHANGE_HISTORY.last().unwrap().change_id;
156156
let warned_id_path = config.out.join("bootstrap").join(".last-warned-change-id");
157157

158-
if let Some(mut id) = config.change_id {
159-
if id == latest_change_id {
160-
return None;
158+
let mut id = match config.change_id {
159+
Some(ChangeId::Id(id)) if id == latest_change_id => return None,
160+
Some(ChangeId::Ignore) => return None,
161+
Some(ChangeId::Id(id)) => id,
162+
None => {
163+
msg.push_str("WARNING: The `change-id` is missing in the `bootstrap.toml`. This means that you will not be able to track the major changes made to the bootstrap configurations.\n");
164+
msg.push_str("NOTE: to silence this warning, ");
165+
msg.push_str(&format!(
166+
"add `change-id = {latest_change_id}` or change-id = \"ignore\" at the top of `bootstrap.toml`"
167+
));
168+
return Some(msg);
161169
}
170+
};
162171

163-
// Always try to use `change-id` from .last-warned-change-id first. If it doesn't exist,
164-
// then use the one from the bootstrap.toml. This way we never show the same warnings
165-
// more than once.
166-
if let Ok(t) = fs::read_to_string(&warned_id_path) {
167-
let last_warned_id = usize::from_str(&t)
168-
.unwrap_or_else(|_| panic!("{} is corrupted.", warned_id_path.display()));
169-
170-
// We only use the last_warned_id if it exists in `CONFIG_CHANGE_HISTORY`.
171-
// Otherwise, we may retrieve all the changes if it's not the highest value.
172-
// For better understanding, refer to `change_tracker::find_recent_config_change_ids`.
173-
if CONFIG_CHANGE_HISTORY.iter().any(|config| config.change_id == last_warned_id) {
174-
id = last_warned_id;
175-
}
176-
};
172+
// Always try to use `change-id` from .last-warned-change-id first. If it doesn't exist,
173+
// then use the one from the bootstrap.toml. This way we never show the same warnings
174+
// more than once.
175+
if let Ok(t) = fs::read_to_string(&warned_id_path) {
176+
let last_warned_id = usize::from_str(&t)
177+
.unwrap_or_else(|_| panic!("{} is corrupted.", warned_id_path.display()));
178+
179+
// We only use the last_warned_id if it exists in `CONFIG_CHANGE_HISTORY`.
180+
// Otherwise, we may retrieve all the changes if it's not the highest value.
181+
// For better understanding, refer to `change_tracker::find_recent_config_change_ids`.
182+
if CONFIG_CHANGE_HISTORY.iter().any(|config| config.change_id == last_warned_id) {
183+
id = last_warned_id;
184+
}
185+
};
177186

178-
let changes = find_recent_config_change_ids(id);
187+
let changes = find_recent_config_change_ids(id);
179188

180-
if changes.is_empty() {
181-
return None;
182-
}
189+
if changes.is_empty() {
190+
return None;
191+
}
183192

184-
msg.push_str("There have been changes to x.py since you last updated:\n");
185-
msg.push_str(&human_readable_changes(&changes));
193+
msg.push_str("There have been changes to x.py since you last updated:\n");
194+
msg.push_str(&human_readable_changes(&changes));
186195

187-
msg.push_str("NOTE: to silence this warning, ");
188-
msg.push_str(&format!(
189-
"update `bootstrap.toml` to use `change-id = {latest_change_id}` instead"
190-
));
196+
msg.push_str("NOTE: to silence this warning, ");
197+
msg.push_str(&format!(
198+
"update `bootstrap.toml` to use `change-id = {latest_change_id}` or change-id = \"ignore\" instead"
199+
));
191200

192-
if io::stdout().is_terminal() {
193-
t!(fs::write(warned_id_path, latest_change_id.to_string()));
194-
}
195-
} else {
196-
msg.push_str("WARNING: The `change-id` is missing in the `bootstrap.toml`. This means that you will not be able to track the major changes made to the bootstrap configurations.\n");
197-
msg.push_str("NOTE: to silence this warning, ");
198-
msg.push_str(&format!(
199-
"add `change-id = {latest_change_id}` at the top of `bootstrap.toml`"
200-
));
201-
};
201+
if io::stdout().is_terminal() {
202+
t!(fs::write(warned_id_path, latest_change_id.to_string()));
203+
}
202204

203205
Some(msg)
204206
}

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

Lines changed: 29 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -193,7 +193,7 @@ pub enum GccCiMode {
193193
/// `bootstrap.example.toml`.
194194
#[derive(Default, Clone)]
195195
pub struct Config {
196-
pub change_id: Option<usize>,
196+
pub change_id: Option<ChangeId>,
197197
pub bypass_bootstrap_lock: bool,
198198
pub ccache: Option<String>,
199199
/// Call Build::ninja() instead of this.
@@ -700,14 +700,36 @@ pub(crate) struct TomlConfig {
700700
profile: Option<String>,
701701
}
702702

703+
/// This enum is used for deserializing change IDs from TOML, allowing both numeric values and the string `"ignore"`.
704+
#[derive(Clone, Debug, PartialEq)]
705+
pub enum ChangeId {
706+
Ignore,
707+
Id(usize),
708+
}
709+
703710
/// Since we use `#[serde(deny_unknown_fields)]` on `TomlConfig`, we need a wrapper type
704711
/// for the "change-id" field to parse it even if other fields are invalid. This ensures
705712
/// that if deserialization fails due to other fields, we can still provide the changelogs
706713
/// to allow developers to potentially find the reason for the failure in the logs..
707714
#[derive(Deserialize, Default)]
708715
pub(crate) struct ChangeIdWrapper {
709-
#[serde(alias = "change-id")]
710-
pub(crate) inner: Option<usize>,
716+
#[serde(alias = "change-id", default, deserialize_with = "deserialize_change_id")]
717+
pub(crate) inner: Option<ChangeId>,
718+
}
719+
720+
fn deserialize_change_id<'de, D: Deserializer<'de>>(
721+
deserializer: D,
722+
) -> Result<Option<ChangeId>, D::Error> {
723+
let value = toml::Value::deserialize(deserializer)?;
724+
Ok(match value {
725+
toml::Value::String(s) if s == "ignore" => Some(ChangeId::Ignore),
726+
toml::Value::Integer(i) => Some(ChangeId::Id(i as usize)),
727+
_ => {
728+
return Err(serde::de::Error::custom(
729+
"expected \"ignore\" or an integer for change-id",
730+
));
731+
}
732+
})
711733
}
712734

713735
/// Describes how to handle conflicts in merging two [`TomlConfig`]
@@ -1351,10 +1373,11 @@ impl Config {
13511373
toml::from_str(&contents)
13521374
.and_then(|table: toml::Value| TomlConfig::deserialize(table))
13531375
.inspect_err(|_| {
1354-
if let Ok(Some(changes)) = toml::from_str(&contents)
1355-
.and_then(|table: toml::Value| ChangeIdWrapper::deserialize(table))
1356-
.map(|change_id| change_id.inner.map(crate::find_recent_config_change_ids))
1376+
if let Ok(ChangeIdWrapper { inner: Some(ChangeId::Id(id)) }) =
1377+
toml::from_str::<toml::Value>(&contents)
1378+
.and_then(|table: toml::Value| ChangeIdWrapper::deserialize(table))
13571379
{
1380+
let changes = crate::find_recent_config_change_ids(id);
13581381
if !changes.is_empty() {
13591382
println!(
13601383
"WARNING: There have been changes to x.py since you last updated:\n{}",

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

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ use serde::Deserialize;
1010

1111
use super::flags::Flags;
1212
use super::{ChangeIdWrapper, Config, RUSTC_IF_UNCHANGED_ALLOWED_PATHS};
13+
use crate::ChangeId;
1314
use crate::core::build_steps::clippy::{LintConfig, get_clippy_rules_in_order};
1415
use crate::core::build_steps::llvm;
1516
use crate::core::build_steps::llvm::LLVM_INVALIDATION_PATHS;
@@ -151,7 +152,7 @@ runner = "x86_64-runner"
151152
)
152153
},
153154
);
154-
assert_eq!(config.change_id, Some(1), "setting top-level value");
155+
assert_eq!(config.change_id, Some(ChangeId::Id(1)), "setting top-level value");
155156
assert_eq!(
156157
config.rust_lto,
157158
crate::core::config::RustcLto::Fat,
@@ -291,7 +292,7 @@ fn parse_change_id_with_unknown_field() {
291292
"#;
292293

293294
let change_id_wrapper: ChangeIdWrapper = toml::from_str(config).unwrap();
294-
assert_eq!(change_id_wrapper.inner, Some(3461));
295+
assert_eq!(change_id_wrapper.inner, Some(ChangeId::Id(3461)));
295296
}
296297

297298
#[test]

‎src/bootstrap/src/lib.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,8 +45,8 @@ mod core;
4545
mod utils;
4646

4747
pub use core::builder::PathSet;
48-
pub use core::config::Config;
4948
pub use core::config::flags::{Flags, Subcommand};
49+
pub use core::config::{ChangeId, Config};
5050

5151
#[cfg(feature = "tracing")]
5252
use tracing::{instrument, span};

‎src/bootstrap/src/utils/cc_detect/tests.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -264,7 +264,7 @@ fn test_find_target_without_config() {
264264
fn test_find() {
265265
let mut build = Build::new(Config { ..Config::parse(Flags::parse(&["check".to_owned()])) });
266266
let target1 = TargetSelection::from_user("x86_64-unknown-linux-gnu");
267-
let target2 = TargetSelection::from_user("arm-linux-androideabi");
267+
let target2 = TargetSelection::from_user("x86_64-unknown-openbsd");
268268
build.targets.push(target1.clone());
269269
build.hosts.push(target2.clone());
270270
find(&build);

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

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -390,4 +390,9 @@ pub const CONFIG_CHANGE_HISTORY: &[ChangeInfo] = &[
390390
severity: ChangeSeverity::Warning,
391391
summary: "The default configuration filename has changed from `config.toml` to `bootstrap.toml`. `config.toml` is deprecated but remains supported for backward compatibility.",
392392
},
393+
ChangeInfo {
394+
change_id: 138986,
395+
severity: ChangeSeverity::Info,
396+
summary: "You can now use `change-id = \"ignore\"` to suppress `change-id ` warnings in the console.",
397+
},
393398
];

‎src/doc/rustc/src/platform-support/thumbv6m-none-eabi.md

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,8 +26,7 @@ only option because there is no FPU support in [Armv6-M].
2626

2727
## Target maintainers
2828

29-
* [Rust Embedded Devices Working Group Cortex-M
30-
Team](https://github.com/rust-embedded), `cortex-m@teams.rust-embedded.org`
29+
* [Rust Embedded Devices Working Group Arm Team](https://github.com/rust-embedded/wg?tab=readme-ov-file#the-arm-team)
3130

3231
## Target CPU and Target Feature options
3332

‎src/doc/rustc/src/platform-support/thumbv7em-none-eabi.md

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,7 @@ See [`arm-none-eabi`](arm-none-eabi.md) for information applicable to all
2121

2222
## Target maintainers
2323

24-
* [Rust Embedded Devices Working Group Cortex-M
25-
Team](https://github.com/rust-embedded), `cortex-m@teams.rust-embedded.org`
24+
* [Rust Embedded Devices Working Group Arm Team](https://github.com/rust-embedded/wg?tab=readme-ov-file#the-arm-team)
2625

2726
## Target CPU and Target Feature options
2827

‎src/doc/rustc/src/platform-support/thumbv7m-none-eabi.md

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,8 +22,7 @@ only option because there is no FPU support in [Armv7-M].
2222

2323
## Target maintainers
2424

25-
* [Rust Embedded Devices Working Group Cortex-M
26-
Team](https://github.com/rust-embedded), `cortex-m@teams.rust-embedded.org`
25+
* [Rust Embedded Devices Working Group Arm Team](https://github.com/rust-embedded/wg?tab=readme-ov-file#the-arm-team)
2726

2827
## Target CPU and Target Feature options
2928

‎src/doc/rustc/src/platform-support/thumbv8m.base-none-eabi.md

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,8 +22,7 @@ only option because there is no FPU support in [Armv8-M] Baseline.
2222

2323
## Target maintainers
2424

25-
* [Rust Embedded Devices Working Group Cortex-M
26-
Team](https://github.com/rust-embedded), `cortex-m@teams.rust-embedded.org`
25+
* [Rust Embedded Devices Working Group Arm Team](https://github.com/rust-embedded/wg?tab=readme-ov-file#the-arm-team)
2726

2827
## Target CPU and Target Feature options
2928

‎src/doc/rustc/src/platform-support/thumbv8m.main-none-eabi.md

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,8 +25,7 @@ See [`arm-none-eabi`](arm-none-eabi.md) for information applicable to all
2525

2626
## Target maintainers
2727

28-
* [Rust Embedded Devices Working Group Cortex-M
29-
Team](https://github.com/rust-embedded), `cortex-m@teams.rust-embedded.org`
28+
* [Rust Embedded Devices Working Group Arm Team](https://github.com/rust-embedded/wg?tab=readme-ov-file#the-arm-team)
3029

3130
## Target CPU and Target Feature options
3231

‎src/librustdoc/doctest/make.rs

Lines changed: 191 additions & 355 deletions
Large diffs are not rendered by default.

‎src/librustdoc/doctest/tests.rs

Lines changed: 76 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -197,6 +197,7 @@ fn make_test_crate_attrs() {
197197
assert_eq!(2+2, 4);";
198198
let expected = "#![allow(unused)]
199199
#![feature(sick_rad)]
200+
200201
fn main() {
201202
assert_eq!(2+2, 4);
202203
}"
@@ -228,8 +229,8 @@ fn make_test_fake_main() {
228229
let input = "//Ceci n'est pas une `fn main`
229230
assert_eq!(2+2, 4);";
230231
let expected = "#![allow(unused)]
231-
//Ceci n'est pas une `fn main`
232232
fn main() {
233+
//Ceci n'est pas une `fn main`
233234
assert_eq!(2+2, 4);
234235
}"
235236
.to_string();
@@ -259,8 +260,8 @@ fn make_test_issues_21299() {
259260
assert_eq!(2+2, 4);";
260261

261262
let expected = "#![allow(unused)]
262-
// fn main
263263
fn main() {
264+
// fn main
264265
assert_eq!(2+2, 4);
265266
}"
266267
.to_string();
@@ -401,3 +402,76 @@ fn check_split_args() {
401402
compare("a\n\t \rb", &["a", "b"]);
402403
compare("a\n\t1 \rb", &["a", "1", "b"]);
403404
}
405+
406+
#[test]
407+
fn comment_in_attrs() {
408+
// If there is an inline code comment after attributes, we need to ensure that
409+
// a backline will be added to prevent generating code "inside" it (and thus generating)
410+
// invalid code.
411+
let opts = default_global_opts("");
412+
let input = "\
413+
#![feature(rustdoc_internals)]
414+
#![allow(internal_features)]
415+
#![doc(rust_logo)]
416+
//! This crate has the Rust(tm) branding on it.";
417+
let expected = "\
418+
#![allow(unused)]
419+
#![feature(rustdoc_internals)]
420+
#![allow(internal_features)]
421+
#![doc(rust_logo)]
422+
//! This crate has the Rust(tm) branding on it.
423+
fn main() {
424+
425+
}"
426+
.to_string();
427+
let (output, len) = make_test(input, None, false, &opts, None);
428+
assert_eq!((output, len), (expected, 2));
429+
430+
// And same, if there is a `main` function provided by the user, we ensure that it's
431+
// correctly separated.
432+
let input = "\
433+
#![feature(rustdoc_internals)]
434+
#![allow(internal_features)]
435+
#![doc(rust_logo)]
436+
//! This crate has the Rust(tm) branding on it.
437+
fn main() {}";
438+
let expected = "\
439+
#![allow(unused)]
440+
#![feature(rustdoc_internals)]
441+
#![allow(internal_features)]
442+
#![doc(rust_logo)]
443+
//! This crate has the Rust(tm) branding on it.
444+
445+
fn main() {}"
446+
.to_string();
447+
let (output, len) = make_test(input, None, false, &opts, None);
448+
assert_eq!((output, len), (expected, 1));
449+
}
450+
451+
// This test ensures that the only attributes taken into account when we switch between
452+
// "crate level" content and the rest doesn't include inner attributes span, as it would
453+
// include part of the item and generate broken code.
454+
#[test]
455+
fn inner_attributes() {
456+
let opts = default_global_opts("");
457+
let input = r#"
458+
//! A doc comment that applies to the implicit anonymous module of this crate
459+
460+
pub mod outer_module {
461+
//!! - Still an inner line doc (but with a bang at the beginning)
462+
}
463+
"#;
464+
let expected = "#![allow(unused)]
465+
466+
//! A doc comment that applies to the implicit anonymous module of this crate
467+
468+
469+
fn main() {
470+
pub mod outer_module {
471+
//!! - Still an inner line doc (but with a bang at the beginning)
472+
}
473+
}"
474+
.to_string();
475+
let (output, len) = make_test(input, None, false, &opts, None);
476+
assert_eq!((output, len), (expected, 2));
477+
}

‎src/librustdoc/html/markdown.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1724,6 +1724,7 @@ pub(crate) fn markdown_links<'md, R>(
17241724
md: &'md str,
17251725
preprocess_link: impl Fn(MarkdownLink) -> Option<R>,
17261726
) -> Vec<R> {
1727+
use itertools::Itertools;
17271728
if md.is_empty() {
17281729
return vec![];
17291730
}
@@ -1882,7 +1883,7 @@ pub(crate) fn markdown_links<'md, R>(
18821883
let mut links = Vec::new();
18831884

18841885
let mut refdefs = FxIndexMap::default();
1885-
for (label, refdef) in event_iter.reference_definitions().iter() {
1886+
for (label, refdef) in event_iter.reference_definitions().iter().sorted_by_key(|x| x.0) {
18861887
refdefs.insert(label.to_string(), (false, refdef.dest.to_string(), refdef.span.clone()));
18871888
}
18881889

‎tests/coverage-run-rustdoc/doctest.coverage

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -58,21 +58,21 @@ $DIR/doctest.rs:
5858
LL| |//!
5959
LL| |//! doctest with custom main:
6060
LL| |//! ```
61-
LL| 1|//! fn some_func() {
62-
LL| 1|//! println!("called some_func()");
63-
LL| 1|//! }
64-
LL| |//!
65-
LL| |//! #[derive(Debug)]
66-
LL| |//! struct SomeError;
61+
LL| |//! fn some_func() {
62+
LL| |//! println!("called some_func()");
63+
LL| |//! }
64+
LL| 1|//!
65+
LL| 1|//! #[derive(Debug)]
66+
LL| 1|//! struct SomeError;
6767
LL| |//!
6868
LL| |//! extern crate doctest_crate;
6969
LL| |//!
70-
LL| 1|//! fn doctest_main() -> Result<(), SomeError> {
70+
LL| |//! fn doctest_main() -> Result<(), SomeError> {
7171
LL| 1|//! some_func();
7272
LL| 1|//! doctest_crate::fn_run_in_doctests(2);
7373
LL| 1|//! Ok(())
7474
LL| 1|//! }
75-
LL| |//!
75+
LL| 1|//!
7676
LL| |//! // this `main` is not shown as covered, as it clashes with all the other
7777
LL| |//! // `main` functions that were automatically generated for doctests
7878
LL| |//! fn main() -> Result<(), SomeError> {

‎tests/run-make/rustdoc-error-lines/rmake.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,11 +8,11 @@ fn main() {
88

99
let should_contain = &[
1010
"input.rs - foo (line 5)",
11-
"input.rs:7:15",
11+
"input.rs:8:15",
1212
"input.rs - bar (line 13)",
13-
"input.rs:15:15",
13+
"input.rs:16:15",
1414
"input.rs - bar (line 22)",
15-
"input.rs:24:15",
15+
"input.rs:25:15",
1616
];
1717
for text in should_contain {
1818
assert!(output.contains(text), "output doesn't contains {:?}", text);

‎tests/rustdoc-ui/doctest/display-output.stdout

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ successes:
66

77
---- $DIR/display-output.rs - foo (line 9) stdout ----
88
warning: unused variable: `x`
9-
--> $DIR/display-output.rs:11:5
9+
--> $DIR/display-output.rs:12:5
1010
|
1111
LL | let x = 12;
1212
| ^ help: if this is intentional, prefix it with an underscore: `_x`
@@ -19,13 +19,13 @@ LL | #![warn(unused)]
1919
= note: `#[warn(unused_variables)]` implied by `#[warn(unused)]`
2020

2121
warning: unused variable: `x`
22-
--> $DIR/display-output.rs:13:8
22+
--> $DIR/display-output.rs:14:8
2323
|
2424
LL | fn foo(x: &dyn std::fmt::Display) {}
2525
| ^ help: if this is intentional, prefix it with an underscore: `_x`
2626

2727
warning: function `foo` is never used
28-
--> $DIR/display-output.rs:13:4
28+
--> $DIR/display-output.rs:14:4
2929
|
3030
LL | fn foo(x: &dyn std::fmt::Display) {}
3131
| ^^^
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
//@ check-pass
2+
//@ compile-flags:--test --test-args=--test-threads=1
3+
//@ normalize-stdout: "tests/rustdoc-ui/doctest" -> "$$DIR"
4+
//@ normalize-stdout: "finished in \d+\.\d+s" -> "finished in $$TIME"
5+
6+
// This test ensures that crate imports are placed outside of the `main` function
7+
// so they work all the time (even in 2015 edition).
8+
9+
/// ```rust
10+
/// #![feature(test)]
11+
///
12+
/// extern crate test;
13+
/// use test::Bencher;
14+
///
15+
/// #[bench]
16+
/// fn bench_xor_1000_ints(b: &mut Bencher) {
17+
/// b.iter(|| {
18+
/// (0..1000).fold(0, |old, new| old ^ new);
19+
/// });
20+
/// }
21+
/// ```
22+
///
23+
pub fn foo() {}
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
2+
running 1 test
3+
test $DIR/extern-crate.rs - foo (line 9) ... ok
4+
5+
test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in $TIME
6+
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
{"format_version":1,"doctests":[{"file":"$DIR/extract-doctests.rs","line":8,"doctest_attributes":{"original":"ignore (checking attributes)","should_panic":false,"no_run":false,"ignore":"All","rust":true,"test_harness":false,"compile_fail":false,"standalone_crate":false,"error_codes":[],"edition":null,"added_css_classes":[],"unknown":[]},"original_code":"let x = 12;\nlet y = 14;","doctest_code":"#![allow(unused)]\nfn main() {\nlet x = 12;\nlet y = 14;\n}","name":"$DIR/extract-doctests.rs - (line 8)"},{"file":"$DIR/extract-doctests.rs","line":13,"doctest_attributes":{"original":"edition2018,compile_fail","should_panic":false,"no_run":true,"ignore":"None","rust":true,"test_harness":false,"compile_fail":true,"standalone_crate":false,"error_codes":[],"edition":"2018","added_css_classes":[],"unknown":[]},"original_code":"let","doctest_code":"#![allow(unused)]\nfn main() {\nlet\n}","name":"$DIR/extract-doctests.rs - (line 13)"}]}
1+
{"format_version":1,"doctests":[{"file":"$DIR/extract-doctests.rs","line":8,"doctest_attributes":{"original":"ignore (checking attributes)","should_panic":false,"no_run":false,"ignore":"All","rust":true,"test_harness":false,"compile_fail":false,"standalone_crate":false,"error_codes":[],"edition":null,"added_css_classes":[],"unknown":[]},"original_code":"let x = 12;\nlet y = 14;","doctest_code":"#![allow(unused)]\nfn main() {\nlet x = 12;\nlet y = 14;\n}","name":"$DIR/extract-doctests.rs - (line 8)"},{"file":"$DIR/extract-doctests.rs","line":13,"doctest_attributes":{"original":"edition2018,compile_fail","should_panic":false,"no_run":true,"ignore":"None","rust":true,"test_harness":false,"compile_fail":true,"standalone_crate":false,"error_codes":[],"edition":"2018","added_css_classes":[],"unknown":[]},"original_code":"let","doctest_code":null,"name":"$DIR/extract-doctests.rs - (line 13)"}]}

‎tests/rustdoc-ui/remap-path-prefix-invalid-doctest.stdout

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,11 @@ test remapped_path/remap-path-prefix-invalid-doctest.rs - SomeStruct (line 10) .
55
failures:
66

77
---- remapped_path/remap-path-prefix-invalid-doctest.rs - SomeStruct (line 10) stdout ----
8-
error: expected one of `!`, `.`, `::`, `;`, `?`, `{`, `}`, or an operator, found `is`
8+
error: expected one of `!` or `::`, found `is`
99
--> remapped_path/remap-path-prefix-invalid-doctest.rs:11:6
1010
|
1111
LL | this is not real code
12-
| ^^ expected one of 8 possible tokens
12+
| ^^ expected one of `!` or `::`
1313

1414
error: aborting due to 1 previous error
1515

‎tests/rustdoc/playground.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,4 +24,4 @@
2424
2525
//@ matches foo/index.html '//a[@class="test-arrow"][@href="https://www.example.com/?code=%23!%5Ballow(unused)%5D%0Afn+main()+%7B%0A++++println!(%22Hello,+world!%22);%0A%7D&edition=2015"]' ""
2626
//@ matches foo/index.html '//a[@class="test-arrow"][@href="https://www.example.com/?code=%23!%5Ballow(unused)%5D%0Afn+main()+%7B%0A++++println!(%22Hello,+world!%22);%0A%7D&edition=2015"]' ""
27-
//@ matches foo/index.html '//a[@class="test-arrow"][@href="https://www.example.com/?code=%23!%5Ballow(unused)%5D%0A%23!%5Bfeature(something)%5D%0A%0Afn+main()+%7B%0A++++println!(%22Hello,+world!%22);%0A%7D&version=nightly&edition=2015"]' ""
27+
//@ matches foo/index.html '//a[@class="test-arrow"][@href="https://www.example.com/?code=%23!%5Ballow(unused)%5D%0A%23!%5Bfeature(something)%5D%0A%0A%0Afn+main()+%7B%0A++++println!(%22Hello,+world!%22);%0A%7D&version=nightly&edition=2015"]' ""

0 commit comments

Comments
 (0)
Please sign in to comment.