Auto merge of #94588 - Dylan-DPC:rollup-7pxd0i3, r=Dylan-DPC

Rollup of 10 pull requests

Successful merges:

 - #88805 (Clarification of default socket flags)
 - #93418 (rustdoc & doc: no `shortcut` for `rel="icon"`)
 - #93913 (Remove the everybody loops pass)
 - #93965 (Make regular stdio lock() return 'static handles)
 - #94339 (ARM: Only allow using d16-d31 with asm! when supported by the target)
 - #94404 (Make Ord and PartialOrd opt-out in `newtype_index`)
 - #94466 (bootstrap: correct reading of flags for llvm)
 - #94572 (Use `HandleOrNull` and `HandleOrInvalid` in the Windows FFI bindings.)
 - #94575 (CTFE SwitchInt: update comment)
 - #94582 (Fix a bug in `x.py fmt` that prevents some files being formatted.)

Failed merges:

r? `@ghost`
`@rustbot` modify labels: rollup
This commit is contained in:
bors 2022-03-04 02:53:40 +00:00
commit 8fa5d74a7c
40 changed files with 190 additions and 614 deletions

View File

@ -39,6 +39,7 @@ const ARM_ALLOWED_FEATURES: &[(&str, Option<Symbol>)] = &[
// #[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<Symbol>)] = &[

View File

@ -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,

View File

@ -42,7 +42,7 @@ where
F: FnOnce(&dyn PrinterSupport) -> A,
{
match *ppmode {
Normal | EveryBodyLoops | Expanded => {
Normal | Expanded => {
let annotation = NoAnn { sess, tcx };
f(&annotation)
}

View File

@ -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| {

View File

@ -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<Vec<ast::Block>>,
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, F: FnOnce(&mut Self) -> 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<Item = &'a P<ast::Ty>>>(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<ast::AssocItem>) -> SmallVec<[P<ast::AssocItem>; 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<ast::AssocItem>) -> SmallVec<[P<ast::AssocItem>; 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<ast::Block>) {
fn stmt_to_block(
rules: ast::BlockCheckMode,
s: Option<ast::Stmt>,
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")

View File

@ -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::<kw::ORD_IMPL>()?;
body.parse::<Token![=]>()?;
body.parse::<kw::custom>()?;
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::<Token![const]>()?;
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<usize> {
<usize as ::std::iter::Step>::steps_between(
&Self::index(*start),
&Self::index(*end),
)
}
#[inline]
fn forward_checked(start: Self, u: usize) -> Option<Self> {
Self::index(start).checked_add(u).map(Self::from_usize)
}
#[inline]
fn backward_checked(start: Self, u: usize) -> Option<Self> {
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<usize> {
<usize as ::std::iter::Step>::steps_between(
&Self::index(*start),
&Self::index(*end),
)
}
#[inline]
fn forward_checked(start: Self, u: usize) -> Option<Self> {
Self::index(start).checked_add(u).map(Self::from_usize)
}
#[inline]
fn backward_checked(start: Self, u: usize) -> Option<Self> {
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]

View File

@ -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

View File

@ -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`,

View File

@ -539,6 +539,7 @@ symbols! {
custom_inner_attributes,
custom_test_frameworks,
d,
d32,
dbg_macro,
dead_code,
dealloc,

View File

@ -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);
},

View File

@ -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

View File

@ -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},

View File

@ -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<StdinLock<'static>> {
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")]

View File

@ -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.

View File

@ -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")]

View File

@ -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,

View File

@ -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;

View File

@ -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())
}
}

View File

@ -78,7 +78,7 @@ impl Handle {
let len = cmp::min(buf.len(), <c::DWORD>::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(), <c::DWORD>::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(), <c::DWORD>::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(), <c::DWORD>::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,

View File

@ -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 {

View File

@ -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);
}
}

View File

@ -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));

View File

@ -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())

View File

@ -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");

View File

@ -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<String> {
fn cflags(&self, target: TargetSelection, which: GitRepo, c: CLang) -> Vec<String> {
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())

View File

@ -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<OsString> {
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,

View File

@ -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) {

View File

@ -1 +1 @@
<link rel="shortcut icon" href="https://www.rust-lang.org/favicon.ico">
<link rel="icon" href="https://www.rust-lang.org/favicon.ico">

View File

@ -1,2 +1,2 @@
<meta name="robots" content="noindex,follow">
<link rel="shortcut icon" href="https://www.rust-lang.org/favicon.ico">
<link rel="icon" href="https://www.rust-lang.org/favicon.ico">

View File

@ -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 `<link rel="shortcut icon" href="{}">` into your docs, where
This will put `<link rel="icon" href="{}">` into your docs, where
the string for the attribute goes into the `{}`.
If you don't use this attribute, there will be no favicon.

View File

@ -54,7 +54,7 @@
href="{{static_root_path|safe}}theme{{page.resource_suffix}}.css"> {#- -#}
{%- endif -%}
{%- if !layout.favicon.is_empty() -%}
<link rel="shortcut icon" href="{{layout.favicon}}"> {#- -#}
<link rel="icon" href="{{layout.favicon}}"> {#- -#}
{%- else -%}
<link rel="alternate icon" type="image/png" {# -#}
href="{{static_root_path|safe}}favicon-16x16{{page.resource_suffix}}.png"> {#- -#}

View File

@ -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!() }
}

View File

@ -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 {} }

View File

@ -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`.

View File

@ -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 {} }

View File

@ -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() {}

View File

@ -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<String>,
pub llvm_components: String,

View File

@ -52,6 +52,7 @@ fn config() -> Config {
"--cc=c",
"--cxx=c++",
"--cflags=",
"--cxxflags=",
"--llvm-components=",
"--android-cross-path=",
"--target=x86_64-unknown-linux-gnu",

View File

@ -126,6 +126,7 @@ pub fn parse_config(args: Vec<String>) -> 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<String>) -> 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(),

View File

@ -2919,15 +2919,22 @@ impl<'test> TestCx<'test> {
.map(|s| s.replace("/", "-"))
.collect::<Vec<_>>()
.join(" ");
let cxxflags = self
.config
.cxxflags
.split(' ')
.map(|s| s.replace("/", "-"))
.collect::<Vec<_>>()
.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") {