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_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/config.toml.example b/config.toml.example index fb62e1b4726bc..c5efb8ed5e51c 100644 --- a/config.toml.example +++ b/config.toml.example @@ -36,8 +36,8 @@ changelog-seen = 1 # toolchain or changing LLVM locally, you probably want to set this to true. # # It's currently false by default due to being newly added; please file bugs if -# enabling this did not work for you on Linux (macOS and Windows support is -# coming soon). +# enabling this did not work for you on x86_64-unknown-linux-gnu. +# Other target triples are currently not supported; see #77084. # # We also currently only support this when building LLVM for the build triple. # @@ -380,7 +380,7 @@ changelog-seen = 1 # Whether or not to leave debug! and trace! calls in the rust binary. # Overrides the `debug-assertions` option, if defined. -# +# # Defaults to rust.debug-assertions value #debug-logging = debug-assertions 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/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/library/std/src/sys/unix/mod.rs b/library/std/src/sys/unix/mod.rs index eddf00d3979f5..166e28435f0a0 100644 --- a/library/std/src/sys/unix/mod.rs +++ b/library/std/src/sys/unix/mod.rs @@ -75,6 +75,13 @@ pub use crate::sys_common::os_str_bytes as os_str; #[cfg(not(test))] pub fn init() { + // The standard streams might be closed on application startup. To prevent + // std::io::{stdin, stdout,stderr} objects from using other unrelated file + // resources opened later, we reopen standards streams when they are closed. + unsafe { + sanitize_standard_fds(); + } + // By default, some platforms will send a *signal* when an EPIPE error // would otherwise be delivered. This runtime doesn't install a SIGPIPE // handler, causing it to kill the program, which isn't exactly what we @@ -86,6 +93,56 @@ pub fn init() { reset_sigpipe(); } + // In the case when all file descriptors are open, the poll has been + // observed to perform better than fcntl (on GNU/Linux). + #[cfg(not(any( + target_os = "emscripten", + target_os = "fuchsia", + // The poll on Darwin doesn't set POLLNVAL for closed fds. + target_os = "macos", + target_os = "ios", + target_os = "redox", + )))] + unsafe fn sanitize_standard_fds() { + use crate::sys::os::errno; + let pfds: &mut [_] = &mut [ + libc::pollfd { fd: 0, events: 0, revents: 0 }, + libc::pollfd { fd: 1, events: 0, revents: 0 }, + libc::pollfd { fd: 2, events: 0, revents: 0 }, + ]; + while libc::poll(pfds.as_mut_ptr(), 3, 0) == -1 { + if errno() == libc::EINTR { + continue; + } + libc::abort(); + } + for pfd in pfds { + if pfd.revents & libc::POLLNVAL == 0 { + continue; + } + if libc::open("/dev/null\0".as_ptr().cast(), libc::O_RDWR, 0) == -1 { + // If the stream is closed but we failed to reopen it, abort the + // process. Otherwise we wouldn't preserve the safety of + // operations on the corresponding Rust object Stdin, Stdout, or + // Stderr. + libc::abort(); + } + } + } + #[cfg(any(target_os = "macos", target_os = "ios", target_os = "redox"))] + unsafe fn sanitize_standard_fds() { + use crate::sys::os::errno; + for fd in 0..3 { + if libc::fcntl(fd, libc::F_GETFD) == -1 && errno() == libc::EBADF { + if libc::open("/dev/null\0".as_ptr().cast(), libc::O_RDWR, 0) == -1 { + libc::abort(); + } + } + } + } + #[cfg(any(target_os = "emscripten", target_os = "fuchsia"))] + unsafe fn sanitize_standard_fds() {} + #[cfg(not(any(target_os = "emscripten", target_os = "fuchsia")))] unsafe fn reset_sigpipe() { assert!(signal(libc::SIGPIPE, libc::SIG_IGN) != libc::SIG_ERR); 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/bootstrap.py b/src/bootstrap/bootstrap.py index 1f0b55a78698d..5c9184f450687 100644 --- a/src/bootstrap/bootstrap.py +++ b/src/bootstrap/bootstrap.py @@ -424,8 +424,19 @@ def download_stage0(self): rustfmt_stamp.write(self.date + self.rustfmt_channel) if self.downloading_llvm(): - llvm_sha = subprocess.check_output(["git", "log", "--author=bors", - "--format=%H", "-n1"]).decode(sys.getdefaultencoding()).strip() + # We want the most recent LLVM submodule update to avoid downloading + # LLVM more often than necessary. + # + # This git command finds that commit SHA, looking for bors-authored + # merges that modified src/llvm-project. + # + # This works even in a repository that has not yet initialized + # submodules. + llvm_sha = subprocess.check_output([ + "git", "log", "--author=bors", "--format=%H", "-n1", + "-m", "--first-parent", + "--", "src/llvm-project" + ]).decode(sys.getdefaultencoding()).strip() llvm_assertions = self.get_toml('assertions', 'llvm') == 'true' if self.program_out_of_date(self.llvm_stamp(), llvm_sha + str(llvm_assertions)): self._download_ci_llvm(llvm_sha, llvm_assertions) 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/test/ui/closed-std-fds.rs b/src/test/ui/closed-std-fds.rs new file mode 100644 index 0000000000000..906da94433455 --- /dev/null +++ b/src/test/ui/closed-std-fds.rs @@ -0,0 +1,69 @@ +// Verifies that std provides replacement for the standard file descriptors when they are missing. +// +// run-pass +// ignore-windows unix specific test +// ignore-cloudabi no processes +// ignore-emscripten no processes +// ignore-sgx no processes + +#![feature(rustc_private)] +extern crate libc; + +use std::io::{self, Read}; +use std::os::unix::process::CommandExt; +use std::process::Command; + +fn main() { + let mut args = std::env::args(); + let argv0 = args.next().expect("argv0"); + match args.next().as_deref() { + Some("child") => child(), + None => parent(&argv0), + _ => unreachable!(), + } +} + +fn parent(argv0: &str) { + let status = unsafe { Command::new(argv0) + .arg("child") + .pre_exec(close_std_fds_on_exec) + .status() + .expect("failed to execute child process") + }; + if !status.success() { + panic!("child failed with {}", status); + } +} + +fn close_std_fds_on_exec() -> io::Result<()> { + for fd in 0..3 { + if unsafe { libc::fcntl(fd, libc::F_SETFD, libc::FD_CLOEXEC) == -1 } { + return Err(io::Error::last_os_error()) + } + } + Ok(()) +} + +fn child() { + // Standard file descriptors should be valid. + assert_fd_is_valid(0); + assert_fd_is_valid(1); + assert_fd_is_valid(2); + + // Writing to stdout & stderr should not panic. + println!("a"); + println!("b"); + eprintln!("c"); + eprintln!("d"); + + // Stdin should be at EOF. + let mut buffer = Vec::new(); + let n = io::stdin().read_to_end(&mut buffer).unwrap(); + assert_eq!(n, 0); +} + +fn assert_fd_is_valid(fd: libc::c_int) { + if unsafe { libc::fcntl(fd, libc::F_GETFD) == -1 } { + panic!("file descriptor {} is not valid {}", fd, io::Error::last_os_error()); + } +} diff --git a/src/tools/miri b/src/tools/miri index 02a33d411d8e3..2f84bfc57dd0e 160000 --- a/src/tools/miri +++ b/src/tools/miri @@ -1 +1 @@ -Subproject commit 02a33d411d8e385942776760a99535d69826349b +Subproject commit 2f84bfc57dd0ef22269bb84dae10f71e5e23e85d 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"]