mirror of
https://github.com/rust-lang/rust.git
synced 2025-02-03 18:43:38 +00:00
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:
commit
8fa5d74a7c
@ -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>)] = &[
|
||||
|
@ -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,
|
||||
|
@ -42,7 +42,7 @@ where
|
||||
F: FnOnce(&dyn PrinterSupport) -> A,
|
||||
{
|
||||
match *ppmode {
|
||||
Normal | EveryBodyLoops | Expanded => {
|
||||
Normal | Expanded => {
|
||||
let annotation = NoAnn { sess, tcx };
|
||||
f(&annotation)
|
||||
}
|
||||
|
@ -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| {
|
||||
|
@ -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")
|
||||
|
@ -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]
|
||||
|
@ -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
|
||||
|
@ -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`,
|
||||
|
@ -539,6 +539,7 @@ symbols! {
|
||||
custom_inner_attributes,
|
||||
custom_test_frameworks,
|
||||
d,
|
||||
d32,
|
||||
dbg_macro,
|
||||
dead_code,
|
||||
dealloc,
|
||||
|
@ -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);
|
||||
},
|
||||
|
@ -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
|
||||
|
@ -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},
|
||||
|
@ -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")]
|
||||
|
@ -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.
|
||||
|
@ -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")]
|
||||
|
||||
|
@ -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,
|
||||
|
@ -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;
|
||||
|
@ -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())
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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,
|
||||
|
@ -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 {
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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));
|
||||
|
@ -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())
|
||||
|
@ -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");
|
||||
|
@ -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())
|
||||
|
@ -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,
|
||||
|
@ -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) {
|
||||
|
@ -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">
|
||||
|
@ -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">
|
||||
|
@ -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.
|
||||
|
@ -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"> {#- -#}
|
||||
|
@ -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!() }
|
||||
}
|
@ -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 {} }
|
@ -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`.
|
@ -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 {} }
|
@ -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() {}
|
@ -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,
|
||||
|
@ -52,6 +52,7 @@ fn config() -> Config {
|
||||
"--cc=c",
|
||||
"--cxx=c++",
|
||||
"--cflags=",
|
||||
"--cxxflags=",
|
||||
"--llvm-components=",
|
||||
"--android-cross-path=",
|
||||
"--target=x86_64-unknown-linux-gnu",
|
||||
|
@ -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(),
|
||||
|
@ -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") {
|
||||
|
Loading…
Reference in New Issue
Block a user