Skip to content

Commit aa5832b

Browse files
committedMay 30, 2025·
Auto merge of #141765 - matthiaskrgr:rollup-4hug83b, r=matthiaskrgr
Rollup of 5 pull requests Successful merges: - #141703 (Structurally normalize types as needed in `projection_ty_core`) - #141719 (Add tls_model for cygwin and enable has_thread_local) - #141736 (resolve stage0 sysroot from rustc) - #141746 (Rework `#[doc(cfg(..))]` checks as distinct pass in rustdoc) - #141749 (Remove RUSTC_RETRY_LINKER_ON_SEGFAULT hack) r? `@ghost` `@rustbot` modify labels: rollup
2 parents e6152cd + 4fce906 commit aa5832b

File tree

19 files changed

+251
-169
lines changed

19 files changed

+251
-169
lines changed
 

‎compiler/rustc_borrowck/src/type_check/mod.rs

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -474,17 +474,18 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
474474
let projected_ty = curr_projected_ty.projection_ty_core(
475475
tcx,
476476
proj,
477-
|this, field, ()| {
478-
let ty = this.field_ty(tcx, field);
479-
self.structurally_resolve(ty, locations)
480-
},
481-
|_, _| unreachable!(),
477+
|ty| self.structurally_resolve(ty, locations),
478+
|ty, variant_index, field, ()| PlaceTy::field_ty(tcx, ty, variant_index, field),
479+
|_| unreachable!(),
482480
);
483481
curr_projected_ty = projected_ty;
484482
}
485483
trace!(?curr_projected_ty);
486484

487-
let ty = curr_projected_ty.ty;
485+
// Need to renormalize `a` as typecheck may have failed to normalize
486+
// higher-ranked aliases if normalization was ambiguous due to inference.
487+
let a = self.normalize(a, locations);
488+
let ty = self.normalize(curr_projected_ty.ty, locations);
488489
self.relate_types(ty, v.xform(ty::Contravariant), a, locations, category)?;
489490

490491
Ok(())
@@ -1852,7 +1853,7 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> {
18521853
| ProjectionElem::Downcast(..) => {}
18531854
ProjectionElem::Field(field, fty) => {
18541855
let fty = self.normalize(fty, location);
1855-
let ty = base_ty.field_ty(tcx, field);
1856+
let ty = PlaceTy::field_ty(tcx, base_ty.ty, base_ty.variant_index, field);
18561857
let ty = self.normalize(ty, location);
18571858
debug!(?fty, ?ty);
18581859

‎compiler/rustc_codegen_ssa/src/back/link.rs

Lines changed: 2 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ use std::fs::{File, OpenOptions, read};
66
use std::io::{BufWriter, Write};
77
use std::ops::{ControlFlow, Deref};
88
use std::path::{Path, PathBuf};
9-
use std::process::{ExitStatus, Output, Stdio};
9+
use std::process::{Output, Stdio};
1010
use std::{env, fmt, fs, io, mem, str};
1111

1212
use cc::windows_registry;
@@ -736,13 +736,10 @@ fn link_natively(
736736

737737
// Invoke the system linker
738738
info!("{cmd:?}");
739-
let retry_on_segfault = env::var("RUSTC_RETRY_LINKER_ON_SEGFAULT").is_ok();
740739
let unknown_arg_regex =
741740
Regex::new(r"(unknown|unrecognized) (command line )?(option|argument)").unwrap();
742741
let mut prog;
743-
let mut i = 0;
744742
loop {
745-
i += 1;
746743
prog = sess.time("run_linker", || exec_linker(sess, &cmd, out_filename, flavor, tmpdir));
747744
let Ok(ref output) = prog else {
748745
break;
@@ -858,54 +855,7 @@ fn link_natively(
858855
continue;
859856
}
860857

861-
// Here's a terribly awful hack that really shouldn't be present in any
862-
// compiler. Here an environment variable is supported to automatically
863-
// retry the linker invocation if the linker looks like it segfaulted.
864-
//
865-
// Gee that seems odd, normally segfaults are things we want to know
866-
// about! Unfortunately though in rust-lang/rust#38878 we're
867-
// experiencing the linker segfaulting on Travis quite a bit which is
868-
// causing quite a bit of pain to land PRs when they spuriously fail
869-
// due to a segfault.
870-
//
871-
// The issue #38878 has some more debugging information on it as well,
872-
// but this unfortunately looks like it's just a race condition in
873-
// macOS's linker with some thread pool working in the background. It
874-
// seems that no one currently knows a fix for this so in the meantime
875-
// we're left with this...
876-
if !retry_on_segfault || i > 3 {
877-
break;
878-
}
879-
let msg_segv = "clang: error: unable to execute command: Segmentation fault: 11";
880-
let msg_bus = "clang: error: unable to execute command: Bus error: 10";
881-
if out.contains(msg_segv) || out.contains(msg_bus) {
882-
warn!(
883-
?cmd, %out,
884-
"looks like the linker segfaulted when we tried to call it, \
885-
automatically retrying again",
886-
);
887-
continue;
888-
}
889-
890-
if is_illegal_instruction(&output.status) {
891-
warn!(
892-
?cmd, %out, status = %output.status,
893-
"looks like the linker hit an illegal instruction when we \
894-
tried to call it, automatically retrying again.",
895-
);
896-
continue;
897-
}
898-
899-
#[cfg(unix)]
900-
fn is_illegal_instruction(status: &ExitStatus) -> bool {
901-
use std::os::unix::prelude::*;
902-
status.signal() == Some(libc::SIGILL)
903-
}
904-
905-
#[cfg(not(unix))]
906-
fn is_illegal_instruction(_status: &ExitStatus) -> bool {
907-
false
908-
}
858+
break;
909859
}
910860

911861
match prog {

‎compiler/rustc_middle/src/mir/statement.rs

Lines changed: 42 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -88,26 +88,31 @@ impl<'tcx> PlaceTy<'tcx> {
8888
///
8989
/// Note that the resulting type has not been normalized.
9090
#[instrument(level = "debug", skip(tcx), ret)]
91-
pub fn field_ty(self, tcx: TyCtxt<'tcx>, f: FieldIdx) -> Ty<'tcx> {
92-
if let Some(variant_index) = self.variant_index {
93-
match *self.ty.kind() {
91+
pub fn field_ty(
92+
tcx: TyCtxt<'tcx>,
93+
self_ty: Ty<'tcx>,
94+
variant_idx: Option<VariantIdx>,
95+
f: FieldIdx,
96+
) -> Ty<'tcx> {
97+
if let Some(variant_index) = variant_idx {
98+
match *self_ty.kind() {
9499
ty::Adt(adt_def, args) if adt_def.is_enum() => {
95100
adt_def.variant(variant_index).fields[f].ty(tcx, args)
96101
}
97102
ty::Coroutine(def_id, args) => {
98103
let mut variants = args.as_coroutine().state_tys(def_id, tcx);
99104
let Some(mut variant) = variants.nth(variant_index.into()) else {
100-
bug!("variant {variant_index:?} of coroutine out of range: {self:?}");
105+
bug!("variant {variant_index:?} of coroutine out of range: {self_ty:?}");
101106
};
102107

103-
variant
104-
.nth(f.index())
105-
.unwrap_or_else(|| bug!("field {f:?} out of range: {self:?}"))
108+
variant.nth(f.index()).unwrap_or_else(|| {
109+
bug!("field {f:?} out of range of variant: {self_ty:?} {variant_idx:?}")
110+
})
106111
}
107-
_ => bug!("can't downcast non-adt non-coroutine type: {self:?}"),
112+
_ => bug!("can't downcast non-adt non-coroutine type: {self_ty:?}"),
108113
}
109114
} else {
110-
match self.ty.kind() {
115+
match self_ty.kind() {
111116
ty::Adt(adt_def, args) if !adt_def.is_enum() => {
112117
adt_def.non_enum_variant().fields[f].ty(tcx, args)
113118
}
@@ -116,26 +121,25 @@ impl<'tcx> PlaceTy<'tcx> {
116121
.upvar_tys()
117122
.get(f.index())
118123
.copied()
119-
.unwrap_or_else(|| bug!("field {f:?} out of range: {self:?}")),
124+
.unwrap_or_else(|| bug!("field {f:?} out of range: {self_ty:?}")),
120125
ty::CoroutineClosure(_, args) => args
121126
.as_coroutine_closure()
122127
.upvar_tys()
123128
.get(f.index())
124129
.copied()
125-
.unwrap_or_else(|| bug!("field {f:?} out of range: {self:?}")),
130+
.unwrap_or_else(|| bug!("field {f:?} out of range: {self_ty:?}")),
126131
// Only prefix fields (upvars and current state) are
127132
// accessible without a variant index.
128-
ty::Coroutine(_, args) => args
129-
.as_coroutine()
130-
.prefix_tys()
131-
.get(f.index())
132-
.copied()
133-
.unwrap_or_else(|| bug!("field {f:?} out of range: {self:?}")),
133+
ty::Coroutine(_, args) => {
134+
args.as_coroutine().prefix_tys().get(f.index()).copied().unwrap_or_else(|| {
135+
bug!("field {f:?} out of range of prefixes for {self_ty}")
136+
})
137+
}
134138
ty::Tuple(tys) => tys
135139
.get(f.index())
136140
.copied()
137-
.unwrap_or_else(|| bug!("field {f:?} out of range: {self:?}")),
138-
_ => bug!("can't project out of {self:?}"),
141+
.unwrap_or_else(|| bug!("field {f:?} out of range: {self_ty:?}")),
142+
_ => bug!("can't project out of {self_ty:?}"),
139143
}
140144
}
141145
}
@@ -148,11 +152,11 @@ impl<'tcx> PlaceTy<'tcx> {
148152
elems.iter().fold(self, |place_ty, &elem| place_ty.projection_ty(tcx, elem))
149153
}
150154

151-
/// Convenience wrapper around `projection_ty_core` for
152-
/// `PlaceElem`, where we can just use the `Ty` that is already
153-
/// stored inline on field projection elems.
155+
/// Convenience wrapper around `projection_ty_core` for `PlaceElem`,
156+
/// where we can just use the `Ty` that is already stored inline on
157+
/// field projection elems.
154158
pub fn projection_ty(self, tcx: TyCtxt<'tcx>, elem: PlaceElem<'tcx>) -> PlaceTy<'tcx> {
155-
self.projection_ty_core(tcx, &elem, |_, _, ty| ty, |_, ty| ty)
159+
self.projection_ty_core(tcx, &elem, |ty| ty, |_, _, _, ty| ty, |ty| ty)
156160
}
157161

158162
/// `place_ty.projection_ty_core(tcx, elem, |...| { ... })`
@@ -164,8 +168,9 @@ impl<'tcx> PlaceTy<'tcx> {
164168
self,
165169
tcx: TyCtxt<'tcx>,
166170
elem: &ProjectionElem<V, T>,
167-
mut handle_field: impl FnMut(&Self, FieldIdx, T) -> Ty<'tcx>,
168-
mut handle_opaque_cast_and_subtype: impl FnMut(&Self, T) -> Ty<'tcx>,
171+
mut structurally_normalize: impl FnMut(Ty<'tcx>) -> Ty<'tcx>,
172+
mut handle_field: impl FnMut(Ty<'tcx>, Option<VariantIdx>, FieldIdx, T) -> Ty<'tcx>,
173+
mut handle_opaque_cast_and_subtype: impl FnMut(T) -> Ty<'tcx>,
169174
) -> PlaceTy<'tcx>
170175
where
171176
V: ::std::fmt::Debug,
@@ -176,16 +181,16 @@ impl<'tcx> PlaceTy<'tcx> {
176181
}
177182
let answer = match *elem {
178183
ProjectionElem::Deref => {
179-
let ty = self.ty.builtin_deref(true).unwrap_or_else(|| {
184+
let ty = structurally_normalize(self.ty).builtin_deref(true).unwrap_or_else(|| {
180185
bug!("deref projection of non-dereferenceable ty {:?}", self)
181186
});
182187
PlaceTy::from_ty(ty)
183188
}
184189
ProjectionElem::Index(_) | ProjectionElem::ConstantIndex { .. } => {
185-
PlaceTy::from_ty(self.ty.builtin_index().unwrap())
190+
PlaceTy::from_ty(structurally_normalize(self.ty).builtin_index().unwrap())
186191
}
187192
ProjectionElem::Subslice { from, to, from_end } => {
188-
PlaceTy::from_ty(match self.ty.kind() {
193+
PlaceTy::from_ty(match structurally_normalize(self.ty).kind() {
189194
ty::Slice(..) => self.ty,
190195
ty::Array(inner, _) if !from_end => Ty::new_array(tcx, *inner, to - from),
191196
ty::Array(inner, size) if from_end => {
@@ -201,17 +206,18 @@ impl<'tcx> PlaceTy<'tcx> {
201206
ProjectionElem::Downcast(_name, index) => {
202207
PlaceTy { ty: self.ty, variant_index: Some(index) }
203208
}
204-
ProjectionElem::Field(f, fty) => PlaceTy::from_ty(handle_field(&self, f, fty)),
205-
ProjectionElem::OpaqueCast(ty) => {
206-
PlaceTy::from_ty(handle_opaque_cast_and_subtype(&self, ty))
207-
}
208-
ProjectionElem::Subtype(ty) => {
209-
PlaceTy::from_ty(handle_opaque_cast_and_subtype(&self, ty))
210-
}
209+
ProjectionElem::Field(f, fty) => PlaceTy::from_ty(handle_field(
210+
structurally_normalize(self.ty),
211+
self.variant_index,
212+
f,
213+
fty,
214+
)),
215+
ProjectionElem::OpaqueCast(ty) => PlaceTy::from_ty(handle_opaque_cast_and_subtype(ty)),
216+
ProjectionElem::Subtype(ty) => PlaceTy::from_ty(handle_opaque_cast_and_subtype(ty)),
211217

212218
// FIXME(unsafe_binders): Rename `handle_opaque_cast_and_subtype` to be more general.
213219
ProjectionElem::UnwrapUnsafeBinder(ty) => {
214-
PlaceTy::from_ty(handle_opaque_cast_and_subtype(&self, ty))
220+
PlaceTy::from_ty(handle_opaque_cast_and_subtype(ty))
215221
}
216222
};
217223
debug!("projection_ty self: {:?} elem: {:?} yields: {:?}", self, elem, answer);

‎compiler/rustc_mir_build/src/builder/custom/parse/instruction.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -323,9 +323,9 @@ impl<'a, 'tcx> ParseCtxt<'a, 'tcx> {
323323
fn parse_place_inner(&self, expr_id: ExprId) -> PResult<(Place<'tcx>, PlaceTy<'tcx>)> {
324324
let (parent, proj) = parse_by_kind!(self, expr_id, expr, "place",
325325
@call(mir_field, args) => {
326-
let (parent, ty) = self.parse_place_inner(args[0])?;
326+
let (parent, place_ty) = self.parse_place_inner(args[0])?;
327327
let field = FieldIdx::from_u32(self.parse_integer_literal(args[1])? as u32);
328-
let field_ty = ty.field_ty(self.tcx, field);
328+
let field_ty = PlaceTy::field_ty(self.tcx, place_ty.ty, place_ty.variant_index, field);
329329
let proj = PlaceElem::Field(field, field_ty);
330330
let place = parent.project_deeper(&[proj], self.tcx);
331331
return Ok((place, PlaceTy::from_ty(field_ty)));

‎compiler/rustc_target/src/spec/base/cygwin.rs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
use std::borrow::Cow;
22

33
use crate::spec::{
4-
BinaryFormat, Cc, DebuginfoKind, LinkerFlavor, Lld, SplitDebuginfo, TargetOptions, cvs,
4+
BinaryFormat, Cc, DebuginfoKind, LinkerFlavor, Lld, SplitDebuginfo, TargetOptions, TlsModel,
5+
cvs,
56
};
67

78
pub(crate) fn opts() -> TargetOptions {
@@ -44,6 +45,8 @@ pub(crate) fn opts() -> TargetOptions {
4445
eh_frame_header: false,
4546
debuginfo_kind: DebuginfoKind::Dwarf,
4647
supported_split_debuginfo: Cow::Borrowed(&[SplitDebuginfo::Off]),
48+
tls_model: TlsModel::Emulated,
49+
has_thread_local: true,
4750
..Default::default()
4851
}
4952
}

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

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1832,7 +1832,9 @@ impl Config {
18321832
.join(exe("rustc", config.build))
18331833
};
18341834

1835-
config.initial_sysroot = config.initial_rustc.ancestors().nth(2).unwrap().into();
1835+
config.initial_sysroot = t!(PathBuf::from_str(
1836+
output(Command::new(&config.initial_rustc).args(["--print", "sysroot"])).trim()
1837+
));
18361838

18371839
config.initial_cargo_clippy = cargo_clippy;
18381840

‎src/ci/github-actions/jobs.yml

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,6 @@ envs:
7272
env-x86_64-apple-tests: &env-x86_64-apple-tests
7373
SCRIPT: ./x.py check compiletest --set build.compiletest-use-stage0-libtest=true && ./x.py --stage 2 test --skip tests/ui --skip tests/rustdoc -- --exact
7474
RUST_CONFIGURE_ARGS: --build=x86_64-apple-darwin --enable-sanitizers --enable-profiler --set rust.jemalloc
75-
RUSTC_RETRY_LINKER_ON_SEGFAULT: 1
7675
# Ensure that host tooling is tested on our minimum supported macOS version.
7776
MACOSX_DEPLOYMENT_TARGET: 10.12
7877
MACOSX_STD_DEPLOYMENT_TARGET: 10.12
@@ -402,7 +401,6 @@ auto:
402401
env:
403402
SCRIPT: ./x.py dist bootstrap --include-default-paths --host=x86_64-apple-darwin --target=x86_64-apple-darwin
404403
RUST_CONFIGURE_ARGS: --enable-full-tools --enable-sanitizers --enable-profiler --set rust.jemalloc --set rust.lto=thin --set rust.codegen-units=1
405-
RUSTC_RETRY_LINKER_ON_SEGFAULT: 1
406404
# Ensure that host tooling is built to support our minimum support macOS version.
407405
MACOSX_DEPLOYMENT_TARGET: 10.12
408406
MACOSX_STD_DEPLOYMENT_TARGET: 10.12
@@ -420,7 +418,6 @@ auto:
420418
# Mac Catalyst cannot currently compile the sanitizer:
421419
# https://github.com/rust-lang/rust/issues/129069
422420
RUST_CONFIGURE_ARGS: --enable-sanitizers --enable-profiler --set rust.jemalloc --set target.aarch64-apple-ios-macabi.sanitizers=false --set target.x86_64-apple-ios-macabi.sanitizers=false
423-
RUSTC_RETRY_LINKER_ON_SEGFAULT: 1
424421
# Ensure that host tooling is built to support our minimum support macOS version.
425422
# FIXME(madsmtm): This might be redundant, as we're not building host tooling here (?)
426423
MACOSX_DEPLOYMENT_TARGET: 10.12
@@ -453,7 +450,6 @@ auto:
453450
--set llvm.ninja=false
454451
--set rust.lto=thin
455452
--set rust.codegen-units=1
456-
RUSTC_RETRY_LINKER_ON_SEGFAULT: 1
457453
SELECT_XCODE: /Applications/Xcode_15.4.app
458454
USE_XCODE_CLANG: 1
459455
# Aarch64 tooling only needs to support macOS 11.0 and up as nothing else
@@ -476,7 +472,6 @@ auto:
476472
--enable-sanitizers
477473
--enable-profiler
478474
--set rust.jemalloc
479-
RUSTC_RETRY_LINKER_ON_SEGFAULT: 1
480475
SELECT_XCODE: /Applications/Xcode_15.4.app
481476
USE_XCODE_CLANG: 1
482477
# Aarch64 tooling only needs to support macOS 11.0 and up as nothing else

‎src/librustdoc/clean/inline.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -409,12 +409,12 @@ pub(crate) fn merge_attrs(
409409
} else {
410410
Attributes::from_hir(&both)
411411
},
412-
extract_cfg_from_attrs(both.iter(), cx.tcx, None, &cx.cache.hidden_cfg),
412+
extract_cfg_from_attrs(both.iter(), cx.tcx, &cx.cache.hidden_cfg),
413413
)
414414
} else {
415415
(
416416
Attributes::from_hir(old_attrs),
417-
extract_cfg_from_attrs(old_attrs.iter(), cx.tcx, None, &cx.cache.hidden_cfg),
417+
extract_cfg_from_attrs(old_attrs.iter(), cx.tcx, &cx.cache.hidden_cfg),
418418
)
419419
}
420420
}

‎src/librustdoc/clean/mod.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -210,7 +210,6 @@ fn generate_item_with_correct_attrs(
210210
Cow::Owned(attr) => attr,
211211
}),
212212
cx.tcx,
213-
def_id.as_local().map(|did| cx.tcx.local_def_id_to_hir_id(did)),
214213
&cx.cache.hidden_cfg,
215214
);
216215
let attrs = Attributes::from_hir_iter(attrs.iter().map(|(attr, did)| (&**attr, *did)), false);

‎src/librustdoc/clean/types.rs

Lines changed: 2 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,8 @@ use rustc_data_structures::fx::{FxHashSet, FxIndexMap, FxIndexSet};
1212
use rustc_hir::def::{CtorKind, DefKind, Res};
1313
use rustc_hir::def_id::{CrateNum, DefId, LOCAL_CRATE, LocalDefId};
1414
use rustc_hir::lang_items::LangItem;
15-
use rustc_hir::{BodyId, HirId, Mutability};
15+
use rustc_hir::{BodyId, Mutability};
1616
use rustc_index::IndexVec;
17-
use rustc_lint_defs::{BuiltinLintDiag, Lint};
1817
use rustc_metadata::rendered_const;
1918
use rustc_middle::span_bug;
2019
use rustc_middle::ty::fast_reject::SimplifiedType;
@@ -478,12 +477,7 @@ impl Item {
478477
name,
479478
kind,
480479
Attributes::from_hir(hir_attrs),
481-
extract_cfg_from_attrs(
482-
hir_attrs.iter(),
483-
cx.tcx,
484-
def_id.as_local().map(|did| cx.tcx.local_def_id_to_hir_id(did)),
485-
&cx.cache.hidden_cfg,
486-
),
480+
extract_cfg_from_attrs(hir_attrs.iter(), cx.tcx, &cx.cache.hidden_cfg),
487481
)
488482
}
489483

@@ -1039,7 +1033,6 @@ pub(crate) fn hir_attr_lists<'a, I: IntoIterator<Item = &'a hir::Attribute>>(
10391033
pub(crate) fn extract_cfg_from_attrs<'a, I: Iterator<Item = &'a hir::Attribute> + Clone>(
10401034
attrs: I,
10411035
tcx: TyCtxt<'_>,
1042-
hir_id: Option<HirId>,
10431036
hidden_cfg: &FxHashSet<Cfg>,
10441037
) -> Option<Arc<Cfg>> {
10451038
let doc_cfg_active = tcx.features().doc_cfg();
@@ -1064,42 +1057,10 @@ pub(crate) fn extract_cfg_from_attrs<'a, I: Iterator<Item = &'a hir::Attribute>
10641057
if doc_cfg.peek().is_some() && doc_cfg_active {
10651058
let sess = tcx.sess;
10661059

1067-
struct RustdocCfgMatchesLintEmitter<'a>(TyCtxt<'a>, Option<HirId>);
1068-
1069-
impl<'a> rustc_attr_parsing::CfgMatchesLintEmitter for RustdocCfgMatchesLintEmitter<'a> {
1070-
fn emit_span_lint(
1071-
&self,
1072-
sess: &Session,
1073-
lint: &'static Lint,
1074-
sp: rustc_span::Span,
1075-
builtin_diag: BuiltinLintDiag,
1076-
) {
1077-
if let Some(hir_id) = self.1 {
1078-
self.0.node_span_lint(lint, hir_id, sp, |diag| {
1079-
rustc_lint::decorate_builtin_lint(
1080-
sess,
1081-
Some(self.0),
1082-
builtin_diag,
1083-
diag,
1084-
)
1085-
});
1086-
} else {
1087-
// No HIR id. Probably in another crate. Don't lint.
1088-
}
1089-
}
1090-
}
1091-
10921060
doc_cfg.fold(Cfg::True, |mut cfg, item| {
10931061
if let Some(cfg_mi) =
10941062
item.meta_item().and_then(|item| rustc_expand::config::parse_cfg(item, sess))
10951063
{
1096-
// The result is unused here but we can gate unstable predicates
1097-
rustc_attr_parsing::cfg_matches(
1098-
cfg_mi,
1099-
tcx.sess,
1100-
RustdocCfgMatchesLintEmitter(tcx, hir_id),
1101-
Some(tcx.features()),
1102-
);
11031064
match Cfg::parse(cfg_mi) {
11041065
Ok(new_cfg) => cfg &= new_cfg,
11051066
Err(e) => {

‎src/librustdoc/doctest/rust.rs

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -116,12 +116,9 @@ impl HirCollector<'_> {
116116
nested: F,
117117
) {
118118
let ast_attrs = self.tcx.hir_attrs(self.tcx.local_def_id_to_hir_id(def_id));
119-
if let Some(ref cfg) = extract_cfg_from_attrs(
120-
ast_attrs.iter(),
121-
self.tcx,
122-
Some(self.tcx.local_def_id_to_hir_id(def_id)),
123-
&FxHashSet::default(),
124-
) && !cfg.matches(&self.tcx.sess.psess)
119+
if let Some(ref cfg) =
120+
extract_cfg_from_attrs(ast_attrs.iter(), self.tcx, &FxHashSet::default())
121+
&& !cfg.matches(&self.tcx.sess.psess)
125122
{
126123
return;
127124
}
Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
use rustc_hir::HirId;
2+
use rustc_hir::def_id::LocalDefId;
3+
use rustc_middle::ty::TyCtxt;
4+
use rustc_span::sym;
5+
6+
use super::Pass;
7+
use crate::clean::{Attributes, Crate, Item};
8+
use crate::core::DocContext;
9+
use crate::visit::DocVisitor;
10+
11+
pub(crate) const CHECK_DOC_CFG: Pass = Pass {
12+
name: "check-doc-cfg",
13+
run: Some(check_doc_cfg),
14+
description: "checks `#[doc(cfg(...))]` for stability feature and unexpected cfgs",
15+
};
16+
17+
pub(crate) fn check_doc_cfg(krate: Crate, cx: &mut DocContext<'_>) -> Crate {
18+
let mut checker = DocCfgChecker { cx };
19+
checker.visit_crate(&krate);
20+
krate
21+
}
22+
23+
struct RustdocCfgMatchesLintEmitter<'a>(TyCtxt<'a>, HirId);
24+
25+
impl<'a> rustc_attr_parsing::CfgMatchesLintEmitter for RustdocCfgMatchesLintEmitter<'a> {
26+
fn emit_span_lint(
27+
&self,
28+
sess: &rustc_session::Session,
29+
lint: &'static rustc_lint::Lint,
30+
sp: rustc_span::Span,
31+
builtin_diag: rustc_lint_defs::BuiltinLintDiag,
32+
) {
33+
self.0.node_span_lint(lint, self.1, sp, |diag| {
34+
rustc_lint::decorate_builtin_lint(sess, Some(self.0), builtin_diag, diag)
35+
});
36+
}
37+
}
38+
39+
struct DocCfgChecker<'a, 'tcx> {
40+
cx: &'a mut DocContext<'tcx>,
41+
}
42+
43+
impl DocCfgChecker<'_, '_> {
44+
fn check_attrs(&mut self, attrs: &Attributes, did: LocalDefId) {
45+
let doc_cfgs = attrs
46+
.other_attrs
47+
.iter()
48+
.filter(|attr| attr.has_name(sym::doc))
49+
.flat_map(|attr| attr.meta_item_list().unwrap_or_default())
50+
.filter(|attr| attr.has_name(sym::cfg));
51+
52+
for doc_cfg in doc_cfgs {
53+
if let Some([cfg_mi]) = doc_cfg.meta_item_list() {
54+
let _ = rustc_attr_parsing::cfg_matches(
55+
cfg_mi,
56+
&self.cx.tcx.sess,
57+
RustdocCfgMatchesLintEmitter(
58+
self.cx.tcx,
59+
self.cx.tcx.local_def_id_to_hir_id(did),
60+
),
61+
Some(self.cx.tcx.features()),
62+
);
63+
}
64+
}
65+
}
66+
}
67+
68+
impl DocVisitor<'_> for DocCfgChecker<'_, '_> {
69+
fn visit_item(&mut self, item: &'_ Item) {
70+
if let Some(Some(local_did)) = item.def_id().map(|did| did.as_local()) {
71+
self.check_attrs(&item.attrs, local_did);
72+
}
73+
74+
self.visit_item_recur(item);
75+
}
76+
}

‎src/librustdoc/passes/mod.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,9 @@ pub(crate) use self::collect_intra_doc_links::COLLECT_INTRA_DOC_LINKS;
3232
mod check_doc_test_visibility;
3333
pub(crate) use self::check_doc_test_visibility::CHECK_DOC_TEST_VISIBILITY;
3434

35+
mod check_doc_cfg;
36+
pub(crate) use self::check_doc_cfg::CHECK_DOC_CFG;
37+
3538
mod collect_trait_impls;
3639
pub(crate) use self::collect_trait_impls::COLLECT_TRAIT_IMPLS;
3740

@@ -72,6 +75,7 @@ pub(crate) enum Condition {
7275

7376
/// The full list of passes.
7477
pub(crate) const PASSES: &[Pass] = &[
78+
CHECK_DOC_CFG,
7579
CHECK_DOC_TEST_VISIBILITY,
7680
STRIP_ALIASED_NON_LOCAL,
7781
STRIP_HIDDEN,
@@ -89,6 +93,7 @@ pub(crate) const PASSES: &[Pass] = &[
8993
pub(crate) const DEFAULT_PASSES: &[ConditionalPass] = &[
9094
ConditionalPass::always(COLLECT_TRAIT_IMPLS),
9195
ConditionalPass::always(CHECK_DOC_TEST_VISIBILITY),
96+
ConditionalPass::always(CHECK_DOC_CFG),
9297
ConditionalPass::always(STRIP_ALIASED_NON_LOCAL),
9398
ConditionalPass::new(STRIP_HIDDEN, WhenNotDocumentHidden),
9499
ConditionalPass::new(STRIP_PRIVATE, WhenNotDocumentPrivate),
Lines changed: 21 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,30 @@
11
warning: unexpected `cfg` condition name: `foo`
2-
--> $DIR/doc-cfg-check-cfg.rs:13:11
2+
--> $DIR/doc-cfg-check-cfg.rs:12:12
3+
|
4+
LL | #![doc(cfg(foo))]
5+
| ^^^
6+
|
7+
= help: to expect this configuration use `--check-cfg=cfg(foo)`
8+
= note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration
9+
= note: `#[warn(unexpected_cfgs)]` on by default
10+
11+
warning: unexpected `cfg` condition name: `foo`
12+
--> $DIR/doc-cfg-check-cfg.rs:19:11
13+
|
14+
LL | #[doc(cfg(foo))]
15+
| ^^^
16+
|
17+
= help: to expect this configuration use `--check-cfg=cfg(foo)`
18+
= note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration
19+
20+
warning: unexpected `cfg` condition name: `foo`
21+
--> $DIR/doc-cfg-check-cfg.rs:15:11
322
|
423
LL | #[doc(cfg(foo))]
524
| ^^^
625
|
726
= help: to expect this configuration use `--check-cfg=cfg(foo)`
827
= note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration
9-
= note: `#[warn(unexpected_cfgs)]` on by default
1028

11-
warning: 1 warning emitted
29+
warning: 3 warnings emitted
1230

‎tests/rustdoc-ui/doc-cfg-check-cfg.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,11 +9,15 @@
99
//@[cfg_foo] compile-flags: --check-cfg cfg(foo)
1010

1111
#![feature(doc_cfg)]
12+
#![doc(cfg(foo))]
13+
//[cfg_empty]~^ WARN unexpected `cfg` condition name: `foo`
1214

1315
#[doc(cfg(foo))]
1416
//[cfg_empty]~^ WARN unexpected `cfg` condition name: `foo`
1517
pub fn foo() {}
1618

19+
#[doc(cfg(foo))]
20+
//[cfg_empty]~^ WARN unexpected `cfg` condition name: `foo`
1721
pub mod module {
1822
#[allow(unexpected_cfgs)]
1923
#[doc(cfg(bar))]

‎tests/rustdoc-ui/doc-cfg.stderr

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,18 @@ error: multiple `cfg` predicates are specified
1010
LL | #[doc(cfg(), cfg(foo, bar))]
1111
| ^^^
1212

13+
error: `cfg` predicate is not specified
14+
--> $DIR/doc-cfg.rs:9:7
15+
|
16+
LL | #[doc(cfg())]
17+
| ^^^^^ help: expected syntax is: `cfg(/* predicate */)`
18+
19+
error: multiple `cfg` predicates are specified
20+
--> $DIR/doc-cfg.rs:10:16
21+
|
22+
LL | #[doc(cfg(foo, bar))]
23+
| ^^^
24+
1325
warning: unexpected `cfg` condition name: `foo`
1426
--> $DIR/doc-cfg.rs:6:11
1527
|
@@ -30,17 +42,5 @@ LL | #[doc(cfg(foo), cfg(bar))]
3042
= help: to expect this configuration use `--check-cfg=cfg(bar)`
3143
= note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration
3244

33-
error: `cfg` predicate is not specified
34-
--> $DIR/doc-cfg.rs:9:7
35-
|
36-
LL | #[doc(cfg())]
37-
| ^^^^^ help: expected syntax is: `cfg(/* predicate */)`
38-
39-
error: multiple `cfg` predicates are specified
40-
--> $DIR/doc-cfg.rs:10:16
41-
|
42-
LL | #[doc(cfg(foo, bar))]
43-
| ^^^
44-
4545
error: aborting due to 4 previous errors; 2 warnings emitted
4646

‎tests/rustdoc-ui/issues/issue-91713.stdout

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
Available passes for running rustdoc:
2+
check-doc-cfg - checks `#[doc(cfg(...))]` for stability feature and unexpected cfgs
23
check_doc_test_visibility - run various visibility-related lints on doctests
34
strip-aliased-non-local - strips all non-local private aliased items from the output
45
strip-hidden - strips all `#[doc(hidden)]` items from the output
@@ -14,6 +15,7 @@ calculate-doc-coverage - counts the number of items with and without documentati
1415
Default passes for rustdoc:
1516
collect-trait-impls
1617
check_doc_test_visibility
18+
check-doc-cfg
1719
strip-aliased-non-local
1820
strip-hidden (when not --document-hidden-items)
1921
strip-private (when not --document-private-items)
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
//@ check-pass
2+
//@ revisions: current next
3+
//@ ignore-compare-mode-next-solver (explicit revisions)
4+
//@[next] compile-flags: -Znext-solver
5+
6+
// Regression test for <https://github.com/rust-lang/rust/issues/141708>.
7+
8+
// See description in there; this has to do with fundamental limitations
9+
// to the old trait solver surrounding higher-ranked aliases with infer
10+
// vars. This always worked in the new trait solver, but I added a revision
11+
// just for good measure.
12+
13+
trait Foo<'a> {
14+
type Assoc;
15+
}
16+
17+
impl Foo<'_> for i32 {
18+
type Assoc = u32;
19+
}
20+
21+
impl Foo<'_> for u32 {
22+
type Assoc = u32;
23+
}
24+
25+
fn foo<'b: 'b, T: for<'a> Foo<'a>, F: for<'a> Fn(<T as Foo<'a>>::Assoc)>(_: F) -> (T, F) {
26+
todo!()
27+
}
28+
29+
fn main() {
30+
let (x, c): (i32, _) = foo::<'static, _, _>(|_| {});
31+
}
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
//@ check-pass
2+
//@ compile-flags: -Znext-solver
3+
4+
// Regression test for <https://github.com/rust-lang/trait-system-refactor-initiative/issues/221>.
5+
// Ensure that we normalize after applying projection elems in MIR typeck.
6+
7+
use std::marker::PhantomData;
8+
9+
#[derive(Copy, Clone)]
10+
struct Span;
11+
12+
trait AstKind {
13+
type Inner;
14+
}
15+
16+
struct WithSpan;
17+
impl AstKind for WithSpan {
18+
type Inner
19+
= (i32,);
20+
}
21+
22+
struct Expr<'a> { f: &'a <WithSpan as AstKind>::Inner }
23+
24+
impl Expr<'_> {
25+
fn span(self) {
26+
match self {
27+
Self { f: (n,) } => {},
28+
}
29+
}
30+
}
31+
32+
fn main() {}

0 commit comments

Comments
 (0)
Please sign in to comment.