diff --git a/Cargo.lock b/Cargo.lock
index 26a9e64b85af4..fc8659b2ec0a9 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -1848,9 +1848,9 @@ dependencies = [
[[package]]
name = "mdbook"
-version = "0.4.2"
+version = "0.4.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b75e31ae4eaa0e45e17ee2b6b9e3ed969c3c6ff12bb4c2e352c42493f4ebb706"
+checksum = "29be448fcafb00c5a8966c4020c2a5ffbbc333e5b96d0bb5ef54b5bd0524d9ff"
dependencies = [
"ammonia",
"anyhow",
diff --git a/compiler/rustc_codegen_ssa/src/traits/intrinsic.rs b/compiler/rustc_codegen_ssa/src/traits/intrinsic.rs
index 9d48e233de655..ccd294d92b2f4 100644
--- a/compiler/rustc_codegen_ssa/src/traits/intrinsic.rs
+++ b/compiler/rustc_codegen_ssa/src/traits/intrinsic.rs
@@ -5,9 +5,9 @@ use rustc_span::Span;
use rustc_target::abi::call::FnAbi;
pub trait IntrinsicCallMethods<'tcx>: BackendTypes {
- /// Remember to add all intrinsics here, in librustc_typeck/check/mod.rs,
- /// and in libcore/intrinsics.rs; if you need access to any llvm intrinsics,
- /// add them to librustc_codegen_llvm/context.rs
+ /// Remember to add all intrinsics here, in `compiler/rustc_typeck/src/check/mod.rs`,
+ /// and in `library/core/src/intrinsics.rs`; if you need access to any LLVM intrinsics,
+ /// add them to `compiler/rustc_codegen_llvm/src/context.rs`.
fn codegen_intrinsic_call(
&mut self,
instance: ty::Instance<'tcx>,
diff --git a/compiler/rustc_error_codes/src/error_codes/E0092.md b/compiler/rustc_error_codes/src/error_codes/E0092.md
index e289534bf7abd..496174b28efac 100644
--- a/compiler/rustc_error_codes/src/error_codes/E0092.md
+++ b/compiler/rustc_error_codes/src/error_codes/E0092.md
@@ -12,8 +12,8 @@ extern "rust-intrinsic" {
```
Please check you didn't make a mistake in the function's name. All intrinsic
-functions are defined in `librustc_codegen_llvm/intrinsic.rs` and in
-`libcore/intrinsics.rs` in the Rust source code. Example:
+functions are defined in `compiler/rustc_codegen_llvm/src/intrinsic.rs` and in
+`library/core/src/intrinsics.rs` in the Rust source code. Example:
```
#![feature(intrinsics)]
diff --git a/compiler/rustc_error_codes/src/error_codes/E0093.md b/compiler/rustc_error_codes/src/error_codes/E0093.md
index 8e7de1a9d37b3..6d58e50ec8813 100644
--- a/compiler/rustc_error_codes/src/error_codes/E0093.md
+++ b/compiler/rustc_error_codes/src/error_codes/E0093.md
@@ -17,8 +17,8 @@ fn main() {
```
Please check you didn't make a mistake in the function's name. All intrinsic
-functions are defined in `librustc_codegen_llvm/intrinsic.rs` and in
-`libcore/intrinsics.rs` in the Rust source code. Example:
+functions are defined in `compiler/rustc_codegen_llvm/src/intrinsic.rs` and in
+`library/core/src/intrinsics.rs` in the Rust source code. Example:
```
#![feature(intrinsics)]
diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs
index cd4185226dce5..636f67a77c890 100644
--- a/compiler/rustc_hir/src/hir.rs
+++ b/compiler/rustc_hir/src/hir.rs
@@ -2004,6 +2004,30 @@ pub enum PrimTy {
Char,
}
+impl PrimTy {
+ pub fn name_str(self) -> &'static str {
+ match self {
+ PrimTy::Int(i) => i.name_str(),
+ PrimTy::Uint(u) => u.name_str(),
+ PrimTy::Float(f) => f.name_str(),
+ PrimTy::Str => "str",
+ PrimTy::Bool => "bool",
+ PrimTy::Char => "char",
+ }
+ }
+
+ pub fn name(self) -> Symbol {
+ match self {
+ PrimTy::Int(i) => i.name(),
+ PrimTy::Uint(u) => u.name(),
+ PrimTy::Float(f) => f.name(),
+ PrimTy::Str => sym::str,
+ PrimTy::Bool => sym::bool,
+ PrimTy::Char => sym::char,
+ }
+ }
+}
+
#[derive(Debug, HashStable_Generic)]
pub struct BareFnTy<'hir> {
pub unsafety: Unsafety,
diff --git a/compiler/rustc_middle/src/traits/mod.rs b/compiler/rustc_middle/src/traits/mod.rs
index a554c80cdaa1a..1dd6d590d908f 100644
--- a/compiler/rustc_middle/src/traits/mod.rs
+++ b/compiler/rustc_middle/src/traits/mod.rs
@@ -28,7 +28,6 @@ pub use self::select::{EvaluationCache, EvaluationResult, OverflowError, Selecti
pub type CanonicalChalkEnvironmentAndGoal<'tcx> = Canonical<'tcx, ChalkEnvironmentAndGoal<'tcx>>;
-pub use self::ImplSource::*;
pub use self::ObligationCauseCode::*;
pub use self::chalk::{ChalkEnvironmentAndGoal, RustInterner as ChalkRustInterner};
@@ -418,10 +417,10 @@ pub type SelectionResult<'tcx, T> = Result, SelectionError<'tcx>>;
///
/// // Case B: ImplSource must be provided by caller. This applies when
/// // type is a type parameter.
-/// param.clone(); // ImplSourceParam
+/// param.clone(); // ImplSource::Param
///
/// // Case C: A mix of cases A and B.
-/// mixed.clone(); // ImplSource(Impl_1, [ImplSourceParam])
+/// mixed.clone(); // ImplSource(Impl_1, [ImplSource::Param])
/// }
/// ```
///
@@ -431,72 +430,72 @@ pub type SelectionResult<'tcx, T> = Result , SelectionError<'tcx>>;
#[derive(Clone, PartialEq, Eq, TyEncodable, TyDecodable, HashStable, TypeFoldable, Lift)]
pub enum ImplSource<'tcx, N> {
/// ImplSource identifying a particular impl.
- ImplSourceUserDefined(ImplSourceUserDefinedData<'tcx, N>),
+ UserDefined(ImplSourceUserDefinedData<'tcx, N>),
/// ImplSource for auto trait implementations.
/// This carries the information and nested obligations with regards
/// to an auto implementation for a trait `Trait`. The nested obligations
/// ensure the trait implementation holds for all the constituent types.
- ImplSourceAutoImpl(ImplSourceAutoImplData),
+ AutoImpl(ImplSourceAutoImplData),
/// Successful resolution to an obligation provided by the caller
/// for some type parameter. The `Vec` represents the
/// obligations incurred from normalizing the where-clause (if
/// any).
- ImplSourceParam(Vec),
+ Param(Vec),
/// Virtual calls through an object.
- ImplSourceObject(ImplSourceObjectData<'tcx, N>),
+ Object(ImplSourceObjectData<'tcx, N>),
/// Successful resolution for a builtin trait.
- ImplSourceBuiltin(ImplSourceBuiltinData),
+ Builtin(ImplSourceBuiltinData),
/// ImplSource automatically generated for a closure. The `DefId` is the ID
- /// of the closure expression. This is a `ImplSourceUserDefined` in spirit, but the
+ /// of the closure expression. This is a `ImplSource::UserDefined` in spirit, but the
/// impl is generated by the compiler and does not appear in the source.
- ImplSourceClosure(ImplSourceClosureData<'tcx, N>),
+ Closure(ImplSourceClosureData<'tcx, N>),
/// Same as above, but for a function pointer type with the given signature.
- ImplSourceFnPointer(ImplSourceFnPointerData<'tcx, N>),
+ FnPointer(ImplSourceFnPointerData<'tcx, N>),
/// ImplSource for a builtin `DeterminantKind` trait implementation.
- ImplSourceDiscriminantKind(ImplSourceDiscriminantKindData),
+ DiscriminantKind(ImplSourceDiscriminantKindData),
/// ImplSource automatically generated for a generator.
- ImplSourceGenerator(ImplSourceGeneratorData<'tcx, N>),
+ Generator(ImplSourceGeneratorData<'tcx, N>),
/// ImplSource for a trait alias.
- ImplSourceTraitAlias(ImplSourceTraitAliasData<'tcx, N>),
+ TraitAlias(ImplSourceTraitAliasData<'tcx, N>),
}
impl<'tcx, N> ImplSource<'tcx, N> {
pub fn nested_obligations(self) -> Vec {
match self {
- ImplSourceUserDefined(i) => i.nested,
- ImplSourceParam(n) => n,
- ImplSourceBuiltin(i) => i.nested,
- ImplSourceAutoImpl(d) => d.nested,
- ImplSourceClosure(c) => c.nested,
- ImplSourceGenerator(c) => c.nested,
- ImplSourceObject(d) => d.nested,
- ImplSourceFnPointer(d) => d.nested,
- ImplSourceDiscriminantKind(ImplSourceDiscriminantKindData) => Vec::new(),
- ImplSourceTraitAlias(d) => d.nested,
+ ImplSource::UserDefined(i) => i.nested,
+ ImplSource::Param(n) => n,
+ ImplSource::Builtin(i) => i.nested,
+ ImplSource::AutoImpl(d) => d.nested,
+ ImplSource::Closure(c) => c.nested,
+ ImplSource::Generator(c) => c.nested,
+ ImplSource::Object(d) => d.nested,
+ ImplSource::FnPointer(d) => d.nested,
+ ImplSource::DiscriminantKind(ImplSourceDiscriminantKindData) => Vec::new(),
+ ImplSource::TraitAlias(d) => d.nested,
}
}
pub fn borrow_nested_obligations(&self) -> &[N] {
match &self {
- ImplSourceUserDefined(i) => &i.nested[..],
- ImplSourceParam(n) => &n[..],
- ImplSourceBuiltin(i) => &i.nested[..],
- ImplSourceAutoImpl(d) => &d.nested[..],
- ImplSourceClosure(c) => &c.nested[..],
- ImplSourceGenerator(c) => &c.nested[..],
- ImplSourceObject(d) => &d.nested[..],
- ImplSourceFnPointer(d) => &d.nested[..],
- ImplSourceDiscriminantKind(ImplSourceDiscriminantKindData) => &[],
- ImplSourceTraitAlias(d) => &d.nested[..],
+ ImplSource::UserDefined(i) => &i.nested[..],
+ ImplSource::Param(n) => &n[..],
+ ImplSource::Builtin(i) => &i.nested[..],
+ ImplSource::AutoImpl(d) => &d.nested[..],
+ ImplSource::Closure(c) => &c.nested[..],
+ ImplSource::Generator(c) => &c.nested[..],
+ ImplSource::Object(d) => &d.nested[..],
+ ImplSource::FnPointer(d) => &d.nested[..],
+ ImplSource::DiscriminantKind(ImplSourceDiscriminantKindData) => &[],
+ ImplSource::TraitAlias(d) => &d.nested[..],
}
}
@@ -505,42 +504,42 @@ impl<'tcx, N> ImplSource<'tcx, N> {
F: FnMut(N) -> M,
{
match self {
- ImplSourceUserDefined(i) => ImplSourceUserDefined(ImplSourceUserDefinedData {
+ ImplSource::UserDefined(i) => ImplSource::UserDefined(ImplSourceUserDefinedData {
impl_def_id: i.impl_def_id,
substs: i.substs,
nested: i.nested.into_iter().map(f).collect(),
}),
- ImplSourceParam(n) => ImplSourceParam(n.into_iter().map(f).collect()),
- ImplSourceBuiltin(i) => ImplSourceBuiltin(ImplSourceBuiltinData {
+ ImplSource::Param(n) => ImplSource::Param(n.into_iter().map(f).collect()),
+ ImplSource::Builtin(i) => ImplSource::Builtin(ImplSourceBuiltinData {
nested: i.nested.into_iter().map(f).collect(),
}),
- ImplSourceObject(o) => ImplSourceObject(ImplSourceObjectData {
+ ImplSource::Object(o) => ImplSource::Object(ImplSourceObjectData {
upcast_trait_ref: o.upcast_trait_ref,
vtable_base: o.vtable_base,
nested: o.nested.into_iter().map(f).collect(),
}),
- ImplSourceAutoImpl(d) => ImplSourceAutoImpl(ImplSourceAutoImplData {
+ ImplSource::AutoImpl(d) => ImplSource::AutoImpl(ImplSourceAutoImplData {
trait_def_id: d.trait_def_id,
nested: d.nested.into_iter().map(f).collect(),
}),
- ImplSourceClosure(c) => ImplSourceClosure(ImplSourceClosureData {
+ ImplSource::Closure(c) => ImplSource::Closure(ImplSourceClosureData {
closure_def_id: c.closure_def_id,
substs: c.substs,
nested: c.nested.into_iter().map(f).collect(),
}),
- ImplSourceGenerator(c) => ImplSourceGenerator(ImplSourceGeneratorData {
+ ImplSource::Generator(c) => ImplSource::Generator(ImplSourceGeneratorData {
generator_def_id: c.generator_def_id,
substs: c.substs,
nested: c.nested.into_iter().map(f).collect(),
}),
- ImplSourceFnPointer(p) => ImplSourceFnPointer(ImplSourceFnPointerData {
+ ImplSource::FnPointer(p) => ImplSource::FnPointer(ImplSourceFnPointerData {
fn_ty: p.fn_ty,
nested: p.nested.into_iter().map(f).collect(),
}),
- ImplSourceDiscriminantKind(ImplSourceDiscriminantKindData) => {
- ImplSourceDiscriminantKind(ImplSourceDiscriminantKindData)
+ ImplSource::DiscriminantKind(ImplSourceDiscriminantKindData) => {
+ ImplSource::DiscriminantKind(ImplSourceDiscriminantKindData)
}
- ImplSourceTraitAlias(d) => ImplSourceTraitAlias(ImplSourceTraitAliasData {
+ ImplSource::TraitAlias(d) => ImplSource::TraitAlias(ImplSourceTraitAliasData {
alias_def_id: d.alias_def_id,
substs: d.substs,
nested: d.nested.into_iter().map(f).collect(),
diff --git a/compiler/rustc_middle/src/traits/structural_impls.rs b/compiler/rustc_middle/src/traits/structural_impls.rs
index d73fc628ceb70..b8f6675b8e219 100644
--- a/compiler/rustc_middle/src/traits/structural_impls.rs
+++ b/compiler/rustc_middle/src/traits/structural_impls.rs
@@ -7,25 +7,25 @@ use std::fmt;
impl<'tcx, N: fmt::Debug> fmt::Debug for traits::ImplSource<'tcx, N> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match *self {
- super::ImplSourceUserDefined(ref v) => write!(f, "{:?}", v),
+ super::ImplSource::UserDefined(ref v) => write!(f, "{:?}", v),
- super::ImplSourceAutoImpl(ref t) => write!(f, "{:?}", t),
+ super::ImplSource::AutoImpl(ref t) => write!(f, "{:?}", t),
- super::ImplSourceClosure(ref d) => write!(f, "{:?}", d),
+ super::ImplSource::Closure(ref d) => write!(f, "{:?}", d),
- super::ImplSourceGenerator(ref d) => write!(f, "{:?}", d),
+ super::ImplSource::Generator(ref d) => write!(f, "{:?}", d),
- super::ImplSourceFnPointer(ref d) => write!(f, "ImplSourceFnPointer({:?})", d),
+ super::ImplSource::FnPointer(ref d) => write!(f, "({:?})", d),
- super::ImplSourceDiscriminantKind(ref d) => write!(f, "{:?}", d),
+ super::ImplSource::DiscriminantKind(ref d) => write!(f, "{:?}", d),
- super::ImplSourceObject(ref d) => write!(f, "{:?}", d),
+ super::ImplSource::Object(ref d) => write!(f, "{:?}", d),
- super::ImplSourceParam(ref n) => write!(f, "ImplSourceParam({:?})", n),
+ super::ImplSource::Param(ref n) => write!(f, "ImplSourceParamData({:?})", n),
- super::ImplSourceBuiltin(ref d) => write!(f, "{:?}", d),
+ super::ImplSource::Builtin(ref d) => write!(f, "{:?}", d),
- super::ImplSourceTraitAlias(ref d) => write!(f, "{:?}", d),
+ super::ImplSource::TraitAlias(ref d) => write!(f, "{:?}", d),
}
}
}
@@ -96,7 +96,7 @@ impl<'tcx, N: fmt::Debug> fmt::Debug for traits::ImplSourceTraitAliasData<'tcx,
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(
f,
- "ImplSourceTraitAlias(alias_def_id={:?}, substs={:?}, nested={:?})",
+ "ImplSourceTraitAliasData(alias_def_id={:?}, substs={:?}, nested={:?})",
self.alias_def_id, self.substs, self.nested
)
}
diff --git a/compiler/rustc_mir/src/interpret/intrinsics.rs b/compiler/rustc_mir/src/interpret/intrinsics.rs
index 0664f25e409dc..d3b6d706337ed 100644
--- a/compiler/rustc_mir/src/interpret/intrinsics.rs
+++ b/compiler/rustc_mir/src/interpret/intrinsics.rs
@@ -435,6 +435,12 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
// These just return their argument
self.copy_op(args[0], dest)?;
}
+ sym::assume => {
+ let cond = self.read_scalar(args[0])?.check_init()?.to_bool()?;
+ if !cond {
+ throw_ub_format!("`assume` intrinsic called with `false`");
+ }
+ }
_ => return Ok(false),
}
diff --git a/compiler/rustc_mir/src/interpret/terminator.rs b/compiler/rustc_mir/src/interpret/terminator.rs
index b789cb76e9f85..9f200ca62b8c6 100644
--- a/compiler/rustc_mir/src/interpret/terminator.rs
+++ b/compiler/rustc_mir/src/interpret/terminator.rs
@@ -390,9 +390,9 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
ty::InstanceDef::Virtual(_, idx) => {
let mut args = args.to_vec();
// We have to implement all "object safe receivers". Currently we
- // support built-in pointers (&, &mut, Box) as well as unsized-self. We do
+ // support built-in pointers `(&, &mut, Box)` as well as unsized-self. We do
// not yet support custom self types.
- // Also see librustc_codegen_llvm/abi.rs and librustc_codegen_llvm/mir/block.rs.
+ // Also see `compiler/rustc_codegen_llvm/src/abi.rs` and `compiler/rustc_codegen_ssa/src/mir/block.rs`.
let receiver_place = match args[0].layout.ty.builtin_deref(true) {
Some(_) => {
// Built-in pointer.
diff --git a/compiler/rustc_mir/src/monomorphize/mod.rs b/compiler/rustc_mir/src/monomorphize/mod.rs
index edafa00a03ad0..d2586f0f84dff 100644
--- a/compiler/rustc_mir/src/monomorphize/mod.rs
+++ b/compiler/rustc_mir/src/monomorphize/mod.rs
@@ -21,7 +21,7 @@ pub fn custom_coerce_unsize_info<'tcx>(
});
match tcx.codegen_fulfill_obligation((ty::ParamEnv::reveal_all(), trait_ref)) {
- Ok(traits::ImplSourceUserDefined(traits::ImplSourceUserDefinedData {
+ Ok(traits::ImplSource::UserDefined(traits::ImplSourceUserDefinedData {
impl_def_id,
..
})) => tcx.coerce_unsized_info(impl_def_id).custom_kind.unwrap(),
diff --git a/compiler/rustc_trait_selection/src/traits/auto_trait.rs b/compiler/rustc_trait_selection/src/traits/auto_trait.rs
index 6b87bc4f34ad4..35bfeff10b4aa 100644
--- a/compiler/rustc_trait_selection/src/traits/auto_trait.rs
+++ b/compiler/rustc_trait_selection/src/traits/auto_trait.rs
@@ -96,7 +96,7 @@ impl<'tcx> AutoTraitFinder<'tcx> {
));
match result {
- Ok(Some(ImplSource::ImplSourceUserDefined(_))) => {
+ Ok(Some(ImplSource::UserDefined(_))) => {
debug!(
"find_auto_trait_generics({:?}): \
manual impl found, bailing out",
@@ -315,9 +315,8 @@ impl AutoTraitFinder<'tcx> {
// If we see an explicit negative impl (e.g., `impl !Send for MyStruct`),
// we immediately bail out, since it's impossible for us to continue.
- if let ImplSource::ImplSourceUserDefined(ImplSourceUserDefinedData {
- impl_def_id,
- ..
+ if let ImplSource::UserDefined(ImplSourceUserDefinedData {
+ impl_def_id, ..
}) = impl_source
{
// Blame 'tidy' for the weird bracket placement.
diff --git a/compiler/rustc_trait_selection/src/traits/project.rs b/compiler/rustc_trait_selection/src/traits/project.rs
index d37f819f376d3..ef8f7b69b5d60 100644
--- a/compiler/rustc_trait_selection/src/traits/project.rs
+++ b/compiler/rustc_trait_selection/src/traits/project.rs
@@ -1000,15 +1000,15 @@ fn assemble_candidates_from_impls<'cx, 'tcx>(
};
let eligible = match &impl_source {
- super::ImplSourceClosure(_)
- | super::ImplSourceGenerator(_)
- | super::ImplSourceFnPointer(_)
- | super::ImplSourceObject(_)
- | super::ImplSourceTraitAlias(_) => {
+ super::ImplSource::Closure(_)
+ | super::ImplSource::Generator(_)
+ | super::ImplSource::FnPointer(_)
+ | super::ImplSource::Object(_)
+ | super::ImplSource::TraitAlias(_) => {
debug!("assemble_candidates_from_impls: impl_source={:?}", impl_source);
true
}
- super::ImplSourceUserDefined(impl_data) => {
+ super::ImplSource::UserDefined(impl_data) => {
// We have to be careful when projecting out of an
// impl because of specialization. If we are not in
// codegen (i.e., projection mode is not "any"), and the
@@ -1060,7 +1060,7 @@ fn assemble_candidates_from_impls<'cx, 'tcx>(
}
}
}
- super::ImplSourceDiscriminantKind(..) => {
+ super::ImplSource::DiscriminantKind(..) => {
// While `DiscriminantKind` is automatically implemented for every type,
// the concrete discriminant may not be known yet.
//
@@ -1100,7 +1100,7 @@ fn assemble_candidates_from_impls<'cx, 'tcx>(
| ty::Error(_) => false,
}
}
- super::ImplSourceParam(..) => {
+ super::ImplSource::Param(..) => {
// This case tell us nothing about the value of an
// associated type. Consider:
//
@@ -1128,7 +1128,7 @@ fn assemble_candidates_from_impls<'cx, 'tcx>(
// in `assemble_candidates_from_param_env`.
false
}
- super::ImplSourceAutoImpl(..) | super::ImplSourceBuiltin(..) => {
+ super::ImplSource::AutoImpl(..) | super::ImplSource::Builtin(..) => {
// These traits have no associated types.
selcx.tcx().sess.delay_span_bug(
obligation.cause.span,
@@ -1186,20 +1186,20 @@ fn confirm_select_candidate<'cx, 'tcx>(
impl_source: Selection<'tcx>,
) -> Progress<'tcx> {
match impl_source {
- super::ImplSourceUserDefined(data) => confirm_impl_candidate(selcx, obligation, data),
- super::ImplSourceGenerator(data) => confirm_generator_candidate(selcx, obligation, data),
- super::ImplSourceClosure(data) => confirm_closure_candidate(selcx, obligation, data),
- super::ImplSourceFnPointer(data) => confirm_fn_pointer_candidate(selcx, obligation, data),
- super::ImplSourceDiscriminantKind(data) => {
+ super::ImplSource::UserDefined(data) => confirm_impl_candidate(selcx, obligation, data),
+ super::ImplSource::Generator(data) => confirm_generator_candidate(selcx, obligation, data),
+ super::ImplSource::Closure(data) => confirm_closure_candidate(selcx, obligation, data),
+ super::ImplSource::FnPointer(data) => confirm_fn_pointer_candidate(selcx, obligation, data),
+ super::ImplSource::DiscriminantKind(data) => {
confirm_discriminant_kind_candidate(selcx, obligation, data)
}
- super::ImplSourceObject(_) => {
+ super::ImplSource::Object(_) => {
confirm_object_candidate(selcx, obligation, obligation_trait_ref)
}
- super::ImplSourceAutoImpl(..)
- | super::ImplSourceParam(..)
- | super::ImplSourceBuiltin(..)
- | super::ImplSourceTraitAlias(..) =>
+ super::ImplSource::AutoImpl(..)
+ | super::ImplSource::Param(..)
+ | super::ImplSource::Builtin(..)
+ | super::ImplSource::TraitAlias(..) =>
// we don't create Select candidates with this kind of resolution
{
span_bug!(
diff --git a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs
index 9906c1f325f3d..88b656ce68082 100644
--- a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs
+++ b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs
@@ -19,16 +19,12 @@ use crate::traits::project::{self, normalize_with_depth};
use crate::traits::select::TraitObligationExt;
use crate::traits::util;
use crate::traits::util::{closure_trait_ref_and_return_type, predicate_for_trait_def};
+use crate::traits::ImplSource;
use crate::traits::Normalized;
use crate::traits::OutputTypeParameterMismatch;
use crate::traits::Selection;
use crate::traits::TraitNotObjectSafe;
use crate::traits::{BuiltinDerivedObligation, ImplDerivedObligation};
-use crate::traits::{
- ImplSourceAutoImpl, ImplSourceBuiltin, ImplSourceClosure, ImplSourceDiscriminantKind,
- ImplSourceFnPointer, ImplSourceGenerator, ImplSourceObject, ImplSourceParam,
- ImplSourceTraitAlias, ImplSourceUserDefined,
-};
use crate::traits::{
ImplSourceAutoImplData, ImplSourceBuiltinData, ImplSourceClosureData,
ImplSourceDiscriminantKindData, ImplSourceFnPointerData, ImplSourceGeneratorData,
@@ -55,67 +51,67 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
match candidate {
BuiltinCandidate { has_nested } => {
let data = self.confirm_builtin_candidate(obligation, has_nested);
- Ok(ImplSourceBuiltin(data))
+ Ok(ImplSource::Builtin(data))
}
ParamCandidate(param) => {
let obligations = self.confirm_param_candidate(obligation, param);
- Ok(ImplSourceParam(obligations))
+ Ok(ImplSource::Param(obligations))
}
ImplCandidate(impl_def_id) => {
- Ok(ImplSourceUserDefined(self.confirm_impl_candidate(obligation, impl_def_id)))
+ Ok(ImplSource::UserDefined(self.confirm_impl_candidate(obligation, impl_def_id)))
}
AutoImplCandidate(trait_def_id) => {
let data = self.confirm_auto_impl_candidate(obligation, trait_def_id);
- Ok(ImplSourceAutoImpl(data))
+ Ok(ImplSource::AutoImpl(data))
}
ProjectionCandidate => {
self.confirm_projection_candidate(obligation);
- Ok(ImplSourceParam(Vec::new()))
+ Ok(ImplSource::Param(Vec::new()))
}
ClosureCandidate => {
let vtable_closure = self.confirm_closure_candidate(obligation)?;
- Ok(ImplSourceClosure(vtable_closure))
+ Ok(ImplSource::Closure(vtable_closure))
}
GeneratorCandidate => {
let vtable_generator = self.confirm_generator_candidate(obligation)?;
- Ok(ImplSourceGenerator(vtable_generator))
+ Ok(ImplSource::Generator(vtable_generator))
}
FnPointerCandidate => {
let data = self.confirm_fn_pointer_candidate(obligation)?;
- Ok(ImplSourceFnPointer(data))
+ Ok(ImplSource::FnPointer(data))
}
DiscriminantKindCandidate => {
- Ok(ImplSourceDiscriminantKind(ImplSourceDiscriminantKindData))
+ Ok(ImplSource::DiscriminantKind(ImplSourceDiscriminantKindData))
}
TraitAliasCandidate(alias_def_id) => {
let data = self.confirm_trait_alias_candidate(obligation, alias_def_id);
- Ok(ImplSourceTraitAlias(data))
+ Ok(ImplSource::TraitAlias(data))
}
ObjectCandidate => {
let data = self.confirm_object_candidate(obligation);
- Ok(ImplSourceObject(data))
+ Ok(ImplSource::Object(data))
}
BuiltinObjectCandidate => {
// This indicates something like `Trait + Send: Send`. In this case, we know that
// this holds because that's what the object type is telling us, and there's really
// no additional obligations to prove and no types in particular to unify, etc.
- Ok(ImplSourceParam(Vec::new()))
+ Ok(ImplSource::Param(Vec::new()))
}
BuiltinUnsizeCandidate => {
let data = self.confirm_builtin_unsize_candidate(obligation)?;
- Ok(ImplSourceBuiltin(data))
+ Ok(ImplSource::Builtin(data))
}
}
}
diff --git a/compiler/rustc_ty/src/instance.rs b/compiler/rustc_ty/src/instance.rs
index 75bf8ea0bb816..220f4cec742f1 100644
--- a/compiler/rustc_ty/src/instance.rs
+++ b/compiler/rustc_ty/src/instance.rs
@@ -119,9 +119,9 @@ fn resolve_associated_item<'tcx>(
// Now that we know which impl is being used, we can dispatch to
// the actual function:
Ok(match vtbl {
- traits::ImplSourceUserDefined(impl_data) => {
+ traits::ImplSource::UserDefined(impl_data) => {
debug!(
- "resolving ImplSourceUserDefined: {:?}, {:?}, {:?}, {:?}",
+ "resolving ImplSource::UserDefined: {:?}, {:?}, {:?}, {:?}",
param_env, trait_item, rcvr_substs, impl_data
);
assert!(!rcvr_substs.needs_infer());
@@ -216,13 +216,13 @@ fn resolve_associated_item<'tcx>(
Some(ty::Instance::new(leaf_def.item.def_id, substs))
}
- traits::ImplSourceGenerator(generator_data) => Some(Instance {
+ traits::ImplSource::Generator(generator_data) => Some(Instance {
def: ty::InstanceDef::Item(ty::WithOptConstParam::unknown(
generator_data.generator_def_id,
)),
substs: generator_data.substs,
}),
- traits::ImplSourceClosure(closure_data) => {
+ traits::ImplSource::Closure(closure_data) => {
let trait_closure_kind = tcx.fn_trait_kind_from_lang_item(trait_id).unwrap();
Some(Instance::resolve_closure(
tcx,
@@ -231,18 +231,18 @@ fn resolve_associated_item<'tcx>(
trait_closure_kind,
))
}
- traits::ImplSourceFnPointer(ref data) => match data.fn_ty.kind() {
+ traits::ImplSource::FnPointer(ref data) => match data.fn_ty.kind() {
ty::FnDef(..) | ty::FnPtr(..) => Some(Instance {
def: ty::InstanceDef::FnPtrShim(trait_item.def_id, data.fn_ty),
substs: rcvr_substs,
}),
_ => None,
},
- traits::ImplSourceObject(ref data) => {
+ traits::ImplSource::Object(ref data) => {
let index = traits::get_vtable_index_of_object_method(tcx, data, def_id);
Some(Instance { def: ty::InstanceDef::Virtual(def_id, index), substs: rcvr_substs })
}
- traits::ImplSourceBuiltin(..) => {
+ traits::ImplSource::Builtin(..) => {
if Some(trait_ref.def_id) == tcx.lang_items().clone_trait() {
// FIXME(eddyb) use lang items for methods instead of names.
let name = tcx.item_name(def_id);
@@ -271,10 +271,10 @@ fn resolve_associated_item<'tcx>(
None
}
}
- traits::ImplSourceAutoImpl(..)
- | traits::ImplSourceParam(..)
- | traits::ImplSourceTraitAlias(..)
- | traits::ImplSourceDiscriminantKind(..) => None,
+ traits::ImplSource::AutoImpl(..)
+ | traits::ImplSource::Param(..)
+ | traits::ImplSource::TraitAlias(..)
+ | traits::ImplSource::DiscriminantKind(..) => None,
})
}
diff --git a/compiler/rustc_typeck/src/check/intrinsic.rs b/compiler/rustc_typeck/src/check/intrinsic.rs
index b8230f524446a..2ee867c2dd648 100644
--- a/compiler/rustc_typeck/src/check/intrinsic.rs
+++ b/compiler/rustc_typeck/src/check/intrinsic.rs
@@ -106,8 +106,8 @@ pub fn intrinsic_operation_unsafety(intrinsic: Symbol) -> hir::Unsafety {
}
}
-/// Remember to add all intrinsics here, in librustc_codegen_llvm/intrinsic.rs,
-/// and in libcore/intrinsics.rs
+/// Remember to add all intrinsics here, in `compiler/rustc_codegen_llvm/src/intrinsic.rs`,
+/// and in `library/core/src/intrinsics.rs`.
pub fn check_intrinsic_type(tcx: TyCtxt<'_>, it: &hir::ForeignItem<'_>) {
let param = |n| tcx.mk_ty_param(n, Symbol::intern(&format!("P{}", n)));
let def_id = tcx.hir().local_def_id(it.hir_id).to_def_id();
diff --git a/compiler/rustc_typeck/src/check/method/probe.rs b/compiler/rustc_typeck/src/check/method/probe.rs
index 8a62031ec887c..c1ba29284da16 100644
--- a/compiler/rustc_typeck/src/check/method/probe.rs
+++ b/compiler/rustc_typeck/src/check/method/probe.rs
@@ -1306,7 +1306,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
.at(&ObligationCause::dummy(), self.param_env)
.sup(candidate.xform_self_ty, self_ty);
match self.select_trait_candidate(trait_ref) {
- Ok(Some(traits::ImplSource::ImplSourceUserDefined(ref impl_data))) => {
+ Ok(Some(traits::ImplSource::UserDefined(ref impl_data))) => {
// If only a single impl matches, make the error message point
// to that impl.
ImplSource(impl_data.impl_def_id)
diff --git a/library/core/src/intrinsics.rs b/library/core/src/intrinsics.rs
index bcbb760021ee4..243fc7bfaa51f 100644
--- a/library/core/src/intrinsics.rs
+++ b/library/core/src/intrinsics.rs
@@ -1,7 +1,7 @@
//! Compiler intrinsics.
//!
-//! The corresponding definitions are in `librustc_codegen_llvm/intrinsic.rs`.
-//! The corresponding const implementations are in `librustc_mir/interpret/intrinsics.rs`
+//! The corresponding definitions are in `compiler/rustc_codegen_llvm/src/intrinsic.rs`.
+//! The corresponding const implementations are in `compiler/rustc_mir/src/interpret/intrinsics.rs`
//!
//! # Const intrinsics
//!
@@ -10,7 +10,7 @@
//!
//! In order to make an intrinsic usable at compile-time, one needs to copy the implementation
//! from https://github.com/rust-lang/miri/blob/master/src/shims/intrinsics.rs to
-//! `librustc_mir/interpret/intrinsics.rs` and add a
+//! `compiler/rustc_mir/src/interpret/intrinsics.rs` and add a
//! `#[rustc_const_unstable(feature = "foo", issue = "01234")]` to the intrinsic.
//!
//! If an intrinsic is supposed to be used from a `const fn` with a `rustc_const_stable` attribute,
@@ -733,6 +733,7 @@ extern "rust-intrinsic" {
/// own, or if it does not enable any significant optimizations.
///
/// This intrinsic does not have a stable counterpart.
+ #[rustc_const_unstable(feature = "const_assume", issue = "76972")]
pub fn assume(b: bool);
/// Hints to the compiler that branch condition is likely to be true.
@@ -904,7 +905,7 @@ extern "rust-intrinsic" {
/// let raw_bytes = [0x78, 0x56, 0x34, 0x12];
///
/// let num = unsafe {
- /// std::mem::transmute::<[u8; 4], u32>(raw_bytes);
+ /// std::mem::transmute::<[u8; 4], u32>(raw_bytes)
/// };
///
/// // use `u32::from_ne_bytes` instead
diff --git a/library/core/src/slice/mod.rs b/library/core/src/slice/mod.rs
index ff926c517bc7c..12dcd6c6ba8d0 100644
--- a/library/core/src/slice/mod.rs
+++ b/library/core/src/slice/mod.rs
@@ -433,8 +433,9 @@ impl [T] {
/// assert_eq!(x, &[3, 4, 6]);
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
+ #[rustc_const_unstable(feature = "const_ptr_offset", issue = "71499")]
#[inline]
- pub fn as_mut_ptr(&mut self) -> *mut T {
+ pub const fn as_mut_ptr(&mut self) -> *mut T {
self as *mut [T] as *mut T
}
@@ -469,8 +470,9 @@ impl [T] {
///
/// [`as_ptr`]: #method.as_ptr
#[unstable(feature = "slice_ptr_range", issue = "65807")]
+ #[rustc_const_unstable(feature = "const_ptr_offset", issue = "71499")]
#[inline]
- pub fn as_ptr_range(&self) -> Range<*const T> {
+ pub const fn as_ptr_range(&self) -> Range<*const T> {
let start = self.as_ptr();
// SAFETY: The `add` here is safe, because:
//
@@ -510,8 +512,9 @@ impl [T] {
///
/// [`as_mut_ptr`]: #method.as_mut_ptr
#[unstable(feature = "slice_ptr_range", issue = "65807")]
+ #[rustc_const_unstable(feature = "const_ptr_offset", issue = "71499")]
#[inline]
- pub fn as_mut_ptr_range(&mut self) -> Range<*mut T> {
+ pub const fn as_mut_ptr_range(&mut self) -> Range<*mut T> {
let start = self.as_mut_ptr();
// SAFETY: See as_ptr_range() above for why `add` here is safe.
let end = unsafe { start.add(self.len()) };
diff --git a/library/core/tests/intrinsics.rs b/library/core/tests/intrinsics.rs
index fed7c4a5bf399..de163a60c98f4 100644
--- a/library/core/tests/intrinsics.rs
+++ b/library/core/tests/intrinsics.rs
@@ -1,4 +1,5 @@
use core::any::TypeId;
+use core::intrinsics::assume;
#[test]
fn test_typeid_sized_types() {
@@ -20,3 +21,17 @@ fn test_typeid_unsized_types() {
assert_eq!(TypeId::of::(), TypeId::of::());
assert!(TypeId::of::() != TypeId::of::());
}
+
+// Check that `const_assume` feature allow `assume` intrinsic
+// to be used in const contexts.
+#[test]
+fn test_assume_can_be_in_const_contexts() {
+ const unsafe fn foo(x: usize, y: usize) -> usize {
+ // SAFETY: the entire function is not safe,
+ // but it is just an example not used elsewhere.
+ unsafe { assume(y != 0) };
+ x / y
+ }
+ let rs = unsafe { foo(42, 97) };
+ assert_eq!(rs, 0);
+}
diff --git a/library/core/tests/lib.rs b/library/core/tests/lib.rs
index d8b36beb3e085..8d86349244b09 100644
--- a/library/core/tests/lib.rs
+++ b/library/core/tests/lib.rs
@@ -8,6 +8,8 @@
#![feature(bound_cloned)]
#![feature(box_syntax)]
#![feature(cell_update)]
+#![feature(const_assume)]
+#![feature(core_intrinsics)]
#![feature(core_private_bignum)]
#![feature(core_private_diy_float)]
#![feature(debug_non_exhaustive)]
diff --git a/library/panic_unwind/src/seh.rs b/library/panic_unwind/src/seh.rs
index eca169373f39f..5597bbb93d236 100644
--- a/library/panic_unwind/src/seh.rs
+++ b/library/panic_unwind/src/seh.rs
@@ -175,7 +175,7 @@ pub struct _TypeDescriptor {
// to be able to catch Rust panics by simply declaring a `struct rust_panic`.
//
// When modifying, make sure that the type name string exactly matches
-// the one used in src/librustc_codegen_llvm/intrinsic.rs.
+// the one used in `compiler/rustc_codegen_llvm/src/intrinsic.rs`.
const TYPE_NAME: [u8; 11] = *b"rust_panic\0";
static mut THROW_INFO: _ThrowInfo = _ThrowInfo {
diff --git a/src/bootstrap/CHANGELOG.md b/src/bootstrap/CHANGELOG.md
index 5fcaafab959e9..dfb39c54c1723 100644
--- a/src/bootstrap/CHANGELOG.md
+++ b/src/bootstrap/CHANGELOG.md
@@ -6,6 +6,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
## [Non-breaking changes since the last major version]
+- Add `x.py setup` [#76631](https://github.com/rust-lang/rust/pull/76631)
- Add a changelog for x.py [#76626](https://github.com/rust-lang/rust/pull/76626)
- Optionally, download LLVM from CI on Linux and NixOS
+ [#76439](https://github.com/rust-lang/rust/pull/76349)
@@ -15,6 +16,10 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
- Make the default stage for x.py configurable [#76625](https://github.com/rust-lang/rust/pull/76625)
- Add a dedicated debug-logging option [#76588](https://github.com/rust-lang/rust/pull/76588)
- Add sample defaults for x.py [#76628](https://github.com/rust-lang/rust/pull/76628)
+- Add `--keep-stage-std`, which behaves like `keep-stage` but allows the stage
+ 0 compiler artifacts (i.e., stage1/bin/rustc) to be rebuilt if changed
+ [#77120](https://github.com/rust-lang/rust/pull/77120).
+
## [Version 0] - 2020-09-11
diff --git a/src/bootstrap/bin/main.rs b/src/bootstrap/bin/main.rs
index f7512aa9fcebd..637083e08d510 100644
--- a/src/bootstrap/bin/main.rs
+++ b/src/bootstrap/bin/main.rs
@@ -7,21 +7,34 @@
use std::env;
-use bootstrap::{Build, Config};
+use bootstrap::{Build, Config, Subcommand};
fn main() {
let args = env::args().skip(1).collect::>();
let config = Config::parse(&args);
let changelog_suggestion = check_version(&config);
- if let Some(suggestion) = &changelog_suggestion {
+
+ // NOTE: Since `./configure` generates a `config.toml`, distro maintainers will see the
+ // changelog warning, not the `x.py setup` message.
+ let suggest_setup = !config.config.exists() && !matches!(config.cmd, Subcommand::Setup { .. });
+ if suggest_setup {
+ println!("warning: you have not made a `config.toml`");
+ println!("help: consider running `x.py setup` or copying `config.toml.example`");
+ } else if let Some(suggestion) = &changelog_suggestion {
println!("{}", suggestion);
}
Build::new(config).build();
- if let Some(suggestion) = changelog_suggestion {
+ if suggest_setup {
+ println!("warning: you have not made a `config.toml`");
+ println!("help: consider running `x.py setup` or copying `config.toml.example`");
+ } else if let Some(suggestion) = &changelog_suggestion {
println!("{}", suggestion);
+ }
+
+ if suggest_setup || changelog_suggestion.is_some() {
println!("note: this message was printed twice to make it more likely to be seen");
}
}
@@ -40,7 +53,7 @@ fn check_version(config: &Config) -> Option {
}
} else {
msg.push_str("warning: x.py has made several changes recently you may want to look at\n");
- format!("add `changelog-seen = {}` to `config.toml`", VERSION)
+ format!("add `changelog-seen = {}` at the top of `config.toml`", VERSION)
};
msg.push_str("help: consider looking at the changes in `src/bootstrap/CHANGELOG.md`\n");
diff --git a/src/bootstrap/builder.rs b/src/bootstrap/builder.rs
index d2537d65e67f5..4aaaeb8a93bda 100644
--- a/src/bootstrap/builder.rs
+++ b/src/bootstrap/builder.rs
@@ -549,7 +549,9 @@ impl<'a> Builder<'a> {
Subcommand::Dist { ref paths } => (Kind::Dist, &paths[..]),
Subcommand::Install { ref paths } => (Kind::Install, &paths[..]),
Subcommand::Run { ref paths } => (Kind::Run, &paths[..]),
- Subcommand::Format { .. } | Subcommand::Clean { .. } => panic!(),
+ Subcommand::Format { .. } | Subcommand::Clean { .. } | Subcommand::Setup { .. } => {
+ panic!()
+ }
};
Self::new_internal(build, kind, paths.to_owned())
diff --git a/src/bootstrap/compile.rs b/src/bootstrap/compile.rs
index 08907edef1d1e..40bf6c48296b2 100644
--- a/src/bootstrap/compile.rs
+++ b/src/bootstrap/compile.rs
@@ -59,7 +59,9 @@ impl Step for Std {
let target = self.target;
let compiler = self.compiler;
- if builder.config.keep_stage.contains(&compiler.stage) {
+ if builder.config.keep_stage.contains(&compiler.stage)
+ || builder.config.keep_stage_std.contains(&compiler.stage)
+ {
builder.info("Warning: Using a potentially old libstd. This may not behave well.");
builder.ensure(StdLink { compiler, target_compiler: compiler, target });
return;
@@ -472,6 +474,7 @@ impl Step for Rustc {
if builder.config.keep_stage.contains(&compiler.stage) {
builder.info("Warning: Using a potentially old librustc. This may not behave well.");
+ builder.info("Warning: Use `--keep-stage-std` if you want to rebuild the compiler when it changes");
builder.ensure(RustcLink { compiler, target_compiler: compiler, target });
return;
}
diff --git a/src/bootstrap/config.rs b/src/bootstrap/config.rs
index c74501979f0ec..b14746dabb93a 100644
--- a/src/bootstrap/config.rs
+++ b/src/bootstrap/config.rs
@@ -71,7 +71,10 @@ pub struct Config {
pub on_fail: Option,
pub stage: u32,
pub keep_stage: Vec,
+ pub keep_stage_std: Vec,
pub src: PathBuf,
+ // defaults to `config.toml`
+ pub config: PathBuf,
pub jobs: Option,
pub cmd: Subcommand,
pub incremental: bool,
@@ -512,6 +515,7 @@ impl Config {
config.rust_codegen_backends = vec![INTERNER.intern_str("llvm")];
config.deny_warnings = true;
config.missing_tools = false;
+ config.config = PathBuf::from("config.toml");
// set by bootstrap.py
config.build = TargetSelection::from_user(&env!("BUILD_TRIPLE"));
@@ -539,6 +543,7 @@ impl Config {
config.incremental = flags.incremental;
config.dry_run = flags.dry_run;
config.keep_stage = flags.keep_stage;
+ config.keep_stage_std = flags.keep_stage_std;
config.bindir = "bin".into(); // default
if let Some(value) = flags.deny_warnings {
config.deny_warnings = value;
@@ -556,7 +561,7 @@ impl Config {
let get_toml = |file: PathBuf| {
use std::process;
- let contents = t!(fs::read_to_string(&file), "configuration file did not exist");
+ let contents = t!(fs::read_to_string(&file), "`include` config not found");
match toml::from_str(&contents) {
Ok(table) => table,
Err(err) => {
@@ -642,6 +647,7 @@ impl Config {
| Subcommand::Clippy { .. }
| Subcommand::Fix { .. }
| Subcommand::Run { .. }
+ | Subcommand::Setup { .. }
| Subcommand::Format { .. } => flags.stage.unwrap_or(0),
};
@@ -666,6 +672,7 @@ impl Config {
| Subcommand::Clippy { .. }
| Subcommand::Fix { .. }
| Subcommand::Run { .. }
+ | Subcommand::Setup { .. }
| Subcommand::Format { .. } => {}
}
}
diff --git a/src/bootstrap/dist.rs b/src/bootstrap/dist.rs
index c119ae38fc391..f1202c82ba690 100644
--- a/src/bootstrap/dist.rs
+++ b/src/bootstrap/dist.rs
@@ -1033,7 +1033,7 @@ impl Step for Src {
copy_src_dirs(
builder,
&builder.src,
- &["library"],
+ &["library", "src/llvm-project/libunwind"],
&[
// not needed and contains symlinks which rustup currently
// chokes on when unpacking.
diff --git a/src/bootstrap/flags.rs b/src/bootstrap/flags.rs
index 842c84a3e5cd6..a12fc50afad58 100644
--- a/src/bootstrap/flags.rs
+++ b/src/bootstrap/flags.rs
@@ -7,6 +7,7 @@ use std::env;
use std::path::PathBuf;
use std::process;
+use build_helper::t;
use getopts::Options;
use crate::builder::Builder;
@@ -19,6 +20,7 @@ pub struct Flags {
pub on_fail: Option,
pub stage: Option,
pub keep_stage: Vec,
+ pub keep_stage_std: Vec,
pub host: Option>,
pub target: Option>,
@@ -88,6 +90,9 @@ pub enum Subcommand {
Run {
paths: Vec,
},
+ Setup {
+ path: String,
+ },
}
impl Default for Subcommand {
@@ -144,6 +149,13 @@ To learn more about a subcommand, run `./x.py -h`",
(pass multiple times to keep e.g., both stages 0 and 1)",
"N",
);
+ opts.optmulti(
+ "",
+ "keep-stage-std",
+ "stage(s) of the standard library to keep without recompiling \
+ (pass multiple times to keep e.g., both stages 0 and 1)",
+ "N",
+ );
opts.optopt("", "src", "path to the root of the rust checkout", "DIR");
let j_msg = format!(
"number of jobs to run in parallel; \
@@ -191,6 +203,7 @@ To learn more about a subcommand, run `./x.py -h`",
|| (s == "install")
|| (s == "run")
|| (s == "r")
+ || (s == "setup")
});
let subcommand = match subcommand {
Some(s) => s,
@@ -445,10 +458,21 @@ Arguments:
At least a tool needs to be called.",
);
}
+ "setup" => {
+ subcommand_help.push_str(
+ "\n
+Arguments:
+ This subcommand accepts a 'profile' to use for builds. For example:
+
+ ./x.py setup library
+
+ The profile is optional and you will be prompted interactively if it is not given.",
+ );
+ }
_ => {}
};
// Get any optional paths which occur after the subcommand
- let paths = matches.free[1..].iter().map(|p| p.into()).collect::>();
+ let mut paths = matches.free[1..].iter().map(|p| p.into()).collect::>();
let cfg_file = env::var_os("BOOTSTRAP_CONFIG").map(PathBuf::from);
let verbose = matches.opt_present("verbose");
@@ -500,6 +524,20 @@ Arguments:
}
Subcommand::Run { paths }
}
+ "setup" => {
+ let path = if paths.len() > 1 {
+ println!("\nat most one profile can be passed to setup\n");
+ usage(1, &opts, verbose, &subcommand_help)
+ } else if let Some(path) = paths.pop() {
+ t!(path.into_os_string().into_string().map_err(|path| format!(
+ "{} is not a valid UTF8 string",
+ path.to_string_lossy()
+ )))
+ } else {
+ t!(crate::setup::interactive_path())
+ };
+ Subcommand::Setup { path }
+ }
_ => {
usage(1, &opts, verbose, &subcommand_help);
}
@@ -510,7 +548,9 @@ Arguments:
println!("--stage not supported for x.py check, always treated as stage 0");
process::exit(1);
}
- if matches.opt_str("keep-stage").is_some() {
+ if matches.opt_str("keep-stage").is_some()
+ || matches.opt_str("keep-stage-std").is_some()
+ {
println!("--keep-stage not supported for x.py check, only one stage available");
process::exit(1);
}
@@ -528,6 +568,11 @@ Arguments:
.into_iter()
.map(|j| j.parse().expect("`keep-stage` should be a number"))
.collect(),
+ keep_stage_std: matches
+ .opt_strs("keep-stage-std")
+ .into_iter()
+ .map(|j| j.parse().expect("`keep-stage-std` should be a number"))
+ .collect(),
host: if matches.opt_present("host") {
Some(
split(&matches.opt_strs("host"))
diff --git a/src/bootstrap/lib.rs b/src/bootstrap/lib.rs
index 3f7aeae0ed495..4cc72f5f39c97 100644
--- a/src/bootstrap/lib.rs
+++ b/src/bootstrap/lib.rs
@@ -141,6 +141,7 @@ mod metadata;
mod native;
mod run;
mod sanity;
+mod setup;
mod test;
mod tool;
mod toolstate;
@@ -165,7 +166,7 @@ mod job {
use crate::cache::{Interned, INTERNER};
pub use crate::config::Config;
-use crate::flags::Subcommand;
+pub use crate::flags::Subcommand;
const LLVM_TOOLS: &[&str] = &[
"llvm-nm", // used to inspect binaries; it shows symbol names, their sizes and visibility
@@ -470,6 +471,10 @@ impl Build {
return clean::clean(self, all);
}
+ if let Subcommand::Setup { path: include_name } = &self.config.cmd {
+ return setup::setup(&self.config.src, include_name);
+ }
+
{
let builder = builder::Builder::new(&self);
if let Some(path) = builder.paths.get(0) {
diff --git a/src/bootstrap/run.rs b/src/bootstrap/run.rs
index 900534714277c..ba593cadbad81 100644
--- a/src/bootstrap/run.rs
+++ b/src/bootstrap/run.rs
@@ -10,7 +10,7 @@ impl Step for ExpandYamlAnchors {
/// Runs the `expand-yaml_anchors` tool.
///
- /// This tool in `src/tools` read the CI configuration files written in YAML and expands the
+ /// This tool in `src/tools` reads the CI configuration files written in YAML and expands the
/// anchors in them, since GitHub Actions doesn't support them.
fn run(self, builder: &Builder<'_>) {
builder.info("Expanding YAML anchors in the GitHub Actions configuration");
diff --git a/src/bootstrap/setup.rs b/src/bootstrap/setup.rs
new file mode 100644
index 0000000000000..9d3a889aa008e
--- /dev/null
+++ b/src/bootstrap/setup.rs
@@ -0,0 +1,88 @@
+use crate::t;
+use std::path::{Path, PathBuf};
+use std::{
+ env, fs,
+ io::{self, Write},
+};
+
+pub fn setup(src_path: &Path, include_name: &str) {
+ let cfg_file = env::var_os("BOOTSTRAP_CONFIG").map(PathBuf::from);
+
+ if cfg_file.as_ref().map_or(false, |f| f.exists()) {
+ let file = cfg_file.unwrap();
+ println!(
+ "error: you asked `x.py` to setup a new config file, but one already exists at `{}`",
+ file.display()
+ );
+ println!(
+ "help: try adding `profile = \"{}\"` at the top of {}",
+ include_name,
+ file.display()
+ );
+ println!(
+ "note: this will use the configuration in {}/src/bootstrap/defaults/config.toml.{}",
+ src_path.display(),
+ include_name
+ );
+ std::process::exit(1);
+ }
+
+ let path = cfg_file.unwrap_or_else(|| src_path.join("config.toml"));
+ let settings = format!(
+ "# Includes one of the default files in src/bootstrap/defaults\n\
+ profile = \"{}\"\n",
+ include_name
+ );
+ t!(fs::write(path, settings));
+
+ let include_path =
+ format!("{}/src/bootstrap/defaults/config.toml.{}", src_path.display(), include_name);
+ println!("`x.py` will now use the configuration at {}", include_path);
+
+ let suggestions = match include_name {
+ "codegen" | "compiler" => &["check", "build", "test"][..],
+ "library" => &["check", "build", "test library/std", "doc"],
+ "user" => &["dist", "build"],
+ _ => return,
+ };
+
+ println!("To get started, try one of the following commands:");
+ for cmd in suggestions {
+ println!("- `x.py {}`", cmd);
+ }
+
+ if include_name != "user" {
+ println!(
+ "For more suggestions, see https://rustc-dev-guide.rust-lang.org/building/suggested.html"
+ );
+ }
+}
+
+// Used to get the path for `Subcommand::Setup`
+pub fn interactive_path() -> io::Result {
+ let mut input = String::new();
+ println!(
+ "Welcome to the Rust project! What do you want to do with x.py?
+a) Contribute to the standard library
+b) Contribute to the compiler
+c) Contribute to the compiler, and also modify LLVM or codegen
+d) Install Rust from source"
+ );
+ let template = loop {
+ print!("Please choose one (a/b/c/d): ");
+ io::stdout().flush()?;
+ io::stdin().read_line(&mut input)?;
+ break match input.trim().to_lowercase().as_str() {
+ "a" | "lib" | "library" => "library",
+ "b" | "compiler" => "compiler",
+ "c" | "llvm" => "llvm",
+ "d" | "user" | "maintainer" => "maintainer",
+ _ => {
+ println!("error: unrecognized option '{}'", input.trim());
+ println!("note: press Ctrl+C to exit");
+ continue;
+ }
+ };
+ };
+ Ok(template.to_owned())
+}
diff --git a/src/librustdoc/passes/collect_intra_doc_links.rs b/src/librustdoc/passes/collect_intra_doc_links.rs
index 93016c401def1..5d74a3da9a205 100644
--- a/src/librustdoc/passes/collect_intra_doc_links.rs
+++ b/src/librustdoc/passes/collect_intra_doc_links.rs
@@ -57,45 +57,16 @@ enum ResolutionFailure<'a> {
/// This resolved, but with the wrong namespace.
/// `Namespace` is the expected namespace (as opposed to the actual).
WrongNamespace(Res, Namespace),
- /// This has a partial resolution, but is not in the TypeNS and so cannot
- /// have associated items or fields.
- CannotHaveAssociatedItems(Res, Namespace),
- /// `name` is the base name of the path (not necessarily the whole link)
- NotInScope { module_id: DefId, name: Cow<'a, str> },
- /// this is a primitive type without an impls (no associated methods)
- /// when will this actually happen?
- /// the `Res` is the primitive it resolved to
- NoPrimitiveImpl(Res, String),
- /// `[u8::not_found]`
- /// the `Res` is the primitive it resolved to
- NoPrimitiveAssocItem { res: Res, prim_name: &'a str, assoc_item: Symbol },
- /// `[S::not_found]`
- /// the `String` is the associated item that wasn't found
- NoAssocItem(Res, Symbol),
+ /// The link failed to resolve. `resolution_failure` should look to see if there's
+ /// a more helpful error that can be given.
+ NotResolved { module_id: DefId, partial_res: Option, unresolved: Cow<'a, str> },
/// should not ever happen
NoParentItem,
- /// this could be an enum variant, but the last path fragment wasn't resolved.
- /// the `String` is the variant that didn't exist
- NotAVariant(Res, Symbol),
/// used to communicate that this should be ignored, but shouldn't be reported to the user
Dummy,
}
impl ResolutionFailure<'a> {
- // A partial or full resolution
- fn res(&self) -> Option {
- use ResolutionFailure::*;
- match self {
- NoPrimitiveAssocItem { res, .. }
- | NoAssocItem(res, _)
- | NoPrimitiveImpl(res, _)
- | NotAVariant(res, _)
- | WrongNamespace(res, _)
- | CannotHaveAssociatedItems(res, _) => Some(*res),
- NotInScope { .. } | NoParentItem | Dummy => None,
- }
- }
-
// This resolved fully (not just partially) but is erroneous for some other reason
fn full_res(&self) -> Option {
match self {
@@ -130,22 +101,25 @@ impl<'a, 'tcx> LinkCollector<'a, 'tcx> {
path_str: &'path str,
current_item: &Option,
module_id: DefId,
- extra_fragment: &Option,
) -> Result<(Res, Option), ErrorKind<'path>> {
let cx = self.cx;
+ let no_res = || ResolutionFailure::NotResolved {
+ module_id,
+ partial_res: None,
+ unresolved: path_str.into(),
+ };
debug!("looking for enum variant {}", path_str);
let mut split = path_str.rsplitn(3, "::");
- let variant_field_name = split
+ let (variant_field_str, variant_field_name) = split
.next()
- .map(|f| Symbol::intern(f))
+ .map(|f| (f, Symbol::intern(f)))
.expect("fold_item should ensure link is non-empty");
- let variant_name =
+ let (variant_str, variant_name) =
// we're not sure this is a variant at all, so use the full string
- split.next().map(|f| Symbol::intern(f)).ok_or_else(|| ResolutionFailure::NotInScope {
- module_id,
- name: path_str.into(),
- })?;
+ // If there's no second component, the link looks like `[path]`.
+ // So there's no partial res and we should say the whole link failed to resolve.
+ split.next().map(|f| (f, Symbol::intern(f))).ok_or_else(no_res)?;
let path = split
.next()
.map(|f| {
@@ -156,10 +130,9 @@ impl<'a, 'tcx> LinkCollector<'a, 'tcx> {
}
f.to_owned()
})
- .ok_or_else(|| ResolutionFailure::NotInScope {
- module_id,
- name: variant_name.to_string().into(),
- })?;
+ // If there's no third component, we saw `[a::b]` before and it failed to resolve.
+ // So there's no partial res.
+ .ok_or_else(no_res)?;
let ty_res = cx
.enter_resolver(|resolver| {
resolver.resolve_str_path_error(DUMMY_SP, &path, TypeNS, module_id)
@@ -167,7 +140,7 @@ impl<'a, 'tcx> LinkCollector<'a, 'tcx> {
.map(|(_, res)| res)
.unwrap_or(Res::Err);
if let Res::Err = ty_res {
- return Err(ResolutionFailure::NotInScope { module_id, name: path.into() }.into());
+ return Err(no_res().into());
}
let ty_res = ty_res.map_id(|_| panic!("unexpected node_id"));
match ty_res {
@@ -190,38 +163,27 @@ impl<'a, 'tcx> LinkCollector<'a, 'tcx> {
ty_res,
Some(format!(
"variant.{}.field.{}",
- variant_name, variant_field_name
+ variant_str, variant_field_name
)),
))
} else {
- Err(ResolutionFailure::NotAVariant(ty_res, variant_field_name).into())
+ Err(ResolutionFailure::NotResolved {
+ module_id,
+ partial_res: Some(Res::Def(DefKind::Enum, def.did)),
+ unresolved: variant_field_str.into(),
+ }
+ .into())
}
}
_ => unreachable!(),
}
}
- // `variant_field` looks at 3 different path segments in a row.
- // But `NoAssocItem` assumes there are only 2. Check to see if there's
- // an intermediate segment that resolves.
- _ => {
- let intermediate_path = format!("{}::{}", path, variant_name);
- // NOTE: we have to be careful here, because we're already in `resolve`.
- // We know this doesn't recurse forever because we use a shorter path each time.
- // NOTE: this uses `TypeNS` because nothing else has a valid path segment after
- let kind = if let Some(intermediate) = self.check_full_res(
- TypeNS,
- &intermediate_path,
- module_id,
- current_item,
- extra_fragment,
- ) {
- ResolutionFailure::NoAssocItem(intermediate, variant_field_name)
- } else {
- // Even with the shorter path, it didn't resolve, so say that.
- ResolutionFailure::NoAssocItem(ty_res, variant_name)
- };
- Err(kind.into())
+ _ => Err(ResolutionFailure::NotResolved {
+ module_id,
+ partial_res: Some(ty_res),
+ unresolved: variant_str.into(),
}
+ .into()),
}
}
@@ -242,11 +204,11 @@ impl<'a, 'tcx> LinkCollector<'a, 'tcx> {
false,
) {
if let SyntaxExtensionKind::LegacyBang { .. } = ext.kind {
- return Some(Ok(res.map_id(|_| panic!("unexpected id"))));
+ return Ok(res.map_id(|_| panic!("unexpected id")));
}
}
if let Some(res) = resolver.all_macros().get(&Symbol::intern(path_str)) {
- return Some(Ok(res.map_id(|_| panic!("unexpected id"))));
+ return Ok(res.map_id(|_| panic!("unexpected id")));
}
debug!("resolving {} as a macro in the module {:?}", path_str, module_id);
if let Ok((_, res)) =
@@ -255,28 +217,14 @@ impl<'a, 'tcx> LinkCollector<'a, 'tcx> {
// don't resolve builtins like `#[derive]`
if let Res::Def(..) = res {
let res = res.map_id(|_| panic!("unexpected node_id"));
- return Some(Ok(res));
- }
- }
- None
- })
- // This weird control flow is so we don't borrow the resolver more than once at a time
- .unwrap_or_else(|| {
- let mut split = path_str.rsplitn(2, "::");
- if let Some((parent, base)) = split.next().and_then(|x| Some((split.next()?, x))) {
- if let Some(res) = self.check_full_res(TypeNS, parent, module_id, &None, &None) {
- return Err(if matches!(res, Res::PrimTy(_)) {
- ResolutionFailure::NoPrimitiveAssocItem {
- res,
- prim_name: parent,
- assoc_item: Symbol::intern(base),
- }
- } else {
- ResolutionFailure::NoAssocItem(res, Symbol::intern(base))
- });
+ return Ok(res);
}
}
- Err(ResolutionFailure::NotInScope { module_id, name: path_str.into() })
+ Err(ResolutionFailure::NotResolved {
+ module_id,
+ partial_res: None,
+ unresolved: path_str.into(),
+ })
})
}
@@ -312,13 +260,13 @@ impl<'a, 'tcx> LinkCollector<'a, 'tcx> {
return handle_variant(cx, res, extra_fragment);
}
// Not a trait item; just return what we found.
- Res::PrimTy(..) => {
+ Res::PrimTy(ty) => {
if extra_fragment.is_some() {
return Err(ErrorKind::AnchorFailure(
AnchorFailure::RustdocAnchorConflict(res),
));
}
- return Ok((res, Some(path_str.to_owned())));
+ return Ok((res, Some(ty.name_str().to_owned())));
}
Res::Def(DefKind::Mod, _) => {
return Ok((res, extra_fragment.clone()));
@@ -331,6 +279,7 @@ impl<'a, 'tcx> LinkCollector<'a, 'tcx> {
if value != (ns == ValueNS) {
return Err(ResolutionFailure::WrongNamespace(res, ns).into());
}
+ // FIXME: why is this necessary?
} else if let Some((path, prim)) = is_primitive(path_str, ns) {
if extra_fragment.is_some() {
return Err(ErrorKind::AnchorFailure(AnchorFailure::RustdocAnchorConflict(prim)));
@@ -341,7 +290,7 @@ impl<'a, 'tcx> LinkCollector<'a, 'tcx> {
// Try looking for methods and associated items.
let mut split = path_str.rsplitn(2, "::");
// this can be an `unwrap()` because we ensure the link is never empty
- let item_name = Symbol::intern(split.next().unwrap());
+ let (item_str, item_name) = split.next().map(|i| (i, Symbol::intern(i))).unwrap();
let path_root = split
.next()
.map(|f| {
@@ -356,12 +305,20 @@ impl<'a, 'tcx> LinkCollector<'a, 'tcx> {
// So we can be sure that `rustc_resolve` was accurate when it said it wasn't resolved.
.ok_or_else(|| {
debug!("found no `::`, assumming {} was correctly not in scope", item_name);
- ResolutionFailure::NotInScope { module_id, name: item_name.to_string().into() }
+ ResolutionFailure::NotResolved {
+ module_id,
+ partial_res: None,
+ unresolved: item_str.into(),
+ }
})?;
if let Some((path, prim)) = is_primitive(&path_root, TypeNS) {
- let impls = primitive_impl(cx, &path)
- .ok_or_else(|| ResolutionFailure::NoPrimitiveImpl(prim, path_root.into()))?;
+ let impls =
+ primitive_impl(cx, &path).ok_or_else(|| ResolutionFailure::NotResolved {
+ module_id,
+ partial_res: Some(prim),
+ unresolved: item_str.into(),
+ })?;
for &impl_ in impls {
let link = cx
.tcx
@@ -377,7 +334,7 @@ impl<'a, 'tcx> LinkCollector<'a, 'tcx> {
ty::AssocKind::Const => "associatedconstant",
ty::AssocKind::Type => "associatedtype",
})
- .map(|out| (prim, Some(format!("{}#{}.{}", path, out, item_name))));
+ .map(|out| (prim, Some(format!("{}#{}.{}", path, out, item_str))));
if let Some(link) = link {
return Ok(link);
}
@@ -388,10 +345,10 @@ impl<'a, 'tcx> LinkCollector<'a, 'tcx> {
item_name,
ns.descr()
);
- return Err(ResolutionFailure::NoPrimitiveAssocItem {
- res: prim,
- prim_name: path,
- assoc_item: item_name,
+ return Err(ResolutionFailure::NotResolved {
+ module_id,
+ partial_res: Some(prim),
+ unresolved: item_str.into(),
}
.into());
}
@@ -405,25 +362,14 @@ impl<'a, 'tcx> LinkCollector<'a, 'tcx> {
let ty_res = match ty_res {
Err(()) | Ok(Res::Err) => {
return if ns == Namespace::ValueNS {
- self.variant_field(path_str, current_item, module_id, extra_fragment)
+ self.variant_field(path_str, current_item, module_id)
} else {
- // See if it only broke because of the namespace.
- let kind = cx.enter_resolver(|resolver| {
- // NOTE: this doesn't use `check_full_res` because we explicitly want to ignore `TypeNS` (we already checked it)
- for &ns in &[MacroNS, ValueNS] {
- match resolver
- .resolve_str_path_error(DUMMY_SP, &path_root, ns, module_id)
- {
- Ok((_, Res::Err)) | Err(()) => {}
- Ok((_, res)) => {
- let res = res.map_id(|_| panic!("unexpected node_id"));
- return ResolutionFailure::CannotHaveAssociatedItems(res, ns);
- }
- }
- }
- ResolutionFailure::NotInScope { module_id, name: path_root.into() }
- });
- Err(kind.into())
+ Err(ResolutionFailure::NotResolved {
+ module_id,
+ partial_res: None,
+ unresolved: path_root.into(),
+ }
+ .into())
};
}
Ok(res) => res,
@@ -473,7 +419,7 @@ impl<'a, 'tcx> LinkCollector<'a, 'tcx> {
// but the disambiguator logic expects the associated item.
// Store the kind in a side channel so that only the disambiguator logic looks at it.
self.kind_side_channel.set(Some((kind.as_def_kind(), id)));
- Ok((ty_res, Some(format!("{}.{}", out, item_name))))
+ Ok((ty_res, Some(format!("{}.{}", out, item_str))))
})
} else if ns == Namespace::ValueNS {
debug!("looking for variants or fields named {} for {:?}", item_name, did);
@@ -516,7 +462,12 @@ impl<'a, 'tcx> LinkCollector<'a, 'tcx> {
}
} else {
// We already know this isn't in ValueNS, so no need to check variant_field
- return Err(ResolutionFailure::NoAssocItem(ty_res, item_name).into());
+ return Err(ResolutionFailure::NotResolved {
+ module_id,
+ partial_res: Some(ty_res),
+ unresolved: item_str.into(),
+ }
+ .into());
}
}
Res::Def(DefKind::Trait, did) => cx
@@ -540,16 +491,21 @@ impl<'a, 'tcx> LinkCollector<'a, 'tcx> {
Err(ErrorKind::AnchorFailure(AnchorFailure::RustdocAnchorConflict(ty_res)))
} else {
let res = Res::Def(item.kind.as_def_kind(), item.def_id);
- Ok((res, Some(format!("{}.{}", kind, item_name))))
+ Ok((res, Some(format!("{}.{}", kind, item_str))))
}
}),
_ => None,
};
res.unwrap_or_else(|| {
if ns == Namespace::ValueNS {
- self.variant_field(path_str, current_item, module_id, extra_fragment)
+ self.variant_field(path_str, current_item, module_id)
} else {
- Err(ResolutionFailure::NoAssocItem(ty_res, item_name).into())
+ Err(ResolutionFailure::NotResolved {
+ module_id,
+ partial_res: Some(ty_res),
+ unresolved: item_str.into(),
+ }
+ .into())
}
})
}
@@ -1044,12 +1000,12 @@ impl LinkCollector<'_, '_> {
suggest_disambiguator(resolved, diag, path_str, dox, sp, &link_range);
});
};
- if let Res::PrimTy(_) = res {
+ if let Res::PrimTy(..) = res {
match disambiguator {
Some(Disambiguator::Primitive | Disambiguator::Namespace(_)) | None => {
item.attrs.links.push(ItemLink {
link: ori_link,
- link_text: path_str.to_owned(),
+ link_text,
did: None,
fragment,
});
@@ -1127,6 +1083,8 @@ impl LinkCollector<'_, '_> {
// We only looked in one namespace. Try to give a better error if possible.
if kind.full_res().is_none() {
let other_ns = if ns == ValueNS { TypeNS } else { ValueNS };
+ // FIXME: really it should be `resolution_failure` that does this, not `resolve_with_disambiguator`
+ // See https://github.com/rust-lang/rust/pull/76955#discussion_r493953382 for a good approach
for &new_ns in &[other_ns, MacroNS] {
if let Some(res) = self.check_full_res(
new_ns,
@@ -1529,7 +1487,6 @@ fn resolution_failure(
dox,
&link_range,
|diag, sp| {
- let in_scope = kinds.iter().any(|kind| kind.res().is_some());
let item = |res: Res| {
format!(
"the {} `{}`",
@@ -1550,53 +1507,142 @@ fn resolution_failure(
// ignore duplicates
let mut variants_seen = SmallVec::<[_; 3]>::new();
for mut failure in kinds {
- // Check if _any_ parent of the path gets resolved.
- // If so, report it and say the first which failed; if not, say the first path segment didn't resolve.
- if let ResolutionFailure::NotInScope { module_id, name } = &mut failure {
- let mut current = name.as_ref();
- loop {
- current = match current.rsplitn(2, "::").nth(1) {
- Some(p) => p,
- None => {
- *name = current.to_owned().into();
- break;
- }
- };
- if let Some(res) =
- collector.check_full_res(TypeNS, ¤t, *module_id, &None, &None)
- {
- failure = ResolutionFailure::NoAssocItem(res, Symbol::intern(current));
- break;
- }
- }
- }
let variant = std::mem::discriminant(&failure);
if variants_seen.contains(&variant) {
continue;
}
variants_seen.push(variant);
- let note = match failure {
- ResolutionFailure::NotInScope { module_id, name, .. } => {
- if in_scope {
- continue;
+
+ if let ResolutionFailure::NotResolved { module_id, partial_res, unresolved } =
+ &mut failure
+ {
+ use DefKind::*;
+
+ let module_id = *module_id;
+ // FIXME(jynelson): this might conflict with my `Self` fix in #76467
+ // FIXME: maybe use itertools `collect_tuple` instead?
+ fn split(path: &str) -> Option<(&str, &str)> {
+ let mut splitter = path.rsplitn(2, "::");
+ splitter.next().and_then(|right| splitter.next().map(|left| (left, right)))
+ }
+
+ // Check if _any_ parent of the path gets resolved.
+ // If so, report it and say the first which failed; if not, say the first path segment didn't resolve.
+ let mut name = path_str;
+ 'outer: loop {
+ let (start, end) = if let Some(x) = split(name) {
+ x
+ } else {
+ // avoid bug that marked [Quux::Z] as missing Z, not Quux
+ if partial_res.is_none() {
+ *unresolved = name.into();
+ }
+ break;
+ };
+ name = start;
+ for &ns in &[TypeNS, ValueNS, MacroNS] {
+ if let Some(res) =
+ collector.check_full_res(ns, &start, module_id, &None, &None)
+ {
+ debug!("found partial_res={:?}", res);
+ *partial_res = Some(res);
+ *unresolved = end.into();
+ break 'outer;
+ }
}
- // NOTE: uses an explicit `continue` so the `note:` will come before the `help:`
- let module_name = collector.cx.tcx.item_name(module_id);
- let note = format!("no item named `{}` in `{}`", name, module_name);
+ *unresolved = end.into();
+ }
+
+ let last_found_module = match *partial_res {
+ Some(Res::Def(DefKind::Mod, id)) => Some(id),
+ None => Some(module_id),
+ _ => None,
+ };
+ // See if this was a module: `[path]` or `[std::io::nope]`
+ if let Some(module) = last_found_module {
+ let module_name = collector.cx.tcx.item_name(module);
+ let note = format!(
+ "the module `{}` contains no item named `{}`",
+ module_name, unresolved
+ );
if let Some(span) = sp {
diag.span_label(span, ¬e);
} else {
diag.note(¬e);
}
- // If the link has `::` in the path, assume it's meant to be an intra-doc link
+ // If the link has `::` in it, assume it was meant to be an intra-doc link.
+ // Otherwise, the `[]` might be unrelated.
+ // FIXME: don't show this for autolinks (`<>`), `()` style links, or reference links
if !path_str.contains("::") {
- // Otherwise, the `[]` might be unrelated.
- // FIXME(https://github.com/raphlinus/pulldown-cmark/issues/373):
- // don't show this for autolinks (`<>`), `()` style links, or reference links
diag.help(r#"to escape `[` and `]` characters, add '\' before them like `\[` or `\]`"#);
}
continue;
}
+
+ // Otherwise, it must be an associated item or variant
+ let res = partial_res.expect("None case was handled by `last_found_module`");
+ let diagnostic_name;
+ let (kind, name) = match res {
+ Res::Def(kind, def_id) => {
+ diagnostic_name = collector.cx.tcx.item_name(def_id).as_str();
+ (Some(kind), &*diagnostic_name)
+ }
+ Res::PrimTy(ty) => (None, ty.name_str()),
+ _ => unreachable!("only ADTs and primitives are in scope at module level"),
+ };
+ let path_description = if let Some(kind) = kind {
+ match kind {
+ Mod | ForeignMod => "inner item",
+ Struct => "field or associated item",
+ Enum | Union => "variant or associated item",
+ Variant
+ | Field
+ | Closure
+ | Generator
+ | AssocTy
+ | AssocConst
+ | AssocFn
+ | Fn
+ | Macro(_)
+ | Const
+ | ConstParam
+ | ExternCrate
+ | Use
+ | LifetimeParam
+ | Ctor(_, _)
+ | AnonConst => {
+ let note = assoc_item_not_allowed(res);
+ if let Some(span) = sp {
+ diag.span_label(span, ¬e);
+ } else {
+ diag.note(¬e);
+ }
+ return;
+ }
+ Trait | TyAlias | ForeignTy | OpaqueTy | TraitAlias | TyParam
+ | Static => "associated item",
+ Impl | GlobalAsm => unreachable!("not a path"),
+ }
+ } else {
+ "associated item"
+ };
+ let note = format!(
+ "the {} `{}` has no {} named `{}`",
+ res.descr(),
+ name,
+ disambiguator.map_or(path_description, |d| d.descr()),
+ unresolved,
+ );
+ if let Some(span) = sp {
+ diag.span_label(span, ¬e);
+ } else {
+ diag.note(¬e);
+ }
+
+ continue;
+ }
+ let note = match failure {
+ ResolutionFailure::NotResolved { .. } => unreachable!("handled above"),
ResolutionFailure::Dummy => continue,
ResolutionFailure::WrongNamespace(res, expected_ns) => {
if let Res::Def(kind, _) = res {
@@ -1621,79 +1667,6 @@ fn resolution_failure(
diag.level = rustc_errors::Level::Bug;
"all intra doc links should have a parent item".to_owned()
}
- ResolutionFailure::NoPrimitiveImpl(res, _) => format!(
- "this link partially resolves to {}, which does not have any associated items",
- item(res),
- ),
- ResolutionFailure::NoPrimitiveAssocItem { prim_name, assoc_item, .. } => {
- format!(
- "the builtin type `{}` does not have an associated item named `{}`",
- prim_name, assoc_item
- )
- }
- ResolutionFailure::NoAssocItem(res, assoc_item) => {
- use DefKind::*;
-
- let (kind, def_id) = match res {
- Res::Def(kind, def_id) => (kind, def_id),
- x => unreachable!(
- "primitives are covered above and other `Res` variants aren't possible at module scope: {:?}",
- x,
- ),
- };
- let name = collector.cx.tcx.item_name(def_id);
- let path_description = if let Some(disambiguator) = disambiguator {
- disambiguator.descr()
- } else {
- match kind {
- Mod | ForeignMod => "inner item",
- Struct => "field or associated item",
- Enum | Union => "variant or associated item",
- Variant
- | Field
- | Closure
- | Generator
- | AssocTy
- | AssocConst
- | AssocFn
- | Fn
- | Macro(_)
- | Const
- | ConstParam
- | ExternCrate
- | Use
- | LifetimeParam
- | Ctor(_, _)
- | AnonConst => {
- let note = assoc_item_not_allowed(res);
- if let Some(span) = sp {
- diag.span_label(span, ¬e);
- } else {
- diag.note(¬e);
- }
- return;
- }
- Trait | TyAlias | ForeignTy | OpaqueTy | TraitAlias | TyParam
- | Static => "associated item",
- Impl | GlobalAsm => unreachable!("not a path"),
- }
- };
- format!(
- "the {} `{}` has no {} named `{}`",
- res.descr(),
- name,
- path_description,
- assoc_item
- )
- }
- ResolutionFailure::CannotHaveAssociatedItems(res, _) => {
- assoc_item_not_allowed(res)
- }
- ResolutionFailure::NotAVariant(res, variant) => format!(
- "this link partially resolves to {}, but there is no variant named {}",
- item(res),
- variant
- ),
};
if let Some(span) = sp {
diag.span_label(span, ¬e);
diff --git a/src/test/rustdoc-ui/deny-intra-link-resolution-failure.stderr b/src/test/rustdoc-ui/deny-intra-link-resolution-failure.stderr
index 5020b97b2f201..33260fa0e1e66 100644
--- a/src/test/rustdoc-ui/deny-intra-link-resolution-failure.stderr
+++ b/src/test/rustdoc-ui/deny-intra-link-resolution-failure.stderr
@@ -2,7 +2,7 @@ error: unresolved link to `v2`
--> $DIR/deny-intra-link-resolution-failure.rs:3:6
|
LL | /// [v2]
- | ^^ no item named `v2` in `deny_intra_link_resolution_failure`
+ | ^^ the module `deny_intra_link_resolution_failure` contains no item named `v2`
|
note: the lint level is defined here
--> $DIR/deny-intra-link-resolution-failure.rs:1:9
diff --git a/src/test/rustdoc-ui/intra-link-errors.rs b/src/test/rustdoc-ui/intra-link-errors.rs
index 26b629b1313da..0278caf308776 100644
--- a/src/test/rustdoc-ui/intra-link-errors.rs
+++ b/src/test/rustdoc-ui/intra-link-errors.rs
@@ -6,19 +6,23 @@
/// [path::to::nonexistent::module]
//~^ ERROR unresolved link
-//~| NOTE no item named `path` in `intra_link_errors`
+//~| NOTE `intra_link_errors` contains no item named `path`
/// [path::to::nonexistent::macro!]
//~^ ERROR unresolved link
-//~| NOTE no item named `path` in `intra_link_errors`
+//~| NOTE `intra_link_errors` contains no item named `path`
/// [type@path::to::nonexistent::type]
//~^ ERROR unresolved link
-//~| NOTE no item named `path` in `intra_link_errors`
+//~| NOTE `intra_link_errors` contains no item named `path`
/// [std::io::not::here]
//~^ ERROR unresolved link
-//~| NOTE the module `io` has no inner item
+//~| NOTE `io` contains no item named `not`
+
+/// [type@std::io::not::here]
+//~^ ERROR unresolved link
+//~| NOTE `io` contains no item named `not`
/// [std::io::Error::x]
//~^ ERROR unresolved link
@@ -32,6 +36,10 @@
//~^ ERROR unresolved link
//~| NOTE `f` is a function, not a module
+/// [f::A!]
+//~^ ERROR unresolved link
+//~| NOTE `f` is a function, not a module
+
/// [S::A]
//~^ ERROR unresolved link
//~| NOTE struct `S` has no field or associated item
@@ -46,7 +54,16 @@
/// [u8::not_found]
//~^ ERROR unresolved link
-//~| NOTE the builtin type `u8` does not have an associated item named `not_found`
+//~| NOTE the builtin type `u8` has no associated item named `not_found`
+
+/// [std::primitive::u8::not_found]
+//~^ ERROR unresolved link
+//~| NOTE the builtin type `u8` has no associated item named `not_found`
+
+/// [type@Vec::into_iter]
+//~^ ERROR unresolved link
+//~| HELP to link to the associated function, add parentheses
+//~| NOTE this link resolves to the associated function `into_iter`
/// [S!]
//~^ ERROR unresolved link
diff --git a/src/test/rustdoc-ui/intra-link-errors.stderr b/src/test/rustdoc-ui/intra-link-errors.stderr
index fbf3dcbbec29a..b63f799535a1f 100644
--- a/src/test/rustdoc-ui/intra-link-errors.stderr
+++ b/src/test/rustdoc-ui/intra-link-errors.stderr
@@ -2,7 +2,7 @@ error: unresolved link to `path::to::nonexistent::module`
--> $DIR/intra-link-errors.rs:7:6
|
LL | /// [path::to::nonexistent::module]
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ no item named `path` in `intra_link_errors`
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the module `intra_link_errors` contains no item named `path`
|
note: the lint level is defined here
--> $DIR/intra-link-errors.rs:1:9
@@ -14,64 +14,91 @@ error: unresolved link to `path::to::nonexistent::macro`
--> $DIR/intra-link-errors.rs:11:6
|
LL | /// [path::to::nonexistent::macro!]
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ no item named `path` in `intra_link_errors`
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the module `intra_link_errors` contains no item named `path`
error: unresolved link to `path::to::nonexistent::type`
--> $DIR/intra-link-errors.rs:15:6
|
LL | /// [type@path::to::nonexistent::type]
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ no item named `path` in `intra_link_errors`
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the module `intra_link_errors` contains no item named `path`
error: unresolved link to `std::io::not::here`
--> $DIR/intra-link-errors.rs:19:6
|
LL | /// [std::io::not::here]
- | ^^^^^^^^^^^^^^^^^^ the module `io` has no inner item named `not`
+ | ^^^^^^^^^^^^^^^^^^ the module `io` contains no item named `not`
-error: unresolved link to `std::io::Error::x`
+error: unresolved link to `std::io::not::here`
--> $DIR/intra-link-errors.rs:23:6
|
+LL | /// [type@std::io::not::here]
+ | ^^^^^^^^^^^^^^^^^^^^^^^ the module `io` contains no item named `not`
+
+error: unresolved link to `std::io::Error::x`
+ --> $DIR/intra-link-errors.rs:27:6
+ |
LL | /// [std::io::Error::x]
| ^^^^^^^^^^^^^^^^^ the struct `Error` has no field or associated item named `x`
error: unresolved link to `std::io::ErrorKind::x`
- --> $DIR/intra-link-errors.rs:27:6
+ --> $DIR/intra-link-errors.rs:31:6
|
LL | /// [std::io::ErrorKind::x]
| ^^^^^^^^^^^^^^^^^^^^^ the enum `ErrorKind` has no variant or associated item named `x`
error: unresolved link to `f::A`
- --> $DIR/intra-link-errors.rs:31:6
+ --> $DIR/intra-link-errors.rs:35:6
|
LL | /// [f::A]
| ^^^^ `f` is a function, not a module or type, and cannot have associated items
+error: unresolved link to `f::A`
+ --> $DIR/intra-link-errors.rs:39:6
+ |
+LL | /// [f::A!]
+ | ^^^^^ `f` is a function, not a module or type, and cannot have associated items
+
error: unresolved link to `S::A`
- --> $DIR/intra-link-errors.rs:35:6
+ --> $DIR/intra-link-errors.rs:43:6
|
LL | /// [S::A]
| ^^^^ the struct `S` has no field or associated item named `A`
error: unresolved link to `S::fmt`
- --> $DIR/intra-link-errors.rs:39:6
+ --> $DIR/intra-link-errors.rs:47:6
|
LL | /// [S::fmt]
| ^^^^^^ the struct `S` has no field or associated item named `fmt`
error: unresolved link to `E::D`
- --> $DIR/intra-link-errors.rs:43:6
+ --> $DIR/intra-link-errors.rs:51:6
|
LL | /// [E::D]
| ^^^^ the enum `E` has no variant or associated item named `D`
error: unresolved link to `u8::not_found`
- --> $DIR/intra-link-errors.rs:47:6
+ --> $DIR/intra-link-errors.rs:55:6
|
LL | /// [u8::not_found]
- | ^^^^^^^^^^^^^ the builtin type `u8` does not have an associated item named `not_found`
+ | ^^^^^^^^^^^^^ the builtin type `u8` has no associated item named `not_found`
+
+error: unresolved link to `std::primitive::u8::not_found`
+ --> $DIR/intra-link-errors.rs:59:6
+ |
+LL | /// [std::primitive::u8::not_found]
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the builtin type `u8` has no associated item named `not_found`
+
+error: unresolved link to `Vec::into_iter`
+ --> $DIR/intra-link-errors.rs:63:6
+ |
+LL | /// [type@Vec::into_iter]
+ | ^^^^^^^^^^^^^^^^^^^
+ | |
+ | this link resolves to the associated function `into_iter`, which is not in the type namespace
+ | help: to link to the associated function, add parentheses: `Vec::into_iter()`
error: unresolved link to `S`
- --> $DIR/intra-link-errors.rs:51:6
+ --> $DIR/intra-link-errors.rs:68:6
|
LL | /// [S!]
| ^^
@@ -80,7 +107,7 @@ LL | /// [S!]
| help: to link to the struct, prefix with `struct@`: `struct@S`
error: unresolved link to `T::g`
- --> $DIR/intra-link-errors.rs:69:6
+ --> $DIR/intra-link-errors.rs:86:6
|
LL | /// [type@T::g]
| ^^^^^^^^^
@@ -89,13 +116,13 @@ LL | /// [type@T::g]
| help: to link to the associated function, add parentheses: `T::g()`
error: unresolved link to `T::h`
- --> $DIR/intra-link-errors.rs:74:6
+ --> $DIR/intra-link-errors.rs:91:6
|
LL | /// [T::h!]
| ^^^^^ the trait `T` has no macro named `h`
error: unresolved link to `S::h`
- --> $DIR/intra-link-errors.rs:61:6
+ --> $DIR/intra-link-errors.rs:78:6
|
LL | /// [type@S::h]
| ^^^^^^^^^
@@ -104,7 +131,7 @@ LL | /// [type@S::h]
| help: to link to the associated function, add parentheses: `S::h()`
error: unresolved link to `m`
- --> $DIR/intra-link-errors.rs:81:6
+ --> $DIR/intra-link-errors.rs:98:6
|
LL | /// [m()]
| ^^^
@@ -112,5 +139,5 @@ LL | /// [m()]
| this link resolves to the macro `m`, which is not in the value namespace
| help: to link to the macro, add an exclamation mark: `m!`
-error: aborting due to 16 previous errors
+error: aborting due to 20 previous errors
diff --git a/src/test/rustdoc-ui/intra-link-span-ice-55723.stderr b/src/test/rustdoc-ui/intra-link-span-ice-55723.stderr
index 3c13df20588d8..d946aa939800c 100644
--- a/src/test/rustdoc-ui/intra-link-span-ice-55723.stderr
+++ b/src/test/rustdoc-ui/intra-link-span-ice-55723.stderr
@@ -2,7 +2,7 @@ error: unresolved link to `i`
--> $DIR/intra-link-span-ice-55723.rs:9:10
|
LL | /// (arr[i])
- | ^ no item named `i` in `intra_link_span_ice_55723`
+ | ^ the module `intra_link_span_ice_55723` contains no item named `i`
|
note: the lint level is defined here
--> $DIR/intra-link-span-ice-55723.rs:1:9
diff --git a/src/test/rustdoc-ui/intra-links-warning-crlf.stderr b/src/test/rustdoc-ui/intra-links-warning-crlf.stderr
index 351f8fafa64d8..76a2ac0c8cf02 100644
--- a/src/test/rustdoc-ui/intra-links-warning-crlf.stderr
+++ b/src/test/rustdoc-ui/intra-links-warning-crlf.stderr
@@ -2,7 +2,7 @@ warning: unresolved link to `error`
--> $DIR/intra-links-warning-crlf.rs:7:6
|
LL | /// [error]
- | ^^^^^ no item named `error` in `intra_links_warning_crlf`
+ | ^^^^^ the module `intra_links_warning_crlf` contains no item named `error`
|
= note: `#[warn(broken_intra_doc_links)]` on by default
= help: to escape `[` and `]` characters, add '\' before them like `\[` or `\]`
@@ -11,7 +11,7 @@ warning: unresolved link to `error1`
--> $DIR/intra-links-warning-crlf.rs:12:11
|
LL | /// docs [error1]
- | ^^^^^^ no item named `error1` in `intra_links_warning_crlf`
+ | ^^^^^^ the module `intra_links_warning_crlf` contains no item named `error1`
|
= help: to escape `[` and `]` characters, add '\' before them like `\[` or `\]`
@@ -19,7 +19,7 @@ warning: unresolved link to `error2`
--> $DIR/intra-links-warning-crlf.rs:15:11
|
LL | /// docs [error2]
- | ^^^^^^ no item named `error2` in `intra_links_warning_crlf`
+ | ^^^^^^ the module `intra_links_warning_crlf` contains no item named `error2`
|
= help: to escape `[` and `]` characters, add '\' before them like `\[` or `\]`
@@ -27,7 +27,7 @@ warning: unresolved link to `error`
--> $DIR/intra-links-warning-crlf.rs:23:20
|
LL | * It also has an [error].
- | ^^^^^ no item named `error` in `intra_links_warning_crlf`
+ | ^^^^^ the module `intra_links_warning_crlf` contains no item named `error`
|
= help: to escape `[` and `]` characters, add '\' before them like `\[` or `\]`
diff --git a/src/test/rustdoc-ui/intra-links-warning.stderr b/src/test/rustdoc-ui/intra-links-warning.stderr
index 0832e00d35a00..09db465df59fb 100644
--- a/src/test/rustdoc-ui/intra-links-warning.stderr
+++ b/src/test/rustdoc-ui/intra-links-warning.stderr
@@ -10,37 +10,37 @@ warning: unresolved link to `Bar::foo`
--> $DIR/intra-links-warning.rs:3:35
|
LL | //! Test with [Foo::baz], [Bar::foo], ...
- | ^^^^^^^^ no item named `Bar` in `intra_links_warning`
+ | ^^^^^^^^ the module `intra_links_warning` contains no item named `Bar`
warning: unresolved link to `Uniooon::X`
--> $DIR/intra-links-warning.rs:6:13
|
LL | //! , [Uniooon::X] and [Qux::Z].
- | ^^^^^^^^^^ no item named `Uniooon` in `intra_links_warning`
+ | ^^^^^^^^^^ the module `intra_links_warning` contains no item named `Uniooon`
warning: unresolved link to `Qux::Z`
--> $DIR/intra-links-warning.rs:6:30
|
LL | //! , [Uniooon::X] and [Qux::Z].
- | ^^^^^^ no item named `Qux` in `intra_links_warning`
+ | ^^^^^^ the module `intra_links_warning` contains no item named `Qux`
warning: unresolved link to `Uniooon::X`
--> $DIR/intra-links-warning.rs:10:14
|
LL | //! , [Uniooon::X] and [Qux::Z].
- | ^^^^^^^^^^ no item named `Uniooon` in `intra_links_warning`
+ | ^^^^^^^^^^ the module `intra_links_warning` contains no item named `Uniooon`
warning: unresolved link to `Qux::Z`
--> $DIR/intra-links-warning.rs:10:31
|
LL | //! , [Uniooon::X] and [Qux::Z].
- | ^^^^^^ no item named `Qux` in `intra_links_warning`
+ | ^^^^^^ the module `intra_links_warning` contains no item named `Qux`
warning: unresolved link to `Qux:Y`
--> $DIR/intra-links-warning.rs:14:13
|
LL | /// [Qux:Y]
- | ^^^^^ no item named `Qux:Y` in `intra_links_warning`
+ | ^^^^^ the module `intra_links_warning` contains no item named `Qux:Y`
|
= help: to escape `[` and `]` characters, add '\' before them like `\[` or `\]`
@@ -48,7 +48,7 @@ warning: unresolved link to `error`
--> $DIR/intra-links-warning.rs:58:30
|
LL | * time to introduce a link [error]*/
- | ^^^^^ no item named `error` in `intra_links_warning`
+ | ^^^^^ the module `intra_links_warning` contains no item named `error`
|
= help: to escape `[` and `]` characters, add '\' before them like `\[` or `\]`
@@ -56,7 +56,7 @@ warning: unresolved link to `error`
--> $DIR/intra-links-warning.rs:64:30
|
LL | * time to introduce a link [error]
- | ^^^^^ no item named `error` in `intra_links_warning`
+ | ^^^^^ the module `intra_links_warning` contains no item named `error`
|
= help: to escape `[` and `]` characters, add '\' before them like `\[` or `\]`
@@ -70,7 +70,7 @@ LL | #[doc = "single line [error]"]
single line [error]
^^^^^
- = note: no item named `error` in `intra_links_warning`
+ = note: the module `intra_links_warning` contains no item named `error`
= help: to escape `[` and `]` characters, add '\' before them like `\[` or `\]`
warning: unresolved link to `error`
@@ -83,7 +83,7 @@ LL | #[doc = "single line with \"escaping\" [error]"]
single line with "escaping" [error]
^^^^^
- = note: no item named `error` in `intra_links_warning`
+ = note: the module `intra_links_warning` contains no item named `error`
= help: to escape `[` and `]` characters, add '\' before them like `\[` or `\]`
warning: unresolved link to `error`
@@ -98,14 +98,14 @@ LL | | /// [error]
[error]
^^^^^
- = note: no item named `error` in `intra_links_warning`
+ = note: the module `intra_links_warning` contains no item named `error`
= help: to escape `[` and `]` characters, add '\' before them like `\[` or `\]`
warning: unresolved link to `error1`
--> $DIR/intra-links-warning.rs:80:11
|
LL | /// docs [error1]
- | ^^^^^^ no item named `error1` in `intra_links_warning`
+ | ^^^^^^ the module `intra_links_warning` contains no item named `error1`
|
= help: to escape `[` and `]` characters, add '\' before them like `\[` or `\]`
@@ -113,7 +113,7 @@ warning: unresolved link to `error2`
--> $DIR/intra-links-warning.rs:82:11
|
LL | /// docs [error2]
- | ^^^^^^ no item named `error2` in `intra_links_warning`
+ | ^^^^^^ the module `intra_links_warning` contains no item named `error2`
|
= help: to escape `[` and `]` characters, add '\' before them like `\[` or `\]`
@@ -121,7 +121,7 @@ warning: unresolved link to `BarA`
--> $DIR/intra-links-warning.rs:21:10
|
LL | /// bar [BarA] bar
- | ^^^^ no item named `BarA` in `intra_links_warning`
+ | ^^^^ the module `intra_links_warning` contains no item named `BarA`
|
= help: to escape `[` and `]` characters, add '\' before them like `\[` or `\]`
@@ -129,7 +129,7 @@ warning: unresolved link to `BarB`
--> $DIR/intra-links-warning.rs:27:9
|
LL | * bar [BarB] bar
- | ^^^^ no item named `BarB` in `intra_links_warning`
+ | ^^^^ the module `intra_links_warning` contains no item named `BarB`
|
= help: to escape `[` and `]` characters, add '\' before them like `\[` or `\]`
@@ -137,7 +137,7 @@ warning: unresolved link to `BarC`
--> $DIR/intra-links-warning.rs:34:6
|
LL | bar [BarC] bar
- | ^^^^ no item named `BarC` in `intra_links_warning`
+ | ^^^^ the module `intra_links_warning` contains no item named `BarC`
|
= help: to escape `[` and `]` characters, add '\' before them like `\[` or `\]`
@@ -151,7 +151,7 @@ LL | #[doc = "Foo\nbar [BarD] bar\nbaz"]
bar [BarD] bar
^^^^
- = note: no item named `BarD` in `intra_links_warning`
+ = note: the module `intra_links_warning` contains no item named `BarD`
= help: to escape `[` and `]` characters, add '\' before them like `\[` or `\]`
warning: unresolved link to `BarF`
@@ -167,7 +167,7 @@ LL | f!("Foo\nbar [BarF] bar\nbaz");
bar [BarF] bar
^^^^
- = note: no item named `BarF` in `intra_links_warning`
+ = note: the module `intra_links_warning` contains no item named `BarF`
= help: to escape `[` and `]` characters, add '\' before them like `\[` or `\]`
= note: this warning originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
diff --git a/src/test/rustdoc-ui/lint-group.stderr b/src/test/rustdoc-ui/lint-group.stderr
index 550b79f6e8928..4e9134ea469bd 100644
--- a/src/test/rustdoc-ui/lint-group.stderr
+++ b/src/test/rustdoc-ui/lint-group.stderr
@@ -32,7 +32,7 @@ error: unresolved link to `error`
--> $DIR/lint-group.rs:9:29
|
LL | /// what up, let's make an [error]
- | ^^^^^ no item named `error` in `lint_group`
+ | ^^^^^ the module `lint_group` contains no item named `error`
|
note: the lint level is defined here
--> $DIR/lint-group.rs:7:9
diff --git a/src/test/rustdoc/intra-link-associated-items.rs b/src/test/rustdoc/intra-link-associated-items.rs
index 16a21e33748fa..daf7075a91740 100644
--- a/src/test/rustdoc/intra-link-associated-items.rs
+++ b/src/test/rustdoc/intra-link-associated-items.rs
@@ -3,8 +3,10 @@
/// [`std::collections::BTreeMap::into_iter`]
/// [`String::from`] is ambiguous as to which `From` impl
+/// [Vec::into_iter()] uses a disambiguator
// @has 'intra_link_associated_items/fn.foo.html' '//a[@href="https://doc.rust-lang.org/nightly/alloc/collections/btree/map/struct.BTreeMap.html#method.into_iter"]' 'std::collections::BTreeMap::into_iter'
// @has 'intra_link_associated_items/fn.foo.html' '//a[@href="https://doc.rust-lang.org/nightly/alloc/string/struct.String.html#method.from"]' 'String::from'
+// @has 'intra_link_associated_items/fn.foo.html' '//a[@href="https://doc.rust-lang.org/nightly/alloc/vec/struct.Vec.html#method.into_iter"]' 'Vec::into_iter'
pub fn foo() {}
/// Link to [MyStruct], [link from struct][MyStruct::method], [MyStruct::clone], [MyStruct::Input]
diff --git a/src/test/rustdoc/primitive-link.rs b/src/test/rustdoc/primitive-link.rs
index 819ef05174a8a..8f69b894a223d 100644
--- a/src/test/rustdoc/primitive-link.rs
+++ b/src/test/rustdoc/primitive-link.rs
@@ -4,6 +4,13 @@
// @has foo/struct.Foo.html '//*[@class="docblock"]/p/a[@href="https://doc.rust-lang.org/nightly/std/primitive.u32.html"]' 'u32'
// @has foo/struct.Foo.html '//*[@class="docblock"]/p/a[@href="https://doc.rust-lang.org/nightly/std/primitive.i64.html"]' 'i64'
+// @has foo/struct.Foo.html '//*[@class="docblock"]/p/a[@href="https://doc.rust-lang.org/nightly/std/primitive.i32.html"]' 'std::primitive::i32'
+// @has foo/struct.Foo.html '//*[@class="docblock"]/p/a[@href="https://doc.rust-lang.org/nightly/std/primitive.str.html"]' 'std::primitive::str'
+
+// FIXME: this doesn't resolve
+// @ has foo/struct.Foo.html '//*[@class="docblock"]/p/a[@href="https://doc.rust-lang.org/nightly/std/primitive.i32.html#associatedconstant.MAX"]' 'std::primitive::i32::MAX'
/// It contains [`u32`] and [i64].
+/// It also links to [std::primitive::i32], [std::primitive::str],
+/// and [`std::primitive::i32::MAX`].
pub struct Foo;
diff --git a/src/tools/cargo b/src/tools/cargo
index 8777a6b1e8834..05c611ae3c425 160000
--- a/src/tools/cargo
+++ b/src/tools/cargo
@@ -1 +1 @@
-Subproject commit 8777a6b1e8834899f51b7e09cc9b8d85b2417110
+Subproject commit 05c611ae3c4255b7a2bcf4fcfa65b20286a07839
diff --git a/src/tools/rustbook/Cargo.toml b/src/tools/rustbook/Cargo.toml
index f0a6ce2fa06c2..f5e5c0867b48a 100644
--- a/src/tools/rustbook/Cargo.toml
+++ b/src/tools/rustbook/Cargo.toml
@@ -9,6 +9,6 @@ edition = "2018"
clap = "2.25.0"
[dependencies.mdbook]
-version = "0.4.0"
+version = "0.4.3"
default-features = false
features = ["search"]