diff --git a/compiler/rustc_codegen_ssa/src/target_features.rs b/compiler/rustc_codegen_ssa/src/target_features.rs index fd4adfea8082c..df011d6ca5fab 100644 --- a/compiler/rustc_codegen_ssa/src/target_features.rs +++ b/compiler/rustc_codegen_ssa/src/target_features.rs @@ -39,6 +39,7 @@ const ARM_ALLOWED_FEATURES: &[(&str, Option)] = &[ // #[target_feature]. ("thumb-mode", Some(sym::arm_target_feature)), ("thumb2", Some(sym::arm_target_feature)), + ("d32", Some(sym::arm_target_feature)), ]; const AARCH64_ALLOWED_FEATURES: &[(&str, Option)] = &[ diff --git a/compiler/rustc_const_eval/src/interpret/terminator.rs b/compiler/rustc_const_eval/src/interpret/terminator.rs index 8094bf0cf2e2f..d2fbd6a9654f9 100644 --- a/compiler/rustc_const_eval/src/interpret/terminator.rs +++ b/compiler/rustc_const_eval/src/interpret/terminator.rs @@ -39,7 +39,8 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { let mut target_block = targets.otherwise(); for (const_int, target) in targets.iter() { - // Compare using binary_op, to also support pointer values + // Compare using MIR BinOp::Eq, to also support pointer values. + // (Avoiding `self.binary_op` as that does some redundant layout computation.) let res = self .overflowing_binary_op( mir::BinOp::Eq, diff --git a/compiler/rustc_driver/src/pretty.rs b/compiler/rustc_driver/src/pretty.rs index 0c0c61309655c..12bac956adb55 100644 --- a/compiler/rustc_driver/src/pretty.rs +++ b/compiler/rustc_driver/src/pretty.rs @@ -42,7 +42,7 @@ where F: FnOnce(&dyn PrinterSupport) -> A, { match *ppmode { - Normal | EveryBodyLoops | Expanded => { + Normal | Expanded => { let annotation = NoAnn { sess, tcx }; f(&annotation) } diff --git a/compiler/rustc_interface/src/passes.rs b/compiler/rustc_interface/src/passes.rs index 3b51f8eb61c8e..35688a6591239 100644 --- a/compiler/rustc_interface/src/passes.rs +++ b/compiler/rustc_interface/src/passes.rs @@ -3,7 +3,6 @@ use crate::proc_macro_decls; use crate::util; use ast::CRATE_NODE_ID; -use rustc_ast::mut_visit::MutVisitor; use rustc_ast::{self as ast, visit}; use rustc_borrowck as mir_borrowck; use rustc_codegen_ssa::back::link::emit_metadata; @@ -29,7 +28,7 @@ use rustc_plugin_impl as plugin; use rustc_query_impl::{OnDiskCache, Queries as TcxQueries}; use rustc_resolve::{Resolver, ResolverArenas}; use rustc_serialize::json; -use rustc_session::config::{CrateType, Input, OutputFilenames, OutputType, PpMode, PpSourceMode}; +use rustc_session::config::{CrateType, Input, OutputFilenames, OutputType}; use rustc_session::cstore::{MetadataLoader, MetadataLoaderDyn}; use rustc_session::lint; use rustc_session::output::{filename_for_input, filename_for_metadata}; @@ -384,11 +383,6 @@ pub fn configure_and_expand( rustc_builtin_macros::test_harness::inject(sess, resolver, &mut krate) }); - if let Some(PpMode::Source(PpSourceMode::EveryBodyLoops)) = sess.opts.pretty { - tracing::debug!("replacing bodies with loop {{}}"); - util::ReplaceBodyWithLoop::new(resolver).visit_crate(&mut krate); - } - let has_proc_macro_decls = sess.time("AST_validation", || { rustc_ast_passes::ast_validation::check_crate(sess, &krate, resolver.lint_buffer()) }); @@ -457,18 +451,12 @@ pub fn configure_and_expand( }); // Add all buffered lints from the `ParseSess` to the `Session`. - // The ReplaceBodyWithLoop pass may have deleted some AST nodes, potentially - // causing a delay_span_bug later if a buffered lint refers to such a deleted - // AST node (issue #87308). Since everybody_loops is for pretty-printing only, - // anyway, we simply skip all buffered lints here. - if !matches!(sess.opts.pretty, Some(PpMode::Source(PpSourceMode::EveryBodyLoops))) { - sess.parse_sess.buffered_lints.with_lock(|buffered_lints| { - info!("{} parse sess buffered_lints", buffered_lints.len()); - for early_lint in buffered_lints.drain(..) { - resolver.lint_buffer().add_early_lint(early_lint); - } - }); - } + sess.parse_sess.buffered_lints.with_lock(|buffered_lints| { + info!("{} parse sess buffered_lints", buffered_lints.len()); + for early_lint in buffered_lints.drain(..) { + resolver.lint_buffer().add_early_lint(early_lint); + } + }); // Gate identifiers containing invalid Unicode codepoints that were recovered during lexing. sess.parse_sess.bad_unicode_identifiers.with_lock(|identifiers| { diff --git a/compiler/rustc_interface/src/util.rs b/compiler/rustc_interface/src/util.rs index 046f4f9451f58..592cf60e6c3bb 100644 --- a/compiler/rustc_interface/src/util.rs +++ b/compiler/rustc_interface/src/util.rs @@ -1,7 +1,5 @@ use libloading::Library; -use rustc_ast::mut_visit::{visit_clobber, MutVisitor, *}; -use rustc_ast::ptr::P; -use rustc_ast::{self as ast, AttrVec, BlockCheckMode, Term}; +use rustc_ast as ast; use rustc_codegen_ssa::traits::CodegenBackend; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; #[cfg(parallel_compiler)] @@ -13,7 +11,6 @@ use rustc_middle::ty::tls; use rustc_parse::validate_attr; #[cfg(parallel_compiler)] use rustc_query_impl::QueryCtxt; -use rustc_resolve::{self, Resolver}; use rustc_session as session; use rustc_session::config::CheckCfg; use rustc_session::config::{self, CrateType}; @@ -25,12 +22,10 @@ use rustc_span::edition::Edition; use rustc_span::lev_distance::find_best_match_for_name; use rustc_span::source_map::FileLoader; use rustc_span::symbol::{sym, Symbol}; -use smallvec::SmallVec; use std::env; use std::env::consts::{DLL_PREFIX, DLL_SUFFIX}; use std::lazy::SyncOnceCell; use std::mem; -use std::ops::DerefMut; #[cfg(not(parallel_compiler))] use std::panic; use std::path::{Path, PathBuf}; @@ -664,214 +659,6 @@ pub fn non_durable_rename(src: &Path, dst: &Path) -> std::io::Result<()> { std::fs::rename(src, dst) } -/// Replaces function bodies with `loop {}` (an infinite loop). This gets rid of -/// all semantic errors in the body while still satisfying the return type, -/// except in certain cases, see below for more. -/// -/// This pass is known as `everybody_loops`. Very punny. -/// -/// As of March 2021, `everybody_loops` is only used for the -/// `-Z unpretty=everybody_loops` debugging option. -/// -/// FIXME: Currently the `everybody_loops` transformation is not applied to: -/// * `const fn`; support could be added, but hasn't. Originally `const fn` -/// was skipped due to issue #43636 that `loop` was not supported for -/// const evaluation. -/// * `impl Trait`, due to issue #43869 that functions returning impl Trait cannot be diverging. -/// Solving this may require `!` to implement every trait, which relies on the an even more -/// ambitious form of the closed RFC #1637. See also [#34511]. -/// -/// [#34511]: https://github.com/rust-lang/rust/issues/34511#issuecomment-322340401 -pub struct ReplaceBodyWithLoop<'a, 'b> { - within_static_or_const: bool, - nested_blocks: Option>, - resolver: &'a mut Resolver<'b>, -} - -impl<'a, 'b> ReplaceBodyWithLoop<'a, 'b> { - pub fn new(resolver: &'a mut Resolver<'b>) -> ReplaceBodyWithLoop<'a, 'b> { - ReplaceBodyWithLoop { within_static_or_const: false, nested_blocks: None, resolver } - } - - fn run R>(&mut self, is_const: bool, action: F) -> R { - let old_const = mem::replace(&mut self.within_static_or_const, is_const); - let old_blocks = self.nested_blocks.take(); - let ret = action(self); - self.within_static_or_const = old_const; - self.nested_blocks = old_blocks; - ret - } - - fn should_ignore_fn(ret_ty: &ast::FnRetTy) -> bool { - let ast::FnRetTy::Ty(ref ty) = ret_ty else { - return false; - }; - fn involves_impl_trait(ty: &ast::Ty) -> bool { - match ty.kind { - ast::TyKind::ImplTrait(..) => true, - ast::TyKind::Slice(ref subty) - | ast::TyKind::Array(ref subty, _) - | ast::TyKind::Ptr(ast::MutTy { ty: ref subty, .. }) - | ast::TyKind::Rptr(_, ast::MutTy { ty: ref subty, .. }) - | ast::TyKind::Paren(ref subty) => involves_impl_trait(subty), - ast::TyKind::Tup(ref tys) => any_involves_impl_trait(tys.iter()), - ast::TyKind::Path(_, ref path) => { - path.segments.iter().any(|seg| match seg.args.as_deref() { - None => false, - Some(&ast::GenericArgs::AngleBracketed(ref data)) => { - data.args.iter().any(|arg| match arg { - ast::AngleBracketedArg::Arg(arg) => match arg { - ast::GenericArg::Type(ty) => involves_impl_trait(ty), - ast::GenericArg::Lifetime(_) | ast::GenericArg::Const(_) => { - false - } - }, - ast::AngleBracketedArg::Constraint(c) => match c.kind { - ast::AssocConstraintKind::Bound { .. } => true, - ast::AssocConstraintKind::Equality { ref term } => { - match term { - Term::Ty(ty) => involves_impl_trait(ty), - // FIXME(...): This should check if the constant - // involves a trait impl, but for now ignore. - Term::Const(_) => false, - } - } - }, - }) - } - Some(&ast::GenericArgs::Parenthesized(ref data)) => { - any_involves_impl_trait(data.inputs.iter()) - || ReplaceBodyWithLoop::should_ignore_fn(&data.output) - } - }) - } - _ => false, - } - } - - fn any_involves_impl_trait<'a, I: Iterator>>(mut it: I) -> bool { - it.any(|subty| involves_impl_trait(subty)) - } - - involves_impl_trait(ty) - } - - fn is_sig_const(sig: &ast::FnSig) -> bool { - matches!(sig.header.constness, ast::Const::Yes(_)) - || ReplaceBodyWithLoop::should_ignore_fn(&sig.decl.output) - } -} - -impl<'a> MutVisitor for ReplaceBodyWithLoop<'a, '_> { - fn visit_item_kind(&mut self, i: &mut ast::ItemKind) { - let is_const = match i { - ast::ItemKind::Static(..) | ast::ItemKind::Const(..) => true, - ast::ItemKind::Fn(box ast::Fn { ref sig, .. }) => Self::is_sig_const(sig), - _ => false, - }; - self.run(is_const, |s| noop_visit_item_kind(i, s)) - } - - fn flat_map_trait_item(&mut self, i: P) -> SmallVec<[P; 1]> { - let is_const = match i.kind { - ast::AssocItemKind::Const(..) => true, - ast::AssocItemKind::Fn(box ast::Fn { ref sig, .. }) => Self::is_sig_const(sig), - _ => false, - }; - self.run(is_const, |s| noop_flat_map_assoc_item(i, s)) - } - - fn flat_map_impl_item(&mut self, i: P) -> SmallVec<[P; 1]> { - self.flat_map_trait_item(i) - } - - fn visit_anon_const(&mut self, c: &mut ast::AnonConst) { - self.run(true, |s| noop_visit_anon_const(c, s)) - } - - fn visit_block(&mut self, b: &mut P) { - fn stmt_to_block( - rules: ast::BlockCheckMode, - s: Option, - resolver: &mut Resolver<'_>, - ) -> ast::Block { - ast::Block { - stmts: s.into_iter().collect(), - rules, - id: resolver.next_node_id(), - span: rustc_span::DUMMY_SP, - tokens: None, - could_be_bare_literal: false, - } - } - - fn block_to_stmt(b: ast::Block, resolver: &mut Resolver<'_>) -> ast::Stmt { - let expr = P(ast::Expr { - id: resolver.next_node_id(), - kind: ast::ExprKind::Block(P(b), None), - span: rustc_span::DUMMY_SP, - attrs: AttrVec::new(), - tokens: None, - }); - - ast::Stmt { - id: resolver.next_node_id(), - kind: ast::StmtKind::Expr(expr), - span: rustc_span::DUMMY_SP, - } - } - - let empty_block = stmt_to_block(BlockCheckMode::Default, None, self.resolver); - let loop_expr = P(ast::Expr { - kind: ast::ExprKind::Loop(P(empty_block), None), - id: self.resolver.next_node_id(), - span: rustc_span::DUMMY_SP, - attrs: AttrVec::new(), - tokens: None, - }); - - let loop_stmt = ast::Stmt { - id: self.resolver.next_node_id(), - span: rustc_span::DUMMY_SP, - kind: ast::StmtKind::Expr(loop_expr), - }; - - if self.within_static_or_const { - noop_visit_block(b, self) - } else { - visit_clobber(b.deref_mut(), |b| { - let mut stmts = vec![]; - for s in b.stmts { - let old_blocks = self.nested_blocks.replace(vec![]); - - stmts.extend(self.flat_map_stmt(s).into_iter().filter(|s| s.is_item())); - - // we put a Some in there earlier with that replace(), so this is valid - let new_blocks = self.nested_blocks.take().unwrap(); - self.nested_blocks = old_blocks; - stmts.extend(new_blocks.into_iter().map(|b| block_to_stmt(b, self.resolver))); - } - - let mut new_block = ast::Block { stmts, ..b }; - - if let Some(old_blocks) = self.nested_blocks.as_mut() { - //push our fresh block onto the cache and yield an empty block with `loop {}` - if !new_block.stmts.is_empty() { - old_blocks.push(new_block); - } - - stmt_to_block(b.rules, Some(loop_stmt), &mut self.resolver) - } else { - //push `loop {}` onto the end of our fresh block and yield that - new_block.stmts.push(loop_stmt); - - new_block - } - }) - } - } -} - /// Returns a version string such as "1.46.0 (04488afe3 2020-08-24)" pub fn version_str() -> Option<&'static str> { option_env!("CFG_VERSION") diff --git a/compiler/rustc_macros/src/newtype.rs b/compiler/rustc_macros/src/newtype.rs index f284e5cdd5c1e..f5968a8a7ea73 100644 --- a/compiler/rustc_macros/src/newtype.rs +++ b/compiler/rustc_macros/src/newtype.rs @@ -10,6 +10,7 @@ mod kw { syn::custom_keyword!(MAX); syn::custom_keyword!(ENCODABLE); syn::custom_keyword!(custom); + syn::custom_keyword!(ORD_IMPL); } #[derive(Debug)] @@ -42,6 +43,7 @@ impl Parse for Newtype { let mut max = None; let mut consts = Vec::new(); let mut encodable = true; + let mut ord = true; // Parse an optional trailing comma let try_comma = || -> Result<()> { @@ -99,13 +101,20 @@ impl Parse for Newtype { encodable = false; continue; } + if body.lookahead1().peek(kw::ORD_IMPL) { + body.parse::()?; + body.parse::()?; + body.parse::()?; + ord = false; + continue; + } // We've parsed everything that the user provided, so we're done if body.is_empty() { break; } - // Otherwise, we are parsng a user-defined constant + // Otherwise, we are parsing a user-defined constant let const_attrs = body.call(Attribute::parse_outer)?; body.parse::()?; let const_name: Ident = body.parse()?; @@ -137,6 +146,40 @@ impl Parse for Newtype { quote! {} }; + if ord { + derive_paths.push(parse_quote!(Ord)); + derive_paths.push(parse_quote!(PartialOrd)); + } + + let step = if ord { + quote! { + impl ::std::iter::Step for #name { + #[inline] + fn steps_between(start: &Self, end: &Self) -> Option { + ::steps_between( + &Self::index(*start), + &Self::index(*end), + ) + } + + #[inline] + fn forward_checked(start: Self, u: usize) -> Option { + Self::index(start).checked_add(u).map(Self::from_usize) + } + + #[inline] + fn backward_checked(start: Self, u: usize) -> Option { + Self::index(start).checked_sub(u).map(Self::from_usize) + } + } + + // Safety: The implementation of `Step` upholds all invariants. + unsafe impl ::std::iter::TrustedStep for #name {} + } + } else { + quote! {} + }; + let debug_impl = match debug_format { DebugFormat::Custom => quote! {}, DebugFormat::Format(format) => { @@ -152,7 +195,7 @@ impl Parse for Newtype { Ok(Self(quote! { #(#attrs)* - #[derive(Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord, #(#derive_paths),*)] + #[derive(Clone, Copy, PartialEq, Eq, Hash, #(#derive_paths),*)] #[rustc_layout_scalar_valid_range_end(#max)] #vis struct #name { private: u32, @@ -247,28 +290,7 @@ impl Parse for Newtype { } } - impl ::std::iter::Step for #name { - #[inline] - fn steps_between(start: &Self, end: &Self) -> Option { - ::steps_between( - &Self::index(*start), - &Self::index(*end), - ) - } - - #[inline] - fn forward_checked(start: Self, u: usize) -> Option { - Self::index(start).checked_add(u).map(Self::from_usize) - } - - #[inline] - fn backward_checked(start: Self, u: usize) -> Option { - Self::index(start).checked_sub(u).map(Self::from_usize) - } - } - - // Safety: The implementation of `Step` upholds all invariants. - unsafe impl ::std::iter::TrustedStep for #name {} + #step impl From<#name> for u32 { #[inline] diff --git a/compiler/rustc_session/src/config.rs b/compiler/rustc_session/src/config.rs index f9b75690e375f..d1cab6280153d 100644 --- a/compiler/rustc_session/src/config.rs +++ b/compiler/rustc_session/src/config.rs @@ -2509,7 +2509,6 @@ fn parse_pretty(debugging_opts: &DebuggingOptions, efmt: ErrorOutputType) -> Opt let first = match debugging_opts.unpretty.as_deref()? { "normal" => Source(PpSourceMode::Normal), "identified" => Source(PpSourceMode::Identified), - "everybody_loops" => Source(PpSourceMode::EveryBodyLoops), "expanded" => Source(PpSourceMode::Expanded), "expanded,identified" => Source(PpSourceMode::ExpandedIdentified), "expanded,hygiene" => Source(PpSourceMode::ExpandedHygiene), @@ -2645,8 +2644,6 @@ impl fmt::Display for CrateType { pub enum PpSourceMode { /// `-Zunpretty=normal` Normal, - /// `-Zunpretty=everybody_loops` - EveryBodyLoops, /// `-Zunpretty=expanded` Expanded, /// `-Zunpretty=identified` @@ -2678,7 +2675,7 @@ pub enum PpHirMode { #[derive(Copy, Clone, PartialEq, Debug)] pub enum PpMode { /// Options that print the source code, i.e. - /// `-Zunpretty=normal` and `-Zunpretty=everybody_loops` + /// `-Zunpretty=normal` and `-Zunpretty=expanded` Source(PpSourceMode), AstTree(PpAstTreeMode), /// Options that print the HIR, i.e. `-Zunpretty=hir` @@ -2700,7 +2697,7 @@ impl PpMode { match *self { Source(Normal | Identified) | AstTree(PpAstTreeMode::Normal) => false, - Source(Expanded | EveryBodyLoops | ExpandedIdentified | ExpandedHygiene) + Source(Expanded | ExpandedIdentified | ExpandedHygiene) | AstTree(PpAstTreeMode::Expanded) | Hir(_) | HirTree diff --git a/compiler/rustc_session/src/options.rs b/compiler/rustc_session/src/options.rs index c2b13346cd6c9..17eec333e0980 100644 --- a/compiler/rustc_session/src/options.rs +++ b/compiler/rustc_session/src/options.rs @@ -1491,7 +1491,6 @@ options! { `normal`, `identified`, `expanded`, `expanded,identified`, `expanded,hygiene` (with internal representations), - `everybody_loops` (all function bodies replaced with `loop {}`), `ast-tree` (raw AST before expansion), `ast-tree,expanded` (raw AST after expansion), `hir` (the HIR), `hir,identified`, diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index 6767593bbc51a..9d452131fa6ac 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -539,6 +539,7 @@ symbols! { custom_inner_attributes, custom_test_frameworks, d, + d32, dbg_macro, dead_code, dealloc, diff --git a/compiler/rustc_target/src/asm/arm.rs b/compiler/rustc_target/src/asm/arm.rs index 88f2d3f80d2c3..aaa632333db38 100644 --- a/compiler/rustc_target/src/asm/arm.rs +++ b/compiler/rustc_target/src/asm/arm.rs @@ -50,9 +50,12 @@ impl ArmInlineAsmRegClass { match self { Self::reg => types! { _: I8, I16, I32, F32; }, Self::sreg | Self::sreg_low16 => types! { vfp2: I32, F32; }, - Self::dreg | Self::dreg_low16 | Self::dreg_low8 => types! { + Self::dreg_low16 | Self::dreg_low8 => types! { vfp2: I64, F64, VecI8(8), VecI16(4), VecI32(2), VecI64(1), VecF32(2); }, + Self::dreg => types! { + d32: I64, F64, VecI8(8), VecI16(4), VecI32(2), VecI64(1), VecF32(2); + }, Self::qreg | Self::qreg_low8 | Self::qreg_low4 => types! { neon: VecI8(16), VecI16(8), VecI32(4), VecI64(2), VecF32(4); }, diff --git a/compiler/rustc_typeck/src/check_unused.rs b/compiler/rustc_typeck/src/check_unused.rs index f45cd3ed68948..1826c3f5f7fa5 100644 --- a/compiler/rustc_typeck/src/check_unused.rs +++ b/compiler/rustc_typeck/src/check_unused.rs @@ -82,8 +82,7 @@ fn unused_crates_lint(tcx: TyCtxt<'_>) { // The `def_id` here actually was calculated during resolution (at least // at the time of this writing) and is being shipped to us via a side // channel of the tcx. There may have been extra expansion phases, - // however, which ended up removing the `def_id` *after* expansion such - // as the `ReplaceBodyWithLoop` pass (which is a bit of a hack, but hey) + // however, which ended up removing the `def_id` *after* expansion. // // As a result we need to verify that `def_id` is indeed still valid for // our AST and actually present in the HIR map. If it's not there then diff --git a/library/std/src/io/mod.rs b/library/std/src/io/mod.rs index 71a59fb580321..3fa965d08e698 100644 --- a/library/std/src/io/mod.rs +++ b/library/std/src/io/mod.rs @@ -268,8 +268,6 @@ pub use self::buffered::WriterPanicked; pub use self::stdio::set_output_capture; #[unstable(feature = "print_internals", issue = "none")] pub use self::stdio::{_eprint, _print}; -#[unstable(feature = "stdio_locked", issue = "86845")] -pub use self::stdio::{stderr_locked, stdin_locked, stdout_locked}; #[stable(feature = "rust1", since = "1.0.0")] pub use self::{ buffered::{BufReader, BufWriter, IntoInnerError, LineWriter}, diff --git a/library/std/src/io/stdio.rs b/library/std/src/io/stdio.rs index 3d6de20d86091..5414ff648d4d5 100644 --- a/library/std/src/io/stdio.rs +++ b/library/std/src/io/stdio.rs @@ -307,48 +307,6 @@ pub fn stdin() -> Stdin { } } -/// Constructs a new locked handle to the standard input of the current -/// process. -/// -/// Each handle returned is a guard granting locked access to a shared -/// global buffer whose access is synchronized via a mutex. If you need -/// more explicit control over locking, for example, in a multi-threaded -/// program, use the [`io::stdin`] function to obtain an unlocked handle, -/// along with the [`Stdin::lock`] method. -/// -/// The lock is released when the returned guard goes out of scope. The -/// returned guard also implements the [`Read`] and [`BufRead`] traits for -/// accessing the underlying data. -/// -/// **Note**: The mutex locked by this handle is not reentrant. Even in a -/// single-threaded program, calling other code that accesses [`Stdin`] -/// could cause a deadlock or panic, if this locked handle is held across -/// that call. -/// -/// ### Note: Windows Portability Consideration -/// When operating in a console, the Windows implementation of this stream does not support -/// non-UTF-8 byte sequences. Attempting to read bytes that are not valid UTF-8 will return -/// an error. -/// -/// # Examples -/// -/// ```no_run -/// #![feature(stdio_locked)] -/// use std::io::{self, BufRead}; -/// -/// fn main() -> io::Result<()> { -/// let mut buffer = String::new(); -/// let mut handle = io::stdin_locked(); -/// -/// handle.read_line(&mut buffer)?; -/// Ok(()) -/// } -/// ``` -#[unstable(feature = "stdio_locked", issue = "86845")] -pub fn stdin_locked() -> StdinLock<'static> { - stdin().into_locked() -} - impl Stdin { /// Locks this handle to the standard input stream, returning a readable /// guard. @@ -372,8 +330,10 @@ impl Stdin { /// } /// ``` #[stable(feature = "rust1", since = "1.0.0")] - pub fn lock(&self) -> StdinLock<'_> { - self.lock_any() + pub fn lock(&self) -> StdinLock<'static> { + // Locks this handle with 'static lifetime. This depends on the + // implementation detail that the underlying `Mutex` is static. + StdinLock { inner: self.inner.lock().unwrap_or_else(|e| e.into_inner()) } } /// Locks this handle and reads a line of input, appending it to the specified buffer. @@ -407,43 +367,6 @@ impl Stdin { self.lock().read_line(buf) } - // Locks this handle with any lifetime. This depends on the - // implementation detail that the underlying `Mutex` is static. - fn lock_any<'a>(&self) -> StdinLock<'a> { - StdinLock { inner: self.inner.lock().unwrap_or_else(|e| e.into_inner()) } - } - - /// Consumes this handle to the standard input stream, locking the - /// shared global buffer associated with the stream and returning a - /// readable guard. - /// - /// The lock is released when the returned guard goes out of scope. The - /// returned guard also implements the [`Read`] and [`BufRead`] traits - /// for accessing the underlying data. - /// - /// It is often simpler to directly get a locked handle using the - /// [`stdin_locked`] function instead, unless nearby code also needs to - /// use an unlocked handle. - /// - /// # Examples - /// - /// ```no_run - /// #![feature(stdio_locked)] - /// use std::io::{self, BufRead}; - /// - /// fn main() -> io::Result<()> { - /// let mut buffer = String::new(); - /// let mut handle = io::stdin().into_locked(); - /// - /// handle.read_line(&mut buffer)?; - /// Ok(()) - /// } - /// ``` - #[unstable(feature = "stdio_locked", issue = "86845")] - pub fn into_locked(self) -> StdinLock<'static> { - self.lock_any() - } - /// Consumes this handle and returns an iterator over input lines. /// /// For detailed semantics of this method, see the documentation on @@ -463,7 +386,7 @@ impl Stdin { #[must_use = "`self` will be dropped if the result is not used"] #[unstable(feature = "stdin_forwarders", issue = "87096")] pub fn lines(self) -> Lines> { - self.into_locked().lines() + self.lock().lines() } } @@ -649,42 +572,6 @@ pub fn stdout() -> Stdout { } } -/// Constructs a new locked handle to the standard output of the current -/// process. -/// -/// Each handle returned is a guard granting locked access to a shared -/// global buffer whose access is synchronized via a mutex. If you need -/// more explicit control over locking, for example, in a multi-threaded -/// program, use the [`io::stdout`] function to obtain an unlocked handle, -/// along with the [`Stdout::lock`] method. -/// -/// The lock is released when the returned guard goes out of scope. The -/// returned guard also implements the [`Write`] trait for writing data. -/// -/// ### Note: Windows Portability Consideration -/// When operating in a console, the Windows implementation of this stream does not support -/// non-UTF-8 byte sequences. Attempting to write bytes that are not valid UTF-8 will return -/// an error. -/// -/// # Examples -/// -/// ```no_run -/// #![feature(stdio_locked)] -/// use std::io::{self, Write}; -/// -/// fn main() -> io::Result<()> { -/// let mut handle = io::stdout_locked(); -/// -/// handle.write_all(b"hello world")?; -/// -/// Ok(()) -/// } -/// ``` -#[unstable(feature = "stdio_locked", issue = "86845")] -pub fn stdout_locked() -> StdoutLock<'static> { - stdout().into_locked() -} - pub fn cleanup() { if let Some(instance) = STDOUT.get() { // Flush the data and disable buffering during shutdown @@ -712,55 +599,20 @@ impl Stdout { /// use std::io::{self, Write}; /// /// fn main() -> io::Result<()> { - /// let stdout = io::stdout(); - /// let mut handle = stdout.lock(); + /// let mut stdout = io::stdout().lock(); /// - /// handle.write_all(b"hello world")?; + /// stdout.write_all(b"hello world")?; /// /// Ok(()) /// } /// ``` #[stable(feature = "rust1", since = "1.0.0")] - pub fn lock(&self) -> StdoutLock<'_> { - self.lock_any() - } - - // Locks this handle with any lifetime. This depends on the - // implementation detail that the underlying `ReentrantMutex` is - // static. - fn lock_any<'a>(&self) -> StdoutLock<'a> { + pub fn lock(&self) -> StdoutLock<'static> { + // Locks this handle with 'static lifetime. This depends on the + // implementation detail that the underlying `ReentrantMutex` is + // static. StdoutLock { inner: self.inner.lock() } } - - /// Consumes this handle to the standard output stream, locking the - /// shared global buffer associated with the stream and returning a - /// writable guard. - /// - /// The lock is released when the returned lock goes out of scope. The - /// returned guard also implements the [`Write`] trait for writing data. - /// - /// It is often simpler to directly get a locked handle using the - /// [`io::stdout_locked`] function instead, unless nearby code also - /// needs to use an unlocked handle. - /// - /// # Examples - /// - /// ```no_run - /// #![feature(stdio_locked)] - /// use std::io::{self, Write}; - /// - /// fn main() -> io::Result<()> { - /// let mut handle = io::stdout().into_locked(); - /// - /// handle.write_all(b"hello world")?; - /// - /// Ok(()) - /// } - /// ``` - #[unstable(feature = "stdio_locked", issue = "86845")] - pub fn into_locked(self) -> StdoutLock<'static> { - self.lock_any() - } } #[stable(feature = "std_debug", since = "1.16.0")] @@ -935,35 +787,6 @@ pub fn stderr() -> Stderr { } } -/// Constructs a new locked handle to the standard error of the current -/// process. -/// -/// This handle is not buffered. -/// -/// ### Note: Windows Portability Consideration -/// When operating in a console, the Windows implementation of this stream does not support -/// non-UTF-8 byte sequences. Attempting to write bytes that are not valid UTF-8 will return -/// an error. -/// -/// # Example -/// -/// ```no_run -/// #![feature(stdio_locked)] -/// use std::io::{self, Write}; -/// -/// fn main() -> io::Result<()> { -/// let mut handle = io::stderr_locked(); -/// -/// handle.write_all(b"hello world")?; -/// -/// Ok(()) -/// } -/// ``` -#[unstable(feature = "stdio_locked", issue = "86845")] -pub fn stderr_locked() -> StderrLock<'static> { - stderr().into_locked() -} - impl Stderr { /// Locks this handle to the standard error stream, returning a writable /// guard. @@ -986,43 +809,12 @@ impl Stderr { /// } /// ``` #[stable(feature = "rust1", since = "1.0.0")] - pub fn lock(&self) -> StderrLock<'_> { - self.lock_any() - } - - // Locks this handle with any lifetime. This depends on the - // implementation detail that the underlying `ReentrantMutex` is - // static. - fn lock_any<'a>(&self) -> StderrLock<'a> { + pub fn lock(&self) -> StderrLock<'static> { + // Locks this handle with 'static lifetime. This depends on the + // implementation detail that the underlying `ReentrantMutex` is + // static. StderrLock { inner: self.inner.lock() } } - - /// Locks and consumes this handle to the standard error stream, - /// returning a writable guard. - /// - /// The lock is released when the returned guard goes out of scope. The - /// returned guard also implements the [`Write`] trait for writing - /// data. - /// - /// # Examples - /// - /// ``` - /// #![feature(stdio_locked)] - /// use std::io::{self, Write}; - /// - /// fn foo() -> io::Result<()> { - /// let stderr = io::stderr(); - /// let mut handle = stderr.into_locked(); - /// - /// handle.write_all(b"hello world")?; - /// - /// Ok(()) - /// } - /// ``` - #[unstable(feature = "stdio_locked", issue = "86845")] - pub fn into_locked(self) -> StderrLock<'static> { - self.lock_any() - } } #[stable(feature = "std_debug", since = "1.16.0")] diff --git a/library/std/src/io/stdio/tests.rs b/library/std/src/io/stdio/tests.rs index b1df6b7131c87..f89fd27ce6c23 100644 --- a/library/std/src/io/stdio/tests.rs +++ b/library/std/src/io/stdio/tests.rs @@ -50,17 +50,17 @@ fn panic_doesnt_poison() { #[test] #[cfg_attr(target_os = "emscripten", ignore)] fn test_lock_stderr() { - test_lock(stderr, stderr_locked); + test_lock(stderr, || stderr().lock()); } #[test] #[cfg_attr(target_os = "emscripten", ignore)] fn test_lock_stdin() { - test_lock(stdin, stdin_locked); + test_lock(stdin, || stdin().lock()); } #[test] #[cfg_attr(target_os = "emscripten", ignore)] fn test_lock_stdout() { - test_lock(stdout, stdout_locked); + test_lock(stdout, || stdout().lock()); } // Helper trait to make lock testing function generic. diff --git a/library/std/src/net/mod.rs b/library/std/src/net/mod.rs index f676e0a04f000..9ed4a98f943cd 100644 --- a/library/std/src/net/mod.rs +++ b/library/std/src/net/mod.rs @@ -14,6 +14,10 @@ //! * [`ToSocketAddrs`] is a trait that used for generic address resolution when interacting //! with networking objects like [`TcpListener`], [`TcpStream`] or [`UdpSocket`] //! * Other types are return or parameter types for various methods in this module +//! +//! Rust disables inheritance of socket objects to child processes by default when possible. For +//! example, through the use of the `CLOEXEC` flag in UNIX systems or the `HANDLE_FLAG_INHERIT` +//! flag on Windows. #![stable(feature = "rust1", since = "1.0.0")] diff --git a/library/std/src/os/windows/io/handle.rs b/library/std/src/os/windows/io/handle.rs index d378d591ba3a9..14b94d8dcdf92 100644 --- a/library/std/src/os/windows/io/handle.rs +++ b/library/std/src/os/windows/io/handle.rs @@ -59,6 +59,7 @@ pub struct BorrowedHandle<'handle> { /// [`RegCloseKey`]: https://docs.microsoft.com/en-us/windows/win32/api/winreg/nf-winreg-regclosekey /// /// [here]: https://devblogs.microsoft.com/oldnewthing/20040302-00/?p=40443 +#[repr(transparent)] #[unstable(feature = "io_safety", issue = "87074")] pub struct OwnedHandle { handle: RawHandle, diff --git a/library/std/src/sys/windows/c.rs b/library/std/src/sys/windows/c.rs index 2affd7e75b030..9b61b2476d5bb 100644 --- a/library/std/src/sys/windows/c.rs +++ b/library/std/src/sys/windows/c.rs @@ -6,6 +6,7 @@ use crate::mem; use crate::os::raw::{c_char, c_int, c_long, c_longlong, c_uint, c_ulong, c_ushort}; +use crate::os::windows::io::{BorrowedHandle, HandleOrInvalid, HandleOrNull}; use crate::ptr; use core::ffi::NonZero_c_ulong; @@ -886,7 +887,7 @@ extern "system" { lpParameter: LPVOID, dwCreationFlags: DWORD, lpThreadId: LPDWORD, - ) -> HANDLE; + ) -> HandleOrNull; pub fn WaitForSingleObject(hHandle: HANDLE, dwMilliseconds: DWORD) -> DWORD; pub fn SwitchToThread() -> BOOL; pub fn Sleep(dwMilliseconds: DWORD); @@ -950,14 +951,14 @@ extern "system" { dwOptions: DWORD, ) -> BOOL; pub fn ReadFile( - hFile: HANDLE, + hFile: BorrowedHandle<'_>, lpBuffer: LPVOID, nNumberOfBytesToRead: DWORD, lpNumberOfBytesRead: LPDWORD, lpOverlapped: LPOVERLAPPED, ) -> BOOL; pub fn WriteFile( - hFile: HANDLE, + hFile: BorrowedHandle<'_>, lpBuffer: LPVOID, nNumberOfBytesToWrite: DWORD, lpNumberOfBytesWritten: LPDWORD, @@ -981,7 +982,7 @@ extern "system" { dwCreationDisposition: DWORD, dwFlagsAndAttributes: DWORD, hTemplateFile: HANDLE, - ) -> HANDLE; + ) -> HandleOrInvalid; pub fn FindFirstFileW(fileName: LPCWSTR, findFileData: LPWIN32_FIND_DATAW) -> HANDLE; pub fn FindNextFileW(findFile: HANDLE, findFileData: LPWIN32_FIND_DATAW) -> BOOL; diff --git a/library/std/src/sys/windows/fs.rs b/library/std/src/sys/windows/fs.rs index cb83ee2469a1c..d6c40a15329a9 100644 --- a/library/std/src/sys/windows/fs.rs +++ b/library/std/src/sys/windows/fs.rs @@ -1,5 +1,6 @@ use crate::os::windows::prelude::*; +use crate::convert::TryInto; use crate::ffi::OsString; use crate::fmt; use crate::io::{self, Error, IoSlice, IoSliceMut, ReadBuf, SeekFrom}; @@ -294,10 +295,10 @@ impl File { ptr::null_mut(), ) }; - if handle == c::INVALID_HANDLE_VALUE { - Err(Error::last_os_error()) + if let Ok(handle) = handle.try_into() { + Ok(File { handle: Handle::from_inner(handle) }) } else { - unsafe { Ok(File { handle: Handle::from_raw_handle(handle) }) } + Err(Error::last_os_error()) } } diff --git a/library/std/src/sys/windows/handle.rs b/library/std/src/sys/windows/handle.rs index daab39bb00cbc..e5c9567957bc1 100644 --- a/library/std/src/sys/windows/handle.rs +++ b/library/std/src/sys/windows/handle.rs @@ -78,7 +78,7 @@ impl Handle { let len = cmp::min(buf.len(), ::MAX as usize) as c::DWORD; let res = cvt(unsafe { c::ReadFile( - self.as_raw_handle(), + self.as_handle(), buf.as_mut_ptr() as c::LPVOID, len, &mut read, @@ -116,7 +116,7 @@ impl Handle { overlapped.Offset = offset as u32; overlapped.OffsetHigh = (offset >> 32) as u32; cvt(c::ReadFile( - self.as_raw_handle(), + self.as_handle(), buf.as_mut_ptr() as c::LPVOID, len, &mut read, @@ -135,7 +135,7 @@ impl Handle { let len = cmp::min(buf.remaining(), ::MAX as usize) as c::DWORD; let res = cvt(unsafe { c::ReadFile( - self.as_raw_handle(), + self.as_handle(), buf.unfilled_mut().as_mut_ptr() as c::LPVOID, len, &mut read, @@ -171,7 +171,7 @@ impl Handle { let len = cmp::min(buf.len(), ::MAX as usize) as c::DWORD; let mut amt = 0; let res = cvt(c::ReadFile( - self.as_raw_handle(), + self.as_handle(), buf.as_ptr() as c::LPVOID, len, &mut amt, @@ -225,7 +225,7 @@ impl Handle { let len = cmp::min(buf.len(), ::MAX as usize) as c::DWORD; cvt(unsafe { c::WriteFile( - self.as_raw_handle(), + self.as_handle(), buf.as_ptr() as c::LPVOID, len, &mut amt, @@ -252,7 +252,7 @@ impl Handle { overlapped.Offset = offset as u32; overlapped.OffsetHigh = (offset >> 32) as u32; cvt(c::WriteFile( - self.as_raw_handle(), + self.as_handle(), buf.as_ptr() as c::LPVOID, len, &mut written, diff --git a/library/std/src/sys/windows/thread.rs b/library/std/src/sys/windows/thread.rs index e4bba9255d23e..bd304dc57371d 100644 --- a/library/std/src/sys/windows/thread.rs +++ b/library/std/src/sys/windows/thread.rs @@ -1,11 +1,13 @@ +use crate::convert::TryInto; use crate::ffi::CStr; use crate::io; use crate::num::NonZeroUsize; -use crate::os::windows::io::{AsRawHandle, FromRawHandle}; +use crate::os::windows::io::AsRawHandle; use crate::ptr; use crate::sys::c; use crate::sys::handle::Handle; use crate::sys::stack_overflow; +use crate::sys_common::FromInner; use crate::time::Duration; use libc::c_void; @@ -40,13 +42,13 @@ impl Thread { ptr::null_mut(), ); - return if ret as usize == 0 { + return if let Ok(handle) = ret.try_into() { + Ok(Thread { handle: Handle::from_inner(handle) }) + } else { // The thread failed to start and as a result p was not consumed. Therefore, it is // safe to reconstruct the box so that it gets deallocated. drop(Box::from_raw(p)); Err(io::Error::last_os_error()) - } else { - Ok(Thread { handle: Handle::from_raw_handle(ret) }) }; extern "system" fn thread_start(main: *mut c_void) -> c::DWORD { diff --git a/src/bootstrap/builder.rs b/src/bootstrap/builder.rs index 4f88b5854b692..0d387ff1e37c2 100644 --- a/src/bootstrap/builder.rs +++ b/src/bootstrap/builder.rs @@ -26,7 +26,7 @@ use crate::run; use crate::test; use crate::tool::{self, SourceType}; use crate::util::{self, add_dylib_path, add_link_lib_path, exe, libdir}; -use crate::{Build, DocTests, GitRepo, Mode}; +use crate::{Build, CLang, DocTests, GitRepo, Mode}; pub use crate::Compiler; // FIXME: replace with std::lazy after it gets stabilized and reaches beta @@ -1511,7 +1511,7 @@ impl<'a> Builder<'a> { let cc = ccacheify(&self.cc(target)); cargo.env(format!("CC_{}", target.triple), &cc); - let cflags = self.cflags(target, GitRepo::Rustc).join(" "); + let cflags = self.cflags(target, GitRepo::Rustc, CLang::C).join(" "); cargo.env(format!("CFLAGS_{}", target.triple), &cflags); if let Some(ar) = self.ar(target) { @@ -1523,9 +1523,10 @@ impl<'a> Builder<'a> { if let Ok(cxx) = self.cxx(target) { let cxx = ccacheify(&cxx); + let cxxflags = self.cflags(target, GitRepo::Rustc, CLang::Cxx).join(" "); cargo .env(format!("CXX_{}", target.triple), &cxx) - .env(format!("CXXFLAGS_{}", target.triple), cflags); + .env(format!("CXXFLAGS_{}", target.triple), cxxflags); } } diff --git a/src/bootstrap/cc_detect.rs b/src/bootstrap/cc_detect.rs index e750c2963dddc..8c47f625d732b 100644 --- a/src/bootstrap/cc_detect.rs +++ b/src/bootstrap/cc_detect.rs @@ -29,7 +29,7 @@ use std::{env, iter}; use build_helper::output; use crate::config::{Target, TargetSelection}; -use crate::{Build, GitRepo}; +use crate::{Build, CLang, GitRepo}; // The `cc` crate doesn't provide a way to obtain a path to the detected archiver, // so use some simplified logic here. First we respect the environment variable `AR`, then @@ -109,7 +109,7 @@ pub fn find(build: &mut Build) { }; build.cc.insert(target, compiler.clone()); - let cflags = build.cflags(target, GitRepo::Rustc); + let cflags = build.cflags(target, GitRepo::Rustc, CLang::C); // If we use llvm-libunwind, we will need a C++ compiler as well for all targets // We'll need one anyways if the target triple is also a host triple @@ -142,8 +142,9 @@ pub fn find(build: &mut Build) { build.verbose(&format!("CC_{} = {:?}", &target.triple, build.cc(target))); build.verbose(&format!("CFLAGS_{} = {:?}", &target.triple, cflags)); if let Ok(cxx) = build.cxx(target) { + let cxxflags = build.cflags(target, GitRepo::Rustc, CLang::Cxx); build.verbose(&format!("CXX_{} = {:?}", &target.triple, cxx)); - build.verbose(&format!("CXXFLAGS_{} = {:?}", &target.triple, cflags)); + build.verbose(&format!("CXXFLAGS_{} = {:?}", &target.triple, cxxflags)); } if let Some(ar) = ar { build.verbose(&format!("AR_{} = {:?}", &target.triple, ar)); diff --git a/src/bootstrap/compile.rs b/src/bootstrap/compile.rs index b4c6210b38814..9971778034601 100644 --- a/src/bootstrap/compile.rs +++ b/src/bootstrap/compile.rs @@ -28,7 +28,7 @@ use crate::native; use crate::tool::SourceType; use crate::util::{exe, is_debug_info, is_dylib, symlink_dir}; use crate::LLVM_TOOLS; -use crate::{Compiler, DependencyType, GitRepo, Mode}; +use crate::{CLang, Compiler, DependencyType, GitRepo, Mode}; #[derive(Debug, PartialOrd, Ord, Copy, Clone, PartialEq, Eq, Hash)] pub struct Std { @@ -249,7 +249,7 @@ fn copy_self_contained_objects( } } else if target.contains("windows-gnu") { for obj in ["crt2.o", "dllcrt2.o"].iter() { - let src = compiler_file(builder, builder.cc(target), target, obj); + let src = compiler_file(builder, builder.cc(target), target, CLang::C, obj); let target = libdir_self_contained.join(obj); builder.copy(&src, &target); target_deps.push((target, DependencyType::TargetSelfContained)); @@ -727,7 +727,13 @@ pub fn rustc_cargo_env(builder: &Builder<'_>, cargo: &mut Cargo, target: TargetS && !target.contains("msvc") && !target.contains("apple") { - let file = compiler_file(builder, builder.cxx(target).unwrap(), target, "libstdc++.a"); + let file = compiler_file( + builder, + builder.cxx(target).unwrap(), + target, + CLang::Cxx, + "libstdc++.a", + ); cargo.env("LLVM_STATIC_STDCPP", file); } if builder.config.llvm_link_shared { @@ -948,10 +954,11 @@ pub fn compiler_file( builder: &Builder<'_>, compiler: &Path, target: TargetSelection, + c: CLang, file: &str, ) -> PathBuf { let mut cmd = Command::new(compiler); - cmd.args(builder.cflags(target, GitRepo::Rustc)); + cmd.args(builder.cflags(target, GitRepo::Rustc, c)); cmd.arg(format!("-print-file-name={}", file)); let out = output(&mut cmd); PathBuf::from(out.trim()) diff --git a/src/bootstrap/format.rs b/src/bootstrap/format.rs index 30fe6a7a44695..530cc829320d1 100644 --- a/src/bootstrap/format.rs +++ b/src/bootstrap/format.rs @@ -97,7 +97,12 @@ pub fn format(build: &Build, check: bool, paths: &[PathBuf]) { }); for untracked_path in untracked_paths { eprintln!("skip untracked path {} during rustfmt invocations", untracked_path); - ignore_fmt.add(&format!("!{}", untracked_path)).expect(&untracked_path); + // The leading `/` makes it an exact match against the + // repository root, rather than a glob. Without that, if you + // have `foo.rs` in the repository root it will also match + // against anything like `compiler/rustc_foo/src/foo.rs`, + // preventing the latter from being formatted. + ignore_fmt.add(&format!("!/{}", untracked_path)).expect(&untracked_path); } } else { eprintln!("Not in git tree. Skipping git-aware format checks"); diff --git a/src/bootstrap/lib.rs b/src/bootstrap/lib.rs index 86339c8d7f88d..abfac2a589793 100644 --- a/src/bootstrap/lib.rs +++ b/src/bootstrap/lib.rs @@ -339,6 +339,11 @@ impl Mode { } } +pub enum CLang { + C, + Cxx, +} + impl Build { /// Creates a new set of build configuration from the `flags` on the command /// line and the filesystem `config`. @@ -941,10 +946,15 @@ impl Build { /// Returns a list of flags to pass to the C compiler for the target /// specified. - fn cflags(&self, target: TargetSelection, which: GitRepo) -> Vec { + fn cflags(&self, target: TargetSelection, which: GitRepo, c: CLang) -> Vec { + let base = match c { + CLang::C => &self.cc[&target], + CLang::Cxx => &self.cxx[&target], + }; + // Filter out -O and /O (the optimization flags) that we picked up from // cc-rs because the build scripts will determine that for themselves. - let mut base = self.cc[&target] + let mut base = base .args() .iter() .map(|s| s.to_string_lossy().into_owned()) diff --git a/src/bootstrap/native.rs b/src/bootstrap/native.rs index f00875239040d..a751a6e3ece7f 100644 --- a/src/bootstrap/native.rs +++ b/src/bootstrap/native.rs @@ -21,7 +21,7 @@ use build_helper::{output, t}; use crate::builder::{Builder, RunConfig, ShouldRun, Step}; use crate::config::TargetSelection; use crate::util::{self, exe}; -use crate::GitRepo; +use crate::{CLang, GitRepo}; use build_helper::up_to_date; pub struct Meta { @@ -529,7 +529,7 @@ fn configure_cmake( } cfg.build_arg("-j").build_arg(builder.jobs().to_string()); - let mut cflags: OsString = builder.cflags(target, GitRepo::Llvm).join(" ").into(); + let mut cflags: OsString = builder.cflags(target, GitRepo::Llvm, CLang::C).join(" ").into(); if let Some(ref s) = builder.config.llvm_cflags { cflags.push(" "); cflags.push(s); @@ -545,12 +545,8 @@ fn configure_cmake( if builder.config.llvm_clang_cl.is_some() { cflags.push(&format!(" --target={}", target)); } - if let Some(flags) = env::var_os("CFLAGS") { - cflags.push(" "); - cflags.push(flags); - } cfg.define("CMAKE_C_FLAGS", cflags); - let mut cxxflags: OsString = builder.cflags(target, GitRepo::Llvm).join(" ").into(); + let mut cxxflags: OsString = builder.cflags(target, GitRepo::Llvm, CLang::Cxx).join(" ").into(); if let Some(ref s) = builder.config.llvm_cxxflags { cxxflags.push(" "); cxxflags.push(s); @@ -558,10 +554,6 @@ fn configure_cmake( if builder.config.llvm_clang_cl.is_some() { cxxflags.push(&format!(" --target={}", target)); } - if let Some(flags) = env::var_os("CXXFLAGS") { - cxxflags.push(" "); - cxxflags.push(flags); - } cfg.define("CMAKE_CXX_FLAGS", cxxflags); if let Some(ar) = builder.ar(target) { if ar.is_absolute() { @@ -583,7 +575,7 @@ fn configure_cmake( ldflags.push_all(flags); } - if let Some(flags) = env::var_os("LDFLAGS") { + if let Some(flags) = get_var("LDFLAGS", &builder.config.build.triple, &target.triple) { ldflags.push_all(&flags); } @@ -596,6 +588,16 @@ fn configure_cmake( } } +// Adapted from https://github.com/alexcrichton/cc-rs/blob/fba7feded71ee4f63cfe885673ead6d7b4f2f454/src/lib.rs#L2347-L2365 +fn get_var(var_base: &str, host: &str, target: &str) -> Option { + let kind = if host == target { "HOST" } else { "TARGET" }; + let target_u = target.replace("-", "_"); + env::var_os(&format!("{}_{}", var_base, target)) + .or_else(|| env::var_os(&format!("{}_{}", var_base, target_u))) + .or_else(|| env::var_os(&format!("{}_{}", kind, var_base))) + .or_else(|| env::var_os(var_base)) +} + #[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] pub struct Lld { pub target: TargetSelection, diff --git a/src/bootstrap/test.rs b/src/bootstrap/test.rs index 176c06114e01d..19d98df3ce902 100644 --- a/src/bootstrap/test.rs +++ b/src/bootstrap/test.rs @@ -24,7 +24,7 @@ use crate::tool::{self, SourceType, Tool}; use crate::toolstate::ToolState; use crate::util::{self, add_link_lib_path, dylib_path, dylib_path_var}; use crate::Crate as CargoCrate; -use crate::{envify, DocTests, GitRepo, Mode}; +use crate::{envify, CLang, DocTests, GitRepo, Mode}; const ADB_TEST_DIR: &str = "/data/tmp/work"; @@ -1509,7 +1509,9 @@ note: if you're sure you want to do this, please open an issue as to why. In the .arg("--cxx") .arg(builder.cxx(target).unwrap()) .arg("--cflags") - .arg(builder.cflags(target, GitRepo::Rustc).join(" ")); + .arg(builder.cflags(target, GitRepo::Rustc, CLang::C).join(" ")) + .arg("--cxxflags") + .arg(builder.cflags(target, GitRepo::Rustc, CLang::Cxx).join(" ")); copts_passed = true; if let Some(ar) = builder.ar(target) { cmd.arg("--ar").arg(ar); @@ -1520,7 +1522,14 @@ note: if you're sure you want to do this, please open an issue as to why. In the cmd.arg("--llvm-components").arg(""); } if !copts_passed { - cmd.arg("--cc").arg("").arg("--cxx").arg("").arg("--cflags").arg(""); + cmd.arg("--cc") + .arg("") + .arg("--cxx") + .arg("") + .arg("--cflags") + .arg("") + .arg("--cxxflags") + .arg(""); } if builder.remote_tested(target) { diff --git a/src/doc/favicon.inc b/src/doc/favicon.inc index 8f881657bdc1a..9c330685209be 100644 --- a/src/doc/favicon.inc +++ b/src/doc/favicon.inc @@ -1 +1 @@ - + diff --git a/src/doc/redirect.inc b/src/doc/redirect.inc index 33e3860c2a434..2fb44be014515 100644 --- a/src/doc/redirect.inc +++ b/src/doc/redirect.inc @@ -1,2 +1,2 @@ - + diff --git a/src/doc/rustdoc/src/the-doc-attribute.md b/src/doc/rustdoc/src/the-doc-attribute.md index a75b6d3893128..c5cc84022e389 100644 --- a/src/doc/rustdoc/src/the-doc-attribute.md +++ b/src/doc/rustdoc/src/the-doc-attribute.md @@ -59,7 +59,7 @@ This form of the `doc` attribute lets you control the favicon of your docs. #![doc(html_favicon_url = "https://example.com/favicon.ico")] ``` -This will put `` into your docs, where +This will put `` into your docs, where the string for the attribute goes into the `{}`. If you don't use this attribute, there will be no favicon. diff --git a/src/librustdoc/html/templates/page.html b/src/librustdoc/html/templates/page.html index baadd3c27b446..564731ab7354b 100644 --- a/src/librustdoc/html/templates/page.html +++ b/src/librustdoc/html/templates/page.html @@ -54,7 +54,7 @@ href="{{static_root_path|safe}}theme{{page.resource_suffix}}.css"> {#- -#} {%- endif -%} {%- if !layout.favicon.is_empty() -%} - {#- -#} + {#- -#} {%- else -%} {#- -#} diff --git a/src/test/ui/lint/issue-87308.rs b/src/test/ui/lint/issue-87308.rs deleted file mode 100644 index 48fbb2a0139f0..0000000000000 --- a/src/test/ui/lint/issue-87308.rs +++ /dev/null @@ -1,12 +0,0 @@ -// Regression test for issue #87308. - -// compile-flags: -Zunpretty=everybody_loops -// check-pass - -macro_rules! foo { - () => { break 'x; } -} - -pub fn main() { - 'x: loop { foo!() } -} diff --git a/src/test/ui/lint/issue-87308.stdout b/src/test/ui/lint/issue-87308.stdout deleted file mode 100644 index 4f81ee8b7e6bb..0000000000000 --- a/src/test/ui/lint/issue-87308.stdout +++ /dev/null @@ -1,14 +0,0 @@ -#![feature(prelude_import)] -#![no_std] -#[prelude_import] -use ::std::prelude::rust_2015::*; -#[macro_use] -extern crate std; -// Regression test for issue #87308. - -// compile-flags: -Zunpretty=everybody_loops -// check-pass - -macro_rules! foo { () => { break 'x ; } } - -pub fn main() { loop {} } diff --git a/src/test/ui/repr/issue-83921-pretty.normal.stderr b/src/test/ui/repr/issue-83921-pretty.normal.stderr deleted file mode 100644 index 6b7e831ed2f7a..0000000000000 --- a/src/test/ui/repr/issue-83921-pretty.normal.stderr +++ /dev/null @@ -1,9 +0,0 @@ -error[E0565]: meta item in `repr` must be an identifier - --> $DIR/issue-83921-pretty.rs:10:8 - | -LL | #[repr("C")] - | ^^^ - -error: aborting due to previous error - -For more information about this error, try `rustc --explain E0565`. diff --git a/src/test/ui/repr/issue-83921-pretty.pretty.stdout b/src/test/ui/repr/issue-83921-pretty.pretty.stdout deleted file mode 100644 index aaf3993538acf..0000000000000 --- a/src/test/ui/repr/issue-83921-pretty.pretty.stdout +++ /dev/null @@ -1,18 +0,0 @@ -#![feature(prelude_import)] -#![no_std] -#[prelude_import] -use ::std::prelude::rust_2015::*; -#[macro_use] -extern crate std; -// Regression test for #83921. A `delay_span_bug()` call was issued, but the -// error was never reported because the pass responsible for detecting and -// reporting the error does not run in certain modes of pretty-printing. - -// Make sure the error is reported if we do not just pretty-print: -// revisions: pretty normal -// [pretty]compile-flags: -Zunpretty=everybody_loops -// [pretty]check-pass -#[repr("C")] -struct A {} - -fn main() { loop {} } diff --git a/src/test/ui/repr/issue-83921-pretty.rs b/src/test/ui/repr/issue-83921-pretty.rs deleted file mode 100644 index d5d36470f11ac..0000000000000 --- a/src/test/ui/repr/issue-83921-pretty.rs +++ /dev/null @@ -1,14 +0,0 @@ -// Regression test for #83921. A `delay_span_bug()` call was issued, but the -// error was never reported because the pass responsible for detecting and -// reporting the error does not run in certain modes of pretty-printing. - -// Make sure the error is reported if we do not just pretty-print: -// revisions: pretty normal -// [pretty]compile-flags: -Zunpretty=everybody_loops -// [pretty]check-pass - -#[repr("C")] -//[normal]~^ ERROR: meta item in `repr` must be an identifier [E0565] -struct A {} - -fn main() {} diff --git a/src/tools/compiletest/src/common.rs b/src/tools/compiletest/src/common.rs index 82fe790a576ab..1bf6e6d011e5c 100644 --- a/src/tools/compiletest/src/common.rs +++ b/src/tools/compiletest/src/common.rs @@ -357,6 +357,7 @@ pub struct Config { pub cc: String, pub cxx: String, pub cflags: String, + pub cxxflags: String, pub ar: String, pub linker: Option, pub llvm_components: String, diff --git a/src/tools/compiletest/src/header/tests.rs b/src/tools/compiletest/src/header/tests.rs index 157b42e2d17f5..5b144a1020f4c 100644 --- a/src/tools/compiletest/src/header/tests.rs +++ b/src/tools/compiletest/src/header/tests.rs @@ -52,6 +52,7 @@ fn config() -> Config { "--cc=c", "--cxx=c++", "--cflags=", + "--cxxflags=", "--llvm-components=", "--android-cross-path=", "--target=x86_64-unknown-linux-gnu", diff --git a/src/tools/compiletest/src/main.rs b/src/tools/compiletest/src/main.rs index 58cde108b3322..3f2cd3ae232ba 100644 --- a/src/tools/compiletest/src/main.rs +++ b/src/tools/compiletest/src/main.rs @@ -126,6 +126,7 @@ pub fn parse_config(args: Vec) -> Config { .reqopt("", "cc", "path to a C compiler", "PATH") .reqopt("", "cxx", "path to a C++ compiler", "PATH") .reqopt("", "cflags", "flags for the C compiler", "FLAGS") + .reqopt("", "cxxflags", "flags for the CXX compiler", "FLAGS") .optopt("", "ar", "path to an archiver", "PATH") .optopt("", "linker", "path to a linker", "PATH") .reqopt("", "llvm-components", "list of LLVM components built in", "LIST") @@ -288,6 +289,7 @@ pub fn parse_config(args: Vec) -> Config { cc: matches.opt_str("cc").unwrap(), cxx: matches.opt_str("cxx").unwrap(), cflags: matches.opt_str("cflags").unwrap(), + cxxflags: matches.opt_str("cxxflags").unwrap(), ar: matches.opt_str("ar").unwrap_or_else(|| String::from("ar")), linker: matches.opt_str("linker"), llvm_components: matches.opt_str("llvm-components").unwrap(), diff --git a/src/tools/compiletest/src/runtest.rs b/src/tools/compiletest/src/runtest.rs index 3f67a64971b67..8431aa7b818df 100644 --- a/src/tools/compiletest/src/runtest.rs +++ b/src/tools/compiletest/src/runtest.rs @@ -2919,15 +2919,22 @@ impl<'test> TestCx<'test> { .map(|s| s.replace("/", "-")) .collect::>() .join(" "); + let cxxflags = self + .config + .cxxflags + .split(' ') + .map(|s| s.replace("/", "-")) + .collect::>() + .join(" "); cmd.env("IS_MSVC", "1") .env("IS_WINDOWS", "1") .env("MSVC_LIB", format!("'{}' -nologo", lib.display())) .env("CC", format!("'{}' {}", self.config.cc, cflags)) - .env("CXX", format!("'{}'", &self.config.cxx)); + .env("CXX", format!("'{}' {}", &self.config.cxx, cxxflags)); } else { cmd.env("CC", format!("{} {}", self.config.cc, self.config.cflags)) - .env("CXX", format!("{} {}", self.config.cxx, self.config.cflags)) + .env("CXX", format!("{} {}", self.config.cxx, self.config.cxxflags)) .env("AR", &self.config.ar); if self.config.target.contains("windows") {