diff --git a/RELEASES.md b/RELEASES.md
index 699735de6fb4d..e72905c15bd25 100644
--- a/RELEASES.md
+++ b/RELEASES.md
@@ -88,7 +88,11 @@ Compatibility Notes
- [When `default-features` is set to false of a workspace dependency, and an inherited dependency of a member has `default-features = true`, Cargo will enable default features of that dependency.](https://github.com/rust-lang/cargo/pull/11409/)
- [Cargo denies `CARGO_HOME` in the `[env]` configuration table. Cargo itself doesn't pick up this value, but recursive calls to cargo would, which was not intended.](https://github.com/rust-lang/cargo/pull/11644/)
- [Debuginfo for build dependencies is now off if not explicitly set. This is expected to improve the overall build time.](https://github.com/rust-lang/cargo/pull/11252/)
-
+- [The Rust distribution no longer always includes rustdoc](https://github.com/rust-lang/rust/pull/106886)
+ If `tools = [...]` is set in config.toml, we will respect a missing rustdoc in that list. By
+ default rustdoc remains included. To retain the prior behavior explicitly add `"rustdoc"` to the
+ list.
+
Internal Changes
diff --git a/compiler/rustc_hir_analysis/src/collect.rs b/compiler/rustc_hir_analysis/src/collect.rs
index 36e294e8aa29f..9fe0c07814ed8 100644
--- a/compiler/rustc_hir_analysis/src/collect.rs
+++ b/compiler/rustc_hir_analysis/src/collect.rs
@@ -1146,8 +1146,14 @@ fn infer_return_ty_for_fn_sig<'tcx>(
let mut visitor = HirPlaceholderCollector::default();
visitor.visit_ty(ty);
+
let mut diag = bad_placeholder(tcx, visitor.0, "return type");
let ret_ty = fn_sig.output();
+ // Don't leak types into signatures unless they're nameable!
+ // For example, if a function returns itself, we don't want that
+ // recursive function definition to leak out into the fn sig.
+ let mut should_recover = false;
+
if let Some(ret_ty) = ret_ty.make_suggestable(tcx, false) {
diag.span_suggestion(
ty.span,
@@ -1155,15 +1161,7 @@ fn infer_return_ty_for_fn_sig<'tcx>(
ret_ty,
Applicability::MachineApplicable,
);
- } else if matches!(ret_ty.kind(), ty::FnDef(..))
- && let Some(fn_sig) = ret_ty.fn_sig(tcx).make_suggestable(tcx, false)
- {
- diag.span_suggestion(
- ty.span,
- "replace with the correct return type",
- fn_sig,
- Applicability::MachineApplicable,
- );
+ should_recover = true;
} else if let Some(sugg) = suggest_impl_trait(tcx, ret_ty, ty.span, def_id) {
diag.span_suggestion(
ty.span,
@@ -1181,9 +1179,20 @@ fn infer_return_ty_for_fn_sig<'tcx>(
https://doc.rust-lang.org/book/ch13-01-closures.html",
);
}
- diag.emit();
- ty::Binder::dummy(fn_sig)
+ let guar = diag.emit();
+
+ if should_recover {
+ ty::Binder::dummy(fn_sig)
+ } else {
+ ty::Binder::dummy(tcx.mk_fn_sig(
+ fn_sig.inputs().iter().copied(),
+ tcx.ty_error(guar),
+ fn_sig.c_variadic,
+ fn_sig.unsafety,
+ fn_sig.abi,
+ ))
+ }
}
None => icx.astconv().ty_of_fn(
hir_id,
diff --git a/compiler/rustc_middle/src/ty/trait_def.rs b/compiler/rustc_middle/src/ty/trait_def.rs
index 6747da7abd3af..e61037e5ea86f 100644
--- a/compiler/rustc_middle/src/ty/trait_def.rs
+++ b/compiler/rustc_middle/src/ty/trait_def.rs
@@ -139,40 +139,6 @@ impl<'tcx> TyCtxt<'tcx> {
treat_projections: TreatProjections,
mut f: impl FnMut(DefId),
) {
- let _: Option<()> =
- self.find_map_relevant_impl(trait_def_id, self_ty, treat_projections, |did| {
- f(did);
- None
- });
- }
-
- /// `trait_def_id` MUST BE the `DefId` of a trait.
- pub fn non_blanket_impls_for_ty(
- self,
- trait_def_id: DefId,
- self_ty: Ty<'tcx>,
- ) -> impl Iterator- + 'tcx {
- let impls = self.trait_impls_of(trait_def_id);
- if let Some(simp) = fast_reject::simplify_type(self, self_ty, TreatParams::AsCandidateKey) {
- if let Some(impls) = impls.non_blanket_impls.get(&simp) {
- return impls.iter().copied();
- }
- }
-
- [].iter().copied()
- }
-
- /// Applies function to every impl that could possibly match the self type `self_ty` and returns
- /// the first non-none value.
- ///
- /// `trait_def_id` MUST BE the `DefId` of a trait.
- pub fn find_map_relevant_impl(
- self,
- trait_def_id: DefId,
- self_ty: Ty<'tcx>,
- treat_projections: TreatProjections,
- mut f: impl FnMut(DefId) -> Option,
- ) -> Option {
// FIXME: This depends on the set of all impls for the trait. That is
// unfortunate wrt. incremental compilation.
//
@@ -181,9 +147,7 @@ impl<'tcx> TyCtxt<'tcx> {
let impls = self.trait_impls_of(trait_def_id);
for &impl_def_id in impls.blanket_impls.iter() {
- if let result @ Some(_) = f(impl_def_id) {
- return result;
- }
+ f(impl_def_id);
}
// Note that we're using `TreatParams::ForLookup` to query `non_blanket_impls` while using
@@ -199,20 +163,30 @@ impl<'tcx> TyCtxt<'tcx> {
if let Some(simp) = fast_reject::simplify_type(self, self_ty, treat_params) {
if let Some(impls) = impls.non_blanket_impls.get(&simp) {
for &impl_def_id in impls {
- if let result @ Some(_) = f(impl_def_id) {
- return result;
- }
+ f(impl_def_id);
}
}
} else {
for &impl_def_id in impls.non_blanket_impls.values().flatten() {
- if let result @ Some(_) = f(impl_def_id) {
- return result;
- }
+ f(impl_def_id);
}
}
+ }
- None
+ /// `trait_def_id` MUST BE the `DefId` of a trait.
+ pub fn non_blanket_impls_for_ty(
+ self,
+ trait_def_id: DefId,
+ self_ty: Ty<'tcx>,
+ ) -> impl Iterator
- + 'tcx {
+ let impls = self.trait_impls_of(trait_def_id);
+ if let Some(simp) = fast_reject::simplify_type(self, self_ty, TreatParams::AsCandidateKey) {
+ if let Some(impls) = impls.non_blanket_impls.get(&simp) {
+ return impls.iter().copied();
+ }
+ }
+
+ [].iter().copied()
}
/// Returns an iterator containing all impls for `trait_def_id`.
diff --git a/compiler/rustc_middle/src/ty/util.rs b/compiler/rustc_middle/src/ty/util.rs
index dbe2eebe33604..9dbd9fbbb5bb3 100644
--- a/compiler/rustc_middle/src/ty/util.rs
+++ b/compiler/rustc_middle/src/ty/util.rs
@@ -2,7 +2,6 @@
use crate::middle::codegen_fn_attrs::CodegenFnAttrFlags;
use crate::mir;
-use crate::ty::fast_reject::TreatProjections;
use crate::ty::layout::IntegerExt;
use crate::ty::{
self, FallibleTypeFolder, ToPredicate, Ty, TyCtxt, TypeFoldable, TypeFolder, TypeSuperFoldable,
@@ -359,21 +358,29 @@ impl<'tcx> TyCtxt<'tcx> {
self.ensure().coherent_trait(drop_trait);
let ty = self.type_of(adt_did).subst_identity();
- let (did, constness) = self.find_map_relevant_impl(
- drop_trait,
- ty,
- // FIXME: This could also be some other mode, like "unexpected"
- TreatProjections::ForLookup,
- |impl_did| {
- if let Some(item_id) = self.associated_item_def_ids(impl_did).first() {
- if validate(self, impl_did).is_ok() {
- return Some((*item_id, self.constness(impl_did)));
- }
- }
- None
- },
- )?;
+ let mut dtor_candidate = None;
+ self.for_each_relevant_impl(drop_trait, ty, |impl_did| {
+ let Some(item_id) = self.associated_item_def_ids(impl_did).first() else {
+ self.sess.delay_span_bug(self.def_span(impl_did), "Drop impl without drop function");
+ return;
+ };
+
+ if validate(self, impl_did).is_err() {
+ // Already `ErrorGuaranteed`, no need to delay a span bug here.
+ return;
+ }
+
+ if let Some((old_item_id, _)) = dtor_candidate {
+ self.sess
+ .struct_span_err(self.def_span(item_id), "multiple drop impls found")
+ .span_note(self.def_span(old_item_id), "other impl here")
+ .delay_as_bug();
+ }
+
+ dtor_candidate = Some((*item_id, self.constness(impl_did)));
+ });
+ let (did, constness) = dtor_candidate?;
Some(ty::Destructor { did, constness })
}
diff --git a/compiler/rustc_span/src/span_encoding.rs b/compiler/rustc_span/src/span_encoding.rs
index c600298c51a08..1eea0f63ca0cc 100644
--- a/compiler/rustc_span/src/span_encoding.rs
+++ b/compiler/rustc_span/src/span_encoding.rs
@@ -181,19 +181,23 @@ impl Span {
#[inline]
pub fn ctxt(self) -> SyntaxContext {
let ctxt_or_tag = self.ctxt_or_tag as u32;
- if ctxt_or_tag <= MAX_CTXT {
- if self.len_or_tag == LEN_TAG || self.len_or_tag & PARENT_MASK == 0 {
- // Inline format or interned format with inline ctxt.
- SyntaxContext::from_u32(ctxt_or_tag)
+ // Check for interned format.
+ if self.len_or_tag == LEN_TAG {
+ if ctxt_or_tag == CTXT_TAG {
+ // Fully interned format.
+ let index = self.base_or_index;
+ with_span_interner(|interner| interner.spans[index as usize].ctxt)
} else {
- // Inline format or interned format with inline parent.
- // We know that the SyntaxContext is root.
- SyntaxContext::root()
+ // Interned format with inline ctxt.
+ SyntaxContext::from_u32(ctxt_or_tag)
}
+ } else if self.len_or_tag & PARENT_MASK == 0 {
+ // Inline format with inline ctxt.
+ SyntaxContext::from_u32(ctxt_or_tag)
} else {
- // Interned format.
- let index = self.base_or_index;
- with_span_interner(|interner| interner.spans[index as usize].ctxt)
+ // Inline format with inline parent.
+ // We know that the SyntaxContext is root.
+ SyntaxContext::root()
}
}
}
diff --git a/compiler/rustc_trait_selection/src/solve/trait_goals.rs b/compiler/rustc_trait_selection/src/solve/trait_goals.rs
index 1abcc80d01a32..8e7097ce4a779 100644
--- a/compiler/rustc_trait_selection/src/solve/trait_goals.rs
+++ b/compiler/rustc_trait_selection/src/solve/trait_goals.rs
@@ -645,12 +645,16 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
// FIXME: Handling opaques here is kinda sus. Especially because we
// simplify them to PlaceholderSimplifiedType.
| ty::Alias(ty::Opaque, _) => {
- if let Some(def_id) = self.tcx().find_map_relevant_impl(
+ let mut disqualifying_impl = None;
+ self.tcx().for_each_relevant_impl_treating_projections(
goal.predicate.def_id(),
goal.predicate.self_ty(),
TreatProjections::NextSolverLookup,
- Some,
- ) {
+ |impl_def_id| {
+ disqualifying_impl = Some(impl_def_id);
+ },
+ );
+ if let Some(def_id) = disqualifying_impl {
debug!(?def_id, ?goal, "disqualified auto-trait implementation");
// No need to actually consider the candidate here,
// since we do that in `consider_impl_candidate`.
diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs
index ae21dcd2a360c..61e382bbe49d6 100644
--- a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs
+++ b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs
@@ -32,7 +32,6 @@ use rustc_infer::infer::{InferOk, TypeTrace};
use rustc_middle::traits::select::OverflowError;
use rustc_middle::ty::abstract_const::NotConstEvaluatable;
use rustc_middle::ty::error::{ExpectedFound, TypeError};
-use rustc_middle::ty::fast_reject::TreatProjections;
use rustc_middle::ty::fold::{TypeFolder, TypeSuperFoldable};
use rustc_middle::ty::print::{with_forced_trimmed_paths, FmtPrinter, Print};
use rustc_middle::ty::{
@@ -1836,57 +1835,61 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
});
let mut diag = struct_span_err!(self.tcx.sess, obligation.cause.span, E0271, "{msg}");
- let secondary_span = match predicate.kind().skip_binder() {
- ty::PredicateKind::Clause(ty::Clause::Projection(proj)) => self
- .tcx
- .opt_associated_item(proj.projection_ty.def_id)
- .and_then(|trait_assoc_item| {
- self.tcx
- .trait_of_item(proj.projection_ty.def_id)
- .map(|id| (trait_assoc_item, id))
- })
- .and_then(|(trait_assoc_item, id)| {
- let trait_assoc_ident = trait_assoc_item.ident(self.tcx);
- self.tcx.find_map_relevant_impl(
- id,
- proj.projection_ty.self_ty(),
- TreatProjections::ForLookup,
- |did| {
- self.tcx
- .associated_items(did)
- .in_definition_order()
- .find(|assoc| assoc.ident(self.tcx) == trait_assoc_ident)
- },
- )
- })
- .and_then(|item| match self.tcx.hir().get_if_local(item.def_id) {
- Some(
- hir::Node::TraitItem(hir::TraitItem {
- kind: hir::TraitItemKind::Type(_, Some(ty)),
- ..
- })
- | hir::Node::ImplItem(hir::ImplItem {
- kind: hir::ImplItemKind::Type(ty),
- ..
- }),
- ) => Some((
- ty.span,
- with_forced_trimmed_paths!(format!(
- "type mismatch resolving `{}`",
- self.resolve_vars_if_possible(predicate)
- .print(FmtPrinter::new_with_limit(
- self.tcx,
- Namespace::TypeNS,
- rustc_session::Limit(5),
- ))
- .unwrap()
- .into_buffer()
- )),
+ let secondary_span = (|| {
+ let ty::PredicateKind::Clause(ty::Clause::Projection(proj)) =
+ predicate.kind().skip_binder()
+ else {
+ return None;
+ };
+
+ let trait_assoc_item = self.tcx.opt_associated_item(proj.projection_ty.def_id)?;
+ let trait_assoc_ident = trait_assoc_item.ident(self.tcx);
+
+ let mut associated_items = vec![];
+ self.tcx.for_each_relevant_impl(
+ self.tcx.trait_of_item(proj.projection_ty.def_id)?,
+ proj.projection_ty.self_ty(),
+ |impl_def_id| {
+ associated_items.extend(
+ self.tcx
+ .associated_items(impl_def_id)
+ .in_definition_order()
+ .find(|assoc| assoc.ident(self.tcx) == trait_assoc_ident),
+ );
+ },
+ );
+
+ let [associated_item]: &[ty::AssocItem] = &associated_items[..] else {
+ return None;
+ };
+ match self.tcx.hir().get_if_local(associated_item.def_id) {
+ Some(
+ hir::Node::TraitItem(hir::TraitItem {
+ kind: hir::TraitItemKind::Type(_, Some(ty)),
+ ..
+ })
+ | hir::Node::ImplItem(hir::ImplItem {
+ kind: hir::ImplItemKind::Type(ty),
+ ..
+ }),
+ ) => Some((
+ ty.span,
+ with_forced_trimmed_paths!(format!(
+ "type mismatch resolving `{}`",
+ self.resolve_vars_if_possible(predicate)
+ .print(FmtPrinter::new_with_limit(
+ self.tcx,
+ Namespace::TypeNS,
+ rustc_session::Limit(5),
+ ))
+ .unwrap()
+ .into_buffer()
)),
- _ => None,
- }),
- _ => None,
- };
+ )),
+ _ => None,
+ }
+ })();
+
self.note_type_err(
&mut diag,
&obligation.cause,
@@ -2228,14 +2231,18 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
err: &mut Diagnostic,
trait_ref: &ty::PolyTraitRef<'tcx>,
) -> bool {
- let get_trait_impl = |trait_def_id| {
- self.tcx.find_map_relevant_impl(
+ let get_trait_impls = |trait_def_id| {
+ let mut trait_impls = vec![];
+ self.tcx.for_each_relevant_impl(
trait_def_id,
trait_ref.skip_binder().self_ty(),
- TreatProjections::ForLookup,
- Some,
- )
+ |impl_def_id| {
+ trait_impls.push(impl_def_id);
+ },
+ );
+ trait_impls
};
+
let required_trait_path = self.tcx.def_path_str(trait_ref.def_id());
let traits_with_same_path: std::collections::BTreeSet<_> = self
.tcx
@@ -2245,17 +2252,23 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
.collect();
let mut suggested = false;
for trait_with_same_path in traits_with_same_path {
- if let Some(impl_def_id) = get_trait_impl(trait_with_same_path) {
- let impl_span = self.tcx.def_span(impl_def_id);
- err.span_help(impl_span, "trait impl with same name found");
- let trait_crate = self.tcx.crate_name(trait_with_same_path.krate);
- let crate_msg = format!(
- "perhaps two different versions of crate `{}` are being used?",
- trait_crate
- );
- err.note(&crate_msg);
- suggested = true;
+ let trait_impls = get_trait_impls(trait_with_same_path);
+ if trait_impls.is_empty() {
+ continue;
}
+ let impl_spans: Vec<_> =
+ trait_impls.iter().map(|impl_def_id| self.tcx.def_span(*impl_def_id)).collect();
+ err.span_help(
+ impl_spans,
+ format!("trait impl{} with same name found", pluralize!(trait_impls.len())),
+ );
+ let trait_crate = self.tcx.crate_name(trait_with_same_path.krate);
+ let crate_msg = format!(
+ "perhaps two different versions of crate `{}` are being used?",
+ trait_crate
+ );
+ err.note(&crate_msg);
+ suggested = true;
}
suggested
}
diff --git a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs
index a019d00461be1..1db9b8ce92e4f 100644
--- a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs
+++ b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs
@@ -11,7 +11,7 @@ use hir::LangItem;
use rustc_hir as hir;
use rustc_infer::traits::ObligationCause;
use rustc_infer::traits::{Obligation, SelectionError, TraitObligation};
-use rustc_middle::ty::fast_reject::{DeepRejectCtxt, TreatParams, TreatProjections};
+use rustc_middle::ty::fast_reject::{DeepRejectCtxt, TreatParams};
use rustc_middle::ty::{self, Ty, TypeVisitableExt};
use crate::traits;
@@ -875,12 +875,24 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
}
ty::Adt(..) => {
- // Find a custom `impl Drop` impl, if it exists
- let relevant_impl = self.tcx().find_map_relevant_impl(
+ let mut relevant_impl = None;
+ self.tcx().for_each_relevant_impl(
self.tcx().require_lang_item(LangItem::Drop, None),
obligation.predicate.skip_binder().trait_ref.self_ty(),
- TreatProjections::ForLookup,
- Some,
+ |impl_def_id| {
+ if let Some(old_impl_def_id) = relevant_impl {
+ self.tcx()
+ .sess
+ .struct_span_err(
+ self.tcx().def_span(impl_def_id),
+ "multiple drop impls found",
+ )
+ .span_note(self.tcx().def_span(old_impl_def_id), "other impl here")
+ .delay_as_bug();
+ }
+
+ relevant_impl = Some(impl_def_id);
+ },
);
if let Some(impl_def_id) = relevant_impl {
diff --git a/src/bootstrap/builder.rs b/src/bootstrap/builder.rs
index 0d2d512b4b2ae..d9d4685dfc790 100644
--- a/src/bootstrap/builder.rs
+++ b/src/bootstrap/builder.rs
@@ -634,6 +634,14 @@ impl Kind {
Kind::Suggest => "suggest",
}
}
+
+ pub fn test_description(&self) -> &'static str {
+ match self {
+ Kind::Test => "Testing",
+ Kind::Bench => "Benchmarking",
+ _ => panic!("not a test command: {}!", self.as_str()),
+ }
+ }
}
impl<'a> Builder<'a> {
@@ -695,7 +703,6 @@ impl<'a> Builder<'a> {
crate::toolstate::ToolStateCheck,
test::ExpandYamlAnchors,
test::Tidy,
- test::TidySelfTest,
test::Ui,
test::RunPassValgrind,
test::MirOpt,
@@ -711,11 +718,9 @@ impl<'a> Builder<'a> {
test::CrateLibrustc,
test::CrateRustdoc,
test::CrateRustdocJsonTypes,
- test::CrateJsonDocLint,
- test::SuggestTestsCrate,
+ test::CrateBootstrap,
test::Linkcheck,
test::TierCheck,
- test::ReplacePlaceholderTest,
test::Cargotest,
test::Cargo,
test::RustAnalyzer,
diff --git a/src/bootstrap/builder/tests.rs b/src/bootstrap/builder/tests.rs
index 3574f11189ee9..72ac46b6bfddd 100644
--- a/src/bootstrap/builder/tests.rs
+++ b/src/bootstrap/builder/tests.rs
@@ -578,7 +578,6 @@ mod dist {
compiler: Compiler { host, stage: 0 },
target: host,
mode: Mode::Std,
- test_kind: test::TestKind::Test,
crates: vec![INTERNER.intern_str("std")],
},]
);
diff --git a/src/bootstrap/format.rs b/src/bootstrap/format.rs
index b79969663ca2e..d8d3f300a3500 100644
--- a/src/bootstrap/format.rs
+++ b/src/bootstrap/format.rs
@@ -145,10 +145,8 @@ pub fn format(build: &Builder<'_>, check: bool, paths: &[PathBuf]) {
let untracked_paths = untracked_paths_output
.lines()
.filter(|entry| entry.starts_with("??"))
- .filter_map(|entry| {
- let path =
- entry.split(' ').nth(1).expect("every git status entry should list a path");
- path.ends_with(".rs").then_some(path)
+ .map(|entry| {
+ entry.split(' ').nth(1).expect("every git status entry should list a path")
});
for untracked_path in untracked_paths {
println!("skip untracked path {} during rustfmt invocations", untracked_path);
diff --git a/src/bootstrap/lib.rs b/src/bootstrap/lib.rs
index bfdb029951f29..488e8efe66eb3 100644
--- a/src/bootstrap/lib.rs
+++ b/src/bootstrap/lib.rs
@@ -248,6 +248,7 @@ struct Crate {
name: Interned,
deps: HashSet>,
path: PathBuf,
+ has_lib: bool,
}
impl Crate {
diff --git a/src/bootstrap/metadata.rs b/src/bootstrap/metadata.rs
index 597aefadcfe4c..8f2c3faca3a48 100644
--- a/src/bootstrap/metadata.rs
+++ b/src/bootstrap/metadata.rs
@@ -5,7 +5,7 @@ use serde_derive::Deserialize;
use crate::cache::INTERNER;
use crate::util::output;
-use crate::{Build, Crate};
+use crate::{t, Build, Crate};
/// For more information, see the output of
///
@@ -22,6 +22,7 @@ struct Package {
source: Option,
manifest_path: String,
dependencies: Vec,
+ targets: Vec,
}
/// For more information, see the output of
@@ -32,6 +33,11 @@ struct Dependency {
source: Option,
}
+#[derive(Debug, Deserialize)]
+struct Target {
+ kind: Vec,
+}
+
/// Collects and stores package metadata of each workspace members into `build`,
/// by executing `cargo metadata` commands.
pub fn build(build: &mut Build) {
@@ -46,11 +52,16 @@ pub fn build(build: &mut Build) {
.filter(|dep| dep.source.is_none())
.map(|dep| INTERNER.intern_string(dep.name))
.collect();
- let krate = Crate { name, deps, path };
+ let has_lib = package.targets.iter().any(|t| t.kind.iter().any(|k| k == "lib"));
+ let krate = Crate { name, deps, path, has_lib };
let relative_path = krate.local_path(build);
build.crates.insert(name, krate);
let existing_path = build.crate_paths.insert(relative_path, name);
- assert!(existing_path.is_none(), "multiple crates with the same path");
+ assert!(
+ existing_path.is_none(),
+ "multiple crates with the same path: {}",
+ existing_path.unwrap()
+ );
}
}
}
@@ -60,7 +71,7 @@ pub fn build(build: &mut Build) {
/// Note that `src/tools/cargo` is no longer a workspace member but we still
/// treat it as one here, by invoking an additional `cargo metadata` command.
fn workspace_members(build: &Build) -> impl Iterator
- {
- let cmd_metadata = |manifest_path| {
+ let collect_metadata = |manifest_path| {
let mut cargo = Command::new(&build.initial_cargo);
cargo
.arg("metadata")
@@ -68,21 +79,20 @@ fn workspace_members(build: &Build) -> impl Iterator
- {
.arg("1")
.arg("--no-deps")
.arg("--manifest-path")
- .arg(manifest_path);
- cargo
+ .arg(build.src.join(manifest_path));
+ let metadata_output = output(&mut cargo);
+ let Output { packages, .. } = t!(serde_json::from_str(&metadata_output));
+ packages
};
- // Collects `metadata.packages` from the root workspace.
- let root_manifest_path = build.src.join("Cargo.toml");
- let root_output = output(&mut cmd_metadata(&root_manifest_path));
- let Output { packages, .. } = serde_json::from_str(&root_output).unwrap();
-
- // Collects `metadata.packages` from src/tools/cargo separately.
- let cargo_manifest_path = build.src.join("src/tools/cargo/Cargo.toml");
- let cargo_output = output(&mut cmd_metadata(&cargo_manifest_path));
- let Output { packages: cargo_packages, .. } = serde_json::from_str(&cargo_output).unwrap();
+ // Collects `metadata.packages` from all workspaces.
+ let packages = collect_metadata("Cargo.toml");
+ let cargo_packages = collect_metadata("src/tools/cargo/Cargo.toml");
+ let ra_packages = collect_metadata("src/tools/rust-analyzer/Cargo.toml");
+ let bootstrap_packages = collect_metadata("src/bootstrap/Cargo.toml");
// We only care about the root package from `src/tool/cargo` workspace.
let cargo_package = cargo_packages.into_iter().find(|pkg| pkg.name == "cargo").into_iter();
- packages.into_iter().chain(cargo_package)
+
+ packages.into_iter().chain(cargo_package).chain(ra_packages).chain(bootstrap_packages)
}
diff --git a/src/bootstrap/test.rs b/src/bootstrap/test.rs
index ccf83974b8c2f..9540adea18973 100644
--- a/src/bootstrap/test.rs
+++ b/src/bootstrap/test.rs
@@ -5,7 +5,6 @@
use std::env;
use std::ffi::OsString;
-use std::fmt;
use std::fs;
use std::iter;
use std::path::{Path, PathBuf};
@@ -14,6 +13,7 @@ use std::process::{Command, Stdio};
use crate::builder::crate_description;
use crate::builder::{Builder, Compiler, Kind, RunConfig, ShouldRun, Step};
use crate::cache::Interned;
+use crate::cache::INTERNER;
use crate::compile;
use crate::config::TargetSelection;
use crate::dist;
@@ -28,44 +28,6 @@ use crate::{envify, CLang, DocTests, GitRepo, Mode};
const ADB_TEST_DIR: &str = "/data/local/tmp/work";
-/// The two modes of the test runner; tests or benchmarks.
-#[derive(Debug, PartialEq, Eq, Hash, Copy, Clone, PartialOrd, Ord)]
-pub enum TestKind {
- /// Run `cargo test`.
- Test,
- /// Run `cargo bench`.
- Bench,
-}
-
-impl From for TestKind {
- fn from(kind: Kind) -> Self {
- match kind {
- Kind::Test => TestKind::Test,
- Kind::Bench => TestKind::Bench,
- _ => panic!("unexpected kind in crate: {:?}", kind),
- }
- }
-}
-
-impl TestKind {
- // Return the cargo subcommand for this test kind
- fn subcommand(self) -> &'static str {
- match self {
- TestKind::Test => "test",
- TestKind::Bench => "bench",
- }
- }
-}
-
-impl fmt::Display for TestKind {
- fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
- f.write_str(match *self {
- TestKind::Test => "Testing",
- TestKind::Bench => "Benchmarking",
- })
- }
-}
-
fn try_run(builder: &Builder<'_>, cmd: &mut Command) -> bool {
if !builder.fail_fast {
if !builder.try_run(cmd) {
@@ -93,26 +55,37 @@ fn try_run_quiet(builder: &Builder<'_>, cmd: &mut Command) -> bool {
}
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
-pub struct CrateJsonDocLint {
+pub struct CrateBootstrap {
+ path: Interned,
host: TargetSelection,
}
-impl Step for CrateJsonDocLint {
+impl Step for CrateBootstrap {
type Output = ();
const ONLY_HOSTS: bool = true;
const DEFAULT: bool = true;
fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
run.path("src/tools/jsondoclint")
+ .path("src/tools/suggest-tests")
+ .path("src/tools/replace-version-placeholder")
+ .alias("tidyselftest")
}
fn make_run(run: RunConfig<'_>) {
- run.builder.ensure(CrateJsonDocLint { host: run.target });
+ for path in run.paths {
+ let path = INTERNER.intern_path(path.assert_single_path().path.clone());
+ run.builder.ensure(CrateBootstrap { host: run.target, path });
+ }
}
fn run(self, builder: &Builder<'_>) {
let bootstrap_host = builder.config.build;
let compiler = builder.compiler(0, bootstrap_host);
+ let mut path = self.path.to_str().unwrap();
+ if path == "tidyselftest" {
+ path = "src/tools/tidy";
+ }
let cargo = tool::prepare_tool_cargo(
builder,
@@ -120,47 +93,18 @@ impl Step for CrateJsonDocLint {
Mode::ToolBootstrap,
bootstrap_host,
"test",
- "src/tools/jsondoclint",
+ path,
SourceType::InTree,
&[],
);
- add_flags_and_try_run_tests(builder, &mut cargo.into());
- }
-}
-
-#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
-pub struct SuggestTestsCrate {
- host: TargetSelection,
-}
-
-impl Step for SuggestTestsCrate {
- type Output = ();
- const ONLY_HOSTS: bool = true;
- const DEFAULT: bool = true;
-
- fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
- run.path("src/tools/suggest-tests")
- }
-
- fn make_run(run: RunConfig<'_>) {
- run.builder.ensure(SuggestTestsCrate { host: run.target });
- }
-
- fn run(self, builder: &Builder<'_>) {
- let bootstrap_host = builder.config.build;
- let compiler = builder.compiler(0, bootstrap_host);
-
- let suggest_tests = tool::prepare_tool_cargo(
- builder,
- compiler,
- Mode::ToolBootstrap,
+ builder.info(&format!(
+ "{} {} stage0 ({})",
+ builder.kind.test_description(),
+ path,
bootstrap_host,
- "test",
- "src/tools/suggest-tests",
- SourceType::InTree,
- &[],
- );
- add_flags_and_try_run_tests(builder, &mut suggest_tests.into());
+ ));
+ let crate_name = path.rsplit_once('/').unwrap().1;
+ run_cargo_test(cargo, &[], &[], crate_name, compiler, bootstrap_host, builder);
}
}
@@ -209,7 +153,11 @@ You can skip linkcheck with --exclude src/tools/linkchecker"
SourceType::InTree,
&[],
);
- add_flags_and_try_run_tests(builder, &mut cargo.into());
+ run_cargo_test(cargo, &[], &[], "linkchecker", compiler, bootstrap_host, builder);
+
+ if builder.doc_tests == DocTests::No {
+ return;
+ }
// Build all the default documentation.
builder.default_doc(&[]);
@@ -356,21 +304,15 @@ impl Step for Cargo {
&[],
);
- if !builder.fail_fast {
- cargo.arg("--no-fail-fast");
- }
- cargo.arg("--").args(builder.config.cmd.test_args());
-
// Don't run cross-compile tests, we may not have cross-compiled libstd libs
// available.
cargo.env("CFG_DISABLE_CROSS_TESTS", "1");
// Forcibly disable tests using nightly features since any changes to
// those features won't be able to land.
cargo.env("CARGO_TEST_DISABLE_NIGHTLY", "1");
-
cargo.env("PATH", &path_for_cargo(builder, compiler));
- add_flags_and_try_run_tests(builder, &mut cargo.into());
+ run_cargo_test(cargo, &[], &[], "cargo", compiler, self.host, builder);
}
}
@@ -427,9 +369,7 @@ impl Step for RustAnalyzer {
cargo.env("SKIP_SLOW_TESTS", "1");
cargo.add_rustc_lib_path(builder, compiler);
- cargo.arg("--").args(builder.config.cmd.test_args());
-
- add_flags_and_try_run_tests(builder, &mut cargo.into());
+ run_cargo_test(cargo, &[], &[], "rust-analyzer", compiler, host, builder);
}
}
@@ -472,17 +412,13 @@ impl Step for Rustfmt {
&[],
);
- if !builder.fail_fast {
- cargo.arg("--no-fail-fast");
- }
-
let dir = testdir(builder, compiler.host);
t!(fs::create_dir_all(&dir));
cargo.env("RUSTFMT_TEST_DIR", dir);
cargo.add_rustc_lib_path(builder, compiler);
- add_flags_and_try_run_tests(builder, &mut cargo.into());
+ run_cargo_test(cargo, &[], &[], "rustfmt", compiler, host, builder);
}
}
@@ -528,12 +464,9 @@ impl Step for RustDemangler {
t!(fs::create_dir_all(&dir));
cargo.env("RUST_DEMANGLER_DRIVER_PATH", rust_demangler);
-
- cargo.arg("--").args(builder.config.cmd.test_args());
-
cargo.add_rustc_lib_path(builder, compiler);
- add_flags_and_try_run_tests(builder, &mut cargo.into());
+ run_cargo_test(cargo, &[], &[], "rust-demangler", compiler, host, builder);
}
}
@@ -656,10 +589,6 @@ impl Step for Miri {
);
cargo.add_rustc_lib_path(builder, compiler);
- if !builder.fail_fast {
- cargo.arg("--no-fail-fast");
- }
-
// miri tests need to know about the stage sysroot
cargo.env("MIRI_SYSROOT", &miri_sysroot);
cargo.env("MIRI_HOST_SYSROOT", sysroot);
@@ -671,13 +600,14 @@ impl Step for Miri {
// Set the target.
cargo.env("MIRI_TEST_TARGET", target.rustc_target_arg());
- // Forward test filters.
- cargo.arg("--").args(builder.config.cmd.test_args());
- // This can NOT be `add_flags_and_try_run_tests` since the Miri test runner
- // does not understand those flags!
- let mut cargo = Command::from(cargo);
- builder.run(&mut cargo);
+ // This can NOT be `run_cargo_test` since the Miri test runner
+ // does not understand the flags added by `add_flags_and_try_run_test`.
+ let mut cargo = prepare_cargo_test(cargo, &[], &[], "miri", compiler, target, builder);
+ {
+ let _time = util::timeit(&builder);
+ builder.run(&mut cargo);
+ }
// # Run `cargo miri test`.
// This is just a smoke test (Miri's own CI invokes this in a bunch of different ways and ensures
@@ -710,6 +640,7 @@ impl Step for Miri {
cargo.env("RUST_BACKTRACE", "1");
let mut cargo = Command::from(cargo);
+ let _time = util::timeit(&builder);
builder.run(&mut cargo);
}
}
@@ -749,8 +680,7 @@ impl Step for CompiletestTest {
&[],
);
cargo.allow_features("test");
-
- add_flags_and_try_run_tests(builder, &mut cargo.into());
+ run_cargo_test(cargo, &[], &[], "compiletest", compiler, host, builder);
}
}
@@ -793,20 +723,15 @@ impl Step for Clippy {
&[],
);
- if !builder.fail_fast {
- cargo.arg("--no-fail-fast");
- }
-
cargo.env("RUSTC_TEST_SUITE", builder.rustc(compiler));
cargo.env("RUSTC_LIB_PATH", builder.rustc_libdir(compiler));
let host_libs = builder.stage_out(compiler, Mode::ToolRustc).join(builder.cargo_dir());
cargo.env("HOST_LIBS", host_libs);
- cargo.arg("--").args(builder.config.cmd.test_args());
-
cargo.add_rustc_lib_path(builder, compiler);
+ let mut cargo = prepare_cargo_test(cargo, &[], &[], "clippy", compiler, host, builder);
- if builder.try_run(&mut cargo.into()) {
+ if builder.try_run(&mut cargo) {
// The tests succeeded; nothing to do.
return;
}
@@ -1204,40 +1129,6 @@ help: to skip test's attempt to check tidiness, pass `--exclude src/tools/tidy`
}
}
-/// Runs tidy's own tests.
-#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
-pub struct TidySelfTest;
-
-impl Step for TidySelfTest {
- type Output = ();
- const DEFAULT: bool = true;
- const ONLY_HOSTS: bool = true;
-
- fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
- run.alias("tidyselftest")
- }
-
- fn make_run(run: RunConfig<'_>) {
- run.builder.ensure(TidySelfTest);
- }
-
- fn run(self, builder: &Builder<'_>) {
- let bootstrap_host = builder.config.build;
- let compiler = builder.compiler(0, bootstrap_host);
- let cargo = tool::prepare_tool_cargo(
- builder,
- compiler,
- Mode::ToolBootstrap,
- bootstrap_host,
- "test",
- "src/tools/tidy",
- SourceType::InTree,
- &[],
- );
- add_flags_and_try_run_tests(builder, &mut cargo.into());
- }
-}
-
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub struct ExpandYamlAnchors;
@@ -2105,7 +1996,6 @@ impl Step for RustcGuide {
pub struct CrateLibrustc {
compiler: Compiler,
target: TargetSelection,
- test_kind: TestKind,
crates: Vec>,
}
@@ -2127,9 +2017,8 @@ impl Step for CrateLibrustc {
.iter()
.map(|p| builder.crate_paths[&p.assert_single_path().path].clone())
.collect();
- let test_kind = builder.kind.into();
- builder.ensure(CrateLibrustc { compiler, target: run.target, test_kind, crates });
+ builder.ensure(CrateLibrustc { compiler, target: run.target, crates });
}
fn run(self, builder: &Builder<'_>) {
@@ -2137,18 +2026,106 @@ impl Step for CrateLibrustc {
compiler: self.compiler,
target: self.target,
mode: Mode::Rustc,
- test_kind: self.test_kind,
crates: self.crates,
});
}
}
+/// Given a `cargo test` subcommand, add the appropriate flags and run it.
+///
+/// Returns whether the test succeeded.
+fn run_cargo_test(
+ cargo: impl Into,
+ libtest_args: &[&str],
+ crates: &[Interned],
+ primary_crate: &str,
+ compiler: Compiler,
+ target: TargetSelection,
+ builder: &Builder<'_>,
+) -> bool {
+ let mut cargo =
+ prepare_cargo_test(cargo, libtest_args, crates, primary_crate, compiler, target, builder);
+ let _time = util::timeit(&builder);
+ add_flags_and_try_run_tests(builder, &mut cargo)
+}
+
+/// Given a `cargo test` subcommand, pass it the appropriate test flags given a `builder`.
+fn prepare_cargo_test(
+ cargo: impl Into,
+ libtest_args: &[&str],
+ crates: &[Interned],
+ primary_crate: &str,
+ compiler: Compiler,
+ target: TargetSelection,
+ builder: &Builder<'_>,
+) -> Command {
+ let mut cargo = cargo.into();
+
+ // Pass in some standard flags then iterate over the graph we've discovered
+ // in `cargo metadata` with the maps above and figure out what `-p`
+ // arguments need to get passed.
+ if builder.kind == Kind::Test && !builder.fail_fast {
+ cargo.arg("--no-fail-fast");
+ }
+ match builder.doc_tests {
+ DocTests::Only => {
+ cargo.arg("--doc");
+ }
+ DocTests::No => {
+ let krate = &builder
+ .crates
+ .get(&INTERNER.intern_str(primary_crate))
+ .unwrap_or_else(|| panic!("missing crate {primary_crate}"));
+ if krate.has_lib {
+ cargo.arg("--lib");
+ }
+ cargo.args(&["--bins", "--examples", "--tests", "--benches"]);
+ }
+ DocTests::Yes => {}
+ }
+
+ for &krate in crates {
+ cargo.arg("-p").arg(krate);
+ }
+
+ cargo.arg("--").args(&builder.config.cmd.test_args()).args(libtest_args);
+ if !builder.config.verbose_tests {
+ cargo.arg("--quiet");
+ }
+
+ // The tests are going to run with the *target* libraries, so we need to
+ // ensure that those libraries show up in the LD_LIBRARY_PATH equivalent.
+ //
+ // Note that to run the compiler we need to run with the *host* libraries,
+ // but our wrapper scripts arrange for that to be the case anyway.
+ let mut dylib_path = dylib_path();
+ dylib_path.insert(0, PathBuf::from(&*builder.sysroot_libdir(compiler, target)));
+ cargo.env(dylib_path_var(), env::join_paths(&dylib_path).unwrap());
+
+ if target.contains("emscripten") {
+ cargo.env(
+ format!("CARGO_TARGET_{}_RUNNER", envify(&target.triple)),
+ builder.config.nodejs.as_ref().expect("nodejs not configured"),
+ );
+ } else if target.starts_with("wasm32") {
+ let node = builder.config.nodejs.as_ref().expect("nodejs not configured");
+ let runner = format!("{} {}/src/etc/wasm32-shim.js", node.display(), builder.src.display());
+ cargo.env(format!("CARGO_TARGET_{}_RUNNER", envify(&target.triple)), &runner);
+ } else if builder.remote_tested(target) {
+ cargo.env(
+ format!("CARGO_TARGET_{}_RUNNER", envify(&target.triple)),
+ format!("{} run 0", builder.tool_exe(Tool::RemoteTestClient).display()),
+ );
+ }
+
+ cargo
+}
+
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct Crate {
pub compiler: Compiler,
pub target: TargetSelection,
pub mode: Mode,
- pub test_kind: TestKind,
pub crates: Vec>,
}
@@ -2164,14 +2141,13 @@ impl Step for Crate {
let builder = run.builder;
let host = run.build_triple();
let compiler = builder.compiler_for(builder.top_stage, host, host);
- let test_kind = builder.kind.into();
let crates = run
.paths
.iter()
.map(|p| builder.crate_paths[&p.assert_single_path().path].clone())
.collect();
- builder.ensure(Crate { compiler, target: run.target, mode: Mode::Std, test_kind, crates });
+ builder.ensure(Crate { compiler, target: run.target, mode: Mode::Std, crates });
}
/// Runs all unit tests plus documentation tests for a given crate defined
@@ -2186,7 +2162,6 @@ impl Step for Crate {
let compiler = self.compiler;
let target = self.target;
let mode = self.mode;
- let test_kind = self.test_kind;
builder.ensure(compile::Std::new(compiler, target));
builder.ensure(RemoteCopyLibs { compiler, target });
@@ -2198,7 +2173,7 @@ impl Step for Crate {
let compiler = builder.compiler_for(compiler.stage, compiler.host, target);
let mut cargo =
- builder.cargo(compiler, mode, SourceType::InTree, target, test_kind.subcommand());
+ builder.cargo(compiler, mode, SourceType::InTree, target, builder.kind.as_str());
match mode {
Mode::Std => {
compile::std_cargo(builder, target, compiler.stage, &mut cargo);
@@ -2209,70 +2184,15 @@ impl Step for Crate {
_ => panic!("can only test libraries"),
};
- // Build up the base `cargo test` command.
- //
- // Pass in some standard flags then iterate over the graph we've discovered
- // in `cargo metadata` with the maps above and figure out what `-p`
- // arguments need to get passed.
- if test_kind.subcommand() == "test" && !builder.fail_fast {
- cargo.arg("--no-fail-fast");
- }
- match builder.doc_tests {
- DocTests::Only => {
- cargo.arg("--doc");
- }
- DocTests::No => {
- cargo.args(&["--lib", "--bins", "--examples", "--tests", "--benches"]);
- }
- DocTests::Yes => {}
- }
-
- for krate in &self.crates {
- cargo.arg("-p").arg(krate);
- }
-
- // The tests are going to run with the *target* libraries, so we need to
- // ensure that those libraries show up in the LD_LIBRARY_PATH equivalent.
- //
- // Note that to run the compiler we need to run with the *host* libraries,
- // but our wrapper scripts arrange for that to be the case anyway.
- let mut dylib_path = dylib_path();
- dylib_path.insert(0, PathBuf::from(&*builder.sysroot_libdir(compiler, target)));
- cargo.env(dylib_path_var(), env::join_paths(&dylib_path).unwrap());
-
- cargo.arg("--");
- cargo.args(&builder.config.cmd.test_args());
-
- cargo.arg("-Z").arg("unstable-options");
- cargo.arg("--format").arg("json");
-
- if target.contains("emscripten") {
- cargo.env(
- format!("CARGO_TARGET_{}_RUNNER", envify(&target.triple)),
- builder.config.nodejs.as_ref().expect("nodejs not configured"),
- );
- } else if target.starts_with("wasm32") {
- let node = builder.config.nodejs.as_ref().expect("nodejs not configured");
- let runner =
- format!("{} {}/src/etc/wasm32-shim.js", node.display(), builder.src.display());
- cargo.env(format!("CARGO_TARGET_{}_RUNNER", envify(&target.triple)), &runner);
- } else if builder.remote_tested(target) {
- cargo.env(
- format!("CARGO_TARGET_{}_RUNNER", envify(&target.triple)),
- format!("{} run 0", builder.tool_exe(Tool::RemoteTestClient).display()),
- );
- }
-
builder.info(&format!(
"{}{} stage{} ({} -> {})",
- test_kind,
+ builder.kind.test_description(),
crate_description(&self.crates),
compiler.stage,
&compiler.host,
target
));
- let _time = util::timeit(&builder);
- crate::render_tests::try_run_tests(builder, &mut cargo.into());
+ run_cargo_test(cargo, &[], &self.crates, &self.crates[0], compiler, target, builder);
}
}
@@ -2280,7 +2200,6 @@ impl Step for Crate {
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub struct CrateRustdoc {
host: TargetSelection,
- test_kind: TestKind,
}
impl Step for CrateRustdoc {
@@ -2295,13 +2214,10 @@ impl Step for CrateRustdoc {
fn make_run(run: RunConfig<'_>) {
let builder = run.builder;
- let test_kind = builder.kind.into();
-
- builder.ensure(CrateRustdoc { host: run.target, test_kind });
+ builder.ensure(CrateRustdoc { host: run.target });
}
fn run(self, builder: &Builder<'_>) {
- let test_kind = self.test_kind;
let target = self.host;
let compiler = if builder.download_rustc() {
@@ -2320,29 +2236,11 @@ impl Step for CrateRustdoc {
compiler,
Mode::ToolRustc,
target,
- test_kind.subcommand(),
+ builder.kind.as_str(),
"src/tools/rustdoc",
SourceType::InTree,
&[],
);
- if test_kind.subcommand() == "test" && !builder.fail_fast {
- cargo.arg("--no-fail-fast");
- }
- match builder.doc_tests {
- DocTests::Only => {
- cargo.arg("--doc");
- }
- DocTests::No => {
- cargo.args(&["--lib", "--bins", "--examples", "--tests", "--benches"]);
- }
- DocTests::Yes => {}
- }
-
- cargo.arg("-p").arg("rustdoc:0.0.0");
-
- cargo.arg("--");
- cargo.args(&builder.config.cmd.test_args());
-
if self.host.contains("musl") {
cargo.arg("'-Ctarget-feature=-crt-static'");
}
@@ -2382,24 +2280,28 @@ impl Step for CrateRustdoc {
dylib_path.insert(0, PathBuf::from(&*libdir));
cargo.env(dylib_path_var(), env::join_paths(&dylib_path).unwrap());
- if !builder.config.verbose_tests {
- cargo.arg("--quiet");
- }
-
builder.info(&format!(
"{} rustdoc stage{} ({} -> {})",
- test_kind, compiler.stage, &compiler.host, target
+ builder.kind.test_description(),
+ compiler.stage,
+ &compiler.host,
+ target
));
- let _time = util::timeit(&builder);
-
- add_flags_and_try_run_tests(builder, &mut cargo.into());
+ run_cargo_test(
+ cargo,
+ &[],
+ &[INTERNER.intern_str("rustdoc:0.0.0")],
+ "rustdoc",
+ compiler,
+ target,
+ builder,
+ );
}
}
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub struct CrateRustdocJsonTypes {
host: TargetSelection,
- test_kind: TestKind,
}
impl Step for CrateRustdocJsonTypes {
@@ -2414,13 +2316,10 @@ impl Step for CrateRustdocJsonTypes {
fn make_run(run: RunConfig<'_>) {
let builder = run.builder;
- let test_kind = builder.kind.into();
-
- builder.ensure(CrateRustdocJsonTypes { host: run.target, test_kind });
+ builder.ensure(CrateRustdocJsonTypes { host: run.target });
}
fn run(self, builder: &Builder<'_>) {
- let test_kind = self.test_kind;
let target = self.host;
// Use the previous stage compiler to reuse the artifacts that are
@@ -2430,36 +2329,40 @@ impl Step for CrateRustdocJsonTypes {
let compiler = builder.compiler_for(builder.top_stage, target, target);
builder.ensure(compile::Rustc::new(compiler, target));
- let mut cargo = tool::prepare_tool_cargo(
+ let cargo = tool::prepare_tool_cargo(
builder,
compiler,
Mode::ToolRustc,
target,
- test_kind.subcommand(),
+ builder.kind.as_str(),
"src/rustdoc-json-types",
SourceType::InTree,
&[],
);
- if test_kind.subcommand() == "test" && !builder.fail_fast {
- cargo.arg("--no-fail-fast");
- }
-
- cargo.arg("-p").arg("rustdoc-json-types");
-
- cargo.arg("--");
- cargo.args(&builder.config.cmd.test_args());
- if self.host.contains("musl") {
- cargo.arg("'-Ctarget-feature=-crt-static'");
- }
+ // FIXME: this looks very wrong, libtest doesn't accept `-C` arguments and the quotes are fishy.
+ let libtest_args = if self.host.contains("musl") {
+ ["'-Ctarget-feature=-crt-static'"].as_slice()
+ } else {
+ &[]
+ };
builder.info(&format!(
"{} rustdoc-json-types stage{} ({} -> {})",
- test_kind, compiler.stage, &compiler.host, target
+ builder.kind.test_description(),
+ compiler.stage,
+ &compiler.host,
+ target
));
- let _time = util::timeit(&builder);
-
- add_flags_and_try_run_tests(builder, &mut cargo.into());
+ run_cargo_test(
+ cargo,
+ libtest_args,
+ &[INTERNER.intern_str("rustdoc-json-types")],
+ "rustdoc-json-types",
+ compiler,
+ target,
+ builder,
+ );
}
}
@@ -2597,13 +2500,15 @@ impl Step for Bootstrap {
check_bootstrap.arg("bootstrap_test.py").current_dir(builder.src.join("src/bootstrap/"));
try_run(builder, &mut check_bootstrap);
+ let host = builder.config.build;
+ let compiler = builder.compiler(0, host);
let mut cmd = Command::new(&builder.initial_cargo);
cmd.arg("test")
.current_dir(builder.src.join("src/bootstrap"))
.env("RUSTFLAGS", "-Cdebuginfo=2")
.env("CARGO_TARGET_DIR", builder.out.join("bootstrap"))
.env("RUSTC_BOOTSTRAP", "1")
- .env("RUSTDOC", builder.rustdoc(builder.compiler(0, builder.build.build)))
+ .env("RUSTDOC", builder.rustdoc(compiler))
.env("RUSTC", &builder.initial_rustc);
if let Some(flags) = option_env!("RUSTFLAGS") {
// Use the same rustc flags for testing as for "normal" compilation,
@@ -2611,24 +2516,9 @@ impl Step for Bootstrap {
// https://github.com/rust-lang/rust/issues/49215
cmd.env("RUSTFLAGS", flags);
}
- if !builder.fail_fast {
- cmd.arg("--no-fail-fast");
- }
- match builder.doc_tests {
- DocTests::Only => {
- cmd.arg("--doc");
- }
- DocTests::No => {
- cmd.args(&["--lib", "--bins", "--examples", "--tests", "--benches"]);
- }
- DocTests::Yes => {}
- }
-
- cmd.arg("--").args(&builder.config.cmd.test_args());
// rustbuild tests are racy on directory creation so just run them one at a time.
// Since there's not many this shouldn't be a problem.
- cmd.arg("--test-threads=1");
- add_flags_and_try_run_tests(builder, &mut cmd);
+ run_cargo_test(cmd, &["--test-threads=1"], &[], "bootstrap", compiler, host, builder);
}
fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
@@ -2684,43 +2574,6 @@ impl Step for TierCheck {
}
}
-#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
-pub struct ReplacePlaceholderTest;
-
-impl Step for ReplacePlaceholderTest {
- type Output = ();
- const ONLY_HOSTS: bool = true;
- const DEFAULT: bool = true;
-
- /// Ensure the version placeholder replacement tool builds
- fn run(self, builder: &Builder<'_>) {
- builder.info("build check for version replacement placeholder");
-
- // Test the version placeholder replacement tool itself.
- let bootstrap_host = builder.config.build;
- let compiler = builder.compiler(0, bootstrap_host);
- let cargo = tool::prepare_tool_cargo(
- builder,
- compiler,
- Mode::ToolBootstrap,
- bootstrap_host,
- "test",
- "src/tools/replace-version-placeholder",
- SourceType::InTree,
- &[],
- );
- add_flags_and_try_run_tests(builder, &mut cargo.into());
- }
-
- fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
- run.path("src/tools/replace-version-placeholder")
- }
-
- fn make_run(run: RunConfig<'_>) {
- run.builder.ensure(Self);
- }
-}
-
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub struct LintDocs {
pub compiler: Compiler,
@@ -2778,7 +2631,7 @@ impl Step for RustInstaller {
SourceType::InTree,
&[],
);
- try_run(builder, &mut cargo.into());
+ run_cargo_test(cargo, &[], &[], "installer", compiler, bootstrap_host, builder);
// We currently don't support running the test.sh script outside linux(?) environments.
// Eventually this should likely migrate to #[test]s in rust-installer proper rather than a
diff --git a/src/bootstrap/tool.rs b/src/bootstrap/tool.rs
index f8da6df0c7ccd..b134adf19674d 100644
--- a/src/bootstrap/tool.rs
+++ b/src/bootstrap/tool.rs
@@ -155,7 +155,7 @@ pub fn prepare_tool_cargo(
mode: Mode,
target: TargetSelection,
command: &'static str,
- path: &'static str,
+ path: &str,
source_type: SourceType,
extra_features: &[String],
) -> CargoCommand {
diff --git a/src/librustdoc/html/static/css/settings.css b/src/librustdoc/html/static/css/settings.css
index d13c783d2e4fb..99cf8e443f032 100644
--- a/src/librustdoc/html/static/css/settings.css
+++ b/src/librustdoc/html/static/css/settings.css
@@ -7,7 +7,6 @@
margin-right: 0.3em;
height: 1.2rem;
width: 1.2rem;
- color: inherit;
border: 2px solid var(--settings-input-border-color);
outline: none;
-webkit-appearance: none;
diff --git a/src/librustdoc/html/static/js/settings.js b/src/librustdoc/html/static/js/settings.js
index ebbe6c1ca9a24..2cba32c1b507a 100644
--- a/src/librustdoc/html/static/js/settings.js
+++ b/src/librustdoc/html/static/js/settings.js
@@ -1,5 +1,5 @@
// Local js definitions:
-/* global getSettingValue, getVirtualKey, updateLocalStorage, updateTheme */
+/* global getSettingValue, updateLocalStorage, updateTheme */
/* global addClass, removeClass, onEach, onEachLazy, blurHandler, elemIsInParent */
/* global MAIN_ID, getVar, getSettingsButton */
@@ -32,21 +32,6 @@
}
}
- function handleKey(ev) {
- // Don't interfere with browser shortcuts
- if (ev.ctrlKey || ev.altKey || ev.metaKey) {
- return;
- }
- switch (getVirtualKey(ev)) {
- case "Enter":
- case "Return":
- case "Space":
- ev.target.checked = !ev.target.checked;
- ev.preventDefault();
- break;
- }
- }
-
function showLightAndDark() {
removeClass(document.getElementById("preferred-light-theme"), "hidden");
removeClass(document.getElementById("preferred-dark-theme"), "hidden");
@@ -77,8 +62,6 @@
toggle.onchange = function() {
changeSetting(this.id, this.checked);
};
- toggle.onkeyup = handleKey;
- toggle.onkeyrelease = handleKey;
});
onEachLazy(settingsElement.querySelectorAll("input[type=\"radio\"]"), elem => {
const settingId = elem.name;
diff --git a/src/librustdoc/passes/collect_intra_doc_links.rs b/src/librustdoc/passes/collect_intra_doc_links.rs
index 33e80df9ed77b..f2486abaaa77e 100644
--- a/src/librustdoc/passes/collect_intra_doc_links.rs
+++ b/src/librustdoc/passes/collect_intra_doc_links.rs
@@ -13,7 +13,7 @@ use rustc_hir::def::Namespace::*;
use rustc_hir::def::{DefKind, Namespace, PerNS};
use rustc_hir::def_id::{DefId, CRATE_DEF_ID};
use rustc_hir::Mutability;
-use rustc_middle::ty::{fast_reject::TreatProjections, Ty, TyCtxt};
+use rustc_middle::ty::{Ty, TyCtxt};
use rustc_middle::{bug, ty};
use rustc_resolve::rustdoc::{has_primitive_or_keyword_docs, prepare_to_doc_link_resolution};
use rustc_resolve::rustdoc::{strip_generics_from_path, MalformedGenerics};
@@ -772,11 +772,10 @@ fn trait_impls_for<'a>(
module: DefId,
) -> FxHashSet<(DefId, DefId)> {
let tcx = cx.tcx;
- let iter = tcx.doc_link_traits_in_scope(module).iter().flat_map(|&trait_| {
- trace!("considering explicit impl for trait {:?}", trait_);
+ let mut impls = FxHashSet::default();
- // Look at each trait implementation to see if it's an impl for `did`
- tcx.find_map_relevant_impl(trait_, ty, TreatProjections::ForLookup, |impl_| {
+ for &trait_ in tcx.doc_link_traits_in_scope(module) {
+ tcx.for_each_relevant_impl(trait_, ty, |impl_| {
let trait_ref = tcx.impl_trait_ref(impl_).expect("this is not an inherent impl");
// Check if these are the same type.
let impl_type = trait_ref.skip_binder().self_ty();
@@ -800,10 +799,13 @@ fn trait_impls_for<'a>(
_ => false,
};
- if saw_impl { Some((impl_, trait_)) } else { None }
- })
- });
- iter.collect()
+ if saw_impl {
+ impls.insert((impl_, trait_));
+ }
+ });
+ }
+
+ impls
}
/// Check for resolve collisions between a trait and its derive.
diff --git a/tests/rustdoc-gui/settings.goml b/tests/rustdoc-gui/settings.goml
index 733be9bebbabc..a44ff9d3e4a9d 100644
--- a/tests/rustdoc-gui/settings.goml
+++ b/tests/rustdoc-gui/settings.goml
@@ -256,6 +256,15 @@ set-local-storage: {"rustdoc-disable-shortcuts": "false"}
click: ".setting-line:last-child .setting-check span"
assert-local-storage: {"rustdoc-disable-shortcuts": "true"}
+// We now check that focusing a toggle and pressing Space is like clicking on it.
+assert-local-storage: {"rustdoc-disable-shortcuts": "true"}
+focus: ".setting-line:last-child .setting-check input"
+press-key: "Space"
+assert-local-storage: {"rustdoc-disable-shortcuts": "false"}
+focus: ".setting-line:last-child .setting-check input"
+press-key: "Space"
+assert-local-storage: {"rustdoc-disable-shortcuts": "true"}
+
// Make sure that "Disable keyboard shortcuts" actually took effect.
press-key: "Escape"
press-key: "?"
diff --git a/tests/ui/typeck/bad-recursive-type-sig-infer.rs b/tests/ui/typeck/bad-recursive-type-sig-infer.rs
new file mode 100644
index 0000000000000..9812d8c381117
--- /dev/null
+++ b/tests/ui/typeck/bad-recursive-type-sig-infer.rs
@@ -0,0 +1,11 @@
+fn a() -> _ {
+ //~^ ERROR the placeholder `_` is not allowed within types on item signatures for return types
+ &a
+}
+
+fn b() -> _ {
+ //~^ ERROR the placeholder `_` is not allowed within types on item signatures for return types
+ &a
+}
+
+fn main() {}
diff --git a/tests/ui/typeck/bad-recursive-type-sig-infer.stderr b/tests/ui/typeck/bad-recursive-type-sig-infer.stderr
new file mode 100644
index 0000000000000..e145da5623ac0
--- /dev/null
+++ b/tests/ui/typeck/bad-recursive-type-sig-infer.stderr
@@ -0,0 +1,15 @@
+error[E0121]: the placeholder `_` is not allowed within types on item signatures for return types
+ --> $DIR/bad-recursive-type-sig-infer.rs:1:11
+ |
+LL | fn a() -> _ {
+ | ^ not allowed in type signatures
+
+error[E0121]: the placeholder `_` is not allowed within types on item signatures for return types
+ --> $DIR/bad-recursive-type-sig-infer.rs:6:11
+ |
+LL | fn b() -> _ {
+ | ^ not allowed in type signatures
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0121`.