提交 14c0c3e5 编写于 作者: B bors

Auto merge of #87095 - JohnTitor:rollup-mn7ggy2, r=JohnTitor

Rollup of 11 pull requests

Successful merges:

 - #86344 (Split MaybeUninit::write into new feature gate and stabilize it)
 - #86811 (Remove unstable `io::Cursor::remaining`)
 - #86846 (stdio_locked: add tracking issue)
 - #86887 (rustdoc: remove dead code in `clean`)
 - #87007 (Fix rust-analyzer install when not available.)
 - #87035 (Fix implementors display)
 - #87065 (Fix ICE with unsized type in const pattern)
 - #87070 (Simplify future incompatible reporting.)
 - #87077 ( rust-analyzer)
 - #87078 (Rustdoc: suggest removing disambiguator if linking to field)
 - #87089 (CTFE engine: small cleanups)

Failed merges:

r? `@ghost`
`@rustbot` modify labels: rollup
......@@ -72,4 +72,7 @@ __pycache__/
**node_modules
**package-lock.json
## Rustdoc GUI tests
src/test/rustdoc-gui/src/**.lock
# Before adding new lines, see the comment at the top.
......@@ -9,7 +9,6 @@
use Destination::*;
use rustc_lint_defs::FutureBreakage;
use rustc_span::source_map::SourceMap;
use rustc_span::{MultiSpan, SourceFile, Span};
......@@ -193,7 +192,7 @@ pub trait Emitter {
/// other formats can, and will, simply ignore it.
fn emit_artifact_notification(&mut self, _path: &Path, _artifact_type: &str) {}
fn emit_future_breakage_report(&mut self, _diags: Vec<(FutureBreakage, Diagnostic)>) {}
fn emit_future_breakage_report(&mut self, _diags: Vec<Diagnostic>) {}
/// Emit list of unused externs
fn emit_unused_externs(&mut self, _lint_level: &str, _unused_externs: &[&str]) {}
......
......@@ -16,7 +16,7 @@
use crate::DiagnosticId;
use crate::ToolMetadata;
use crate::{CodeSuggestion, SubDiagnostic};
use rustc_lint_defs::{Applicability, FutureBreakage};
use rustc_lint_defs::Applicability;
use rustc_data_structures::sync::Lrc;
use rustc_span::hygiene::ExpnData;
......@@ -134,17 +134,14 @@ fn emit_artifact_notification(&mut self, path: &Path, artifact_type: &str) {
}
}
fn emit_future_breakage_report(&mut self, diags: Vec<(FutureBreakage, crate::Diagnostic)>) {
fn emit_future_breakage_report(&mut self, diags: Vec<crate::Diagnostic>) {
let data: Vec<FutureBreakageItem> = diags
.into_iter()
.map(|(breakage, mut diag)| {
.map(|mut diag| {
if diag.level == crate::Level::Allow {
diag.level = crate::Level::Warning;
}
FutureBreakageItem {
future_breakage_date: breakage.date,
diagnostic: Diagnostic::from_errors_diagnostic(&diag, self),
}
FutureBreakageItem { diagnostic: Diagnostic::from_errors_diagnostic(&diag, self) }
})
.collect();
let report = FutureIncompatReport { future_incompat_report: data };
......@@ -326,7 +323,6 @@ struct ArtifactNotification<'a> {
#[derive(Encodable)]
struct FutureBreakageItem {
future_breakage_date: Option<&'static str>,
diagnostic: Diagnostic,
}
......
......@@ -23,7 +23,6 @@
use rustc_data_structures::stable_hasher::StableHasher;
use rustc_data_structures::sync::{self, Lock, Lrc};
use rustc_data_structures::AtomicRef;
use rustc_lint_defs::FutureBreakage;
pub use rustc_lint_defs::{pluralize, Applicability};
use rustc_serialize::json::Json;
use rustc_serialize::{Decodable, Decoder, Encodable, Encoder};
......@@ -790,7 +789,7 @@ pub fn emit_artifact_notification(&self, path: &Path, artifact_type: &str) {
self.inner.borrow_mut().emit_artifact_notification(path, artifact_type)
}
pub fn emit_future_breakage_report(&self, diags: Vec<(FutureBreakage, Diagnostic)>) {
pub fn emit_future_breakage_report(&self, diags: Vec<Diagnostic>) {
self.inner.borrow_mut().emitter.emit_future_breakage_report(diags)
}
......
......@@ -6,7 +6,7 @@
//! compiler code, rather than using their own custom pass. Those
//! lints are all available in `rustc_lint::builtin`.
use crate::{declare_lint, declare_lint_pass, FutureBreakage, FutureIncompatibilityReason};
use crate::{declare_lint, declare_lint_pass, FutureIncompatibilityReason};
use rustc_span::edition::Edition;
declare_lint! {
......@@ -3176,9 +3176,7 @@
"detects usage of old versions of certain proc-macro crates",
@future_incompatible = FutureIncompatibleInfo {
reference: "issue #83125 <https://github.com/rust-lang/rust/issues/83125>",
future_breakage: Some(FutureBreakage {
date: None
})
reason: FutureIncompatibilityReason::FutureReleaseErrorReportNow,
};
}
......
......@@ -152,10 +152,6 @@ pub struct FutureIncompatibleInfo {
/// Set to false for lints that already include a more detailed
/// explanation.
pub explain_reason: bool,
/// Information about a future breakage, which will
/// be emitted in JSON messages to be displayed by Cargo
/// for upstream deps
pub future_breakage: Option<FutureBreakage>,
}
/// The reason for future incompatibility
......@@ -164,6 +160,9 @@ pub enum FutureIncompatibilityReason {
/// This will be an error in a future release
/// for all editions
FutureReleaseError,
/// This will be an error in a future release, and
/// Cargo should create a report even for dependencies
FutureReleaseErrorReportNow,
/// Previously accepted code that will become an
/// error in the provided edition
EditionError(Edition),
......@@ -182,18 +181,12 @@ pub fn edition(self) -> Option<Edition> {
}
}
#[derive(Copy, Clone, Debug)]
pub struct FutureBreakage {
pub date: Option<&'static str>,
}
impl FutureIncompatibleInfo {
pub const fn default_fields_for_macro() -> Self {
FutureIncompatibleInfo {
reference: "",
reason: FutureIncompatibilityReason::FutureReleaseError,
explain_reason: true,
future_breakage: None,
}
}
}
......
......@@ -8,7 +8,7 @@
use rustc_index::vec::IndexVec;
use rustc_session::lint::{
builtin::{self, FORBIDDEN_LINT_GROUPS},
FutureIncompatibilityReason, Level, Lint, LintId,
FutureIncompatibilityReason, FutureIncompatibleInfo, Level, Lint, LintId,
};
use rustc_session::{DiagnosticMessageId, Session};
use rustc_span::hygiene::MacroKind;
......@@ -223,8 +223,13 @@ fn struct_lint_level_impl(
let lint_id = LintId::of(lint);
let future_incompatible = lint.future_incompatible;
let has_future_breakage =
future_incompatible.map_or(false, |incompat| incompat.future_breakage.is_some());
let has_future_breakage = matches!(
future_incompatible,
Some(FutureIncompatibleInfo {
reason: FutureIncompatibilityReason::FutureReleaseErrorReportNow,
..
})
);
let mut err = match (level, span) {
(Level::Allow, span) => {
......
......@@ -512,7 +512,7 @@ pub fn no_bytes_init(&self) -> bool {
/// Transferring the initialization mask to other allocations.
impl<Tag, Extra> Allocation<Tag, Extra> {
/// Creates a run-length encoding of the initialization mask.
pub fn compress_uninit_range(&self, src: Pointer<Tag>, size: Size) -> InitMaskCompressed {
pub fn compress_uninit_range(&self, range: AllocRange) -> InitMaskCompressed {
// Since we are copying `size` bytes from `src` to `dest + i * size` (`for i in 0..repeat`),
// a naive initialization mask copying algorithm would repeatedly have to read the initialization mask from
// the source and write it to the destination. Even if we optimized the memory accesses,
......@@ -526,13 +526,13 @@ pub fn compress_uninit_range(&self, src: Pointer<Tag>, size: Size) -> InitMaskCo
// where each element toggles the state.
let mut ranges = smallvec::SmallVec::<[u64; 1]>::new();
let initial = self.init_mask.get(src.offset);
let initial = self.init_mask.get(range.start);
let mut cur_len = 1;
let mut cur = initial;
for i in 1..size.bytes() {
for i in 1..range.size.bytes() {
// FIXME: optimize to bitshift the current uninitialized block's bits and read the top bit.
if self.init_mask.get(src.offset + Size::from_bytes(i)) == cur {
if self.init_mask.get(range.start + Size::from_bytes(i)) == cur {
cur_len += 1;
} else {
ranges.push(cur_len);
......@@ -550,24 +550,23 @@ pub fn compress_uninit_range(&self, src: Pointer<Tag>, size: Size) -> InitMaskCo
pub fn mark_compressed_init_range(
&mut self,
defined: &InitMaskCompressed,
dest: Pointer<Tag>,
size: Size,
range: AllocRange,
repeat: u64,
) {
// An optimization where we can just overwrite an entire range of initialization
// bits if they are going to be uniformly `1` or `0`.
if defined.ranges.len() <= 1 {
self.init_mask.set_range_inbounds(
dest.offset,
dest.offset + size * repeat, // `Size` operations
range.start,
range.start + range.size * repeat, // `Size` operations
defined.initial,
);
return;
}
for mut j in 0..repeat {
j *= size.bytes();
j += dest.offset.bytes();
j *= range.size.bytes();
j += range.start.bytes();
let mut cur = defined.initial;
for range in &defined.ranges {
let old_j = j;
......
......@@ -18,8 +18,8 @@
use rustc_target::abi::{Align, HasDataLayout, LayoutOf, Size, TargetDataLayout};
use super::{
Immediate, MPlaceTy, Machine, MemPlace, MemPlaceMeta, Memory, Operand, Place, PlaceTy,
ScalarMaybeUninit, StackPopJump,
Immediate, MPlaceTy, Machine, MemPlace, MemPlaceMeta, Memory, MemoryKind, Operand, Place,
PlaceTy, ScalarMaybeUninit, StackPopJump,
};
use crate::transform::validate::equal_up_to_regions;
use crate::util::storage::AlwaysLiveLocals;
......@@ -900,7 +900,7 @@ fn deallocate_local(&mut self, local: LocalValue<M::PointerTag>) -> InterpResult
// due to the local having ZST type.
let ptr = ptr.assert_ptr();
trace!("deallocating local: {:?}", self.memory.dump_alloc(ptr.alloc_id));
self.memory.deallocate_local(ptr)?;
self.memory.deallocate(ptr, None, MemoryKind::Stack)?;
};
Ok(())
}
......
......@@ -276,17 +276,6 @@ pub fn reallocate(
Ok(new_ptr)
}
/// Deallocate a local, or do nothing if that local has been made into a global.
pub fn deallocate_local(&mut self, ptr: Pointer<M::PointerTag>) -> InterpResult<'tcx> {
// The allocation might be already removed by global interning.
// This can only really happen in the CTFE instance, not in miri.
if self.alloc_map.contains_key(&ptr.alloc_id) {
self.deallocate(ptr, None, MemoryKind::Stack)
} else {
Ok(())
}
}
pub fn deallocate(
&mut self,
ptr: Pointer<M::PointerTag>,
......@@ -1049,7 +1038,7 @@ pub fn copy_repeatedly(
num_copies,
);
// Prepare a copy of the initialization mask.
let compressed = src_alloc.compress_uninit_range(src, size);
let compressed = src_alloc.compress_uninit_range(alloc_range(src.offset, size));
// This checks relocation edges on the src.
let src_bytes = src_alloc
.get_bytes_with_uninit_and_ptr(&tcx, alloc_range(src.offset, size))
......@@ -1110,7 +1099,11 @@ pub fn copy_repeatedly(
}
// now fill in all the "init" data
dest_alloc.mark_compressed_init_range(&compressed, dest, size, num_copies);
dest_alloc.mark_compressed_init_range(
&compressed,
alloc_range(dest.offset, size),
num_copies,
);
// copy the relocations to the destination
dest_alloc.mark_relocation_range(relocations);
......
......@@ -490,17 +490,29 @@ fn recur(
// convert the dereferenced constant to a pattern that is the sub-pattern of the
// deref pattern.
_ => {
let old = self.behind_reference.replace(true);
// In case there are structural-match violations somewhere in this subpattern,
// we fall back to a const pattern. If we do not do this, we may end up with
// a !structural-match constant that is not of reference type, which makes it
// very hard to invoke `PartialEq::eq` on it as a fallback.
let val = match self.recur(tcx.deref_const(self.param_env.and(cv)), false) {
Ok(subpattern) => PatKind::Deref { subpattern },
Err(_) => PatKind::Constant { value: cv },
};
self.behind_reference.set(old);
val
if !pointee_ty.is_sized(tcx.at(span), param_env) {
// `tcx.deref_const()` below will ICE with an unsized type
// (except slices, which are handled in a separate arm above).
let msg = format!("cannot use unsized non-slice type `{}` in constant patterns", pointee_ty);
if self.include_lint_checks {
tcx.sess.span_err(span, &msg);
} else {
tcx.sess.delay_span_bug(span, &msg);
}
PatKind::Wild
} else {
let old = self.behind_reference.replace(true);
// In case there are structural-match violations somewhere in this subpattern,
// we fall back to a const pattern. If we do not do this, we may end up with
// a !structural-match constant that is not of reference type, which makes it
// very hard to invoke `PartialEq::eq` on it as a fallback.
let val = match self.recur(tcx.deref_const(self.param_env.and(cv)), false) {
Ok(subpattern) => PatKind::Deref { subpattern },
Err(_) => PatKind::Constant { value: cv },
};
self.behind_reference.set(old);
val
}
}
},
ty::Bool | ty::Char | ty::Int(_) | ty::Uint(_) | ty::FnDef(..) => {
......
......@@ -20,8 +20,7 @@
use rustc_errors::emitter::{Emitter, EmitterWriter, HumanReadableErrorType};
use rustc_errors::json::JsonEmitter;
use rustc_errors::registry::Registry;
use rustc_errors::{Diagnostic, DiagnosticBuilder, DiagnosticId, ErrorReported};
use rustc_lint_defs::FutureBreakage;
use rustc_errors::{DiagnosticBuilder, DiagnosticId, ErrorReported};
use rustc_macros::HashStable_Generic;
pub use rustc_span::def_id::StableCrateId;
use rustc_span::source_map::{FileLoader, MultiSpan, RealFileLoader, SourceMap, Span};
......@@ -317,23 +316,7 @@ fn emit_future_breakage(&self) {
if diags.is_empty() {
return;
}
// If any future-breakage lints were registered, this lint store
// should be available
let lint_store = self.lint_store.get().expect("`lint_store` not initialized!");
let diags_and_breakage: Vec<(FutureBreakage, Diagnostic)> = diags
.into_iter()
.map(|diag| {
let lint_name = match &diag.code {
Some(DiagnosticId::Lint { name, has_future_breakage: true, .. }) => name,
_ => panic!("Unexpected code in diagnostic {:?}", diag),
};
let lint = lint_store.name_to_lint(&lint_name);
let future_breakage =
lint.lint.future_incompatible.unwrap().future_breakage.unwrap();
(future_breakage, diag)
})
.collect();
self.parse_sess.span_diagnostic.emit_future_breakage_report(diags_and_breakage);
self.parse_sess.span_diagnostic.emit_future_breakage_report(diags);
}
pub fn local_stable_crate_id(&self) -> StableCrateId {
......
......@@ -79,7 +79,7 @@
/// // a `MaybeUninit<T>` may be invalid, and hence this is not UB:
/// let mut x = MaybeUninit::<&i32>::uninit();
/// // Set it to a valid value.
/// unsafe { x.as_mut_ptr().write(&0); }
/// x.write(&0);
/// // Extract the initialized data -- this is only allowed *after* properly
/// // initializing `x`!
/// let x = unsafe { x.assume_init() };
......@@ -135,7 +135,7 @@
/// // this loop, we have a memory leak, but there is no memory safety
/// // issue.
/// for elem in &mut data[..] {
/// *elem = MaybeUninit::new(vec![42]);
/// elem.write(vec![42]);
/// }
///
/// // Everything is initialized. Transmute the array to the
......@@ -161,7 +161,7 @@
/// let mut data_len: usize = 0;
///
/// for elem in &mut data[0..500] {
/// *elem = MaybeUninit::new(String::from("hello"));
/// elem.write(String::from("hello"));
/// data_len += 1;
/// }
///
......@@ -410,7 +410,7 @@ pub fn zeroed() -> MaybeUninit<T> {
/// (now safely initialized) contents of `self`.
///
/// As the content is stored inside a `MaybeUninit`, the destructor is not
/// ran for the inner data if the MaybeUninit leaves scope without a call to
/// run for the inner data if the MaybeUninit leaves scope without a call to
/// [`assume_init`], [`assume_init_drop`], or similar. Code that receives
/// the mutable reference returned by this function needs to keep this in
/// mind. The safety model of Rust regards leaks as safe, but they are
......@@ -426,7 +426,6 @@ pub fn zeroed() -> MaybeUninit<T> {
/// Correct usage of this method:
///
/// ```rust
/// #![feature(maybe_uninit_extra)]
/// use std::mem::MaybeUninit;
///
/// let mut x = MaybeUninit::<Vec<u8>>::uninit();
......@@ -445,7 +444,6 @@ pub fn zeroed() -> MaybeUninit<T> {
/// This usage of the method causes a leak:
///
/// ```rust
/// #![feature(maybe_uninit_extra)]
/// use std::mem::MaybeUninit;
///
/// let mut x = MaybeUninit::<String>::uninit();
......@@ -456,8 +454,38 @@ pub fn zeroed() -> MaybeUninit<T> {
/// // x is initialized now:
/// let s = unsafe { x.assume_init() };
/// ```
#[unstable(feature = "maybe_uninit_extra", issue = "63567")]
#[rustc_const_unstable(feature = "maybe_uninit_extra", issue = "63567")]
///
/// This method can be used to avoid unsafe in some cases. The example below
/// shows a part of an implementation of a fixed sized arena that lends out
/// pinned references.
/// With `write`, we can avoid the need to write through a raw pointer:
///
/// ```rust
/// #![feature(maybe_uninit_extra)]
/// use core::pin::Pin;
/// use core::mem::MaybeUninit;
///
/// struct PinArena<T> {
/// memory: Box<[MaybeUninit<T>]>,
/// len: usize,
/// }
///
/// impl <T> PinArena<T> {
/// pub fn capacity(&self) -> usize {
/// self.memory.len()
/// }
/// pub fn push(&mut self, val: T) -> Pin<&mut T> {
/// if self.len >= self.capacity() {
/// panic!("Attempted to push to a full pin arena!");
/// }
/// let ref_ = self.memory[self.len].write(val);
/// self.len += 1;
/// unsafe { Pin::new_unchecked(ref_) }
/// }
/// }
/// ```
#[stable(feature = "maybe_uninit_write", since = "1.55.0")]
#[rustc_const_unstable(feature = "const_maybe_uninit_write", issue = "63567")]
#[inline(always)]
pub const fn write(&mut self, val: T) -> &mut T {
*self = MaybeUninit::new(val);
......@@ -478,7 +506,7 @@ pub const fn write(&mut self, val: T) -> &mut T {
/// use std::mem::MaybeUninit;
///
/// let mut x = MaybeUninit::<Vec<u32>>::uninit();
/// unsafe { x.as_mut_ptr().write(vec![0, 1, 2]); }
/// x.write(vec![0, 1, 2]);
/// // Create a reference into the `MaybeUninit<T>`. This is okay because we initialized it.
/// let x_vec = unsafe { &*x.as_ptr() };
/// assert_eq!(x_vec.len(), 3);
......@@ -515,7 +543,7 @@ pub const fn as_ptr(&self) -> *const T {
/// use std::mem::MaybeUninit;
///
/// let mut x = MaybeUninit::<Vec<u32>>::uninit();
/// unsafe { x.as_mut_ptr().write(vec![0, 1, 2]); }
/// x.write(vec![0, 1, 2]);
/// // Create a reference into the `MaybeUninit<Vec<u32>>`.
/// // This is okay because we initialized it.
/// let x_vec = unsafe { &mut *x.as_mut_ptr() };
......@@ -574,7 +602,7 @@ pub const fn as_mut_ptr(&mut self) -> *mut T {
/// use std::mem::MaybeUninit;
///
/// let mut x = MaybeUninit::<bool>::uninit();
/// unsafe { x.as_mut_ptr().write(true); }
/// x.write(true);
/// let x_init = unsafe { x.assume_init() };
/// assert_eq!(x_init, true);
/// ```
......@@ -723,7 +751,7 @@ pub unsafe fn assume_init_drop(&mut self) {
///
/// let mut x = MaybeUninit::<Vec<u32>>::uninit();
/// // Initialize `x`:
/// unsafe { x.as_mut_ptr().write(vec![1, 2, 3]); }
/// x.write(vec![1, 2, 3]);
/// // Now that our `MaybeUninit<_>` is known to be initialized, it is okay to
/// // create a shared reference to it:
/// let x: &Vec<u32> = unsafe {
......@@ -897,9 +925,9 @@ pub unsafe fn assume_init_drop(&mut self) {
/// use std::mem::MaybeUninit;
///
/// let mut array: [MaybeUninit<i32>; 3] = MaybeUninit::uninit_array();
/// array[0] = MaybeUninit::new(0);
/// array[1] = MaybeUninit::new(1);
/// array[2] = MaybeUninit::new(2);
/// array[0].write(0);
/// array[1].write(1);
/// array[2].write(2);
///
/// // SAFETY: Now safe as we initialised all elements
/// let array = unsafe {
......
......@@ -209,32 +209,6 @@ impl<T> Cursor<T>
where
T: AsRef<[u8]>,
{
/// Returns the remaining length.
///
/// # Examples
///
/// ```
/// #![feature(cursor_remaining)]
/// use std::io::Cursor;
///
/// let mut buff = Cursor::new(vec![1, 2, 3, 4, 5]);
///
/// assert_eq!(buff.remaining(), 5);
///
/// buff.set_position(2);
/// assert_eq!(buff.remaining(), 3);
///
/// buff.set_position(4);
/// assert_eq!(buff.remaining(), 1);
///
/// buff.set_position(6);
/// assert_eq!(buff.remaining(), 0);
/// ```
#[unstable(feature = "cursor_remaining", issue = "86369")]
pub fn remaining(&self) -> u64 {
(self.inner.as_ref().len() as u64).checked_sub(self.pos).unwrap_or(0)
}
/// Returns the remaining slice.
///
/// # Examples
......
......@@ -277,7 +277,7 @@
pub use self::stdio::set_output_capture;
#[stable(feature = "rust1", since = "1.0.0")]
pub use self::stdio::{stderr, stdin, stdout, Stderr, Stdin, Stdout};
#[unstable(feature = "stdio_locked", issue = "none")]
#[unstable(feature = "stdio_locked", issue = "86845")]
pub use self::stdio::{stderr_locked, stdin_locked, stdout_locked};
#[stable(feature = "rust1", since = "1.0.0")]
pub use self::stdio::{StderrLock, StdinLock, StdoutLock};
......
......@@ -347,7 +347,7 @@ pub fn stdin() -> Stdin {
/// Ok(())
/// }
/// ```
#[unstable(feature = "stdio_locked", issue = "none")]
#[unstable(feature = "stdio_locked", issue = "86845")]
pub fn stdin_locked() -> StdinLock<'static> {
stdin().into_locked()
}
......@@ -442,7 +442,7 @@ fn lock_any<'a>(&self) -> StdinLock<'a> {
/// Ok(())
/// }
/// ```
#[unstable(feature = "stdio_locked", issue = "none")]
#[unstable(feature = "stdio_locked", issue = "86845")]
pub fn into_locked(self) -> StdinLock<'static> {
self.lock_any()
}
......@@ -668,7 +668,7 @@ pub fn stdout() -> Stdout {
/// Ok(())
/// }
/// ```
#[unstable(feature = "stdio_locked", issue = "none")]
#[unstable(feature = "stdio_locked", issue = "86845")]
pub fn stdout_locked() -> StdoutLock<'static> {
stdout().into_locked()
}
......@@ -745,7 +745,7 @@ fn lock_any<'a>(&self) -> StdoutLock<'a> {
/// Ok(())
/// }
/// ```
#[unstable(feature = "stdio_locked", issue = "none")]
#[unstable(feature = "stdio_locked", issue = "86845")]
pub fn into_locked(self) -> StdoutLock<'static> {
self.lock_any()
}
......@@ -945,7 +945,7 @@ pub fn stderr() -> Stderr {
/// Ok(())
/// }
/// ```
#[unstable(feature = "stdio_locked", issue = "none")]
#[unstable(feature = "stdio_locked", issue = "86845")]
pub fn stderr_locked() -> StderrLock<'static> {
stderr().into_locked()
}
......@@ -1005,7 +1005,7 @@ fn lock_any<'a>(&self) -> StderrLock<'a> {
/// Ok(())
/// }
/// ```
#[unstable(feature = "stdio_locked", issue = "none")]
#[unstable(feature = "stdio_locked", issue = "86845")]
pub fn into_locked(self) -> StderrLock<'static> {
self.lock_any()
}
......
......@@ -139,11 +139,17 @@ fn run($sel, $builder: &Builder<'_>) {
install!((self, builder, _config),
Docs, "src/doc", _config.docs, only_hosts: false, {
let tarball = builder.ensure(dist::Docs { host: self.target }).expect("missing docs");
install_sh(builder, "docs", self.compiler.stage, Some(self.target), &tarball);
if let Some(tarball) = builder.ensure(dist::Docs { host: self.target }) {
install_sh(builder, "docs", self.compiler.stage, Some(self.target), &tarball);
} else {
panic!("docs are not available to install, \
check that `build.docs` is true in `config.toml`");
}
};
Std, "library/std", true, only_hosts: false, {
for target in &builder.targets {
// `expect` should be safe, only None when host != build, but this
// only runs when host == build
let tarball = builder.ensure(dist::Std {
compiler: self.compiler,
target: *target
......@@ -165,10 +171,15 @@ fn run($sel, $builder: &Builder<'_>) {
}
};
RustAnalyzer, "rust-analyzer", Self::should_build(_config), only_hosts: true, {
let tarball = builder
.ensure(dist::RustAnalyzer { compiler: self.compiler, target: self.target })
.expect("missing rust-analyzer");
install_sh(builder, "rust-analyzer", self.compiler.stage, Some(self.target), &tarball);
if let Some(tarball) =
builder.ensure(dist::RustAnalyzer { compiler: self.compiler, target: self.target })
{
install_sh(builder, "rust-analyzer", self.compiler.stage, Some(self.target), &tarball);
} else {
builder.info(
&format!("skipping Install rust-analyzer stage{} ({})", self.compiler.stage, self.target),
);
}
};
Clippy, "clippy", Self::should_build(_config), only_hosts: true, {
let tarball = builder.ensure(dist::Clippy { compiler: self.compiler, target: self.target });
......@@ -212,6 +223,8 @@ fn run($sel, $builder: &Builder<'_>) {
}
};
Analysis, "analysis", Self::should_build(_config), only_hosts: false, {
// `expect` should be safe, only None with host != build, but this
// only uses the `build` compiler
let tarball = builder.ensure(dist::Analysis {
// Find the actual compiler (handling the full bootstrap option) which
// produced the save-analysis data because that data isn't copied
......
......@@ -907,27 +907,25 @@ fn run(self, builder: &Builder<'_>) {
// We remove existing folder to be sure there won't be artifacts remaining.
let _ = fs::remove_dir_all(&out_dir);
let mut nb_generated = 0;
let src_path = "src/test/rustdoc-gui/src";
// We generate docs for the libraries present in the rustdoc-gui's src folder.
let libs_dir = builder.build.src.join("src/test/rustdoc-gui/src");
for entry in libs_dir.read_dir().expect("read_dir call failed") {
let entry = entry.expect("invalid entry");
let path = entry.path();
if path.extension().map(|e| e == "rs").unwrap_or(false) {
let mut command = builder.rustdoc_cmd(self.compiler);
command.arg(path).arg("-o").arg(&out_dir);
builder.run(&mut command);
nb_generated += 1;
}
}
assert!(nb_generated > 0, "no documentation was generated...");
let mut cargo = Command::new(&builder.initial_cargo);
cargo
.arg("doc")
.arg("--workspace")
.arg("--target-dir")
.arg(&out_dir)
.env("RUSTDOC", builder.rustdoc(self.compiler))
.env("RUSTC", builder.rustc(self.compiler))
.current_dir(&builder.build.src.join(src_path));
builder.run(&mut cargo);
// We now run GUI tests.
let mut command = Command::new(&nodejs);
command
.arg(builder.build.src.join("src/tools/rustdoc-gui/tester.js"))
.arg("--doc-folder")
.arg(out_dir)
.arg(out_dir.join("doc"))
.arg("--tests-folder")
.arg(builder.build.src.join("src/test/rustdoc-gui"));
for path in &builder.paths {
......
......@@ -98,7 +98,7 @@ impl<'a, 'tcx> BlanketImplFinder<'a, 'tcx> {
visibility: Inherited,
def_id: ItemId::Blanket { impl_id: impl_def_id, for_: item_def_id },
kind: box ImplItem(Impl {
span: self.cx.tcx.def_span(impl_def_id).clean(self.cx),
span: Span::from_rustc_span(self.cx.tcx.def_span(impl_def_id)),
unsafety: hir::Unsafety::Normal,
generics: (
self.cx.tcx.generics_of(impl_def_id),
......
......@@ -227,20 +227,6 @@ fn clean(&self, cx: &mut DocContext<'_>) -> GenericBound {
}
}
impl<'tcx> Clean<Option<Vec<GenericBound>>> for InternalSubsts<'tcx> {
fn clean(&self, cx: &mut DocContext<'_>) -> Option<Vec<GenericBound>> {
let mut v = Vec::new();
v.extend(self.regions().filter_map(|r| r.clean(cx)).map(GenericBound::Outlives));
v.extend(self.types().map(|t| {
GenericBound::TraitBound(
PolyTrait { trait_: t.clean(cx), generic_params: Vec::new() },
hir::TraitBoundModifier::None,
)
}));
if !v.is_empty() { Some(v) } else { None }
}
}
impl Clean<Lifetime> for hir::Lifetime {
fn clean(&self, cx: &mut DocContext<'_>) -> Lifetime {
let def = cx.tcx.named_region(self.hir_id);
......@@ -296,12 +282,6 @@ fn clean(&self, cx: &mut DocContext<'_>) -> Constant {
}
}
impl Clean<Lifetime> for ty::GenericParamDef {
fn clean(&self, _cx: &mut DocContext<'_>) -> Lifetime {
Lifetime(self.name)
}
}
impl Clean<Option<Lifetime>> for ty::RegionKind {
fn clean(&self, _cx: &mut DocContext<'_>) -> Option<Lifetime> {
match *self {
......@@ -1764,12 +1744,6 @@ fn clean(&self, cx: &mut DocContext<'_>) -> Variant {
}
}
impl Clean<Span> for rustc_span::Span {
fn clean(&self, _cx: &mut DocContext<'_>) -> Span {
Span::from_rustc_span(*self)
}
}
impl Clean<Path> for hir::Path<'_> {
fn clean(&self, cx: &mut DocContext<'_>) -> Path {
Path {
......@@ -2193,22 +2167,3 @@ fn clean(&self, cx: &mut DocContext<'_>) -> TypeBindingKind {
}
}
}
enum SimpleBound {
TraitBound(Vec<PathSegment>, Vec<SimpleBound>, Vec<GenericParamDef>, hir::TraitBoundModifier),
Outlives(Lifetime),
}
impl From<GenericBound> for SimpleBound {
fn from(bound: GenericBound) -> Self {
match bound.clone() {
GenericBound::Outlives(l) => SimpleBound::Outlives(l),
GenericBound::TraitBound(t, mod_) => match t.trait_ {
Type::ResolvedPath { path, .. } => {
SimpleBound::TraitBound(path.segments, Vec::new(), t.generic_params, mod_)
}
_ => panic!("Unexpected bound {:?}", bound),
},
}
}
}
......@@ -683,6 +683,9 @@ function hideThemeButtonState() {
});
}
var currentNbImpls = implementors.getElementsByClassName("impl").length;
var traitName = document.querySelector("h1.fqn > .in-band > .trait").textContent;
var baseIdName = "impl-" + traitName + "-";
var libs = Object.getOwnPropertyNames(imp);
for (var i = 0, llength = libs.length; i < llength; ++i) {
if (libs[i] === window.currentCrate) { continue; }
......@@ -705,6 +708,7 @@ function hideThemeButtonState() {
var code = document.createElement("code");
code.innerHTML = struct.text;
addClass(code, "in-band");
onEachLazy(code.getElementsByTagName("a"), function(elem) {
var href = elem.getAttribute("href");
......@@ -714,12 +718,18 @@ function hideThemeButtonState() {
}
});
var display = document.createElement("h3");
var currentId = baseIdName + currentNbImpls;
var anchor = document.createElement("a");
anchor.href = "#" + currentId;
addClass(anchor, "anchor");
var display = document.createElement("div");
display.id = currentId;
addClass(display, "impl");
display.innerHTML = "<span class=\"in-band\"><table class=\"table-display\">" +
"<tbody><tr><td><code>" + code.outerHTML + "</code></td><td></td></tr>" +
"</tbody></table></span>";
display.appendChild(anchor);
display.appendChild(code);
list.appendChild(display);
currentNbImpls += 1;
}
}
};
......
......@@ -1610,6 +1610,8 @@ fn suggestion(self) -> Suggestion {
return Suggestion::Macro;
} else if kind == DefKind::Fn || kind == DefKind::AssocFn {
return Suggestion::Function;
} else if kind == DefKind::Field {
return Suggestion::RemoveDisambiguator;
}
let prefix = match kind {
......@@ -1674,6 +1676,8 @@ enum Suggestion {
Function,
/// `m!`
Macro,
/// `foo` without any disambiguator
RemoveDisambiguator,
}
impl Suggestion {
......@@ -1682,6 +1686,7 @@ fn descr(&self) -> Cow<'static, str> {
Self::Prefix(x) => format!("prefix with `{}@`", x).into(),
Self::Function => "add parentheses".into(),
Self::Macro => "add an exclamation mark".into(),
Self::RemoveDisambiguator => "remove the disambiguator".into(),
}
}
......@@ -1691,6 +1696,7 @@ fn as_help(&self, path_str: &str) -> String {
Self::Prefix(prefix) => format!("{}@{}", prefix, path_str),
Self::Function => format!("{}()", path_str),
Self::Macro => format!("{}!", path_str),
Self::RemoveDisambiguator => path_str.into(),
}
}
}
......
// The goal of this test is to check that the external trait implementors, generated with JS,
// have the same display than the "local" ones.
goto: file://|DOC_PATH|/implementors/trait.Whatever.html
assert: "#implementors-list"
// There are supposed to be two implementors listed.
assert-count: ("#implementors-list > .impl", 2)
// Now we check that both implementors have an anchor, an ID and a similar DOM.
assert: ("#implementors-list > .impl:nth-child(1) > a.anchor")
assert-attribute: ("#implementors-list > .impl:nth-child(1)", {"id": "impl-Whatever"})
assert-attribute: ("#implementors-list > .impl:nth-child(1) > a.anchor", {"href": "#impl-Whatever"})
assert: "#implementors-list > .impl:nth-child(1) > code.in-band"
assert: ("#implementors-list > .impl:nth-child(2) > a.anchor")
assert-attribute: ("#implementors-list > .impl:nth-child(2)", {"id": "impl-Whatever-1"})
assert-attribute: ("#implementors-list > .impl:nth-child(2) > a.anchor", {"href": "#impl-Whatever-1"})
assert: "#implementors-list > .impl:nth-child(2) > code.in-band"
# This file is automatically @generated by Cargo.
# It is not intended for manual editing.
version = 3
[[package]]
name = "implementors"
version = "0.1.0"
[[package]]
name = "lib2"
version = "0.1.0"
dependencies = [
"implementors",
]
[[package]]
name = "test_docs"
version = "0.1.0"
[workspace]
members = [
"test_docs",
"lib2",
"implementors",
]
[package]
name = "implementors"
version = "0.1.0"
edition = "2018"
[lib]
path = "lib.rs"
pub trait Whatever {
fn method() {}
}
pub struct Struct;
impl Whatever for Struct {}
[package]
name = "lib2"
version = "0.1.0"
edition = "2018"
[lib]
path = "lib.rs"
[dependencies]
implementors = { path = "../implementors" }
......@@ -31,3 +31,5 @@ impl Trait for Foo {
type X = u32;
const Y: u32 = 0;
}
impl implementors::Whatever for Foo {}
#[cfg(test)]
mod tests {
#[test]
fn it_works() {
assert_eq!(2 + 2, 4);
}
}
[package]
name = "test_docs"
version = "0.1.0"
edition = "2018"
[lib]
path = "lib.rs"
#![deny(rustdoc::broken_intra_doc_links)]
//~^NOTE the lint level is defined here
/// [`Foo::bar`]
/// [`Foo::bar()`]
//~^ERROR incompatible link kind for `Foo::bar`
//~|HELP to link to the field, remove the disambiguator
//~|NOTE this link resolved to a field, which is not a function
pub struct Foo {
pub bar: u8
}
error: incompatible link kind for `Foo::bar`
--> $DIR/field-ice.rs:5:6
|
LL | /// [`Foo::bar()`]
| ^^^^^^^^^^^^ help: to link to the field, remove the disambiguator: ``Foo::bar``
|
note: the lint level is defined here
--> $DIR/field-ice.rs:1:9
|
LL | #![deny(rustdoc::broken_intra_doc_links)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
= note: this link resolved to a field, which is not a function
error: aborting due to previous error
// Regression test for the ICE described in #87046.
#![crate_type="lib"]
#![allow(unreachable_patterns)]
#![feature(const_fn_union)]
#[derive(PartialEq, Eq)]
#[repr(transparent)]
pub struct Username(str);
pub const ROOT_USER: &Username = Username::from_str("root");
impl Username {
pub const fn from_str(raw: &str) -> &Self {
union Transmute<'a> {
raw: &'a str,
typed: &'a Username,
}
unsafe { Transmute { raw }.typed }
}
pub const fn as_str(&self) -> &str {
&self.0
}
pub fn is_root(&self) -> bool {
match self {
ROOT_USER => true,
//~^ ERROR: cannot use unsized non-slice type `Username` in constant patterns
_ => false,
}
}
}
error: cannot use unsized non-slice type `Username` in constant patterns
--> $DIR/issue-87046.rs:29:13
|
LL | ROOT_USER => true,
| ^^^^^^^^^
error: aborting due to previous error
Subproject commit e5c1c8cf2fcfae3e15c8bcf5256e84cad3bd3436
Subproject commit fe00358888a24c64878abc15f09b0e60e16db9d6
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册