diff --git a/.gitignore b/.gitignore index 0cd6b9f648d0f..b7e8e8fa15752 100644 --- a/.gitignore +++ b/.gitignore @@ -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. diff --git a/compiler/rustc_errors/src/emitter.rs b/compiler/rustc_errors/src/emitter.rs index fd024a8ecfa4a..becc1c6db5bbb 100644 --- a/compiler/rustc_errors/src/emitter.rs +++ b/compiler/rustc_errors/src/emitter.rs @@ -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) {} /// Emit list of unused externs fn emit_unused_externs(&mut self, _lint_level: &str, _unused_externs: &[&str]) {} diff --git a/compiler/rustc_errors/src/json.rs b/compiler/rustc_errors/src/json.rs index 485e7564587ea..1b6cd04cca642 100644 --- a/compiler/rustc_errors/src/json.rs +++ b/compiler/rustc_errors/src/json.rs @@ -16,7 +16,7 @@ use crate::registry::Registry; 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 @@ impl Emitter for JsonEmitter { } } - fn emit_future_breakage_report(&mut self, diags: Vec<(FutureBreakage, crate::Diagnostic)>) { + fn emit_future_breakage_report(&mut self, diags: Vec) { let data: Vec = 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, } diff --git a/compiler/rustc_errors/src/lib.rs b/compiler/rustc_errors/src/lib.rs index f8339d6e3f493..993a7c2c162c6 100644 --- a/compiler/rustc_errors/src/lib.rs +++ b/compiler/rustc_errors/src/lib.rs @@ -23,7 +23,6 @@ use rustc_data_structures::fx::{FxHashSet, FxIndexMap}; 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 @@ impl Handler { 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) { self.inner.borrow_mut().emitter.emit_future_breakage_report(diags) } diff --git a/compiler/rustc_lint_defs/src/builtin.rs b/compiler/rustc_lint_defs/src/builtin.rs index 01291de51bdab..5b1cd0bcb3ffe 100644 --- a/compiler/rustc_lint_defs/src/builtin.rs +++ b/compiler/rustc_lint_defs/src/builtin.rs @@ -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 @@ declare_lint! { "detects usage of old versions of certain proc-macro crates", @future_incompatible = FutureIncompatibleInfo { reference: "issue #83125 ", - future_breakage: Some(FutureBreakage { - date: None - }) + reason: FutureIncompatibilityReason::FutureReleaseErrorReportNow, }; } diff --git a/compiler/rustc_lint_defs/src/lib.rs b/compiler/rustc_lint_defs/src/lib.rs index 89453e8e73a2b..001198226d9a3 100644 --- a/compiler/rustc_lint_defs/src/lib.rs +++ b/compiler/rustc_lint_defs/src/lib.rs @@ -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, } /// 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 @@ impl FutureIncompatibilityReason { } } -#[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, } } } diff --git a/compiler/rustc_middle/src/lint.rs b/compiler/rustc_middle/src/lint.rs index 63872ca901766..484e30027e521 100644 --- a/compiler/rustc_middle/src/lint.rs +++ b/compiler/rustc_middle/src/lint.rs @@ -8,7 +8,7 @@ use rustc_hir::HirId; 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 @@ pub fn struct_lint_level<'s, 'd>( 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) => { diff --git a/compiler/rustc_middle/src/mir/interpret/allocation.rs b/compiler/rustc_middle/src/mir/interpret/allocation.rs index c2645a0914007..75cbb55239c8b 100644 --- a/compiler/rustc_middle/src/mir/interpret/allocation.rs +++ b/compiler/rustc_middle/src/mir/interpret/allocation.rs @@ -512,7 +512,7 @@ impl InitMaskCompressed { /// Transferring the initialization mask to other allocations. impl Allocation { /// Creates a run-length encoding of the initialization mask. - pub fn compress_uninit_range(&self, src: Pointer, 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 @@ impl Allocation { // 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 @@ impl Allocation { pub fn mark_compressed_init_range( &mut self, defined: &InitMaskCompressed, - dest: Pointer, - 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; diff --git a/compiler/rustc_mir/src/interpret/eval_context.rs b/compiler/rustc_mir/src/interpret/eval_context.rs index 648a7abfdc7b1..8cd459265dfc5 100644 --- a/compiler/rustc_mir/src/interpret/eval_context.rs +++ b/compiler/rustc_mir/src/interpret/eval_context.rs @@ -18,8 +18,8 @@ use rustc_span::{Pos, Span}; 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 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { // 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(()) } diff --git a/compiler/rustc_mir/src/interpret/memory.rs b/compiler/rustc_mir/src/interpret/memory.rs index cb929c21850cb..5f719cc160706 100644 --- a/compiler/rustc_mir/src/interpret/memory.rs +++ b/compiler/rustc_mir/src/interpret/memory.rs @@ -276,17 +276,6 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M> { 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) -> 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, @@ -1049,7 +1038,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M> { 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 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M> { } // 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); diff --git a/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs b/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs index cb9c89324d6b3..3859b22223c00 100644 --- a/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs +++ b/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs @@ -490,17 +490,29 @@ impl<'a, 'tcx> ConstToPat<'a, 'tcx> { // 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(..) => { diff --git a/compiler/rustc_session/src/session.rs b/compiler/rustc_session/src/session.rs index 8270bbbe8fd80..f3ce78d2d78f8 100644 --- a/compiler/rustc_session/src/session.rs +++ b/compiler/rustc_session/src/session.rs @@ -20,8 +20,7 @@ use rustc_errors::annotate_snippet_emitter_writer::AnnotateSnippetEmitterWriter; 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 @@ impl Session { 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 { diff --git a/library/core/src/mem/maybe_uninit.rs b/library/core/src/mem/maybe_uninit.rs index 3dfbd98fa6c7b..5122421ea8c85 100644 --- a/library/core/src/mem/maybe_uninit.rs +++ b/library/core/src/mem/maybe_uninit.rs @@ -79,7 +79,7 @@ use crate::ptr; /// // a `MaybeUninit` 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 @@ use crate::ptr; /// // 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 @@ use crate::ptr; /// 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 @@ impl MaybeUninit { /// (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 @@ impl MaybeUninit { /// Correct usage of this method: /// /// ```rust - /// #![feature(maybe_uninit_extra)] /// use std::mem::MaybeUninit; /// /// let mut x = MaybeUninit::>::uninit(); @@ -445,7 +444,6 @@ impl MaybeUninit { /// This usage of the method causes a leak: /// /// ```rust - /// #![feature(maybe_uninit_extra)] /// use std::mem::MaybeUninit; /// /// let mut x = MaybeUninit::::uninit(); @@ -456,8 +454,38 @@ impl MaybeUninit { /// // 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 { + /// memory: Box<[MaybeUninit]>, + /// len: usize, + /// } + /// + /// impl PinArena { + /// 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 @@ impl MaybeUninit { /// use std::mem::MaybeUninit; /// /// let mut x = MaybeUninit::>::uninit(); - /// unsafe { x.as_mut_ptr().write(vec![0, 1, 2]); } + /// x.write(vec![0, 1, 2]); /// // Create a reference into the `MaybeUninit`. This is okay because we initialized it. /// let x_vec = unsafe { &*x.as_ptr() }; /// assert_eq!(x_vec.len(), 3); @@ -515,7 +543,7 @@ impl MaybeUninit { /// use std::mem::MaybeUninit; /// /// let mut x = MaybeUninit::>::uninit(); - /// unsafe { x.as_mut_ptr().write(vec![0, 1, 2]); } + /// x.write(vec![0, 1, 2]); /// // Create a reference into the `MaybeUninit>`. /// // This is okay because we initialized it. /// let x_vec = unsafe { &mut *x.as_mut_ptr() }; @@ -574,7 +602,7 @@ impl MaybeUninit { /// use std::mem::MaybeUninit; /// /// let mut x = MaybeUninit::::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 @@ impl MaybeUninit { /// /// let mut x = MaybeUninit::>::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 = unsafe { @@ -897,9 +925,9 @@ impl MaybeUninit { /// use std::mem::MaybeUninit; /// /// let mut array: [MaybeUninit; 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 { diff --git a/library/std/src/io/cursor.rs b/library/std/src/io/cursor.rs index 04f13cdeb88e3..ae0cea985d77c 100644 --- a/library/std/src/io/cursor.rs +++ b/library/std/src/io/cursor.rs @@ -209,32 +209,6 @@ impl Cursor 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 diff --git a/library/std/src/io/mod.rs b/library/std/src/io/mod.rs index 9daeee711adea..ad8975c03f175 100644 --- a/library/std/src/io/mod.rs +++ b/library/std/src/io/mod.rs @@ -277,7 +277,7 @@ pub use self::error::{Error, ErrorKind, Result}; 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}; diff --git a/library/std/src/io/stdio.rs b/library/std/src/io/stdio.rs index 293f0e31ce050..206687e38fb9c 100644 --- a/library/std/src/io/stdio.rs +++ b/library/std/src/io/stdio.rs @@ -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 @@ impl Stdin { /// 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 @@ impl Stdout { /// 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 @@ impl Stderr { /// Ok(()) /// } /// ``` - #[unstable(feature = "stdio_locked", issue = "none")] + #[unstable(feature = "stdio_locked", issue = "86845")] pub fn into_locked(self) -> StderrLock<'static> { self.lock_any() } diff --git a/src/bootstrap/install.rs b/src/bootstrap/install.rs index 13ee909afd5e4..8a1b6df0dafe3 100644 --- a/src/bootstrap/install.rs +++ b/src/bootstrap/install.rs @@ -139,11 +139,17 @@ macro_rules! install { 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 @@ install!((self, builder, _config), } }; 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 @@ install!((self, builder, _config), } }; 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 diff --git a/src/bootstrap/test.rs b/src/bootstrap/test.rs index e4d6a3f587b05..61ffae47e2ad0 100644 --- a/src/bootstrap/test.rs +++ b/src/bootstrap/test.rs @@ -907,27 +907,25 @@ impl Step for RustdocGUI { // 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 { diff --git a/src/librustdoc/clean/blanket_impl.rs b/src/librustdoc/clean/blanket_impl.rs index c257d362694fe..8f74a48547d88 100644 --- a/src/librustdoc/clean/blanket_impl.rs +++ b/src/librustdoc/clean/blanket_impl.rs @@ -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), diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index 0ff708d01f5e7..80aaae1580114 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -227,20 +227,6 @@ impl<'tcx> Clean for ty::PolyTraitRef<'tcx> { } } -impl<'tcx> Clean>> for InternalSubsts<'tcx> { - fn clean(&self, cx: &mut DocContext<'_>) -> Option> { - 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 for hir::Lifetime { fn clean(&self, cx: &mut DocContext<'_>) -> Lifetime { let def = cx.tcx.named_region(self.hir_id); @@ -296,12 +282,6 @@ impl Clean for hir::ConstArg { } } -impl Clean for ty::GenericParamDef { - fn clean(&self, _cx: &mut DocContext<'_>) -> Lifetime { - Lifetime(self.name) - } -} - impl Clean> for ty::RegionKind { fn clean(&self, _cx: &mut DocContext<'_>) -> Option { match *self { @@ -1764,12 +1744,6 @@ impl Clean for hir::VariantData<'_> { } } -impl Clean for rustc_span::Span { - fn clean(&self, _cx: &mut DocContext<'_>) -> Span { - Span::from_rustc_span(*self) - } -} - impl Clean for hir::Path<'_> { fn clean(&self, cx: &mut DocContext<'_>) -> Path { Path { @@ -2193,22 +2167,3 @@ impl Clean for hir::TypeBindingKind<'_> { } } } - -enum SimpleBound { - TraitBound(Vec, Vec, Vec, hir::TraitBoundModifier), - Outlives(Lifetime), -} - -impl From 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), - }, - } - } -} diff --git a/src/librustdoc/html/static/js/main.js b/src/librustdoc/html/static/js/main.js index 98128878999e4..38ddbb3ad7427 100644 --- a/src/librustdoc/html/static/js/main.js +++ b/src/librustdoc/html/static/js/main.js @@ -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 = "" + - "" + - "
" + code.outerHTML + "
"; + display.appendChild(anchor); + display.appendChild(code); list.appendChild(display); + currentNbImpls += 1; } } }; diff --git a/src/librustdoc/passes/collect_intra_doc_links.rs b/src/librustdoc/passes/collect_intra_doc_links.rs index 44a3faf6f7be2..21bd3ebd21bc8 100644 --- a/src/librustdoc/passes/collect_intra_doc_links.rs +++ b/src/librustdoc/passes/collect_intra_doc_links.rs @@ -1610,6 +1610,8 @@ impl Disambiguator { 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 @@ impl Suggestion { 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 @@ impl Suggestion { Self::Prefix(prefix) => format!("{}@{}", prefix, path_str), Self::Function => format!("{}()", path_str), Self::Macro => format!("{}!", path_str), + Self::RemoveDisambiguator => path_str.into(), } } } diff --git a/src/test/rustdoc-gui/implementors.goml b/src/test/rustdoc-gui/implementors.goml new file mode 100644 index 0000000000000..a4db5cee7c768 --- /dev/null +++ b/src/test/rustdoc-gui/implementors.goml @@ -0,0 +1,16 @@ +// 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" diff --git a/src/test/rustdoc-gui/src/Cargo.lock b/src/test/rustdoc-gui/src/Cargo.lock new file mode 100644 index 0000000000000..a72ccffc6ddf9 --- /dev/null +++ b/src/test/rustdoc-gui/src/Cargo.lock @@ -0,0 +1,18 @@ +# 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" diff --git a/src/test/rustdoc-gui/src/Cargo.toml b/src/test/rustdoc-gui/src/Cargo.toml new file mode 100644 index 0000000000000..9c8c0c636f07f --- /dev/null +++ b/src/test/rustdoc-gui/src/Cargo.toml @@ -0,0 +1,6 @@ +[workspace] +members = [ + "test_docs", + "lib2", + "implementors", +] diff --git a/src/test/rustdoc-gui/src/implementors/Cargo.toml b/src/test/rustdoc-gui/src/implementors/Cargo.toml new file mode 100644 index 0000000000000..7ef1052c49fd2 --- /dev/null +++ b/src/test/rustdoc-gui/src/implementors/Cargo.toml @@ -0,0 +1,7 @@ +[package] +name = "implementors" +version = "0.1.0" +edition = "2018" + +[lib] +path = "lib.rs" diff --git a/src/test/rustdoc-gui/src/implementors/lib.rs b/src/test/rustdoc-gui/src/implementors/lib.rs new file mode 100644 index 0000000000000..4b2f6962e30c5 --- /dev/null +++ b/src/test/rustdoc-gui/src/implementors/lib.rs @@ -0,0 +1,7 @@ +pub trait Whatever { + fn method() {} +} + +pub struct Struct; + +impl Whatever for Struct {} diff --git a/src/test/rustdoc-gui/src/lib2/Cargo.toml b/src/test/rustdoc-gui/src/lib2/Cargo.toml new file mode 100644 index 0000000000000..6041a793f08da --- /dev/null +++ b/src/test/rustdoc-gui/src/lib2/Cargo.toml @@ -0,0 +1,10 @@ +[package] +name = "lib2" +version = "0.1.0" +edition = "2018" + +[lib] +path = "lib.rs" + +[dependencies] +implementors = { path = "../implementors" } diff --git a/src/test/rustdoc-gui/src/lib2.rs b/src/test/rustdoc-gui/src/lib2/lib.rs similarity index 91% rename from src/test/rustdoc-gui/src/lib2.rs rename to src/test/rustdoc-gui/src/lib2/lib.rs index 77d384f3113e4..72ef3cbd2026d 100644 --- a/src/test/rustdoc-gui/src/lib2.rs +++ b/src/test/rustdoc-gui/src/lib2/lib.rs @@ -31,3 +31,5 @@ impl Trait for Foo { type X = u32; const Y: u32 = 0; } + +impl implementors::Whatever for Foo {} diff --git a/src/test/rustdoc-gui/src/lib2/src/lib.rs b/src/test/rustdoc-gui/src/lib2/src/lib.rs new file mode 100644 index 0000000000000..31e1bb209f98e --- /dev/null +++ b/src/test/rustdoc-gui/src/lib2/src/lib.rs @@ -0,0 +1,7 @@ +#[cfg(test)] +mod tests { + #[test] + fn it_works() { + assert_eq!(2 + 2, 4); + } +} diff --git a/src/test/rustdoc-gui/src/test_docs/Cargo.toml b/src/test/rustdoc-gui/src/test_docs/Cargo.toml new file mode 100644 index 0000000000000..7f3c65746fcf8 --- /dev/null +++ b/src/test/rustdoc-gui/src/test_docs/Cargo.toml @@ -0,0 +1,7 @@ +[package] +name = "test_docs" +version = "0.1.0" +edition = "2018" + +[lib] +path = "lib.rs" diff --git a/src/test/rustdoc-gui/src/lib.rs b/src/test/rustdoc-gui/src/test_docs/lib.rs similarity index 100% rename from src/test/rustdoc-gui/src/lib.rs rename to src/test/rustdoc-gui/src/test_docs/lib.rs diff --git a/src/test/rustdoc-ui/intra-doc/field-ice.rs b/src/test/rustdoc-ui/intra-doc/field-ice.rs new file mode 100644 index 0000000000000..c5d501e38daf5 --- /dev/null +++ b/src/test/rustdoc-ui/intra-doc/field-ice.rs @@ -0,0 +1,11 @@ +#![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 +} diff --git a/src/test/rustdoc-ui/intra-doc/field-ice.stderr b/src/test/rustdoc-ui/intra-doc/field-ice.stderr new file mode 100644 index 0000000000000..ccb05b84a7282 --- /dev/null +++ b/src/test/rustdoc-ui/intra-doc/field-ice.stderr @@ -0,0 +1,15 @@ +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 + diff --git a/src/test/ui/consts/issue-87046.rs b/src/test/ui/consts/issue-87046.rs new file mode 100644 index 0000000000000..1f147439f8bc3 --- /dev/null +++ b/src/test/ui/consts/issue-87046.rs @@ -0,0 +1,34 @@ +// 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, + } + } +} diff --git a/src/test/ui/consts/issue-87046.stderr b/src/test/ui/consts/issue-87046.stderr new file mode 100644 index 0000000000000..5da7a9e239000 --- /dev/null +++ b/src/test/ui/consts/issue-87046.stderr @@ -0,0 +1,8 @@ +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 + diff --git a/src/tools/rust-analyzer b/src/tools/rust-analyzer index e5c1c8cf2fcfa..fe00358888a24 160000 --- a/src/tools/rust-analyzer +++ b/src/tools/rust-analyzer @@ -1 +1 @@ -Subproject commit e5c1c8cf2fcfae3e15c8bcf5256e84cad3bd3436 +Subproject commit fe00358888a24c64878abc15f09b0e60e16db9d6