Auto merge of #96123 - Dylan-DPC:rollup-qjog6n1, r=Dylan-DPC
Rollup of 7 pull requests Successful merges: - #94985 (Parse inner attributes on inline const block) - #95006 (Reject `#[thread_local]` attribute on non-static items) - #95426 (Include Refs in Valtree Creation) - #95908 (Inline `shallow_resolve_ty` into `ShallowResolver`) - #96058 (separate flock implementations into separate modules) - #96088 (Update mdbook) - #96118 (rustdoc: Rename `def_id` into `item_id` when the type is `ItemId` for readability) Failed merges: r? `@ghost` `@rustbot` modify labels: rollup
This commit is contained in:
commit
878c7833f6
22
Cargo.lock
22
Cargo.lock
@ -606,12 +606,22 @@ dependencies = [
|
||||
"atty",
|
||||
"bitflags",
|
||||
"indexmap",
|
||||
"lazy_static",
|
||||
"os_str_bytes",
|
||||
"strsim 0.10.0",
|
||||
"termcolor",
|
||||
"textwrap 0.14.2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "clap_complete"
|
||||
version = "3.1.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "df6f3613c0a3cddfd78b41b10203eb322cb29b600cbdf808a7d3db95691b8e25"
|
||||
dependencies = [
|
||||
"clap 3.1.1",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "clippy"
|
||||
version = "0.1.62"
|
||||
@ -2240,14 +2250,15 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "mdbook"
|
||||
version = "0.4.15"
|
||||
version = "0.4.18"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "241f10687eb3b4e0634b3b4e423f97c5f1efbd69dc9522e24a8b94583eeec3c6"
|
||||
checksum = "74612ae81a3e5ee509854049dfa4c7975ae033c06f5fc4735c7dfbe60ee2a39d"
|
||||
dependencies = [
|
||||
"ammonia",
|
||||
"anyhow",
|
||||
"chrono",
|
||||
"clap 2.34.0",
|
||||
"clap 3.1.1",
|
||||
"clap_complete",
|
||||
"elasticlunr-rs",
|
||||
"env_logger 0.7.1",
|
||||
"handlebars",
|
||||
@ -2911,7 +2922,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "34f197a544b0c9ab3ae46c359a7ec9cbbb5c7bf97054266fecb7ead794a181d6"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
"getopts",
|
||||
"memchr",
|
||||
"unicase",
|
||||
]
|
||||
@ -3129,9 +3139,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "regex"
|
||||
version = "1.5.4"
|
||||
version = "1.5.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d07a8629359eb56f1e2fb1652bb04212c072a87ba68546a04065d525673ac461"
|
||||
checksum = "1a11647b6b25ff05a515cb92c365cec08801e83423a235b51e231e1808747286"
|
||||
dependencies = [
|
||||
"aho-corasick",
|
||||
"memchr",
|
||||
|
@ -959,7 +959,7 @@ impl<'a> State<'a> {
|
||||
self.word_space("=");
|
||||
match term {
|
||||
Term::Ty(ty) => self.print_type(ty),
|
||||
Term::Const(c) => self.print_expr_anon_const(c),
|
||||
Term::Const(c) => self.print_expr_anon_const(c, &[]),
|
||||
}
|
||||
}
|
||||
ast::AssocConstraintKind::Bound { bounds } => self.print_type_bounds(":", &*bounds),
|
||||
|
@ -88,10 +88,21 @@ impl<'a> State<'a> {
|
||||
self.end();
|
||||
}
|
||||
|
||||
pub(super) fn print_expr_anon_const(&mut self, expr: &ast::AnonConst) {
|
||||
pub(super) fn print_expr_anon_const(
|
||||
&mut self,
|
||||
expr: &ast::AnonConst,
|
||||
attrs: &[ast::Attribute],
|
||||
) {
|
||||
self.ibox(INDENT_UNIT);
|
||||
self.word("const");
|
||||
self.print_expr(&expr.value);
|
||||
self.nbsp();
|
||||
if let ast::ExprKind::Block(block, None) = &expr.value.kind {
|
||||
self.cbox(0);
|
||||
self.ibox(0);
|
||||
self.print_block_with_attrs(block, attrs);
|
||||
} else {
|
||||
self.print_expr(&expr.value);
|
||||
}
|
||||
self.end();
|
||||
}
|
||||
|
||||
@ -275,7 +286,7 @@ impl<'a> State<'a> {
|
||||
self.print_expr_vec(exprs);
|
||||
}
|
||||
ast::ExprKind::ConstBlock(ref anon_const) => {
|
||||
self.print_expr_anon_const(anon_const);
|
||||
self.print_expr_anon_const(anon_const, attrs);
|
||||
}
|
||||
ast::ExprKind::Repeat(ref element, ref count) => {
|
||||
self.print_expr_repeat(element, count);
|
||||
|
@ -188,6 +188,7 @@ pub(super) fn op_to_const<'tcx>(
|
||||
}
|
||||
}
|
||||
|
||||
#[instrument(skip(tcx), level = "debug")]
|
||||
fn turn_into_const_value<'tcx>(
|
||||
tcx: TyCtxt<'tcx>,
|
||||
constant: ConstAlloc<'tcx>,
|
||||
@ -206,6 +207,7 @@ fn turn_into_const_value<'tcx>(
|
||||
!is_static || cid.promoted.is_some(),
|
||||
"the `eval_to_const_value_raw` query should not be used for statics, use `eval_to_allocation` instead"
|
||||
);
|
||||
|
||||
// Turn this into a proper constant.
|
||||
op_to_const(&ecx, &mplace.into())
|
||||
}
|
||||
|
@ -3,12 +3,14 @@
|
||||
use std::convert::TryFrom;
|
||||
|
||||
use rustc_hir::Mutability;
|
||||
use rustc_middle::ty::layout::HasTyCtxt;
|
||||
use rustc_middle::ty::{self, TyCtxt};
|
||||
use rustc_middle::{
|
||||
mir::{self, interpret::ConstAlloc},
|
||||
ty::ScalarInt,
|
||||
};
|
||||
use rustc_span::{source_map::DUMMY_SP, symbol::Symbol};
|
||||
use rustc_target::abi::VariantIdx;
|
||||
|
||||
use crate::interpret::{
|
||||
intern_const_alloc_recursive, ConstValue, InternKind, InterpCx, InterpResult, MPlaceTy,
|
||||
@ -55,28 +57,48 @@ pub(crate) fn const_to_valtree<'tcx>(
|
||||
const_to_valtree_inner(&ecx, &place)
|
||||
}
|
||||
|
||||
#[instrument(skip(ecx), level = "debug")]
|
||||
fn branches<'tcx>(
|
||||
ecx: &CompileTimeEvalContext<'tcx, 'tcx>,
|
||||
place: &MPlaceTy<'tcx>,
|
||||
n: usize,
|
||||
variant: Option<VariantIdx>,
|
||||
) -> Option<ty::ValTree<'tcx>> {
|
||||
let place = match variant {
|
||||
Some(variant) => ecx.mplace_downcast(&place, variant).unwrap(),
|
||||
None => *place,
|
||||
};
|
||||
let variant = variant.map(|variant| Some(ty::ValTree::Leaf(ScalarInt::from(variant.as_u32()))));
|
||||
debug!(?place, ?variant);
|
||||
|
||||
let fields = (0..n).map(|i| {
|
||||
let field = ecx.mplace_field(&place, i).unwrap();
|
||||
const_to_valtree_inner(ecx, &field)
|
||||
});
|
||||
// For enums, we prepend their variant index before the variant's fields so we can figure out
|
||||
// the variant again when just seeing a valtree.
|
||||
let branches = variant.into_iter().chain(fields);
|
||||
Some(ty::ValTree::Branch(ecx.tcx.arena.alloc_from_iter(branches.collect::<Option<Vec<_>>>()?)))
|
||||
}
|
||||
|
||||
fn slice_branches<'tcx>(
|
||||
ecx: &CompileTimeEvalContext<'tcx, 'tcx>,
|
||||
place: &MPlaceTy<'tcx>,
|
||||
) -> Option<ty::ValTree<'tcx>> {
|
||||
let n = place.len(&ecx.tcx()).expect(&format!("expected to use len of place {:?}", place));
|
||||
let branches = (0..n).map(|i| {
|
||||
let place_elem = ecx.mplace_index(place, i).unwrap();
|
||||
const_to_valtree_inner(ecx, &place_elem)
|
||||
});
|
||||
|
||||
Some(ty::ValTree::Branch(ecx.tcx.arena.alloc_from_iter(branches.collect::<Option<Vec<_>>>()?)))
|
||||
}
|
||||
|
||||
#[instrument(skip(ecx), level = "debug")]
|
||||
fn const_to_valtree_inner<'tcx>(
|
||||
ecx: &CompileTimeEvalContext<'tcx, 'tcx>,
|
||||
place: &MPlaceTy<'tcx>,
|
||||
) -> Option<ty::ValTree<'tcx>> {
|
||||
let branches = |n, variant| {
|
||||
let place = match variant {
|
||||
Some(variant) => ecx.mplace_downcast(&place, variant).unwrap(),
|
||||
None => *place,
|
||||
};
|
||||
let variant =
|
||||
variant.map(|variant| Some(ty::ValTree::Leaf(ScalarInt::from(variant.as_u32()))));
|
||||
let fields = (0..n).map(|i| {
|
||||
let field = ecx.mplace_field(&place, i).unwrap();
|
||||
const_to_valtree_inner(ecx, &field)
|
||||
});
|
||||
// For enums, we preped their variant index before the variant's fields so we can figure out
|
||||
// the variant again when just seeing a valtree.
|
||||
let branches = variant.into_iter().chain(fields);
|
||||
Some(ty::ValTree::Branch(
|
||||
ecx.tcx.arena.alloc_from_iter(branches.collect::<Option<Vec<_>>>()?),
|
||||
))
|
||||
};
|
||||
match place.layout.ty.kind() {
|
||||
ty::FnDef(..) => Some(ty::ValTree::zst()),
|
||||
ty::Bool | ty::Int(_) | ty::Uint(_) | ty::Float(_) | ty::Char => {
|
||||
@ -90,19 +112,27 @@ fn const_to_valtree_inner<'tcx>(
|
||||
// Technically we could allow function pointers (represented as `ty::Instance`), but this is not guaranteed to
|
||||
// agree with runtime equality tests.
|
||||
ty::FnPtr(_) | ty::RawPtr(_) => None,
|
||||
ty::Ref(..) => unimplemented!("need to use deref_const"),
|
||||
|
||||
ty::Ref(_, _, _) => {
|
||||
let derefd_place = ecx.deref_operand(&place.into()).unwrap_or_else(|e| bug!("couldn't deref {:?}, error: {:?}", place, e));
|
||||
debug!(?derefd_place);
|
||||
|
||||
const_to_valtree_inner(ecx, &derefd_place)
|
||||
}
|
||||
|
||||
ty::Str | ty::Slice(_) | ty::Array(_, _) => {
|
||||
let valtree = slice_branches(ecx, place);
|
||||
debug!(?valtree);
|
||||
|
||||
valtree
|
||||
}
|
||||
// Trait objects are not allowed in type level constants, as we have no concept for
|
||||
// resolving their backing type, even if we can do that at const eval time. We may
|
||||
// hypothetically be able to allow `dyn StructuralEq` trait objects in the future,
|
||||
// but it is unclear if this is useful.
|
||||
ty::Dynamic(..) => None,
|
||||
|
||||
ty::Slice(_) | ty::Str => {
|
||||
unimplemented!("need to find the backing data of the slice/str and recurse on that")
|
||||
}
|
||||
ty::Tuple(substs) => branches(substs.len(), None),
|
||||
ty::Array(_, len) => branches(usize::try_from(len.eval_usize(ecx.tcx.tcx, ecx.param_env)).unwrap(), None),
|
||||
ty::Tuple(substs) => branches(ecx, place, substs.len(), None),
|
||||
|
||||
ty::Adt(def, _) => {
|
||||
if def.variants().is_empty() {
|
||||
@ -111,7 +141,7 @@ fn const_to_valtree_inner<'tcx>(
|
||||
|
||||
let variant = ecx.read_discriminant(&place.into()).unwrap().1;
|
||||
|
||||
branches(def.variant(variant).fields.len(), def.is_enum().then_some(variant))
|
||||
branches(ecx, place, def.variant(variant).fields.len(), def.is_enum().then_some(variant))
|
||||
}
|
||||
|
||||
ty::Never
|
||||
|
@ -191,7 +191,7 @@ impl<'tcx, Tag: Provenance> MPlaceTy<'tcx, Tag> {
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub(super) fn len(&self, cx: &impl HasDataLayout) -> InterpResult<'tcx, u64> {
|
||||
pub(crate) fn len(&self, cx: &impl HasDataLayout) -> InterpResult<'tcx, u64> {
|
||||
if self.layout.is_unsized() {
|
||||
// We need to consult `meta` metadata
|
||||
match self.layout.ty.kind() {
|
||||
|
@ -7,225 +7,20 @@
|
||||
#![allow(non_camel_case_types)]
|
||||
#![allow(nonstandard_style)]
|
||||
|
||||
use std::fs::{File, OpenOptions};
|
||||
use std::io;
|
||||
use std::path::Path;
|
||||
|
||||
cfg_if! {
|
||||
// We use `flock` rather than `fcntl` on Linux, because WSL1 does not support
|
||||
// `fcntl`-style advisory locks properly (rust-lang/rust#72157).
|
||||
//
|
||||
// For other Unix targets we still use `fcntl` because it's more portable than
|
||||
// `flock`.
|
||||
if #[cfg(target_os = "linux")] {
|
||||
use std::os::unix::prelude::*;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct Lock {
|
||||
_file: File,
|
||||
}
|
||||
|
||||
impl Lock {
|
||||
pub fn new(p: &Path,
|
||||
wait: bool,
|
||||
create: bool,
|
||||
exclusive: bool)
|
||||
-> io::Result<Lock> {
|
||||
let file = OpenOptions::new()
|
||||
.read(true)
|
||||
.write(true)
|
||||
.create(create)
|
||||
.mode(libc::S_IRWXU as u32)
|
||||
.open(p)?;
|
||||
|
||||
let mut operation = if exclusive {
|
||||
libc::LOCK_EX
|
||||
} else {
|
||||
libc::LOCK_SH
|
||||
};
|
||||
if !wait {
|
||||
operation |= libc::LOCK_NB
|
||||
}
|
||||
|
||||
let ret = unsafe { libc::flock(file.as_raw_fd(), operation) };
|
||||
if ret == -1 {
|
||||
Err(io::Error::last_os_error())
|
||||
} else {
|
||||
Ok(Lock { _file: file })
|
||||
}
|
||||
}
|
||||
|
||||
pub fn error_unsupported(err: &io::Error) -> bool {
|
||||
matches!(err.raw_os_error(), Some(libc::ENOTSUP) | Some(libc::ENOSYS))
|
||||
}
|
||||
}
|
||||
|
||||
// Note that we don't need a Drop impl to execute `flock(fd, LOCK_UN)`. Lock acquired by
|
||||
// `flock` is associated with the file descriptor and closing the file release it
|
||||
// automatically.
|
||||
mod linux;
|
||||
use linux as imp;
|
||||
} else if #[cfg(unix)] {
|
||||
use std::mem;
|
||||
use std::os::unix::prelude::*;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct Lock {
|
||||
file: File,
|
||||
}
|
||||
|
||||
impl Lock {
|
||||
pub fn new(p: &Path,
|
||||
wait: bool,
|
||||
create: bool,
|
||||
exclusive: bool)
|
||||
-> io::Result<Lock> {
|
||||
let file = OpenOptions::new()
|
||||
.read(true)
|
||||
.write(true)
|
||||
.create(create)
|
||||
.mode(libc::S_IRWXU as u32)
|
||||
.open(p)?;
|
||||
|
||||
let lock_type = if exclusive {
|
||||
libc::F_WRLCK
|
||||
} else {
|
||||
libc::F_RDLCK
|
||||
};
|
||||
|
||||
let mut flock: libc::flock = unsafe { mem::zeroed() };
|
||||
flock.l_type = lock_type as libc::c_short;
|
||||
flock.l_whence = libc::SEEK_SET as libc::c_short;
|
||||
flock.l_start = 0;
|
||||
flock.l_len = 0;
|
||||
|
||||
let cmd = if wait { libc::F_SETLKW } else { libc::F_SETLK };
|
||||
let ret = unsafe {
|
||||
libc::fcntl(file.as_raw_fd(), cmd, &flock)
|
||||
};
|
||||
if ret == -1 {
|
||||
Err(io::Error::last_os_error())
|
||||
} else {
|
||||
Ok(Lock { file })
|
||||
}
|
||||
}
|
||||
|
||||
pub fn error_unsupported(err: &io::Error) -> bool {
|
||||
matches!(err.raw_os_error(), Some(libc::ENOTSUP) | Some(libc::ENOSYS))
|
||||
}
|
||||
}
|
||||
|
||||
impl Drop for Lock {
|
||||
fn drop(&mut self) {
|
||||
let mut flock: libc::flock = unsafe { mem::zeroed() };
|
||||
flock.l_type = libc::F_UNLCK as libc::c_short;
|
||||
flock.l_whence = libc::SEEK_SET as libc::c_short;
|
||||
flock.l_start = 0;
|
||||
flock.l_len = 0;
|
||||
|
||||
unsafe {
|
||||
libc::fcntl(self.file.as_raw_fd(), libc::F_SETLK, &flock);
|
||||
}
|
||||
}
|
||||
}
|
||||
mod unix;
|
||||
use unix as imp;
|
||||
} else if #[cfg(windows)] {
|
||||
use std::mem;
|
||||
use std::os::windows::prelude::*;
|
||||
|
||||
use winapi::shared::winerror::ERROR_INVALID_FUNCTION;
|
||||
use winapi::um::minwinbase::{OVERLAPPED, LOCKFILE_FAIL_IMMEDIATELY, LOCKFILE_EXCLUSIVE_LOCK};
|
||||
use winapi::um::fileapi::LockFileEx;
|
||||
use winapi::um::winnt::{FILE_SHARE_DELETE, FILE_SHARE_READ, FILE_SHARE_WRITE};
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct Lock {
|
||||
_file: File,
|
||||
}
|
||||
|
||||
impl Lock {
|
||||
pub fn new(p: &Path,
|
||||
wait: bool,
|
||||
create: bool,
|
||||
exclusive: bool)
|
||||
-> io::Result<Lock> {
|
||||
assert!(p.parent().unwrap().exists(),
|
||||
"Parent directory of lock-file must exist: {}",
|
||||
p.display());
|
||||
|
||||
let share_mode = FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE;
|
||||
|
||||
let mut open_options = OpenOptions::new();
|
||||
open_options.read(true)
|
||||
.share_mode(share_mode);
|
||||
|
||||
if create {
|
||||
open_options.create(true)
|
||||
.write(true);
|
||||
}
|
||||
|
||||
debug!("attempting to open lock file `{}`", p.display());
|
||||
let file = match open_options.open(p) {
|
||||
Ok(file) => {
|
||||
debug!("lock file opened successfully");
|
||||
file
|
||||
}
|
||||
Err(err) => {
|
||||
debug!("error opening lock file: {}", err);
|
||||
return Err(err)
|
||||
}
|
||||
};
|
||||
|
||||
let ret = unsafe {
|
||||
let mut overlapped: OVERLAPPED = mem::zeroed();
|
||||
|
||||
let mut dwFlags = 0;
|
||||
if !wait {
|
||||
dwFlags |= LOCKFILE_FAIL_IMMEDIATELY;
|
||||
}
|
||||
|
||||
if exclusive {
|
||||
dwFlags |= LOCKFILE_EXCLUSIVE_LOCK;
|
||||
}
|
||||
|
||||
debug!("attempting to acquire lock on lock file `{}`",
|
||||
p.display());
|
||||
LockFileEx(file.as_raw_handle(),
|
||||
dwFlags,
|
||||
0,
|
||||
0xFFFF_FFFF,
|
||||
0xFFFF_FFFF,
|
||||
&mut overlapped)
|
||||
};
|
||||
if ret == 0 {
|
||||
let err = io::Error::last_os_error();
|
||||
debug!("failed acquiring file lock: {}", err);
|
||||
Err(err)
|
||||
} else {
|
||||
debug!("successfully acquired lock");
|
||||
Ok(Lock { _file: file })
|
||||
}
|
||||
}
|
||||
|
||||
pub fn error_unsupported(err: &io::Error) -> bool {
|
||||
err.raw_os_error() == Some(ERROR_INVALID_FUNCTION as i32)
|
||||
}
|
||||
}
|
||||
|
||||
// Note that we don't need a Drop impl on the Windows: The file is unlocked
|
||||
// automatically when it's closed.
|
||||
mod windows;
|
||||
use windows as imp;
|
||||
} else {
|
||||
#[derive(Debug)]
|
||||
pub struct Lock(());
|
||||
|
||||
impl Lock {
|
||||
pub fn new(_p: &Path, _wait: bool, _create: bool, _exclusive: bool)
|
||||
-> io::Result<Lock>
|
||||
{
|
||||
let msg = "file locks not supported on this platform";
|
||||
Err(io::Error::new(io::ErrorKind::Other, msg))
|
||||
}
|
||||
|
||||
pub fn error_unsupported(_err: &io::Error) -> bool {
|
||||
true
|
||||
}
|
||||
}
|
||||
mod unsupported;
|
||||
use unsupported as imp;
|
||||
}
|
||||
}
|
||||
|
||||
pub use imp::Lock;
|
||||
|
40
compiler/rustc_data_structures/src/flock/linux.rs
Normal file
40
compiler/rustc_data_structures/src/flock/linux.rs
Normal file
@ -0,0 +1,40 @@
|
||||
//! We use `flock` rather than `fcntl` on Linux, because WSL1 does not support
|
||||
//! `fcntl`-style advisory locks properly (rust-lang/rust#72157). For other Unix
|
||||
//! targets we still use `fcntl` because it's more portable than `flock`.
|
||||
|
||||
use std::fs::{File, OpenOptions};
|
||||
use std::io;
|
||||
use std::os::unix::prelude::*;
|
||||
use std::path::Path;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct Lock {
|
||||
_file: File,
|
||||
}
|
||||
|
||||
impl Lock {
|
||||
pub fn new(p: &Path, wait: bool, create: bool, exclusive: bool) -> io::Result<Lock> {
|
||||
let file = OpenOptions::new()
|
||||
.read(true)
|
||||
.write(true)
|
||||
.create(create)
|
||||
.mode(libc::S_IRWXU as u32)
|
||||
.open(p)?;
|
||||
|
||||
let mut operation = if exclusive { libc::LOCK_EX } else { libc::LOCK_SH };
|
||||
if !wait {
|
||||
operation |= libc::LOCK_NB
|
||||
}
|
||||
|
||||
let ret = unsafe { libc::flock(file.as_raw_fd(), operation) };
|
||||
if ret == -1 { Err(io::Error::last_os_error()) } else { Ok(Lock { _file: file }) }
|
||||
}
|
||||
|
||||
pub fn error_unsupported(err: &io::Error) -> bool {
|
||||
matches!(err.raw_os_error(), Some(libc::ENOTSUP) | Some(libc::ENOSYS))
|
||||
}
|
||||
}
|
||||
|
||||
// Note that we don't need a Drop impl to execute `flock(fd, LOCK_UN)`. A lock acquired by
|
||||
// `flock` is associated with the file descriptor and closing the file releases it
|
||||
// automatically.
|
51
compiler/rustc_data_structures/src/flock/unix.rs
Normal file
51
compiler/rustc_data_structures/src/flock/unix.rs
Normal file
@ -0,0 +1,51 @@
|
||||
use std::fs::{File, OpenOptions};
|
||||
use std::io;
|
||||
use std::mem;
|
||||
use std::os::unix::prelude::*;
|
||||
use std::path::Path;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct Lock {
|
||||
file: File,
|
||||
}
|
||||
|
||||
impl Lock {
|
||||
pub fn new(p: &Path, wait: bool, create: bool, exclusive: bool) -> io::Result<Lock> {
|
||||
let file = OpenOptions::new()
|
||||
.read(true)
|
||||
.write(true)
|
||||
.create(create)
|
||||
.mode(libc::S_IRWXU as u32)
|
||||
.open(p)?;
|
||||
|
||||
let lock_type = if exclusive { libc::F_WRLCK } else { libc::F_RDLCK };
|
||||
|
||||
let mut flock: libc::flock = unsafe { mem::zeroed() };
|
||||
flock.l_type = lock_type as libc::c_short;
|
||||
flock.l_whence = libc::SEEK_SET as libc::c_short;
|
||||
flock.l_start = 0;
|
||||
flock.l_len = 0;
|
||||
|
||||
let cmd = if wait { libc::F_SETLKW } else { libc::F_SETLK };
|
||||
let ret = unsafe { libc::fcntl(file.as_raw_fd(), cmd, &flock) };
|
||||
if ret == -1 { Err(io::Error::last_os_error()) } else { Ok(Lock { file }) }
|
||||
}
|
||||
|
||||
pub fn error_unsupported(err: &io::Error) -> bool {
|
||||
matches!(err.raw_os_error(), Some(libc::ENOTSUP) | Some(libc::ENOSYS))
|
||||
}
|
||||
}
|
||||
|
||||
impl Drop for Lock {
|
||||
fn drop(&mut self) {
|
||||
let mut flock: libc::flock = unsafe { mem::zeroed() };
|
||||
flock.l_type = libc::F_UNLCK as libc::c_short;
|
||||
flock.l_whence = libc::SEEK_SET as libc::c_short;
|
||||
flock.l_start = 0;
|
||||
flock.l_len = 0;
|
||||
|
||||
unsafe {
|
||||
libc::fcntl(self.file.as_raw_fd(), libc::F_SETLK, &flock);
|
||||
}
|
||||
}
|
||||
}
|
16
compiler/rustc_data_structures/src/flock/unsupported.rs
Normal file
16
compiler/rustc_data_structures/src/flock/unsupported.rs
Normal file
@ -0,0 +1,16 @@
|
||||
use std::io;
|
||||
use std::path::Path;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct Lock(());
|
||||
|
||||
impl Lock {
|
||||
pub fn new(_p: &Path, _wait: bool, _create: bool, _exclusive: bool) -> io::Result<Lock> {
|
||||
let msg = "file locks not supported on this platform";
|
||||
Err(io::Error::new(io::ErrorKind::Other, msg))
|
||||
}
|
||||
|
||||
pub fn error_unsupported(_err: &io::Error) -> bool {
|
||||
true
|
||||
}
|
||||
}
|
77
compiler/rustc_data_structures/src/flock/windows.rs
Normal file
77
compiler/rustc_data_structures/src/flock/windows.rs
Normal file
@ -0,0 +1,77 @@
|
||||
use std::fs::{File, OpenOptions};
|
||||
use std::io;
|
||||
use std::mem;
|
||||
use std::os::windows::prelude::*;
|
||||
use std::path::Path;
|
||||
|
||||
use winapi::shared::winerror::ERROR_INVALID_FUNCTION;
|
||||
use winapi::um::fileapi::LockFileEx;
|
||||
use winapi::um::minwinbase::{LOCKFILE_EXCLUSIVE_LOCK, LOCKFILE_FAIL_IMMEDIATELY, OVERLAPPED};
|
||||
use winapi::um::winnt::{FILE_SHARE_DELETE, FILE_SHARE_READ, FILE_SHARE_WRITE};
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct Lock {
|
||||
_file: File,
|
||||
}
|
||||
|
||||
impl Lock {
|
||||
pub fn new(p: &Path, wait: bool, create: bool, exclusive: bool) -> io::Result<Lock> {
|
||||
assert!(
|
||||
p.parent().unwrap().exists(),
|
||||
"Parent directory of lock-file must exist: {}",
|
||||
p.display()
|
||||
);
|
||||
|
||||
let share_mode = FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE;
|
||||
|
||||
let mut open_options = OpenOptions::new();
|
||||
open_options.read(true).share_mode(share_mode);
|
||||
|
||||
if create {
|
||||
open_options.create(true).write(true);
|
||||
}
|
||||
|
||||
debug!("attempting to open lock file `{}`", p.display());
|
||||
let file = match open_options.open(p) {
|
||||
Ok(file) => {
|
||||
debug!("lock file opened successfully");
|
||||
file
|
||||
}
|
||||
Err(err) => {
|
||||
debug!("error opening lock file: {}", err);
|
||||
return Err(err);
|
||||
}
|
||||
};
|
||||
|
||||
let ret = unsafe {
|
||||
let mut overlapped: OVERLAPPED = mem::zeroed();
|
||||
|
||||
let mut dwFlags = 0;
|
||||
if !wait {
|
||||
dwFlags |= LOCKFILE_FAIL_IMMEDIATELY;
|
||||
}
|
||||
|
||||
if exclusive {
|
||||
dwFlags |= LOCKFILE_EXCLUSIVE_LOCK;
|
||||
}
|
||||
|
||||
debug!("attempting to acquire lock on lock file `{}`", p.display());
|
||||
LockFileEx(file.as_raw_handle(), dwFlags, 0, 0xFFFF_FFFF, 0xFFFF_FFFF, &mut overlapped)
|
||||
};
|
||||
if ret == 0 {
|
||||
let err = io::Error::last_os_error();
|
||||
debug!("failed acquiring file lock: {}", err);
|
||||
Err(err)
|
||||
} else {
|
||||
debug!("successfully acquired lock");
|
||||
Ok(Lock { _file: file })
|
||||
}
|
||||
}
|
||||
|
||||
pub fn error_unsupported(err: &io::Error) -> bool {
|
||||
err.raw_os_error() == Some(ERROR_INVALID_FUNCTION as i32)
|
||||
}
|
||||
}
|
||||
|
||||
// Note that we don't need a Drop impl on Windows: The file is unlocked
|
||||
// automatically when it's closed.
|
@ -1659,49 +1659,6 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
|
||||
self.tcx.const_eval_resolve(param_env_erased, unevaluated, span)
|
||||
}
|
||||
|
||||
/// If `typ` is a type variable of some kind, resolve it one level
|
||||
/// (but do not resolve types found in the result). If `typ` is
|
||||
/// not a type variable, just return it unmodified.
|
||||
// FIXME(eddyb) inline into `ShallowResolver::visit_ty`.
|
||||
fn shallow_resolve_ty(&self, typ: Ty<'tcx>) -> Ty<'tcx> {
|
||||
match *typ.kind() {
|
||||
ty::Infer(ty::TyVar(v)) => {
|
||||
// Not entirely obvious: if `typ` is a type variable,
|
||||
// it can be resolved to an int/float variable, which
|
||||
// can then be recursively resolved, hence the
|
||||
// recursion. Note though that we prevent type
|
||||
// variables from unifying to other type variables
|
||||
// directly (though they may be embedded
|
||||
// structurally), and we prevent cycles in any case,
|
||||
// so this recursion should always be of very limited
|
||||
// depth.
|
||||
//
|
||||
// Note: if these two lines are combined into one we get
|
||||
// dynamic borrow errors on `self.inner`.
|
||||
let known = self.inner.borrow_mut().type_variables().probe(v).known();
|
||||
known.map_or(typ, |t| self.shallow_resolve_ty(t))
|
||||
}
|
||||
|
||||
ty::Infer(ty::IntVar(v)) => self
|
||||
.inner
|
||||
.borrow_mut()
|
||||
.int_unification_table()
|
||||
.probe_value(v)
|
||||
.map(|v| v.to_type(self.tcx))
|
||||
.unwrap_or(typ),
|
||||
|
||||
ty::Infer(ty::FloatVar(v)) => self
|
||||
.inner
|
||||
.borrow_mut()
|
||||
.float_unification_table()
|
||||
.probe_value(v)
|
||||
.map(|v| v.to_type(self.tcx))
|
||||
.unwrap_or(typ),
|
||||
|
||||
_ => typ,
|
||||
}
|
||||
}
|
||||
|
||||
/// `ty_or_const_infer_var_changed` is equivalent to one of these two:
|
||||
/// * `shallow_resolve(ty) != ty` (where `ty.kind = ty::Infer(_)`)
|
||||
/// * `shallow_resolve(ct) != ct` (where `ct.kind = ty::ConstKind::Infer(_)`)
|
||||
@ -1831,8 +1788,46 @@ impl<'a, 'tcx> TypeFolder<'tcx> for ShallowResolver<'a, 'tcx> {
|
||||
self.infcx.tcx
|
||||
}
|
||||
|
||||
/// If `ty` is a type variable of some kind, resolve it one level
|
||||
/// (but do not resolve types found in the result). If `typ` is
|
||||
/// not a type variable, just return it unmodified.
|
||||
fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> {
|
||||
self.infcx.shallow_resolve_ty(ty)
|
||||
match *ty.kind() {
|
||||
ty::Infer(ty::TyVar(v)) => {
|
||||
// Not entirely obvious: if `typ` is a type variable,
|
||||
// it can be resolved to an int/float variable, which
|
||||
// can then be recursively resolved, hence the
|
||||
// recursion. Note though that we prevent type
|
||||
// variables from unifying to other type variables
|
||||
// directly (though they may be embedded
|
||||
// structurally), and we prevent cycles in any case,
|
||||
// so this recursion should always be of very limited
|
||||
// depth.
|
||||
//
|
||||
// Note: if these two lines are combined into one we get
|
||||
// dynamic borrow errors on `self.inner`.
|
||||
let known = self.infcx.inner.borrow_mut().type_variables().probe(v).known();
|
||||
known.map_or(ty, |t| self.fold_ty(t))
|
||||
}
|
||||
|
||||
ty::Infer(ty::IntVar(v)) => self
|
||||
.infcx
|
||||
.inner
|
||||
.borrow_mut()
|
||||
.int_unification_table()
|
||||
.probe_value(v)
|
||||
.map_or(ty, |v| v.to_type(self.infcx.tcx)),
|
||||
|
||||
ty::Infer(ty::FloatVar(v)) => self
|
||||
.infcx
|
||||
.inner
|
||||
.borrow_mut()
|
||||
.float_unification_table()
|
||||
.probe_value(v)
|
||||
.map_or(ty, |v| v.to_type(self.infcx.tcx)),
|
||||
|
||||
_ => ty,
|
||||
}
|
||||
}
|
||||
|
||||
fn fold_const(&mut self, ct: ty::Const<'tcx>) -> ty::Const<'tcx> {
|
||||
|
@ -1,5 +1,5 @@
|
||||
use super::ScalarInt;
|
||||
use rustc_macros::HashStable;
|
||||
use rustc_macros::{HashStable, TyDecodable, TyEncodable};
|
||||
|
||||
#[derive(Copy, Clone, Debug, Hash, TyEncodable, TyDecodable, Eq, PartialEq, Ord, PartialOrd)]
|
||||
#[derive(HashStable)]
|
||||
|
@ -1125,13 +1125,13 @@ impl<'a> Parser<'a> {
|
||||
self.sess.gated_spans.gate(sym::inline_const, span);
|
||||
}
|
||||
self.eat_keyword(kw::Const);
|
||||
let blk = self.parse_block()?;
|
||||
let (attrs, blk) = self.parse_inner_attrs_and_block()?;
|
||||
let anon_const = AnonConst {
|
||||
id: DUMMY_NODE_ID,
|
||||
value: self.mk_expr(blk.span, ExprKind::Block(blk, None), AttrVec::new()),
|
||||
};
|
||||
let blk_span = anon_const.value.span;
|
||||
Ok(self.mk_expr(span.to(blk_span), ExprKind::ConstBlock(anon_const), AttrVec::new()))
|
||||
Ok(self.mk_expr(span.to(blk_span), ExprKind::ConstBlock(anon_const), AttrVec::from(attrs)))
|
||||
}
|
||||
|
||||
/// Parses mutability (`mut` or nothing).
|
||||
|
@ -80,6 +80,7 @@ impl CheckAttrVisitor<'_> {
|
||||
self.check_rustc_must_implement_one_of(attr, span, target)
|
||||
}
|
||||
sym::target_feature => self.check_target_feature(hir_id, attr, span, target),
|
||||
sym::thread_local => self.check_thread_local(attr, span, target),
|
||||
sym::track_caller => {
|
||||
self.check_track_caller(hir_id, attr.span, attrs, span, target)
|
||||
}
|
||||
@ -523,6 +524,21 @@ impl CheckAttrVisitor<'_> {
|
||||
}
|
||||
}
|
||||
|
||||
/// Checks if the `#[thread_local]` attribute on `item` is valid. Returns `true` if valid.
|
||||
fn check_thread_local(&self, attr: &Attribute, span: Span, target: Target) -> bool {
|
||||
match target {
|
||||
Target::ForeignStatic | Target::Static => true,
|
||||
_ => {
|
||||
self.tcx
|
||||
.sess
|
||||
.struct_span_err(attr.span, "attribute should be applied to a static")
|
||||
.span_label(span, "not a static")
|
||||
.emit();
|
||||
false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn doc_attr_str_error(&self, meta: &NestedMetaItem, attr_name: &str) {
|
||||
self.tcx
|
||||
.sess
|
||||
|
@ -116,7 +116,7 @@ impl<'a, 'tcx> AutoTraitFinder<'a, 'tcx> {
|
||||
name: None,
|
||||
attrs: Default::default(),
|
||||
visibility: Inherited,
|
||||
def_id: ItemId::Auto { trait_: trait_def_id, for_: item_def_id },
|
||||
item_id: ItemId::Auto { trait_: trait_def_id, for_: item_def_id },
|
||||
kind: box ImplItem(Impl {
|
||||
unsafety: hir::Unsafety::Normal,
|
||||
generics: new_generics,
|
||||
|
@ -105,7 +105,7 @@ impl<'a, 'tcx> BlanketImplFinder<'a, 'tcx> {
|
||||
name: None,
|
||||
attrs: Default::default(),
|
||||
visibility: Inherited,
|
||||
def_id: ItemId::Blanket { impl_id: impl_def_id, for_: item_def_id },
|
||||
item_id: ItemId::Blanket { impl_id: impl_def_id, for_: item_def_id },
|
||||
kind: box ImplItem(Impl {
|
||||
unsafety: hir::Unsafety::Normal,
|
||||
generics: clean_ty_generics(
|
||||
|
@ -534,7 +534,7 @@ fn build_module(
|
||||
items.push(clean::Item {
|
||||
name: None,
|
||||
attrs: box clean::Attributes::default(),
|
||||
def_id: ItemId::Primitive(prim_ty, did.krate),
|
||||
item_id: ItemId::Primitive(prim_ty, did.krate),
|
||||
visibility: clean::Public,
|
||||
kind: box clean::ImportItem(clean::Import::new_simple(
|
||||
item.ident.name,
|
||||
|
@ -2009,7 +2009,7 @@ fn clean_extern_crate(
|
||||
vec![Item {
|
||||
name: Some(name),
|
||||
attrs: box attrs.clean(cx),
|
||||
def_id: crate_def_id.into(),
|
||||
item_id: crate_def_id.into(),
|
||||
visibility: ty_vis.clean(cx),
|
||||
kind: box ExternCrateItem { src: orig_name },
|
||||
cfg: attrs.cfg(cx.tcx, &cx.cache.hidden_cfg),
|
||||
|
@ -366,7 +366,7 @@ crate struct Item {
|
||||
/// Information about this item that is specific to what kind of item it is.
|
||||
/// E.g., struct vs enum vs function.
|
||||
crate kind: Box<ItemKind>,
|
||||
crate def_id: ItemId,
|
||||
crate item_id: ItemId,
|
||||
|
||||
crate cfg: Option<Arc<Cfg>>,
|
||||
}
|
||||
@ -380,7 +380,7 @@ impl fmt::Debug for Item {
|
||||
let mut fmt = f.debug_struct("Item");
|
||||
fmt.field("name", &self.name)
|
||||
.field("visibility", &self.visibility)
|
||||
.field("def_id", &self.def_id);
|
||||
.field("item_id", &self.item_id);
|
||||
// allow printing the full item if someone really wants to
|
||||
if alternate {
|
||||
fmt.field("attrs", &self.attrs).field("kind", &self.kind).field("cfg", &self.cfg);
|
||||
@ -408,19 +408,19 @@ crate fn rustc_span(def_id: DefId, tcx: TyCtxt<'_>) -> Span {
|
||||
|
||||
impl Item {
|
||||
crate fn stability<'tcx>(&self, tcx: TyCtxt<'tcx>) -> Option<Stability> {
|
||||
self.def_id.as_def_id().and_then(|did| tcx.lookup_stability(did))
|
||||
self.item_id.as_def_id().and_then(|did| tcx.lookup_stability(did))
|
||||
}
|
||||
|
||||
crate fn const_stability<'tcx>(&self, tcx: TyCtxt<'tcx>) -> Option<ConstStability> {
|
||||
self.def_id.as_def_id().and_then(|did| tcx.lookup_const_stability(did))
|
||||
self.item_id.as_def_id().and_then(|did| tcx.lookup_const_stability(did))
|
||||
}
|
||||
|
||||
crate fn deprecation(&self, tcx: TyCtxt<'_>) -> Option<Deprecation> {
|
||||
self.def_id.as_def_id().and_then(|did| tcx.lookup_deprecation(did))
|
||||
self.item_id.as_def_id().and_then(|did| tcx.lookup_deprecation(did))
|
||||
}
|
||||
|
||||
crate fn inner_docs(&self, tcx: TyCtxt<'_>) -> bool {
|
||||
self.def_id.as_def_id().map(|did| tcx.get_attrs(did).inner_docs()).unwrap_or(false)
|
||||
self.item_id.as_def_id().map(|did| tcx.get_attrs(did).inner_docs()).unwrap_or(false)
|
||||
}
|
||||
|
||||
crate fn span(&self, tcx: TyCtxt<'_>) -> Span {
|
||||
@ -432,14 +432,14 @@ impl Item {
|
||||
ItemKind::ModuleItem(Module { span, .. }) => *span,
|
||||
ItemKind::ImplItem(Impl { kind: ImplKind::Auto, .. }) => Span::dummy(),
|
||||
ItemKind::ImplItem(Impl { kind: ImplKind::Blanket(_), .. }) => {
|
||||
if let ItemId::Blanket { impl_id, .. } = self.def_id {
|
||||
if let ItemId::Blanket { impl_id, .. } = self.item_id {
|
||||
rustc_span(impl_id, tcx)
|
||||
} else {
|
||||
panic!("blanket impl item has non-blanket ID")
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
self.def_id.as_def_id().map(|did| rustc_span(did, tcx)).unwrap_or_else(Span::dummy)
|
||||
self.item_id.as_def_id().map(|did| rustc_span(did, tcx)).unwrap_or_else(Span::dummy)
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -503,7 +503,7 @@ impl Item {
|
||||
cx.tcx.visibility(def_id).clean(cx)
|
||||
};
|
||||
|
||||
Item { def_id: def_id.into(), kind: box kind, name, attrs, visibility, cfg }
|
||||
Item { item_id: def_id.into(), kind: box kind, name, attrs, visibility, cfg }
|
||||
}
|
||||
|
||||
/// Finds all `doc` attributes as NameValues and returns their corresponding values, joined
|
||||
@ -517,7 +517,7 @@ impl Item {
|
||||
|
||||
cx.cache()
|
||||
.intra_doc_links
|
||||
.get(&self.def_id)
|
||||
.get(&self.item_id)
|
||||
.map_or(&[][..], |v| v.as_slice())
|
||||
.iter()
|
||||
.filter_map(|ItemLink { link: s, link_text, did, ref fragment }| {
|
||||
@ -547,7 +547,7 @@ impl Item {
|
||||
crate fn link_names(&self, cache: &Cache) -> Vec<RenderedLink> {
|
||||
cache
|
||||
.intra_doc_links
|
||||
.get(&self.def_id)
|
||||
.get(&self.item_id)
|
||||
.map_or(&[][..], |v| v.as_slice())
|
||||
.iter()
|
||||
.map(|ItemLink { link: s, link_text, .. }| RenderedLink {
|
||||
@ -559,7 +559,7 @@ impl Item {
|
||||
}
|
||||
|
||||
crate fn is_crate(&self) -> bool {
|
||||
self.is_mod() && self.def_id.as_def_id().map_or(false, |did| did.index == CRATE_DEF_INDEX)
|
||||
self.is_mod() && self.item_id.as_def_id().map_or(false, |did| did.index == CRATE_DEF_INDEX)
|
||||
}
|
||||
crate fn is_mod(&self) -> bool {
|
||||
self.type_() == ItemType::Module
|
||||
@ -695,7 +695,7 @@ impl Item {
|
||||
}
|
||||
let header = match *self.kind {
|
||||
ItemKind::ForeignFunctionItem(_) => {
|
||||
let abi = tcx.fn_sig(self.def_id.as_def_id().unwrap()).abi();
|
||||
let abi = tcx.fn_sig(self.item_id.as_def_id().unwrap()).abi();
|
||||
hir::FnHeader {
|
||||
unsafety: if abi == Abi::RustIntrinsic {
|
||||
intrinsic_operation_unsafety(self.name.unwrap())
|
||||
@ -708,11 +708,11 @@ impl Item {
|
||||
}
|
||||
}
|
||||
ItemKind::FunctionItem(_) | ItemKind::MethodItem(_, _) => {
|
||||
let def_id = self.def_id.as_def_id().unwrap();
|
||||
let def_id = self.item_id.as_def_id().unwrap();
|
||||
build_fn_header(def_id, tcx, tcx.asyncness(def_id))
|
||||
}
|
||||
ItemKind::TyMethodItem(_) => {
|
||||
build_fn_header(self.def_id.as_def_id().unwrap(), tcx, hir::IsAsync::NotAsync)
|
||||
build_fn_header(self.item_id.as_def_id().unwrap(), tcx, hir::IsAsync::NotAsync)
|
||||
}
|
||||
_ => return None,
|
||||
};
|
||||
|
@ -44,9 +44,9 @@ crate fn krate(cx: &mut DocContext<'_>) -> Crate {
|
||||
// `#[doc(masked)]` to the injected `extern crate` because it's unstable.
|
||||
if it.is_extern_crate()
|
||||
&& (it.attrs.has_doc_flag(sym::masked)
|
||||
|| cx.tcx.is_compiler_builtins(it.def_id.krate()))
|
||||
|| cx.tcx.is_compiler_builtins(it.item_id.krate()))
|
||||
{
|
||||
cx.cache.masked_crates.insert(it.def_id.krate());
|
||||
cx.cache.masked_crates.insert(it.item_id.krate());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -113,8 +113,8 @@ impl<'tcx> DocContext<'tcx> {
|
||||
|
||||
/// Like `hir().local_def_id_to_hir_id()`, but skips calling it on fake DefIds.
|
||||
/// (This avoids a slice-index-out-of-bounds panic.)
|
||||
crate fn as_local_hir_id(tcx: TyCtxt<'_>, def_id: ItemId) -> Option<HirId> {
|
||||
match def_id {
|
||||
crate fn as_local_hir_id(tcx: TyCtxt<'_>, item_id: ItemId) -> Option<HirId> {
|
||||
match item_id {
|
||||
ItemId::DefId(real_id) => {
|
||||
real_id.as_local().map(|def_id| tcx.hir().local_def_id_to_hir_id(def_id))
|
||||
}
|
||||
@ -390,7 +390,7 @@ crate fn run_global_ctxt(
|
||||
);
|
||||
tcx.struct_lint_node(
|
||||
crate::lint::MISSING_CRATE_LEVEL_DOCS,
|
||||
DocContext::as_local_hir_id(tcx, krate.module.def_id).unwrap(),
|
||||
DocContext::as_local_hir_id(tcx, krate.module.item_id).unwrap(),
|
||||
|lint| {
|
||||
let mut diag =
|
||||
lint.build("no documentation found for this crate's top-level module");
|
||||
|
@ -186,8 +186,8 @@ impl Cache {
|
||||
|
||||
impl<'a, 'tcx> DocFolder for CacheBuilder<'a, 'tcx> {
|
||||
fn fold_item(&mut self, item: clean::Item) -> Option<clean::Item> {
|
||||
if item.def_id.is_local() {
|
||||
debug!("folding {} \"{:?}\", id {:?}", item.type_(), item.name, item.def_id);
|
||||
if item.item_id.is_local() {
|
||||
debug!("folding {} \"{:?}\", id {:?}", item.type_(), item.name, item.item_id);
|
||||
}
|
||||
|
||||
// If this is a stripped module,
|
||||
@ -202,7 +202,7 @@ impl<'a, 'tcx> DocFolder for CacheBuilder<'a, 'tcx> {
|
||||
// If the impl is from a masked crate or references something from a
|
||||
// masked crate then remove it completely.
|
||||
if let clean::ImplItem(ref i) = *item.kind {
|
||||
if self.cache.masked_crates.contains(&item.def_id.krate())
|
||||
if self.cache.masked_crates.contains(&item.item_id.krate())
|
||||
|| i.trait_
|
||||
.as_ref()
|
||||
.map_or(false, |t| self.cache.masked_crates.contains(&t.def_id().krate))
|
||||
@ -217,7 +217,7 @@ impl<'a, 'tcx> DocFolder for CacheBuilder<'a, 'tcx> {
|
||||
// Propagate a trait method's documentation to all implementors of the
|
||||
// trait.
|
||||
if let clean::TraitItem(ref t) = *item.kind {
|
||||
self.cache.traits.entry(item.def_id.expect_def_id()).or_insert_with(|| {
|
||||
self.cache.traits.entry(item.item_id.expect_def_id()).or_insert_with(|| {
|
||||
clean::TraitWithExtraInfo {
|
||||
trait_: t.clone(),
|
||||
is_notable: item.attrs.has_doc_flag(sym::notable_trait),
|
||||
@ -293,7 +293,7 @@ impl<'a, 'tcx> DocFolder for CacheBuilder<'a, 'tcx> {
|
||||
// A crate has a module at its root, containing all items,
|
||||
// which should not be indexed. The crate-item itself is
|
||||
// inserted later on when serializing the search-index.
|
||||
if item.def_id.index().map_or(false, |idx| idx != CRATE_DEF_INDEX) {
|
||||
if item.item_id.index().map_or(false, |idx| idx != CRATE_DEF_INDEX) {
|
||||
let desc = item.doc_value().map_or_else(String::new, |x| {
|
||||
short_markdown_summary(x.as_str(), &item.link_names(self.cache))
|
||||
});
|
||||
@ -351,11 +351,11 @@ impl<'a, 'tcx> DocFolder for CacheBuilder<'a, 'tcx> {
|
||||
// `public_items` map, so we can skip inserting into the
|
||||
// paths map if there was already an entry present and we're
|
||||
// not a public item.
|
||||
if !self.cache.paths.contains_key(&item.def_id.expect_def_id())
|
||||
|| self.cache.access_levels.is_public(item.def_id.expect_def_id())
|
||||
if !self.cache.paths.contains_key(&item.item_id.expect_def_id())
|
||||
|| self.cache.access_levels.is_public(item.item_id.expect_def_id())
|
||||
{
|
||||
self.cache.paths.insert(
|
||||
item.def_id.expect_def_id(),
|
||||
item.item_id.expect_def_id(),
|
||||
(self.cache.stack.clone(), item.type_()),
|
||||
);
|
||||
}
|
||||
@ -364,7 +364,7 @@ impl<'a, 'tcx> DocFolder for CacheBuilder<'a, 'tcx> {
|
||||
clean::PrimitiveItem(..) => {
|
||||
self.cache
|
||||
.paths
|
||||
.insert(item.def_id.expect_def_id(), (self.cache.stack.clone(), item.type_()));
|
||||
.insert(item.item_id.expect_def_id(), (self.cache.stack.clone(), item.type_()));
|
||||
}
|
||||
|
||||
clean::ExternCrateItem { .. }
|
||||
@ -396,7 +396,7 @@ impl<'a, 'tcx> DocFolder for CacheBuilder<'a, 'tcx> {
|
||||
| clean::StructItem(..)
|
||||
| clean::UnionItem(..)
|
||||
| clean::VariantItem(..) => {
|
||||
self.cache.parent_stack.push(item.def_id.expect_def_id());
|
||||
self.cache.parent_stack.push(item.item_id.expect_def_id());
|
||||
self.cache.parent_is_trait_impl = false;
|
||||
true
|
||||
}
|
||||
|
@ -222,7 +222,7 @@ impl<'tcx> Context<'tcx> {
|
||||
&self.shared.style_files,
|
||||
)
|
||||
} else {
|
||||
if let Some(&(ref names, ty)) = self.cache().paths.get(&it.def_id.expect_def_id()) {
|
||||
if let Some(&(ref names, ty)) = self.cache().paths.get(&it.item_id.expect_def_id()) {
|
||||
if self.current.len() + 1 != names.len()
|
||||
|| self.current.iter().zip(names.iter()).any(|(a, b)| a != b)
|
||||
{
|
||||
|
@ -830,7 +830,7 @@ fn assoc_const(
|
||||
w,
|
||||
"{extra}{vis}const <a{href} class=\"constant\">{name}</a>: {ty}",
|
||||
extra = extra,
|
||||
vis = it.visibility.print_with_space(it.def_id, cx),
|
||||
vis = it.visibility.print_with_space(it.item_id, cx),
|
||||
href = assoc_href_attr(it, link, cx),
|
||||
name = it.name.as_ref().unwrap(),
|
||||
ty = ty.print(cx),
|
||||
@ -884,7 +884,7 @@ fn assoc_method(
|
||||
) {
|
||||
let header = meth.fn_header(cx.tcx()).expect("Trying to get header from a non-function item");
|
||||
let name = meth.name.as_ref().unwrap();
|
||||
let vis = meth.visibility.print_with_space(meth.def_id, cx).to_string();
|
||||
let vis = meth.visibility.print_with_space(meth.item_id, cx).to_string();
|
||||
// FIXME: Once https://github.com/rust-lang/rust/issues/67792 is implemented, we can remove
|
||||
// this condition.
|
||||
let constness = match render_mode {
|
||||
@ -2060,7 +2060,7 @@ fn small_url_encode(s: String) -> String {
|
||||
}
|
||||
|
||||
fn sidebar_assoc_items(cx: &Context<'_>, out: &mut Buffer, it: &clean::Item) {
|
||||
let did = it.def_id.expect_def_id();
|
||||
let did = it.item_id.expect_def_id();
|
||||
let cache = cx.cache();
|
||||
|
||||
if let Some(v) = cache.impls.get(&did) {
|
||||
@ -2412,7 +2412,7 @@ fn sidebar_trait(cx: &Context<'_>, buf: &mut Buffer, it: &clean::Item, t: &clean
|
||||
);
|
||||
|
||||
let cache = cx.cache();
|
||||
if let Some(implementors) = cache.implementors.get(&it.def_id.expect_def_id()) {
|
||||
if let Some(implementors) = cache.implementors.get(&it.item_id.expect_def_id()) {
|
||||
let mut res = implementors
|
||||
.iter()
|
||||
.filter(|i| {
|
||||
@ -2761,7 +2761,7 @@ const NUM_VISIBLE_LINES: usize = 10;
|
||||
/// Generates the HTML for example call locations generated via the --scrape-examples flag.
|
||||
fn render_call_locations(w: &mut Buffer, cx: &Context<'_>, item: &clean::Item) {
|
||||
let tcx = cx.tcx();
|
||||
let def_id = item.def_id.expect_def_id();
|
||||
let def_id = item.item_id.expect_def_id();
|
||||
let key = tcx.def_path_hash(def_id);
|
||||
let Some(call_locations) = cx.shared.call_locations.get(&key) else { return };
|
||||
|
||||
|
@ -264,7 +264,7 @@ fn item_module(w: &mut Buffer, cx: &Context<'_>, item: &clean::Item, items: &[cl
|
||||
// (which is the position in the vector).
|
||||
indices.dedup_by_key(|i| {
|
||||
(
|
||||
items[*i].def_id,
|
||||
items[*i].item_id,
|
||||
if items[*i].name.is_some() { Some(full_path(cx, &items[*i])) } else { None },
|
||||
items[*i].type_(),
|
||||
if items[*i].is_import() { *i } else { 0 },
|
||||
@ -306,15 +306,15 @@ fn item_module(w: &mut Buffer, cx: &Context<'_>, item: &clean::Item, items: &[cl
|
||||
Some(src) => write!(
|
||||
w,
|
||||
"<div class=\"item-left\"><code>{}extern crate {} as {};",
|
||||
myitem.visibility.print_with_space(myitem.def_id, cx),
|
||||
anchor(myitem.def_id.expect_def_id(), src, cx),
|
||||
myitem.visibility.print_with_space(myitem.item_id, cx),
|
||||
anchor(myitem.item_id.expect_def_id(), src, cx),
|
||||
myitem.name.unwrap(),
|
||||
),
|
||||
None => write!(
|
||||
w,
|
||||
"<div class=\"item-left\"><code>{}extern crate {};",
|
||||
myitem.visibility.print_with_space(myitem.def_id, cx),
|
||||
anchor(myitem.def_id.expect_def_id(), myitem.name.unwrap(), cx),
|
||||
myitem.visibility.print_with_space(myitem.item_id, cx),
|
||||
anchor(myitem.item_id.expect_def_id(), myitem.name.unwrap(), cx),
|
||||
),
|
||||
}
|
||||
w.write_str("</code></div>");
|
||||
@ -328,7 +328,7 @@ fn item_module(w: &mut Buffer, cx: &Context<'_>, item: &clean::Item, items: &[cl
|
||||
|
||||
// Just need an item with the correct def_id and attrs
|
||||
let import_item = clean::Item {
|
||||
def_id: import_def_id.into(),
|
||||
item_id: import_def_id.into(),
|
||||
attrs: import_attrs,
|
||||
cfg: ast_attrs.cfg(cx.tcx(), &cx.cache().hidden_cfg),
|
||||
..myitem.clone()
|
||||
@ -352,7 +352,7 @@ fn item_module(w: &mut Buffer, cx: &Context<'_>, item: &clean::Item, items: &[cl
|
||||
<div class=\"item-right docblock-short\">{stab_tags}</div>",
|
||||
stab = stab.unwrap_or_default(),
|
||||
add = add,
|
||||
vis = myitem.visibility.print_with_space(myitem.def_id, cx),
|
||||
vis = myitem.visibility.print_with_space(myitem.item_id, cx),
|
||||
imp = import.print(cx),
|
||||
stab_tags = stab_tags.unwrap_or_default(),
|
||||
);
|
||||
@ -468,7 +468,7 @@ fn item_function(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, f: &clean::
|
||||
let unsafety = header.unsafety.print_with_space();
|
||||
let abi = print_abi_with_space(header.abi).to_string();
|
||||
let asyncness = header.asyncness.print_with_space();
|
||||
let visibility = it.visibility.print_with_space(it.def_id, cx).to_string();
|
||||
let visibility = it.visibility.print_with_space(it.item_id, cx).to_string();
|
||||
let name = it.name.unwrap();
|
||||
|
||||
let generics_len = format!("{:#}", f.generics.print(cx)).len();
|
||||
@ -524,7 +524,7 @@ fn item_trait(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, t: &clean::Tra
|
||||
write!(
|
||||
w,
|
||||
"{}{}{}trait {}{}{}",
|
||||
it.visibility.print_with_space(it.def_id, cx),
|
||||
it.visibility.print_with_space(it.item_id, cx),
|
||||
t.unsafety.print_with_space(),
|
||||
if t.is_auto { "auto " } else { "" },
|
||||
it.name.unwrap(),
|
||||
@ -787,10 +787,10 @@ fn item_trait(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, t: &clean::Tra
|
||||
}
|
||||
|
||||
// If there are methods directly on this trait object, render them here.
|
||||
render_assoc_items(w, cx, it, it.def_id.expect_def_id(), AssocItemRender::All);
|
||||
render_assoc_items(w, cx, it, it.item_id.expect_def_id(), AssocItemRender::All);
|
||||
|
||||
let cache = cx.cache();
|
||||
if let Some(implementors) = cache.implementors.get(&it.def_id.expect_def_id()) {
|
||||
if let Some(implementors) = cache.implementors.get(&it.item_id.expect_def_id()) {
|
||||
// The DefId is for the first Type found with that name. The bool is
|
||||
// if any Types with the same name but different DefId have been found.
|
||||
let mut implementor_dups: FxHashMap<Symbol, (DefId, bool)> = FxHashMap::default();
|
||||
@ -827,7 +827,7 @@ fn item_trait(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, t: &clean::Tra
|
||||
for implementor in foreign {
|
||||
let provided_methods = implementor.inner_impl().provided_trait_methods(cx.tcx());
|
||||
let assoc_link =
|
||||
AssocItemLink::GotoSource(implementor.impl_item.def_id, &provided_methods);
|
||||
AssocItemLink::GotoSource(implementor.impl_item.item_id, &provided_methods);
|
||||
render_impl(
|
||||
w,
|
||||
cx,
|
||||
@ -902,10 +902,10 @@ fn item_trait(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, t: &clean::Tra
|
||||
.take(cx.current.len())
|
||||
.chain(std::iter::once("implementors"))
|
||||
.collect();
|
||||
if it.def_id.is_local() {
|
||||
if it.item_id.is_local() {
|
||||
js_src_path.extend(cx.current.iter().copied());
|
||||
} else {
|
||||
let (ref path, _) = cache.external_paths[&it.def_id.expect_def_id()];
|
||||
let (ref path, _) = cache.external_paths[&it.item_id.expect_def_id()];
|
||||
js_src_path.extend(path[..path.len() - 1].iter().copied());
|
||||
}
|
||||
js_src_path.push_fmt(format_args!("{}.{}.js", it.type_(), it.name.unwrap()));
|
||||
@ -937,7 +937,7 @@ fn item_trait_alias(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, t: &clea
|
||||
// won't be visible anywhere in the docs. It would be nice to also show
|
||||
// associated items from the aliased type (see discussion in #32077), but
|
||||
// we need #14072 to make sense of the generics.
|
||||
render_assoc_items(w, cx, it, it.def_id.expect_def_id(), AssocItemRender::All)
|
||||
render_assoc_items(w, cx, it, it.item_id.expect_def_id(), AssocItemRender::All)
|
||||
}
|
||||
|
||||
fn item_opaque_ty(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, t: &clean::OpaqueTy) {
|
||||
@ -961,14 +961,14 @@ fn item_opaque_ty(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, t: &clean:
|
||||
// won't be visible anywhere in the docs. It would be nice to also show
|
||||
// associated items from the aliased type (see discussion in #32077), but
|
||||
// we need #14072 to make sense of the generics.
|
||||
render_assoc_items(w, cx, it, it.def_id.expect_def_id(), AssocItemRender::All)
|
||||
render_assoc_items(w, cx, it, it.item_id.expect_def_id(), AssocItemRender::All)
|
||||
}
|
||||
|
||||
fn item_typedef(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, t: &clean::Typedef) {
|
||||
fn write_content(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, t: &clean::Typedef) {
|
||||
wrap_item(w, "typedef", |w| {
|
||||
render_attributes_in_pre(w, it, "");
|
||||
write!(w, "{}", it.visibility.print_with_space(it.def_id, cx));
|
||||
write!(w, "{}", it.visibility.print_with_space(it.item_id, cx));
|
||||
write!(
|
||||
w,
|
||||
"type {}{}{where_clause} = {type_};",
|
||||
@ -984,7 +984,7 @@ fn item_typedef(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, t: &clean::T
|
||||
|
||||
document(w, cx, it, None, HeadingOffset::H2);
|
||||
|
||||
let def_id = it.def_id.expect_def_id();
|
||||
let def_id = it.item_id.expect_def_id();
|
||||
// Render any items associated directly to this alias, as otherwise they
|
||||
// won't be visible anywhere in the docs. It would be nice to also show
|
||||
// associated items from the aliased type (see discussion in #32077), but
|
||||
@ -1037,7 +1037,7 @@ fn item_union(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, s: &clean::Uni
|
||||
document(w, cx, field, Some(it), HeadingOffset::H3);
|
||||
}
|
||||
}
|
||||
let def_id = it.def_id.expect_def_id();
|
||||
let def_id = it.item_id.expect_def_id();
|
||||
render_assoc_items(w, cx, it, def_id, AssocItemRender::All);
|
||||
document_type_layout(w, cx, def_id);
|
||||
}
|
||||
@ -1062,7 +1062,7 @@ fn item_enum(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, e: &clean::Enum
|
||||
write!(
|
||||
w,
|
||||
"{}enum {}{}{}",
|
||||
it.visibility.print_with_space(it.def_id, cx),
|
||||
it.visibility.print_with_space(it.item_id, cx),
|
||||
it.name.unwrap(),
|
||||
e.generics.print(cx),
|
||||
print_where_clause(&e.generics, cx, 0, true),
|
||||
@ -1197,7 +1197,7 @@ fn item_enum(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, e: &clean::Enum
|
||||
document(w, cx, variant, Some(it), HeadingOffset::H4);
|
||||
}
|
||||
}
|
||||
let def_id = it.def_id.expect_def_id();
|
||||
let def_id = it.item_id.expect_def_id();
|
||||
render_assoc_items(w, cx, it, def_id, AssocItemRender::All);
|
||||
document_type_layout(w, cx, def_id);
|
||||
}
|
||||
@ -1253,7 +1253,7 @@ fn item_proc_macro(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, m: &clean
|
||||
|
||||
fn item_primitive(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item) {
|
||||
document(w, cx, it, None, HeadingOffset::H2);
|
||||
render_assoc_items(w, cx, it, it.def_id.expect_def_id(), AssocItemRender::All)
|
||||
render_assoc_items(w, cx, it, it.item_id.expect_def_id(), AssocItemRender::All)
|
||||
}
|
||||
|
||||
fn item_constant(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, c: &clean::Constant) {
|
||||
@ -1264,7 +1264,7 @@ fn item_constant(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, c: &clean::
|
||||
write!(
|
||||
w,
|
||||
"{vis}const {name}: {typ}",
|
||||
vis = it.visibility.print_with_space(it.def_id, cx),
|
||||
vis = it.visibility.print_with_space(it.item_id, cx),
|
||||
name = it.name.unwrap(),
|
||||
typ = c.type_.print(cx),
|
||||
);
|
||||
@ -1344,7 +1344,7 @@ fn item_struct(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, s: &clean::St
|
||||
}
|
||||
}
|
||||
}
|
||||
let def_id = it.def_id.expect_def_id();
|
||||
let def_id = it.item_id.expect_def_id();
|
||||
render_assoc_items(w, cx, it, def_id, AssocItemRender::All);
|
||||
document_type_layout(w, cx, def_id);
|
||||
}
|
||||
@ -1356,7 +1356,7 @@ fn item_static(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, s: &clean::St
|
||||
write!(
|
||||
w,
|
||||
"{vis}static {mutability}{name}: {typ}",
|
||||
vis = it.visibility.print_with_space(it.def_id, cx),
|
||||
vis = it.visibility.print_with_space(it.item_id, cx),
|
||||
mutability = s.mutability.print_with_space(),
|
||||
name = it.name.unwrap(),
|
||||
typ = s.type_.print(cx)
|
||||
@ -1374,7 +1374,7 @@ fn item_foreign_type(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item) {
|
||||
write!(
|
||||
w,
|
||||
" {}type {};\n}}",
|
||||
it.visibility.print_with_space(it.def_id, cx),
|
||||
it.visibility.print_with_space(it.item_id, cx),
|
||||
it.name.unwrap(),
|
||||
);
|
||||
});
|
||||
@ -1382,7 +1382,7 @@ fn item_foreign_type(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item) {
|
||||
|
||||
document(w, cx, it, None, HeadingOffset::H2);
|
||||
|
||||
render_assoc_items(w, cx, it, it.def_id.expect_def_id(), AssocItemRender::All)
|
||||
render_assoc_items(w, cx, it, it.item_id.expect_def_id(), AssocItemRender::All)
|
||||
}
|
||||
|
||||
fn item_keyword(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item) {
|
||||
@ -1543,7 +1543,7 @@ fn render_union(
|
||||
tab: &str,
|
||||
cx: &Context<'_>,
|
||||
) {
|
||||
write!(w, "{}union {}", it.visibility.print_with_space(it.def_id, cx), it.name.unwrap());
|
||||
write!(w, "{}union {}", it.visibility.print_with_space(it.item_id, cx), it.name.unwrap());
|
||||
if let Some(g) = g {
|
||||
write!(w, "{}", g.print(cx));
|
||||
write!(w, "{}", print_where_clause(g, cx, 0, true));
|
||||
@ -1562,7 +1562,7 @@ fn render_union(
|
||||
write!(
|
||||
w,
|
||||
" {}{}: {},\n{}",
|
||||
field.visibility.print_with_space(field.def_id, cx),
|
||||
field.visibility.print_with_space(field.item_id, cx),
|
||||
field.name.unwrap(),
|
||||
ty.print(cx),
|
||||
tab
|
||||
@ -1592,7 +1592,7 @@ fn render_struct(
|
||||
write!(
|
||||
w,
|
||||
"{}{}{}",
|
||||
it.visibility.print_with_space(it.def_id, cx),
|
||||
it.visibility.print_with_space(it.item_id, cx),
|
||||
if structhead { "struct " } else { "" },
|
||||
it.name.unwrap()
|
||||
);
|
||||
@ -1618,7 +1618,7 @@ fn render_struct(
|
||||
w,
|
||||
"\n{} {}{}: {},",
|
||||
tab,
|
||||
field.visibility.print_with_space(field.def_id, cx),
|
||||
field.visibility.print_with_space(field.item_id, cx),
|
||||
field.name.unwrap(),
|
||||
ty.print(cx),
|
||||
);
|
||||
@ -1650,7 +1650,7 @@ fn render_struct(
|
||||
write!(
|
||||
w,
|
||||
"{}{}",
|
||||
field.visibility.print_with_space(field.def_id, cx),
|
||||
field.visibility.print_with_space(field.item_id, cx),
|
||||
ty.print(cx),
|
||||
)
|
||||
}
|
||||
|
@ -535,7 +535,7 @@ pub(super) fn write_shared(
|
||||
//
|
||||
// If the implementation is from another crate then that crate
|
||||
// should add it.
|
||||
if imp.impl_item.def_id.krate() == did.krate || !imp.impl_item.def_id.is_local() {
|
||||
if imp.impl_item.item_id.krate() == did.krate || !imp.impl_item.item_id.is_local() {
|
||||
None
|
||||
} else {
|
||||
Some(Implementor {
|
||||
|
@ -27,7 +27,7 @@ impl JsonRenderer<'_> {
|
||||
let links = self
|
||||
.cache
|
||||
.intra_doc_links
|
||||
.get(&item.def_id)
|
||||
.get(&item.item_id)
|
||||
.into_iter()
|
||||
.flatten()
|
||||
.map(|clean::ItemLink { link, did, .. }| (link.clone(), from_item_id((*did).into())))
|
||||
@ -40,14 +40,14 @@ impl JsonRenderer<'_> {
|
||||
.map(rustc_ast_pretty::pprust::attribute_to_string)
|
||||
.collect();
|
||||
let span = item.span(self.tcx);
|
||||
let clean::Item { name, attrs: _, kind: _, visibility, def_id, cfg: _ } = item;
|
||||
let clean::Item { name, attrs: _, kind: _, visibility, item_id, cfg: _ } = item;
|
||||
let inner = match *item.kind {
|
||||
clean::StrippedItem(_) => return None,
|
||||
_ => from_clean_item(item, self.tcx),
|
||||
};
|
||||
Some(Item {
|
||||
id: from_item_id(def_id),
|
||||
crate_id: def_id.krate().as_u32(),
|
||||
id: from_item_id(item_id),
|
||||
crate_id: item_id.krate().as_u32(),
|
||||
name: name.map(|sym| sym.to_string()),
|
||||
span: self.convert_span(span),
|
||||
visibility: self.convert_visibility(visibility),
|
||||
@ -174,7 +174,7 @@ impl FromWithTcx<clean::TypeBindingKind> for TypeBindingKind {
|
||||
}
|
||||
}
|
||||
|
||||
crate fn from_item_id(did: ItemId) -> Id {
|
||||
crate fn from_item_id(item_id: ItemId) -> Id {
|
||||
struct DisplayDefId(DefId);
|
||||
|
||||
impl fmt::Display for DisplayDefId {
|
||||
@ -183,7 +183,7 @@ crate fn from_item_id(did: ItemId) -> Id {
|
||||
}
|
||||
}
|
||||
|
||||
match did {
|
||||
match item_id {
|
||||
ItemId::DefId(did) => Id(format!("{}", DisplayDefId(did))),
|
||||
ItemId::Blanket { for_, impl_id } => {
|
||||
Id(format!("b:{}-{}", DisplayDefId(impl_id), DisplayDefId(for_)))
|
||||
@ -732,5 +732,5 @@ impl FromWithTcx<ItemType> for ItemKind {
|
||||
}
|
||||
|
||||
fn ids(items: impl IntoIterator<Item = clean::Item>) -> Vec<Id> {
|
||||
items.into_iter().filter(|x| !x.is_stripped()).map(|i| from_item_id(i.def_id)).collect()
|
||||
items.into_iter().filter(|x| !x.is_stripped()).map(|i| from_item_id(i.item_id)).collect()
|
||||
}
|
||||
|
@ -54,7 +54,7 @@ impl<'tcx> JsonRenderer<'tcx> {
|
||||
.map(|i| {
|
||||
let item = &i.impl_item;
|
||||
self.item(item.clone()).unwrap();
|
||||
from_item_id(item.def_id)
|
||||
from_item_id(item.item_id)
|
||||
})
|
||||
.collect()
|
||||
})
|
||||
@ -84,9 +84,9 @@ impl<'tcx> JsonRenderer<'tcx> {
|
||||
}
|
||||
}
|
||||
|
||||
if item.def_id.is_local() || is_primitive_impl {
|
||||
if item.item_id.is_local() || is_primitive_impl {
|
||||
self.item(item.clone()).unwrap();
|
||||
Some(from_item_id(item.def_id))
|
||||
Some(from_item_id(item.item_id))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
@ -176,18 +176,18 @@ impl<'tcx> FormatRenderer<'tcx> for JsonRenderer<'tcx> {
|
||||
// Flatten items that recursively store other items
|
||||
item.kind.inner_items().for_each(|i| self.item(i.clone()).unwrap());
|
||||
|
||||
let id = item.def_id;
|
||||
let item_id = item.item_id;
|
||||
if let Some(mut new_item) = self.convert_item(item) {
|
||||
if let types::ItemEnum::Trait(ref mut t) = new_item.inner {
|
||||
t.implementations = self.get_trait_implementors(id.expect_def_id())
|
||||
t.implementations = self.get_trait_implementors(item_id.expect_def_id())
|
||||
} else if let types::ItemEnum::Struct(ref mut s) = new_item.inner {
|
||||
s.impls = self.get_impls(id.expect_def_id())
|
||||
s.impls = self.get_impls(item_id.expect_def_id())
|
||||
} else if let types::ItemEnum::Enum(ref mut e) = new_item.inner {
|
||||
e.impls = self.get_impls(id.expect_def_id())
|
||||
e.impls = self.get_impls(item_id.expect_def_id())
|
||||
} else if let types::ItemEnum::Union(ref mut u) = new_item.inner {
|
||||
u.impls = self.get_impls(id.expect_def_id())
|
||||
u.impls = self.get_impls(item_id.expect_def_id())
|
||||
}
|
||||
let removed = self.index.borrow_mut().insert(from_item_id(id), new_item.clone());
|
||||
let removed = self.index.borrow_mut().insert(from_item_id(item_id), new_item.clone());
|
||||
|
||||
// FIXME(adotinthevoid): Currently, the index is duplicated. This is a sanity check
|
||||
// to make sure the items are unique. The main place this happens is when an item, is
|
||||
|
@ -61,7 +61,7 @@ crate fn check_bare_urls(krate: Crate, cx: &mut DocContext<'_>) -> Crate {
|
||||
|
||||
impl<'a, 'tcx> DocVisitor for BareUrlsLinter<'a, 'tcx> {
|
||||
fn visit_item(&mut self, item: &Item) {
|
||||
let Some(hir_id) = DocContext::as_local_hir_id(self.cx.tcx, item.def_id)
|
||||
let Some(hir_id) = DocContext::as_local_hir_id(self.cx.tcx, item.item_id)
|
||||
else {
|
||||
// If non-local, no need to check anything.
|
||||
return;
|
||||
|
@ -185,7 +185,7 @@ impl<'a, 'b> CoverageCalculator<'a, 'b> {
|
||||
|
||||
impl<'a, 'b> DocVisitor for CoverageCalculator<'a, 'b> {
|
||||
fn visit_item(&mut self, i: &clean::Item) {
|
||||
if !i.def_id.is_local() {
|
||||
if !i.item_id.is_local() {
|
||||
// non-local items are skipped because they can be out of the users control,
|
||||
// especially in the case of trait impls, which rustdoc eagerly inlines
|
||||
return;
|
||||
@ -223,7 +223,7 @@ impl<'a, 'b> DocVisitor for CoverageCalculator<'a, 'b> {
|
||||
.ctx
|
||||
.tcx
|
||||
.hir()
|
||||
.local_def_id_to_hir_id(i.def_id.expect_def_id().expect_local());
|
||||
.local_def_id_to_hir_id(i.item_id.expect_def_id().expect_local());
|
||||
let (level, source) = self.ctx.tcx.lint_level_at_node(MISSING_DOCS, hir_id);
|
||||
|
||||
// In case we have:
|
||||
@ -237,7 +237,7 @@ impl<'a, 'b> DocVisitor for CoverageCalculator<'a, 'b> {
|
||||
// there is no need to require documentation on the fields of tuple variants and
|
||||
// tuple structs.
|
||||
let should_be_ignored = i
|
||||
.def_id
|
||||
.item_id
|
||||
.as_def_id()
|
||||
.and_then(|def_id| self.ctx.tcx.parent(def_id))
|
||||
.and_then(|def_id| self.ctx.tcx.hir().get_if_local(def_id))
|
||||
|
@ -69,7 +69,7 @@ impl<'a, 'tcx> SyntaxChecker<'a, 'tcx> {
|
||||
return;
|
||||
}
|
||||
|
||||
let Some(local_id) = item.def_id.as_def_id().and_then(|x| x.as_local())
|
||||
let Some(local_id) = item.item_id.as_def_id().and_then(|x| x.as_local())
|
||||
else {
|
||||
// We don't need to check the syntax for other crates so returning
|
||||
// without doing anything should not be a problem.
|
||||
@ -153,7 +153,7 @@ impl<'a, 'tcx> DocVisitor for SyntaxChecker<'a, 'tcx> {
|
||||
let sp = item.attr_span(self.cx.tcx);
|
||||
let extra = crate::html::markdown::ExtraInfo::new_did(
|
||||
self.cx.tcx,
|
||||
item.def_id.expect_def_id(),
|
||||
item.item_id.expect_def_id(),
|
||||
sp,
|
||||
);
|
||||
for code_block in markdown::rust_code_blocks(dox, &extra) {
|
||||
|
@ -56,7 +56,7 @@ impl crate::doctest::Tester for Tests {
|
||||
}
|
||||
|
||||
crate fn should_have_doc_example(cx: &DocContext<'_>, item: &clean::Item) -> bool {
|
||||
if !cx.cache.access_levels.is_public(item.def_id.expect_def_id())
|
||||
if !cx.cache.access_levels.is_public(item.item_id.expect_def_id())
|
||||
|| matches!(
|
||||
*item.kind,
|
||||
clean::StructFieldItem(_)
|
||||
@ -79,7 +79,7 @@ crate fn should_have_doc_example(cx: &DocContext<'_>, item: &clean::Item) -> boo
|
||||
|
||||
// The `expect_def_id()` should be okay because `local_def_id_to_hir_id`
|
||||
// would presumably panic if a fake `DefIndex` were passed.
|
||||
let hir_id = cx.tcx.hir().local_def_id_to_hir_id(item.def_id.expect_def_id().expect_local());
|
||||
let hir_id = cx.tcx.hir().local_def_id_to_hir_id(item.item_id.expect_def_id().expect_local());
|
||||
|
||||
// check if parent is trait impl
|
||||
if let Some(parent_hir_id) = cx.tcx.hir().find_parent_node(hir_id) {
|
||||
@ -107,7 +107,7 @@ crate fn should_have_doc_example(cx: &DocContext<'_>, item: &clean::Item) -> boo
|
||||
}
|
||||
|
||||
crate fn look_for_tests<'tcx>(cx: &DocContext<'tcx>, dox: &str, item: &Item) {
|
||||
let Some(hir_id) = DocContext::as_local_hir_id(cx.tcx, item.def_id)
|
||||
let Some(hir_id) = DocContext::as_local_hir_id(cx.tcx, item.item_id)
|
||||
else {
|
||||
// If non-local, no need to check anything.
|
||||
return;
|
||||
@ -131,7 +131,7 @@ crate fn look_for_tests<'tcx>(cx: &DocContext<'tcx>, dox: &str, item: &Item) {
|
||||
);
|
||||
}
|
||||
} else if tests.found_tests > 0
|
||||
&& !cx.cache.access_levels.is_exported(item.def_id.expect_def_id())
|
||||
&& !cx.cache.access_levels.is_exported(item.item_id.expect_def_id())
|
||||
{
|
||||
cx.tcx.struct_span_lint_hir(
|
||||
crate::lint::PRIVATE_DOC_TESTS,
|
||||
|
@ -1025,15 +1025,15 @@ fn is_derive_trait_collision<T>(ns: &PerNS<Result<(Res, T), ResolutionFailure<'_
|
||||
impl<'a, 'tcx> DocVisitor for LinkCollector<'a, 'tcx> {
|
||||
fn visit_item(&mut self, item: &Item) {
|
||||
let parent_node =
|
||||
item.def_id.as_def_id().and_then(|did| find_nearest_parent_module(self.cx.tcx, did));
|
||||
item.item_id.as_def_id().and_then(|did| find_nearest_parent_module(self.cx.tcx, did));
|
||||
if parent_node.is_some() {
|
||||
trace!("got parent node for {:?} {:?}, id {:?}", item.type_(), item.name, item.def_id);
|
||||
trace!("got parent node for {:?} {:?}, id {:?}", item.type_(), item.name, item.item_id);
|
||||
}
|
||||
|
||||
let inner_docs = item.inner_docs(self.cx.tcx);
|
||||
|
||||
if item.is_mod() && inner_docs {
|
||||
self.mod_ids.push(item.def_id.expect_def_id());
|
||||
self.mod_ids.push(item.item_id.expect_def_id());
|
||||
}
|
||||
|
||||
// We want to resolve in the lexical scope of the documentation.
|
||||
@ -1048,14 +1048,14 @@ impl<'a, 'tcx> DocVisitor for LinkCollector<'a, 'tcx> {
|
||||
for md_link in markdown_links(&doc) {
|
||||
let link = self.resolve_link(&item, &doc, parent_node, md_link);
|
||||
if let Some(link) = link {
|
||||
self.cx.cache.intra_doc_links.entry(item.def_id).or_default().push(link);
|
||||
self.cx.cache.intra_doc_links.entry(item.item_id).or_default().push(link);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if item.is_mod() {
|
||||
if !inner_docs {
|
||||
self.mod_ids.push(item.def_id.expect_def_id());
|
||||
self.mod_ids.push(item.item_id.expect_def_id());
|
||||
}
|
||||
|
||||
self.visit_item_recur(item);
|
||||
@ -1246,7 +1246,7 @@ impl LinkCollector<'_, '_> {
|
||||
|
||||
let (mut res, fragment) = self.resolve_with_disambiguator_cached(
|
||||
ResolutionInfo {
|
||||
item_id: item.def_id,
|
||||
item_id: item.item_id,
|
||||
module_id,
|
||||
dis: disambiguator,
|
||||
path_str: path_str.to_owned(),
|
||||
@ -1302,7 +1302,7 @@ impl LinkCollector<'_, '_> {
|
||||
// FIXME: it would be nice to check that the feature gate was enabled in the original crate, not just ignore it altogether.
|
||||
// However I'm not sure how to check that across crates.
|
||||
if prim == PrimitiveType::RawPointer
|
||||
&& item.def_id.is_local()
|
||||
&& item.item_id.is_local()
|
||||
&& !self.cx.tcx.features().intra_doc_pointers
|
||||
{
|
||||
self.report_rawptr_assoc_feature_gate(dox, &ori_link, item);
|
||||
@ -1386,7 +1386,7 @@ impl LinkCollector<'_, '_> {
|
||||
// The `expect_def_id()` should be okay because `local_def_id_to_hir_id`
|
||||
// would presumably panic if a fake `DefIndex` were passed.
|
||||
.and_then(|dst_id| {
|
||||
item.def_id.expect_def_id().as_local().map(|src_id| (src_id, dst_id))
|
||||
item.item_id.expect_def_id().as_local().map(|src_id| (src_id, dst_id))
|
||||
})
|
||||
{
|
||||
if self.cx.tcx.privacy_access_levels(()).is_exported(src_id)
|
||||
@ -1864,7 +1864,7 @@ fn report_diagnostic(
|
||||
DiagnosticInfo { item, ori_link: _, dox, link_range }: &DiagnosticInfo<'_>,
|
||||
decorate: impl FnOnce(&mut Diagnostic, Option<rustc_span::Span>),
|
||||
) {
|
||||
let Some(hir_id) = DocContext::as_local_hir_id(tcx, item.def_id)
|
||||
let Some(hir_id) = DocContext::as_local_hir_id(tcx, item.item_id)
|
||||
else {
|
||||
// If non-local, no need to check anything.
|
||||
info!("ignoring warning from parent crate: {}", msg);
|
||||
|
@ -52,7 +52,7 @@ crate fn collect_trait_impls(mut krate: Crate, cx: &mut DocContext<'_>) -> Crate
|
||||
// FIXME(eddyb) is this `doc(hidden)` check needed?
|
||||
if !cx.tcx.is_doc_hidden(def_id) {
|
||||
let impls = get_auto_trait_and_blanket_impls(cx, def_id);
|
||||
new_items.extend(impls.filter(|i| cx.inlined.insert(i.def_id)));
|
||||
new_items.extend(impls.filter(|i| cx.inlined.insert(i.item_id)));
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -176,9 +176,9 @@ impl<'a, 'tcx> DocVisitor for SyntheticImplCollector<'a, 'tcx> {
|
||||
fn visit_item(&mut self, i: &Item) {
|
||||
if i.is_struct() || i.is_enum() || i.is_union() {
|
||||
// FIXME(eddyb) is this `doc(hidden)` check needed?
|
||||
if !self.cx.tcx.is_doc_hidden(i.def_id.expect_def_id()) {
|
||||
if !self.cx.tcx.is_doc_hidden(i.item_id.expect_def_id()) {
|
||||
self.impls
|
||||
.extend(get_auto_trait_and_blanket_impls(self.cx, i.def_id.expect_def_id()));
|
||||
.extend(get_auto_trait_and_blanket_impls(self.cx, i.item_id.expect_def_id()));
|
||||
}
|
||||
}
|
||||
|
||||
@ -199,7 +199,7 @@ impl ItemCollector {
|
||||
|
||||
impl DocVisitor for ItemCollector {
|
||||
fn visit_item(&mut self, i: &Item) {
|
||||
self.items.insert(i.def_id);
|
||||
self.items.insert(i.item_id);
|
||||
|
||||
self.visit_item_recur(i)
|
||||
}
|
||||
@ -225,7 +225,7 @@ impl<'a> BadImplStripper<'a> {
|
||||
}
|
||||
}
|
||||
|
||||
fn keep_impl_with_def_id(&self, did: ItemId) -> bool {
|
||||
self.items.contains(&did)
|
||||
fn keep_impl_with_def_id(&self, item_id: ItemId) -> bool {
|
||||
self.items.contains(&item_id)
|
||||
}
|
||||
}
|
||||
|
@ -197,7 +197,7 @@ fn extract_tags(
|
||||
impl<'a, 'tcx> DocVisitor for InvalidHtmlTagsLinter<'a, 'tcx> {
|
||||
fn visit_item(&mut self, item: &Item) {
|
||||
let tcx = self.cx.tcx;
|
||||
let Some(hir_id) = DocContext::as_local_hir_id(tcx, item.def_id)
|
||||
let Some(hir_id) = DocContext::as_local_hir_id(tcx, item.item_id)
|
||||
// If non-local, no need to check anything.
|
||||
else { return };
|
||||
let dox = item.attrs.collapsed_doc_value().unwrap_or_default();
|
||||
|
@ -53,7 +53,7 @@ impl<'a> DocFolder for Stripper<'a> {
|
||||
}
|
||||
} else {
|
||||
if self.update_retained {
|
||||
self.retained.insert(i.def_id);
|
||||
self.retained.insert(i.item_id);
|
||||
}
|
||||
}
|
||||
Some(self.fold_item_recur(i))
|
||||
|
@ -45,7 +45,8 @@ impl<'a> DocFolder for Stripper<'a> {
|
||||
| clean::TraitAliasItem(..)
|
||||
| clean::MacroItem(..)
|
||||
| clean::ForeignTypeItem => {
|
||||
if i.def_id.is_local() && !self.access_levels.is_exported(i.def_id.expect_def_id())
|
||||
if i.item_id.is_local()
|
||||
&& !self.access_levels.is_exported(i.item_id.expect_def_id())
|
||||
{
|
||||
debug!("Stripper: stripping {:?} {:?}", i.type_(), i.name);
|
||||
return None;
|
||||
@ -59,7 +60,7 @@ impl<'a> DocFolder for Stripper<'a> {
|
||||
}
|
||||
|
||||
clean::ModuleItem(..) => {
|
||||
if i.def_id.is_local() && !i.visibility.is_public() {
|
||||
if i.item_id.is_local() && !i.visibility.is_public() {
|
||||
debug!("Stripper: stripping module {:?}", i.name);
|
||||
let old = mem::replace(&mut self.update_retained, false);
|
||||
let ret = strip_item(self.fold_item_recur(i));
|
||||
@ -100,7 +101,7 @@ impl<'a> DocFolder for Stripper<'a> {
|
||||
|
||||
let i = if fastreturn {
|
||||
if self.update_retained {
|
||||
self.retained.insert(i.def_id);
|
||||
self.retained.insert(i.item_id);
|
||||
}
|
||||
return Some(i);
|
||||
} else {
|
||||
@ -108,7 +109,7 @@ impl<'a> DocFolder for Stripper<'a> {
|
||||
};
|
||||
|
||||
if self.update_retained {
|
||||
self.retained.insert(i.def_id);
|
||||
self.retained.insert(i.item_id);
|
||||
}
|
||||
Some(i)
|
||||
}
|
||||
|
@ -1,6 +1,8 @@
|
||||
// pp-exact
|
||||
|
||||
#![feature(box_syntax)]
|
||||
#![feature(inline_const)]
|
||||
#![feature(inline_const_pat)]
|
||||
#![feature(rustc_attrs)]
|
||||
#![feature(stmt_expr_attributes)]
|
||||
|
||||
@ -16,6 +18,7 @@ fn _1() {
|
||||
|
||||
#[rustc_dummy]
|
||||
unsafe {
|
||||
#![rustc_dummy]
|
||||
// code
|
||||
}
|
||||
}
|
||||
@ -206,6 +209,12 @@ fn _11() {
|
||||
let _ = ();
|
||||
()
|
||||
};
|
||||
let const {
|
||||
#![rustc_dummy]
|
||||
} =
|
||||
#[rustc_dummy] const {
|
||||
#![rustc_dummy]
|
||||
};
|
||||
let mut x = 0;
|
||||
let _ = #[rustc_dummy] x = 15;
|
||||
let _ = #[rustc_dummy] x += 15;
|
||||
|
30
src/test/ui/thread-local/non-static.rs
Normal file
30
src/test/ui/thread-local/non-static.rs
Normal file
@ -0,0 +1,30 @@
|
||||
// Check that #[thread_local] attribute is rejected on non-static items.
|
||||
#![feature(thread_local)]
|
||||
|
||||
#[thread_local]
|
||||
//~^ ERROR attribute should be applied to a static
|
||||
const A: u32 = 0;
|
||||
|
||||
#[thread_local]
|
||||
//~^ ERROR attribute should be applied to a static
|
||||
fn main() {
|
||||
#[thread_local] || {};
|
||||
//~^ ERROR attribute should be applied to a static
|
||||
}
|
||||
|
||||
struct S {
|
||||
#[thread_local]
|
||||
//~^ ERROR attribute should be applied to a static
|
||||
a: String,
|
||||
b: String,
|
||||
}
|
||||
|
||||
#[thread_local]
|
||||
// Static. OK.
|
||||
static B: u32 = 0;
|
||||
|
||||
extern "C" {
|
||||
#[thread_local]
|
||||
// Foreign static. OK.
|
||||
static C: u32;
|
||||
}
|
38
src/test/ui/thread-local/non-static.stderr
Normal file
38
src/test/ui/thread-local/non-static.stderr
Normal file
@ -0,0 +1,38 @@
|
||||
error: attribute should be applied to a static
|
||||
--> $DIR/non-static.rs:4:1
|
||||
|
|
||||
LL | #[thread_local]
|
||||
| ^^^^^^^^^^^^^^^
|
||||
LL |
|
||||
LL | const A: u32 = 0;
|
||||
| ----------------- not a static
|
||||
|
||||
error: attribute should be applied to a static
|
||||
--> $DIR/non-static.rs:8:1
|
||||
|
|
||||
LL | #[thread_local]
|
||||
| ^^^^^^^^^^^^^^^
|
||||
LL |
|
||||
LL | / fn main() {
|
||||
LL | | #[thread_local] || {};
|
||||
LL | |
|
||||
LL | | }
|
||||
| |_- not a static
|
||||
|
||||
error: attribute should be applied to a static
|
||||
--> $DIR/non-static.rs:11:5
|
||||
|
|
||||
LL | #[thread_local] || {};
|
||||
| ^^^^^^^^^^^^^^^ ----- not a static
|
||||
|
||||
error: attribute should be applied to a static
|
||||
--> $DIR/non-static.rs:16:5
|
||||
|
|
||||
LL | #[thread_local]
|
||||
| ^^^^^^^^^^^^^^^
|
||||
LL |
|
||||
LL | a: String,
|
||||
| --------- not a static
|
||||
|
||||
error: aborting due to 4 previous errors
|
||||
|
@ -9,6 +9,6 @@ clap = "2.25.0"
|
||||
env_logger = "0.7.1"
|
||||
|
||||
[dependencies.mdbook]
|
||||
version = "0.4.14"
|
||||
version = "0.4.18"
|
||||
default-features = false
|
||||
features = ["search"]
|
||||
|
Loading…
x
Reference in New Issue
Block a user