Auto merge of #74422 - Manishearth:rollup-7mfrf6g, r=Manishearth

Rollup of 8 pull requests

Successful merges:

 - #73101 (Resolve items for cross-crate imports relative to the original module)
 - #73269 (Enable some timeouts in SGX platform)
 - #74033 (Add build support for Cargo's build-std feature.)
 - #74351 (Do not render unstable items for rustc doc)
 - #74357 (Some `Symbol` related improvements)
 - #74371 (Improve ayu rustdoc theme)
 - #74386 (Add RISC-V GNU/Linux to src/tools/build-manifest as a host platform)
 - #74398 (Clean up E0723 explanation)

Failed merges:

r? @ghost
This commit is contained in:
bors 2020-07-17 00:09:49 +00:00
commit 8534be72fc
113 changed files with 1314 additions and 804 deletions

View File

@ -2056,6 +2056,7 @@ dependencies = [
name = "panic_abort"
version = "0.0.0"
dependencies = [
"cfg-if",
"compiler_builtins",
"core",
"libc",
@ -4552,6 +4553,7 @@ dependencies = [
name = "test"
version = "0.0.0"
dependencies = [
"cfg-if",
"core",
"getopts",
"libc",

View File

@ -11,6 +11,7 @@ bench = false
doc = false
[dependencies]
cfg-if = { version = "0.1.8", features = ['rustc-dep-of-std'] }
core = { path = "../libcore" }
libc = { version = "0.2", default-features = false }
compiler_builtins = "0.1.0"

View File

@ -40,23 +40,26 @@ pub unsafe extern "C" fn __rust_panic_cleanup(_: *mut u8) -> *mut (dyn Any + Sen
pub unsafe extern "C" fn __rust_start_panic(_payload: usize) -> u32 {
abort();
#[cfg(any(unix, target_os = "cloudabi"))]
unsafe fn abort() -> ! {
libc::abort();
}
#[cfg(any(windows, all(target_arch = "wasm32", not(target_os = "emscripten"))))]
unsafe fn abort() -> ! {
core::intrinsics::abort();
}
#[cfg(any(target_os = "hermit", all(target_vendor = "fortanix", target_env = "sgx")))]
unsafe fn abort() -> ! {
// call std::sys::abort_internal
extern "C" {
pub fn __rust_abort() -> !;
cfg_if::cfg_if! {
if #[cfg(any(unix, target_os = "cloudabi"))] {
unsafe fn abort() -> ! {
libc::abort();
}
} else if #[cfg(any(target_os = "hermit",
all(target_vendor = "fortanix", target_env = "sgx")
))] {
unsafe fn abort() -> ! {
// call std::sys::abort_internal
extern "C" {
pub fn __rust_abort() -> !;
}
__rust_abort();
}
} else {
unsafe fn abort() -> ! {
core::intrinsics::abort();
}
}
__rust_abort();
}
}

View File

@ -41,21 +41,33 @@ cfg_if::cfg_if! {
if #[cfg(target_os = "emscripten")] {
#[path = "emcc.rs"]
mod real_imp;
} else if #[cfg(target_arch = "wasm32")] {
#[path = "dummy.rs"]
mod real_imp;
} else if #[cfg(target_os = "hermit")] {
#[path = "hermit.rs"]
mod real_imp;
} else if #[cfg(target_env = "msvc")] {
#[path = "seh.rs"]
mod real_imp;
} else {
} else if #[cfg(any(
all(target_family = "windows", target_env = "gnu"),
target_os = "cloudabi",
target_family = "unix",
all(target_vendor = "fortanix", target_env = "sgx"),
))] {
// Rust runtime's startup objects depend on these symbols, so make them public.
#[cfg(all(target_os="windows", target_arch = "x86", target_env="gnu"))]
pub use real_imp::eh_frame_registry::*;
#[path = "gcc.rs"]
mod real_imp;
} else {
// Targets that don't support unwinding.
// - arch=wasm32
// - os=none ("bare metal" targets)
// - os=uefi
// - nvptx64-nvidia-cuda
// - avr-unknown-unknown
// - mipsel-sony-psp
#[path = "dummy.rs"]
mod real_imp;
}
}

View File

@ -26,6 +26,7 @@
#![feature(in_band_lifetimes)]
#![feature(negative_impls)]
#![feature(optin_builtin_traits)]
#![feature(restricted_std)]
#![feature(rustc_attrs)]
#![feature(min_specialization)]
#![recursion_limit = "256"]

View File

@ -16,9 +16,9 @@ pub fn expand_deriving_copy(
let trait_def = TraitDef {
span,
attributes: Vec::new(),
path: path_std!(cx, marker::Copy),
path: path_std!(marker::Copy),
additional_bounds: Vec::new(),
generics: LifetimeBounds::empty(),
generics: Bounds::empty(),
is_unsafe: false,
supports_unions: true,
methods: Vec::new(),

View File

@ -56,7 +56,7 @@ pub fn expand_deriving_clone(
}
}
ItemKind::Union(..) => {
bounds = vec![Literal(path_std!(cx, marker::Copy))];
bounds = vec![Literal(path_std!(marker::Copy))];
is_shallow = true;
substructure = combine_substructure(Box::new(|c, s, sub| {
cs_clone_shallow("Clone", c, s, sub, true)
@ -78,14 +78,14 @@ pub fn expand_deriving_clone(
let trait_def = TraitDef {
span,
attributes: Vec::new(),
path: path_std!(cx, clone::Clone),
path: path_std!(clone::Clone),
additional_bounds: bounds,
generics: LifetimeBounds::empty(),
generics: Bounds::empty(),
is_unsafe: false,
supports_unions: true,
methods: vec![MethodDef {
name: sym::clone,
generics: LifetimeBounds::empty(),
generics: Bounds::empty(),
explicit_self: borrowed_explicit_self(),
args: Vec::new(),
ret_ty: Self_,

View File

@ -22,14 +22,14 @@ pub fn expand_deriving_eq(
let trait_def = TraitDef {
span,
attributes: Vec::new(),
path: path_std!(cx, cmp::Eq),
path: path_std!(cmp::Eq),
additional_bounds: Vec::new(),
generics: LifetimeBounds::empty(),
generics: Bounds::empty(),
is_unsafe: false,
supports_unions: true,
methods: vec![MethodDef {
name: sym::assert_receiver_is_total_eq,
generics: LifetimeBounds::empty(),
generics: Bounds::empty(),
explicit_self: borrowed_explicit_self(),
args: vec![],
ret_ty: nil_ty(),
@ -43,13 +43,7 @@ pub fn expand_deriving_eq(
associated_types: Vec::new(),
};
super::inject_impl_of_structural_trait(
cx,
span,
item,
path_std!(cx, marker::StructuralEq),
push,
);
super::inject_impl_of_structural_trait(cx, span, item, path_std!(marker::StructuralEq), push);
trait_def.expand_ext(cx, mitem, item, push, true)
}

View File

@ -20,17 +20,17 @@ pub fn expand_deriving_ord(
let trait_def = TraitDef {
span,
attributes: Vec::new(),
path: path_std!(cx, cmp::Ord),
path: path_std!(cmp::Ord),
additional_bounds: Vec::new(),
generics: LifetimeBounds::empty(),
generics: Bounds::empty(),
is_unsafe: false,
supports_unions: false,
methods: vec![MethodDef {
name: sym::cmp,
generics: LifetimeBounds::empty(),
generics: Bounds::empty(),
explicit_self: borrowed_explicit_self(),
args: vec![(borrowed_self(), "other")],
ret_ty: Literal(path_std!(cx, cmp::Ordering)),
args: vec![(borrowed_self(), sym::other)],
ret_ty: Literal(path_std!(cmp::Ordering)),
attributes: attrs,
is_unsafe: false,
unify_fieldless_variants: true,

View File

@ -69,9 +69,9 @@ pub fn expand_deriving_partial_eq(
let attrs = vec![cx.attribute(inline)];
MethodDef {
name: $name,
generics: LifetimeBounds::empty(),
generics: Bounds::empty(),
explicit_self: borrowed_explicit_self(),
args: vec![(borrowed_self(), "other")],
args: vec![(borrowed_self(), sym::other)],
ret_ty: Literal(path_local!(bool)),
attributes: attrs,
is_unsafe: false,
@ -85,7 +85,7 @@ pub fn expand_deriving_partial_eq(
cx,
span,
item,
path_std!(cx, marker::StructuralPartialEq),
path_std!(marker::StructuralPartialEq),
push,
);
@ -100,9 +100,9 @@ pub fn expand_deriving_partial_eq(
let trait_def = TraitDef {
span,
attributes: Vec::new(),
path: path_std!(cx, cmp::PartialEq),
path: path_std!(cmp::PartialEq),
additional_bounds: Vec::new(),
generics: LifetimeBounds::empty(),
generics: Bounds::empty(),
is_unsafe: false,
supports_unions: false,
methods,

View File

@ -23,9 +23,9 @@ pub fn expand_deriving_partial_ord(
let attrs = vec![cx.attribute(inline)];
MethodDef {
name: $name,
generics: LifetimeBounds::empty(),
generics: Bounds::empty(),
explicit_self: borrowed_explicit_self(),
args: vec![(borrowed_self(), "other")],
args: vec![(borrowed_self(), sym::other)],
ret_ty: Literal(path_local!(bool)),
attributes: attrs,
is_unsafe: false,
@ -37,9 +37,9 @@ pub fn expand_deriving_partial_ord(
}};
}
let ordering_ty = Literal(path_std!(cx, cmp::Ordering));
let ordering_ty = Literal(path_std!(cmp::Ordering));
let ret_ty = Literal(Path::new_(
pathvec_std!(cx, option::Option),
pathvec_std!(option::Option),
None,
vec![Box::new(ordering_ty)],
PathKind::Std,
@ -50,9 +50,9 @@ pub fn expand_deriving_partial_ord(
let partial_cmp_def = MethodDef {
name: sym::partial_cmp,
generics: LifetimeBounds::empty(),
generics: Bounds::empty(),
explicit_self: borrowed_explicit_self(),
args: vec![(borrowed_self(), "other")],
args: vec![(borrowed_self(), sym::other)],
ret_ty,
attributes: attrs,
is_unsafe: false,
@ -80,9 +80,9 @@ pub fn expand_deriving_partial_ord(
let trait_def = TraitDef {
span,
attributes: vec![],
path: path_std!(cx, cmp::PartialOrd),
path: path_std!(cmp::PartialOrd),
additional_bounds: vec![],
generics: LifetimeBounds::empty(),
generics: Bounds::empty(),
is_unsafe: false,
supports_unions: false,
methods,

View File

@ -18,22 +18,22 @@ pub fn expand_deriving_debug(
) {
// &mut ::std::fmt::Formatter
let fmtr =
Ptr(Box::new(Literal(path_std!(cx, fmt::Formatter))), Borrowed(None, ast::Mutability::Mut));
Ptr(Box::new(Literal(path_std!(fmt::Formatter))), Borrowed(None, ast::Mutability::Mut));
let trait_def = TraitDef {
span,
attributes: Vec::new(),
path: path_std!(cx, fmt::Debug),
path: path_std!(fmt::Debug),
additional_bounds: Vec::new(),
generics: LifetimeBounds::empty(),
generics: Bounds::empty(),
is_unsafe: false,
supports_unions: false,
methods: vec![MethodDef {
name: sym::fmt,
generics: LifetimeBounds::empty(),
generics: Bounds::empty(),
explicit_self: borrowed_explicit_self(),
args: vec![(fmtr, "f")],
ret_ty: Literal(path_std!(cx, fmt::Result)),
args: vec![(fmtr, sym::f)],
ret_ty: Literal(path_std!(fmt::Result)),
attributes: Vec::new(),
is_unsafe: false,
unify_fieldless_variants: false,
@ -62,7 +62,7 @@ fn show_substructure(cx: &mut ExtCtxt<'_>, span: Span, substr: &Substructure<'_>
// We want to make sure we have the ctxt set so that we can use unstable methods
let span = cx.with_def_site_ctxt(span);
let name = cx.expr_lit(span, ast::LitKind::Str(ident.name, ast::StrStyle::Cooked));
let builder = cx.ident_of("debug_trait_builder", span);
let builder = Ident::new(sym::debug_trait_builder, span);
let builder_expr = cx.expr_ident(span, builder);
let fmt = substr.nonself_args[0].clone();
@ -71,7 +71,8 @@ fn show_substructure(cx: &mut ExtCtxt<'_>, span: Span, substr: &Substructure<'_>
match vdata {
ast::VariantData::Tuple(..) | ast::VariantData::Unit(..) => {
// tuple struct/"normal" variant
let expr = cx.expr_method_call(span, fmt, cx.ident_of("debug_tuple", span), vec![name]);
let expr =
cx.expr_method_call(span, fmt, Ident::new(sym::debug_tuple, span), vec![name]);
stmts.push(cx.stmt_let(span, true, builder, expr));
for field in fields {
@ -94,7 +95,7 @@ fn show_substructure(cx: &mut ExtCtxt<'_>, span: Span, substr: &Substructure<'_>
ast::VariantData::Struct(..) => {
// normal struct/struct variant
let expr =
cx.expr_method_call(span, fmt, cx.ident_of("debug_struct", span), vec![name]);
cx.expr_method_call(span, fmt, Ident::new(sym::debug_struct, span), vec![name]);
stmts.push(cx.stmt_let(DUMMY_SP, true, builder, expr));
for field in fields {
@ -117,7 +118,7 @@ fn show_substructure(cx: &mut ExtCtxt<'_>, span: Span, substr: &Substructure<'_>
}
}
let expr = cx.expr_method_call(span, builder_expr, cx.ident_of("finish", span), vec![]);
let expr = cx.expr_method_call(span, builder_expr, Ident::new(sym::finish, span), vec![]);
stmts.push(cx.stmt_expr(expr));
let block = cx.block(span, stmts);

View File

@ -8,7 +8,7 @@ use rustc_ast::ast;
use rustc_ast::ast::{Expr, MetaItem, Mutability};
use rustc_ast::ptr::P;
use rustc_expand::base::{Annotatable, ExtCtxt};
use rustc_span::symbol::{sym, Symbol};
use rustc_span::symbol::{sym, Ident, Symbol};
use rustc_span::Span;
pub fn expand_deriving_rustc_decodable(
@ -18,38 +18,37 @@ pub fn expand_deriving_rustc_decodable(
item: &Annotatable,
push: &mut dyn FnMut(Annotatable),
) {
let krate = "rustc_serialize";
let typaram = "__D";
let krate = sym::rustc_serialize;
let typaram = sym::__D;
let trait_def = TraitDef {
span,
attributes: Vec::new(),
path: Path::new_(vec![krate, "Decodable"], None, vec![], PathKind::Global),
path: Path::new_(vec![krate, sym::Decodable], None, vec![], PathKind::Global),
additional_bounds: Vec::new(),
generics: LifetimeBounds::empty(),
generics: Bounds::empty(),
is_unsafe: false,
supports_unions: false,
methods: vec![MethodDef {
name: sym::decode,
generics: LifetimeBounds {
lifetimes: Vec::new(),
generics: Bounds {
bounds: vec![(
typaram,
vec![Path::new_(vec![krate, "Decoder"], None, vec![], PathKind::Global)],
vec![Path::new_(vec![krate, sym::Decoder], None, vec![], PathKind::Global)],
)],
},
explicit_self: None,
args: vec![(
Ptr(Box::new(Literal(Path::new_local(typaram))), Borrowed(None, Mutability::Mut)),
"d",
sym::d,
)],
ret_ty: Literal(Path::new_(
pathvec_std!(cx, result::Result),
pathvec_std!(result::Result),
None,
vec![
Box::new(Self_),
Box::new(Literal(Path::new_(
vec![typaram, "Error"],
vec![typaram, sym::Error],
None,
vec![],
PathKind::Local,
@ -74,17 +73,17 @@ fn decodable_substructure(
cx: &mut ExtCtxt<'_>,
trait_span: Span,
substr: &Substructure<'_>,
krate: &str,
krate: Symbol,
) -> P<Expr> {
let decoder = substr.nonself_args[0].clone();
let recurse = vec![
cx.ident_of(krate, trait_span),
cx.ident_of("Decodable", trait_span),
cx.ident_of("decode", trait_span),
Ident::new(krate, trait_span),
Ident::new(sym::Decodable, trait_span),
Ident::new(sym::decode, trait_span),
];
let exprdecode = cx.expr_path(cx.path_global(trait_span, recurse));
// throw an underscore in front to suppress unused variable warnings
let blkarg = cx.ident_of("_d", trait_span);
let blkarg = Ident::new(sym::_d, trait_span);
let blkdecoder = cx.expr_ident(trait_span, blkarg);
match *substr.fields {
@ -93,7 +92,7 @@ fn decodable_substructure(
Unnamed(ref fields, _) => fields.len(),
Named(ref fields) => fields.len(),
};
let read_struct_field = cx.ident_of("read_struct_field", trait_span);
let read_struct_field = Ident::new(sym::read_struct_field, trait_span);
let path = cx.path_ident(trait_span, substr.type_ident);
let result =
@ -116,7 +115,7 @@ fn decodable_substructure(
cx.expr_method_call(
trait_span,
decoder,
cx.ident_of("read_struct", trait_span),
Ident::new(sym::read_struct, trait_span),
vec![
cx.expr_str(trait_span, substr.type_ident.name),
cx.expr_usize(trait_span, nfields),
@ -125,11 +124,11 @@ fn decodable_substructure(
)
}
StaticEnum(_, ref fields) => {
let variant = cx.ident_of("i", trait_span);
let variant = Ident::new(sym::i, trait_span);
let mut arms = Vec::with_capacity(fields.len() + 1);
let mut variants = Vec::with_capacity(fields.len());
let rvariant_arg = cx.ident_of("read_enum_variant_arg", trait_span);
let rvariant_arg = Ident::new(sym::read_enum_variant_arg, trait_span);
for (i, &(ident, v_span, ref parts)) in fields.iter().enumerate() {
variants.push(cx.expr_str(v_span, ident.name));
@ -164,13 +163,13 @@ fn decodable_substructure(
let result = cx.expr_method_call(
trait_span,
blkdecoder,
cx.ident_of("read_enum_variant", trait_span),
Ident::new(sym::read_enum_variant, trait_span),
vec![variant_vec, lambda],
);
cx.expr_method_call(
trait_span,
decoder,
cx.ident_of("read_enum", trait_span),
Ident::new(sym::read_enum, trait_span),
vec![
cx.expr_str(trait_span, substr.type_ident.name),
cx.lambda1(trait_span, result, blkarg),

View File

@ -1,6 +1,5 @@
use crate::deriving::generic::ty::*;
use crate::deriving::generic::*;
use crate::deriving::path_std;
use rustc_ast::ast::{Expr, MetaItem};
use rustc_ast::ptr::P;
@ -21,14 +20,14 @@ pub fn expand_deriving_default(
let trait_def = TraitDef {
span,
attributes: Vec::new(),
path: path_std!(cx, default::Default),
path: Path::new(vec![kw::Default, sym::Default]),
additional_bounds: Vec::new(),
generics: LifetimeBounds::empty(),
generics: Bounds::empty(),
is_unsafe: false,
supports_unions: false,
methods: vec![MethodDef {
name: kw::Default,
generics: LifetimeBounds::empty(),
generics: Bounds::empty(),
explicit_self: None,
args: Vec::new(),
ret_ty: Self_,

View File

@ -92,7 +92,7 @@ use crate::deriving::pathvec_std;
use rustc_ast::ast::{Expr, ExprKind, MetaItem, Mutability};
use rustc_ast::ptr::P;
use rustc_expand::base::{Annotatable, ExtCtxt};
use rustc_span::symbol::{sym, Symbol};
use rustc_span::symbol::{sym, Ident, Symbol};
use rustc_span::Span;
pub fn expand_deriving_rustc_encodable(
@ -102,38 +102,42 @@ pub fn expand_deriving_rustc_encodable(
item: &Annotatable,
push: &mut dyn FnMut(Annotatable),
) {
let krate = "rustc_serialize";
let typaram = "__S";
let krate = sym::rustc_serialize;
let typaram = sym::__S;
let trait_def = TraitDef {
span,
attributes: Vec::new(),
path: Path::new_(vec![krate, "Encodable"], None, vec![], PathKind::Global),
path: Path::new_(vec![krate, sym::Encodable], None, vec![], PathKind::Global),
additional_bounds: Vec::new(),
generics: LifetimeBounds::empty(),
generics: Bounds::empty(),
is_unsafe: false,
supports_unions: false,
methods: vec![MethodDef {
name: sym::encode,
generics: LifetimeBounds {
lifetimes: Vec::new(),
generics: Bounds {
bounds: vec![(
typaram,
vec![Path::new_(vec![krate, "Encoder"], None, vec![], PathKind::Global)],
vec![Path::new_(vec![krate, sym::Encoder], None, vec![], PathKind::Global)],
)],
},
explicit_self: borrowed_explicit_self(),
args: vec![(
Ptr(Box::new(Literal(Path::new_local(typaram))), Borrowed(None, Mutability::Mut)),
"s",
// FIXME: we could use `sym::s` here, but making `s` a static
// symbol changes the symbol index ordering in a way that makes
// ui/lint/rfc-2457-non-ascii-idents/lint-confusable-idents.rs
// fail. The linting code should be fixed so that its output
// does not depend on the symbol index ordering.
Symbol::intern("s"),
)],
ret_ty: Literal(Path::new_(
pathvec_std!(cx, result::Result),
pathvec_std!(result::Result),
None,
vec![
Box::new(Tuple(Vec::new())),
Box::new(Literal(Path::new_(
vec![typaram, "Error"],
vec![typaram, sym::Error],
None,
vec![],
PathKind::Local,
@ -158,24 +162,24 @@ fn encodable_substructure(
cx: &mut ExtCtxt<'_>,
trait_span: Span,
substr: &Substructure<'_>,
krate: &'static str,
krate: Symbol,
) -> P<Expr> {
let encoder = substr.nonself_args[0].clone();
// throw an underscore in front to suppress unused variable warnings
let blkarg = cx.ident_of("_e", trait_span);
let blkarg = Ident::new(sym::_e, trait_span);
let blkencoder = cx.expr_ident(trait_span, blkarg);
let fn_path = cx.expr_path(cx.path_global(
trait_span,
vec![
cx.ident_of(krate, trait_span),
cx.ident_of("Encodable", trait_span),
cx.ident_of("encode", trait_span),
Ident::new(krate, trait_span),
Ident::new(sym::Encodable, trait_span),
Ident::new(sym::encode, trait_span),
],
));
match *substr.fields {
Struct(_, ref fields) => {
let emit_struct_field = cx.ident_of("emit_struct_field", trait_span);
let emit_struct_field = Ident::new(sym::emit_struct_field, trait_span);
let mut stmts = Vec::new();
for (i, &FieldInfo { name, ref self_, span, .. }) in fields.iter().enumerate() {
let name = match name {
@ -215,7 +219,7 @@ fn encodable_substructure(
cx.expr_method_call(
trait_span,
encoder,
cx.ident_of("emit_struct", trait_span),
Ident::new(sym::emit_struct, trait_span),
vec![
cx.expr_str(trait_span, substr.type_ident.name),
cx.expr_usize(trait_span, fields.len()),
@ -231,7 +235,7 @@ fn encodable_substructure(
// actually exist.
let me = cx.stmt_let(trait_span, false, blkarg, encoder);
let encoder = cx.expr_ident(trait_span, blkarg);
let emit_variant_arg = cx.ident_of("emit_enum_variant_arg", trait_span);
let emit_variant_arg = Ident::new(sym::emit_enum_variant_arg, trait_span);
let mut stmts = Vec::new();
if !fields.is_empty() {
let last = fields.len() - 1;
@ -264,7 +268,7 @@ fn encodable_substructure(
let call = cx.expr_method_call(
trait_span,
blkencoder,
cx.ident_of("emit_enum_variant", trait_span),
Ident::new(sym::emit_enum_variant, trait_span),
vec![
name,
cx.expr_usize(trait_span, idx),
@ -276,7 +280,7 @@ fn encodable_substructure(
let ret = cx.expr_method_call(
trait_span,
encoder,
cx.ident_of("emit_enum", trait_span),
Ident::new(sym::emit_enum, trait_span),
vec![cx.expr_str(trait_span, substr.type_ident.name), blk],
);
cx.expr_block(cx.block(trait_span, vec![me, cx.stmt_expr(ret)]))

View File

@ -191,7 +191,7 @@ use rustc_span::source_map::respan;
use rustc_span::symbol::{kw, sym, Ident, Symbol};
use rustc_span::Span;
use ty::{LifetimeBounds, Path, Ptr, PtrTy, Self_, Ty};
use ty::{Bounds, Path, Ptr, PtrTy, Self_, Ty};
use crate::deriving;
@ -204,14 +204,14 @@ pub struct TraitDef<'a> {
pub attributes: Vec<ast::Attribute>,
/// Path of the trait, including any type parameters
pub path: Path<'a>,
pub path: Path,
/// Additional bounds required of any type parameters of the type,
/// other than the current trait
pub additional_bounds: Vec<Ty<'a>>,
pub additional_bounds: Vec<Ty>,
/// Any extra lifetimes and/or bounds, e.g., `D: serialize::Decoder`
pub generics: LifetimeBounds<'a>,
pub generics: Bounds,
/// Is it an `unsafe` trait?
pub is_unsafe: bool,
@ -221,14 +221,14 @@ pub struct TraitDef<'a> {
pub methods: Vec<MethodDef<'a>>,
pub associated_types: Vec<(Ident, Ty<'a>)>,
pub associated_types: Vec<(Ident, Ty)>,
}
pub struct MethodDef<'a> {
/// name of the method
pub name: Symbol,
/// List of generics, e.g., `R: rand::Rng`
pub generics: LifetimeBounds<'a>,
pub generics: Bounds,
/// Whether there is a self argument (outer Option) i.e., whether
/// this is a static function, and whether it is a pointer (inner
@ -236,10 +236,10 @@ pub struct MethodDef<'a> {
pub explicit_self: Option<Option<PtrTy>>,
/// Arguments other than the self argument
pub args: Vec<(Ty<'a>, &'a str)>,
pub args: Vec<(Ty, Symbol)>,
/// Returns type
pub ret_ty: Ty<'a>,
pub ret_ty: Ty,
pub attributes: Vec<ast::Attribute>,
@ -865,7 +865,7 @@ impl<'a> MethodDef<'a> {
for (ty, name) in self.args.iter() {
let ast_ty = ty.to_ty(cx, trait_.span, type_ident, generics);
let ident = cx.ident_of(name, trait_.span);
let ident = Ident::new(*name, trait_.span);
arg_tys.push((ident, ast_ty));
let arg_expr = cx.expr_ident(trait_.span, ident);
@ -1170,8 +1170,10 @@ impl<'a> MethodDef<'a> {
)
.collect::<Vec<String>>();
let self_arg_idents =
self_arg_names.iter().map(|name| cx.ident_of(name, sp)).collect::<Vec<Ident>>();
let self_arg_idents = self_arg_names
.iter()
.map(|name| Ident::from_str_and_span(name, sp))
.collect::<Vec<Ident>>();
// The `vi_idents` will be bound, solely in the catch-all, to
// a series of let statements mapping each self_arg to an int
@ -1180,7 +1182,7 @@ impl<'a> MethodDef<'a> {
.iter()
.map(|name| {
let vi_suffix = format!("{}_vi", &name[..]);
cx.ident_of(&vi_suffix[..], trait_.span)
Ident::from_str_and_span(&vi_suffix, trait_.span)
})
.collect::<Vec<Ident>>();
@ -1568,7 +1570,7 @@ impl<'a> TraitDef<'a> {
let mut ident_exprs = Vec::new();
for (i, struct_field) in struct_def.fields().iter().enumerate() {
let sp = struct_field.span.with_ctxt(self.span.ctxt());
let ident = cx.ident_of(&format!("{}_{}", prefix, i), self.span);
let ident = Ident::from_str_and_span(&format!("{}_{}", prefix, i), self.span);
paths.push(ident.with_span_pos(sp));
let val = cx.expr_path(cx.path_ident(sp, ident));
let val = if use_temporaries { val } else { cx.expr_deref(sp, val) };

View File

@ -8,7 +8,7 @@ use rustc_ast::ast::{self, Expr, GenericArg, GenericParamKind, Generics, SelfKin
use rustc_ast::ptr::P;
use rustc_expand::base::ExtCtxt;
use rustc_span::source_map::{respan, DUMMY_SP};
use rustc_span::symbol::{kw, Ident};
use rustc_span::symbol::{kw, Ident, Symbol};
use rustc_span::Span;
/// The types of pointers
@ -24,10 +24,10 @@ pub enum PtrTy {
/// A path, e.g., `::std::option::Option::<i32>` (global). Has support
/// for type parameters and a lifetime.
#[derive(Clone)]
pub struct Path<'a> {
path: Vec<&'a str>,
pub struct Path {
path: Vec<Symbol>,
lifetime: Option<Ident>,
params: Vec<Box<Ty<'a>>>,
params: Vec<Box<Ty>>,
kind: PathKind,
}
@ -38,19 +38,19 @@ pub enum PathKind {
Std,
}
impl<'a> Path<'a> {
pub fn new(path: Vec<&str>) -> Path<'_> {
impl Path {
pub fn new(path: Vec<Symbol>) -> Path {
Path::new_(path, None, Vec::new(), PathKind::Std)
}
pub fn new_local(path: &str) -> Path<'_> {
pub fn new_local(path: Symbol) -> Path {
Path::new_(vec![path], None, Vec::new(), PathKind::Local)
}
pub fn new_<'r>(
path: Vec<&'r str>,
pub fn new_(
path: Vec<Symbol>,
lifetime: Option<Ident>,
params: Vec<Box<Ty<'r>>>,
params: Vec<Box<Ty>>,
kind: PathKind,
) -> Path<'r> {
) -> Path {
Path { path, lifetime, params, kind }
}
@ -70,7 +70,7 @@ impl<'a> Path<'a> {
self_ty: Ident,
self_generics: &Generics,
) -> ast::Path {
let mut idents = self.path.iter().map(|s| cx.ident_of(*s, span)).collect();
let mut idents = self.path.iter().map(|s| Ident::new(*s, span)).collect();
let lt = mk_lifetimes(cx, span, &self.lifetime);
let tys: Vec<P<ast::Ty>> =
self.params.iter().map(|t| t.to_ty(cx, span, self_ty, self_generics)).collect();
@ -94,21 +94,21 @@ impl<'a> Path<'a> {
/// A type. Supports pointers, Self, and literals.
#[derive(Clone)]
pub enum Ty<'a> {
pub enum Ty {
Self_,
/// &/Box/ Ty
Ptr(Box<Ty<'a>>, PtrTy),
Ptr(Box<Ty>, PtrTy),
/// `mod::mod::Type<[lifetime], [Params...]>`, including a plain type
/// parameter, and things like `i32`
Literal(Path<'a>),
Literal(Path),
/// includes unit
Tuple(Vec<Ty<'a>>),
Tuple(Vec<Ty>),
}
pub fn borrowed_ptrty() -> PtrTy {
Borrowed(None, ast::Mutability::Not)
}
pub fn borrowed(ty: Box<Ty<'_>>) -> Ty<'_> {
pub fn borrowed(ty: Box<Ty>) -> Ty {
Ptr(ty, borrowed_ptrty())
}
@ -116,11 +116,11 @@ pub fn borrowed_explicit_self() -> Option<Option<PtrTy>> {
Some(Some(borrowed_ptrty()))
}
pub fn borrowed_self<'r>() -> Ty<'r> {
pub fn borrowed_self() -> Ty {
borrowed(Box::new(Self_))
}
pub fn nil_ty<'r>() -> Ty<'r> {
pub fn nil_ty() -> Ty {
Tuple(Vec::new())
}
@ -132,7 +132,7 @@ fn mk_lifetimes(cx: &ExtCtxt<'_>, span: Span, lt: &Option<Ident>) -> Vec<ast::Li
mk_lifetime(cx, span, lt).into_iter().collect()
}
impl<'a> Ty<'a> {
impl Ty {
pub fn to_ty(
&self,
cx: &ExtCtxt<'_>,
@ -199,9 +199,9 @@ impl<'a> Ty<'a> {
fn mk_ty_param(
cx: &ExtCtxt<'_>,
span: Span,
name: &str,
name: Symbol,
attrs: &[ast::Attribute],
bounds: &[Path<'_>],
bounds: &[Path],
self_ident: Ident,
self_generics: &Generics,
) -> ast::GenericParam {
@ -212,7 +212,7 @@ fn mk_ty_param(
cx.trait_bound(path)
})
.collect();
cx.typaram(span, cx.ident_of(name, span), attrs.to_owned(), bounds, None)
cx.typaram(span, Ident::new(name, span), attrs.to_owned(), bounds, None)
}
fn mk_generics(params: Vec<ast::GenericParam>, span: Span) -> Generics {
@ -223,16 +223,15 @@ fn mk_generics(params: Vec<ast::GenericParam>, span: Span) -> Generics {
}
}
/// Lifetimes and bounds on type parameters
/// Bounds on type parameters.
#[derive(Clone)]
pub struct LifetimeBounds<'a> {
pub lifetimes: Vec<(&'a str, Vec<&'a str>)>,
pub bounds: Vec<(&'a str, Vec<Path<'a>>)>,
pub struct Bounds {
pub bounds: Vec<(Symbol, Vec<Path>)>,
}
impl<'a> LifetimeBounds<'a> {
pub fn empty() -> LifetimeBounds<'a> {
LifetimeBounds { lifetimes: Vec::new(), bounds: Vec::new() }
impl Bounds {
pub fn empty() -> Bounds {
Bounds { bounds: Vec::new() }
}
pub fn to_generics(
&self,
@ -242,18 +241,12 @@ impl<'a> LifetimeBounds<'a> {
self_generics: &Generics,
) -> Generics {
let generic_params = self
.lifetimes
.bounds
.iter()
.map(|&(lt, ref bounds)| {
let bounds = bounds
.iter()
.map(|b| ast::GenericBound::Outlives(cx.lifetime(span, Ident::from_str(b))));
cx.lifetime_def(span, Ident::from_str(lt), vec![], bounds.collect())
})
.chain(self.bounds.iter().map(|t| {
.map(|t| {
let (name, ref bounds) = *t;
mk_ty_param(cx, span, name, &[], &bounds, self_ty, self_generics)
}))
})
.collect();
mk_generics(generic_params, span)

View File

@ -15,9 +15,9 @@ pub fn expand_deriving_hash(
item: &Annotatable,
push: &mut dyn FnMut(Annotatable),
) {
let path = Path::new_(pathvec_std!(cx, hash::Hash), None, vec![], PathKind::Std);
let path = Path::new_(pathvec_std!(hash::Hash), None, vec![], PathKind::Std);
let typaram = "__H";
let typaram = sym::__H;
let arg = Path::new_local(typaram);
let hash_trait_def = TraitDef {
@ -25,17 +25,14 @@ pub fn expand_deriving_hash(
attributes: Vec::new(),
path,
additional_bounds: Vec::new(),
generics: LifetimeBounds::empty(),
generics: Bounds::empty(),
is_unsafe: false,
supports_unions: false,
methods: vec![MethodDef {
name: sym::hash,
generics: LifetimeBounds {
lifetimes: Vec::new(),
bounds: vec![(typaram, vec![path_std!(cx, hash::Hasher)])],
},
generics: Bounds { bounds: vec![(typaram, vec![path_std!(hash::Hasher)])] },
explicit_self: borrowed_explicit_self(),
args: vec![(Ptr(Box::new(Literal(arg)), Borrowed(None, Mutability::Mut)), "state")],
args: vec![(Ptr(Box::new(Literal(arg)), Borrowed(None, Mutability::Mut)), sym::state)],
ret_ty: nil_ty(),
attributes: vec![],
is_unsafe: false,

View File

@ -7,11 +7,11 @@ use rustc_span::symbol::{sym, Ident, Symbol};
use rustc_span::Span;
macro path_local($x:ident) {
generic::ty::Path::new_local(stringify!($x))
generic::ty::Path::new_local(sym::$x)
}
macro pathvec_std($cx:expr, $($rest:ident)::+) {{
vec![ $( stringify!($rest) ),+ ]
macro pathvec_std($($rest:ident)::+) {{
vec![ $( sym::$rest ),+ ]
}}
macro path_std($($x:tt)*) {
@ -84,7 +84,7 @@ fn inject_impl_of_structural_trait(
cx: &mut ExtCtxt<'_>,
span: Span,
item: &Annotatable,
structural_path: generic::ty::Path<'_>,
structural_path: generic::ty::Path,
push: &mut dyn FnMut(Annotatable),
) {
let item = match *item {

View File

@ -578,31 +578,31 @@ impl<'a, 'b> Context<'a, 'b> {
self.count_args_index_offset = sofar;
}
fn rtpath(ecx: &ExtCtxt<'_>, s: &str) -> Vec<Ident> {
ecx.std_path(&[sym::fmt, sym::rt, sym::v1, Symbol::intern(s)])
fn rtpath(ecx: &ExtCtxt<'_>, s: Symbol) -> Vec<Ident> {
ecx.std_path(&[sym::fmt, sym::rt, sym::v1, s])
}
fn build_count(&self, c: parse::Count) -> P<ast::Expr> {
let sp = self.macsp;
let count = |c, arg| {
let mut path = Context::rtpath(self.ecx, "Count");
path.push(self.ecx.ident_of(c, sp));
let mut path = Context::rtpath(self.ecx, sym::Count);
path.push(Ident::new(c, sp));
match arg {
Some(arg) => self.ecx.expr_call_global(sp, path, vec![arg]),
None => self.ecx.expr_path(self.ecx.path_global(sp, path)),
}
};
match c {
parse::CountIs(i) => count("Is", Some(self.ecx.expr_usize(sp, i))),
parse::CountIs(i) => count(sym::Is, Some(self.ecx.expr_usize(sp, i))),
parse::CountIsParam(i) => {
// This needs mapping too, as `i` is referring to a macro
// argument. If `i` is not found in `count_positions` then
// the error had already been emitted elsewhere.
let i = self.count_positions.get(&i).cloned().unwrap_or(0)
+ self.count_args_index_offset;
count("Param", Some(self.ecx.expr_usize(sp, i)))
count(sym::Param, Some(self.ecx.expr_usize(sp, i)))
}
parse::CountImplied => count("Implied", None),
parse::CountImplied => count(sym::Implied, None),
// should never be the case, names are already resolved
parse::CountIsName(_) => panic!("should never happen"),
}
@ -690,40 +690,40 @@ impl<'a, 'b> Context<'a, 'b> {
// Build the format
let fill = self.ecx.expr_lit(sp, ast::LitKind::Char(fill));
let align = |name| {
let mut p = Context::rtpath(self.ecx, "Alignment");
p.push(self.ecx.ident_of(name, sp));
let mut p = Context::rtpath(self.ecx, sym::Alignment);
p.push(Ident::new(name, sp));
self.ecx.path_global(sp, p)
};
let align = match arg.format.align {
parse::AlignLeft => align("Left"),
parse::AlignRight => align("Right"),
parse::AlignCenter => align("Center"),
parse::AlignUnknown => align("Unknown"),
parse::AlignLeft => align(sym::Left),
parse::AlignRight => align(sym::Right),
parse::AlignCenter => align(sym::Center),
parse::AlignUnknown => align(sym::Unknown),
};
let align = self.ecx.expr_path(align);
let flags = self.ecx.expr_u32(sp, arg.format.flags);
let prec = self.build_count(arg.format.precision);
let width = self.build_count(arg.format.width);
let path = self.ecx.path_global(sp, Context::rtpath(self.ecx, "FormatSpec"));
let path = self.ecx.path_global(sp, Context::rtpath(self.ecx, sym::FormatSpec));
let fmt = self.ecx.expr_struct(
sp,
path,
vec![
self.ecx.field_imm(sp, self.ecx.ident_of("fill", sp), fill),
self.ecx.field_imm(sp, self.ecx.ident_of("align", sp), align),
self.ecx.field_imm(sp, self.ecx.ident_of("flags", sp), flags),
self.ecx.field_imm(sp, self.ecx.ident_of("precision", sp), prec),
self.ecx.field_imm(sp, self.ecx.ident_of("width", sp), width),
self.ecx.field_imm(sp, Ident::new(sym::fill, sp), fill),
self.ecx.field_imm(sp, Ident::new(sym::align, sp), align),
self.ecx.field_imm(sp, Ident::new(sym::flags, sp), flags),
self.ecx.field_imm(sp, Ident::new(sym::precision, sp), prec),
self.ecx.field_imm(sp, Ident::new(sym::width, sp), width),
],
);
let path = self.ecx.path_global(sp, Context::rtpath(self.ecx, "Argument"));
let path = self.ecx.path_global(sp, Context::rtpath(self.ecx, sym::Argument));
Some(self.ecx.expr_struct(
sp,
path,
vec![
self.ecx.field_imm(sp, self.ecx.ident_of("position", sp), pos),
self.ecx.field_imm(sp, self.ecx.ident_of("format", sp), fmt),
self.ecx.field_imm(sp, Ident::new(sym::position, sp), pos),
self.ecx.field_imm(sp, Ident::new(sym::format, sp), fmt),
],
))
}
@ -740,7 +740,7 @@ impl<'a, 'b> Context<'a, 'b> {
let mut heads = Vec::with_capacity(self.args.len());
let names_pos: Vec<_> = (0..self.args.len())
.map(|i| self.ecx.ident_of(&format!("arg{}", i), self.macsp))
.map(|i| Ident::from_str_and_span(&format!("arg{}", i), self.macsp))
.collect();
// First, build up the static array which will become our precompiled

View File

@ -58,7 +58,7 @@ impl AllocFnFactory<'_, '_> {
let mut abi_args = Vec::new();
let mut i = 0;
let mut mk = || {
let name = self.cx.ident_of(&format!("arg{}", i), self.span);
let name = Ident::from_str_and_span(&format!("arg{}", i), self.span);
i += 1;
name
};
@ -72,7 +72,7 @@ impl AllocFnFactory<'_, '_> {
let kind = ItemKind::Fn(ast::Defaultness::Final, sig, Generics::default(), block);
let item = self.cx.item(
self.span,
self.cx.ident_of(&self.kind.fn_name(method.name), self.span),
Ident::from_str_and_span(&self.kind.fn_name(method.name), self.span),
self.attrs(),
kind,
);

View File

@ -384,12 +384,12 @@ fn mk_decls(
let proc_macro = Ident::new(sym::proc_macro, span);
let krate = cx.item(span, proc_macro, Vec::new(), ast::ItemKind::ExternCrate(None));
let bridge = cx.ident_of("bridge", span);
let client = cx.ident_of("client", span);
let proc_macro_ty = cx.ident_of("ProcMacro", span);
let custom_derive = cx.ident_of("custom_derive", span);
let attr = cx.ident_of("attr", span);
let bang = cx.ident_of("bang", span);
let bridge = Ident::new(sym::bridge, span);
let client = Ident::new(sym::client, span);
let proc_macro_ty = Ident::new(sym::ProcMacro, span);
let custom_derive = Ident::new(sym::custom_derive, span);
let attr = Ident::new(sym::attr, span);
let bang = Ident::new(sym::bang, span);
let krate_ref = RefCell::new(ast_krate);
@ -447,7 +447,7 @@ fn mk_decls(
let decls_static = cx
.item_static(
span,
cx.ident_of("_DECLS", span),
Ident::new(sym::_DECLS, span),
cx.ty_rptr(
span,
cx.ty(

View File

@ -108,22 +108,38 @@ pub fn expand_test_or_bench(
let test_id = Ident::new(sym::test, attr_sp);
// creates test::$name
let test_path = |name| cx.path(sp, vec![test_id, cx.ident_of(name, sp)]);
let test_path = |name| cx.path(sp, vec![test_id, Ident::from_str_and_span(name, sp)]);
// creates test::ShouldPanic::$name
let should_panic_path =
|name| cx.path(sp, vec![test_id, cx.ident_of("ShouldPanic", sp), cx.ident_of(name, sp)]);
let should_panic_path = |name| {
cx.path(
sp,
vec![
test_id,
Ident::from_str_and_span("ShouldPanic", sp),
Ident::from_str_and_span(name, sp),
],
)
};
// creates test::TestType::$name
let test_type_path =
|name| cx.path(sp, vec![test_id, cx.ident_of("TestType", sp), cx.ident_of(name, sp)]);
let test_type_path = |name| {
cx.path(
sp,
vec![
test_id,
Ident::from_str_and_span("TestType", sp),
Ident::from_str_and_span(name, sp),
],
)
};
// creates $name: $expr
let field = |name, expr| cx.field_imm(sp, cx.ident_of(name, sp), expr);
let field = |name, expr| cx.field_imm(sp, Ident::from_str_and_span(name, sp), expr);
let test_fn = if is_bench {
// A simple ident for a lambda
let b = cx.ident_of("b", attr_sp);
let b = Ident::from_str_and_span("b", attr_sp);
cx.expr_call(
sp,

View File

@ -270,7 +270,7 @@ fn mk_main(cx: &mut TestCtxt<'_>) -> P<ast::Item> {
let mut test_runner = cx
.test_runner
.clone()
.unwrap_or(ecx.path(sp, vec![test_id, ecx.ident_of(runner_name, sp)]));
.unwrap_or(ecx.path(sp, vec![test_id, Ident::from_str_and_span(runner_name, sp)]));
test_runner.span = sp;

View File

@ -1,4 +1,4 @@
An feature unstable in `const` contexts was used.
An unstable feature in `const` contexts was used.
Erroneous code example:

View File

@ -1061,9 +1061,6 @@ impl<'a> ExtCtxt<'a> {
pub fn set_trace_macros(&mut self, x: bool) {
self.ecfg.trace_mac = x
}
pub fn ident_of(&self, st: &str, sp: Span) -> Ident {
Ident::from_str_and_span(st, sp)
}
pub fn std_path(&self, components: &[Symbol]) -> Vec<Ident> {
let def_site = self.with_def_site_ctxt(DUMMY_SP);
iter::once(Ident::new(kw::DollarCrate, def_site))

View File

@ -368,7 +368,7 @@ impl<'a> ExtCtxt<'a> {
let err = self.std_path(&[sym::result, sym::Result, sym::Err]);
let err_path = self.path_global(sp, err);
let binding_variable = self.ident_of("__try_var", sp);
let binding_variable = Ident::new(sym::__try_var, sp);
let binding_pat = self.pat_ident(sp, binding_variable);
let binding_expr = self.expr_ident(sp, binding_variable);

View File

@ -8,7 +8,7 @@ use rustc_hir as hir;
use rustc_hir::def_id::{DefId, LocalDefId};
use rustc_index::bit_set::BitMatrix;
use rustc_index::vec::IndexVec;
use rustc_span::{Span, Symbol};
use rustc_span::Span;
use rustc_target::abi::VariantIdx;
use smallvec::SmallVec;
use std::cell::Cell;
@ -18,7 +18,7 @@ use super::{Field, SourceInfo};
#[derive(Copy, Clone, PartialEq, RustcEncodable, RustcDecodable, HashStable)]
pub enum UnsafetyViolationKind {
/// Only permitted in regular `fn`s, prohibitted in `const fn`s.
/// Only permitted in regular `fn`s, prohibited in `const fn`s.
General,
/// Permitted both in `const fn`s and regular `fn`s.
GeneralAndConstFn,
@ -35,13 +35,97 @@ pub enum UnsafetyViolationKind {
UnsafeFnBorrowPacked,
}
#[derive(Copy, Clone, PartialEq, RustcEncodable, RustcDecodable, HashStable)]
pub enum UnsafetyViolationDetails {
CallToUnsafeFunction,
UseOfInlineAssembly,
InitializingTypeWith,
CastOfPointerToInt,
BorrowOfPackedField,
UseOfMutableStatic,
UseOfExternStatic,
DerefOfRawPointer,
AssignToNonCopyUnionField,
AccessToUnionField,
MutationOfLayoutConstrainedField,
BorrowOfLayoutConstrainedField,
CallToFunctionWith,
}
impl UnsafetyViolationDetails {
pub fn description_and_note(&self) -> (&'static str, &'static str) {
use UnsafetyViolationDetails::*;
match self {
CallToUnsafeFunction => (
"call to unsafe function",
"consult the function's documentation for information on how to avoid undefined \
behavior",
),
UseOfInlineAssembly => (
"use of inline assembly",
"inline assembly is entirely unchecked and can cause undefined behavior",
),
InitializingTypeWith => (
"initializing type with `rustc_layout_scalar_valid_range` attr",
"initializing a layout restricted type's field with a value outside the valid \
range is undefined behavior",
),
CastOfPointerToInt => {
("cast of pointer to int", "casting pointers to integers in constants")
}
BorrowOfPackedField => (
"borrow of packed field",
"fields of packed structs might be misaligned: dereferencing a misaligned pointer \
or even just creating a misaligned reference is undefined behavior",
),
UseOfMutableStatic => (
"use of mutable static",
"mutable statics can be mutated by multiple threads: aliasing violations or data \
races will cause undefined behavior",
),
UseOfExternStatic => (
"use of extern static",
"extern statics are not controlled by the Rust type system: invalid data, \
aliasing violations or data races will cause undefined behavior",
),
DerefOfRawPointer => (
"dereference of raw pointer",
"raw pointers may be NULL, dangling or unaligned; they can violate aliasing rules \
and cause data races: all of these are undefined behavior",
),
AssignToNonCopyUnionField => (
"assignment to non-`Copy` union field",
"the previous content of the field will be dropped, which causes undefined \
behavior if the field was not properly initialized",
),
AccessToUnionField => (
"access to union field",
"the field may not be properly initialized: using uninitialized data will cause \
undefined behavior",
),
MutationOfLayoutConstrainedField => (
"mutation of layout constrained field",
"mutating layout constrained fields cannot statically be checked for valid values",
),
BorrowOfLayoutConstrainedField => (
"borrow of layout constrained field with interior mutability",
"references to fields of layout constrained fields lose the constraints. Coupled \
with interior mutability, the field can be changed to invalid values",
),
CallToFunctionWith => (
"call to function with `#[target_feature]`",
"can only be called if the required target features are available",
),
}
}
}
#[derive(Copy, Clone, PartialEq, RustcEncodable, RustcDecodable, HashStable)]
pub struct UnsafetyViolation {
pub source_info: SourceInfo,
pub lint_root: hir::HirId,
pub description: Symbol,
pub details: Symbol,
pub kind: UnsafetyViolationKind,
pub details: UnsafetyViolationDetails,
}
#[derive(Clone, RustcEncodable, RustcDecodable, HashStable)]

View File

@ -1440,12 +1440,12 @@ impl<F: fmt::Write> Printer<'tcx> for FmtPrinter<'_, 'tcx, F> {
// FIXME(eddyb) `name` should never be empty, but it
// currently is for `extern { ... }` "foreign modules".
let name = disambiguated_data.data.as_symbol().as_str();
if !name.is_empty() {
let name = disambiguated_data.data.as_symbol();
if name != kw::Invalid {
if !self.empty_path {
write!(self, "::")?;
}
if Ident::from_str(&name).is_raw_guess() {
if Ident::with_dummy_span(name).is_raw_guess() {
write!(self, "r#")?;
}
write!(self, "{}", name)?;

View File

@ -60,12 +60,12 @@ impl<'p, 'c, 'tcx> QueryKeyStringBuilder<'p, 'c, 'tcx> {
match def_key.disambiguated_data.data {
DefPathData::CrateRoot => {
name = self.tcx.original_crate_name(def_id.krate).as_str();
name = self.tcx.original_crate_name(def_id.krate);
dis = "";
end_index = 3;
}
other => {
name = other.as_symbol().as_str();
name = other.as_symbol();
if def_key.disambiguated_data.disambiguator == 0 {
dis = "";
end_index = 3;
@ -79,10 +79,11 @@ impl<'p, 'c, 'tcx> QueryKeyStringBuilder<'p, 'c, 'tcx> {
}
}
let name = &*name.as_str();
let components = [
StringComponent::Ref(parent_string_id),
StringComponent::Value("::"),
StringComponent::Value(&name[..]),
StringComponent::Value(name),
StringComponent::Value(dis),
];

View File

@ -12,7 +12,7 @@ use rustc_middle::ty::query::Providers;
use rustc_middle::ty::{self, TyCtxt};
use rustc_session::lint::builtin::{SAFE_PACKED_BORROWS, UNSAFE_OP_IN_UNSAFE_FN, UNUSED_UNSAFE};
use rustc_session::lint::Level;
use rustc_span::symbol::{sym, Symbol};
use rustc_span::symbol::sym;
use std::ops::Bound;
@ -86,10 +86,8 @@ impl<'a, 'tcx> Visitor<'tcx> for UnsafetyChecker<'a, 'tcx> {
let sig = func_ty.fn_sig(self.tcx);
if let hir::Unsafety::Unsafe = sig.unsafety() {
self.require_unsafe(
"call to unsafe function",
"consult the function's documentation for information on how to avoid \
undefined behavior",
UnsafetyViolationKind::GeneralAndConstFn,
UnsafetyViolationDetails::CallToUnsafeFunction,
)
}
@ -99,9 +97,8 @@ impl<'a, 'tcx> Visitor<'tcx> for UnsafetyChecker<'a, 'tcx> {
}
TerminatorKind::InlineAsm { .. } => self.require_unsafe(
"use of inline assembly",
"inline assembly is entirely unchecked and can cause undefined behavior",
UnsafetyViolationKind::General,
UnsafetyViolationDetails::UseOfInlineAssembly,
),
}
self.super_terminator(terminator, location);
@ -122,9 +119,8 @@ impl<'a, 'tcx> Visitor<'tcx> for UnsafetyChecker<'a, 'tcx> {
}
StatementKind::LlvmInlineAsm { .. } => self.require_unsafe(
"use of inline assembly",
"inline assembly is entirely unchecked and can cause undefined behavior",
UnsafetyViolationKind::General,
UnsafetyViolationDetails::UseOfInlineAssembly,
),
}
self.super_statement(statement, location);
@ -138,10 +134,8 @@ impl<'a, 'tcx> Visitor<'tcx> for UnsafetyChecker<'a, 'tcx> {
match self.tcx.layout_scalar_valid_range(def.did) {
(Bound::Unbounded, Bound::Unbounded) => {}
_ => self.require_unsafe(
"initializing type with `rustc_layout_scalar_valid_range` attr",
"initializing a layout restricted type's field with a value \
outside the valid range is undefined behavior",
UnsafetyViolationKind::GeneralAndConstFn,
UnsafetyViolationDetails::InitializingTypeWith,
),
}
}
@ -163,9 +157,8 @@ impl<'a, 'tcx> Visitor<'tcx> for UnsafetyChecker<'a, 'tcx> {
match (cast_in, cast_out) {
(CastTy::Ptr(_) | CastTy::FnPtr, CastTy::Int(_)) => {
self.require_unsafe(
"cast of pointer to int",
"casting pointers to integers in constants",
UnsafetyViolationKind::General,
UnsafetyViolationDetails::CastOfPointerToInt,
);
}
_ => {}
@ -190,11 +183,8 @@ impl<'a, 'tcx> Visitor<'tcx> for UnsafetyChecker<'a, 'tcx> {
if context.is_borrow() {
if util::is_disaligned(self.tcx, self.body, self.param_env, *place) {
self.require_unsafe(
"borrow of packed field",
"fields of packed structs might be misaligned: dereferencing a \
misaligned pointer or even just creating a misaligned reference \
is undefined behavior",
UnsafetyViolationKind::BorrowPacked,
UnsafetyViolationDetails::BorrowOfPackedField,
);
}
}
@ -204,11 +194,8 @@ impl<'a, 'tcx> Visitor<'tcx> for UnsafetyChecker<'a, 'tcx> {
if context.is_borrow() {
if util::is_disaligned(self.tcx, self.body, self.param_env, *place) {
self.require_unsafe(
"borrow of packed field",
"fields of packed structs might be misaligned: dereferencing a \
misaligned pointer or even just creating a misaligned reference \
is undefined behavior",
UnsafetyViolationKind::BorrowPacked,
UnsafetyViolationDetails::BorrowOfPackedField,
);
}
}
@ -219,19 +206,14 @@ impl<'a, 'tcx> Visitor<'tcx> for UnsafetyChecker<'a, 'tcx> {
if let Some(box LocalInfo::StaticRef { def_id, .. }) = decl.local_info {
if self.tcx.is_mutable_static(def_id) {
self.require_unsafe(
"use of mutable static",
"mutable statics can be mutated by multiple threads: aliasing \
violations or data races will cause undefined behavior",
UnsafetyViolationKind::General,
UnsafetyViolationDetails::UseOfMutableStatic,
);
return;
} else if self.tcx.is_foreign_item(def_id) {
self.require_unsafe(
"use of extern static",
"extern statics are not controlled by the Rust type system: \
invalid data, aliasing violations or data races will cause \
undefined behavior",
UnsafetyViolationKind::General,
UnsafetyViolationDetails::UseOfExternStatic,
);
return;
}
@ -246,11 +228,8 @@ impl<'a, 'tcx> Visitor<'tcx> for UnsafetyChecker<'a, 'tcx> {
let base_ty = Place::ty_from(place.local, proj_base, self.body, self.tcx).ty;
match base_ty.kind {
ty::RawPtr(..) => self.require_unsafe(
"dereference of raw pointer",
"raw pointers may be NULL, dangling or unaligned; they can violate \
aliasing rules and cause data races: all of these are undefined \
behavior",
UnsafetyViolationKind::General,
UnsafetyViolationDetails::DerefOfRawPointer,
),
ty::Adt(adt, _) => {
if adt.is_union() {
@ -271,21 +250,16 @@ impl<'a, 'tcx> Visitor<'tcx> for UnsafetyChecker<'a, 'tcx> {
self.param_env,
) {
self.require_unsafe(
"assignment to non-`Copy` union field",
"the previous content of the field will be dropped, which \
causes undefined behavior if the field was not properly \
initialized",
UnsafetyViolationKind::GeneralAndConstFn,
UnsafetyViolationDetails::AssignToNonCopyUnionField,
)
} else {
// write to non-move union, safe
}
} else {
self.require_unsafe(
"access to union field",
"the field may not be properly initialized: using \
uninitialized data will cause undefined behavior",
UnsafetyViolationKind::GeneralAndConstFn,
UnsafetyViolationDetails::AccessToUnionField,
)
}
}
@ -298,12 +272,7 @@ impl<'a, 'tcx> Visitor<'tcx> for UnsafetyChecker<'a, 'tcx> {
}
impl<'a, 'tcx> UnsafetyChecker<'a, 'tcx> {
fn require_unsafe(
&mut self,
description: &'static str,
details: &'static str,
kind: UnsafetyViolationKind,
) {
fn require_unsafe(&mut self, kind: UnsafetyViolationKind, details: UnsafetyViolationDetails) {
let source_info = self.source_info;
let lint_root = self.body.source_scopes[self.source_info.scope]
.local_data
@ -311,13 +280,7 @@ impl<'a, 'tcx> UnsafetyChecker<'a, 'tcx> {
.assert_crate_local()
.lint_root;
self.register_violations(
&[UnsafetyViolation {
source_info,
lint_root,
description: Symbol::intern(description),
details: Symbol::intern(details),
kind,
}],
&[UnsafetyViolation { source_info, lint_root, kind, details }],
&[],
);
}
@ -434,12 +397,8 @@ impl<'a, 'tcx> UnsafetyChecker<'a, 'tcx> {
if self.tcx.layout_scalar_valid_range(def.did)
!= (Bound::Unbounded, Bound::Unbounded)
{
let (description, details) = if is_mut_use {
(
"mutation of layout constrained field",
"mutating layout constrained fields cannot statically be \
checked for valid values",
)
let details = if is_mut_use {
UnsafetyViolationDetails::MutationOfLayoutConstrainedField
// Check `is_freeze` as late as possible to avoid cycle errors
// with opaque types.
@ -448,21 +407,11 @@ impl<'a, 'tcx> UnsafetyChecker<'a, 'tcx> {
.ty
.is_freeze(self.tcx.at(self.source_info.span), self.param_env)
{
(
"borrow of layout constrained field with interior \
mutability",
"references to fields of layout constrained fields \
lose the constraints. Coupled with interior mutability, \
the field can be changed to invalid values",
)
UnsafetyViolationDetails::BorrowOfLayoutConstrainedField
} else {
continue;
};
self.require_unsafe(
description,
details,
UnsafetyViolationKind::GeneralAndConstFn,
);
self.require_unsafe(UnsafetyViolationKind::GeneralAndConstFn, details);
}
}
}
@ -480,9 +429,8 @@ impl<'a, 'tcx> UnsafetyChecker<'a, 'tcx> {
// Is `callee_features` a subset of `calling_features`?
if !callee_features.iter().all(|feature| self_features.contains(feature)) {
self.require_unsafe(
"call to function with `#[target_feature]`",
"can only be called if the required target features are available",
UnsafetyViolationKind::GeneralAndConstFn,
UnsafetyViolationDetails::CallToFunctionWith,
)
}
}
@ -675,9 +623,9 @@ pub fn check_unsafety(tcx: TyCtxt<'_>, def_id: LocalDefId) {
let UnsafetyCheckResult { violations, unsafe_blocks } = tcx.unsafety_check_result(def_id);
for &UnsafetyViolation { source_info, lint_root, description, details, kind } in
violations.iter()
{
for &UnsafetyViolation { source_info, lint_root, kind, details } in violations.iter() {
let (description, note) = details.description_and_note();
// Report an error.
let unsafe_fn_msg =
if unsafe_op_in_unsafe_fn_allowed(tcx, lint_root) { " function or" } else { "" };
@ -693,8 +641,8 @@ pub fn check_unsafety(tcx: TyCtxt<'_>, def_id: LocalDefId) {
description,
unsafe_fn_msg,
)
.span_label(source_info.span, &*description.as_str())
.note(&details.as_str())
.span_label(source_info.span, description)
.note(note)
.emit();
}
UnsafetyViolationKind::BorrowPacked => {
@ -712,7 +660,7 @@ pub fn check_unsafety(tcx: TyCtxt<'_>, def_id: LocalDefId) {
"{} is unsafe and requires unsafe{} block (error E0133)",
description, unsafe_fn_msg,
))
.note(&details.as_str())
.note(note)
.emit()
},
)
@ -727,8 +675,8 @@ pub fn check_unsafety(tcx: TyCtxt<'_>, def_id: LocalDefId) {
"{} is unsafe and requires unsafe block (error E0133)",
description,
))
.span_label(source_info.span, &*description.as_str())
.note(&details.as_str())
.span_label(source_info.span, description)
.note(note)
.emit();
},
),
@ -756,8 +704,8 @@ pub fn check_unsafety(tcx: TyCtxt<'_>, def_id: LocalDefId) {
"{} is unsafe and requires unsafe block (error E0133)",
description,
))
.span_label(source_info.span, &*description.as_str())
.note(&details.as_str())
.span_label(source_info.span, description)
.note(note)
.emit();
})
}

View File

@ -502,7 +502,8 @@ impl Visitor<'tcx> for Checker<'tcx> {
match item.kind {
hir::ItemKind::ExternCrate(_) => {
// compiler-generated `extern crate` items have a dummy span.
if item.span.is_dummy() {
// `std` is still checked for the `restricted-std` feature.
if item.span.is_dummy() && item.ident.as_str() != "std" {
return;
}

View File

@ -111,12 +111,17 @@ impl<'a> Resolver<'a> {
(self.cstore().crate_name_untracked(def_id.krate), None)
} else {
let def_key = self.cstore().def_key(def_id);
(
// This unwrap is safe: crates must always have a name
def_key.disambiguated_data.data.get_opt_name().unwrap(),
// This unwrap is safe since we know this isn't the root
Some(self.get_module(DefId { index: def_key.parent.unwrap(), ..def_id })),
)
let name = def_key
.disambiguated_data
.data
.get_opt_name()
.expect("given a DefId that wasn't a module");
// This unwrap is safe since we know this isn't the root
let parent = Some(self.get_module(DefId {
index: def_key.parent.expect("failed to get parent for module"),
..def_id
}));
(name, parent)
};
// Allocate and return a new module with the information we found

View File

@ -2978,7 +2978,7 @@ impl<'a> Resolver<'a> {
span: Span,
path_str: &str,
ns: Namespace,
module_id: LocalDefId,
module_id: DefId,
) -> Result<(ast::Path, Res), ()> {
let path = if path_str.starts_with("::") {
ast::Path {
@ -2998,7 +2998,7 @@ impl<'a> Resolver<'a> {
.collect(),
}
};
let module = self.module_map.get(&module_id).copied().unwrap_or(self.graph_root);
let module = self.get_module(module_id);
let parent_scope = &ParentScope::module(module);
let res = self.resolve_ast_path(&path, ns, parent_scope).map_err(|_| ())?;
Ok((path, res))

View File

@ -122,19 +122,28 @@ symbols! {
// There is currently no checking that all symbols are used; that would be
// nice to have.
Symbols {
Alignment,
Arc,
Argument,
ArgumentV1,
Arguments,
C,
Center,
Clone,
Copy,
Count,
Debug,
Decodable,
Decoder,
Default,
Encodable,
Encoder,
Eq,
Equal,
Err,
Error,
FormatSpec,
Formatter,
From,
Future,
FxHashMap,
@ -143,11 +152,15 @@ symbols! {
Hash,
HashMap,
HashSet,
Hasher,
Implied,
Input,
IntoIterator,
Is,
ItemContext,
Iterator,
Layout,
Left,
LintPass,
None,
Ok,
@ -155,11 +168,13 @@ symbols! {
Ord,
Ordering,
Output,
Param,
PartialEq,
PartialOrd,
Pending,
Pin,
Poll,
ProcMacro,
ProcMacroHack,
ProceduralMasqueradeDummyType,
Range,
@ -172,20 +187,31 @@ symbols! {
Ready,
Result,
Return,
Right,
RustcDecodable,
RustcEncodable,
Send,
Some,
StructuralEq,
StructuralPartialEq,
Sync,
Target,
Try,
Ty,
TyCtxt,
TyKind,
Unknown,
Vec,
Yield,
_DECLS,
_Self,
__D,
__H,
__S,
__next,
__try_var,
_d,
_e,
_task_context,
aarch64_target_feature,
abi,
@ -226,6 +252,7 @@ symbols! {
allowed,
always,
and,
and_then,
any,
arbitrary_enum_discriminant,
arbitrary_self_types,
@ -256,6 +283,7 @@ symbols! {
automatically_derived,
avx512_target_feature,
await_macro,
bang,
begin_panic,
bench,
bin,
@ -278,6 +306,7 @@ symbols! {
box_syntax,
braced_empty_structs,
breakpoint,
bridge,
bswap,
c_variadic,
call,
@ -299,6 +328,7 @@ symbols! {
cfg_target_vendor,
cfg_version,
char,
client,
clippy,
clone,
clone_closures,
@ -370,11 +400,15 @@ symbols! {
custom_derive,
custom_inner_attributes,
custom_test_frameworks,
d,
dead_code,
dealloc,
debug,
debug_assertions,
debug_struct,
debug_trait,
debug_trait_builder,
debug_tuple,
decl_macro,
declare_lint_pass,
decode,
@ -421,6 +455,11 @@ symbols! {
dyn_trait,
eh_catch_typeinfo,
eh_personality,
emit_enum,
emit_enum_variant,
emit_enum_variant_arg,
emit_struct,
emit_struct_field,
enable,
enclosing_scope,
encode,
@ -448,6 +487,7 @@ symbols! {
extern_prelude,
extern_types,
external_doc,
f,
f16c_target_feature,
f32,
f32_runtime,
@ -464,6 +504,9 @@ symbols! {
field,
field_init_shorthand,
file,
fill,
finish,
flags,
float_to_int_unchecked,
floorf32,
floorf64,
@ -478,6 +521,7 @@ symbols! {
fn_once_output,
forbid,
forget,
format,
format_args,
format_args_capture,
format_args_nl,
@ -519,6 +563,7 @@ symbols! {
html_no_source,
html_playground_url,
html_root_url,
i,
i128,
i128_type,
i16,
@ -606,6 +651,7 @@ symbols! {
main,
managed_boxes,
manually_drop,
map,
marker,
marker_trait_attr,
masked,
@ -708,6 +754,7 @@ symbols! {
options,
or,
or_patterns,
other,
out,
overlapping_marker_traits,
owned_box,
@ -739,6 +786,7 @@ symbols! {
plugins,
pointer,
poll,
position,
post_dash_lto: "post-lto",
powerpc_target_feature,
powf32,
@ -747,6 +795,7 @@ symbols! {
powif64,
pre_dash_lto: "pre-lto",
precise_pointer_size_matching,
precision,
pref_align_of,
prefetch_read_data,
prefetch_read_instruction,
@ -783,6 +832,11 @@ symbols! {
raw_identifiers,
raw_ref_op,
re_rebalance_coherence,
read_enum,
read_enum_variant,
read_enum_variant_arg,
read_struct,
read_struct_field,
readonly,
realloc,
reason,
@ -872,6 +926,7 @@ symbols! {
rustc_promotable,
rustc_regions,
rustc_reservation_impl,
rustc_serialize,
rustc_specialization_trait,
rustc_stable,
rustc_std_internal_symbol,
@ -976,6 +1031,7 @@ symbols! {
stable,
staged_api,
start,
state,
static_in_const,
static_nobundle,
static_recursion,
@ -1123,6 +1179,7 @@ symbols! {
wasm_import_module,
wasm_target_feature,
while_let,
width,
windows,
windows_subsystem,
wrapping_add,

View File

@ -26,7 +26,7 @@ use rustc_middle::ty::{
TypeFoldable, WithConstness,
};
use rustc_session::DiagnosticMessageId;
use rustc_span::symbol::sym;
use rustc_span::symbol::{kw, sym};
use rustc_span::{ExpnKind, MultiSpan, Span, DUMMY_SP};
use std::fmt;
@ -1524,7 +1524,7 @@ impl<'a, 'tcx> InferCtxtPrivExt<'tcx> for InferCtxt<'a, 'tcx> {
(self.tcx.sess.source_map().span_to_snippet(span), &obligation.cause.code)
{
let generics = self.tcx.generics_of(*def_id);
if generics.params.iter().any(|p| p.name.as_str() != "Self")
if generics.params.iter().any(|p| p.name != kw::SelfUpper)
&& !snippet.ends_with('>')
{
// FIXME: To avoid spurious suggestions in functions where type arguments

View File

@ -322,12 +322,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
let self_ty = self.tables.borrow().node_type(method_expr[0].hir_id);
let self_ty = format!("{:?}", self_ty);
let name = method_path.ident.as_str();
let name = method_path.ident.name;
let is_as_ref_able = (self_ty.starts_with("&std::option::Option")
|| self_ty.starts_with("&std::result::Result")
|| self_ty.starts_with("std::option::Option")
|| self_ty.starts_with("std::result::Result"))
&& (name == "map" || name == "and_then");
&& (name == sym::map || name == sym::and_then);
match (is_as_ref_able, self.sess().source_map().span_to_snippet(*method_span)) {
(true, Ok(src)) => {
let suggestion = format!("as_ref().{}", src);

View File

@ -430,7 +430,7 @@ pub fn run_core(options: RustdocOptions) -> (clean::Crate, RenderInfo, RenderOpt
DUMMY_SP,
extern_name,
TypeNS,
LocalDefId { local_def_index: CRATE_DEF_INDEX },
LocalDefId { local_def_index: CRATE_DEF_INDEX }.to_def_id(),
)
.unwrap_or_else(|()| {
panic!("Unable to resolve external crate {}", extern_name)

View File

@ -2230,12 +2230,15 @@ fn stability_tags(item: &clean::Item) -> String {
tags += &tag_html("deprecated", message);
}
if let Some(stab) = item.stability.as_ref().filter(|s| s.level == stability::Unstable) {
if stab.feature.as_deref() == Some("rustc_private") {
tags += &tag_html("internal", "Internal");
} else {
tags += &tag_html("unstable", "Experimental");
}
// The "rustc_private" crates are permanently unstable so it makes no sense
// to render "unstable" everywhere.
if item
.stability
.as_ref()
.map(|s| s.level == stability::Unstable && s.feature.as_deref() != Some("rustc_private"))
== Some(true)
{
tags += &tag_html("unstable", "Experimental");
}
if let Some(ref cfg) = item.attrs.cfg {
@ -2286,15 +2289,13 @@ fn short_stability(item: &clean::Item, cx: &Context) -> Vec<String> {
));
}
if let Some(stab) = item.stability.as_ref().filter(|stab| stab.level == stability::Unstable) {
let is_rustc_private = stab.feature.as_deref() == Some("rustc_private");
let mut message = if is_rustc_private {
"<span class='emoji'>⚙️</span> This is an internal compiler API."
} else {
"<span class='emoji'>🔬</span> This is a nightly-only experimental API."
}
.to_owned();
// Render unstable items. But don't render "rustc_private" crates (internal compiler crates).
// Those crates are permanently unstable so it makes no sense to render "unstable" everywhere.
if let Some(stab) = item.stability.as_ref().filter(|stab| {
stab.level == stability::Unstable && stab.feature.as_deref() != Some("rustc_private")
}) {
let mut message =
"<span class='emoji'>🔬</span> This is a nightly-only experimental API.".to_owned();
if let Some(feature) = stab.feature.as_deref() {
let mut feature = format!("<code>{}</code>", Escape(&feature));
@ -2310,17 +2311,6 @@ fn short_stability(item: &clean::Item, cx: &Context) -> Vec<String> {
}
if let Some(unstable_reason) = &stab.unstable_reason {
// Provide a more informative message than the compiler help.
let unstable_reason = if is_rustc_private {
"This crate is being loaded from the sysroot, a permanently unstable location \
for private compiler dependencies. It is not intended for general use. Prefer \
using a public version of this crate from \
[crates.io](https://crates.io) via [`Cargo.toml`]\
(https://doc.rust-lang.org/cargo/reference/specifying-dependencies.html)."
} else {
unstable_reason
};
let mut ids = cx.id_map.borrow_mut();
message = format!(
"<details><summary>{}</summary>{}</details>",
@ -2336,8 +2326,7 @@ fn short_stability(item: &clean::Item, cx: &Context) -> Vec<String> {
);
}
let class = if is_rustc_private { "internal" } else { "unstable" };
stability.push(format!("<div class='stab {}'>{}</div>", class, message));
stability.push(format!("<div class='stab unstable'>{}</div>", message));
}
if let Some(ref cfg) = item.attrs.cfg {

View File

@ -108,7 +108,7 @@ pre {
}
.sidebar .version {
border-bottom-color: #DDD;
border-bottom-color: #424c57;
}
.sidebar-title {
@ -198,7 +198,7 @@ pre.rust .comment, pre.rust .doccomment {
}
nav:not(.sidebar) {
border-bottom-color: #e0e0e0;
border-bottom-color: #424c57;
}
nav.main .current {
border-top-color: #5c6773;
@ -216,10 +216,6 @@ a {
color: #39AFD7;
}
.stab.internal a {
color: #304FFE;
}
.collapse-toggle {
color: #999;
}
@ -227,22 +223,19 @@ a {
#crate-search {
color: #c5c5c5;
background-color: #141920;
border-radius: 4px;
box-shadow: none;
border-color: #5c6773;
box-shadow: 0 0 0 1px #424c57,0 0 0 2px transparent;
border-color: #424c57;
}
.search-input {
color: #ffffff;
background-color: #141920;
box-shadow: none;
box-shadow: 0 0 0 1px #424c57,0 0 0 2px transparent;
transition: box-shadow 150ms ease-in-out;
border-radius: 4px;
margin-left: 8px;
}
#crate-search+.search-input:focus {
box-shadow: 0px 6px 20px 0px black;
box-shadow: 0 0 0 1px #148099,0 0 0 2px transparent;
}
.search-focus:disabled {
@ -254,7 +247,6 @@ a {
}
.stab.unstable,
.stab.internal,
.stab.deprecated,
.stab.portability {
color: #c5c5c5;
@ -462,7 +454,6 @@ pre.rust .doccomment {}
.content .highlighted.type {}
pre.rust .kw-2,pre.rust .prelude-ty {}
.content span.trait,.content a.trait,.block a.current.trait {}
.stab.internal {}
@media (max-width: 700px) {
.sidebar-menu {

View File

@ -172,10 +172,6 @@ a {
color: #D2991D;
}
.stab.internal a {
color: #304FFE;
}
a.test-arrow {
color: #dedede;
}
@ -214,7 +210,6 @@ a.test-arrow {
}
.stab.unstable { background: #FFF5D6; border-color: #FFC600; color: #2f2f2f; }
.stab.internal { background: #FFB9B3; border-color: #B71C1C; color: #2f2f2f; }
.stab.deprecated { background: #F3DFFF; border-color: #7F0087; color: #2f2f2f; }
.stab.portability { background: #C4ECFF; border-color: #7BA5DB; color: #2f2f2f; }

View File

@ -173,10 +173,6 @@ a {
color: #3873AD;
}
.stab.internal a {
color: #304FFE;
}
a.test-arrow {
color: #f5f5f5;
}
@ -215,7 +211,6 @@ a.test-arrow {
}
.stab.unstable { background: #FFF5D6; border-color: #FFC600; }
.stab.internal { background: #FFB9B3; border-color: #B71C1C; }
.stab.deprecated { background: #F3DFFF; border-color: #7F0087; }
.stab.portability { background: #C4ECFF; border-color: #7BA5DB; }

View File

@ -8,7 +8,7 @@ use rustc_hir::def::{
Namespace::{self, *},
PerNS, Res,
};
use rustc_hir::def_id::{DefId, LocalDefId};
use rustc_hir::def_id::DefId;
use rustc_middle::ty;
use rustc_resolve::ParentScope;
use rustc_session::lint;
@ -50,7 +50,8 @@ enum ErrorKind {
struct LinkCollector<'a, 'tcx> {
cx: &'a DocContext<'tcx>,
mod_ids: Vec<hir::HirId>,
// NOTE: this may not necessarily be a module in the current crate
mod_ids: Vec<DefId>,
}
impl<'a, 'tcx> LinkCollector<'a, 'tcx> {
@ -62,7 +63,7 @@ impl<'a, 'tcx> LinkCollector<'a, 'tcx> {
&self,
path_str: &str,
current_item: &Option<String>,
module_id: LocalDefId,
module_id: DefId,
) -> Result<(Res, Option<String>), ErrorKind> {
let cx = self.cx;
@ -124,7 +125,7 @@ impl<'a, 'tcx> LinkCollector<'a, 'tcx> {
}
/// Resolves a string as a macro.
fn macro_resolve(&self, path_str: &str, parent_id: Option<hir::HirId>) -> Option<Res> {
fn macro_resolve(&self, path_str: &str, parent_id: Option<DefId>) -> Option<Res> {
let cx = self.cx;
let path = ast::Path::from_ident(Ident::from_str(path_str));
cx.enter_resolver(|resolver| {
@ -142,8 +143,7 @@ impl<'a, 'tcx> LinkCollector<'a, 'tcx> {
if let Some(res) = resolver.all_macros().get(&Symbol::intern(path_str)) {
return Some(res.map_id(|_| panic!("unexpected id")));
}
if let Some(module_id) = parent_id.or(self.mod_ids.last().cloned()) {
let module_id = cx.tcx.hir().local_def_id(module_id);
if let Some(module_id) = parent_id {
if let Ok((_, res)) =
resolver.resolve_str_path_error(DUMMY_SP, path_str, MacroNS, module_id)
{
@ -167,15 +167,14 @@ impl<'a, 'tcx> LinkCollector<'a, 'tcx> {
disambiguator: Option<&str>,
ns: Namespace,
current_item: &Option<String>,
parent_id: Option<hir::HirId>,
parent_id: Option<DefId>,
extra_fragment: &Option<String>,
item_opt: Option<&Item>,
) -> Result<(Res, Option<String>), ErrorKind> {
let cx = self.cx;
// In case we're in a module, try to resolve the relative path.
if let Some(module_id) = parent_id.or(self.mod_ids.last().cloned()) {
let module_id = cx.tcx.hir().local_def_id(module_id);
if let Some(module_id) = parent_id {
let result = cx.enter_resolver(|resolver| {
resolver.resolve_str_path_error(DUMMY_SP, &path_str, ns, module_id)
});
@ -445,40 +444,40 @@ fn is_derive_trait_collision<T>(ns: &PerNS<Option<(Res, T)>>) -> bool {
impl<'a, 'tcx> DocFolder for LinkCollector<'a, 'tcx> {
fn fold_item(&mut self, mut item: Item) -> Option<Item> {
let item_hir_id = if item.is_mod() {
if let Some(def_id) = item.def_id.as_local() {
Some(self.cx.tcx.hir().as_local_hir_id(def_id))
} else {
debug!("attempting to fold on a non-local item: {:?}", item);
return self.fold_item_recur(item);
}
} else {
use rustc_middle::ty::DefIdTree;
let parent_node = if item.is_fake() {
// FIXME: is this correct?
None
} else {
let mut current = item.def_id;
// The immediate parent might not always be a module.
// Find the first parent which is.
loop {
if let Some(parent) = self.cx.tcx.parent(current) {
if self.cx.tcx.def_kind(parent) == DefKind::Mod {
break Some(parent);
}
current = parent;
} else {
break None;
}
}
};
// FIXME: get the resolver to work with non-local resolve scopes.
let parent_node = self.cx.as_local_hir_id(item.def_id).and_then(|hir_id| {
// FIXME: this fails hard for impls in non-module scope, but is necessary for the
// current `resolve()` implementation.
match self.cx.as_local_hir_id(self.cx.tcx.parent_module(hir_id).to_def_id()).unwrap() {
id if id != hir_id => Some(id),
_ => None,
}
});
if parent_node.is_some() {
debug!("got parent node for {:?} {:?}, id {:?}", item.type_(), item.name, item.def_id);
trace!("got parent node for {:?} {:?}, id {:?}", item.type_(), item.name, item.def_id);
}
let current_item = match item.inner {
ModuleItem(..) => {
if item.attrs.inner_docs {
if item_hir_id.unwrap() != hir::CRATE_HIR_ID { item.name.clone() } else { None }
if item.def_id.is_top_level_module() { item.name.clone() } else { None }
} else {
match parent_node.or(self.mod_ids.last().cloned()) {
Some(parent) if parent != hir::CRATE_HIR_ID => {
match parent_node.or(self.mod_ids.last().copied()) {
Some(parent) if !parent.is_top_level_module() => {
// FIXME: can we pull the parent module's name from elsewhere?
Some(self.cx.tcx.hir().name(parent).to_string())
Some(self.cx.tcx.item_name(parent).to_string())
}
_ => None,
}
@ -488,18 +487,22 @@ impl<'a, 'tcx> DocFolder for LinkCollector<'a, 'tcx> {
for_.def_id().map(|did| self.cx.tcx.item_name(did).to_string())
}
// we don't display docs on `extern crate` items anyway, so don't process them.
ExternCrateItem(..) => return self.fold_item_recur(item),
ExternCrateItem(..) => {
debug!("ignoring extern crate item {:?}", item.def_id);
return self.fold_item_recur(item);
}
ImportItem(Import::Simple(ref name, ..)) => Some(name.clone()),
MacroItem(..) => None,
_ => item.name.clone(),
};
if item.is_mod() && item.attrs.inner_docs {
self.mod_ids.push(item_hir_id.unwrap());
self.mod_ids.push(item.def_id);
}
let cx = self.cx;
let dox = item.attrs.collapsed_doc_value().unwrap_or_else(String::new);
trace!("got documentation '{}'", dox);
look_for_tests(&cx, &dox, &item, true);
@ -541,6 +544,8 @@ impl<'a, 'tcx> DocFolder for LinkCollector<'a, 'tcx> {
});
for (ori_link, link_range) in markdown_links(&dox) {
trace!("considering link '{}'", ori_link);
// Bail early for real links.
if ori_link.contains('/') {
continue;
@ -641,8 +646,11 @@ impl<'a, 'tcx> DocFolder for LinkCollector<'a, 'tcx> {
// we've already pushed this node onto the resolution stack but
// for outer comments we explicitly try and resolve against the
// parent_node first.
let base_node =
if item.is_mod() && item.attrs.inner_docs { None } else { parent_node };
let base_node = if item.is_mod() && item.attrs.inner_docs {
self.mod_ids.last().copied()
} else {
parent_node
};
// replace `Self` with suitable item's parent name
if path_str.starts_with("Self::") {
@ -826,7 +834,7 @@ impl<'a, 'tcx> DocFolder for LinkCollector<'a, 'tcx> {
}
if item.is_mod() && !item.attrs.inner_docs {
self.mod_ids.push(item_hir_id.unwrap());
self.mod_ids.push(item.def_id);
}
if item.is_mod() {
@ -864,6 +872,7 @@ fn build_diagnostic(
Some(hir_id) => hir_id,
None => {
// If non-local, no need to check anything.
info!("ignoring warning from parent crate: {}", err_msg);
return;
}
};

View File

@ -62,5 +62,29 @@ fn main() {
}
println!("cargo:rustc-link-lib=c");
println!("cargo:rustc-link-lib=compiler_rt");
} else if (target.contains("sgx") && target.contains("fortanix"))
|| target.contains("hermit")
|| target.contains("l4re")
|| target.contains("redox")
|| target.contains("haiku")
|| target.contains("vxworks")
|| target.contains("wasm32")
|| target.contains("asmjs")
{
// These platforms don't have any special requirements.
} else {
// This is for Cargo's build-std support, to mark std as unstable for
// typically no_std platforms.
// This covers:
// - os=none ("bare metal" targets)
// - mipsel-sony-psp
// - nvptx64-nvidia-cuda
// - avr-unknown-unknown
// - tvos (aarch64-apple-tvos, x86_64-apple-tvos)
// - uefi (x86_64-unknown-uefi, i686-unknown-uefi)
// - JSON targets
// - Any new targets that have not been explicitly added above.
println!("cargo:rustc-cfg=feature=\"restricted-std\"");
}
println!("cargo:rustc-env=STD_ENV_ARCH={}", env::var("CARGO_CFG_TARGET_ARCH").unwrap());
}

View File

@ -882,7 +882,7 @@ pub mod consts {
/// - s390x
/// - sparc64
#[stable(feature = "env", since = "1.0.0")]
pub const ARCH: &str = super::arch::ARCH;
pub const ARCH: &str = env!("STD_ENV_ARCH");
/// The family of the operating system. Example value is `unix`.
///
@ -966,81 +966,6 @@ pub mod consts {
pub const EXE_EXTENSION: &str = os::EXE_EXTENSION;
}
#[cfg(target_arch = "x86")]
mod arch {
pub const ARCH: &str = "x86";
}
#[cfg(target_arch = "x86_64")]
mod arch {
pub const ARCH: &str = "x86_64";
}
#[cfg(target_arch = "arm")]
mod arch {
pub const ARCH: &str = "arm";
}
#[cfg(target_arch = "aarch64")]
mod arch {
pub const ARCH: &str = "aarch64";
}
#[cfg(target_arch = "mips")]
mod arch {
pub const ARCH: &str = "mips";
}
#[cfg(target_arch = "mips64")]
mod arch {
pub const ARCH: &str = "mips64";
}
#[cfg(target_arch = "powerpc")]
mod arch {
pub const ARCH: &str = "powerpc";
}
#[cfg(target_arch = "powerpc64")]
mod arch {
pub const ARCH: &str = "powerpc64";
}
#[cfg(target_arch = "s390x")]
mod arch {
pub const ARCH: &str = "s390x";
}
#[cfg(target_arch = "sparc64")]
mod arch {
pub const ARCH: &str = "sparc64";
}
#[cfg(target_arch = "le32")]
mod arch {
pub const ARCH: &str = "le32";
}
#[cfg(target_arch = "asmjs")]
mod arch {
pub const ARCH: &str = "asmjs";
}
#[cfg(target_arch = "wasm32")]
mod arch {
pub const ARCH: &str = "wasm32";
}
#[cfg(target_arch = "hexagon")]
mod arch {
pub const ARCH: &'static str = "hexagon";
}
#[cfg(target_arch = "riscv64")]
mod arch {
pub const ARCH: &'static str = "riscv64";
}
#[cfg(test)]
mod tests {
use super::*;

View File

@ -198,7 +198,8 @@
//! [primitive types]: ../book/ch03-02-data-types.html
//! [rust-discord]: https://discord.gg/rust-lang
#![stable(feature = "rust1", since = "1.0.0")]
#![cfg_attr(not(feature = "restricted-std"), stable(feature = "rust1", since = "1.0.0"))]
#![cfg_attr(feature = "restricted-std", unstable(feature = "restricted_std", issue = "none"))]
#![doc(
html_root_url = "https://doc.rust-lang.org/nightly/",
html_playground_url = "https://play.rust-lang.org/",
@ -554,3 +555,9 @@ include!("primitive_docs.rs");
// the rustdoc documentation for the existing keywords. Using `include!`
// because rustdoc only looks for these modules at the crate level.
include!("keyword_docs.rs");
// This is required to avoid an unstable error when `restricted-std` is not
// enabled. The use of #![feature(restricted_std)] in rustc-std-workspace-std
// is unconditional, so the unstable feature needs to be defined somewhere.
#[cfg_attr(not(feature = "restricted-std"), unstable(feature = "restricted_std", issue = "none"))]
mod __restricted_std_workaround {}

View File

@ -694,7 +694,6 @@ mod tests {
#[test]
#[cfg_attr(target_os = "emscripten", ignore)]
#[cfg_attr(target_env = "sgx", ignore)] // FIXME: https://github.com/fortanix/rust-sgx/issues/31
fn wait_timeout_wait() {
let m = Arc::new(Mutex::new(()));
let c = Arc::new(Condvar::new());
@ -714,7 +713,6 @@ mod tests {
#[test]
#[cfg_attr(target_os = "emscripten", ignore)]
#[cfg_attr(target_env = "sgx", ignore)] // FIXME: https://github.com/fortanix/rust-sgx/issues/31
fn wait_timeout_while_wait() {
let m = Arc::new(Mutex::new(()));
let c = Arc::new(Condvar::new());
@ -739,7 +737,6 @@ mod tests {
#[test]
#[cfg_attr(target_os = "emscripten", ignore)]
#[cfg_attr(target_env = "sgx", ignore)] // FIXME: https://github.com/fortanix/rust-sgx/issues/31
fn wait_timeout_while_wake() {
let pair = Arc::new((Mutex::new(false), Condvar::new()));
let pair_copy = pair.clone();
@ -763,7 +760,6 @@ mod tests {
#[test]
#[cfg_attr(target_os = "emscripten", ignore)]
#[cfg_attr(target_env = "sgx", ignore)] // FIXME: https://github.com/fortanix/rust-sgx/issues/31
fn wait_timeout_wake() {
let m = Arc::new(Mutex::new(()));
let c = Arc::new(Condvar::new());

View File

@ -2088,7 +2088,6 @@ mod tests {
}
#[test]
#[cfg_attr(target_env = "sgx", ignore)] // FIXME: https://github.com/fortanix/rust-sgx/issues/31
fn oneshot_single_thread_recv_timeout() {
let (tx, rx) = channel();
tx.send(()).unwrap();
@ -2099,7 +2098,6 @@ mod tests {
}
#[test]
#[cfg_attr(target_env = "sgx", ignore)] // FIXME: https://github.com/fortanix/rust-sgx/issues/31
fn stress_recv_timeout_two_threads() {
let (tx, rx) = channel();
let stress = stress_factor() + 100;
@ -2130,7 +2128,6 @@ mod tests {
}
#[test]
#[cfg_attr(target_env = "sgx", ignore)] // FIXME: https://github.com/fortanix/rust-sgx/issues/31
fn recv_timeout_upgrade() {
let (tx, rx) = channel::<()>();
let timeout = Duration::from_millis(1);
@ -2142,7 +2139,6 @@ mod tests {
}
#[test]
#[cfg_attr(target_env = "sgx", ignore)] // FIXME: https://github.com/fortanix/rust-sgx/issues/31
fn stress_recv_timeout_shared() {
let (tx, rx) = channel();
let stress = stress_factor() + 100;
@ -2173,7 +2169,6 @@ mod tests {
}
#[test]
#[cfg_attr(target_env = "sgx", ignore)] // FIXME: https://github.com/fortanix/rust-sgx/issues/31
fn very_long_recv_timeout_wont_panic() {
let (tx, rx) = channel::<()>();
let join_handle = thread::spawn(move || rx.recv_timeout(Duration::from_secs(u64::MAX)));
@ -2195,7 +2190,6 @@ mod tests {
}
#[test]
#[cfg_attr(target_env = "sgx", ignore)] // FIXME: https://github.com/fortanix/rust-sgx/issues/31
fn shared_recv_timeout() {
let (tx, rx) = channel();
let total = 5;
@ -2425,7 +2419,6 @@ mod sync_tests {
}
#[test]
#[cfg_attr(target_env = "sgx", ignore)] // FIXME: https://github.com/fortanix/rust-sgx/issues/31
fn recv_timeout() {
let (tx, rx) = sync_channel::<i32>(1);
assert_eq!(rx.recv_timeout(Duration::from_millis(1)), Err(RecvTimeoutError::Timeout));
@ -2517,7 +2510,6 @@ mod sync_tests {
}
#[test]
#[cfg_attr(target_env = "sgx", ignore)] // FIXME: https://github.com/fortanix/rust-sgx/issues/31
fn stress_recv_timeout_two_threads() {
let (tx, rx) = sync_channel::<i32>(0);
@ -2543,7 +2535,6 @@ mod sync_tests {
}
#[test]
#[cfg_attr(target_env = "sgx", ignore)] // FIXME: https://github.com/fortanix/rust-sgx/issues/31
fn stress_recv_timeout_shared() {
const AMT: u32 = 1000;
const NTHREADS: u32 = 8;

View File

@ -48,7 +48,8 @@ cfg_if::cfg_if! {
mod sgx;
pub use self::sgx::*;
} else {
compile_error!("libstd doesn't compile for this platform yet");
mod unsupported;
pub use self::unsupported::*;
}
}

View File

@ -1,6 +1,8 @@
use crate::cmp;
use crate::io::{Error as IoError, IoSlice, IoSliceMut, Result as IoResult};
use crate::time::Duration;
use crate::convert::TryFrom;
use crate::io::{Error as IoError, ErrorKind, IoSlice, IoSliceMut, Result as IoResult};
use crate::sys::rand::rdrand64;
use crate::time::{Duration, Instant};
pub(crate) mod alloc;
#[macro_use]
@ -149,10 +151,94 @@ pub fn exit(panic: bool) -> ! {
/// Usercall `wait`. See the ABI documentation for more information.
#[unstable(feature = "sgx_platform", issue = "56975")]
pub fn wait(event_mask: u64, timeout: u64) -> IoResult<u64> {
pub fn wait(event_mask: u64, mut timeout: u64) -> IoResult<u64> {
if timeout != WAIT_NO && timeout != WAIT_INDEFINITE {
// We don't want people to rely on accuracy of timeouts to make
// security decisions in an SGX enclave. That's why we add a random
// amount not exceeding +/- 10% to the timeout value to discourage
// people from relying on accuracy of timeouts while providing a way
// to make things work in other cases. Note that in the SGX threat
// model the enclave runner which is serving the wait usercall is not
// trusted to ensure accurate timeouts.
if let Ok(timeout_signed) = i64::try_from(timeout) {
let tenth = timeout_signed / 10;
let deviation = (rdrand64() as i64).checked_rem(tenth).unwrap_or(0);
timeout = timeout_signed.saturating_add(deviation) as _;
}
}
unsafe { raw::wait(event_mask, timeout).from_sgx_result() }
}
/// This function makes an effort to wait for a non-spurious event at least as
/// long as `duration`. Note that in general there is no guarantee about accuracy
/// of time and timeouts in SGX model. The enclave runner serving usercalls may
/// lie about current time and/or ignore timeout values.
///
/// Once the event is observed, `should_wake_up` will be used to determine
/// whether or not the event was spurious.
#[unstable(feature = "sgx_platform", issue = "56975")]
pub fn wait_timeout<F>(event_mask: u64, duration: Duration, should_wake_up: F)
where
F: Fn() -> bool,
{
// Calls the wait usercall and checks the result. Returns true if event was
// returned, and false if WouldBlock/TimedOut was returned.
// If duration is None, it will use WAIT_NO.
fn wait_checked(event_mask: u64, duration: Option<Duration>) -> bool {
let timeout = duration.map_or(raw::WAIT_NO, |duration| {
cmp::min((u64::MAX - 1) as u128, duration.as_nanos()) as u64
});
match wait(event_mask, timeout) {
Ok(eventset) => {
if event_mask == 0 {
rtabort!("expected wait() to return Err, found Ok.");
}
rtassert!(eventset != 0 && eventset & !event_mask == 0);
true
}
Err(e) => {
rtassert!(e.kind() == ErrorKind::TimedOut || e.kind() == ErrorKind::WouldBlock);
false
}
}
}
match wait_checked(event_mask, Some(duration)) {
false => return, // timed out
true if should_wake_up() => return, // woken up
true => {} // spurious event
}
// Drain all cached events.
// Note that `event_mask != 0` is implied if we get here.
loop {
match wait_checked(event_mask, None) {
false => break, // no more cached events
true if should_wake_up() => return, // woken up
true => {} // spurious event
}
}
// Continue waiting, but take note of time spent waiting so we don't wait
// forever. We intentionally don't call `Instant::now()` before this point
// to avoid the cost of the `insecure_time` usercall in case there are no
// spurious wakeups.
let start = Instant::now();
let mut remaining = duration;
loop {
match wait_checked(event_mask, Some(remaining)) {
false => return, // timed out
true if should_wake_up() => return, // woken up
true => {} // spurious event
}
remaining = match duration.checked_sub(start.elapsed()) {
Some(remaining) => remaining,
None => break,
}
}
}
/// Usercall `send`. See the ABI documentation for more information.
#[unstable(feature = "sgx_platform", issue = "56975")]
pub fn send(event_set: u64, tcs: Option<Tcs>) -> IoResult<()> {

View File

@ -31,8 +31,10 @@ impl Condvar {
mutex.lock()
}
pub unsafe fn wait_timeout(&self, _mutex: &Mutex, _dur: Duration) -> bool {
rtabort!("timeout not supported in SGX");
pub unsafe fn wait_timeout(&self, mutex: &Mutex, dur: Duration) -> bool {
let success = WaitQueue::wait_timeout(&self.inner, dur, || mutex.unlock());
mutex.lock();
success
}
#[inline]

View File

@ -137,8 +137,8 @@ pub extern "C" fn __rust_abort() {
abort_internal();
}
pub fn hashmap_random_keys() -> (u64, u64) {
fn rdrand64() -> u64 {
pub mod rand {
pub fn rdrand64() -> u64 {
unsafe {
let mut ret: u64 = 0;
for _ in 0..10 {
@ -149,7 +149,10 @@ pub fn hashmap_random_keys() -> (u64, u64) {
rtabort!("Failed to obtain random data");
}
}
(rdrand64(), rdrand64())
}
pub fn hashmap_random_keys() -> (u64, u64) {
(self::rand::rdrand64(), self::rand::rdrand64())
}
pub use crate::sys_common::{AsInner, FromInner, IntoInner};

View File

@ -73,8 +73,8 @@ impl Thread {
// FIXME: could store this pointer in TLS somewhere
}
pub fn sleep(_dur: Duration) {
rtabort!("can't sleep"); // FIXME
pub fn sleep(dur: Duration) {
usercalls::wait_timeout(0, dur, || true);
}
pub fn join(self) {

View File

@ -1,16 +1,17 @@
//! A simple queue implementation for synchronization primitives.
//!
//! This queue is used to implement condition variable and mutexes.
//!
//! Users of this API are expected to use the `WaitVariable<T>` type. Since
//! that type is not `Sync`, it needs to be protected by e.g., a `SpinMutex` to
//! allow shared access.
//!
//! Since userspace may send spurious wake-ups, the wakeup event state is
//! recorded in the enclave. The wakeup event state is protected by a spinlock.
//! The queue and associated wait state are stored in a `WaitVariable`.
use crate::num::NonZeroUsize;
/// A simple queue implementation for synchronization primitives.
///
/// This queue is used to implement condition variable and mutexes.
///
/// Users of this API are expected to use the `WaitVariable<T>` type. Since
/// that type is not `Sync`, it needs to be protected by e.g., a `SpinMutex` to
/// allow shared access.
///
/// Since userspace may send spurious wake-ups, the wakeup event state is
/// recorded in the enclave. The wakeup event state is protected by a spinlock.
/// The queue and associated wait state are stored in a `WaitVariable`.
use crate::ops::{Deref, DerefMut};
use crate::time::Duration;
use super::abi::thread;
use super::abi::usercalls;
@ -158,6 +159,34 @@ impl WaitQueue {
}
}
/// Adds the calling thread to the `WaitVariable`'s wait queue, then wait
/// until a wakeup event or timeout. If event was observed, returns true.
/// If not, it will remove the calling thread from the wait queue.
pub fn wait_timeout<T, F: FnOnce()>(
lock: &SpinMutex<WaitVariable<T>>,
timeout: Duration,
before_wait: F,
) -> bool {
// very unsafe: check requirements of UnsafeList::push
unsafe {
let mut entry = UnsafeListEntry::new(SpinMutex::new(WaitEntry {
tcs: thread::current(),
wake: false,
}));
let entry_lock = lock.lock().queue.inner.push(&mut entry);
before_wait();
usercalls::wait_timeout(EV_UNPARK, timeout, || entry_lock.lock().wake);
// acquire the wait queue's lock first to avoid deadlock.
let mut guard = lock.lock();
let success = entry_lock.lock().wake;
if !success {
// nobody is waking us up, so remove our entry from the wait queue.
guard.queue.inner.remove(&mut entry);
}
success
}
}
/// Either find the next waiter on the wait queue, or return the mutex
/// guard unchanged.
///
@ -325,6 +354,31 @@ mod unsafe_list {
Some((*first.as_ptr()).value.as_ref().unwrap())
}
}
/// Removes an entry from the list.
///
/// # Safety
///
/// The caller must ensure that `entry` has been pushed onto `self`
/// prior to this call and has not moved since then.
pub unsafe fn remove(&mut self, entry: &mut UnsafeListEntry<T>) {
rtassert!(!self.is_empty());
// BEFORE:
// /----\ next ---> /-----\ next ---> /----\
// ... |prev| |entry| |next| ...
// \----/ <--- prev \-----/ <--- prev \----/
//
// AFTER:
// /----\ next ---> /----\
// ... |prev| |next| ...
// \----/ <--- prev \----/
let mut prev = entry.prev;
let mut next = entry.next;
prev.as_mut().next = next;
next.as_mut().prev = prev;
entry.next = NonNull::dangling();
entry.prev = NonNull::dangling();
}
}
#[cfg(test)]
@ -354,6 +408,51 @@ mod unsafe_list {
}
}
#[test]
fn push_remove() {
unsafe {
let mut node = UnsafeListEntry::new(1234);
let mut list = UnsafeList::new();
assert_eq!(list.push(&mut node), &1234);
list.remove(&mut node);
assert_empty(&mut list);
}
}
#[test]
fn push_remove_pop() {
unsafe {
let mut node1 = UnsafeListEntry::new(11);
let mut node2 = UnsafeListEntry::new(12);
let mut node3 = UnsafeListEntry::new(13);
let mut node4 = UnsafeListEntry::new(14);
let mut node5 = UnsafeListEntry::new(15);
let mut list = UnsafeList::new();
assert_eq!(list.push(&mut node1), &11);
assert_eq!(list.push(&mut node2), &12);
assert_eq!(list.push(&mut node3), &13);
assert_eq!(list.push(&mut node4), &14);
assert_eq!(list.push(&mut node5), &15);
list.remove(&mut node1);
assert_eq!(list.pop().unwrap(), &12);
list.remove(&mut node3);
assert_eq!(list.pop().unwrap(), &14);
list.remove(&mut node5);
assert_empty(&mut list);
assert_eq!(list.push(&mut node1), &11);
assert_eq!(list.pop().unwrap(), &11);
assert_empty(&mut list);
assert_eq!(list.push(&mut node3), &13);
assert_eq!(list.push(&mut node4), &14);
list.remove(&mut node3);
list.remove(&mut node4);
assert_empty(&mut list);
}
}
#[test]
fn complex_pushes_pops() {
unsafe {
@ -474,7 +573,7 @@ mod spin_mutex {
use super::*;
use crate::sync::Arc;
use crate::thread;
use crate::time::{Duration, SystemTime};
use crate::time::Duration;
#[test]
fn sleep() {
@ -485,11 +584,7 @@ mod spin_mutex {
*mutex2.lock() = 1;
});
// "sleep" for 50ms
// FIXME: https://github.com/fortanix/rust-sgx/issues/31
let start = SystemTime::now();
let max = Duration::from_millis(50);
while start.elapsed().unwrap() < max {}
thread::sleep(Duration::from_millis(50));
assert_eq!(*guard, 0);
drop(guard);

View File

@ -0,0 +1,22 @@
use crate::alloc::{GlobalAlloc, Layout, System};
#[stable(feature = "alloc_system_type", since = "1.28.0")]
unsafe impl GlobalAlloc for System {
#[inline]
unsafe fn alloc(&self, _layout: Layout) -> *mut u8 {
0 as *mut u8
}
#[inline]
unsafe fn alloc_zeroed(&self, _layout: Layout) -> *mut u8 {
0 as *mut u8
}
#[inline]
unsafe fn dealloc(&self, _ptr: *mut u8, _layout: Layout) {}
#[inline]
unsafe fn realloc(&self, _ptr: *mut u8, _layout: Layout, _new_size: usize) -> *mut u8 {
0 as *mut u8
}
}

View File

@ -0,0 +1,38 @@
use crate::ffi::OsString;
pub unsafe fn init(_argc: isize, _argv: *const *const u8) {}
pub unsafe fn cleanup() {}
pub struct Args {}
pub fn args() -> Args {
Args {}
}
impl Args {
pub fn inner_debug(&self) -> &[OsString] {
&[]
}
}
impl Iterator for Args {
type Item = OsString;
fn next(&mut self) -> Option<OsString> {
None
}
fn size_hint(&self) -> (usize, Option<usize>) {
(0, Some(0))
}
}
impl ExactSizeIterator for Args {
fn len(&self) -> usize {
0
}
}
impl DoubleEndedIterator for Args {
fn next_back(&mut self) -> Option<OsString> {
None
}
}

View File

@ -0,0 +1,48 @@
use crate::io as std_io;
pub mod memchr {
pub use core::slice::memchr::{memchr, memrchr};
}
pub use crate::sys_common::os_str_bytes as os_str;
// This is not necessarily correct. May want to consider making it part of the
// spec definition?
use crate::os::raw::c_char;
#[cfg(not(test))]
pub fn init() {}
pub fn unsupported<T>() -> std_io::Result<T> {
Err(unsupported_err())
}
pub fn unsupported_err() -> std_io::Error {
std_io::Error::new(std_io::ErrorKind::Other, "operation not supported on this platform")
}
pub fn decode_error_kind(_code: i32) -> crate::io::ErrorKind {
crate::io::ErrorKind::Other
}
pub fn abort_internal() -> ! {
core::intrinsics::abort();
}
pub fn hashmap_random_keys() -> (u64, u64) {
(1, 2)
}
// This enum is used as the storage for a bunch of types which can't actually
// exist.
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Debug, Hash)]
pub enum Void {}
pub unsafe fn strlen(mut s: *const c_char) -> usize {
let mut n = 0;
while *s != 0 {
n += 1;
s = s.offset(1);
}
return n;
}

View File

@ -18,11 +18,11 @@ impl Condvar {
pub unsafe fn notify_all(&self) {}
pub unsafe fn wait(&self, _mutex: &Mutex) {
panic!("can't block with web assembly")
panic!("condvar wait not supported")
}
pub unsafe fn wait_timeout(&self, _mutex: &Mutex, _dur: Duration) -> bool {
panic!("can't block with web assembly");
panic!("condvar wait not supported");
}
#[inline]

View File

@ -0,0 +1,9 @@
pub mod os {
pub const FAMILY: &str = "";
pub const OS: &str = "";
pub const DLL_PREFIX: &str = "";
pub const DLL_SUFFIX: &str = "";
pub const DLL_EXTENSION: &str = "";
pub const EXE_SUFFIX: &str = "";
pub const EXE_EXTENSION: &str = "";
}

View File

@ -0,0 +1,24 @@
pub mod alloc;
pub mod args;
pub mod cmath;
pub mod condvar;
pub mod env;
pub mod fs;
pub mod io;
pub mod mutex;
pub mod net;
pub mod os;
pub mod path;
pub mod pipe;
pub mod process;
pub mod rwlock;
pub mod stack_overflow;
pub mod stdio;
pub mod thread;
#[cfg(target_thread_local)]
pub mod thread_local_dtor;
pub mod thread_local_key;
pub mod time;
mod common;
pub use common::*;

View File

@ -5,9 +5,10 @@ pub struct Mutex {
}
unsafe impl Send for Mutex {}
unsafe impl Sync for Mutex {} // no threads on wasm
unsafe impl Sync for Mutex {} // no threads on this platform
impl Mutex {
#[rustc_const_stable(feature = "const_sys_mutex_new", since = "1.0.0")]
pub const fn new() -> Mutex {
Mutex { locked: UnsafeCell::new(false) }
}
@ -42,8 +43,8 @@ impl Mutex {
pub unsafe fn destroy(&self) {}
}
// All empty stubs because wasm has no threads yet, so lock acquisition always
// succeeds.
// All empty stubs because this platform does not yet support threads, so lock
// acquisition always succeeds.
pub struct ReentrantMutex {}
impl ReentrantMutex {

View File

@ -1,10 +1,9 @@
use super::{unsupported, Void};
use crate::error::Error as StdError;
use crate::ffi::{OsStr, OsString};
use crate::fmt;
use crate::io;
use crate::path::{self, PathBuf};
use crate::str;
use crate::sys::{unsupported, Void};
pub fn errno() -> i32 {
0
@ -48,14 +47,14 @@ where
impl fmt::Display for JoinPathsError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
"not supported on wasm yet".fmt(f)
"not supported on this platform yet".fmt(f)
}
}
impl StdError for JoinPathsError {
#[allow(deprecated)]
fn description(&self) -> &str {
"not supported on wasm yet"
"not supported on this platform yet"
}
}
@ -73,7 +72,7 @@ impl Iterator for Env {
}
pub fn env() -> Env {
panic!("not supported on web assembly")
panic!("not supported on this platform")
}
pub fn getenv(_: &OsStr) -> io::Result<Option<OsString>> {
@ -81,15 +80,15 @@ pub fn getenv(_: &OsStr) -> io::Result<Option<OsString>> {
}
pub fn setenv(_: &OsStr, _: &OsStr) -> io::Result<()> {
Err(io::Error::new(io::ErrorKind::Other, "cannot set env vars on wasm32-unknown-unknown"))
Err(io::Error::new(io::ErrorKind::Other, "cannot set env vars on this platform"))
}
pub fn unsetenv(_: &OsStr) -> io::Result<()> {
Err(io::Error::new(io::ErrorKind::Other, "cannot unset env vars on wasm32-unknown-unknown"))
Err(io::Error::new(io::ErrorKind::Other, "cannot unset env vars on this platform"))
}
pub fn temp_dir() -> PathBuf {
panic!("no filesystem on wasm")
panic!("no filesystem on this platform")
}
pub fn home_dir() -> Option<PathBuf> {
@ -97,11 +96,9 @@ pub fn home_dir() -> Option<PathBuf> {
}
pub fn exit(_code: i32) -> ! {
unsafe {
crate::arch::wasm32::unreachable();
}
crate::intrinsics::abort()
}
pub fn getpid() -> u32 {
panic!("no pids on wasm")
panic!("no pids on this platform")
}

View File

@ -5,7 +5,7 @@ pub struct RWLock {
}
unsafe impl Send for RWLock {}
unsafe impl Sync for RWLock {} // no threads on wasm
unsafe impl Sync for RWLock {} // no threads on this platform
impl RWLock {
pub const fn new() -> RWLock {

View File

@ -0,0 +1,41 @@
use super::{unsupported, Void};
use crate::ffi::CStr;
use crate::io;
use crate::time::Duration;
pub struct Thread(Void);
pub const DEFAULT_MIN_STACK_SIZE: usize = 4096;
impl Thread {
// unsafe: see thread::Builder::spawn_unchecked for safety requirements
pub unsafe fn new(_stack: usize, _p: Box<dyn FnOnce()>) -> io::Result<Thread> {
unsupported()
}
pub fn yield_now() {
// do nothing
}
pub fn set_name(_name: &CStr) {
// nope
}
pub fn sleep(_dur: Duration) {
panic!("can't sleep");
}
pub fn join(self) {
match self.0 {}
}
}
pub mod guard {
pub type Guard = !;
pub unsafe fn current() -> Option<Guard> {
None
}
pub unsafe fn init() -> Option<Guard> {
None
}
}

View File

@ -2,25 +2,25 @@ pub type Key = usize;
#[inline]
pub unsafe fn create(_dtor: Option<unsafe extern "C" fn(*mut u8)>) -> Key {
panic!("should not be used on the wasm target");
panic!("should not be used on this target");
}
#[inline]
pub unsafe fn set(_key: Key, _value: *mut u8) {
panic!("should not be used on the wasm target");
panic!("should not be used on this target");
}
#[inline]
pub unsafe fn get(_key: Key) -> *mut u8 {
panic!("should not be used on the wasm target");
panic!("should not be used on this target");
}
#[inline]
pub unsafe fn destroy(_key: Key) {
panic!("should not be used on the wasm target");
panic!("should not be used on this target");
}
#[inline]
pub fn requires_synchronized_create() -> bool {
panic!("should not be used on the wasm target");
panic!("should not be used on this target");
}

View File

@ -10,7 +10,7 @@ pub const UNIX_EPOCH: SystemTime = SystemTime(Duration::from_secs(0));
impl Instant {
pub fn now() -> Instant {
panic!("time not implemented on wasm32-unknown-unknown")
panic!("time not implemented on this platform")
}
pub const fn zero() -> Instant {
@ -36,7 +36,7 @@ impl Instant {
impl SystemTime {
pub fn now() -> SystemTime {
panic!("time not implemented on wasm32-unknown-unknown")
panic!("time not implemented on this platform")
}
pub fn sub_time(&self, other: &SystemTime) -> Result<Duration, Duration> {

View File

@ -16,21 +16,18 @@
use crate::io as std_io;
use crate::mem;
use crate::os::raw::c_char;
pub mod alloc;
pub mod args;
#[path = "../wasm/cmath.rs"]
#[path = "../unsupported/cmath.rs"]
pub mod cmath;
#[path = "../wasm/condvar.rs"]
#[path = "../unsupported/condvar.rs"]
pub mod condvar;
pub mod env;
pub mod fd;
pub mod fs;
pub mod io;
#[path = "../wasm/memchr.rs"]
pub mod memchr;
#[path = "../wasm/mutex.rs"]
#[path = "../unsupported/mutex.rs"]
pub mod mutex;
pub mod net;
pub mod os;
@ -39,28 +36,22 @@ pub mod ext;
pub mod path;
pub mod pipe;
pub mod process;
#[path = "../wasm/rwlock.rs"]
#[path = "../unsupported/rwlock.rs"]
pub mod rwlock;
#[path = "../wasm/stack_overflow.rs"]
#[path = "../unsupported/stack_overflow.rs"]
pub mod stack_overflow;
pub mod stdio;
pub mod thread;
#[path = "../wasm/thread_local_dtor.rs"]
#[path = "../unsupported/thread_local_dtor.rs"]
pub mod thread_local_dtor;
#[path = "../wasm/thread_local_key.rs"]
#[path = "../unsupported/thread_local_key.rs"]
pub mod thread_local_key;
pub mod time;
#[cfg(not(test))]
pub fn init() {}
pub fn unsupported<T>() -> std_io::Result<T> {
Err(unsupported_err())
}
pub fn unsupported_err() -> std_io::Error {
std_io::Error::new(std_io::ErrorKind::Other, "operation not supported on wasm yet")
}
#[path = "../unsupported/common.rs"]
#[allow(unused)]
mod common;
pub use common::*;
pub fn decode_error_kind(errno: i32) -> std_io::ErrorKind {
use std_io::ErrorKind::*;
@ -86,20 +77,6 @@ pub fn decode_error_kind(errno: i32) -> std_io::ErrorKind {
}
}
// This enum is used as the storage for a bunch of types which can't actually
// exist.
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Debug, Hash)]
pub enum Void {}
pub unsafe fn strlen(mut s: *const c_char) -> usize {
let mut n = 0;
while *s != 0 {
n += 1;
s = s.offset(1);
}
return n;
}
pub fn abort_internal() -> ! {
unsafe { libc::abort() }
}

View File

@ -1 +0,0 @@
pub use core::slice::memchr::{memchr, memrchr};

View File

@ -14,25 +14,35 @@
//! compiling for wasm. That way it's a compile time error for something that's
//! guaranteed to be a runtime error!
use crate::os::raw::c_char;
pub mod alloc;
pub mod args;
#[path = "../unsupported/cmath.rs"]
pub mod cmath;
pub mod env;
#[path = "../unsupported/fs.rs"]
pub mod fs;
#[path = "../unsupported/io.rs"]
pub mod io;
pub mod memchr;
#[path = "../unsupported/net.rs"]
pub mod net;
#[path = "../unsupported/os.rs"]
pub mod os;
#[path = "../unsupported/path.rs"]
pub mod path;
#[path = "../unsupported/pipe.rs"]
pub mod pipe;
#[path = "../unsupported/process.rs"]
pub mod process;
#[path = "../unsupported/stack_overflow.rs"]
pub mod stack_overflow;
#[path = "../unsupported/stdio.rs"]
pub mod stdio;
pub mod thread;
#[path = "../unsupported/thread_local_dtor.rs"]
pub mod thread_local_dtor;
#[path = "../unsupported/thread_local_key.rs"]
pub mod thread_local_key;
#[path = "../unsupported/time.rs"]
pub mod time;
pub use crate::sys_common::os_str_bytes as os_str;
@ -46,50 +56,15 @@ cfg_if::cfg_if! {
#[path = "rwlock_atomics.rs"]
pub mod rwlock;
} else {
#[path = "../unsupported/condvar.rs"]
pub mod condvar;
#[path = "../unsupported/mutex.rs"]
pub mod mutex;
#[path = "../unsupported/rwlock.rs"]
pub mod rwlock;
}
}
#[cfg(not(test))]
pub fn init() {}
pub fn unsupported<T>() -> crate::io::Result<T> {
Err(unsupported_err())
}
pub fn unsupported_err() -> crate::io::Error {
crate::io::Error::new(crate::io::ErrorKind::Other, "operation not supported on wasm yet")
}
pub fn decode_error_kind(_code: i32) -> crate::io::ErrorKind {
crate::io::ErrorKind::Other
}
// This enum is used as the storage for a bunch of types which can't actually
// exist.
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Debug, Hash)]
pub enum Void {}
pub unsafe fn strlen(mut s: *const c_char) -> usize {
let mut n = 0;
while *s != 0 {
n += 1;
s = s.offset(1);
}
return n;
}
pub fn abort_internal() -> ! {
unsafe { crate::arch::wasm32::unreachable() }
}
// We don't have randomness yet, but I totally used a random number generator to
// generate these numbers.
//
// More seriously though this is just for DOS protection in hash maps. It's ok
// if we don't do that on wasm just yet.
pub fn hashmap_random_keys() -> (u64, u64) {
(1, 2)
}
#[path = "../unsupported/common.rs"]
mod common;
pub use common::*;

View File

@ -51,13 +51,9 @@ pub mod condvar;
pub mod fs;
pub mod io;
pub mod mutex;
#[cfg(any(doc, // see `mod os`, docs are generated for multiple platforms
unix,
target_os = "redox",
target_os = "cloudabi",
target_os = "hermit",
target_arch = "wasm32",
all(target_vendor = "fortanix", target_env = "sgx")))]
// `doc` is required because `sys/mod.rs` imports `unix/ext/mod.rs` on Windows
// when generating documentation.
#[cfg(any(doc, not(windows)))]
pub mod os_str_bytes;
pub mod poison;
pub mod process;
@ -74,6 +70,7 @@ cfg_if::cfg_if! {
if #[cfg(any(target_os = "cloudabi",
target_os = "l4re",
target_os = "hermit",
feature = "restricted-std",
all(target_arch = "wasm32", not(target_os = "emscripten")),
all(target_vendor = "fortanix", target_env = "sgx")))] {
pub use crate::sys::net;

View File

@ -17,6 +17,7 @@ impl Mutex {
/// Also, until `init` is called, behavior is undefined if this
/// mutex is ever used reentrantly, i.e., `raw_lock` or `try_lock`
/// are called by the thread currently holding the lock.
#[rustc_const_stable(feature = "const_sys_mutex_new", since = "1.0.0")]
pub const fn new() -> Mutex {
Mutex(imp::Mutex::new())
}

View File

@ -1741,7 +1741,6 @@ mod tests {
}
#[test]
#[cfg_attr(target_env = "sgx", ignore)] // FIXME: https://github.com/fortanix/rust-sgx/issues/31
fn test_park_timeout_unpark_not_called() {
for _ in 0..10 {
thread::park_timeout(Duration::from_millis(10));
@ -1749,7 +1748,6 @@ mod tests {
}
#[test]
#[cfg_attr(target_env = "sgx", ignore)] // FIXME: https://github.com/fortanix/rust-sgx/issues/31
fn test_park_timeout_unpark_called_other_thread() {
for _ in 0..10 {
let th = thread::current();
@ -1764,7 +1762,6 @@ mod tests {
}
#[test]
#[cfg_attr(target_env = "sgx", ignore)] // FIXME: https://github.com/fortanix/rust-sgx/issues/31
fn sleep_ms_smoke() {
thread::sleep(Duration::from_millis(2));
}

View File

@ -10,6 +10,7 @@ path = "lib.rs"
crate-type = ["dylib", "rlib"]
[dependencies]
cfg-if = { version = "0.1.8", features = ['rustc-dep-of-std'] }
getopts = { version = "0.2.21", features = ['rustc-dep-of-std'] }
term = { path = "../libterm" }
std = { path = "../libstd" }

View File

@ -14,61 +14,36 @@ pub fn get_concurrency() -> usize {
}
Err(..) => num_cpus(),
};
}
#[cfg(windows)]
#[allow(nonstandard_style)]
fn num_cpus() -> usize {
#[repr(C)]
struct SYSTEM_INFO {
wProcessorArchitecture: u16,
wReserved: u16,
dwPageSize: u32,
lpMinimumApplicationAddress: *mut u8,
lpMaximumApplicationAddress: *mut u8,
dwActiveProcessorMask: *mut u8,
dwNumberOfProcessors: u32,
dwProcessorType: u32,
dwAllocationGranularity: u32,
wProcessorLevel: u16,
wProcessorRevision: u16,
cfg_if::cfg_if! {
if #[cfg(windows)] {
#[allow(nonstandard_style)]
fn num_cpus() -> usize {
#[repr(C)]
struct SYSTEM_INFO {
wProcessorArchitecture: u16,
wReserved: u16,
dwPageSize: u32,
lpMinimumApplicationAddress: *mut u8,
lpMaximumApplicationAddress: *mut u8,
dwActiveProcessorMask: *mut u8,
dwNumberOfProcessors: u32,
dwProcessorType: u32,
dwAllocationGranularity: u32,
wProcessorLevel: u16,
wProcessorRevision: u16,
}
extern "system" {
fn GetSystemInfo(info: *mut SYSTEM_INFO) -> i32;
}
unsafe {
let mut sysinfo = std::mem::zeroed();
GetSystemInfo(&mut sysinfo);
sysinfo.dwNumberOfProcessors as usize
}
}
extern "system" {
fn GetSystemInfo(info: *mut SYSTEM_INFO) -> i32;
}
unsafe {
let mut sysinfo = std::mem::zeroed();
GetSystemInfo(&mut sysinfo);
sysinfo.dwNumberOfProcessors as usize
}
}
#[cfg(target_os = "vxworks")]
fn num_cpus() -> usize {
// FIXME: Implement num_cpus on vxWorks
1
}
#[cfg(target_os = "redox")]
fn num_cpus() -> usize {
// FIXME: Implement num_cpus on Redox
1
}
#[cfg(target_os = "hermit")]
fn num_cpus() -> usize {
// FIXME: Implement num_cpus on HermitCore
1
}
#[cfg(any(
all(target_arch = "wasm32", not(target_os = "emscripten")),
all(target_vendor = "fortanix", target_env = "sgx")
))]
fn num_cpus() -> usize {
1
}
#[cfg(any(
} else if #[cfg(any(
target_os = "android",
target_os = "cloudabi",
target_os = "emscripten",
@ -78,23 +53,46 @@ pub fn get_concurrency() -> usize {
target_os = "macos",
target_os = "solaris",
target_os = "illumos",
))]
fn num_cpus() -> usize {
unsafe { libc::sysconf(libc::_SC_NPROCESSORS_ONLN) as usize }
}
#[cfg(any(target_os = "freebsd", target_os = "dragonfly", target_os = "netbsd"))]
fn num_cpus() -> usize {
use std::ptr;
let mut cpus: libc::c_uint = 0;
let mut cpus_size = std::mem::size_of_val(&cpus);
unsafe {
cpus = libc::sysconf(libc::_SC_NPROCESSORS_ONLN) as libc::c_uint;
))] {
fn num_cpus() -> usize {
unsafe { libc::sysconf(libc::_SC_NPROCESSORS_ONLN) as usize }
}
if cpus < 1 {
} else if #[cfg(any(target_os = "freebsd", target_os = "dragonfly", target_os = "netbsd"))] {
fn num_cpus() -> usize {
use std::ptr;
let mut cpus: libc::c_uint = 0;
let mut cpus_size = std::mem::size_of_val(&cpus);
unsafe {
cpus = libc::sysconf(libc::_SC_NPROCESSORS_ONLN) as libc::c_uint;
}
if cpus < 1 {
let mut mib = [libc::CTL_HW, libc::HW_NCPU, 0, 0];
unsafe {
libc::sysctl(
mib.as_mut_ptr(),
2,
&mut cpus as *mut _ as *mut _,
&mut cpus_size as *mut _ as *mut _,
ptr::null_mut(),
0,
);
}
if cpus < 1 {
cpus = 1;
}
}
cpus as usize
}
} else if #[cfg(target_os = "openbsd")] {
fn num_cpus() -> usize {
use std::ptr;
let mut cpus: libc::c_uint = 0;
let mut cpus_size = std::mem::size_of_val(&cpus);
let mut mib = [libc::CTL_HW, libc::HW_NCPU, 0, 0];
unsafe {
libc::sysctl(
mib.as_mut_ptr(),
@ -108,43 +106,12 @@ pub fn get_concurrency() -> usize {
if cpus < 1 {
cpus = 1;
}
cpus as usize
}
cpus as usize
}
#[cfg(target_os = "openbsd")]
fn num_cpus() -> usize {
use std::ptr;
let mut cpus: libc::c_uint = 0;
let mut cpus_size = std::mem::size_of_val(&cpus);
let mut mib = [libc::CTL_HW, libc::HW_NCPU, 0, 0];
unsafe {
libc::sysctl(
mib.as_mut_ptr(),
2,
&mut cpus as *mut _ as *mut _,
&mut cpus_size as *mut _ as *mut _,
ptr::null_mut(),
0,
);
} else {
// FIXME: implement on vxWorks, Redox, HermitCore, Haiku, l4re
fn num_cpus() -> usize {
1
}
if cpus < 1 {
cpus = 1;
}
cpus as usize
}
#[cfg(target_os = "haiku")]
fn num_cpus() -> usize {
// FIXME: implement
1
}
#[cfg(target_os = "l4re")]
fn num_cpus() -> usize {
// FIXME: implement
1
}
}

View File

@ -1,34 +1,32 @@
//! Helper module which provides a function to test
//! if stdout is a tty.
#[cfg(any(
target_os = "cloudabi",
target_os = "hermit",
all(target_arch = "wasm32", not(target_os = "emscripten")),
all(target_vendor = "fortanix", target_env = "sgx")
))]
pub fn stdout_isatty() -> bool {
// FIXME: Implement isatty on SGX
false
}
#[cfg(unix)]
pub fn stdout_isatty() -> bool {
unsafe { libc::isatty(libc::STDOUT_FILENO) != 0 }
}
#[cfg(windows)]
pub fn stdout_isatty() -> bool {
type DWORD = u32;
type BOOL = i32;
type HANDLE = *mut u8;
type LPDWORD = *mut u32;
const STD_OUTPUT_HANDLE: DWORD = -11i32 as DWORD;
extern "system" {
fn GetStdHandle(which: DWORD) -> HANDLE;
fn GetConsoleMode(hConsoleHandle: HANDLE, lpMode: LPDWORD) -> BOOL;
}
unsafe {
let handle = GetStdHandle(STD_OUTPUT_HANDLE);
let mut out = 0;
GetConsoleMode(handle, &mut out) != 0
cfg_if::cfg_if! {
if #[cfg(unix)] {
pub fn stdout_isatty() -> bool {
unsafe { libc::isatty(libc::STDOUT_FILENO) != 0 }
}
} else if #[cfg(windows)] {
pub fn stdout_isatty() -> bool {
type DWORD = u32;
type BOOL = i32;
type HANDLE = *mut u8;
type LPDWORD = *mut u32;
const STD_OUTPUT_HANDLE: DWORD = -11i32 as DWORD;
extern "system" {
fn GetStdHandle(which: DWORD) -> HANDLE;
fn GetConsoleMode(hConsoleHandle: HANDLE, lpMode: LPDWORD) -> BOOL;
}
unsafe {
let handle = GetStdHandle(STD_OUTPUT_HANDLE);
let mut out = 0;
GetConsoleMode(handle, &mut out) != 0
}
}
} else {
// FIXME: Implement isatty on SGX
pub fn stdout_isatty() -> bool {
false
}
}
}

View File

@ -9,12 +9,31 @@
cfg_if::cfg_if! {
if #[cfg(target_env = "msvc")] {
// no extra unwinder support needed
} else if #[cfg(all(target_arch = "wasm32", not(target_os = "emscripten")))] {
// no unwinder on the system!
} else {
// Windows MSVC no extra unwinder support needed
} else if #[cfg(any(
target_os = "l4re",
target_os = "none",
))] {
// These "unix" family members do not have unwinder.
// Note this also matches x86_64-linux-kernel.
} else if #[cfg(any(
unix,
windows,
target_os = "cloudabi",
all(target_vendor = "fortanix", target_env = "sgx"),
))] {
mod libunwind;
pub use libunwind::*;
} else {
// no unwinder on the system!
// - wasm32 (not emscripten, which is "unix" family)
// - os=none ("bare metal" targets)
// - os=hermit
// - os=uefi
// - os=cuda
// - nvptx64-nvidia-cuda
// - mipsel-sony-psp
// - Any new targets not listed above.
}
}

View File

@ -1,7 +1,7 @@
// check-pass
// revisions: public private
// [private]compile-flags: --document-private-items
#![cfg_attr(private, deny(intra_doc_resolution_failure))]
#![cfg_attr(private, deny(intra_doc_link_resolution_failure))]
/// docs [DontDocMe]
//[public]~^ WARNING `[DontDocMe]` public documentation for `DocMe` links to a private item

View File

@ -1,11 +1,13 @@
// compile-flags: -Z force-unstable-if-unmarked
// @matches internal/index.html '//*[@class="docblock-short"]/span[@class="stab internal"]' \
// 'Internal'
// Check that the unstable marker is not added for "rustc_private".
// @!matches internal/index.html '//*[@class="docblock-short"]/span[@class="stab unstable"]'
// @!matches internal/index.html '//*[@class="docblock-short"]/span[@class="stab internal"]'
// @matches - '//*[@class="docblock-short"]' 'Docs'
// @has internal/struct.S.html '//*[@class="stab internal"]' \
// 'This is an internal compiler API. (rustc_private)'
// @!has internal/struct.S.html '//*[@class="stab unstable"]'
// @!has internal/struct.S.html '//*[@class="stab internal"]'
/// Docs
pub struct S;

View File

@ -0,0 +1,10 @@
// aux-build:additional_doc.rs
// build-aux-docs
#![deny(intra_doc_link_resolution_failure)]
extern crate my_rand;
// @has 'additional_doc/trait.Rng.html' '//a[@href="../additional_doc/trait.Rng.html"]' 'Rng'
// @has 'additional_doc/trait.Rng.html' '//a[@href="../my_rand/trait.RngCore.html"]' 'RngCore'
/// This is an [`Rng`].
pub use my_rand::Rng;

View File

@ -0,0 +1,6 @@
#![crate_name = "my_rand"]
#![deny(intra_doc_link_resolution_failure)]
pub trait RngCore {}
/// Rng extends [`RngCore`].
pub trait Rng: RngCore {}

View File

@ -0,0 +1,7 @@
#![crate_name = "a"]
#![deny(intra_doc_link_resolution_failure)]
pub struct Foo;
/// Link to [Foo]
pub struct Bar;

View File

@ -0,0 +1,10 @@
#![crate_name = "macro_inner"]
#![deny(intra_doc_link_resolution_failure)]
pub struct Foo;
/// See also [`Foo`]
#[macro_export]
macro_rules! my_macro {
() => {}
}

View File

@ -0,0 +1,7 @@
#![crate_name = "module_inner"]
#![deny(intra_doc_link_resolution_failure)]
/// [SomeType] links to [bar]
pub struct SomeType;
pub trait SomeTrait {}
/// [bar] links to [SomeTrait] and also [SomeType]
pub mod bar {}

View File

@ -0,0 +1,20 @@
// force-host
// no-prefer-dynamic
// compile-flags: --crate-type proc-macro
#![crate_type="proc-macro"]
#![crate_name="proc_macro_inner"]
extern crate proc_macro;
use proc_macro::TokenStream;
/// Links to [`OtherDerive`]
#[proc_macro_derive(DeriveA)]
pub fn a_derive(input: TokenStream) -> TokenStream {
input
}
#[proc_macro_derive(OtherDerive)]
pub fn other_derive(input: TokenStream) -> TokenStream {
input
}

View File

@ -0,0 +1,12 @@
#![crate_name = "a"]
#![deny(intra_doc_link_resolution_failure)]
pub mod bar {
pub struct Bar;
}
pub mod foo {
use crate::bar;
/// link to [bar::Bar]
pub struct Foo;
}

View File

@ -0,0 +1,13 @@
#![crate_name = "bar"]
#![deny(intra_doc_link_resolution_failure)]
pub trait Foo {
/// [`Bar`] [`Baz`]
fn foo();
}
pub trait Bar {
}
pub trait Baz {
}

View File

@ -0,0 +1,16 @@
#![crate_name = "inner"]
/// this is a trait
pub trait SomeTrait {
/// this is a method for [a trait][SomeTrait]
fn foo();
}
pub mod bar {
use super::SomeTrait;
pub struct BarStruct;
impl SomeTrait for BarStruct {
fn foo() {}
}
}

View File

@ -0,0 +1,9 @@
// aux-build:intra-doc-basic.rs
// build-aux-docs
#![deny(intra_doc_link_resolution_failure)]
// from https://github.com/rust-lang/rust/issues/65983
extern crate a;
// @has 'basic/struct.Bar.html' '//a[@href="../a/struct.Foo.html"]' 'Foo'
pub use a::Bar;

View File

@ -0,0 +1,12 @@
// ignore-tidy-linelength
// aux-build:macro_inner.rs
// aux-build:proc_macro.rs
// build-aux-docs
#![deny(intra_doc_link_resolution_failure)]
extern crate macro_inner;
extern crate proc_macro_inner;
// @has 'macro/macro.my_macro.html' '//a[@href="../macro_inner/struct.Foo.html"]' 'Foo'
pub use macro_inner::my_macro;
// @has 'macro/derive.DeriveA.html' '//a[@href="../proc_macro_inner/derive.OtherDerive.html"]' 'OtherDerive'
pub use proc_macro_inner::DeriveA;

View File

@ -0,0 +1,8 @@
// outer.rs
// aux-build: module.rs
// build-aux-docs
#![deny(intra_doc_link_resolution_failure)]
extern crate module_inner;
// @has 'module/bar/index.html' '//a[@href="../../module_inner/trait.SomeTrait.html"]' 'SomeTrait'
// @has 'module/bar/index.html' '//a[@href="../../module_inner/struct.SomeType.html"]' 'SomeType'
pub use module_inner::bar;

Some files were not shown because too many files have changed in this diff Show More