Auto merge of #141765 - matthiaskrgr:rollup-4hug83b, r=matthiaskrgr
Rollup of 5 pull requests Successful merges: - rust-lang/rust#141703 (Structurally normalize types as needed in `projection_ty_core`) - rust-lang/rust#141719 (Add tls_model for cygwin and enable has_thread_local) - rust-lang/rust#141736 (resolve stage0 sysroot from rustc) - rust-lang/rust#141746 (Rework `#[doc(cfg(..))]` checks as distinct pass in rustdoc) - rust-lang/rust#141749 (Remove RUSTC_RETRY_LINKER_ON_SEGFAULT hack) r? `@ghost` `@rustbot` modify labels: rollup
This commit is contained in:
commit
aa5832b142
19 changed files with 251 additions and 169 deletions
|
|
@ -474,17 +474,18 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
|
|||
let projected_ty = curr_projected_ty.projection_ty_core(
|
||||
tcx,
|
||||
proj,
|
||||
|this, field, ()| {
|
||||
let ty = this.field_ty(tcx, field);
|
||||
self.structurally_resolve(ty, locations)
|
||||
},
|
||||
|_, _| unreachable!(),
|
||||
|ty| self.structurally_resolve(ty, locations),
|
||||
|ty, variant_index, field, ()| PlaceTy::field_ty(tcx, ty, variant_index, field),
|
||||
|_| unreachable!(),
|
||||
);
|
||||
curr_projected_ty = projected_ty;
|
||||
}
|
||||
trace!(?curr_projected_ty);
|
||||
|
||||
let ty = curr_projected_ty.ty;
|
||||
// Need to renormalize `a` as typecheck may have failed to normalize
|
||||
// higher-ranked aliases if normalization was ambiguous due to inference.
|
||||
let a = self.normalize(a, locations);
|
||||
let ty = self.normalize(curr_projected_ty.ty, locations);
|
||||
self.relate_types(ty, v.xform(ty::Contravariant), a, locations, category)?;
|
||||
|
||||
Ok(())
|
||||
|
|
@ -1852,7 +1853,7 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> {
|
|||
| ProjectionElem::Downcast(..) => {}
|
||||
ProjectionElem::Field(field, fty) => {
|
||||
let fty = self.normalize(fty, location);
|
||||
let ty = base_ty.field_ty(tcx, field);
|
||||
let ty = PlaceTy::field_ty(tcx, base_ty.ty, base_ty.variant_index, field);
|
||||
let ty = self.normalize(ty, location);
|
||||
debug!(?fty, ?ty);
|
||||
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ use std::fs::{File, OpenOptions, read};
|
|||
use std::io::{BufWriter, Write};
|
||||
use std::ops::{ControlFlow, Deref};
|
||||
use std::path::{Path, PathBuf};
|
||||
use std::process::{ExitStatus, Output, Stdio};
|
||||
use std::process::{Output, Stdio};
|
||||
use std::{env, fmt, fs, io, mem, str};
|
||||
|
||||
use cc::windows_registry;
|
||||
|
|
@ -736,13 +736,10 @@ fn link_natively(
|
|||
|
||||
// Invoke the system linker
|
||||
info!("{cmd:?}");
|
||||
let retry_on_segfault = env::var("RUSTC_RETRY_LINKER_ON_SEGFAULT").is_ok();
|
||||
let unknown_arg_regex =
|
||||
Regex::new(r"(unknown|unrecognized) (command line )?(option|argument)").unwrap();
|
||||
let mut prog;
|
||||
let mut i = 0;
|
||||
loop {
|
||||
i += 1;
|
||||
prog = sess.time("run_linker", || exec_linker(sess, &cmd, out_filename, flavor, tmpdir));
|
||||
let Ok(ref output) = prog else {
|
||||
break;
|
||||
|
|
@ -858,54 +855,7 @@ fn link_natively(
|
|||
continue;
|
||||
}
|
||||
|
||||
// Here's a terribly awful hack that really shouldn't be present in any
|
||||
// compiler. Here an environment variable is supported to automatically
|
||||
// retry the linker invocation if the linker looks like it segfaulted.
|
||||
//
|
||||
// Gee that seems odd, normally segfaults are things we want to know
|
||||
// about! Unfortunately though in rust-lang/rust#38878 we're
|
||||
// experiencing the linker segfaulting on Travis quite a bit which is
|
||||
// causing quite a bit of pain to land PRs when they spuriously fail
|
||||
// due to a segfault.
|
||||
//
|
||||
// The issue #38878 has some more debugging information on it as well,
|
||||
// but this unfortunately looks like it's just a race condition in
|
||||
// macOS's linker with some thread pool working in the background. It
|
||||
// seems that no one currently knows a fix for this so in the meantime
|
||||
// we're left with this...
|
||||
if !retry_on_segfault || i > 3 {
|
||||
break;
|
||||
}
|
||||
let msg_segv = "clang: error: unable to execute command: Segmentation fault: 11";
|
||||
let msg_bus = "clang: error: unable to execute command: Bus error: 10";
|
||||
if out.contains(msg_segv) || out.contains(msg_bus) {
|
||||
warn!(
|
||||
?cmd, %out,
|
||||
"looks like the linker segfaulted when we tried to call it, \
|
||||
automatically retrying again",
|
||||
);
|
||||
continue;
|
||||
}
|
||||
|
||||
if is_illegal_instruction(&output.status) {
|
||||
warn!(
|
||||
?cmd, %out, status = %output.status,
|
||||
"looks like the linker hit an illegal instruction when we \
|
||||
tried to call it, automatically retrying again.",
|
||||
);
|
||||
continue;
|
||||
}
|
||||
|
||||
#[cfg(unix)]
|
||||
fn is_illegal_instruction(status: &ExitStatus) -> bool {
|
||||
use std::os::unix::prelude::*;
|
||||
status.signal() == Some(libc::SIGILL)
|
||||
}
|
||||
|
||||
#[cfg(not(unix))]
|
||||
fn is_illegal_instruction(_status: &ExitStatus) -> bool {
|
||||
false
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
match prog {
|
||||
|
|
|
|||
|
|
@ -88,26 +88,31 @@ impl<'tcx> PlaceTy<'tcx> {
|
|||
///
|
||||
/// Note that the resulting type has not been normalized.
|
||||
#[instrument(level = "debug", skip(tcx), ret)]
|
||||
pub fn field_ty(self, tcx: TyCtxt<'tcx>, f: FieldIdx) -> Ty<'tcx> {
|
||||
if let Some(variant_index) = self.variant_index {
|
||||
match *self.ty.kind() {
|
||||
pub fn field_ty(
|
||||
tcx: TyCtxt<'tcx>,
|
||||
self_ty: Ty<'tcx>,
|
||||
variant_idx: Option<VariantIdx>,
|
||||
f: FieldIdx,
|
||||
) -> Ty<'tcx> {
|
||||
if let Some(variant_index) = variant_idx {
|
||||
match *self_ty.kind() {
|
||||
ty::Adt(adt_def, args) if adt_def.is_enum() => {
|
||||
adt_def.variant(variant_index).fields[f].ty(tcx, args)
|
||||
}
|
||||
ty::Coroutine(def_id, args) => {
|
||||
let mut variants = args.as_coroutine().state_tys(def_id, tcx);
|
||||
let Some(mut variant) = variants.nth(variant_index.into()) else {
|
||||
bug!("variant {variant_index:?} of coroutine out of range: {self:?}");
|
||||
bug!("variant {variant_index:?} of coroutine out of range: {self_ty:?}");
|
||||
};
|
||||
|
||||
variant
|
||||
.nth(f.index())
|
||||
.unwrap_or_else(|| bug!("field {f:?} out of range: {self:?}"))
|
||||
variant.nth(f.index()).unwrap_or_else(|| {
|
||||
bug!("field {f:?} out of range of variant: {self_ty:?} {variant_idx:?}")
|
||||
})
|
||||
}
|
||||
_ => bug!("can't downcast non-adt non-coroutine type: {self:?}"),
|
||||
_ => bug!("can't downcast non-adt non-coroutine type: {self_ty:?}"),
|
||||
}
|
||||
} else {
|
||||
match self.ty.kind() {
|
||||
match self_ty.kind() {
|
||||
ty::Adt(adt_def, args) if !adt_def.is_enum() => {
|
||||
adt_def.non_enum_variant().fields[f].ty(tcx, args)
|
||||
}
|
||||
|
|
@ -116,26 +121,25 @@ impl<'tcx> PlaceTy<'tcx> {
|
|||
.upvar_tys()
|
||||
.get(f.index())
|
||||
.copied()
|
||||
.unwrap_or_else(|| bug!("field {f:?} out of range: {self:?}")),
|
||||
.unwrap_or_else(|| bug!("field {f:?} out of range: {self_ty:?}")),
|
||||
ty::CoroutineClosure(_, args) => args
|
||||
.as_coroutine_closure()
|
||||
.upvar_tys()
|
||||
.get(f.index())
|
||||
.copied()
|
||||
.unwrap_or_else(|| bug!("field {f:?} out of range: {self:?}")),
|
||||
.unwrap_or_else(|| bug!("field {f:?} out of range: {self_ty:?}")),
|
||||
// Only prefix fields (upvars and current state) are
|
||||
// accessible without a variant index.
|
||||
ty::Coroutine(_, args) => args
|
||||
.as_coroutine()
|
||||
.prefix_tys()
|
||||
.get(f.index())
|
||||
.copied()
|
||||
.unwrap_or_else(|| bug!("field {f:?} out of range: {self:?}")),
|
||||
ty::Coroutine(_, args) => {
|
||||
args.as_coroutine().prefix_tys().get(f.index()).copied().unwrap_or_else(|| {
|
||||
bug!("field {f:?} out of range of prefixes for {self_ty}")
|
||||
})
|
||||
}
|
||||
ty::Tuple(tys) => tys
|
||||
.get(f.index())
|
||||
.copied()
|
||||
.unwrap_or_else(|| bug!("field {f:?} out of range: {self:?}")),
|
||||
_ => bug!("can't project out of {self:?}"),
|
||||
.unwrap_or_else(|| bug!("field {f:?} out of range: {self_ty:?}")),
|
||||
_ => bug!("can't project out of {self_ty:?}"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -148,11 +152,11 @@ impl<'tcx> PlaceTy<'tcx> {
|
|||
elems.iter().fold(self, |place_ty, &elem| place_ty.projection_ty(tcx, elem))
|
||||
}
|
||||
|
||||
/// Convenience wrapper around `projection_ty_core` for
|
||||
/// `PlaceElem`, where we can just use the `Ty` that is already
|
||||
/// stored inline on field projection elems.
|
||||
/// Convenience wrapper around `projection_ty_core` for `PlaceElem`,
|
||||
/// where we can just use the `Ty` that is already stored inline on
|
||||
/// field projection elems.
|
||||
pub fn projection_ty(self, tcx: TyCtxt<'tcx>, elem: PlaceElem<'tcx>) -> PlaceTy<'tcx> {
|
||||
self.projection_ty_core(tcx, &elem, |_, _, ty| ty, |_, ty| ty)
|
||||
self.projection_ty_core(tcx, &elem, |ty| ty, |_, _, _, ty| ty, |ty| ty)
|
||||
}
|
||||
|
||||
/// `place_ty.projection_ty_core(tcx, elem, |...| { ... })`
|
||||
|
|
@ -164,8 +168,9 @@ impl<'tcx> PlaceTy<'tcx> {
|
|||
self,
|
||||
tcx: TyCtxt<'tcx>,
|
||||
elem: &ProjectionElem<V, T>,
|
||||
mut handle_field: impl FnMut(&Self, FieldIdx, T) -> Ty<'tcx>,
|
||||
mut handle_opaque_cast_and_subtype: impl FnMut(&Self, T) -> Ty<'tcx>,
|
||||
mut structurally_normalize: impl FnMut(Ty<'tcx>) -> Ty<'tcx>,
|
||||
mut handle_field: impl FnMut(Ty<'tcx>, Option<VariantIdx>, FieldIdx, T) -> Ty<'tcx>,
|
||||
mut handle_opaque_cast_and_subtype: impl FnMut(T) -> Ty<'tcx>,
|
||||
) -> PlaceTy<'tcx>
|
||||
where
|
||||
V: ::std::fmt::Debug,
|
||||
|
|
@ -176,16 +181,16 @@ impl<'tcx> PlaceTy<'tcx> {
|
|||
}
|
||||
let answer = match *elem {
|
||||
ProjectionElem::Deref => {
|
||||
let ty = self.ty.builtin_deref(true).unwrap_or_else(|| {
|
||||
let ty = structurally_normalize(self.ty).builtin_deref(true).unwrap_or_else(|| {
|
||||
bug!("deref projection of non-dereferenceable ty {:?}", self)
|
||||
});
|
||||
PlaceTy::from_ty(ty)
|
||||
}
|
||||
ProjectionElem::Index(_) | ProjectionElem::ConstantIndex { .. } => {
|
||||
PlaceTy::from_ty(self.ty.builtin_index().unwrap())
|
||||
PlaceTy::from_ty(structurally_normalize(self.ty).builtin_index().unwrap())
|
||||
}
|
||||
ProjectionElem::Subslice { from, to, from_end } => {
|
||||
PlaceTy::from_ty(match self.ty.kind() {
|
||||
PlaceTy::from_ty(match structurally_normalize(self.ty).kind() {
|
||||
ty::Slice(..) => self.ty,
|
||||
ty::Array(inner, _) if !from_end => Ty::new_array(tcx, *inner, to - from),
|
||||
ty::Array(inner, size) if from_end => {
|
||||
|
|
@ -201,17 +206,18 @@ impl<'tcx> PlaceTy<'tcx> {
|
|||
ProjectionElem::Downcast(_name, index) => {
|
||||
PlaceTy { ty: self.ty, variant_index: Some(index) }
|
||||
}
|
||||
ProjectionElem::Field(f, fty) => PlaceTy::from_ty(handle_field(&self, f, fty)),
|
||||
ProjectionElem::OpaqueCast(ty) => {
|
||||
PlaceTy::from_ty(handle_opaque_cast_and_subtype(&self, ty))
|
||||
}
|
||||
ProjectionElem::Subtype(ty) => {
|
||||
PlaceTy::from_ty(handle_opaque_cast_and_subtype(&self, ty))
|
||||
}
|
||||
ProjectionElem::Field(f, fty) => PlaceTy::from_ty(handle_field(
|
||||
structurally_normalize(self.ty),
|
||||
self.variant_index,
|
||||
f,
|
||||
fty,
|
||||
)),
|
||||
ProjectionElem::OpaqueCast(ty) => PlaceTy::from_ty(handle_opaque_cast_and_subtype(ty)),
|
||||
ProjectionElem::Subtype(ty) => PlaceTy::from_ty(handle_opaque_cast_and_subtype(ty)),
|
||||
|
||||
// FIXME(unsafe_binders): Rename `handle_opaque_cast_and_subtype` to be more general.
|
||||
ProjectionElem::UnwrapUnsafeBinder(ty) => {
|
||||
PlaceTy::from_ty(handle_opaque_cast_and_subtype(&self, ty))
|
||||
PlaceTy::from_ty(handle_opaque_cast_and_subtype(ty))
|
||||
}
|
||||
};
|
||||
debug!("projection_ty self: {:?} elem: {:?} yields: {:?}", self, elem, answer);
|
||||
|
|
|
|||
|
|
@ -323,9 +323,9 @@ impl<'a, 'tcx> ParseCtxt<'a, 'tcx> {
|
|||
fn parse_place_inner(&self, expr_id: ExprId) -> PResult<(Place<'tcx>, PlaceTy<'tcx>)> {
|
||||
let (parent, proj) = parse_by_kind!(self, expr_id, expr, "place",
|
||||
@call(mir_field, args) => {
|
||||
let (parent, ty) = self.parse_place_inner(args[0])?;
|
||||
let (parent, place_ty) = self.parse_place_inner(args[0])?;
|
||||
let field = FieldIdx::from_u32(self.parse_integer_literal(args[1])? as u32);
|
||||
let field_ty = ty.field_ty(self.tcx, field);
|
||||
let field_ty = PlaceTy::field_ty(self.tcx, place_ty.ty, place_ty.variant_index, field);
|
||||
let proj = PlaceElem::Field(field, field_ty);
|
||||
let place = parent.project_deeper(&[proj], self.tcx);
|
||||
return Ok((place, PlaceTy::from_ty(field_ty)));
|
||||
|
|
|
|||
|
|
@ -1,7 +1,8 @@
|
|||
use std::borrow::Cow;
|
||||
|
||||
use crate::spec::{
|
||||
BinaryFormat, Cc, DebuginfoKind, LinkerFlavor, Lld, SplitDebuginfo, TargetOptions, cvs,
|
||||
BinaryFormat, Cc, DebuginfoKind, LinkerFlavor, Lld, SplitDebuginfo, TargetOptions, TlsModel,
|
||||
cvs,
|
||||
};
|
||||
|
||||
pub(crate) fn opts() -> TargetOptions {
|
||||
|
|
@ -44,6 +45,8 @@ pub(crate) fn opts() -> TargetOptions {
|
|||
eh_frame_header: false,
|
||||
debuginfo_kind: DebuginfoKind::Dwarf,
|
||||
supported_split_debuginfo: Cow::Borrowed(&[SplitDebuginfo::Off]),
|
||||
tls_model: TlsModel::Emulated,
|
||||
has_thread_local: true,
|
||||
..Default::default()
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1832,7 +1832,9 @@ impl Config {
|
|||
.join(exe("rustc", config.build))
|
||||
};
|
||||
|
||||
config.initial_sysroot = config.initial_rustc.ancestors().nth(2).unwrap().into();
|
||||
config.initial_sysroot = t!(PathBuf::from_str(
|
||||
output(Command::new(&config.initial_rustc).args(["--print", "sysroot"])).trim()
|
||||
));
|
||||
|
||||
config.initial_cargo_clippy = cargo_clippy;
|
||||
|
||||
|
|
|
|||
|
|
@ -72,7 +72,6 @@ envs:
|
|||
env-x86_64-apple-tests: &env-x86_64-apple-tests
|
||||
SCRIPT: ./x.py check compiletest --set build.compiletest-use-stage0-libtest=true && ./x.py --stage 2 test --skip tests/ui --skip tests/rustdoc -- --exact
|
||||
RUST_CONFIGURE_ARGS: --build=x86_64-apple-darwin --enable-sanitizers --enable-profiler --set rust.jemalloc
|
||||
RUSTC_RETRY_LINKER_ON_SEGFAULT: 1
|
||||
# Ensure that host tooling is tested on our minimum supported macOS version.
|
||||
MACOSX_DEPLOYMENT_TARGET: 10.12
|
||||
MACOSX_STD_DEPLOYMENT_TARGET: 10.12
|
||||
|
|
@ -402,7 +401,6 @@ auto:
|
|||
env:
|
||||
SCRIPT: ./x.py dist bootstrap --include-default-paths --host=x86_64-apple-darwin --target=x86_64-apple-darwin
|
||||
RUST_CONFIGURE_ARGS: --enable-full-tools --enable-sanitizers --enable-profiler --set rust.jemalloc --set rust.lto=thin --set rust.codegen-units=1
|
||||
RUSTC_RETRY_LINKER_ON_SEGFAULT: 1
|
||||
# Ensure that host tooling is built to support our minimum support macOS version.
|
||||
MACOSX_DEPLOYMENT_TARGET: 10.12
|
||||
MACOSX_STD_DEPLOYMENT_TARGET: 10.12
|
||||
|
|
@ -420,7 +418,6 @@ auto:
|
|||
# Mac Catalyst cannot currently compile the sanitizer:
|
||||
# https://github.com/rust-lang/rust/issues/129069
|
||||
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
|
||||
RUSTC_RETRY_LINKER_ON_SEGFAULT: 1
|
||||
# Ensure that host tooling is built to support our minimum support macOS version.
|
||||
# FIXME(madsmtm): This might be redundant, as we're not building host tooling here (?)
|
||||
MACOSX_DEPLOYMENT_TARGET: 10.12
|
||||
|
|
@ -453,7 +450,6 @@ auto:
|
|||
--set llvm.ninja=false
|
||||
--set rust.lto=thin
|
||||
--set rust.codegen-units=1
|
||||
RUSTC_RETRY_LINKER_ON_SEGFAULT: 1
|
||||
SELECT_XCODE: /Applications/Xcode_15.4.app
|
||||
USE_XCODE_CLANG: 1
|
||||
# Aarch64 tooling only needs to support macOS 11.0 and up as nothing else
|
||||
|
|
@ -476,7 +472,6 @@ auto:
|
|||
--enable-sanitizers
|
||||
--enable-profiler
|
||||
--set rust.jemalloc
|
||||
RUSTC_RETRY_LINKER_ON_SEGFAULT: 1
|
||||
SELECT_XCODE: /Applications/Xcode_15.4.app
|
||||
USE_XCODE_CLANG: 1
|
||||
# Aarch64 tooling only needs to support macOS 11.0 and up as nothing else
|
||||
|
|
|
|||
|
|
@ -409,12 +409,12 @@ pub(crate) fn merge_attrs(
|
|||
} else {
|
||||
Attributes::from_hir(&both)
|
||||
},
|
||||
extract_cfg_from_attrs(both.iter(), cx.tcx, None, &cx.cache.hidden_cfg),
|
||||
extract_cfg_from_attrs(both.iter(), cx.tcx, &cx.cache.hidden_cfg),
|
||||
)
|
||||
} else {
|
||||
(
|
||||
Attributes::from_hir(old_attrs),
|
||||
extract_cfg_from_attrs(old_attrs.iter(), cx.tcx, None, &cx.cache.hidden_cfg),
|
||||
extract_cfg_from_attrs(old_attrs.iter(), cx.tcx, &cx.cache.hidden_cfg),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -210,7 +210,6 @@ fn generate_item_with_correct_attrs(
|
|||
Cow::Owned(attr) => attr,
|
||||
}),
|
||||
cx.tcx,
|
||||
def_id.as_local().map(|did| cx.tcx.local_def_id_to_hir_id(did)),
|
||||
&cx.cache.hidden_cfg,
|
||||
);
|
||||
let attrs = Attributes::from_hir_iter(attrs.iter().map(|(attr, did)| (&**attr, *did)), false);
|
||||
|
|
|
|||
|
|
@ -12,9 +12,8 @@ use rustc_data_structures::fx::{FxHashSet, FxIndexMap, FxIndexSet};
|
|||
use rustc_hir::def::{CtorKind, DefKind, Res};
|
||||
use rustc_hir::def_id::{CrateNum, DefId, LOCAL_CRATE, LocalDefId};
|
||||
use rustc_hir::lang_items::LangItem;
|
||||
use rustc_hir::{BodyId, HirId, Mutability};
|
||||
use rustc_hir::{BodyId, Mutability};
|
||||
use rustc_index::IndexVec;
|
||||
use rustc_lint_defs::{BuiltinLintDiag, Lint};
|
||||
use rustc_metadata::rendered_const;
|
||||
use rustc_middle::span_bug;
|
||||
use rustc_middle::ty::fast_reject::SimplifiedType;
|
||||
|
|
@ -478,12 +477,7 @@ impl Item {
|
|||
name,
|
||||
kind,
|
||||
Attributes::from_hir(hir_attrs),
|
||||
extract_cfg_from_attrs(
|
||||
hir_attrs.iter(),
|
||||
cx.tcx,
|
||||
def_id.as_local().map(|did| cx.tcx.local_def_id_to_hir_id(did)),
|
||||
&cx.cache.hidden_cfg,
|
||||
),
|
||||
extract_cfg_from_attrs(hir_attrs.iter(), cx.tcx, &cx.cache.hidden_cfg),
|
||||
)
|
||||
}
|
||||
|
||||
|
|
@ -1039,7 +1033,6 @@ pub(crate) fn hir_attr_lists<'a, I: IntoIterator<Item = &'a hir::Attribute>>(
|
|||
pub(crate) fn extract_cfg_from_attrs<'a, I: Iterator<Item = &'a hir::Attribute> + Clone>(
|
||||
attrs: I,
|
||||
tcx: TyCtxt<'_>,
|
||||
hir_id: Option<HirId>,
|
||||
hidden_cfg: &FxHashSet<Cfg>,
|
||||
) -> Option<Arc<Cfg>> {
|
||||
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>
|
|||
if doc_cfg.peek().is_some() && doc_cfg_active {
|
||||
let sess = tcx.sess;
|
||||
|
||||
struct RustdocCfgMatchesLintEmitter<'a>(TyCtxt<'a>, Option<HirId>);
|
||||
|
||||
impl<'a> rustc_attr_parsing::CfgMatchesLintEmitter for RustdocCfgMatchesLintEmitter<'a> {
|
||||
fn emit_span_lint(
|
||||
&self,
|
||||
sess: &Session,
|
||||
lint: &'static Lint,
|
||||
sp: rustc_span::Span,
|
||||
builtin_diag: BuiltinLintDiag,
|
||||
) {
|
||||
if let Some(hir_id) = self.1 {
|
||||
self.0.node_span_lint(lint, hir_id, sp, |diag| {
|
||||
rustc_lint::decorate_builtin_lint(
|
||||
sess,
|
||||
Some(self.0),
|
||||
builtin_diag,
|
||||
diag,
|
||||
)
|
||||
});
|
||||
} else {
|
||||
// No HIR id. Probably in another crate. Don't lint.
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
doc_cfg.fold(Cfg::True, |mut cfg, item| {
|
||||
if let Some(cfg_mi) =
|
||||
item.meta_item().and_then(|item| rustc_expand::config::parse_cfg(item, sess))
|
||||
{
|
||||
// The result is unused here but we can gate unstable predicates
|
||||
rustc_attr_parsing::cfg_matches(
|
||||
cfg_mi,
|
||||
tcx.sess,
|
||||
RustdocCfgMatchesLintEmitter(tcx, hir_id),
|
||||
Some(tcx.features()),
|
||||
);
|
||||
match Cfg::parse(cfg_mi) {
|
||||
Ok(new_cfg) => cfg &= new_cfg,
|
||||
Err(e) => {
|
||||
|
|
|
|||
|
|
@ -116,12 +116,9 @@ impl HirCollector<'_> {
|
|||
nested: F,
|
||||
) {
|
||||
let ast_attrs = self.tcx.hir_attrs(self.tcx.local_def_id_to_hir_id(def_id));
|
||||
if let Some(ref cfg) = extract_cfg_from_attrs(
|
||||
ast_attrs.iter(),
|
||||
self.tcx,
|
||||
Some(self.tcx.local_def_id_to_hir_id(def_id)),
|
||||
&FxHashSet::default(),
|
||||
) && !cfg.matches(&self.tcx.sess.psess)
|
||||
if let Some(ref cfg) =
|
||||
extract_cfg_from_attrs(ast_attrs.iter(), self.tcx, &FxHashSet::default())
|
||||
&& !cfg.matches(&self.tcx.sess.psess)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
|
|
|||
76
src/librustdoc/passes/check_doc_cfg.rs
Normal file
76
src/librustdoc/passes/check_doc_cfg.rs
Normal file
|
|
@ -0,0 +1,76 @@
|
|||
use rustc_hir::HirId;
|
||||
use rustc_hir::def_id::LocalDefId;
|
||||
use rustc_middle::ty::TyCtxt;
|
||||
use rustc_span::sym;
|
||||
|
||||
use super::Pass;
|
||||
use crate::clean::{Attributes, Crate, Item};
|
||||
use crate::core::DocContext;
|
||||
use crate::visit::DocVisitor;
|
||||
|
||||
pub(crate) const CHECK_DOC_CFG: Pass = Pass {
|
||||
name: "check-doc-cfg",
|
||||
run: Some(check_doc_cfg),
|
||||
description: "checks `#[doc(cfg(...))]` for stability feature and unexpected cfgs",
|
||||
};
|
||||
|
||||
pub(crate) fn check_doc_cfg(krate: Crate, cx: &mut DocContext<'_>) -> Crate {
|
||||
let mut checker = DocCfgChecker { cx };
|
||||
checker.visit_crate(&krate);
|
||||
krate
|
||||
}
|
||||
|
||||
struct RustdocCfgMatchesLintEmitter<'a>(TyCtxt<'a>, HirId);
|
||||
|
||||
impl<'a> rustc_attr_parsing::CfgMatchesLintEmitter for RustdocCfgMatchesLintEmitter<'a> {
|
||||
fn emit_span_lint(
|
||||
&self,
|
||||
sess: &rustc_session::Session,
|
||||
lint: &'static rustc_lint::Lint,
|
||||
sp: rustc_span::Span,
|
||||
builtin_diag: rustc_lint_defs::BuiltinLintDiag,
|
||||
) {
|
||||
self.0.node_span_lint(lint, self.1, sp, |diag| {
|
||||
rustc_lint::decorate_builtin_lint(sess, Some(self.0), builtin_diag, diag)
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
struct DocCfgChecker<'a, 'tcx> {
|
||||
cx: &'a mut DocContext<'tcx>,
|
||||
}
|
||||
|
||||
impl DocCfgChecker<'_, '_> {
|
||||
fn check_attrs(&mut self, attrs: &Attributes, did: LocalDefId) {
|
||||
let doc_cfgs = attrs
|
||||
.other_attrs
|
||||
.iter()
|
||||
.filter(|attr| attr.has_name(sym::doc))
|
||||
.flat_map(|attr| attr.meta_item_list().unwrap_or_default())
|
||||
.filter(|attr| attr.has_name(sym::cfg));
|
||||
|
||||
for doc_cfg in doc_cfgs {
|
||||
if let Some([cfg_mi]) = doc_cfg.meta_item_list() {
|
||||
let _ = rustc_attr_parsing::cfg_matches(
|
||||
cfg_mi,
|
||||
&self.cx.tcx.sess,
|
||||
RustdocCfgMatchesLintEmitter(
|
||||
self.cx.tcx,
|
||||
self.cx.tcx.local_def_id_to_hir_id(did),
|
||||
),
|
||||
Some(self.cx.tcx.features()),
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl DocVisitor<'_> for DocCfgChecker<'_, '_> {
|
||||
fn visit_item(&mut self, item: &'_ Item) {
|
||||
if let Some(Some(local_did)) = item.def_id().map(|did| did.as_local()) {
|
||||
self.check_attrs(&item.attrs, local_did);
|
||||
}
|
||||
|
||||
self.visit_item_recur(item);
|
||||
}
|
||||
}
|
||||
|
|
@ -32,6 +32,9 @@ pub(crate) use self::collect_intra_doc_links::COLLECT_INTRA_DOC_LINKS;
|
|||
mod check_doc_test_visibility;
|
||||
pub(crate) use self::check_doc_test_visibility::CHECK_DOC_TEST_VISIBILITY;
|
||||
|
||||
mod check_doc_cfg;
|
||||
pub(crate) use self::check_doc_cfg::CHECK_DOC_CFG;
|
||||
|
||||
mod collect_trait_impls;
|
||||
pub(crate) use self::collect_trait_impls::COLLECT_TRAIT_IMPLS;
|
||||
|
||||
|
|
@ -72,6 +75,7 @@ pub(crate) enum Condition {
|
|||
|
||||
/// The full list of passes.
|
||||
pub(crate) const PASSES: &[Pass] = &[
|
||||
CHECK_DOC_CFG,
|
||||
CHECK_DOC_TEST_VISIBILITY,
|
||||
STRIP_ALIASED_NON_LOCAL,
|
||||
STRIP_HIDDEN,
|
||||
|
|
@ -89,6 +93,7 @@ pub(crate) const PASSES: &[Pass] = &[
|
|||
pub(crate) const DEFAULT_PASSES: &[ConditionalPass] = &[
|
||||
ConditionalPass::always(COLLECT_TRAIT_IMPLS),
|
||||
ConditionalPass::always(CHECK_DOC_TEST_VISIBILITY),
|
||||
ConditionalPass::always(CHECK_DOC_CFG),
|
||||
ConditionalPass::always(STRIP_ALIASED_NON_LOCAL),
|
||||
ConditionalPass::new(STRIP_HIDDEN, WhenNotDocumentHidden),
|
||||
ConditionalPass::new(STRIP_PRIVATE, WhenNotDocumentPrivate),
|
||||
|
|
|
|||
|
|
@ -1,12 +1,30 @@
|
|||
warning: unexpected `cfg` condition name: `foo`
|
||||
--> $DIR/doc-cfg-check-cfg.rs:13:11
|
||||
--> $DIR/doc-cfg-check-cfg.rs:12:12
|
||||
|
|
||||
LL | #![doc(cfg(foo))]
|
||||
| ^^^
|
||||
|
|
||||
= help: to expect this configuration use `--check-cfg=cfg(foo)`
|
||||
= note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration
|
||||
= note: `#[warn(unexpected_cfgs)]` on by default
|
||||
|
||||
warning: unexpected `cfg` condition name: `foo`
|
||||
--> $DIR/doc-cfg-check-cfg.rs:19:11
|
||||
|
|
||||
LL | #[doc(cfg(foo))]
|
||||
| ^^^
|
||||
|
|
||||
= help: to expect this configuration use `--check-cfg=cfg(foo)`
|
||||
= note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration
|
||||
= note: `#[warn(unexpected_cfgs)]` on by default
|
||||
|
||||
warning: 1 warning emitted
|
||||
warning: unexpected `cfg` condition name: `foo`
|
||||
--> $DIR/doc-cfg-check-cfg.rs:15:11
|
||||
|
|
||||
LL | #[doc(cfg(foo))]
|
||||
| ^^^
|
||||
|
|
||||
= help: to expect this configuration use `--check-cfg=cfg(foo)`
|
||||
= note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration
|
||||
|
||||
warning: 3 warnings emitted
|
||||
|
||||
|
|
|
|||
|
|
@ -9,11 +9,15 @@
|
|||
//@[cfg_foo] compile-flags: --check-cfg cfg(foo)
|
||||
|
||||
#![feature(doc_cfg)]
|
||||
#![doc(cfg(foo))]
|
||||
//[cfg_empty]~^ WARN unexpected `cfg` condition name: `foo`
|
||||
|
||||
#[doc(cfg(foo))]
|
||||
//[cfg_empty]~^ WARN unexpected `cfg` condition name: `foo`
|
||||
pub fn foo() {}
|
||||
|
||||
#[doc(cfg(foo))]
|
||||
//[cfg_empty]~^ WARN unexpected `cfg` condition name: `foo`
|
||||
pub mod module {
|
||||
#[allow(unexpected_cfgs)]
|
||||
#[doc(cfg(bar))]
|
||||
|
|
|
|||
|
|
@ -10,6 +10,18 @@ error: multiple `cfg` predicates are specified
|
|||
LL | #[doc(cfg(), cfg(foo, bar))]
|
||||
| ^^^
|
||||
|
||||
error: `cfg` predicate is not specified
|
||||
--> $DIR/doc-cfg.rs:9:7
|
||||
|
|
||||
LL | #[doc(cfg())]
|
||||
| ^^^^^ help: expected syntax is: `cfg(/* predicate */)`
|
||||
|
||||
error: multiple `cfg` predicates are specified
|
||||
--> $DIR/doc-cfg.rs:10:16
|
||||
|
|
||||
LL | #[doc(cfg(foo, bar))]
|
||||
| ^^^
|
||||
|
||||
warning: unexpected `cfg` condition name: `foo`
|
||||
--> $DIR/doc-cfg.rs:6:11
|
||||
|
|
||||
|
|
@ -30,17 +42,5 @@ LL | #[doc(cfg(foo), cfg(bar))]
|
|||
= help: to expect this configuration use `--check-cfg=cfg(bar)`
|
||||
= note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration
|
||||
|
||||
error: `cfg` predicate is not specified
|
||||
--> $DIR/doc-cfg.rs:9:7
|
||||
|
|
||||
LL | #[doc(cfg())]
|
||||
| ^^^^^ help: expected syntax is: `cfg(/* predicate */)`
|
||||
|
||||
error: multiple `cfg` predicates are specified
|
||||
--> $DIR/doc-cfg.rs:10:16
|
||||
|
|
||||
LL | #[doc(cfg(foo, bar))]
|
||||
| ^^^
|
||||
|
||||
error: aborting due to 4 previous errors; 2 warnings emitted
|
||||
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
Available passes for running rustdoc:
|
||||
check-doc-cfg - checks `#[doc(cfg(...))]` for stability feature and unexpected cfgs
|
||||
check_doc_test_visibility - run various visibility-related lints on doctests
|
||||
strip-aliased-non-local - strips all non-local private aliased items from the output
|
||||
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
|
|||
Default passes for rustdoc:
|
||||
collect-trait-impls
|
||||
check_doc_test_visibility
|
||||
check-doc-cfg
|
||||
strip-aliased-non-local
|
||||
strip-hidden (when not --document-hidden-items)
|
||||
strip-private (when not --document-private-items)
|
||||
|
|
|
|||
31
tests/ui/nll/user-annotations/normalizing-user-annotation.rs
Normal file
31
tests/ui/nll/user-annotations/normalizing-user-annotation.rs
Normal file
|
|
@ -0,0 +1,31 @@
|
|||
//@ check-pass
|
||||
//@ revisions: current next
|
||||
//@ ignore-compare-mode-next-solver (explicit revisions)
|
||||
//@[next] compile-flags: -Znext-solver
|
||||
|
||||
// Regression test for <https://github.com/rust-lang/rust/issues/141708>.
|
||||
|
||||
// See description in there; this has to do with fundamental limitations
|
||||
// to the old trait solver surrounding higher-ranked aliases with infer
|
||||
// vars. This always worked in the new trait solver, but I added a revision
|
||||
// just for good measure.
|
||||
|
||||
trait Foo<'a> {
|
||||
type Assoc;
|
||||
}
|
||||
|
||||
impl Foo<'_> for i32 {
|
||||
type Assoc = u32;
|
||||
}
|
||||
|
||||
impl Foo<'_> for u32 {
|
||||
type Assoc = u32;
|
||||
}
|
||||
|
||||
fn foo<'b: 'b, T: for<'a> Foo<'a>, F: for<'a> Fn(<T as Foo<'a>>::Assoc)>(_: F) -> (T, F) {
|
||||
todo!()
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let (x, c): (i32, _) = foo::<'static, _, _>(|_| {});
|
||||
}
|
||||
|
|
@ -0,0 +1,32 @@
|
|||
//@ check-pass
|
||||
//@ compile-flags: -Znext-solver
|
||||
|
||||
// Regression test for <https://github.com/rust-lang/trait-system-refactor-initiative/issues/221>.
|
||||
// Ensure that we normalize after applying projection elems in MIR typeck.
|
||||
|
||||
use std::marker::PhantomData;
|
||||
|
||||
#[derive(Copy, Clone)]
|
||||
struct Span;
|
||||
|
||||
trait AstKind {
|
||||
type Inner;
|
||||
}
|
||||
|
||||
struct WithSpan;
|
||||
impl AstKind for WithSpan {
|
||||
type Inner
|
||||
= (i32,);
|
||||
}
|
||||
|
||||
struct Expr<'a> { f: &'a <WithSpan as AstKind>::Inner }
|
||||
|
||||
impl Expr<'_> {
|
||||
fn span(self) {
|
||||
match self {
|
||||
Self { f: (n,) } => {},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {}
|
||||
Loading…
Add table
Add a link
Reference in a new issue