Auto merge of #86806 - GuillaumeGomez:rollup-pr5r37w, r=GuillaumeGomez

Rollup of 5 pull requests

Successful merges:

 - #85749 (Revert "Don't load all extern crates unconditionally")
 - #86714 (Add linked list cursor end methods)
 - #86737 (Document rustfmt on nightly-rustc)
 - #86776 (Skip layout query when computing integer type size during mangling)
 - #86797 (Stabilize `Bound::cloned()`)

Failed merges:

r? `@ghost`
`@rustbot` modify labels: rollup
This commit is contained in:
bors 2021-07-02 11:42:38 +00:00
commit ce331ee6ee
18 changed files with 327 additions and 174 deletions

View File

@ -3,9 +3,11 @@ use rustc_data_structures::fx::{FxHashMap, FxHashSet};
use rustc_hir as hir;
use rustc_hir::def_id::{CrateNum, DefId};
use rustc_hir::definitions::{DefPathData, DisambiguatedDefPathData};
use rustc_middle::ty::layout::IntegerExt;
use rustc_middle::ty::print::{Print, Printer};
use rustc_middle::ty::subst::{GenericArg, GenericArgKind, Subst};
use rustc_middle::ty::{self, FloatTy, Instance, IntTy, Ty, TyCtxt, TypeFoldable, UintTy};
use rustc_target::abi::Integer;
use rustc_target::spec::abi::Abi;
use std::fmt::Write;
@ -553,11 +555,9 @@ impl Printer<'tcx> for SymbolMangler<'tcx> {
ty::Uint(_) | ty::Bool | ty::Char => {
ct.try_eval_bits(self.tcx, ty::ParamEnv::reveal_all(), ct.ty)
}
ty::Int(_) => {
let param_env = ty::ParamEnv::reveal_all();
ct.try_eval_bits(self.tcx, param_env, ct.ty).and_then(|b| {
let sz = self.tcx.layout_of(param_env.and(ct.ty)).ok()?.size;
let val = sz.sign_extend(b) as i128;
ty::Int(ity) => {
ct.try_eval_bits(self.tcx, ty::ParamEnv::reveal_all(), ct.ty).and_then(|b| {
let val = Integer::from_int_ty(&self.tcx, *ity).size().sign_extend(b) as i128;
if val < 0 {
neg = true;
}

View File

@ -1243,6 +1243,20 @@ impl<'a, T> Cursor<'a, T> {
prev.map(|prev| &(*prev.as_ptr()).element)
}
}
/// Provides a reference to the front element of the cursor's parent list,
/// or None if the list is empty.
#[unstable(feature = "linked_list_cursors", issue = "58533")]
pub fn front(&self) -> Option<&'a T> {
self.list.front()
}
/// Provides a reference to the back element of the cursor's parent list,
/// or None if the list is empty.
#[unstable(feature = "linked_list_cursors", issue = "58533")]
pub fn back(&self) -> Option<&'a T> {
self.list.back()
}
}
impl<'a, T> CursorMut<'a, T> {
@ -1506,6 +1520,135 @@ impl<'a, T> CursorMut<'a, T> {
self.index = 0;
unsafe { self.list.split_off_before_node(self.current, split_off_idx) }
}
/// Appends an element to the front of the cursor's parent list. The node
/// that the cursor points to is unchanged, even if it is the "ghost" node.
///
/// This operation should compute in O(1) time.
// `push_front` continues to point to "ghost" when it addes a node to mimic
// the behavior of `insert_before` on an empty list.
#[unstable(feature = "linked_list_cursors", issue = "58533")]
pub fn push_front(&mut self, elt: T) {
// Safety: We know that `push_front` does not change the position in
// memory of other nodes. This ensures that `self.current` remains
// valid.
self.list.push_front(elt);
self.index += 1;
}
/// Appends an element to the back of the cursor's parent list. The node
/// that the cursor points to is unchanged, even if it is the "ghost" node.
///
/// This operation should compute in O(1) time.
#[unstable(feature = "linked_list_cursors", issue = "58533")]
pub fn push_back(&mut self, elt: T) {
// Safety: We know that `push_back` does not change the position in
// memory of other nodes. This ensures that `self.current` remains
// valid.
self.list.push_back(elt);
if self.current().is_none() {
// The index of "ghost" is the length of the list, so we just need
// to increment self.index to reflect the new length of the list.
self.index += 1;
}
}
/// Removes the first element from the cursor's parent list and returns it,
/// or None if the list is empty. The element the cursor points to remains
/// unchanged, unless it was pointing to the front element. In that case, it
/// points to the new front element.
///
/// This operation should compute in O(1) time.
#[unstable(feature = "linked_list_cursors", issue = "58533")]
pub fn pop_front(&mut self) -> Option<T> {
// We can't check if current is empty, we must check the list directly.
// It is possible for `self.current == None` and the list to be
// non-empty.
if self.list.is_empty() {
None
} else {
// We can't point to the node that we pop. Copying the behavior of
// `remove_current`, we move on the the next node in the sequence.
// If the list is of length 1 then we end pointing to the "ghost"
// node at index 0, which is expected.
if self.list.head == self.current {
self.move_next();
} else {
self.index -= 1;
}
self.list.pop_front()
}
}
/// Removes the last element from the cursor's parent list and returns it,
/// or None if the list is empty. The element the cursor points to remains
/// unchanged, unless it was pointing to the back element. In that case, it
/// points to the "ghost" element.
///
/// This operation should compute in O(1) time.
#[unstable(feature = "linked_list_cursors", issue = "58533")]
pub fn pop_back(&mut self) -> Option<T> {
if self.list.is_empty() {
None
} else {
if self.list.tail == self.current {
// The index now reflects the length of the list. It was the
// length of the list minus 1, but now the list is 1 smaller. No
// change is needed for `index`.
self.current = None;
} else if self.current.is_none() {
self.index = self.list.len - 1;
}
self.list.pop_back()
}
}
/// Provides a reference to the front element of the cursor's parent list,
/// or None if the list is empty.
#[unstable(feature = "linked_list_cursors", issue = "58533")]
pub fn front(&self) -> Option<&T> {
self.list.front()
}
/// Provides a mutable reference to the front element of the cursor's
/// parent list, or None if the list is empty.
#[unstable(feature = "linked_list_cursors", issue = "58533")]
pub fn front_mut(&mut self) -> Option<&mut T> {
self.list.front_mut()
}
/// Provides a reference to the back element of the cursor's parent list,
/// or None if the list is empty.
#[unstable(feature = "linked_list_cursors", issue = "58533")]
pub fn back(&self) -> Option<&T> {
self.list.back()
}
/// Provides a mutable reference to back element of the cursor's parent
/// list, or `None` if the list is empty.
///
/// # Examples
/// Building and mutating a list with a cursor, then getting the back element:
/// ```
/// #![feature(linked_list_cursors)]
/// use std::collections::LinkedList;
/// let mut dl = LinkedList::new();
/// dl.push_front(3);
/// dl.push_front(2);
/// dl.push_front(1);
/// let mut cursor = dl.cursor_front_mut();
/// *cursor.current().unwrap() = 99;
/// *cursor.back_mut().unwrap() = 0;
/// let mut contents = dl.into_iter();
/// assert_eq!(contents.next(), Some(99));
/// assert_eq!(contents.next(), Some(2));
/// assert_eq!(contents.next(), Some(0));
/// assert_eq!(contents.next(), None);
/// ```
#[unstable(feature = "linked_list_cursors", issue = "58533")]
pub fn back_mut(&mut self) -> Option<&mut T> {
self.list.back_mut()
}
}
/// An iterator produced by calling `drain_filter` on LinkedList.

View File

@ -428,3 +428,50 @@ fn test_cursor_mut_insert() {
check_links(&m);
assert_eq!(m.iter().cloned().collect::<Vec<_>>(), &[200, 201, 202, 203, 1, 100, 101]);
}
#[test]
fn test_cursor_push_front_back() {
let mut ll: LinkedList<u32> = LinkedList::new();
ll.extend(&[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]);
let mut c = ll.cursor_front_mut();
assert_eq!(c.current(), Some(&mut 1));
assert_eq!(c.index(), Some(0));
c.push_front(0);
assert_eq!(c.current(), Some(&mut 1));
assert_eq!(c.peek_prev(), Some(&mut 0));
assert_eq!(c.index(), Some(1));
c.push_back(11);
drop(c);
let p = ll.cursor_back().front().unwrap();
assert_eq!(p, &0);
assert_eq!(ll, (0..12).collect());
check_links(&ll);
}
#[test]
fn test_cursor_pop_front_back() {
let mut ll: LinkedList<u32> = LinkedList::new();
ll.extend(&[1, 2, 3, 4, 5, 6]);
let mut c = ll.cursor_back_mut();
assert_eq!(c.pop_front(), Some(1));
c.move_prev();
c.move_prev();
c.move_prev();
assert_eq!(c.pop_back(), Some(6));
let c = c.as_cursor();
assert_eq!(c.front(), Some(&2));
assert_eq!(c.back(), Some(&5));
assert_eq!(c.index(), Some(1));
drop(c);
assert_eq!(ll, (2..6).collect());
check_links(&ll);
let mut c = ll.cursor_back_mut();
assert_eq!(c.current(), Some(&mut 5));
assert_eq!(c.index, 3);
assert_eq!(c.pop_back(), Some(5));
assert_eq!(c.current(), None);
assert_eq!(c.index, 3);
assert_eq!(c.pop_back(), Some(4));
assert_eq!(c.current(), None);
assert_eq!(c.index, 2);
}

View File

@ -737,14 +737,13 @@ impl<T: Clone> Bound<&T> {
/// # Examples
///
/// ```
/// #![feature(bound_cloned)]
/// use std::ops::Bound::*;
/// use std::ops::RangeBounds;
///
/// assert_eq!((1..12).start_bound(), Included(&1));
/// assert_eq!((1..12).start_bound().cloned(), Included(1));
/// ```
#[unstable(feature = "bound_cloned", issue = "61356")]
#[stable(feature = "bound_cloned", since = "1.55.0")]
pub fn cloned(self) -> Bound<T> {
match self {
Bound::Unbounded => Bound::Unbounded,

View File

@ -4,7 +4,6 @@
#![feature(array_map)]
#![feature(array_windows)]
#![feature(bool_to_option)]
#![feature(bound_cloned)]
#![feature(box_syntax)]
#![feature(cell_update)]
#![feature(cfg_panic)]

View File

@ -31,7 +31,6 @@
#![feature(restricted_std)]
#![feature(rustc_attrs)]
#![feature(min_specialization)]
#![feature(bound_cloned)]
#![recursion_limit = "256"]
#[unstable(feature = "proc_macro_internals", issue = "27812")]

View File

@ -465,6 +465,7 @@ impl<'a> Builder<'a> {
doc::Std,
doc::Rustc,
doc::Rustdoc,
doc::Rustfmt,
doc::ErrorIndex,
doc::Nomicon,
doc::Reference,

View File

@ -593,84 +593,97 @@ impl Step for Rustc {
}
}
#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
pub struct Rustdoc {
stage: u32,
target: TargetSelection,
}
impl Step for Rustdoc {
type Output = ();
const DEFAULT: bool = true;
const ONLY_HOSTS: bool = true;
fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
run.krate("rustdoc-tool")
}
fn make_run(run: RunConfig<'_>) {
run.builder.ensure(Rustdoc { stage: run.builder.top_stage, target: run.target });
}
/// Generates compiler documentation.
///
/// This will generate all documentation for compiler and dependencies.
/// Compiler documentation is distributed separately, so we make sure
/// we do not merge it with the other documentation from std, test and
/// proc_macros. This is largely just a wrapper around `cargo doc`.
fn run(self, builder: &Builder<'_>) {
let stage = self.stage;
let target = self.target;
builder.info(&format!("Documenting stage{} rustdoc ({})", stage, target));
// This is the intended out directory for compiler documentation.
let out = builder.compiler_doc_out(target);
t!(fs::create_dir_all(&out));
let compiler = builder.compiler(stage, builder.config.build);
if !builder.config.compiler_docs {
builder.info("\tskipping - compiler/librustdoc docs disabled");
return;
macro_rules! tool_doc {
($tool: ident, $should_run: literal, $path: literal, [$($krate: literal),+ $(,)?] $(, binary=$bin:expr)?) => {
#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
pub struct $tool {
stage: u32,
target: TargetSelection,
}
// Build rustc docs so that we generate relative links.
builder.ensure(Rustc { stage, target });
impl Step for $tool {
type Output = ();
const DEFAULT: bool = true;
const ONLY_HOSTS: bool = true;
// Build rustdoc.
builder.ensure(tool::Rustdoc { compiler });
fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
run.krate($should_run)
}
// Symlink compiler docs to the output directory of rustdoc documentation.
let out_dir = builder.stage_out(compiler, Mode::ToolRustc).join(target.triple).join("doc");
t!(fs::create_dir_all(&out_dir));
t!(symlink_dir_force(&builder.config, &out, &out_dir));
fn make_run(run: RunConfig<'_>) {
run.builder.ensure($tool { stage: run.builder.top_stage, target: run.target });
}
// Build cargo command.
let mut cargo = prepare_tool_cargo(
builder,
compiler,
Mode::ToolRustc,
target,
"doc",
"src/tools/rustdoc",
SourceType::InTree,
&[],
);
/// Generates compiler documentation.
///
/// This will generate all documentation for compiler and dependencies.
/// Compiler documentation is distributed separately, so we make sure
/// we do not merge it with the other documentation from std, test and
/// proc_macros. This is largely just a wrapper around `cargo doc`.
fn run(self, builder: &Builder<'_>) {
let stage = self.stage;
let target = self.target;
builder.info(&format!("Documenting stage{} {} ({})", stage, stringify!($tool).to_lowercase(), target));
cargo.arg("-Zskip-rustdoc-fingerprint");
// Only include compiler crates, no dependencies of those, such as `libc`.
cargo.arg("--no-deps");
cargo.arg("-p").arg("rustdoc");
cargo.arg("-p").arg("rustdoc-json-types");
// This is the intended out directory for compiler documentation.
let out = builder.compiler_doc_out(target);
t!(fs::create_dir_all(&out));
cargo.rustdocflag("--document-private-items");
cargo.rustdocflag("--enable-index-page");
cargo.rustdocflag("--show-type-layout");
cargo.rustdocflag("-Zunstable-options");
builder.run(&mut cargo.into());
let compiler = builder.compiler(stage, builder.config.build);
if !builder.config.compiler_docs {
builder.info("\tskipping - compiler/tool docs disabled");
return;
}
// Build rustc docs so that we generate relative links.
builder.ensure(Rustc { stage, target });
// Symlink compiler docs to the output directory of rustdoc documentation.
let out_dir = builder.stage_out(compiler, Mode::ToolRustc).join(target.triple).join("doc");
t!(fs::create_dir_all(&out_dir));
t!(symlink_dir_force(&builder.config, &out, &out_dir));
// Build cargo command.
let mut cargo = prepare_tool_cargo(
builder,
compiler,
Mode::ToolRustc,
target,
"doc",
$path,
SourceType::InTree,
&[],
);
cargo.arg("-Zskip-rustdoc-fingerprint");
// Only include compiler crates, no dependencies of those, such as `libc`.
cargo.arg("--no-deps");
$(
cargo.arg("-p").arg($krate);
)+
$(if !$bin {
cargo.rustdocflag("--document-private-items");
})?
cargo.rustdocflag("--enable-index-page");
cargo.rustdocflag("--show-type-layout");
cargo.rustdocflag("-Zunstable-options");
builder.run(&mut cargo.into());
}
}
}
}
tool_doc!(Rustdoc, "rustdoc-tool", "src/tools/rustdoc", ["rustdoc", "rustdoc-json-types"]);
tool_doc!(
Rustfmt,
"rustfmt-nightly",
"src/tools/rustfmt",
["rustfmt-nightly", "rustfmt-config_proc_macro"],
binary = true
);
#[derive(Ord, PartialOrd, Debug, Copy, Clone, Hash, PartialEq, Eq)]
pub struct ErrorIndex {
pub target: TargetSelection,

View File

@ -1,12 +1,12 @@
use rustc_ast as ast;
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
use rustc_data_structures::sync::{self, Lrc};
use rustc_driver::abort_on_err;
use rustc_errors::emitter::{Emitter, EmitterWriter};
use rustc_errors::json::JsonEmitter;
use rustc_feature::UnstableFeatures;
use rustc_hir::def::Namespace::TypeNS;
use rustc_hir::def::Res;
use rustc_hir::def_id::{DefId, LocalDefId};
use rustc_hir::def_id::{DefId, LocalDefId, CRATE_DEF_INDEX};
use rustc_hir::HirId;
use rustc_hir::{
intravisit::{self, NestedVisitorMap, Visitor},
@ -23,7 +23,7 @@ use rustc_session::DiagnosticOutput;
use rustc_session::Session;
use rustc_span::source_map;
use rustc_span::symbol::sym;
use rustc_span::Span;
use rustc_span::{Span, DUMMY_SP};
use std::cell::RefCell;
use std::mem;
@ -300,16 +300,41 @@ crate fn create_config(
}
crate fn create_resolver<'a>(
externs: config::Externs,
queries: &Queries<'a>,
sess: &Session,
) -> Rc<RefCell<interface::BoxedResolver>> {
let (krate, resolver, _) = &*abort_on_err(queries.expansion(), sess).peek();
let resolver = resolver.clone();
let extern_names: Vec<String> = externs
.iter()
.filter(|(_, entry)| entry.add_prelude)
.map(|(name, _)| name)
.cloned()
.collect();
let mut loader = crate::passes::collect_intra_doc_links::IntraLinkCrateLoader::new(resolver);
ast::visit::walk_crate(&mut loader, krate);
let (_, resolver, _) = &*abort_on_err(queries.expansion(), sess).peek();
loader.resolver
// Before we actually clone it, let's force all the extern'd crates to
// actually be loaded, just in case they're only referred to inside
// intra-doc links
resolver.borrow_mut().access(|resolver| {
sess.time("load_extern_crates", || {
for extern_name in &extern_names {
debug!("loading extern crate {}", extern_name);
if let Err(()) = resolver
.resolve_str_path_error(
DUMMY_SP,
extern_name,
TypeNS,
LocalDefId { local_def_index: CRATE_DEF_INDEX }.to_def_id(),
) {
warn!("unable to resolve external crate {} (do you have an unused `--extern` crate?)", extern_name)
}
}
});
});
// Now we're good to clone the resolver because everything should be loaded
resolver.clone()
}
crate fn run_global_ctxt(

View File

@ -31,7 +31,6 @@ extern crate tracing;
// Dependencies listed in Cargo.toml do not need `extern crate`.
extern crate rustc_ast;
extern crate rustc_ast_lowering;
extern crate rustc_ast_pretty;
extern crate rustc_attr;
extern crate rustc_data_structures;
@ -714,6 +713,7 @@ fn main_options(options: config::Options) -> MainResult {
let default_passes = options.default_passes;
let output_format = options.output_format;
// FIXME: fix this clone (especially render_options)
let externs = options.externs.clone();
let manual_passes = options.manual_passes.clone();
let render_options = options.render_options.clone();
let config = core::create_config(options);
@ -731,7 +731,7 @@ fn main_options(options: config::Options) -> MainResult {
// We need to hold on to the complete resolver, so we cause everything to be
// cloned for the analysis passes to use. Suboptimal, but necessary in the
// current architecture.
let resolver = core::create_resolver(queries, &sess);
let resolver = core::create_resolver(externs, queries, &sess);
if sess.has_errors() {
sess.fatal("Compilation failed, aborting rustdoc");

View File

@ -37,9 +37,6 @@ use crate::html::markdown::{markdown_links, MarkdownLink};
use crate::lint::{BROKEN_INTRA_DOC_LINKS, PRIVATE_INTRA_DOC_LINKS};
use crate::passes::Pass;
mod early;
crate use early::IntraLinkCrateLoader;
crate const COLLECT_INTRA_DOC_LINKS: Pass = Pass {
name: "collect-intra-doc-links",
run: collect_intra_doc_links,

View File

@ -1,63 +0,0 @@
use rustc_ast as ast;
use rustc_hir::def::Namespace::TypeNS;
use rustc_hir::def_id::{DefId, LocalDefId, CRATE_DEF_INDEX};
use rustc_interface::interface;
use std::cell::RefCell;
use std::mem;
use std::rc::Rc;
// Letting the resolver escape at the end of the function leads to inconsistencies between the
// crates the TyCtxt sees and the resolver sees (because the resolver could load more crates
// after escaping). Hopefully `IntraLinkCrateLoader` gets all the crates we need ...
crate struct IntraLinkCrateLoader {
current_mod: DefId,
crate resolver: Rc<RefCell<interface::BoxedResolver>>,
}
impl IntraLinkCrateLoader {
crate fn new(resolver: Rc<RefCell<interface::BoxedResolver>>) -> Self {
let crate_id = LocalDefId { local_def_index: CRATE_DEF_INDEX }.to_def_id();
Self { current_mod: crate_id, resolver }
}
}
impl ast::visit::Visitor<'_> for IntraLinkCrateLoader {
fn visit_attribute(&mut self, attr: &ast::Attribute) {
use crate::html::markdown::markdown_links;
use crate::passes::collect_intra_doc_links::preprocess_link;
if let Some(doc) = attr.doc_str() {
for link in markdown_links(&doc.as_str()) {
let path_str = if let Some(Ok(x)) = preprocess_link(&link) {
x.path_str
} else {
continue;
};
self.resolver.borrow_mut().access(|resolver| {
let _ = resolver.resolve_str_path_error(
attr.span,
&path_str,
TypeNS,
self.current_mod,
);
});
}
}
ast::visit::walk_attribute(self, attr);
}
fn visit_item(&mut self, item: &ast::Item) {
use rustc_ast_lowering::ResolverAstLowering;
if let ast::ItemKind::Mod(..) = item.kind {
let new_mod =
self.resolver.borrow_mut().access(|resolver| resolver.local_def_id(item.id));
let old_mod = mem::replace(&mut self.current_mod, new_mod.to_def_id());
ast::visit::walk_item(self, item);
self.current_mod = old_mod;
} else {
ast::visit::walk_item(self, item);
}
}
}

View File

@ -30,7 +30,7 @@ crate use self::unindent_comments::UNINDENT_COMMENTS;
mod propagate_doc_cfg;
crate use self::propagate_doc_cfg::PROPAGATE_DOC_CFG;
crate mod collect_intra_doc_links;
mod collect_intra_doc_links;
crate use self::collect_intra_doc_links::COLLECT_INTRA_DOC_LINKS;
mod doc_test_lints;

View File

@ -1,17 +0,0 @@
// no-prefer-dynamic
#![crate_type = "lib"]
#![no_std]
#![feature(lang_items)]
use core::panic::PanicInfo;
use core::sync::atomic::{self, Ordering};
#[panic_handler]
fn panic(_info: &PanicInfo) -> ! {
loop {
atomic::compiler_fence(Ordering::SeqCst);
}
}
#[lang = "eh_personality"]
fn foo() {}

View File

@ -1,3 +0,0 @@
// check-pass
// aux-crate:panic_item=panic-item.rs
// @has unused_extern_crate/index.html

View File

@ -0,0 +1,2 @@
/// This will be referred to by the test docstring
pub struct Something;

View File

@ -0,0 +1,10 @@
// aux-crate:priv:issue_66159_1=issue-66159-1.rs
// compile-flags:-Z unstable-options
// The issue was an ICE which meant that we never actually generated the docs
// so if we have generated the docs, we're okay.
// Since we don't generate the docs for the auxiliary files, we can't actually
// verify that the struct is linked correctly.
// @has issue_66159/index.html
//! [issue_66159_1::Something]

View File

@ -1,6 +1,7 @@
#![feature(rustc_private)]
#![deny(rust_2018_idioms)]
#![warn(unreachable_pub)]
#![recursion_limit = "256"]
#[macro_use]
extern crate derive_new;