commit
49482caad2
176 changed files with 2220 additions and 1742 deletions
21
Cargo.lock
21
Cargo.lock
|
|
@ -3390,6 +3390,7 @@ version = "0.0.0"
|
|||
dependencies = [
|
||||
"rustc_ast",
|
||||
"rustc_ast_pretty",
|
||||
"rustc_attr_data_structures",
|
||||
"rustc_attr_parsing",
|
||||
"rustc_data_structures",
|
||||
"rustc_errors",
|
||||
|
|
@ -3424,7 +3425,7 @@ dependencies = [
|
|||
"rustc-demangle",
|
||||
"rustc_abi",
|
||||
"rustc_ast",
|
||||
"rustc_attr_parsing",
|
||||
"rustc_attr_data_structures",
|
||||
"rustc_codegen_ssa",
|
||||
"rustc_data_structures",
|
||||
"rustc_errors",
|
||||
|
|
@ -3467,6 +3468,7 @@ dependencies = [
|
|||
"rustc_abi",
|
||||
"rustc_arena",
|
||||
"rustc_ast",
|
||||
"rustc_attr_data_structures",
|
||||
"rustc_attr_parsing",
|
||||
"rustc_data_structures",
|
||||
"rustc_errors",
|
||||
|
|
@ -3504,7 +3506,7 @@ dependencies = [
|
|||
"rustc_abi",
|
||||
"rustc_apfloat",
|
||||
"rustc_ast",
|
||||
"rustc_attr_parsing",
|
||||
"rustc_attr_data_structures",
|
||||
"rustc_data_structures",
|
||||
"rustc_errors",
|
||||
"rustc_fluent_macro",
|
||||
|
|
@ -3680,6 +3682,7 @@ dependencies = [
|
|||
"rustc_ast",
|
||||
"rustc_ast_passes",
|
||||
"rustc_ast_pretty",
|
||||
"rustc_attr_data_structures",
|
||||
"rustc_attr_parsing",
|
||||
"rustc_data_structures",
|
||||
"rustc_errors",
|
||||
|
|
@ -3768,7 +3771,7 @@ dependencies = [
|
|||
"rustc_abi",
|
||||
"rustc_arena",
|
||||
"rustc_ast",
|
||||
"rustc_attr_parsing",
|
||||
"rustc_attr_data_structures",
|
||||
"rustc_data_structures",
|
||||
"rustc_errors",
|
||||
"rustc_feature",
|
||||
|
|
@ -3805,7 +3808,7 @@ dependencies = [
|
|||
"itertools",
|
||||
"rustc_abi",
|
||||
"rustc_ast",
|
||||
"rustc_attr_parsing",
|
||||
"rustc_attr_data_structures",
|
||||
"rustc_data_structures",
|
||||
"rustc_errors",
|
||||
"rustc_fluent_macro",
|
||||
|
|
@ -3950,6 +3953,7 @@ dependencies = [
|
|||
"rustc_abi",
|
||||
"rustc_ast",
|
||||
"rustc_ast_pretty",
|
||||
"rustc_attr_data_structures",
|
||||
"rustc_attr_parsing",
|
||||
"rustc_data_structures",
|
||||
"rustc_errors",
|
||||
|
|
@ -4023,6 +4027,7 @@ dependencies = [
|
|||
"odht",
|
||||
"rustc_abi",
|
||||
"rustc_ast",
|
||||
"rustc_attr_data_structures",
|
||||
"rustc_attr_parsing",
|
||||
"rustc_data_structures",
|
||||
"rustc_errors",
|
||||
|
|
@ -4136,7 +4141,7 @@ dependencies = [
|
|||
"rustc_abi",
|
||||
"rustc_arena",
|
||||
"rustc_ast",
|
||||
"rustc_attr_parsing",
|
||||
"rustc_attr_data_structures",
|
||||
"rustc_const_eval",
|
||||
"rustc_data_structures",
|
||||
"rustc_errors",
|
||||
|
|
@ -4162,7 +4167,7 @@ version = "0.0.0"
|
|||
dependencies = [
|
||||
"rustc_abi",
|
||||
"rustc_ast",
|
||||
"rustc_attr_parsing",
|
||||
"rustc_attr_data_structures",
|
||||
"rustc_data_structures",
|
||||
"rustc_errors",
|
||||
"rustc_fluent_macro",
|
||||
|
|
@ -4232,7 +4237,7 @@ dependencies = [
|
|||
"rustc_ast",
|
||||
"rustc_ast_lowering",
|
||||
"rustc_ast_pretty",
|
||||
"rustc_attr_parsing",
|
||||
"rustc_attr_data_structures",
|
||||
"rustc_data_structures",
|
||||
"rustc_errors",
|
||||
"rustc_expand",
|
||||
|
|
@ -4278,7 +4283,7 @@ name = "rustc_privacy"
|
|||
version = "0.0.0"
|
||||
dependencies = [
|
||||
"rustc_ast",
|
||||
"rustc_attr_parsing",
|
||||
"rustc_attr_data_structures",
|
||||
"rustc_data_structures",
|
||||
"rustc_errors",
|
||||
"rustc_fluent_macro",
|
||||
|
|
|
|||
|
|
@ -15,6 +15,7 @@
|
|||
#![feature(associated_type_defaults)]
|
||||
#![feature(box_patterns)]
|
||||
#![feature(if_let_guard)]
|
||||
#![feature(macro_metavar_expr)]
|
||||
#![feature(negative_impls)]
|
||||
#![feature(never_type)]
|
||||
#![feature(rustdoc_internals)]
|
||||
|
|
|
|||
|
|
@ -20,7 +20,7 @@ use thin_vec::ThinVec;
|
|||
use crate::ast::*;
|
||||
use crate::ptr::P;
|
||||
use crate::tokenstream::*;
|
||||
use crate::visit::{AssocCtxt, BoundKind, FnCtxt};
|
||||
use crate::visit::{AssocCtxt, BoundKind, FnCtxt, try_visit};
|
||||
|
||||
pub trait ExpectOne<A: Array> {
|
||||
fn expect_one(self, err: &'static str) -> A::Item;
|
||||
|
|
@ -388,6 +388,8 @@ pub trait MutVisitor: Sized {
|
|||
}
|
||||
}
|
||||
|
||||
super::common_visitor_and_walkers!((mut) MutVisitor);
|
||||
|
||||
/// Use a map-style function (`FnOnce(T) -> T`) to overwrite a `&mut T`. Useful
|
||||
/// when using a `flat_map_*` or `filter_map_*` method within a `visit_`
|
||||
/// method.
|
||||
|
|
@ -777,15 +779,6 @@ fn visit_defaultness<T: MutVisitor>(vis: &mut T, defaultness: &mut Defaultness)
|
|||
}
|
||||
}
|
||||
|
||||
// No `noop_` prefix because there isn't a corresponding method in `MutVisitor`.
|
||||
fn visit_safety<T: MutVisitor>(vis: &mut T, safety: &mut Safety) {
|
||||
match safety {
|
||||
Safety::Unsafe(span) => vis.visit_span(span),
|
||||
Safety::Safe(span) => vis.visit_span(span),
|
||||
Safety::Default => {}
|
||||
}
|
||||
}
|
||||
|
||||
// No `noop_` prefix because there isn't a corresponding method in `MutVisitor`.
|
||||
fn visit_polarity<T: MutVisitor>(vis: &mut T, polarity: &mut ImplPolarity) {
|
||||
match polarity {
|
||||
|
|
@ -794,14 +787,6 @@ fn visit_polarity<T: MutVisitor>(vis: &mut T, polarity: &mut ImplPolarity) {
|
|||
}
|
||||
}
|
||||
|
||||
// No `noop_` prefix because there isn't a corresponding method in `MutVisitor`.
|
||||
fn visit_constness<T: MutVisitor>(vis: &mut T, constness: &mut Const) {
|
||||
match constness {
|
||||
Const::Yes(span) => vis.visit_span(span),
|
||||
Const::No => {}
|
||||
}
|
||||
}
|
||||
|
||||
fn walk_closure_binder<T: MutVisitor>(vis: &mut T, binder: &mut ClosureBinder) {
|
||||
match binder {
|
||||
ClosureBinder::NotPresent => {}
|
||||
|
|
@ -940,15 +925,6 @@ pub fn walk_flat_map_generic_param<T: MutVisitor>(
|
|||
smallvec![param]
|
||||
}
|
||||
|
||||
fn walk_label<T: MutVisitor>(vis: &mut T, Label { ident }: &mut Label) {
|
||||
vis.visit_ident(ident);
|
||||
}
|
||||
|
||||
fn walk_lifetime<T: MutVisitor>(vis: &mut T, Lifetime { id, ident }: &mut Lifetime) {
|
||||
vis.visit_id(id);
|
||||
vis.visit_ident(ident);
|
||||
}
|
||||
|
||||
fn walk_generics<T: MutVisitor>(vis: &mut T, generics: &mut Generics) {
|
||||
let Generics { params, where_clause, span } = generics;
|
||||
params.flat_map_in_place(|param| vis.flat_map_generic_param(param));
|
||||
|
|
@ -1340,13 +1316,6 @@ fn walk_const_item<T: MutVisitor>(vis: &mut T, item: &mut ConstItem) {
|
|||
walk_define_opaques(vis, define_opaque);
|
||||
}
|
||||
|
||||
fn walk_fn_header<T: MutVisitor>(vis: &mut T, header: &mut FnHeader) {
|
||||
let FnHeader { safety, coroutine_kind, constness, ext: _ } = header;
|
||||
visit_constness(vis, constness);
|
||||
coroutine_kind.as_mut().map(|coroutine_kind| vis.visit_coroutine_kind(coroutine_kind));
|
||||
visit_safety(vis, safety);
|
||||
}
|
||||
|
||||
pub fn walk_crate<T: MutVisitor>(vis: &mut T, krate: &mut Crate) {
|
||||
let Crate { attrs, items, spans, id, is_placeholder: _ } = krate;
|
||||
vis.visit_id(id);
|
||||
|
|
|
|||
|
|
@ -315,6 +315,75 @@ pub trait Visitor<'ast>: Sized {
|
|||
}
|
||||
}
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! common_visitor_and_walkers {
|
||||
($(($mut: ident))? $Visitor:ident$(<$lt:lifetime>)?) => {
|
||||
// this is only used by the MutVisitor. We include this symmetry here to make writing other functions easier
|
||||
$(${ignore($lt)}
|
||||
#[expect(unused, rustc::pass_by_value)]
|
||||
#[inline]
|
||||
)?
|
||||
fn visit_span<$($lt,)? V: $Visitor$(<$lt>)?>(visitor: &mut V, span: &$($lt)? $($mut)? Span) $(-> <V as Visitor<$lt>>::Result)? {
|
||||
$(
|
||||
let _ = stringify!($mut);
|
||||
visitor.visit_span(span);
|
||||
)?
|
||||
$(${ignore($lt)}V::Result::output())?
|
||||
}
|
||||
|
||||
// this is only used by the MutVisitor. We include this symmetry here to make writing other functions easier
|
||||
$(${ignore($lt)}
|
||||
#[expect(unused, rustc::pass_by_value)]
|
||||
#[inline]
|
||||
)?
|
||||
fn visit_id<$($lt,)? V: $Visitor$(<$lt>)?>(visitor: &mut V, id: &$($lt)? $($mut)? NodeId) $(-> <V as Visitor<$lt>>::Result)? {
|
||||
$(
|
||||
let _ = stringify!($mut);
|
||||
visitor.visit_id(id);
|
||||
)?
|
||||
$(${ignore($lt)}V::Result::output())?
|
||||
}
|
||||
|
||||
// this is only used by the MutVisitor. We include this symmetry here to make writing other functions easier
|
||||
fn visit_safety<$($lt,)? V: $Visitor$(<$lt>)?>(vis: &mut V, safety: &$($lt)? $($mut)? Safety) $(-> <V as Visitor<$lt>>::Result)? {
|
||||
match safety {
|
||||
Safety::Unsafe(span) => visit_span(vis, span),
|
||||
Safety::Safe(span) => visit_span(vis, span),
|
||||
Safety::Default => { $(${ignore($lt)}V::Result::output())? }
|
||||
}
|
||||
}
|
||||
|
||||
fn visit_constness<$($lt,)? V: $Visitor$(<$lt>)?>(vis: &mut V, constness: &$($lt)? $($mut)? Const) $(-> <V as Visitor<$lt>>::Result)? {
|
||||
match constness {
|
||||
Const::Yes(span) => visit_span(vis, span),
|
||||
Const::No => {
|
||||
$(<V as Visitor<$lt>>::Result::output())?
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn walk_label<$($lt,)? V: $Visitor$(<$lt>)?>(visitor: &mut V, Label { ident }: &$($lt)? $($mut)? Label) $(-> <V as Visitor<$lt>>::Result)? {
|
||||
visitor.visit_ident(ident)
|
||||
}
|
||||
|
||||
pub fn walk_fn_header<$($lt,)? V: $Visitor$(<$lt>)?>(visitor: &mut V, header: &$($lt)? $($mut)? FnHeader) $(-> <V as Visitor<$lt>>::Result)? {
|
||||
let FnHeader { safety, coroutine_kind, constness, ext: _ } = header;
|
||||
try_visit!(visit_constness(visitor, constness));
|
||||
if let Some(coroutine_kind) = coroutine_kind {
|
||||
try_visit!(visitor.visit_coroutine_kind(coroutine_kind));
|
||||
}
|
||||
visit_safety(visitor, safety)
|
||||
}
|
||||
|
||||
pub fn walk_lifetime<$($lt,)? V: $Visitor$(<$lt>)?>(visitor: &mut V, Lifetime { id, ident }: &$($lt)? $($mut)? Lifetime) $(-> <V as Visitor<$lt>>::Result)? {
|
||||
try_visit!(visit_id(visitor, id));
|
||||
visitor.visit_ident(ident)
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
common_visitor_and_walkers!(Visitor<'a>);
|
||||
|
||||
pub fn walk_crate<'a, V: Visitor<'a>>(visitor: &mut V, krate: &'a Crate) -> V::Result {
|
||||
let Crate { attrs, items, spans: _, id: _, is_placeholder: _ } = krate;
|
||||
walk_list!(visitor, visit_attribute, attrs);
|
||||
|
|
@ -334,15 +403,6 @@ pub fn walk_local<'a, V: Visitor<'a>>(visitor: &mut V, local: &'a Local) -> V::R
|
|||
V::Result::output()
|
||||
}
|
||||
|
||||
pub fn walk_label<'a, V: Visitor<'a>>(visitor: &mut V, Label { ident }: &'a Label) -> V::Result {
|
||||
visitor.visit_ident(ident)
|
||||
}
|
||||
|
||||
pub fn walk_lifetime<'a, V: Visitor<'a>>(visitor: &mut V, lifetime: &'a Lifetime) -> V::Result {
|
||||
let Lifetime { id: _, ident } = lifetime;
|
||||
visitor.visit_ident(ident)
|
||||
}
|
||||
|
||||
pub fn walk_poly_trait_ref<'a, V>(visitor: &mut V, trait_ref: &'a PolyTraitRef) -> V::Result
|
||||
where
|
||||
V: Visitor<'a>,
|
||||
|
|
@ -926,12 +986,6 @@ pub fn walk_fn_ret_ty<'a, V: Visitor<'a>>(visitor: &mut V, ret_ty: &'a FnRetTy)
|
|||
V::Result::output()
|
||||
}
|
||||
|
||||
pub fn walk_fn_header<'a, V: Visitor<'a>>(visitor: &mut V, fn_header: &'a FnHeader) -> V::Result {
|
||||
let FnHeader { safety: _, coroutine_kind, constness: _, ext: _ } = fn_header;
|
||||
visit_opt!(visitor, visit_coroutine_kind, coroutine_kind.as_ref());
|
||||
V::Result::output()
|
||||
}
|
||||
|
||||
pub fn walk_fn_decl<'a, V: Visitor<'a>>(
|
||||
visitor: &mut V,
|
||||
FnDecl { inputs, output }: &'a FnDecl,
|
||||
|
|
|
|||
|
|
@ -60,7 +60,8 @@
|
|||
//! `#[stable(...)]` and `#[unstable()]` cannot occur together, and both semantically define
|
||||
//! a "stability" of an item. So, the stability attribute has an
|
||||
//! [`AttributeParser`](attributes::AttributeParser) that recognizes both the `#[stable()]`
|
||||
//! and `#[unstable()]` syntactic attributes, and at the end produce a single [`AttributeKind::Stability`].
|
||||
//! and `#[unstable()]` syntactic attributes, and at the end produce a single
|
||||
//! [`AttributeKind::Stability`](rustc_attr_data_structures::AttributeKind::Stability).
|
||||
//!
|
||||
//! As a rule of thumb, when a syntactical attribute can be applied more than once, they should be
|
||||
//! combined into a single semantic attribute. For example:
|
||||
|
|
@ -91,6 +92,5 @@ mod session_diagnostics;
|
|||
pub use attributes::cfg::*;
|
||||
pub use attributes::util::{find_crate_name, is_builtin_attr, parse_version};
|
||||
pub use context::{AttributeParser, OmitDoc};
|
||||
pub use rustc_attr_data_structures::*;
|
||||
|
||||
rustc_fluent_macro::fluent_messages! { "../messages.ftl" }
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@ doctest = false
|
|||
# tidy-alphabetical-start
|
||||
rustc_ast = { path = "../rustc_ast" }
|
||||
rustc_ast_pretty = { path = "../rustc_ast_pretty" }
|
||||
rustc_attr_data_structures = { path = "../rustc_attr_data_structures" }
|
||||
rustc_attr_parsing = { path = "../rustc_attr_parsing" }
|
||||
rustc_data_structures = { path = "../rustc_data_structures" }
|
||||
rustc_errors = { path = "../rustc_errors" }
|
||||
|
|
|
|||
|
|
@ -73,10 +73,10 @@ mod llvm_enzyme {
|
|||
}
|
||||
|
||||
// Get information about the function the macro is applied to
|
||||
fn extract_item_info(iitem: &P<ast::Item>) -> Option<(Visibility, FnSig, Ident)> {
|
||||
fn extract_item_info(iitem: &P<ast::Item>) -> Option<(Visibility, FnSig, Ident, Generics)> {
|
||||
match &iitem.kind {
|
||||
ItemKind::Fn(box ast::Fn { sig, ident, .. }) => {
|
||||
Some((iitem.vis.clone(), sig.clone(), ident.clone()))
|
||||
ItemKind::Fn(box ast::Fn { sig, ident, generics, .. }) => {
|
||||
Some((iitem.vis.clone(), sig.clone(), ident.clone(), generics.clone()))
|
||||
}
|
||||
_ => None,
|
||||
}
|
||||
|
|
@ -210,16 +210,18 @@ mod llvm_enzyme {
|
|||
}
|
||||
let dcx = ecx.sess.dcx();
|
||||
|
||||
// first get information about the annotable item:
|
||||
let Some((vis, sig, primal)) = (match &item {
|
||||
// first get information about the annotable item: visibility, signature, name and generic
|
||||
// parameters.
|
||||
// these will be used to generate the differentiated version of the function
|
||||
let Some((vis, sig, primal, generics)) = (match &item {
|
||||
Annotatable::Item(iitem) => extract_item_info(iitem),
|
||||
Annotatable::Stmt(stmt) => match &stmt.kind {
|
||||
ast::StmtKind::Item(iitem) => extract_item_info(iitem),
|
||||
_ => None,
|
||||
},
|
||||
Annotatable::AssocItem(assoc_item, Impl { .. }) => match &assoc_item.kind {
|
||||
ast::AssocItemKind::Fn(box ast::Fn { sig, ident, .. }) => {
|
||||
Some((assoc_item.vis.clone(), sig.clone(), ident.clone()))
|
||||
ast::AssocItemKind::Fn(box ast::Fn { sig, ident, generics, .. }) => {
|
||||
Some((assoc_item.vis.clone(), sig.clone(), ident.clone(), generics.clone()))
|
||||
}
|
||||
_ => None,
|
||||
},
|
||||
|
|
@ -303,6 +305,7 @@ mod llvm_enzyme {
|
|||
let (d_sig, new_args, idents, errored) = gen_enzyme_decl(ecx, &sig, &x, span);
|
||||
let d_body = gen_enzyme_body(
|
||||
ecx, &x, n_active, &sig, &d_sig, primal, &new_args, span, sig_span, idents, errored,
|
||||
&generics,
|
||||
);
|
||||
|
||||
// The first element of it is the name of the function to be generated
|
||||
|
|
@ -310,7 +313,7 @@ mod llvm_enzyme {
|
|||
defaultness: ast::Defaultness::Final,
|
||||
sig: d_sig,
|
||||
ident: first_ident(&meta_item_vec[0]),
|
||||
generics: Generics::default(),
|
||||
generics,
|
||||
contract: None,
|
||||
body: Some(d_body),
|
||||
define_opaque: None,
|
||||
|
|
@ -475,6 +478,7 @@ mod llvm_enzyme {
|
|||
new_decl_span: Span,
|
||||
idents: &[Ident],
|
||||
errored: bool,
|
||||
generics: &Generics,
|
||||
) -> (P<ast::Block>, P<ast::Expr>, P<ast::Expr>, P<ast::Expr>) {
|
||||
let blackbox_path = ecx.std_path(&[sym::hint, sym::black_box]);
|
||||
let noop = ast::InlineAsm {
|
||||
|
|
@ -497,7 +501,7 @@ mod llvm_enzyme {
|
|||
};
|
||||
let unsf_expr = ecx.expr_block(P(unsf_block));
|
||||
let blackbox_call_expr = ecx.expr_path(ecx.path(span, blackbox_path));
|
||||
let primal_call = gen_primal_call(ecx, span, primal, idents);
|
||||
let primal_call = gen_primal_call(ecx, span, primal, idents, generics);
|
||||
let black_box_primal_call = ecx.expr_call(
|
||||
new_decl_span,
|
||||
blackbox_call_expr.clone(),
|
||||
|
|
@ -546,6 +550,7 @@ mod llvm_enzyme {
|
|||
sig_span: Span,
|
||||
idents: Vec<Ident>,
|
||||
errored: bool,
|
||||
generics: &Generics,
|
||||
) -> P<ast::Block> {
|
||||
let new_decl_span = d_sig.span;
|
||||
|
||||
|
|
@ -566,6 +571,7 @@ mod llvm_enzyme {
|
|||
new_decl_span,
|
||||
&idents,
|
||||
errored,
|
||||
generics,
|
||||
);
|
||||
|
||||
if !has_ret(&d_sig.decl.output) {
|
||||
|
|
@ -608,7 +614,6 @@ mod llvm_enzyme {
|
|||
panic!("Did not expect Default ret ty: {:?}", span);
|
||||
}
|
||||
};
|
||||
|
||||
if x.mode.is_fwd() {
|
||||
// Fwd mode is easy. If the return activity is Const, we support arbitrary types.
|
||||
// Otherwise, we only support a scalar, a pair of scalars, or an array of scalars.
|
||||
|
|
@ -668,8 +673,10 @@ mod llvm_enzyme {
|
|||
span: Span,
|
||||
primal: Ident,
|
||||
idents: &[Ident],
|
||||
generics: &Generics,
|
||||
) -> P<ast::Expr> {
|
||||
let has_self = idents.len() > 0 && idents[0].name == kw::SelfLower;
|
||||
|
||||
if has_self {
|
||||
let args: ThinVec<_> =
|
||||
idents[1..].iter().map(|arg| ecx.expr_path(ecx.path_ident(span, *arg))).collect();
|
||||
|
|
@ -678,7 +685,51 @@ mod llvm_enzyme {
|
|||
} else {
|
||||
let args: ThinVec<_> =
|
||||
idents.iter().map(|arg| ecx.expr_path(ecx.path_ident(span, *arg))).collect();
|
||||
let primal_call_expr = ecx.expr_path(ecx.path_ident(span, primal));
|
||||
let mut primal_path = ecx.path_ident(span, primal);
|
||||
|
||||
let is_generic = !generics.params.is_empty();
|
||||
|
||||
match (is_generic, primal_path.segments.last_mut()) {
|
||||
(true, Some(function_path)) => {
|
||||
let primal_generic_types = generics
|
||||
.params
|
||||
.iter()
|
||||
.filter(|param| matches!(param.kind, ast::GenericParamKind::Type { .. }));
|
||||
|
||||
let generated_generic_types = primal_generic_types
|
||||
.map(|type_param| {
|
||||
let generic_param = TyKind::Path(
|
||||
None,
|
||||
ast::Path {
|
||||
span,
|
||||
segments: thin_vec![ast::PathSegment {
|
||||
ident: type_param.ident,
|
||||
args: None,
|
||||
id: ast::DUMMY_NODE_ID,
|
||||
}],
|
||||
tokens: None,
|
||||
},
|
||||
);
|
||||
|
||||
ast::AngleBracketedArg::Arg(ast::GenericArg::Type(P(ast::Ty {
|
||||
id: type_param.id,
|
||||
span,
|
||||
kind: generic_param,
|
||||
tokens: None,
|
||||
})))
|
||||
})
|
||||
.collect();
|
||||
|
||||
function_path.args =
|
||||
Some(P(ast::GenericArgs::AngleBracketed(ast::AngleBracketedArgs {
|
||||
span,
|
||||
args: generated_generic_types,
|
||||
})));
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
|
||||
let primal_call_expr = ecx.expr_path(primal_path);
|
||||
ecx.expr_call(span, primal_call_expr, args)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -185,7 +185,8 @@ use rustc_ast::{
|
|||
self as ast, AnonConst, BindingMode, ByRef, EnumDef, Expr, GenericArg, GenericParamKind,
|
||||
Generics, Mutability, PatKind, VariantData,
|
||||
};
|
||||
use rustc_attr_parsing::{AttributeKind, AttributeParser, ReprPacked};
|
||||
use rustc_attr_data_structures::{AttributeKind, ReprPacked};
|
||||
use rustc_attr_parsing::AttributeParser;
|
||||
use rustc_expand::base::{Annotatable, ExtCtxt};
|
||||
use rustc_hir::Attribute;
|
||||
use rustc_span::{DUMMY_SP, Ident, Span, Symbol, kw, sym};
|
||||
|
|
|
|||
|
|
@ -2,8 +2,8 @@
|
|||
use gccjit::FnAttribute;
|
||||
use gccjit::Function;
|
||||
#[cfg(feature = "master")]
|
||||
use rustc_attr_parsing::InlineAttr;
|
||||
use rustc_attr_parsing::InstructionSetAttr;
|
||||
use rustc_attr_data_structures::InlineAttr;
|
||||
use rustc_attr_data_structures::InstructionSetAttr;
|
||||
#[cfg(feature = "master")]
|
||||
use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrFlags;
|
||||
#[cfg(feature = "master")]
|
||||
|
|
|
|||
|
|
@ -106,7 +106,7 @@ pub fn get_fn<'gcc, 'tcx>(cx: &CodegenCx<'gcc, 'tcx>, instance: Instance<'tcx>)
|
|||
// This is a monomorphization of a generic function.
|
||||
if !(cx.tcx.sess.opts.share_generics()
|
||||
|| tcx.codegen_fn_attrs(instance_def_id).inline
|
||||
== rustc_attr_parsing::InlineAttr::Never)
|
||||
== rustc_attr_data_structures::InlineAttr::Never)
|
||||
{
|
||||
// When not sharing generics, all instances are in the same
|
||||
// crate and have hidden visibility.
|
||||
|
|
|
|||
|
|
@ -37,7 +37,7 @@ extern crate tracing;
|
|||
extern crate rustc_abi;
|
||||
extern crate rustc_apfloat;
|
||||
extern crate rustc_ast;
|
||||
extern crate rustc_attr_parsing;
|
||||
extern crate rustc_attr_data_structures;
|
||||
extern crate rustc_codegen_ssa;
|
||||
extern crate rustc_data_structures;
|
||||
extern crate rustc_errors;
|
||||
|
|
|
|||
|
|
@ -19,7 +19,7 @@ object = { version = "0.36.3", default-features = false, features = ["std", "rea
|
|||
rustc-demangle = "0.1.21"
|
||||
rustc_abi = { path = "../rustc_abi" }
|
||||
rustc_ast = { path = "../rustc_ast" }
|
||||
rustc_attr_parsing = { path = "../rustc_attr_parsing" }
|
||||
rustc_attr_data_structures = { path = "../rustc_attr_data_structures" }
|
||||
rustc_codegen_ssa = { path = "../rustc_codegen_ssa" }
|
||||
rustc_data_structures = { path = "../rustc_data_structures" }
|
||||
rustc_errors = { path = "../rustc_errors" }
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
//! Set and unset common attributes on LLVM values.
|
||||
use rustc_attr_parsing::{InlineAttr, InstructionSetAttr, OptimizeAttr};
|
||||
use rustc_attr_data_structures::{InlineAttr, InstructionSetAttr, OptimizeAttr};
|
||||
use rustc_codegen_ssa::traits::*;
|
||||
use rustc_hir::def_id::DefId;
|
||||
use rustc_middle::middle::codegen_fn_attrs::{CodegenFnAttrFlags, PatchableFunctionEntry};
|
||||
|
|
|
|||
|
|
@ -103,7 +103,7 @@ pub(crate) fn get_fn<'ll, 'tcx>(cx: &CodegenCx<'ll, 'tcx>, instance: Instance<'t
|
|||
// This is a monomorphization of a generic function.
|
||||
if !(cx.tcx.sess.opts.share_generics()
|
||||
|| tcx.codegen_fn_attrs(instance_def_id).inline
|
||||
== rustc_attr_parsing::InlineAttr::Never)
|
||||
== rustc_attr_data_structures::InlineAttr::Never)
|
||||
{
|
||||
// When not sharing generics, all instances are in the same
|
||||
// crate and have hidden visibility.
|
||||
|
|
|
|||
|
|
@ -155,6 +155,20 @@ pub(crate) struct Regions {
|
|||
impl Regions {
|
||||
/// Returns true if none of this structure's tables contain any regions.
|
||||
pub(crate) fn has_no_regions(&self) -> bool {
|
||||
// Every region has a span, so if there are no spans then there are no regions.
|
||||
self.all_cov_spans().next().is_none()
|
||||
}
|
||||
|
||||
pub(crate) fn all_cov_spans(&self) -> impl Iterator<Item = &CoverageSpan> {
|
||||
macro_rules! iter_cov_spans {
|
||||
( $( $regions:expr ),* $(,)? ) => {
|
||||
std::iter::empty()
|
||||
$(
|
||||
.chain( $regions.iter().map(|region| ®ion.cov_span) )
|
||||
)*
|
||||
}
|
||||
}
|
||||
|
||||
let Self {
|
||||
code_regions,
|
||||
expansion_regions,
|
||||
|
|
@ -163,11 +177,13 @@ impl Regions {
|
|||
mcdc_decision_regions,
|
||||
} = self;
|
||||
|
||||
code_regions.is_empty()
|
||||
&& expansion_regions.is_empty()
|
||||
&& branch_regions.is_empty()
|
||||
&& mcdc_branch_regions.is_empty()
|
||||
&& mcdc_decision_regions.is_empty()
|
||||
iter_cov_spans!(
|
||||
code_regions,
|
||||
expansion_regions,
|
||||
branch_regions,
|
||||
mcdc_branch_regions,
|
||||
mcdc_decision_regions,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -11,6 +11,7 @@ use rustc_abi::Align;
|
|||
use rustc_codegen_ssa::traits::{
|
||||
BaseTypeCodegenMethods as _, ConstCodegenMethods, StaticCodegenMethods,
|
||||
};
|
||||
use rustc_index::IndexVec;
|
||||
use rustc_middle::mir::coverage::{
|
||||
BasicCoverageBlock, CovTerm, CoverageIdsInfo, Expression, FunctionCoverageInfo, Mapping,
|
||||
MappingKind, Op,
|
||||
|
|
@ -104,6 +105,16 @@ fn fill_region_tables<'tcx>(
|
|||
ids_info: &'tcx CoverageIdsInfo,
|
||||
covfun: &mut CovfunRecord<'tcx>,
|
||||
) {
|
||||
// If this function is unused, replace all counters with zero.
|
||||
let counter_for_bcb = |bcb: BasicCoverageBlock| -> ffi::Counter {
|
||||
let term = if covfun.is_used {
|
||||
ids_info.term_for_bcb[bcb].expect("every BCB in a mapping was given a term")
|
||||
} else {
|
||||
CovTerm::Zero
|
||||
};
|
||||
ffi::Counter::from_term(term)
|
||||
};
|
||||
|
||||
// Currently a function's mappings must all be in the same file, so use the
|
||||
// first mapping's span to determine the file.
|
||||
let source_map = tcx.sess.source_map();
|
||||
|
|
@ -115,6 +126,12 @@ fn fill_region_tables<'tcx>(
|
|||
|
||||
let local_file_id = covfun.virtual_file_mapping.push_file(&source_file);
|
||||
|
||||
// If this testing flag is set, add an extra unused entry to the local
|
||||
// file table, to help test the code for detecting unused file IDs.
|
||||
if tcx.sess.coverage_inject_unused_local_file() {
|
||||
covfun.virtual_file_mapping.push_file(&source_file);
|
||||
}
|
||||
|
||||
// In rare cases, _all_ of a function's spans are discarded, and coverage
|
||||
// codegen needs to handle that gracefully to avoid #133606.
|
||||
// It's hard for tests to trigger this organically, so instead we set
|
||||
|
|
@ -135,16 +152,6 @@ fn fill_region_tables<'tcx>(
|
|||
// For each counter/region pair in this function+file, convert it to a
|
||||
// form suitable for FFI.
|
||||
for &Mapping { ref kind, span } in &fn_cov_info.mappings {
|
||||
// If this function is unused, replace all counters with zero.
|
||||
let counter_for_bcb = |bcb: BasicCoverageBlock| -> ffi::Counter {
|
||||
let term = if covfun.is_used {
|
||||
ids_info.term_for_bcb[bcb].expect("every BCB in a mapping was given a term")
|
||||
} else {
|
||||
CovTerm::Zero
|
||||
};
|
||||
ffi::Counter::from_term(term)
|
||||
};
|
||||
|
||||
let Some(coords) = make_coords(span) else { continue };
|
||||
let cov_span = coords.make_coverage_span(local_file_id);
|
||||
|
||||
|
|
@ -177,6 +184,19 @@ fn fill_region_tables<'tcx>(
|
|||
}
|
||||
}
|
||||
|
||||
/// LLVM requires all local file IDs to have at least one mapping region.
|
||||
/// If that's not the case, skip this function, to avoid an assertion failure
|
||||
/// (or worse) in LLVM.
|
||||
fn check_local_file_table(covfun: &CovfunRecord<'_>) -> bool {
|
||||
let mut local_file_id_seen =
|
||||
IndexVec::<u32, _>::from_elem_n(false, covfun.virtual_file_mapping.local_file_table.len());
|
||||
for cov_span in covfun.regions.all_cov_spans() {
|
||||
local_file_id_seen[cov_span.file_id] = true;
|
||||
}
|
||||
|
||||
local_file_id_seen.into_iter().all(|seen| seen)
|
||||
}
|
||||
|
||||
/// Generates the contents of the covfun record for this function, which
|
||||
/// contains the function's coverage mapping data. The record is then stored
|
||||
/// as a global variable in the `__llvm_covfun` section.
|
||||
|
|
@ -185,6 +205,10 @@ pub(crate) fn generate_covfun_record<'tcx>(
|
|||
global_file_table: &GlobalFileTable,
|
||||
covfun: &CovfunRecord<'tcx>,
|
||||
) {
|
||||
if !check_local_file_table(covfun) {
|
||||
return;
|
||||
}
|
||||
|
||||
let &CovfunRecord {
|
||||
mangled_function_name,
|
||||
source_hash,
|
||||
|
|
|
|||
|
|
@ -39,7 +39,10 @@ impl Coords {
|
|||
/// or other expansions), and if it does happen then skipping a span or function is
|
||||
/// better than an ICE or `llvm-cov` failure that the user might have no way to avoid.
|
||||
pub(crate) fn make_coords(source_map: &SourceMap, file: &SourceFile, span: Span) -> Option<Coords> {
|
||||
let span = ensure_non_empty_span(source_map, span)?;
|
||||
if span.is_empty() {
|
||||
debug_assert!(false, "can't make coords from empty span: {span:?}");
|
||||
return None;
|
||||
}
|
||||
|
||||
let lo = span.lo();
|
||||
let hi = span.hi();
|
||||
|
|
@ -70,29 +73,6 @@ pub(crate) fn make_coords(source_map: &SourceMap, file: &SourceFile, span: Span)
|
|||
})
|
||||
}
|
||||
|
||||
fn ensure_non_empty_span(source_map: &SourceMap, span: Span) -> Option<Span> {
|
||||
if !span.is_empty() {
|
||||
return Some(span);
|
||||
}
|
||||
|
||||
// The span is empty, so try to enlarge it to cover an adjacent '{' or '}'.
|
||||
source_map
|
||||
.span_to_source(span, |src, start, end| try {
|
||||
// Adjusting span endpoints by `BytePos(1)` is normally a bug,
|
||||
// but in this case we have specifically checked that the character
|
||||
// we're skipping over is one of two specific ASCII characters, so
|
||||
// adjusting by exactly 1 byte is correct.
|
||||
if src.as_bytes().get(end).copied() == Some(b'{') {
|
||||
Some(span.with_hi(span.hi() + BytePos(1)))
|
||||
} else if start > 0 && src.as_bytes()[start - 1] == b'}' {
|
||||
Some(span.with_lo(span.lo() - BytePos(1)))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
})
|
||||
.ok()?
|
||||
}
|
||||
|
||||
/// If `llvm-cov` sees a source region that is improperly ordered (end < start),
|
||||
/// it will immediately exit with a fatal error. To prevent that from happening,
|
||||
/// discard regions that are improperly ordered, or might be interpreted in a
|
||||
|
|
|
|||
|
|
@ -19,6 +19,7 @@ regex = "1.4"
|
|||
rustc_abi = { path = "../rustc_abi" }
|
||||
rustc_arena = { path = "../rustc_arena" }
|
||||
rustc_ast = { path = "../rustc_ast" }
|
||||
rustc_attr_data_structures = { path = "../rustc_attr_data_structures" }
|
||||
rustc_attr_parsing = { path = "../rustc_attr_parsing" }
|
||||
rustc_data_structures = { path = "../rustc_data_structures" }
|
||||
rustc_errors = { path = "../rustc_errors" }
|
||||
|
|
|
|||
|
|
@ -370,7 +370,7 @@ fn exported_symbols_provider_local<'tcx>(
|
|||
|
||||
if !tcx.sess.opts.share_generics() {
|
||||
if tcx.codegen_fn_attrs(mono_item.def_id()).inline
|
||||
== rustc_attr_parsing::InlineAttr::Never
|
||||
== rustc_attr_data_structures::InlineAttr::Never
|
||||
{
|
||||
// this is OK, we explicitly allow sharing inline(never) across crates even
|
||||
// without share-generics.
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@ use itertools::Itertools;
|
|||
use rustc_abi::FIRST_VARIANT;
|
||||
use rustc_ast as ast;
|
||||
use rustc_ast::expand::allocator::{ALLOCATOR_METHODS, AllocatorKind, global_fn_name};
|
||||
use rustc_attr_parsing::OptimizeAttr;
|
||||
use rustc_attr_data_structures::OptimizeAttr;
|
||||
use rustc_data_structures::fx::{FxHashMap, FxIndexSet};
|
||||
use rustc_data_structures::profiling::{get_resident_set_size, print_time_passes_entry};
|
||||
use rustc_data_structures::sync::{IntoDynSyncSend, par_map};
|
||||
|
|
|
|||
|
|
@ -3,8 +3,8 @@ use std::str::FromStr;
|
|||
use rustc_abi::ExternAbi;
|
||||
use rustc_ast::expand::autodiff_attrs::{AutoDiffAttrs, DiffActivity, DiffMode};
|
||||
use rustc_ast::{LitKind, MetaItem, MetaItemInner, attr};
|
||||
use rustc_attr_parsing::ReprAttr::ReprAlign;
|
||||
use rustc_attr_parsing::{AttributeKind, InlineAttr, InstructionSetAttr, OptimizeAttr};
|
||||
use rustc_attr_data_structures::ReprAttr::ReprAlign;
|
||||
use rustc_attr_data_structures::{AttributeKind, InlineAttr, InstructionSetAttr, OptimizeAttr};
|
||||
use rustc_data_structures::fx::FxHashMap;
|
||||
use rustc_hir::def::DefKind;
|
||||
use rustc_hir::def_id::{DefId, LOCAL_CRATE, LocalDefId};
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
use rustc_abi::{BackendRepr, Float, Integer, Primitive, RegKind};
|
||||
use rustc_attr_parsing::InstructionSetAttr;
|
||||
use rustc_attr_data_structures::InstructionSetAttr;
|
||||
use rustc_hir::def_id::DefId;
|
||||
use rustc_middle::mir::mono::{Linkage, MonoItemData, Visibility};
|
||||
use rustc_middle::mir::{InlineAsmOperand, START_BLOCK};
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
use rustc_attr_parsing::InstructionSetAttr;
|
||||
use rustc_attr_data_structures::InstructionSetAttr;
|
||||
use rustc_data_structures::fx::FxIndexSet;
|
||||
use rustc_data_structures::unord::{UnordMap, UnordSet};
|
||||
use rustc_errors::Applicability;
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ either = "1"
|
|||
rustc_abi = { path = "../rustc_abi" }
|
||||
rustc_apfloat = "0.2.0"
|
||||
rustc_ast = { path = "../rustc_ast" }
|
||||
rustc_attr_parsing = { path = "../rustc_attr_parsing" }
|
||||
rustc_attr_data_structures = { path = "../rustc_attr_data_structures" }
|
||||
rustc_data_structures = { path = "../rustc_data_structures" }
|
||||
rustc_errors = { path = "../rustc_errors" }
|
||||
rustc_fluent_macro = { path = "../rustc_fluent_macro" }
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ use std::mem;
|
|||
use std::num::NonZero;
|
||||
use std::ops::Deref;
|
||||
|
||||
use rustc_attr_parsing::{ConstStability, StabilityLevel};
|
||||
use rustc_attr_data_structures as attrs;
|
||||
use rustc_errors::{Diag, ErrorGuaranteed};
|
||||
use rustc_hir::def::DefKind;
|
||||
use rustc_hir::def_id::DefId;
|
||||
|
|
@ -475,7 +475,7 @@ impl<'mir, 'tcx> Checker<'mir, 'tcx> {
|
|||
/// Check the const stability of the given item (fn or trait).
|
||||
fn check_callee_stability(&mut self, def_id: DefId) {
|
||||
match self.tcx.lookup_const_stability(def_id) {
|
||||
Some(ConstStability { level: StabilityLevel::Stable { .. }, .. }) => {
|
||||
Some(attrs::ConstStability { level: attrs::StabilityLevel::Stable { .. }, .. }) => {
|
||||
// All good.
|
||||
}
|
||||
None => {
|
||||
|
|
@ -491,8 +491,8 @@ impl<'mir, 'tcx> Checker<'mir, 'tcx> {
|
|||
});
|
||||
}
|
||||
}
|
||||
Some(ConstStability {
|
||||
level: StabilityLevel::Unstable { implied_by: implied_feature, issue, .. },
|
||||
Some(attrs::ConstStability {
|
||||
level: attrs::StabilityLevel::Unstable { implied_by: implied_feature, issue, .. },
|
||||
feature,
|
||||
..
|
||||
}) => {
|
||||
|
|
@ -918,8 +918,8 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> {
|
|||
});
|
||||
}
|
||||
}
|
||||
Some(ConstStability {
|
||||
level: StabilityLevel::Unstable { .. },
|
||||
Some(attrs::ConstStability {
|
||||
level: attrs::StabilityLevel::Unstable { .. },
|
||||
feature,
|
||||
..
|
||||
}) => {
|
||||
|
|
@ -930,7 +930,10 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> {
|
|||
suggestion: self.crate_inject_span(),
|
||||
});
|
||||
}
|
||||
Some(ConstStability { level: StabilityLevel::Stable { .. }, .. }) => {
|
||||
Some(attrs::ConstStability {
|
||||
level: attrs::StabilityLevel::Stable { .. },
|
||||
..
|
||||
}) => {
|
||||
// All good. Note that a `#[rustc_const_stable]` intrinsic (meaning it
|
||||
// can be *directly* invoked from stable const code) does not always
|
||||
// have the `#[rustc_intrinsic_const_stable_indirect]` attribute (which controls
|
||||
|
|
|
|||
|
|
@ -4,13 +4,12 @@
|
|||
//! has interior mutability or needs to be dropped, as well as the visitor that emits errors when
|
||||
//! it finds operations that are invalid in a certain context.
|
||||
|
||||
use rustc_attr_parsing::{AttributeKind, find_attr};
|
||||
use rustc_errors::DiagCtxtHandle;
|
||||
use rustc_hir as hir;
|
||||
use rustc_hir::def_id::{DefId, LocalDefId};
|
||||
use rustc_middle::ty::{self, PolyFnSig, TyCtxt};
|
||||
use rustc_middle::{bug, mir};
|
||||
use rustc_span::Symbol;
|
||||
use {rustc_attr_data_structures as attrs, rustc_hir as hir};
|
||||
|
||||
pub use self::qualifs::Qualif;
|
||||
|
||||
|
|
@ -83,7 +82,7 @@ pub fn rustc_allow_const_fn_unstable(
|
|||
) -> bool {
|
||||
let attrs = tcx.hir_attrs(tcx.local_def_id_to_hir_id(def_id));
|
||||
|
||||
find_attr!(attrs, AttributeKind::AllowConstFnUnstable(syms) if syms.contains(&feature_gate))
|
||||
attrs::find_attr!(attrs, attrs::AttributeKind::AllowConstFnUnstable(syms) if syms.contains(&feature_gate))
|
||||
}
|
||||
|
||||
/// Returns `true` if the given `def_id` (trait or function) is "safe to expose on stable".
|
||||
|
|
|
|||
|
|
@ -12,6 +12,7 @@ doctest = false
|
|||
rustc_ast = { path = "../rustc_ast" }
|
||||
rustc_ast_passes = { path = "../rustc_ast_passes" }
|
||||
rustc_ast_pretty = { path = "../rustc_ast_pretty" }
|
||||
rustc_attr_data_structures = { path = "../rustc_attr_data_structures" }
|
||||
rustc_attr_parsing = { path = "../rustc_attr_parsing" }
|
||||
rustc_data_structures = { path = "../rustc_data_structures" }
|
||||
rustc_errors = { path = "../rustc_errors" }
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@ use rustc_ast::token::MetaVarKind;
|
|||
use rustc_ast::tokenstream::TokenStream;
|
||||
use rustc_ast::visit::{AssocCtxt, Visitor};
|
||||
use rustc_ast::{self as ast, AttrVec, Attribute, HasAttrs, Item, NodeId, PatKind};
|
||||
use rustc_attr_parsing::{AttributeKind, Deprecation, Stability, find_attr};
|
||||
use rustc_attr_data_structures::{AttributeKind, Deprecation, Stability, find_attr};
|
||||
use rustc_data_structures::fx::FxIndexMap;
|
||||
use rustc_data_structures::sync;
|
||||
use rustc_errors::{DiagCtxtHandle, ErrorGuaranteed, PResult};
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@ use rustc_ast::token::{self, NonterminalKind, Token, TokenKind};
|
|||
use rustc_ast::tokenstream::{DelimSpan, TokenStream};
|
||||
use rustc_ast::{self as ast, DUMMY_NODE_ID, NodeId};
|
||||
use rustc_ast_pretty::pprust;
|
||||
use rustc_attr_parsing::{AttributeKind, find_attr};
|
||||
use rustc_attr_data_structures::{AttributeKind, find_attr};
|
||||
use rustc_data_structures::fx::{FxHashMap, FxIndexMap};
|
||||
use rustc_errors::{Applicability, Diag, ErrorGuaranteed};
|
||||
use rustc_feature::Features;
|
||||
|
|
|
|||
|
|
@ -13,7 +13,7 @@ itertools = "0.12"
|
|||
rustc_abi = { path = "../rustc_abi" }
|
||||
rustc_arena = { path = "../rustc_arena" }
|
||||
rustc_ast = { path = "../rustc_ast" }
|
||||
rustc_attr_parsing = { path = "../rustc_attr_parsing" }
|
||||
rustc_attr_data_structures = { path = "../rustc_attr_data_structures" }
|
||||
rustc_data_structures = { path = "../rustc_data_structures" }
|
||||
rustc_errors = { path = "../rustc_errors" }
|
||||
rustc_feature = { path = "../rustc_feature" }
|
||||
|
|
|
|||
|
|
@ -2,8 +2,7 @@ use std::cell::LazyCell;
|
|||
use std::ops::ControlFlow;
|
||||
|
||||
use rustc_abi::FieldIdx;
|
||||
use rustc_attr_parsing::AttributeKind;
|
||||
use rustc_attr_parsing::ReprAttr::ReprPacked;
|
||||
use rustc_attr_data_structures::ReprAttr::ReprPacked;
|
||||
use rustc_data_structures::unord::{UnordMap, UnordSet};
|
||||
use rustc_errors::MultiSpan;
|
||||
use rustc_errors::codes::*;
|
||||
|
|
@ -31,7 +30,7 @@ use rustc_trait_selection::traits;
|
|||
use rustc_trait_selection::traits::query::evaluate_obligation::InferCtxtExt;
|
||||
use tracing::{debug, instrument};
|
||||
use ty::TypingMode;
|
||||
use {rustc_attr_parsing as attr, rustc_hir as hir};
|
||||
use {rustc_attr_data_structures as attrs, rustc_hir as hir};
|
||||
|
||||
use super::compare_impl_item::check_type_bounds;
|
||||
use super::*;
|
||||
|
|
@ -1154,7 +1153,7 @@ pub(super) fn check_packed(tcx: TyCtxt<'_>, sp: Span, def: ty::AdtDef<'_>) {
|
|||
let repr = def.repr();
|
||||
if repr.packed() {
|
||||
if let Some(reprs) =
|
||||
attr::find_attr!(tcx.get_all_attrs(def.did()), AttributeKind::Repr(r) => r)
|
||||
attrs::find_attr!(tcx.get_all_attrs(def.did()), attrs::AttributeKind::Repr(r) => r)
|
||||
{
|
||||
for (r, _) in reprs {
|
||||
if let ReprPacked(pack) = r
|
||||
|
|
@ -1371,9 +1370,9 @@ fn check_enum(tcx: TyCtxt<'_>, def_id: LocalDefId) {
|
|||
def.destructor(tcx); // force the destructor to be evaluated
|
||||
|
||||
if def.variants().is_empty() {
|
||||
attr::find_attr!(
|
||||
attrs::find_attr!(
|
||||
tcx.get_all_attrs(def_id),
|
||||
AttributeKind::Repr(rs) => {
|
||||
attrs::AttributeKind::Repr(rs) => {
|
||||
struct_span_code_err!(
|
||||
tcx.dcx(),
|
||||
rs.first().unwrap().1,
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ edition = "2024"
|
|||
itertools = "0.12"
|
||||
rustc_abi = { path = "../rustc_abi" }
|
||||
rustc_ast = { path = "../rustc_ast" }
|
||||
rustc_attr_parsing = { path = "../rustc_attr_parsing" }
|
||||
rustc_attr_data_structures = { path = "../rustc_attr_data_structures" }
|
||||
rustc_data_structures = { path = "../rustc_data_structures" }
|
||||
rustc_errors = { path = "../rustc_errors" }
|
||||
rustc_fluent_macro = { path = "../rustc_fluent_macro" }
|
||||
|
|
|
|||
|
|
@ -37,7 +37,7 @@
|
|||
|
||||
use std::ops::Deref;
|
||||
|
||||
use rustc_attr_parsing::InlineAttr;
|
||||
use rustc_attr_data_structures::InlineAttr;
|
||||
use rustc_errors::codes::*;
|
||||
use rustc_errors::{Applicability, Diag, struct_span_code_err};
|
||||
use rustc_hir as hir;
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ use std::path::PathBuf;
|
|||
|
||||
use hir::Expr;
|
||||
use rustc_ast::ast::Mutability;
|
||||
use rustc_attr_parsing::{AttributeKind, find_attr};
|
||||
use rustc_attr_data_structures::{AttributeKind, find_attr};
|
||||
use rustc_data_structures::fx::{FxIndexMap, FxIndexSet};
|
||||
use rustc_data_structures::sorted_map::SortedMap;
|
||||
use rustc_data_structures::unord::UnordSet;
|
||||
|
|
|
|||
|
|
@ -282,6 +282,7 @@ fn configure_and_expand(
|
|||
resolver.resolve_crate(&krate);
|
||||
|
||||
CStore::from_tcx(tcx).report_incompatible_target_modifiers(tcx, &krate);
|
||||
CStore::from_tcx(tcx).report_incompatible_async_drop_feature(tcx, &krate);
|
||||
krate
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -776,7 +776,8 @@ fn test_unstable_options_tracking_hash() {
|
|||
CoverageOptions {
|
||||
level: CoverageLevel::Mcdc,
|
||||
no_mir_spans: true,
|
||||
discard_all_spans_in_codegen: true
|
||||
discard_all_spans_in_codegen: true,
|
||||
inject_unused_local_file: true,
|
||||
}
|
||||
);
|
||||
tracked!(crate_attr, vec!["abc".to_string()]);
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@ edition = "2024"
|
|||
rustc_abi = { path = "../rustc_abi" }
|
||||
rustc_ast = { path = "../rustc_ast" }
|
||||
rustc_ast_pretty = { path = "../rustc_ast_pretty" }
|
||||
rustc_attr_data_structures = { path = "../rustc_attr_data_structures" }
|
||||
rustc_attr_parsing = { path = "../rustc_attr_parsing" }
|
||||
rustc_data_structures = { path = "../rustc_data_structures" }
|
||||
rustc_errors = { path = "../rustc_errors" }
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
use rustc_abi::ExternAbi;
|
||||
use rustc_attr_parsing::{AttributeKind, AttributeParser, ReprAttr};
|
||||
use rustc_attr_data_structures::{AttributeKind, ReprAttr};
|
||||
use rustc_attr_parsing::AttributeParser;
|
||||
use rustc_hir::def::{DefKind, Res};
|
||||
use rustc_hir::intravisit::FnKind;
|
||||
use rustc_hir::{AttrArgs, AttrItem, Attribute, GenericParamKind, PatExprKind, PatKind};
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ use rustc_middle::ty::Ty;
|
|||
use rustc_middle::ty::layout::IntegerExt;
|
||||
use rustc_middle::{bug, ty};
|
||||
use rustc_span::Span;
|
||||
use {rustc_ast as ast, rustc_attr_parsing as attr, rustc_hir as hir};
|
||||
use {rustc_ast as ast, rustc_attr_data_structures as attrs, rustc_hir as hir};
|
||||
|
||||
use crate::LateContext;
|
||||
use crate::context::LintContext;
|
||||
|
|
@ -131,18 +131,18 @@ fn report_bin_hex_error(
|
|||
cx: &LateContext<'_>,
|
||||
hir_id: HirId,
|
||||
span: Span,
|
||||
ty: attr::IntType,
|
||||
ty: attrs::IntType,
|
||||
size: Size,
|
||||
repr_str: String,
|
||||
val: u128,
|
||||
negative: bool,
|
||||
) {
|
||||
let (t, actually) = match ty {
|
||||
attr::IntType::SignedInt(t) => {
|
||||
attrs::IntType::SignedInt(t) => {
|
||||
let actually = if negative { -(size.sign_extend(val)) } else { size.sign_extend(val) };
|
||||
(t.name_str(), actually.to_string())
|
||||
}
|
||||
attr::IntType::UnsignedInt(t) => {
|
||||
attrs::IntType::UnsignedInt(t) => {
|
||||
let actually = size.truncate(val);
|
||||
(t.name_str(), actually.to_string())
|
||||
}
|
||||
|
|
@ -264,7 +264,7 @@ fn lint_int_literal<'tcx>(
|
|||
cx,
|
||||
hir_id,
|
||||
span,
|
||||
attr::IntType::SignedInt(ty::ast_int_ty(t)),
|
||||
attrs::IntType::SignedInt(ty::ast_int_ty(t)),
|
||||
Integer::from_int_ty(cx, t).size(),
|
||||
repr_str,
|
||||
v,
|
||||
|
|
@ -336,7 +336,7 @@ fn lint_uint_literal<'tcx>(
|
|||
cx,
|
||||
hir_id,
|
||||
span,
|
||||
attr::IntType::UnsignedInt(ty::ast_uint_ty(t)),
|
||||
attrs::IntType::UnsignedInt(ty::ast_uint_ty(t)),
|
||||
Integer::from_uint_ty(cx, t).size(),
|
||||
repr_str,
|
||||
lit_val,
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@ libloading = "0.8.0"
|
|||
odht = { version = "0.3.1", features = ["nightly"] }
|
||||
rustc_abi = { path = "../rustc_abi" }
|
||||
rustc_ast = { path = "../rustc_ast" }
|
||||
rustc_attr_data_structures = { path = "../rustc_attr_data_structures" }
|
||||
rustc_attr_parsing = { path = "../rustc_attr_parsing" }
|
||||
rustc_data_structures = { path = "../rustc_data_structures" }
|
||||
rustc_errors = { path = "../rustc_errors" }
|
||||
|
|
|
|||
|
|
@ -1,6 +1,10 @@
|
|||
metadata_as_needed_compatibility =
|
||||
linking modifier `as-needed` is only compatible with `dylib` and `framework` linking kinds
|
||||
|
||||
metadata_async_drop_types_in_dependency =
|
||||
found async drop types in dependecy `{$extern_crate}`, but async_drop feature is disabled for `{$local_crate}`
|
||||
.help = if async drop type will be dropped in a crate without `feature(async_drop)`, sync Drop will be used
|
||||
|
||||
metadata_bad_panic_strategy =
|
||||
the linked panic runtime `{$runtime}` is not compiled with this crate's panic strategy `{$strategy}`
|
||||
|
||||
|
|
|
|||
|
|
@ -473,6 +473,27 @@ impl CStore {
|
|||
}
|
||||
}
|
||||
|
||||
// Report about async drop types in dependency if async drop feature is disabled
|
||||
pub fn report_incompatible_async_drop_feature(&self, tcx: TyCtxt<'_>, krate: &Crate) {
|
||||
if tcx.features().async_drop() {
|
||||
return;
|
||||
}
|
||||
for (_cnum, data) in self.iter_crate_data() {
|
||||
if data.is_proc_macro_crate() {
|
||||
continue;
|
||||
}
|
||||
if data.has_async_drops() {
|
||||
let extern_crate = data.name();
|
||||
let local_crate = tcx.crate_name(LOCAL_CRATE);
|
||||
tcx.dcx().emit_warn(errors::AsyncDropTypesInDependency {
|
||||
span: krate.spans.inner_span.shrink_to_lo(),
|
||||
extern_crate,
|
||||
local_crate,
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn new(metadata_loader: Box<MetadataLoaderDyn>) -> CStore {
|
||||
CStore {
|
||||
metadata_loader,
|
||||
|
|
|
|||
|
|
@ -811,3 +811,13 @@ pub struct UnknownTargetModifierUnsafeAllowed {
|
|||
pub span: Span,
|
||||
pub flag_name: String,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(metadata_async_drop_types_in_dependency)]
|
||||
#[help]
|
||||
pub struct AsyncDropTypesInDependency {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
pub extern_crate: Symbol,
|
||||
pub local_crate: Symbol,
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1984,6 +1984,10 @@ impl CrateMetadata {
|
|||
self.root.header.hash
|
||||
}
|
||||
|
||||
pub(crate) fn has_async_drops(&self) -> bool {
|
||||
self.root.tables.adt_async_destructor.len > 0
|
||||
}
|
||||
|
||||
fn num_def_ids(&self) -> usize {
|
||||
self.root.tables.def_keys.size()
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@ use std::any::Any;
|
|||
use std::mem;
|
||||
use std::sync::Arc;
|
||||
|
||||
use rustc_attr_parsing::Deprecation;
|
||||
use rustc_attr_data_structures::Deprecation;
|
||||
use rustc_hir::def::{CtorKind, DefKind, Res};
|
||||
use rustc_hir::def_id::{CrateNum, DefId, DefIdMap, LOCAL_CRATE};
|
||||
use rustc_hir::definitions::{DefKey, DefPath, DefPathHash};
|
||||
|
|
|
|||
|
|
@ -40,7 +40,7 @@ use rustc_span::hygiene::{ExpnIndex, MacroKind, SyntaxContextKey};
|
|||
use rustc_span::{self, ExpnData, ExpnHash, ExpnId, Ident, Span, Symbol};
|
||||
use rustc_target::spec::{PanicStrategy, TargetTuple};
|
||||
use table::TableBuilder;
|
||||
use {rustc_ast as ast, rustc_attr_parsing as attr, rustc_hir as hir};
|
||||
use {rustc_ast as ast, rustc_attr_data_structures as attrs, rustc_hir as hir};
|
||||
|
||||
use crate::creader::CrateMetadataRef;
|
||||
|
||||
|
|
@ -200,7 +200,7 @@ type ExpnHashTable = LazyTable<ExpnIndex, Option<LazyValue<ExpnHash>>>;
|
|||
#[derive(MetadataEncodable, MetadataDecodable)]
|
||||
pub(crate) struct ProcMacroData {
|
||||
proc_macro_decls_static: DefIndex,
|
||||
stability: Option<attr::Stability>,
|
||||
stability: Option<attrs::Stability>,
|
||||
macros: LazyArray<DefIndex>,
|
||||
}
|
||||
|
||||
|
|
@ -422,10 +422,10 @@ define_tables! {
|
|||
safety: Table<DefIndex, hir::Safety>,
|
||||
def_span: Table<DefIndex, LazyValue<Span>>,
|
||||
def_ident_span: Table<DefIndex, LazyValue<Span>>,
|
||||
lookup_stability: Table<DefIndex, LazyValue<attr::Stability>>,
|
||||
lookup_const_stability: Table<DefIndex, LazyValue<attr::ConstStability>>,
|
||||
lookup_default_body_stability: Table<DefIndex, LazyValue<attr::DefaultBodyStability>>,
|
||||
lookup_deprecation_entry: Table<DefIndex, LazyValue<attr::Deprecation>>,
|
||||
lookup_stability: Table<DefIndex, LazyValue<attrs::Stability>>,
|
||||
lookup_const_stability: Table<DefIndex, LazyValue<attrs::ConstStability>>,
|
||||
lookup_default_body_stability: Table<DefIndex, LazyValue<attrs::DefaultBodyStability>>,
|
||||
lookup_deprecation_entry: Table<DefIndex, LazyValue<attrs::Deprecation>>,
|
||||
explicit_predicates_of: Table<DefIndex, LazyValue<ty::GenericPredicates<'static>>>,
|
||||
generics_of: Table<DefIndex, LazyValue<ty::Generics>>,
|
||||
type_of: Table<DefIndex, LazyValue<ty::EarlyBinder<'static, Ty<'static>>>>,
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ use std::num::NonZero;
|
|||
|
||||
use rustc_ast::NodeId;
|
||||
use rustc_attr_data_structures::{
|
||||
self as attr, ConstStability, DefaultBodyStability, DeprecatedSince, Deprecation, Stability,
|
||||
self as attrs, ConstStability, DefaultBodyStability, DeprecatedSince, Deprecation, Stability,
|
||||
};
|
||||
use rustc_data_structures::unord::UnordMap;
|
||||
use rustc_errors::{Applicability, Diag, EmissionGuarantee};
|
||||
|
|
@ -411,7 +411,7 @@ impl<'tcx> TyCtxt<'tcx> {
|
|||
|
||||
match stability {
|
||||
Some(Stability {
|
||||
level: attr::StabilityLevel::Unstable { reason, issue, is_soft, implied_by },
|
||||
level: attrs::StabilityLevel::Unstable { reason, issue, is_soft, implied_by },
|
||||
feature,
|
||||
..
|
||||
}) => {
|
||||
|
|
@ -494,7 +494,7 @@ impl<'tcx> TyCtxt<'tcx> {
|
|||
|
||||
match stability {
|
||||
Some(DefaultBodyStability {
|
||||
level: attr::StabilityLevel::Unstable { reason, issue, is_soft, .. },
|
||||
level: attrs::StabilityLevel::Unstable { reason, issue, is_soft, .. },
|
||||
feature,
|
||||
}) => {
|
||||
if span.allows_unstable(feature) {
|
||||
|
|
@ -643,7 +643,7 @@ impl<'tcx> TyCtxt<'tcx> {
|
|||
|
||||
match stability {
|
||||
Some(ConstStability {
|
||||
level: attr::StabilityLevel::Unstable { reason, issue, is_soft, implied_by, .. },
|
||||
level: attrs::StabilityLevel::Unstable { reason, issue, is_soft, implied_by, .. },
|
||||
feature,
|
||||
..
|
||||
}) => {
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@ itertools = "0.12"
|
|||
rustc_abi = { path = "../rustc_abi" }
|
||||
rustc_arena = { path = "../rustc_arena" }
|
||||
rustc_ast = { path = "../rustc_ast" }
|
||||
rustc_attr_parsing = { path = "../rustc_attr_parsing" }
|
||||
rustc_attr_data_structures = { path = "../rustc_attr_data_structures" }
|
||||
rustc_const_eval = { path = "../rustc_const_eval" }
|
||||
rustc_data_structures = { path = "../rustc_data_structures" }
|
||||
rustc_errors = { path = "../rustc_errors" }
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
//! Check that a body annotated with `#[rustc_force_inline]` will not fail to inline based on its
|
||||
//! definition alone (irrespective of any specific caller).
|
||||
|
||||
use rustc_attr_parsing::InlineAttr;
|
||||
use rustc_attr_data_structures::InlineAttr;
|
||||
use rustc_hir::def_id::DefId;
|
||||
use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrFlags;
|
||||
use rustc_middle::mir::{Body, TerminatorKind};
|
||||
|
|
|
|||
|
|
@ -1,7 +1,8 @@
|
|||
use rustc_data_structures::fx::FxHashSet;
|
||||
use rustc_middle::mir;
|
||||
use rustc_middle::ty::TyCtxt;
|
||||
use rustc_span::{DesugaringKind, ExpnKind, MacroKind, Span};
|
||||
use rustc_span::source_map::SourceMap;
|
||||
use rustc_span::{BytePos, DesugaringKind, ExpnKind, MacroKind, Span};
|
||||
use tracing::instrument;
|
||||
|
||||
use crate::coverage::graph::{BasicCoverageBlock, CoverageGraph};
|
||||
|
|
@ -83,8 +84,18 @@ pub(super) fn extract_refined_covspans<'tcx>(
|
|||
// Discard any span that overlaps with a hole.
|
||||
discard_spans_overlapping_holes(&mut covspans, &holes);
|
||||
|
||||
// Perform more refinement steps after holes have been dealt with.
|
||||
// Discard spans that overlap in unwanted ways.
|
||||
let mut covspans = remove_unwanted_overlapping_spans(covspans);
|
||||
|
||||
// For all empty spans, either enlarge them to be non-empty, or discard them.
|
||||
let source_map = tcx.sess.source_map();
|
||||
covspans.retain_mut(|covspan| {
|
||||
let Some(span) = ensure_non_empty_span(source_map, covspan.span) else { return false };
|
||||
covspan.span = span;
|
||||
true
|
||||
});
|
||||
|
||||
// Merge covspans that can be merged.
|
||||
covspans.dedup_by(|b, a| a.merge_if_eligible(b));
|
||||
|
||||
code_mappings.extend(covspans.into_iter().map(|Covspan { span, bcb }| {
|
||||
|
|
@ -230,3 +241,26 @@ fn compare_spans(a: Span, b: Span) -> std::cmp::Ordering {
|
|||
// - Both have the same start and span A extends further right
|
||||
.then_with(|| Ord::cmp(&a.hi(), &b.hi()).reverse())
|
||||
}
|
||||
|
||||
fn ensure_non_empty_span(source_map: &SourceMap, span: Span) -> Option<Span> {
|
||||
if !span.is_empty() {
|
||||
return Some(span);
|
||||
}
|
||||
|
||||
// The span is empty, so try to enlarge it to cover an adjacent '{' or '}'.
|
||||
source_map
|
||||
.span_to_source(span, |src, start, end| try {
|
||||
// Adjusting span endpoints by `BytePos(1)` is normally a bug,
|
||||
// but in this case we have specifically checked that the character
|
||||
// we're skipping over is one of two specific ASCII characters, so
|
||||
// adjusting by exactly 1 byte is correct.
|
||||
if src.as_bytes().get(end).copied() == Some(b'{') {
|
||||
Some(span.with_hi(span.hi() + BytePos(1)))
|
||||
} else if start > 0 && src.as_bytes()[start - 1] == b'}' {
|
||||
Some(span.with_lo(span.lo() - BytePos(1)))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
})
|
||||
.ok()?
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
use rustc_attr_parsing::InlineAttr;
|
||||
use rustc_attr_data_structures::InlineAttr;
|
||||
use rustc_hir::def::DefKind;
|
||||
use rustc_hir::def_id::LocalDefId;
|
||||
use rustc_middle::mir::visit::Visitor;
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ use std::iter;
|
|||
use std::ops::{Range, RangeFrom};
|
||||
|
||||
use rustc_abi::{ExternAbi, FieldIdx};
|
||||
use rustc_attr_parsing::{InlineAttr, OptimizeAttr};
|
||||
use rustc_attr_data_structures::{InlineAttr, OptimizeAttr};
|
||||
use rustc_hir::def::DefKind;
|
||||
use rustc_hir::def_id::DefId;
|
||||
use rustc_index::Idx;
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
//! Validates the MIR to ensure that invariants are upheld.
|
||||
|
||||
use rustc_abi::{ExternAbi, FIRST_VARIANT, Size};
|
||||
use rustc_attr_parsing::InlineAttr;
|
||||
use rustc_attr_data_structures::InlineAttr;
|
||||
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
|
||||
use rustc_hir::LangItem;
|
||||
use rustc_index::IndexVec;
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@ edition = "2024"
|
|||
# tidy-alphabetical-start
|
||||
rustc_abi = { path = "../rustc_abi" }
|
||||
rustc_ast = { path = "../rustc_ast" }
|
||||
rustc_attr_parsing = { path = "../rustc_attr_parsing" }
|
||||
rustc_attr_data_structures = { path = "../rustc_attr_data_structures" }
|
||||
rustc_data_structures = { path = "../rustc_data_structures" }
|
||||
rustc_errors = { path = "../rustc_errors" }
|
||||
rustc_fluent_macro = { path = "../rustc_fluent_macro" }
|
||||
|
|
|
|||
|
|
@ -208,7 +208,7 @@
|
|||
use std::cell::OnceCell;
|
||||
use std::path::PathBuf;
|
||||
|
||||
use rustc_attr_parsing::InlineAttr;
|
||||
use rustc_attr_data_structures::InlineAttr;
|
||||
use rustc_data_structures::fx::FxIndexMap;
|
||||
use rustc_data_structures::sync::{MTLock, par_for_each_in};
|
||||
use rustc_data_structures::unord::{UnordMap, UnordSet};
|
||||
|
|
|
|||
|
|
@ -100,6 +100,7 @@ use std::fs::{self, File};
|
|||
use std::io::Write;
|
||||
use std::path::{Path, PathBuf};
|
||||
|
||||
use rustc_attr_data_structures::InlineAttr;
|
||||
use rustc_data_structures::fx::{FxIndexMap, FxIndexSet};
|
||||
use rustc_data_structures::sync;
|
||||
use rustc_data_structures::unord::{UnordMap, UnordSet};
|
||||
|
|
@ -845,8 +846,7 @@ fn mono_item_visibility<'tcx>(
|
|||
return if is_generic
|
||||
&& (always_export_generics
|
||||
|| (can_export_generics
|
||||
&& tcx.codegen_fn_attrs(def_id).inline
|
||||
== rustc_attr_parsing::InlineAttr::Never))
|
||||
&& tcx.codegen_fn_attrs(def_id).inline == InlineAttr::Never))
|
||||
{
|
||||
// If it is an upstream monomorphization and we export generics, we must make
|
||||
// it available to downstream crates.
|
||||
|
|
@ -859,8 +859,7 @@ fn mono_item_visibility<'tcx>(
|
|||
|
||||
if is_generic {
|
||||
if always_export_generics
|
||||
|| (can_export_generics
|
||||
&& tcx.codegen_fn_attrs(def_id).inline == rustc_attr_parsing::InlineAttr::Never)
|
||||
|| (can_export_generics && tcx.codegen_fn_attrs(def_id).inline == InlineAttr::Never)
|
||||
{
|
||||
if tcx.is_unreachable_local_definition(def_id) {
|
||||
// This instance cannot be used from another crate.
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ rustc_abi = { path = "../rustc_abi" }
|
|||
rustc_ast = { path = "../rustc_ast" }
|
||||
rustc_ast_lowering = { path = "../rustc_ast_lowering" }
|
||||
rustc_ast_pretty = { path = "../rustc_ast_pretty" }
|
||||
rustc_attr_parsing = { path = "../rustc_attr_parsing" }
|
||||
rustc_attr_data_structures = { path = "../rustc_attr_data_structures" }
|
||||
rustc_data_structures = { path = "../rustc_data_structures" }
|
||||
rustc_errors = { path = "../rustc_errors" }
|
||||
rustc_expand = { path = "../rustc_expand" }
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@ use std::collections::hash_map::Entry;
|
|||
|
||||
use rustc_abi::{Align, ExternAbi, Size};
|
||||
use rustc_ast::{AttrStyle, LitKind, MetaItemInner, MetaItemKind, MetaItemLit, ast};
|
||||
use rustc_attr_parsing::{AttributeKind, ReprAttr, find_attr};
|
||||
use rustc_attr_data_structures::{AttributeKind, ReprAttr, find_attr};
|
||||
use rustc_data_structures::fx::FxHashMap;
|
||||
use rustc_errors::{Applicability, DiagCtxtHandle, IntoDiagArg, MultiSpan, StashKey};
|
||||
use rustc_feature::{AttributeDuplicates, AttributeType, BUILTIN_ATTRIBUTE_MAP, BuiltinAttribute};
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@
|
|||
//! but are not declared in one single location (unlike lang features), which means we need to
|
||||
//! collect them instead.
|
||||
|
||||
use rustc_attr_parsing::{AttributeKind, StabilityLevel, StableSince};
|
||||
use rustc_attr_data_structures::{AttributeKind, StabilityLevel, StableSince};
|
||||
use rustc_hir::Attribute;
|
||||
use rustc_hir::intravisit::Visitor;
|
||||
use rustc_middle::hir::nested_filter;
|
||||
|
|
|
|||
|
|
@ -5,9 +5,9 @@ use std::mem::replace;
|
|||
use std::num::NonZero;
|
||||
|
||||
use rustc_ast_lowering::stability::extern_abi_stability;
|
||||
use rustc_attr_parsing::{
|
||||
self as attr, AttributeKind, ConstStability, DeprecatedSince, PartialConstStability, Stability,
|
||||
StabilityLevel, StableSince, UnstableReason, VERSION_PLACEHOLDER, find_attr,
|
||||
use rustc_attr_data_structures::{
|
||||
self as attrs, AttributeKind, ConstStability, DeprecatedSince, PartialConstStability,
|
||||
Stability, StabilityLevel, StableSince, UnstableReason, VERSION_PLACEHOLDER, find_attr,
|
||||
};
|
||||
use rustc_data_structures::fx::FxIndexMap;
|
||||
use rustc_data_structures::unord::{ExtendUnord, UnordMap, UnordSet};
|
||||
|
|
@ -121,7 +121,7 @@ impl<'a, 'tcx> Annotator<'a, 'tcx> {
|
|||
let attrs = self.tcx.hir_attrs(self.tcx.local_def_id_to_hir_id(def_id));
|
||||
debug!("annotate(id = {:?}, attrs = {:?})", def_id, attrs);
|
||||
|
||||
let depr = attr::find_attr!(attrs, AttributeKind::Deprecation{deprecation, span} => (*deprecation, *span));
|
||||
let depr = attrs::find_attr!(attrs, AttributeKind::Deprecation{deprecation, span} => (*deprecation, *span));
|
||||
let const_stability_indirect = find_attr!(attrs, AttributeKind::ConstStabilityIndirect);
|
||||
|
||||
let mut is_deprecated = false;
|
||||
|
|
@ -174,9 +174,9 @@ impl<'a, 'tcx> Annotator<'a, 'tcx> {
|
|||
}
|
||||
|
||||
// # Regular and body stability
|
||||
let stab = attr::find_attr!(attrs, AttributeKind::Stability { stability, span } => (*stability, *span));
|
||||
let stab = attrs::find_attr!(attrs, AttributeKind::Stability { stability, span } => (*stability, *span));
|
||||
let body_stab =
|
||||
attr::find_attr!(attrs, AttributeKind::BodyStability { stability, .. } => *stability);
|
||||
attrs::find_attr!(attrs, AttributeKind::BodyStability { stability, .. } => *stability);
|
||||
|
||||
if let Some((depr, span)) = &depr
|
||||
&& depr.is_since_rustc_version()
|
||||
|
|
@ -206,7 +206,7 @@ impl<'a, 'tcx> Annotator<'a, 'tcx> {
|
|||
// this is *almost surely* an accident.
|
||||
if let (
|
||||
&Some(DeprecatedSince::RustcVersion(dep_since)),
|
||||
&attr::StabilityLevel::Stable { since: stab_since, .. },
|
||||
&attrs::StabilityLevel::Stable { since: stab_since, .. },
|
||||
) = (&depr.as_ref().map(|(d, _)| d.since), &stab.level)
|
||||
{
|
||||
match stab_since {
|
||||
|
|
@ -263,7 +263,7 @@ impl<'a, 'tcx> Annotator<'a, 'tcx> {
|
|||
|
||||
// # Const stability
|
||||
|
||||
let const_stab = attr::find_attr!(attrs, AttributeKind::ConstStability { stability, span } => (*stability, *span));
|
||||
let const_stab = attrs::find_attr!(attrs, AttributeKind::ConstStability { stability, span } => (*stability, *span));
|
||||
|
||||
// If the current node is a function with const stability attributes (directly given or
|
||||
// implied), check if the function/method is const or the parent impl block is const.
|
||||
|
|
@ -713,7 +713,7 @@ fn stability_index(tcx: TyCtxt<'_>, (): ()) -> Index {
|
|||
// by default and are unable to be used.
|
||||
if tcx.sess.opts.unstable_opts.force_unstable_if_unmarked {
|
||||
let stability = Stability {
|
||||
level: attr::StabilityLevel::Unstable {
|
||||
level: attrs::StabilityLevel::Unstable {
|
||||
reason: UnstableReason::Default,
|
||||
issue: NonZero::new(27812),
|
||||
is_soft: false,
|
||||
|
|
@ -796,17 +796,17 @@ impl<'tcx> Visitor<'tcx> for Checker<'tcx> {
|
|||
let features = self.tcx.features();
|
||||
if features.staged_api() {
|
||||
let attrs = self.tcx.hir_attrs(item.hir_id());
|
||||
let stab = attr::find_attr!(attrs, AttributeKind::Stability{stability, span} => (*stability, *span));
|
||||
let stab = attrs::find_attr!(attrs, AttributeKind::Stability{stability, span} => (*stability, *span));
|
||||
|
||||
// FIXME(jdonszelmann): make it impossible to miss the or_else in the typesystem
|
||||
let const_stab = attr::find_attr!(attrs, AttributeKind::ConstStability{stability, ..} => *stability);
|
||||
let const_stab = attrs::find_attr!(attrs, AttributeKind::ConstStability{stability, ..} => *stability);
|
||||
|
||||
// If this impl block has an #[unstable] attribute, give an
|
||||
// error if all involved types and traits are stable, because
|
||||
// it will have no effect.
|
||||
// See: https://github.com/rust-lang/rust/issues/55436
|
||||
if let Some((
|
||||
Stability { level: attr::StabilityLevel::Unstable { .. }, .. },
|
||||
Stability { level: attrs::StabilityLevel::Unstable { .. }, .. },
|
||||
span,
|
||||
)) = stab
|
||||
{
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ edition = "2024"
|
|||
[dependencies]
|
||||
# tidy-alphabetical-start
|
||||
rustc_ast = { path = "../rustc_ast" }
|
||||
rustc_attr_parsing = { path = "../rustc_attr_parsing" }
|
||||
rustc_attr_data_structures = { path = "../rustc_attr_data_structures" }
|
||||
rustc_data_structures = { path = "../rustc_data_structures" }
|
||||
rustc_errors = { path = "../rustc_errors" }
|
||||
rustc_fluent_macro = { path = "../rustc_fluent_macro" }
|
||||
|
|
|
|||
|
|
@ -20,7 +20,6 @@ use errors::{
|
|||
};
|
||||
use rustc_ast::MacroDef;
|
||||
use rustc_ast::visit::{VisitorResult, try_visit};
|
||||
use rustc_attr_parsing::AttributeKind;
|
||||
use rustc_data_structures::fx::FxHashSet;
|
||||
use rustc_data_structures::intern::Interned;
|
||||
use rustc_errors::{MultiSpan, listify};
|
||||
|
|
@ -40,7 +39,7 @@ use rustc_session::lint;
|
|||
use rustc_span::hygiene::Transparency;
|
||||
use rustc_span::{Ident, Span, Symbol, sym};
|
||||
use tracing::debug;
|
||||
use {rustc_attr_parsing as attr, rustc_hir as hir};
|
||||
use {rustc_attr_data_structures as attrs, rustc_hir as hir};
|
||||
|
||||
rustc_fluent_macro::fluent_messages! { "../messages.ftl" }
|
||||
|
||||
|
|
@ -497,7 +496,7 @@ impl<'tcx> EmbargoVisitor<'tcx> {
|
|||
let hir_id = self.tcx.local_def_id_to_hir_id(local_def_id);
|
||||
let attrs = self.tcx.hir_attrs(hir_id);
|
||||
|
||||
if attr::find_attr!(attrs, AttributeKind::MacroTransparency(x) => *x)
|
||||
if attrs::find_attr!(attrs, attrs::AttributeKind::MacroTransparency(x) => *x)
|
||||
.unwrap_or(Transparency::fallback(md.macro_rules))
|
||||
!= Transparency::Opaque
|
||||
{
|
||||
|
|
|
|||
|
|
@ -1433,6 +1433,8 @@ fn panic_on_forbidden_read<D: Deps>(data: &DepGraphData<D>, dep_node_index: DepN
|
|||
&& let Some(nodes) = &data.current.nodes_in_current_session
|
||||
{
|
||||
// Try to find it among the nodes allocated so far in this session
|
||||
// This is OK, there's only ever one node result possible so this is deterministic.
|
||||
#[allow(rustc::potential_query_instability)]
|
||||
if let Some((node, _)) = nodes.lock().iter().find(|&(_, index)| *index == dep_node_index) {
|
||||
dep_node = Some(*node);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -784,6 +784,8 @@ impl<D: Deps> EncoderState<D> {
|
|||
) {
|
||||
if let Some(record_stats) = &self.stats {
|
||||
let record_stats = record_stats.lock();
|
||||
// `stats` is sorted below so we can allow this lint here.
|
||||
#[allow(rustc::potential_query_instability)]
|
||||
let mut stats: Vec<_> = record_stats.values().collect();
|
||||
stats.sort_by_key(|s| -(s.node_counter as i64));
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
// tidy-alphabetical-start
|
||||
#![allow(rustc::potential_query_instability, internal_features)]
|
||||
#![allow(internal_features)]
|
||||
#![feature(assert_matches)]
|
||||
#![feature(core_intrinsics)]
|
||||
#![feature(dropck_eyepatch)]
|
||||
|
|
|
|||
|
|
@ -510,6 +510,10 @@ pub fn break_query_cycles<I: Clone + Debug>(
|
|||
registry: &rayon_core::Registry,
|
||||
) {
|
||||
let mut wakelist = Vec::new();
|
||||
// It is OK per the comments:
|
||||
// - https://github.com/rust-lang/rust/pull/131200#issuecomment-2798854932
|
||||
// - https://github.com/rust-lang/rust/pull/131200#issuecomment-2798866392
|
||||
#[allow(rustc::potential_query_instability)]
|
||||
let mut jobs: Vec<QueryJobId> = query_map.keys().cloned().collect();
|
||||
|
||||
let mut found_cycle = false;
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ use std::sync::Arc;
|
|||
use rustc_ast::expand::StrippedCfgItem;
|
||||
use rustc_ast::{self as ast, Crate, NodeId, attr};
|
||||
use rustc_ast_pretty::pprust;
|
||||
use rustc_attr_parsing::StabilityLevel;
|
||||
use rustc_attr_data_structures::StabilityLevel;
|
||||
use rustc_data_structures::intern::Interned;
|
||||
use rustc_errors::{Applicability, DiagCtxtHandle, StashKey};
|
||||
use rustc_expand::base::{
|
||||
|
|
|
|||
|
|
@ -195,6 +195,11 @@ pub struct CoverageOptions {
|
|||
/// regression tests for #133606, because we don't have an easy way to
|
||||
/// reproduce it from actual source code.
|
||||
pub discard_all_spans_in_codegen: bool,
|
||||
|
||||
/// `-Zcoverage-options=inject-unused-local-file`: During codegen, add an
|
||||
/// extra dummy entry to each function's local file table, to exercise the
|
||||
/// code that checks for local file IDs with no mapping regions.
|
||||
pub inject_unused_local_file: bool,
|
||||
}
|
||||
|
||||
/// Controls whether branch coverage or MC/DC coverage is enabled.
|
||||
|
|
|
|||
|
|
@ -82,9 +82,7 @@ fn current_dll_path() -> Result<PathBuf, String> {
|
|||
let fname_ptr = info.dli_fname.as_ptr();
|
||||
#[cfg(not(target_os = "cygwin"))]
|
||||
let fname_ptr = {
|
||||
if info.dli_fname.is_null() {
|
||||
return Err("dladdr returned null pointer".into());
|
||||
}
|
||||
assert!(!info.dli_fname.is_null(), "dli_fname cannot be null");
|
||||
info.dli_fname
|
||||
};
|
||||
let bytes = CStr::from_ptr(fname_ptr).to_bytes();
|
||||
|
|
|
|||
|
|
@ -1413,6 +1413,7 @@ pub mod parse {
|
|||
"mcdc" => slot.level = CoverageLevel::Mcdc,
|
||||
"no-mir-spans" => slot.no_mir_spans = true,
|
||||
"discard-all-spans-in-codegen" => slot.discard_all_spans_in_codegen = true,
|
||||
"inject-unused-local-file" => slot.inject_unused_local_file = true,
|
||||
_ => return false,
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -371,6 +371,11 @@ impl Session {
|
|||
self.opts.unstable_opts.coverage_options.discard_all_spans_in_codegen
|
||||
}
|
||||
|
||||
/// True if testing flag `-Zcoverage-options=inject-unused-local-file` was passed.
|
||||
pub fn coverage_inject_unused_local_file(&self) -> bool {
|
||||
self.opts.unstable_opts.coverage_options.inject_unused_local_file
|
||||
}
|
||||
|
||||
pub fn is_sanitizer_cfi_enabled(&self) -> bool {
|
||||
self.opts.unstable_opts.sanitizer.contains(SanitizerSet::CFI)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@
|
|||
#![stable(feature = "rust1", since = "1.0.0")]
|
||||
|
||||
use crate::convert::FloatToInt;
|
||||
use crate::num::{FpCategory, libm};
|
||||
use crate::num::FpCategory;
|
||||
use crate::panic::const_assert;
|
||||
use crate::{cfg_match, intrinsics, mem};
|
||||
|
||||
|
|
@ -1557,413 +1557,441 @@ impl f32 {
|
|||
}
|
||||
}
|
||||
|
||||
/// Experimental version of `floor` in `core`. See [`f32::floor`] for details.
|
||||
/// Experimental implementations of floating point functions in `core`.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// #![feature(core_float_math)]
|
||||
///
|
||||
/// use core::f32;
|
||||
///
|
||||
/// let f = 3.7_f32;
|
||||
/// let g = 3.0_f32;
|
||||
/// let h = -3.7_f32;
|
||||
///
|
||||
/// assert_eq!(f32::floor(f), 3.0);
|
||||
/// assert_eq!(f32::floor(g), 3.0);
|
||||
/// assert_eq!(f32::floor(h), -4.0);
|
||||
/// ```
|
||||
///
|
||||
/// _This standalone function is for testing only. It will be stabilized as an inherent method._
|
||||
///
|
||||
/// [`f32::floor`]: ../../std/primitive.f32.html#method.floor
|
||||
#[inline]
|
||||
/// _The standalone functions in this module are for testing only.
|
||||
/// They will be stabilized as inherent methods._
|
||||
#[unstable(feature = "core_float_math", issue = "137578")]
|
||||
#[must_use = "method returns a new number and does not mutate the original value"]
|
||||
pub fn floor(x: f32) -> f32 {
|
||||
// SAFETY: intrinsic with no preconditions
|
||||
unsafe { intrinsics::floorf32(x) }
|
||||
}
|
||||
pub mod math {
|
||||
use crate::intrinsics;
|
||||
use crate::num::libm;
|
||||
|
||||
/// Experimental version of `ceil` in `core`. See [`f32::ceil`] for details.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// #![feature(core_float_math)]
|
||||
///
|
||||
/// use core::f32;
|
||||
///
|
||||
/// let f = 3.01_f32;
|
||||
/// let g = 4.0_f32;
|
||||
///
|
||||
/// assert_eq!(f32::ceil(f), 4.0);
|
||||
/// assert_eq!(f32::ceil(g), 4.0);
|
||||
/// ```
|
||||
///
|
||||
/// _This standalone function is for testing only. It will be stabilized as an inherent method._
|
||||
///
|
||||
/// [`f32::ceil`]: ../../std/primitive.f32.html#method.ceil
|
||||
#[inline]
|
||||
#[doc(alias = "ceiling")]
|
||||
#[must_use = "method returns a new number and does not mutate the original value"]
|
||||
#[unstable(feature = "core_float_math", issue = "137578")]
|
||||
pub fn ceil(x: f32) -> f32 {
|
||||
// SAFETY: intrinsic with no preconditions
|
||||
unsafe { intrinsics::ceilf32(x) }
|
||||
}
|
||||
|
||||
/// Experimental version of `round` in `core`. See [`f32::round`] for details.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// #![feature(core_float_math)]
|
||||
///
|
||||
/// use core::f32;
|
||||
///
|
||||
/// let f = 3.3_f32;
|
||||
/// let g = -3.3_f32;
|
||||
/// let h = -3.7_f32;
|
||||
/// let i = 3.5_f32;
|
||||
/// let j = 4.5_f32;
|
||||
///
|
||||
/// assert_eq!(f32::round(f), 3.0);
|
||||
/// assert_eq!(f32::round(g), -3.0);
|
||||
/// assert_eq!(f32::round(h), -4.0);
|
||||
/// assert_eq!(f32::round(i), 4.0);
|
||||
/// assert_eq!(f32::round(j), 5.0);
|
||||
/// ```
|
||||
///
|
||||
/// _This standalone function is for testing only. It will be stabilized as an inherent method._
|
||||
///
|
||||
/// [`f32::round`]: ../../std/primitive.f32.html#method.round
|
||||
#[inline]
|
||||
#[unstable(feature = "core_float_math", issue = "137578")]
|
||||
#[must_use = "method returns a new number and does not mutate the original value"]
|
||||
pub fn round(x: f32) -> f32 {
|
||||
// SAFETY: intrinsic with no preconditions
|
||||
unsafe { intrinsics::roundf32(x) }
|
||||
}
|
||||
|
||||
/// Experimental version of `round_ties_even` in `core`. See [`f32::round_ties_even`] for details.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// #![feature(core_float_math)]
|
||||
///
|
||||
/// use core::f32;
|
||||
///
|
||||
/// let f = 3.3_f32;
|
||||
/// let g = -3.3_f32;
|
||||
/// let h = 3.5_f32;
|
||||
/// let i = 4.5_f32;
|
||||
///
|
||||
/// assert_eq!(f32::round_ties_even(f), 3.0);
|
||||
/// assert_eq!(f32::round_ties_even(g), -3.0);
|
||||
/// assert_eq!(f32::round_ties_even(h), 4.0);
|
||||
/// assert_eq!(f32::round_ties_even(i), 4.0);
|
||||
/// ```
|
||||
///
|
||||
/// _This standalone function is for testing only. It will be stabilized as an inherent method._
|
||||
///
|
||||
/// [`f32::round_ties_even`]: ../../std/primitive.f32.html#method.round_ties_even
|
||||
#[inline]
|
||||
#[unstable(feature = "core_float_math", issue = "137578")]
|
||||
#[must_use = "method returns a new number and does not mutate the original value"]
|
||||
pub fn round_ties_even(x: f32) -> f32 {
|
||||
intrinsics::round_ties_even_f32(x)
|
||||
}
|
||||
|
||||
/// Experimental version of `trunc` in `core`. See [`f32::trunc`] for details.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// #![feature(core_float_math)]
|
||||
///
|
||||
/// use core::f32;
|
||||
///
|
||||
/// let f = 3.7_f32;
|
||||
/// let g = 3.0_f32;
|
||||
/// let h = -3.7_f32;
|
||||
///
|
||||
/// assert_eq!(f32::trunc(f), 3.0);
|
||||
/// assert_eq!(f32::trunc(g), 3.0);
|
||||
/// assert_eq!(f32::trunc(h), -3.0);
|
||||
/// ```
|
||||
///
|
||||
/// _This standalone function is for testing only. It will be stabilized as an inherent method._
|
||||
///
|
||||
/// [`f32::trunc`]: ../../std/primitive.f32.html#method.trunc
|
||||
#[inline]
|
||||
#[doc(alias = "truncate")]
|
||||
#[must_use = "method returns a new number and does not mutate the original value"]
|
||||
#[unstable(feature = "core_float_math", issue = "137578")]
|
||||
pub fn trunc(x: f32) -> f32 {
|
||||
// SAFETY: intrinsic with no preconditions
|
||||
unsafe { intrinsics::truncf32(x) }
|
||||
}
|
||||
|
||||
/// Experimental version of `fract` in `core`. See [`f32::fract`] for details.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// #![feature(core_float_math)]
|
||||
///
|
||||
/// use core::f32;
|
||||
///
|
||||
/// let x = 3.6_f32;
|
||||
/// let y = -3.6_f32;
|
||||
/// let abs_difference_x = (f32::fract(x) - 0.6).abs();
|
||||
/// let abs_difference_y = (f32::fract(y) - (-0.6)).abs();
|
||||
///
|
||||
/// assert!(abs_difference_x <= f32::EPSILON);
|
||||
/// assert!(abs_difference_y <= f32::EPSILON);
|
||||
/// ```
|
||||
///
|
||||
/// _This standalone function is for testing only. It will be stabilized as an inherent method._
|
||||
///
|
||||
/// [`f32::fract`]: ../../std/primitive.f32.html#method.fract
|
||||
#[inline]
|
||||
#[unstable(feature = "core_float_math", issue = "137578")]
|
||||
#[must_use = "method returns a new number and does not mutate the original value"]
|
||||
pub fn fract(x: f32) -> f32 {
|
||||
x - trunc(x)
|
||||
}
|
||||
|
||||
/// Experimental version of `mul_add` in `core`. See [`f32::mul_add`] for details.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// #![feature(core_float_math)]
|
||||
///
|
||||
/// # // FIXME(#140515): mingw has an incorrect fma https://sourceforge.net/p/mingw-w64/bugs/848/
|
||||
/// # #[cfg(all(target_os = "windows", target_env = "gnu", not(target_abi = "llvm")))] {
|
||||
/// use core::f32;
|
||||
///
|
||||
/// let m = 10.0_f32;
|
||||
/// let x = 4.0_f32;
|
||||
/// let b = 60.0_f32;
|
||||
///
|
||||
/// assert_eq!(f32::mul_add(m, x, b), 100.0);
|
||||
/// assert_eq!(m * x + b, 100.0);
|
||||
///
|
||||
/// let one_plus_eps = 1.0_f32 + f32::EPSILON;
|
||||
/// let one_minus_eps = 1.0_f32 - f32::EPSILON;
|
||||
/// let minus_one = -1.0_f32;
|
||||
///
|
||||
/// // The exact result (1 + eps) * (1 - eps) = 1 - eps * eps.
|
||||
/// assert_eq!(f32::mul_add(one_plus_eps, one_minus_eps, minus_one), -f32::EPSILON * f32::EPSILON);
|
||||
/// // Different rounding with the non-fused multiply and add.
|
||||
/// assert_eq!(one_plus_eps * one_minus_eps + minus_one, 0.0);
|
||||
/// # }
|
||||
/// ```
|
||||
///
|
||||
/// _This standalone function is for testing only. It will be stabilized as an inherent method._
|
||||
///
|
||||
/// [`f32::mul_add`]: ../../std/primitive.f32.html#method.mul_add
|
||||
#[inline]
|
||||
#[doc(alias = "fmaf", alias = "fusedMultiplyAdd")]
|
||||
#[must_use = "method returns a new number and does not mutate the original value"]
|
||||
#[unstable(feature = "core_float_math", issue = "137578")]
|
||||
pub fn mul_add(x: f32, y: f32, z: f32) -> f32 {
|
||||
// SAFETY: intrinsic with no preconditions
|
||||
unsafe { intrinsics::fmaf32(x, y, z) }
|
||||
}
|
||||
|
||||
/// Experimental version of `div_euclid` in `core`. See [`f32::div_euclid`] for details.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// #![feature(core_float_math)]
|
||||
///
|
||||
/// use core::f32;
|
||||
///
|
||||
/// let a: f32 = 7.0;
|
||||
/// let b = 4.0;
|
||||
/// assert_eq!(f32::div_euclid(a, b), 1.0); // 7.0 > 4.0 * 1.0
|
||||
/// assert_eq!(f32::div_euclid(-a, b), -2.0); // -7.0 >= 4.0 * -2.0
|
||||
/// assert_eq!(f32::div_euclid(a, -b), -1.0); // 7.0 >= -4.0 * -1.0
|
||||
/// assert_eq!(f32::div_euclid(-a, -b), 2.0); // -7.0 >= -4.0 * 2.0
|
||||
/// ```
|
||||
///
|
||||
/// _This standalone function is for testing only. It will be stabilized as an inherent method._
|
||||
///
|
||||
/// [`f32::div_euclid`]: ../../std/primitive.f32.html#method.div_euclid
|
||||
#[inline]
|
||||
#[unstable(feature = "core_float_math", issue = "137578")]
|
||||
#[must_use = "method returns a new number and does not mutate the original value"]
|
||||
pub fn div_euclid(x: f32, rhs: f32) -> f32 {
|
||||
let q = trunc(x / rhs);
|
||||
if x % rhs < 0.0 {
|
||||
return if rhs > 0.0 { q - 1.0 } else { q + 1.0 };
|
||||
/// Experimental version of `floor` in `core`. See [`f32::floor`] for details.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// #![feature(core_float_math)]
|
||||
///
|
||||
/// use core::f32;
|
||||
///
|
||||
/// let f = 3.7_f32;
|
||||
/// let g = 3.0_f32;
|
||||
/// let h = -3.7_f32;
|
||||
///
|
||||
/// assert_eq!(f32::math::floor(f), 3.0);
|
||||
/// assert_eq!(f32::math::floor(g), 3.0);
|
||||
/// assert_eq!(f32::math::floor(h), -4.0);
|
||||
/// ```
|
||||
///
|
||||
/// _This standalone function is for testing only.
|
||||
/// It will be stabilized as an inherent method._
|
||||
///
|
||||
/// [`f32::floor`]: ../../../std/primitive.f32.html#method.floor
|
||||
#[inline]
|
||||
#[unstable(feature = "core_float_math", issue = "137578")]
|
||||
#[must_use = "method returns a new number and does not mutate the original value"]
|
||||
pub fn floor(x: f32) -> f32 {
|
||||
// SAFETY: intrinsic with no preconditions
|
||||
unsafe { intrinsics::floorf32(x) }
|
||||
}
|
||||
q
|
||||
}
|
||||
|
||||
/// Experimental version of `rem_euclid` in `core`. See [`f32::rem_euclid`] for details.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// #![feature(core_float_math)]
|
||||
///
|
||||
/// use core::f32;
|
||||
///
|
||||
/// let a: f32 = 7.0;
|
||||
/// let b = 4.0;
|
||||
/// assert_eq!(f32::rem_euclid(a, b), 3.0);
|
||||
/// assert_eq!(f32::rem_euclid(-a, b), 1.0);
|
||||
/// assert_eq!(f32::rem_euclid(a, -b), 3.0);
|
||||
/// assert_eq!(f32::rem_euclid(-a, -b), 1.0);
|
||||
/// // limitation due to round-off error
|
||||
/// assert!(f32::rem_euclid(-f32::EPSILON, 3.0) != 0.0);
|
||||
/// ```
|
||||
///
|
||||
/// _This standalone function is for testing only. It will be stabilized as an inherent method._
|
||||
///
|
||||
/// [`f32::rem_euclid`]: ../../std/primitive.f32.html#method.rem_euclid
|
||||
#[inline]
|
||||
#[doc(alias = "modulo", alias = "mod")]
|
||||
#[unstable(feature = "core_float_math", issue = "137578")]
|
||||
#[must_use = "method returns a new number and does not mutate the original value"]
|
||||
pub fn rem_euclid(x: f32, rhs: f32) -> f32 {
|
||||
let r = x % rhs;
|
||||
if r < 0.0 { r + rhs.abs() } else { r }
|
||||
}
|
||||
/// Experimental version of `ceil` in `core`. See [`f32::ceil`] for details.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// #![feature(core_float_math)]
|
||||
///
|
||||
/// use core::f32;
|
||||
///
|
||||
/// let f = 3.01_f32;
|
||||
/// let g = 4.0_f32;
|
||||
///
|
||||
/// assert_eq!(f32::math::ceil(f), 4.0);
|
||||
/// assert_eq!(f32::math::ceil(g), 4.0);
|
||||
/// ```
|
||||
///
|
||||
/// _This standalone function is for testing only.
|
||||
/// It will be stabilized as an inherent method._
|
||||
///
|
||||
/// [`f32::ceil`]: ../../../std/primitive.f32.html#method.ceil
|
||||
#[inline]
|
||||
#[doc(alias = "ceiling")]
|
||||
#[must_use = "method returns a new number and does not mutate the original value"]
|
||||
#[unstable(feature = "core_float_math", issue = "137578")]
|
||||
pub fn ceil(x: f32) -> f32 {
|
||||
// SAFETY: intrinsic with no preconditions
|
||||
unsafe { intrinsics::ceilf32(x) }
|
||||
}
|
||||
|
||||
/// Experimental version of `powi` in `core`. See [`f32::powi`] for details.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// #![feature(core_float_math)]
|
||||
///
|
||||
/// use core::f32;
|
||||
///
|
||||
/// let x = 2.0_f32;
|
||||
/// let abs_difference = (f32::powi(x, 2) - (x * x)).abs();
|
||||
/// assert!(abs_difference <= f32::EPSILON);
|
||||
///
|
||||
/// assert_eq!(f32::powi(f32::NAN, 0), 1.0);
|
||||
/// ```
|
||||
///
|
||||
/// _This standalone function is for testing only. It will be stabilized as an inherent method._
|
||||
///
|
||||
/// [`f32::powi`]: ../../std/primitive.f32.html#method.powi
|
||||
#[inline]
|
||||
#[must_use = "method returns a new number and does not mutate the original value"]
|
||||
#[unstable(feature = "core_float_math", issue = "137578")]
|
||||
pub fn powi(x: f32, n: i32) -> f32 {
|
||||
// SAFETY: intrinsic with no preconditions
|
||||
unsafe { intrinsics::powif32(x, n) }
|
||||
}
|
||||
/// Experimental version of `round` in `core`. See [`f32::round`] for details.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// #![feature(core_float_math)]
|
||||
///
|
||||
/// use core::f32;
|
||||
///
|
||||
/// let f = 3.3_f32;
|
||||
/// let g = -3.3_f32;
|
||||
/// let h = -3.7_f32;
|
||||
/// let i = 3.5_f32;
|
||||
/// let j = 4.5_f32;
|
||||
///
|
||||
/// assert_eq!(f32::math::round(f), 3.0);
|
||||
/// assert_eq!(f32::math::round(g), -3.0);
|
||||
/// assert_eq!(f32::math::round(h), -4.0);
|
||||
/// assert_eq!(f32::math::round(i), 4.0);
|
||||
/// assert_eq!(f32::math::round(j), 5.0);
|
||||
/// ```
|
||||
///
|
||||
/// _This standalone function is for testing only.
|
||||
/// It will be stabilized as an inherent method._
|
||||
///
|
||||
/// [`f32::round`]: ../../../std/primitive.f32.html#method.round
|
||||
#[inline]
|
||||
#[unstable(feature = "core_float_math", issue = "137578")]
|
||||
#[must_use = "method returns a new number and does not mutate the original value"]
|
||||
pub fn round(x: f32) -> f32 {
|
||||
// SAFETY: intrinsic with no preconditions
|
||||
unsafe { intrinsics::roundf32(x) }
|
||||
}
|
||||
|
||||
/// Experimental version of `sqrt` in `core`. See [`f32::sqrt`] for details.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// #![feature(core_float_math)]
|
||||
///
|
||||
/// use core::f32;
|
||||
///
|
||||
/// let positive = 4.0_f32;
|
||||
/// let negative = -4.0_f32;
|
||||
/// let negative_zero = -0.0_f32;
|
||||
///
|
||||
/// assert_eq!(f32::sqrt(positive), 2.0);
|
||||
/// assert!(f32::sqrt(negative).is_nan());
|
||||
/// assert_eq!(f32::sqrt(negative_zero), negative_zero);
|
||||
/// ```
|
||||
///
|
||||
/// _This standalone function is for testing only. It will be stabilized as an inherent method._
|
||||
///
|
||||
/// [`f32::sqrt`]: ../../std/primitive.f32.html#method.sqrt
|
||||
#[inline]
|
||||
#[doc(alias = "squareRoot")]
|
||||
#[unstable(feature = "core_float_math", issue = "137578")]
|
||||
#[must_use = "method returns a new number and does not mutate the original value"]
|
||||
pub fn sqrt(x: f32) -> f32 {
|
||||
// SAFETY: intrinsic with no preconditions
|
||||
unsafe { intrinsics::sqrtf32(x) }
|
||||
}
|
||||
/// Experimental version of `round_ties_even` in `core`. See [`f32::round_ties_even`] for
|
||||
/// details.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// #![feature(core_float_math)]
|
||||
///
|
||||
/// use core::f32;
|
||||
///
|
||||
/// let f = 3.3_f32;
|
||||
/// let g = -3.3_f32;
|
||||
/// let h = 3.5_f32;
|
||||
/// let i = 4.5_f32;
|
||||
///
|
||||
/// assert_eq!(f32::math::round_ties_even(f), 3.0);
|
||||
/// assert_eq!(f32::math::round_ties_even(g), -3.0);
|
||||
/// assert_eq!(f32::math::round_ties_even(h), 4.0);
|
||||
/// assert_eq!(f32::math::round_ties_even(i), 4.0);
|
||||
/// ```
|
||||
///
|
||||
/// _This standalone function is for testing only.
|
||||
/// It will be stabilized as an inherent method._
|
||||
///
|
||||
/// [`f32::round_ties_even`]: ../../../std/primitive.f32.html#method.round_ties_even
|
||||
#[inline]
|
||||
#[unstable(feature = "core_float_math", issue = "137578")]
|
||||
#[must_use = "method returns a new number and does not mutate the original value"]
|
||||
pub fn round_ties_even(x: f32) -> f32 {
|
||||
intrinsics::round_ties_even_f32(x)
|
||||
}
|
||||
|
||||
/// Experimental version of `abs_sub` in `core`. See [`f32::abs_sub`] for details.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// #![feature(core_float_math)]
|
||||
///
|
||||
/// use core::f32;
|
||||
///
|
||||
/// let x = 3.0f32;
|
||||
/// let y = -3.0f32;
|
||||
///
|
||||
/// let abs_difference_x = (f32::abs_sub(x, 1.0) - 2.0).abs();
|
||||
/// let abs_difference_y = (f32::abs_sub(y, 1.0) - 0.0).abs();
|
||||
///
|
||||
/// assert!(abs_difference_x <= f32::EPSILON);
|
||||
/// assert!(abs_difference_y <= f32::EPSILON);
|
||||
/// ```
|
||||
///
|
||||
/// _This standalone function is for testing only. It will be stabilized as an inherent method._
|
||||
///
|
||||
/// [`f32::abs_sub`]: ../../std/primitive.f32.html#method.abs_sub
|
||||
#[inline]
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
#[deprecated(
|
||||
since = "1.10.0",
|
||||
note = "you probably meant `(self - other).abs()`: \
|
||||
/// Experimental version of `trunc` in `core`. See [`f32::trunc`] for details.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// #![feature(core_float_math)]
|
||||
///
|
||||
/// use core::f32;
|
||||
///
|
||||
/// let f = 3.7_f32;
|
||||
/// let g = 3.0_f32;
|
||||
/// let h = -3.7_f32;
|
||||
///
|
||||
/// assert_eq!(f32::math::trunc(f), 3.0);
|
||||
/// assert_eq!(f32::math::trunc(g), 3.0);
|
||||
/// assert_eq!(f32::math::trunc(h), -3.0);
|
||||
/// ```
|
||||
///
|
||||
/// _This standalone function is for testing only.
|
||||
/// It will be stabilized as an inherent method._
|
||||
///
|
||||
/// [`f32::trunc`]: ../../../std/primitive.f32.html#method.trunc
|
||||
#[inline]
|
||||
#[doc(alias = "truncate")]
|
||||
#[must_use = "method returns a new number and does not mutate the original value"]
|
||||
#[unstable(feature = "core_float_math", issue = "137578")]
|
||||
pub fn trunc(x: f32) -> f32 {
|
||||
// SAFETY: intrinsic with no preconditions
|
||||
unsafe { intrinsics::truncf32(x) }
|
||||
}
|
||||
|
||||
/// Experimental version of `fract` in `core`. See [`f32::fract`] for details.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// #![feature(core_float_math)]
|
||||
///
|
||||
/// use core::f32;
|
||||
///
|
||||
/// let x = 3.6_f32;
|
||||
/// let y = -3.6_f32;
|
||||
/// let abs_difference_x = (f32::math::fract(x) - 0.6).abs();
|
||||
/// let abs_difference_y = (f32::math::fract(y) - (-0.6)).abs();
|
||||
///
|
||||
/// assert!(abs_difference_x <= f32::EPSILON);
|
||||
/// assert!(abs_difference_y <= f32::EPSILON);
|
||||
/// ```
|
||||
///
|
||||
/// _This standalone function is for testing only.
|
||||
/// It will be stabilized as an inherent method._
|
||||
///
|
||||
/// [`f32::fract`]: ../../../std/primitive.f32.html#method.fract
|
||||
#[inline]
|
||||
#[unstable(feature = "core_float_math", issue = "137578")]
|
||||
#[must_use = "method returns a new number and does not mutate the original value"]
|
||||
pub fn fract(x: f32) -> f32 {
|
||||
x - trunc(x)
|
||||
}
|
||||
|
||||
/// Experimental version of `mul_add` in `core`. See [`f32::mul_add`] for details.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// #![feature(core_float_math)]
|
||||
///
|
||||
/// # // FIXME(#140515): mingw has an incorrect fma
|
||||
/// # // https://sourceforge.net/p/mingw-w64/bugs/848/
|
||||
/// # #[cfg(all(target_os = "windows", target_env = "gnu", not(target_abi = "llvm")))] {
|
||||
/// use core::f32;
|
||||
///
|
||||
/// let m = 10.0_f32;
|
||||
/// let x = 4.0_f32;
|
||||
/// let b = 60.0_f32;
|
||||
///
|
||||
/// assert_eq!(f32::math::mul_add(m, x, b), 100.0);
|
||||
/// assert_eq!(m * x + b, 100.0);
|
||||
///
|
||||
/// let one_plus_eps = 1.0_f32 + f32::EPSILON;
|
||||
/// let one_minus_eps = 1.0_f32 - f32::EPSILON;
|
||||
/// let minus_one = -1.0_f32;
|
||||
///
|
||||
/// // The exact result (1 + eps) * (1 - eps) = 1 - eps * eps.
|
||||
/// assert_eq!(
|
||||
/// f32::math::mul_add(one_plus_eps, one_minus_eps, minus_one),
|
||||
/// -f32::EPSILON * f32::EPSILON
|
||||
/// );
|
||||
/// // Different rounding with the non-fused multiply and add.
|
||||
/// assert_eq!(one_plus_eps * one_minus_eps + minus_one, 0.0);
|
||||
/// # }
|
||||
/// ```
|
||||
///
|
||||
/// _This standalone function is for testing only.
|
||||
/// It will be stabilized as an inherent method._
|
||||
///
|
||||
/// [`f32::mul_add`]: ../../../std/primitive.f32.html#method.mul_add
|
||||
#[inline]
|
||||
#[doc(alias = "fmaf", alias = "fusedMultiplyAdd")]
|
||||
#[must_use = "method returns a new number and does not mutate the original value"]
|
||||
#[unstable(feature = "core_float_math", issue = "137578")]
|
||||
pub fn mul_add(x: f32, y: f32, z: f32) -> f32 {
|
||||
// SAFETY: intrinsic with no preconditions
|
||||
unsafe { intrinsics::fmaf32(x, y, z) }
|
||||
}
|
||||
|
||||
/// Experimental version of `div_euclid` in `core`. See [`f32::div_euclid`] for details.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// #![feature(core_float_math)]
|
||||
///
|
||||
/// use core::f32;
|
||||
///
|
||||
/// let a: f32 = 7.0;
|
||||
/// let b = 4.0;
|
||||
/// assert_eq!(f32::math::div_euclid(a, b), 1.0); // 7.0 > 4.0 * 1.0
|
||||
/// assert_eq!(f32::math::div_euclid(-a, b), -2.0); // -7.0 >= 4.0 * -2.0
|
||||
/// assert_eq!(f32::math::div_euclid(a, -b), -1.0); // 7.0 >= -4.0 * -1.0
|
||||
/// assert_eq!(f32::math::div_euclid(-a, -b), 2.0); // -7.0 >= -4.0 * 2.0
|
||||
/// ```
|
||||
///
|
||||
/// _This standalone function is for testing only.
|
||||
/// It will be stabilized as an inherent method._
|
||||
///
|
||||
/// [`f32::div_euclid`]: ../../../std/primitive.f32.html#method.div_euclid
|
||||
#[inline]
|
||||
#[unstable(feature = "core_float_math", issue = "137578")]
|
||||
#[must_use = "method returns a new number and does not mutate the original value"]
|
||||
pub fn div_euclid(x: f32, rhs: f32) -> f32 {
|
||||
let q = trunc(x / rhs);
|
||||
if x % rhs < 0.0 {
|
||||
return if rhs > 0.0 { q - 1.0 } else { q + 1.0 };
|
||||
}
|
||||
q
|
||||
}
|
||||
|
||||
/// Experimental version of `rem_euclid` in `core`. See [`f32::rem_euclid`] for details.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// #![feature(core_float_math)]
|
||||
///
|
||||
/// use core::f32;
|
||||
///
|
||||
/// let a: f32 = 7.0;
|
||||
/// let b = 4.0;
|
||||
/// assert_eq!(f32::math::rem_euclid(a, b), 3.0);
|
||||
/// assert_eq!(f32::math::rem_euclid(-a, b), 1.0);
|
||||
/// assert_eq!(f32::math::rem_euclid(a, -b), 3.0);
|
||||
/// assert_eq!(f32::math::rem_euclid(-a, -b), 1.0);
|
||||
/// // limitation due to round-off error
|
||||
/// assert!(f32::math::rem_euclid(-f32::EPSILON, 3.0) != 0.0);
|
||||
/// ```
|
||||
///
|
||||
/// _This standalone function is for testing only.
|
||||
/// It will be stabilized as an inherent method._
|
||||
///
|
||||
/// [`f32::rem_euclid`]: ../../../std/primitive.f32.html#method.rem_euclid
|
||||
#[inline]
|
||||
#[doc(alias = "modulo", alias = "mod")]
|
||||
#[unstable(feature = "core_float_math", issue = "137578")]
|
||||
#[must_use = "method returns a new number and does not mutate the original value"]
|
||||
pub fn rem_euclid(x: f32, rhs: f32) -> f32 {
|
||||
let r = x % rhs;
|
||||
if r < 0.0 { r + rhs.abs() } else { r }
|
||||
}
|
||||
|
||||
/// Experimental version of `powi` in `core`. See [`f32::powi`] for details.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// #![feature(core_float_math)]
|
||||
///
|
||||
/// use core::f32;
|
||||
///
|
||||
/// let x = 2.0_f32;
|
||||
/// let abs_difference = (f32::math::powi(x, 2) - (x * x)).abs();
|
||||
/// assert!(abs_difference <= f32::EPSILON);
|
||||
///
|
||||
/// assert_eq!(f32::math::powi(f32::NAN, 0), 1.0);
|
||||
/// ```
|
||||
///
|
||||
/// _This standalone function is for testing only.
|
||||
/// It will be stabilized as an inherent method._
|
||||
///
|
||||
/// [`f32::powi`]: ../../../std/primitive.f32.html#method.powi
|
||||
#[inline]
|
||||
#[must_use = "method returns a new number and does not mutate the original value"]
|
||||
#[unstable(feature = "core_float_math", issue = "137578")]
|
||||
pub fn powi(x: f32, n: i32) -> f32 {
|
||||
// SAFETY: intrinsic with no preconditions
|
||||
unsafe { intrinsics::powif32(x, n) }
|
||||
}
|
||||
|
||||
/// Experimental version of `sqrt` in `core`. See [`f32::sqrt`] for details.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// #![feature(core_float_math)]
|
||||
///
|
||||
/// use core::f32;
|
||||
///
|
||||
/// let positive = 4.0_f32;
|
||||
/// let negative = -4.0_f32;
|
||||
/// let negative_zero = -0.0_f32;
|
||||
///
|
||||
/// assert_eq!(f32::math::sqrt(positive), 2.0);
|
||||
/// assert!(f32::math::sqrt(negative).is_nan());
|
||||
/// assert_eq!(f32::math::sqrt(negative_zero), negative_zero);
|
||||
/// ```
|
||||
///
|
||||
/// _This standalone function is for testing only.
|
||||
/// It will be stabilized as an inherent method._
|
||||
///
|
||||
/// [`f32::sqrt`]: ../../../std/primitive.f32.html#method.sqrt
|
||||
#[inline]
|
||||
#[doc(alias = "squareRoot")]
|
||||
#[unstable(feature = "core_float_math", issue = "137578")]
|
||||
#[must_use = "method returns a new number and does not mutate the original value"]
|
||||
pub fn sqrt(x: f32) -> f32 {
|
||||
// SAFETY: intrinsic with no preconditions
|
||||
unsafe { intrinsics::sqrtf32(x) }
|
||||
}
|
||||
|
||||
/// Experimental version of `abs_sub` in `core`. See [`f32::abs_sub`] for details.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// #![feature(core_float_math)]
|
||||
///
|
||||
/// use core::f32;
|
||||
///
|
||||
/// let x = 3.0f32;
|
||||
/// let y = -3.0f32;
|
||||
///
|
||||
/// let abs_difference_x = (f32::math::abs_sub(x, 1.0) - 2.0).abs();
|
||||
/// let abs_difference_y = (f32::math::abs_sub(y, 1.0) - 0.0).abs();
|
||||
///
|
||||
/// assert!(abs_difference_x <= f32::EPSILON);
|
||||
/// assert!(abs_difference_y <= f32::EPSILON);
|
||||
/// ```
|
||||
///
|
||||
/// _This standalone function is for testing only.
|
||||
/// It will be stabilized as an inherent method._
|
||||
///
|
||||
/// [`f32::abs_sub`]: ../../../std/primitive.f32.html#method.abs_sub
|
||||
#[inline]
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
#[deprecated(
|
||||
since = "1.10.0",
|
||||
note = "you probably meant `(self - other).abs()`: \
|
||||
this operation is `(self - other).max(0.0)` \
|
||||
except that `abs_sub` also propagates NaNs (also \
|
||||
known as `fdimf` in C). If you truly need the positive \
|
||||
difference, consider using that expression or the C function \
|
||||
`fdimf`, depending on how you wish to handle NaN (please consider \
|
||||
filing an issue describing your use-case too)."
|
||||
)]
|
||||
#[must_use = "method returns a new number and does not mutate the original value"]
|
||||
pub fn abs_sub(x: f32, other: f32) -> f32 {
|
||||
libm::fdimf(x, other)
|
||||
}
|
||||
)]
|
||||
#[must_use = "method returns a new number and does not mutate the original value"]
|
||||
pub fn abs_sub(x: f32, other: f32) -> f32 {
|
||||
libm::fdimf(x, other)
|
||||
}
|
||||
|
||||
/// Experimental version of `cbrt` in `core`. See [`f32::cbrt`] for details.
|
||||
///
|
||||
/// # Unspecified precision
|
||||
///
|
||||
/// The precision of this function is non-deterministic. This means it varies by platform, Rust version, and
|
||||
/// can even differ within the same execution from one invocation to the next.
|
||||
/// This function currently corresponds to the `cbrtf` from libc on Unix
|
||||
/// and Windows. Note that this might change in the future.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// #![feature(core_float_math)]
|
||||
///
|
||||
/// use core::f32;
|
||||
///
|
||||
/// let x = 8.0f32;
|
||||
///
|
||||
/// // x^(1/3) - 2 == 0
|
||||
/// let abs_difference = (f32::cbrt(x) - 2.0).abs();
|
||||
///
|
||||
/// assert!(abs_difference <= f32::EPSILON);
|
||||
/// ```
|
||||
///
|
||||
/// _This standalone function is for testing only. It will be stabilized as an inherent method._
|
||||
///
|
||||
/// [`f32::cbrt`]: ../../std/primitive.f32.html#method.cbrt
|
||||
#[inline]
|
||||
#[must_use = "method returns a new number and does not mutate the original value"]
|
||||
#[unstable(feature = "core_float_math", issue = "137578")]
|
||||
pub fn cbrt(x: f32) -> f32 {
|
||||
libm::cbrtf(x)
|
||||
/// Experimental version of `cbrt` in `core`. See [`f32::cbrt`] for details.
|
||||
///
|
||||
/// # Unspecified precision
|
||||
///
|
||||
/// The precision of this function is non-deterministic. This means it varies by platform, Rust version, and
|
||||
/// can even differ within the same execution from one invocation to the next.
|
||||
/// This function currently corresponds to the `cbrtf` from libc on Unix
|
||||
/// and Windows. Note that this might change in the future.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// #![feature(core_float_math)]
|
||||
///
|
||||
/// use core::f32;
|
||||
///
|
||||
/// let x = 8.0f32;
|
||||
///
|
||||
/// // x^(1/3) - 2 == 0
|
||||
/// let abs_difference = (f32::math::cbrt(x) - 2.0).abs();
|
||||
///
|
||||
/// assert!(abs_difference <= f32::EPSILON);
|
||||
/// ```
|
||||
///
|
||||
/// _This standalone function is for testing only.
|
||||
/// It will be stabilized as an inherent method._
|
||||
///
|
||||
/// [`f32::cbrt`]: ../../../std/primitive.f32.html#method.cbrt
|
||||
#[inline]
|
||||
#[must_use = "method returns a new number and does not mutate the original value"]
|
||||
#[unstable(feature = "core_float_math", issue = "137578")]
|
||||
pub fn cbrt(x: f32) -> f32 {
|
||||
libm::cbrtf(x)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@
|
|||
#![stable(feature = "rust1", since = "1.0.0")]
|
||||
|
||||
use crate::convert::FloatToInt;
|
||||
use crate::num::{FpCategory, libm};
|
||||
use crate::num::FpCategory;
|
||||
use crate::panic::const_assert;
|
||||
use crate::{intrinsics, mem};
|
||||
|
||||
|
|
@ -1556,406 +1556,434 @@ impl f64 {
|
|||
}
|
||||
}
|
||||
|
||||
/// Experimental version of `floor` in `core`. See [`f64::floor`] for details.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// #![feature(core_float_math)]
|
||||
///
|
||||
/// use core::f64;
|
||||
///
|
||||
/// let f = 3.7_f64;
|
||||
/// let g = 3.0_f64;
|
||||
/// let h = -3.7_f64;
|
||||
///
|
||||
/// assert_eq!(f64::floor(f), 3.0);
|
||||
/// assert_eq!(f64::floor(g), 3.0);
|
||||
/// assert_eq!(f64::floor(h), -4.0);
|
||||
/// ```
|
||||
///
|
||||
/// _This standalone function is for testing only. It will be stabilized as an inherent method._
|
||||
///
|
||||
/// [`f64::floor`]: ../../std/primitive.f64.html#method.floor
|
||||
#[inline]
|
||||
#[unstable(feature = "core_float_math", issue = "137578")]
|
||||
#[must_use = "method returns a new number and does not mutate the original value"]
|
||||
pub fn floor(x: f64) -> f64 {
|
||||
// SAFETY: intrinsic with no preconditions
|
||||
unsafe { intrinsics::floorf64(x) }
|
||||
}
|
||||
/// Experimental implementations of floating point functions in `core`.
|
||||
///
|
||||
/// _The standalone functions in this module are for testing only.
|
||||
/// They will be stabilized as inherent methods._
|
||||
pub mod math {
|
||||
use crate::intrinsics;
|
||||
use crate::num::libm;
|
||||
|
||||
/// Experimental version of `ceil` in `core`. See [`f64::ceil`] for details.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// #![feature(core_float_math)]
|
||||
///
|
||||
/// use core::f64;
|
||||
///
|
||||
/// let f = 3.01_f64;
|
||||
/// let g = 4.0_f64;
|
||||
///
|
||||
/// assert_eq!(f64::ceil(f), 4.0);
|
||||
/// assert_eq!(f64::ceil(g), 4.0);
|
||||
/// ```
|
||||
///
|
||||
/// _This standalone function is for testing only. It will be stabilized as an inherent method._
|
||||
///
|
||||
/// [`f64::ceil`]: ../../std/primitive.f64.html#method.ceil
|
||||
#[inline]
|
||||
#[doc(alias = "ceiling")]
|
||||
#[unstable(feature = "core_float_math", issue = "137578")]
|
||||
#[must_use = "method returns a new number and does not mutate the original value"]
|
||||
pub fn ceil(x: f64) -> f64 {
|
||||
// SAFETY: intrinsic with no preconditions
|
||||
unsafe { intrinsics::ceilf64(x) }
|
||||
}
|
||||
|
||||
/// Experimental version of `round` in `core`. See [`f64::round`] for details.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// #![feature(core_float_math)]
|
||||
///
|
||||
/// use core::f64;
|
||||
///
|
||||
/// let f = 3.3_f64;
|
||||
/// let g = -3.3_f64;
|
||||
/// let h = -3.7_f64;
|
||||
/// let i = 3.5_f64;
|
||||
/// let j = 4.5_f64;
|
||||
///
|
||||
/// assert_eq!(f64::round(f), 3.0);
|
||||
/// assert_eq!(f64::round(g), -3.0);
|
||||
/// assert_eq!(f64::round(h), -4.0);
|
||||
/// assert_eq!(f64::round(i), 4.0);
|
||||
/// assert_eq!(f64::round(j), 5.0);
|
||||
/// ```
|
||||
///
|
||||
/// _This standalone function is for testing only. It will be stabilized as an inherent method._
|
||||
///
|
||||
/// [`f64::round`]: ../../std/primitive.f64.html#method.round
|
||||
#[inline]
|
||||
#[unstable(feature = "core_float_math", issue = "137578")]
|
||||
#[must_use = "method returns a new number and does not mutate the original value"]
|
||||
pub fn round(x: f64) -> f64 {
|
||||
// SAFETY: intrinsic with no preconditions
|
||||
unsafe { intrinsics::roundf64(x) }
|
||||
}
|
||||
|
||||
/// Experimental version of `round_ties_even` in `core`. See [`f64::round_ties_even`] for details.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// #![feature(core_float_math)]
|
||||
///
|
||||
/// use core::f64;
|
||||
///
|
||||
/// let f = 3.3_f64;
|
||||
/// let g = -3.3_f64;
|
||||
/// let h = 3.5_f64;
|
||||
/// let i = 4.5_f64;
|
||||
///
|
||||
/// assert_eq!(f64::round_ties_even(f), 3.0);
|
||||
/// assert_eq!(f64::round_ties_even(g), -3.0);
|
||||
/// assert_eq!(f64::round_ties_even(h), 4.0);
|
||||
/// assert_eq!(f64::round_ties_even(i), 4.0);
|
||||
/// ```
|
||||
///
|
||||
/// _This standalone function is for testing only. It will be stabilized as an inherent method._
|
||||
///
|
||||
/// [`f64::round_ties_even`]: ../../std/primitive.f64.html#method.round_ties_even
|
||||
#[inline]
|
||||
#[unstable(feature = "core_float_math", issue = "137578")]
|
||||
#[must_use = "method returns a new number and does not mutate the original value"]
|
||||
pub fn round_ties_even(x: f64) -> f64 {
|
||||
intrinsics::round_ties_even_f64(x)
|
||||
}
|
||||
|
||||
/// Experimental version of `trunc` in `core`. See [`f64::trunc`] for details.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// #![feature(core_float_math)]
|
||||
///
|
||||
/// use core::f64;
|
||||
///
|
||||
/// let f = 3.7_f64;
|
||||
/// let g = 3.0_f64;
|
||||
/// let h = -3.7_f64;
|
||||
///
|
||||
/// assert_eq!(f64::trunc(f), 3.0);
|
||||
/// assert_eq!(f64::trunc(g), 3.0);
|
||||
/// assert_eq!(f64::trunc(h), -3.0);
|
||||
/// ```
|
||||
///
|
||||
/// _This standalone function is for testing only. It will be stabilized as an inherent method._
|
||||
///
|
||||
/// [`f64::trunc`]: ../../std/primitive.f64.html#method.trunc
|
||||
#[inline]
|
||||
#[doc(alias = "truncate")]
|
||||
#[unstable(feature = "core_float_math", issue = "137578")]
|
||||
#[must_use = "method returns a new number and does not mutate the original value"]
|
||||
pub fn trunc(x: f64) -> f64 {
|
||||
// SAFETY: intrinsic with no preconditions
|
||||
unsafe { intrinsics::truncf64(x) }
|
||||
}
|
||||
|
||||
/// Experimental version of `fract` in `core`. See [`f64::fract`] for details.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// #![feature(core_float_math)]
|
||||
///
|
||||
/// use core::f64;
|
||||
///
|
||||
/// let x = 3.6_f64;
|
||||
/// let y = -3.6_f64;
|
||||
/// let abs_difference_x = (f64::fract(x) - 0.6).abs();
|
||||
/// let abs_difference_y = (f64::fract(y) - (-0.6)).abs();
|
||||
///
|
||||
/// assert!(abs_difference_x < 1e-10);
|
||||
/// assert!(abs_difference_y < 1e-10);
|
||||
/// ```
|
||||
///
|
||||
/// _This standalone function is for testing only. It will be stabilized as an inherent method._
|
||||
///
|
||||
/// [`f64::fract`]: ../../std/primitive.f64.html#method.fract
|
||||
#[inline]
|
||||
#[unstable(feature = "core_float_math", issue = "137578")]
|
||||
#[must_use = "method returns a new number and does not mutate the original value"]
|
||||
pub fn fract(x: f64) -> f64 {
|
||||
x - trunc(x)
|
||||
}
|
||||
|
||||
/// Experimental version of `mul_add` in `core`. See [`f64::mul_add`] for details.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// #![feature(core_float_math)]
|
||||
///
|
||||
/// # // FIXME(#140515): mingw has an incorrect fma https://sourceforge.net/p/mingw-w64/bugs/848/
|
||||
/// # #[cfg(all(target_os = "windows", target_env = "gnu", not(target_abi = "llvm")))] {
|
||||
/// use core::f64;
|
||||
///
|
||||
/// let m = 10.0_f64;
|
||||
/// let x = 4.0_f64;
|
||||
/// let b = 60.0_f64;
|
||||
///
|
||||
/// assert_eq!(f64::mul_add(m, x, b), 100.0);
|
||||
/// assert_eq!(m * x + b, 100.0);
|
||||
///
|
||||
/// let one_plus_eps = 1.0_f64 + f64::EPSILON;
|
||||
/// let one_minus_eps = 1.0_f64 - f64::EPSILON;
|
||||
/// let minus_one = -1.0_f64;
|
||||
///
|
||||
/// // The exact result (1 + eps) * (1 - eps) = 1 - eps * eps.
|
||||
/// assert_eq!(f64::mul_add(one_plus_eps, one_minus_eps, minus_one), -f64::EPSILON * f64::EPSILON);
|
||||
/// // Different rounding with the non-fused multiply and add.
|
||||
/// assert_eq!(one_plus_eps * one_minus_eps + minus_one, 0.0);
|
||||
/// # }
|
||||
/// ```
|
||||
///
|
||||
/// _This standalone function is for testing only. It will be stabilized as an inherent method._
|
||||
///
|
||||
/// [`f64::mul_add`]: ../../std/primitive.f64.html#method.mul_add
|
||||
#[inline]
|
||||
#[doc(alias = "fma", alias = "fusedMultiplyAdd")]
|
||||
#[unstable(feature = "core_float_math", issue = "137578")]
|
||||
#[must_use = "method returns a new number and does not mutate the original value"]
|
||||
pub fn mul_add(x: f64, a: f64, b: f64) -> f64 {
|
||||
// SAFETY: intrinsic with no preconditions
|
||||
unsafe { intrinsics::fmaf64(x, a, b) }
|
||||
}
|
||||
|
||||
/// Experimental version of `div_euclid` in `core`. See [`f64::div_euclid`] for details.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// #![feature(core_float_math)]
|
||||
///
|
||||
/// use core::f64;
|
||||
///
|
||||
/// let a: f64 = 7.0;
|
||||
/// let b = 4.0;
|
||||
/// assert_eq!(f64::div_euclid(a, b), 1.0); // 7.0 > 4.0 * 1.0
|
||||
/// assert_eq!(f64::div_euclid(-a, b), -2.0); // -7.0 >= 4.0 * -2.0
|
||||
/// assert_eq!(f64::div_euclid(a, -b), -1.0); // 7.0 >= -4.0 * -1.0
|
||||
/// assert_eq!(f64::div_euclid(-a, -b), 2.0); // -7.0 >= -4.0 * 2.0
|
||||
/// ```
|
||||
///
|
||||
/// _This standalone function is for testing only. It will be stabilized as an inherent method._
|
||||
///
|
||||
/// [`f64::div_euclid`]: ../../std/primitive.f64.html#method.div_euclid
|
||||
#[inline]
|
||||
#[unstable(feature = "core_float_math", issue = "137578")]
|
||||
#[must_use = "method returns a new number and does not mutate the original value"]
|
||||
pub fn div_euclid(x: f64, rhs: f64) -> f64 {
|
||||
let q = trunc(x / rhs);
|
||||
if x % rhs < 0.0 {
|
||||
return if rhs > 0.0 { q - 1.0 } else { q + 1.0 };
|
||||
/// Experimental version of `floor` in `core`. See [`f64::floor`] for details.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// #![feature(core_float_math)]
|
||||
///
|
||||
/// use core::f64;
|
||||
///
|
||||
/// let f = 3.7_f64;
|
||||
/// let g = 3.0_f64;
|
||||
/// let h = -3.7_f64;
|
||||
///
|
||||
/// assert_eq!(f64::math::floor(f), 3.0);
|
||||
/// assert_eq!(f64::math::floor(g), 3.0);
|
||||
/// assert_eq!(f64::math::floor(h), -4.0);
|
||||
/// ```
|
||||
///
|
||||
/// _This standalone function is for testing only.
|
||||
/// It will be stabilized as an inherent method._
|
||||
///
|
||||
/// [`f64::floor`]: ../../../std/primitive.f64.html#method.floor
|
||||
#[inline]
|
||||
#[unstable(feature = "core_float_math", issue = "137578")]
|
||||
#[must_use = "method returns a new number and does not mutate the original value"]
|
||||
pub fn floor(x: f64) -> f64 {
|
||||
// SAFETY: intrinsic with no preconditions
|
||||
unsafe { intrinsics::floorf64(x) }
|
||||
}
|
||||
q
|
||||
}
|
||||
|
||||
/// Experimental version of `rem_euclid` in `core`. See [`f64::rem_euclid`] for details.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// #![feature(core_float_math)]
|
||||
///
|
||||
/// use core::f64;
|
||||
///
|
||||
/// let a: f64 = 7.0;
|
||||
/// let b = 4.0;
|
||||
/// assert_eq!(f64::rem_euclid(a, b), 3.0);
|
||||
/// assert_eq!(f64::rem_euclid(-a, b), 1.0);
|
||||
/// assert_eq!(f64::rem_euclid(a, -b), 3.0);
|
||||
/// assert_eq!(f64::rem_euclid(-a, -b), 1.0);
|
||||
/// // limitation due to round-off error
|
||||
/// assert!(f64::rem_euclid(-f64::EPSILON, 3.0) != 0.0);
|
||||
/// ```
|
||||
///
|
||||
/// _This standalone function is for testing only. It will be stabilized as an inherent method._
|
||||
///
|
||||
/// [`f64::rem_euclid`]: ../../std/primitive.f64.html#method.rem_euclid
|
||||
#[inline]
|
||||
#[doc(alias = "modulo", alias = "mod")]
|
||||
#[unstable(feature = "core_float_math", issue = "137578")]
|
||||
#[must_use = "method returns a new number and does not mutate the original value"]
|
||||
pub fn rem_euclid(x: f64, rhs: f64) -> f64 {
|
||||
let r = x % rhs;
|
||||
if r < 0.0 { r + rhs.abs() } else { r }
|
||||
}
|
||||
/// Experimental version of `ceil` in `core`. See [`f64::ceil`] for details.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// #![feature(core_float_math)]
|
||||
///
|
||||
/// use core::f64;
|
||||
///
|
||||
/// let f = 3.01_f64;
|
||||
/// let g = 4.0_f64;
|
||||
///
|
||||
/// assert_eq!(f64::math::ceil(f), 4.0);
|
||||
/// assert_eq!(f64::math::ceil(g), 4.0);
|
||||
/// ```
|
||||
///
|
||||
/// _This standalone function is for testing only.
|
||||
/// It will be stabilized as an inherent method._
|
||||
///
|
||||
/// [`f64::ceil`]: ../../../std/primitive.f64.html#method.ceil
|
||||
#[inline]
|
||||
#[doc(alias = "ceiling")]
|
||||
#[unstable(feature = "core_float_math", issue = "137578")]
|
||||
#[must_use = "method returns a new number and does not mutate the original value"]
|
||||
pub fn ceil(x: f64) -> f64 {
|
||||
// SAFETY: intrinsic with no preconditions
|
||||
unsafe { intrinsics::ceilf64(x) }
|
||||
}
|
||||
|
||||
/// Experimental version of `powi` in `core`. See [`f64::powi`] for details.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// #![feature(core_float_math)]
|
||||
///
|
||||
/// use core::f64;
|
||||
///
|
||||
/// let x = 2.0_f64;
|
||||
/// let abs_difference = (f64::powi(x, 2) - (x * x)).abs();
|
||||
/// assert!(abs_difference <= f64::EPSILON);
|
||||
///
|
||||
/// assert_eq!(f64::powi(f64::NAN, 0), 1.0);
|
||||
/// ```
|
||||
///
|
||||
/// _This standalone function is for testing only. It will be stabilized as an inherent method._
|
||||
///
|
||||
/// [`f64::powi`]: ../../std/primitive.f64.html#method.powi
|
||||
#[inline]
|
||||
#[unstable(feature = "core_float_math", issue = "137578")]
|
||||
#[must_use = "method returns a new number and does not mutate the original value"]
|
||||
pub fn powi(x: f64, n: i32) -> f64 {
|
||||
// SAFETY: intrinsic with no preconditions
|
||||
unsafe { intrinsics::powif64(x, n) }
|
||||
}
|
||||
/// Experimental version of `round` in `core`. See [`f64::round`] for details.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// #![feature(core_float_math)]
|
||||
///
|
||||
/// use core::f64;
|
||||
///
|
||||
/// let f = 3.3_f64;
|
||||
/// let g = -3.3_f64;
|
||||
/// let h = -3.7_f64;
|
||||
/// let i = 3.5_f64;
|
||||
/// let j = 4.5_f64;
|
||||
///
|
||||
/// assert_eq!(f64::math::round(f), 3.0);
|
||||
/// assert_eq!(f64::math::round(g), -3.0);
|
||||
/// assert_eq!(f64::math::round(h), -4.0);
|
||||
/// assert_eq!(f64::math::round(i), 4.0);
|
||||
/// assert_eq!(f64::math::round(j), 5.0);
|
||||
/// ```
|
||||
///
|
||||
/// _This standalone function is for testing only.
|
||||
/// It will be stabilized as an inherent method._
|
||||
///
|
||||
/// [`f64::round`]: ../../../std/primitive.f64.html#method.round
|
||||
#[inline]
|
||||
#[unstable(feature = "core_float_math", issue = "137578")]
|
||||
#[must_use = "method returns a new number and does not mutate the original value"]
|
||||
pub fn round(x: f64) -> f64 {
|
||||
// SAFETY: intrinsic with no preconditions
|
||||
unsafe { intrinsics::roundf64(x) }
|
||||
}
|
||||
|
||||
/// Experimental version of `sqrt` in `core`. See [`f64::sqrt`] for details.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// #![feature(core_float_math)]
|
||||
///
|
||||
/// use core::f64;
|
||||
///
|
||||
/// let positive = 4.0_f64;
|
||||
/// let negative = -4.0_f64;
|
||||
/// let negative_zero = -0.0_f64;
|
||||
///
|
||||
/// assert_eq!(f64::sqrt(positive), 2.0);
|
||||
/// assert!(f64::sqrt(negative).is_nan());
|
||||
/// assert_eq!(f64::sqrt(negative_zero), negative_zero);
|
||||
/// ```
|
||||
///
|
||||
/// _This standalone function is for testing only. It will be stabilized as an inherent method._
|
||||
///
|
||||
/// [`f64::sqrt`]: ../../std/primitive.f64.html#method.sqrt
|
||||
#[inline]
|
||||
#[doc(alias = "squareRoot")]
|
||||
#[unstable(feature = "core_float_math", issue = "137578")]
|
||||
#[must_use = "method returns a new number and does not mutate the original value"]
|
||||
pub fn sqrt(x: f64) -> f64 {
|
||||
// SAFETY: intrinsic with no preconditions
|
||||
unsafe { intrinsics::sqrtf64(x) }
|
||||
}
|
||||
/// Experimental version of `round_ties_even` in `core`. See [`f64::round_ties_even`] for
|
||||
/// details.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// #![feature(core_float_math)]
|
||||
///
|
||||
/// use core::f64;
|
||||
///
|
||||
/// let f = 3.3_f64;
|
||||
/// let g = -3.3_f64;
|
||||
/// let h = 3.5_f64;
|
||||
/// let i = 4.5_f64;
|
||||
///
|
||||
/// assert_eq!(f64::math::round_ties_even(f), 3.0);
|
||||
/// assert_eq!(f64::math::round_ties_even(g), -3.0);
|
||||
/// assert_eq!(f64::math::round_ties_even(h), 4.0);
|
||||
/// assert_eq!(f64::math::round_ties_even(i), 4.0);
|
||||
/// ```
|
||||
///
|
||||
/// _This standalone function is for testing only.
|
||||
/// It will be stabilized as an inherent method._
|
||||
///
|
||||
/// [`f64::round_ties_even`]: ../../../std/primitive.f64.html#method.round_ties_even
|
||||
#[inline]
|
||||
#[unstable(feature = "core_float_math", issue = "137578")]
|
||||
#[must_use = "method returns a new number and does not mutate the original value"]
|
||||
pub fn round_ties_even(x: f64) -> f64 {
|
||||
intrinsics::round_ties_even_f64(x)
|
||||
}
|
||||
|
||||
/// Experimental version of `abs_sub` in `core`. See [`f64::abs_sub`] for details.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// #![feature(core_float_math)]
|
||||
///
|
||||
/// use core::f64;
|
||||
///
|
||||
/// let x = 3.0_f64;
|
||||
/// let y = -3.0_f64;
|
||||
///
|
||||
/// let abs_difference_x = (f64::abs_sub(x, 1.0) - 2.0).abs();
|
||||
/// let abs_difference_y = (f64::abs_sub(y, 1.0) - 0.0).abs();
|
||||
///
|
||||
/// assert!(abs_difference_x < 1e-10);
|
||||
/// assert!(abs_difference_y < 1e-10);
|
||||
/// ```
|
||||
///
|
||||
/// _This standalone function is for testing only. It will be stabilized as an inherent method._
|
||||
///
|
||||
/// [`f64::abs_sub`]: ../../std/primitive.f64.html#method.abs_sub
|
||||
#[inline]
|
||||
#[unstable(feature = "core_float_math", issue = "137578")]
|
||||
#[deprecated(
|
||||
since = "1.10.0",
|
||||
note = "you probably meant `(self - other).abs()`: \
|
||||
/// Experimental version of `trunc` in `core`. See [`f64::trunc`] for details.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// #![feature(core_float_math)]
|
||||
///
|
||||
/// use core::f64;
|
||||
///
|
||||
/// let f = 3.7_f64;
|
||||
/// let g = 3.0_f64;
|
||||
/// let h = -3.7_f64;
|
||||
///
|
||||
/// assert_eq!(f64::math::trunc(f), 3.0);
|
||||
/// assert_eq!(f64::math::trunc(g), 3.0);
|
||||
/// assert_eq!(f64::math::trunc(h), -3.0);
|
||||
/// ```
|
||||
///
|
||||
/// _This standalone function is for testing only.
|
||||
/// It will be stabilized as an inherent method._
|
||||
///
|
||||
/// [`f64::trunc`]: ../../../std/primitive.f64.html#method.trunc
|
||||
#[inline]
|
||||
#[doc(alias = "truncate")]
|
||||
#[unstable(feature = "core_float_math", issue = "137578")]
|
||||
#[must_use = "method returns a new number and does not mutate the original value"]
|
||||
pub fn trunc(x: f64) -> f64 {
|
||||
// SAFETY: intrinsic with no preconditions
|
||||
unsafe { intrinsics::truncf64(x) }
|
||||
}
|
||||
|
||||
/// Experimental version of `fract` in `core`. See [`f64::fract`] for details.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// #![feature(core_float_math)]
|
||||
///
|
||||
/// use core::f64;
|
||||
///
|
||||
/// let x = 3.6_f64;
|
||||
/// let y = -3.6_f64;
|
||||
/// let abs_difference_x = (f64::math::fract(x) - 0.6).abs();
|
||||
/// let abs_difference_y = (f64::math::fract(y) - (-0.6)).abs();
|
||||
///
|
||||
/// assert!(abs_difference_x < 1e-10);
|
||||
/// assert!(abs_difference_y < 1e-10);
|
||||
/// ```
|
||||
///
|
||||
/// _This standalone function is for testing only.
|
||||
/// It will be stabilized as an inherent method._
|
||||
///
|
||||
/// [`f64::fract`]: ../../../std/primitive.f64.html#method.fract
|
||||
#[inline]
|
||||
#[unstable(feature = "core_float_math", issue = "137578")]
|
||||
#[must_use = "method returns a new number and does not mutate the original value"]
|
||||
pub fn fract(x: f64) -> f64 {
|
||||
x - trunc(x)
|
||||
}
|
||||
|
||||
/// Experimental version of `mul_add` in `core`. See [`f64::mul_add`] for details.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// #![feature(core_float_math)]
|
||||
///
|
||||
/// # // FIXME(#140515): mingw has an incorrect fma
|
||||
/// # // https://sourceforge.net/p/mingw-w64/bugs/848/
|
||||
/// # #[cfg(all(target_os = "windows", target_env = "gnu", not(target_abi = "llvm")))] {
|
||||
/// use core::f64;
|
||||
///
|
||||
/// let m = 10.0_f64;
|
||||
/// let x = 4.0_f64;
|
||||
/// let b = 60.0_f64;
|
||||
///
|
||||
/// assert_eq!(f64::math::mul_add(m, x, b), 100.0);
|
||||
/// assert_eq!(m * x + b, 100.0);
|
||||
///
|
||||
/// let one_plus_eps = 1.0_f64 + f64::EPSILON;
|
||||
/// let one_minus_eps = 1.0_f64 - f64::EPSILON;
|
||||
/// let minus_one = -1.0_f64;
|
||||
///
|
||||
/// // The exact result (1 + eps) * (1 - eps) = 1 - eps * eps.
|
||||
/// assert_eq!(
|
||||
/// f64::math::mul_add(one_plus_eps, one_minus_eps, minus_one),
|
||||
/// -f64::EPSILON * f64::EPSILON
|
||||
/// );
|
||||
/// // Different rounding with the non-fused multiply and add.
|
||||
/// assert_eq!(one_plus_eps * one_minus_eps + minus_one, 0.0);
|
||||
/// # }
|
||||
/// ```
|
||||
///
|
||||
/// _This standalone function is for testing only.
|
||||
/// It will be stabilized as an inherent method._
|
||||
///
|
||||
/// [`f64::mul_add`]: ../../../std/primitive.f64.html#method.mul_add
|
||||
#[inline]
|
||||
#[doc(alias = "fma", alias = "fusedMultiplyAdd")]
|
||||
#[unstable(feature = "core_float_math", issue = "137578")]
|
||||
#[must_use = "method returns a new number and does not mutate the original value"]
|
||||
pub fn mul_add(x: f64, a: f64, b: f64) -> f64 {
|
||||
// SAFETY: intrinsic with no preconditions
|
||||
unsafe { intrinsics::fmaf64(x, a, b) }
|
||||
}
|
||||
|
||||
/// Experimental version of `div_euclid` in `core`. See [`f64::div_euclid`] for details.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// #![feature(core_float_math)]
|
||||
///
|
||||
/// use core::f64;
|
||||
///
|
||||
/// let a: f64 = 7.0;
|
||||
/// let b = 4.0;
|
||||
/// assert_eq!(f64::math::div_euclid(a, b), 1.0); // 7.0 > 4.0 * 1.0
|
||||
/// assert_eq!(f64::math::div_euclid(-a, b), -2.0); // -7.0 >= 4.0 * -2.0
|
||||
/// assert_eq!(f64::math::div_euclid(a, -b), -1.0); // 7.0 >= -4.0 * -1.0
|
||||
/// assert_eq!(f64::math::div_euclid(-a, -b), 2.0); // -7.0 >= -4.0 * 2.0
|
||||
/// ```
|
||||
///
|
||||
/// _This standalone function is for testing only.
|
||||
/// It will be stabilized as an inherent method._
|
||||
///
|
||||
/// [`f64::div_euclid`]: ../../../std/primitive.f64.html#method.div_euclid
|
||||
#[inline]
|
||||
#[unstable(feature = "core_float_math", issue = "137578")]
|
||||
#[must_use = "method returns a new number and does not mutate the original value"]
|
||||
pub fn div_euclid(x: f64, rhs: f64) -> f64 {
|
||||
let q = trunc(x / rhs);
|
||||
if x % rhs < 0.0 {
|
||||
return if rhs > 0.0 { q - 1.0 } else { q + 1.0 };
|
||||
}
|
||||
q
|
||||
}
|
||||
|
||||
/// Experimental version of `rem_euclid` in `core`. See [`f64::rem_euclid`] for details.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// #![feature(core_float_math)]
|
||||
///
|
||||
/// use core::f64;
|
||||
///
|
||||
/// let a: f64 = 7.0;
|
||||
/// let b = 4.0;
|
||||
/// assert_eq!(f64::math::rem_euclid(a, b), 3.0);
|
||||
/// assert_eq!(f64::math::rem_euclid(-a, b), 1.0);
|
||||
/// assert_eq!(f64::math::rem_euclid(a, -b), 3.0);
|
||||
/// assert_eq!(f64::math::rem_euclid(-a, -b), 1.0);
|
||||
/// // limitation due to round-off error
|
||||
/// assert!(f64::math::rem_euclid(-f64::EPSILON, 3.0) != 0.0);
|
||||
/// ```
|
||||
///
|
||||
/// _This standalone function is for testing only.
|
||||
/// It will be stabilized as an inherent method._
|
||||
///
|
||||
/// [`f64::rem_euclid`]: ../../../std/primitive.f64.html#method.rem_euclid
|
||||
#[inline]
|
||||
#[doc(alias = "modulo", alias = "mod")]
|
||||
#[unstable(feature = "core_float_math", issue = "137578")]
|
||||
#[must_use = "method returns a new number and does not mutate the original value"]
|
||||
pub fn rem_euclid(x: f64, rhs: f64) -> f64 {
|
||||
let r = x % rhs;
|
||||
if r < 0.0 { r + rhs.abs() } else { r }
|
||||
}
|
||||
|
||||
/// Experimental version of `powi` in `core`. See [`f64::powi`] for details.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// #![feature(core_float_math)]
|
||||
///
|
||||
/// use core::f64;
|
||||
///
|
||||
/// let x = 2.0_f64;
|
||||
/// let abs_difference = (f64::math::powi(x, 2) - (x * x)).abs();
|
||||
/// assert!(abs_difference <= f64::EPSILON);
|
||||
///
|
||||
/// assert_eq!(f64::math::powi(f64::NAN, 0), 1.0);
|
||||
/// ```
|
||||
///
|
||||
/// _This standalone function is for testing only.
|
||||
/// It will be stabilized as an inherent method._
|
||||
///
|
||||
/// [`f64::powi`]: ../../../std/primitive.f64.html#method.powi
|
||||
#[inline]
|
||||
#[unstable(feature = "core_float_math", issue = "137578")]
|
||||
#[must_use = "method returns a new number and does not mutate the original value"]
|
||||
pub fn powi(x: f64, n: i32) -> f64 {
|
||||
// SAFETY: intrinsic with no preconditions
|
||||
unsafe { intrinsics::powif64(x, n) }
|
||||
}
|
||||
|
||||
/// Experimental version of `sqrt` in `core`. See [`f64::sqrt`] for details.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// #![feature(core_float_math)]
|
||||
///
|
||||
/// use core::f64;
|
||||
///
|
||||
/// let positive = 4.0_f64;
|
||||
/// let negative = -4.0_f64;
|
||||
/// let negative_zero = -0.0_f64;
|
||||
///
|
||||
/// assert_eq!(f64::math::sqrt(positive), 2.0);
|
||||
/// assert!(f64::math::sqrt(negative).is_nan());
|
||||
/// assert_eq!(f64::math::sqrt(negative_zero), negative_zero);
|
||||
/// ```
|
||||
///
|
||||
/// _This standalone function is for testing only.
|
||||
/// It will be stabilized as an inherent method._
|
||||
///
|
||||
/// [`f64::sqrt`]: ../../../std/primitive.f64.html#method.sqrt
|
||||
#[inline]
|
||||
#[doc(alias = "squareRoot")]
|
||||
#[unstable(feature = "core_float_math", issue = "137578")]
|
||||
#[must_use = "method returns a new number and does not mutate the original value"]
|
||||
pub fn sqrt(x: f64) -> f64 {
|
||||
// SAFETY: intrinsic with no preconditions
|
||||
unsafe { intrinsics::sqrtf64(x) }
|
||||
}
|
||||
|
||||
/// Experimental version of `abs_sub` in `core`. See [`f64::abs_sub`] for details.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// #![feature(core_float_math)]
|
||||
///
|
||||
/// use core::f64;
|
||||
///
|
||||
/// let x = 3.0_f64;
|
||||
/// let y = -3.0_f64;
|
||||
///
|
||||
/// let abs_difference_x = (f64::math::abs_sub(x, 1.0) - 2.0).abs();
|
||||
/// let abs_difference_y = (f64::math::abs_sub(y, 1.0) - 0.0).abs();
|
||||
///
|
||||
/// assert!(abs_difference_x < 1e-10);
|
||||
/// assert!(abs_difference_y < 1e-10);
|
||||
/// ```
|
||||
///
|
||||
/// _This standalone function is for testing only.
|
||||
/// It will be stabilized as an inherent method._
|
||||
///
|
||||
/// [`f64::abs_sub`]: ../../../std/primitive.f64.html#method.abs_sub
|
||||
#[inline]
|
||||
#[unstable(feature = "core_float_math", issue = "137578")]
|
||||
#[deprecated(
|
||||
since = "1.10.0",
|
||||
note = "you probably meant `(self - other).abs()`: \
|
||||
this operation is `(self - other).max(0.0)` \
|
||||
except that `abs_sub` also propagates NaNs (also \
|
||||
known as `fdim` in C). If you truly need the positive \
|
||||
difference, consider using that expression or the C function \
|
||||
`fdim`, depending on how you wish to handle NaN (please consider \
|
||||
filing an issue describing your use-case too)."
|
||||
)]
|
||||
#[must_use = "method returns a new number and does not mutate the original value"]
|
||||
pub fn abs_sub(x: f64, other: f64) -> f64 {
|
||||
libm::fdim(x, other)
|
||||
}
|
||||
)]
|
||||
#[must_use = "method returns a new number and does not mutate the original value"]
|
||||
pub fn abs_sub(x: f64, other: f64) -> f64 {
|
||||
libm::fdim(x, other)
|
||||
}
|
||||
|
||||
/// Experimental version of `cbrt` in `core`. See [`f64::cbrt`] for details.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// #![feature(core_float_math)]
|
||||
///
|
||||
/// use core::f64;
|
||||
///
|
||||
/// let x = 8.0_f64;
|
||||
///
|
||||
/// // x^(1/3) - 2 == 0
|
||||
/// let abs_difference = (f64::cbrt(x) - 2.0).abs();
|
||||
///
|
||||
/// assert!(abs_difference < 1e-10);
|
||||
/// ```
|
||||
///
|
||||
/// _This standalone function is for testing only. It will be stabilized as an inherent method._
|
||||
///
|
||||
/// [`f64::cbrt`]: ../../std/primitive.f64.html#method.cbrt
|
||||
#[inline]
|
||||
#[unstable(feature = "core_float_math", issue = "137578")]
|
||||
#[must_use = "method returns a new number and does not mutate the original value"]
|
||||
pub fn cbrt(x: f64) -> f64 {
|
||||
libm::cbrt(x)
|
||||
/// Experimental version of `cbrt` in `core`. See [`f64::cbrt`] for details.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// #![feature(core_float_math)]
|
||||
///
|
||||
/// use core::f64;
|
||||
///
|
||||
/// let x = 8.0_f64;
|
||||
///
|
||||
/// // x^(1/3) - 2 == 0
|
||||
/// let abs_difference = (f64::math::cbrt(x) - 2.0).abs();
|
||||
///
|
||||
/// assert!(abs_difference < 1e-10);
|
||||
/// ```
|
||||
///
|
||||
/// _This standalone function is for testing only.
|
||||
/// It will be stabilized as an inherent method._
|
||||
///
|
||||
/// [`f64::cbrt`]: ../../../std/primitive.f64.html#method.cbrt
|
||||
#[inline]
|
||||
#[unstable(feature = "core_float_math", issue = "137578")]
|
||||
#[must_use = "method returns a new number and does not mutate the original value"]
|
||||
pub fn cbrt(x: f64) -> f64 {
|
||||
libm::cbrt(x)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4383,7 +4383,7 @@ impl<T> [T] {
|
|||
/// assert_eq!(first_three, &['a', 'b', 'c']);
|
||||
/// ```
|
||||
///
|
||||
/// Splitting off the last two elements of a slice:
|
||||
/// Splitting off a slice starting with the third element:
|
||||
///
|
||||
/// ```
|
||||
/// let mut slice: &[_] = &['a', 'b', 'c', 'd'];
|
||||
|
|
@ -4449,7 +4449,7 @@ impl<T> [T] {
|
|||
/// assert_eq!(first_three, &mut ['a', 'b', 'c']);
|
||||
/// ```
|
||||
///
|
||||
/// Taking the last two elements of a slice:
|
||||
/// Splitting off a slice starting with the third element:
|
||||
///
|
||||
/// ```
|
||||
/// let mut slice: &mut [_] = &mut ['a', 'b', 'c', 'd'];
|
||||
|
|
|
|||
|
|
@ -215,88 +215,88 @@ fn test_classify() {
|
|||
|
||||
#[test]
|
||||
fn test_floor() {
|
||||
assert_approx_eq!(f32::floor(1.0f32), 1.0f32);
|
||||
assert_approx_eq!(f32::floor(1.3f32), 1.0f32);
|
||||
assert_approx_eq!(f32::floor(1.5f32), 1.0f32);
|
||||
assert_approx_eq!(f32::floor(1.7f32), 1.0f32);
|
||||
assert_approx_eq!(f32::floor(0.0f32), 0.0f32);
|
||||
assert_approx_eq!(f32::floor(-0.0f32), -0.0f32);
|
||||
assert_approx_eq!(f32::floor(-1.0f32), -1.0f32);
|
||||
assert_approx_eq!(f32::floor(-1.3f32), -2.0f32);
|
||||
assert_approx_eq!(f32::floor(-1.5f32), -2.0f32);
|
||||
assert_approx_eq!(f32::floor(-1.7f32), -2.0f32);
|
||||
assert_approx_eq!(f32::math::floor(1.0f32), 1.0f32);
|
||||
assert_approx_eq!(f32::math::floor(1.3f32), 1.0f32);
|
||||
assert_approx_eq!(f32::math::floor(1.5f32), 1.0f32);
|
||||
assert_approx_eq!(f32::math::floor(1.7f32), 1.0f32);
|
||||
assert_approx_eq!(f32::math::floor(0.0f32), 0.0f32);
|
||||
assert_approx_eq!(f32::math::floor(-0.0f32), -0.0f32);
|
||||
assert_approx_eq!(f32::math::floor(-1.0f32), -1.0f32);
|
||||
assert_approx_eq!(f32::math::floor(-1.3f32), -2.0f32);
|
||||
assert_approx_eq!(f32::math::floor(-1.5f32), -2.0f32);
|
||||
assert_approx_eq!(f32::math::floor(-1.7f32), -2.0f32);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_ceil() {
|
||||
assert_approx_eq!(f32::ceil(1.0f32), 1.0f32);
|
||||
assert_approx_eq!(f32::ceil(1.3f32), 2.0f32);
|
||||
assert_approx_eq!(f32::ceil(1.5f32), 2.0f32);
|
||||
assert_approx_eq!(f32::ceil(1.7f32), 2.0f32);
|
||||
assert_approx_eq!(f32::ceil(0.0f32), 0.0f32);
|
||||
assert_approx_eq!(f32::ceil(-0.0f32), -0.0f32);
|
||||
assert_approx_eq!(f32::ceil(-1.0f32), -1.0f32);
|
||||
assert_approx_eq!(f32::ceil(-1.3f32), -1.0f32);
|
||||
assert_approx_eq!(f32::ceil(-1.5f32), -1.0f32);
|
||||
assert_approx_eq!(f32::ceil(-1.7f32), -1.0f32);
|
||||
assert_approx_eq!(f32::math::ceil(1.0f32), 1.0f32);
|
||||
assert_approx_eq!(f32::math::ceil(1.3f32), 2.0f32);
|
||||
assert_approx_eq!(f32::math::ceil(1.5f32), 2.0f32);
|
||||
assert_approx_eq!(f32::math::ceil(1.7f32), 2.0f32);
|
||||
assert_approx_eq!(f32::math::ceil(0.0f32), 0.0f32);
|
||||
assert_approx_eq!(f32::math::ceil(-0.0f32), -0.0f32);
|
||||
assert_approx_eq!(f32::math::ceil(-1.0f32), -1.0f32);
|
||||
assert_approx_eq!(f32::math::ceil(-1.3f32), -1.0f32);
|
||||
assert_approx_eq!(f32::math::ceil(-1.5f32), -1.0f32);
|
||||
assert_approx_eq!(f32::math::ceil(-1.7f32), -1.0f32);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_round() {
|
||||
assert_approx_eq!(f32::round(2.5f32), 3.0f32);
|
||||
assert_approx_eq!(f32::round(1.0f32), 1.0f32);
|
||||
assert_approx_eq!(f32::round(1.3f32), 1.0f32);
|
||||
assert_approx_eq!(f32::round(1.5f32), 2.0f32);
|
||||
assert_approx_eq!(f32::round(1.7f32), 2.0f32);
|
||||
assert_approx_eq!(f32::round(0.0f32), 0.0f32);
|
||||
assert_approx_eq!(f32::round(-0.0f32), -0.0f32);
|
||||
assert_approx_eq!(f32::round(-1.0f32), -1.0f32);
|
||||
assert_approx_eq!(f32::round(-1.3f32), -1.0f32);
|
||||
assert_approx_eq!(f32::round(-1.5f32), -2.0f32);
|
||||
assert_approx_eq!(f32::round(-1.7f32), -2.0f32);
|
||||
assert_approx_eq!(f32::math::round(2.5f32), 3.0f32);
|
||||
assert_approx_eq!(f32::math::round(1.0f32), 1.0f32);
|
||||
assert_approx_eq!(f32::math::round(1.3f32), 1.0f32);
|
||||
assert_approx_eq!(f32::math::round(1.5f32), 2.0f32);
|
||||
assert_approx_eq!(f32::math::round(1.7f32), 2.0f32);
|
||||
assert_approx_eq!(f32::math::round(0.0f32), 0.0f32);
|
||||
assert_approx_eq!(f32::math::round(-0.0f32), -0.0f32);
|
||||
assert_approx_eq!(f32::math::round(-1.0f32), -1.0f32);
|
||||
assert_approx_eq!(f32::math::round(-1.3f32), -1.0f32);
|
||||
assert_approx_eq!(f32::math::round(-1.5f32), -2.0f32);
|
||||
assert_approx_eq!(f32::math::round(-1.7f32), -2.0f32);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_round_ties_even() {
|
||||
assert_approx_eq!(f32::round_ties_even(2.5f32), 2.0f32);
|
||||
assert_approx_eq!(f32::round_ties_even(1.0f32), 1.0f32);
|
||||
assert_approx_eq!(f32::round_ties_even(1.3f32), 1.0f32);
|
||||
assert_approx_eq!(f32::round_ties_even(1.5f32), 2.0f32);
|
||||
assert_approx_eq!(f32::round_ties_even(1.7f32), 2.0f32);
|
||||
assert_approx_eq!(f32::round_ties_even(0.0f32), 0.0f32);
|
||||
assert_approx_eq!(f32::round_ties_even(-0.0f32), -0.0f32);
|
||||
assert_approx_eq!(f32::round_ties_even(-1.0f32), -1.0f32);
|
||||
assert_approx_eq!(f32::round_ties_even(-1.3f32), -1.0f32);
|
||||
assert_approx_eq!(f32::round_ties_even(-1.5f32), -2.0f32);
|
||||
assert_approx_eq!(f32::round_ties_even(-1.7f32), -2.0f32);
|
||||
assert_approx_eq!(f32::math::round_ties_even(2.5f32), 2.0f32);
|
||||
assert_approx_eq!(f32::math::round_ties_even(1.0f32), 1.0f32);
|
||||
assert_approx_eq!(f32::math::round_ties_even(1.3f32), 1.0f32);
|
||||
assert_approx_eq!(f32::math::round_ties_even(1.5f32), 2.0f32);
|
||||
assert_approx_eq!(f32::math::round_ties_even(1.7f32), 2.0f32);
|
||||
assert_approx_eq!(f32::math::round_ties_even(0.0f32), 0.0f32);
|
||||
assert_approx_eq!(f32::math::round_ties_even(-0.0f32), -0.0f32);
|
||||
assert_approx_eq!(f32::math::round_ties_even(-1.0f32), -1.0f32);
|
||||
assert_approx_eq!(f32::math::round_ties_even(-1.3f32), -1.0f32);
|
||||
assert_approx_eq!(f32::math::round_ties_even(-1.5f32), -2.0f32);
|
||||
assert_approx_eq!(f32::math::round_ties_even(-1.7f32), -2.0f32);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_trunc() {
|
||||
assert_approx_eq!(f32::trunc(1.0f32), 1.0f32);
|
||||
assert_approx_eq!(f32::trunc(1.3f32), 1.0f32);
|
||||
assert_approx_eq!(f32::trunc(1.5f32), 1.0f32);
|
||||
assert_approx_eq!(f32::trunc(1.7f32), 1.0f32);
|
||||
assert_approx_eq!(f32::trunc(0.0f32), 0.0f32);
|
||||
assert_approx_eq!(f32::trunc(-0.0f32), -0.0f32);
|
||||
assert_approx_eq!(f32::trunc(-1.0f32), -1.0f32);
|
||||
assert_approx_eq!(f32::trunc(-1.3f32), -1.0f32);
|
||||
assert_approx_eq!(f32::trunc(-1.5f32), -1.0f32);
|
||||
assert_approx_eq!(f32::trunc(-1.7f32), -1.0f32);
|
||||
assert_approx_eq!(f32::math::trunc(1.0f32), 1.0f32);
|
||||
assert_approx_eq!(f32::math::trunc(1.3f32), 1.0f32);
|
||||
assert_approx_eq!(f32::math::trunc(1.5f32), 1.0f32);
|
||||
assert_approx_eq!(f32::math::trunc(1.7f32), 1.0f32);
|
||||
assert_approx_eq!(f32::math::trunc(0.0f32), 0.0f32);
|
||||
assert_approx_eq!(f32::math::trunc(-0.0f32), -0.0f32);
|
||||
assert_approx_eq!(f32::math::trunc(-1.0f32), -1.0f32);
|
||||
assert_approx_eq!(f32::math::trunc(-1.3f32), -1.0f32);
|
||||
assert_approx_eq!(f32::math::trunc(-1.5f32), -1.0f32);
|
||||
assert_approx_eq!(f32::math::trunc(-1.7f32), -1.0f32);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_fract() {
|
||||
assert_approx_eq!(f32::fract(1.0f32), 0.0f32);
|
||||
assert_approx_eq!(f32::fract(1.3f32), 0.3f32);
|
||||
assert_approx_eq!(f32::fract(1.5f32), 0.5f32);
|
||||
assert_approx_eq!(f32::fract(1.7f32), 0.7f32);
|
||||
assert_approx_eq!(f32::fract(0.0f32), 0.0f32);
|
||||
assert_approx_eq!(f32::fract(-0.0f32), -0.0f32);
|
||||
assert_approx_eq!(f32::fract(-1.0f32), -0.0f32);
|
||||
assert_approx_eq!(f32::fract(-1.3f32), -0.3f32);
|
||||
assert_approx_eq!(f32::fract(-1.5f32), -0.5f32);
|
||||
assert_approx_eq!(f32::fract(-1.7f32), -0.7f32);
|
||||
assert_approx_eq!(f32::math::fract(1.0f32), 0.0f32);
|
||||
assert_approx_eq!(f32::math::fract(1.3f32), 0.3f32);
|
||||
assert_approx_eq!(f32::math::fract(1.5f32), 0.5f32);
|
||||
assert_approx_eq!(f32::math::fract(1.7f32), 0.7f32);
|
||||
assert_approx_eq!(f32::math::fract(0.0f32), 0.0f32);
|
||||
assert_approx_eq!(f32::math::fract(-0.0f32), -0.0f32);
|
||||
assert_approx_eq!(f32::math::fract(-1.0f32), -0.0f32);
|
||||
assert_approx_eq!(f32::math::fract(-1.3f32), -0.3f32);
|
||||
assert_approx_eq!(f32::math::fract(-1.5f32), -0.5f32);
|
||||
assert_approx_eq!(f32::math::fract(-1.7f32), -0.7f32);
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
|
@ -417,15 +417,15 @@ fn test_mul_add() {
|
|||
let nan: f32 = f32::NAN;
|
||||
let inf: f32 = f32::INFINITY;
|
||||
let neg_inf: f32 = f32::NEG_INFINITY;
|
||||
assert_approx_eq!(f32::mul_add(12.3f32, 4.5, 6.7), 62.05);
|
||||
assert_approx_eq!(f32::mul_add(-12.3f32, -4.5, -6.7), 48.65);
|
||||
assert_approx_eq!(f32::mul_add(0.0f32, 8.9, 1.2), 1.2);
|
||||
assert_approx_eq!(f32::mul_add(3.4f32, -0.0, 5.6), 5.6);
|
||||
assert!(f32::mul_add(nan, 7.8, 9.0).is_nan());
|
||||
assert_eq!(f32::mul_add(inf, 7.8, 9.0), inf);
|
||||
assert_eq!(f32::mul_add(neg_inf, 7.8, 9.0), neg_inf);
|
||||
assert_eq!(f32::mul_add(8.9f32, inf, 3.2), inf);
|
||||
assert_eq!(f32::mul_add(-3.2f32, 2.4, neg_inf), neg_inf);
|
||||
assert_approx_eq!(f32::math::mul_add(12.3f32, 4.5, 6.7), 62.05);
|
||||
assert_approx_eq!(f32::math::mul_add(-12.3f32, -4.5, -6.7), 48.65);
|
||||
assert_approx_eq!(f32::math::mul_add(0.0f32, 8.9, 1.2), 1.2);
|
||||
assert_approx_eq!(f32::math::mul_add(3.4f32, -0.0, 5.6), 5.6);
|
||||
assert!(f32::math::mul_add(nan, 7.8, 9.0).is_nan());
|
||||
assert_eq!(f32::math::mul_add(inf, 7.8, 9.0), inf);
|
||||
assert_eq!(f32::math::mul_add(neg_inf, 7.8, 9.0), neg_inf);
|
||||
assert_eq!(f32::math::mul_add(8.9f32, inf, 3.2), inf);
|
||||
assert_eq!(f32::math::mul_add(-3.2f32, 2.4, neg_inf), neg_inf);
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
use std::f64::consts;
|
||||
use std::num::FpCategory as Fp;
|
||||
use core::f64;
|
||||
use core::f64::consts;
|
||||
use core::num::FpCategory as Fp;
|
||||
|
||||
/// Smallest number
|
||||
const TINY_BITS: u64 = 0x1;
|
||||
|
|
@ -201,88 +202,88 @@ fn test_classify() {
|
|||
|
||||
#[test]
|
||||
fn test_floor() {
|
||||
assert_approx_eq!(f64::floor(1.0f64), 1.0f64);
|
||||
assert_approx_eq!(f64::floor(1.3f64), 1.0f64);
|
||||
assert_approx_eq!(f64::floor(1.5f64), 1.0f64);
|
||||
assert_approx_eq!(f64::floor(1.7f64), 1.0f64);
|
||||
assert_approx_eq!(f64::floor(0.0f64), 0.0f64);
|
||||
assert_approx_eq!(f64::floor(-0.0f64), -0.0f64);
|
||||
assert_approx_eq!(f64::floor(-1.0f64), -1.0f64);
|
||||
assert_approx_eq!(f64::floor(-1.3f64), -2.0f64);
|
||||
assert_approx_eq!(f64::floor(-1.5f64), -2.0f64);
|
||||
assert_approx_eq!(f64::floor(-1.7f64), -2.0f64);
|
||||
assert_approx_eq!(f64::math::floor(1.0f64), 1.0f64);
|
||||
assert_approx_eq!(f64::math::floor(1.3f64), 1.0f64);
|
||||
assert_approx_eq!(f64::math::floor(1.5f64), 1.0f64);
|
||||
assert_approx_eq!(f64::math::floor(1.7f64), 1.0f64);
|
||||
assert_approx_eq!(f64::math::floor(0.0f64), 0.0f64);
|
||||
assert_approx_eq!(f64::math::floor(-0.0f64), -0.0f64);
|
||||
assert_approx_eq!(f64::math::floor(-1.0f64), -1.0f64);
|
||||
assert_approx_eq!(f64::math::floor(-1.3f64), -2.0f64);
|
||||
assert_approx_eq!(f64::math::floor(-1.5f64), -2.0f64);
|
||||
assert_approx_eq!(f64::math::floor(-1.7f64), -2.0f64);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_ceil() {
|
||||
assert_approx_eq!(f64::ceil(1.0f64), 1.0f64);
|
||||
assert_approx_eq!(f64::ceil(1.3f64), 2.0f64);
|
||||
assert_approx_eq!(f64::ceil(1.5f64), 2.0f64);
|
||||
assert_approx_eq!(f64::ceil(1.7f64), 2.0f64);
|
||||
assert_approx_eq!(f64::ceil(0.0f64), 0.0f64);
|
||||
assert_approx_eq!(f64::ceil(-0.0f64), -0.0f64);
|
||||
assert_approx_eq!(f64::ceil(-1.0f64), -1.0f64);
|
||||
assert_approx_eq!(f64::ceil(-1.3f64), -1.0f64);
|
||||
assert_approx_eq!(f64::ceil(-1.5f64), -1.0f64);
|
||||
assert_approx_eq!(f64::ceil(-1.7f64), -1.0f64);
|
||||
assert_approx_eq!(f64::math::ceil(1.0f64), 1.0f64);
|
||||
assert_approx_eq!(f64::math::ceil(1.3f64), 2.0f64);
|
||||
assert_approx_eq!(f64::math::ceil(1.5f64), 2.0f64);
|
||||
assert_approx_eq!(f64::math::ceil(1.7f64), 2.0f64);
|
||||
assert_approx_eq!(f64::math::ceil(0.0f64), 0.0f64);
|
||||
assert_approx_eq!(f64::math::ceil(-0.0f64), -0.0f64);
|
||||
assert_approx_eq!(f64::math::ceil(-1.0f64), -1.0f64);
|
||||
assert_approx_eq!(f64::math::ceil(-1.3f64), -1.0f64);
|
||||
assert_approx_eq!(f64::math::ceil(-1.5f64), -1.0f64);
|
||||
assert_approx_eq!(f64::math::ceil(-1.7f64), -1.0f64);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_round() {
|
||||
assert_approx_eq!(f64::round(2.5f64), 3.0f64);
|
||||
assert_approx_eq!(f64::round(1.0f64), 1.0f64);
|
||||
assert_approx_eq!(f64::round(1.3f64), 1.0f64);
|
||||
assert_approx_eq!(f64::round(1.5f64), 2.0f64);
|
||||
assert_approx_eq!(f64::round(1.7f64), 2.0f64);
|
||||
assert_approx_eq!(f64::round(0.0f64), 0.0f64);
|
||||
assert_approx_eq!(f64::round(-0.0f64), -0.0f64);
|
||||
assert_approx_eq!(f64::round(-1.0f64), -1.0f64);
|
||||
assert_approx_eq!(f64::round(-1.3f64), -1.0f64);
|
||||
assert_approx_eq!(f64::round(-1.5f64), -2.0f64);
|
||||
assert_approx_eq!(f64::round(-1.7f64), -2.0f64);
|
||||
assert_approx_eq!(f64::math::round(2.5f64), 3.0f64);
|
||||
assert_approx_eq!(f64::math::round(1.0f64), 1.0f64);
|
||||
assert_approx_eq!(f64::math::round(1.3f64), 1.0f64);
|
||||
assert_approx_eq!(f64::math::round(1.5f64), 2.0f64);
|
||||
assert_approx_eq!(f64::math::round(1.7f64), 2.0f64);
|
||||
assert_approx_eq!(f64::math::round(0.0f64), 0.0f64);
|
||||
assert_approx_eq!(f64::math::round(-0.0f64), -0.0f64);
|
||||
assert_approx_eq!(f64::math::round(-1.0f64), -1.0f64);
|
||||
assert_approx_eq!(f64::math::round(-1.3f64), -1.0f64);
|
||||
assert_approx_eq!(f64::math::round(-1.5f64), -2.0f64);
|
||||
assert_approx_eq!(f64::math::round(-1.7f64), -2.0f64);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_round_ties_even() {
|
||||
assert_approx_eq!(f64::round_ties_even(2.5f64), 2.0f64);
|
||||
assert_approx_eq!(f64::round_ties_even(1.0f64), 1.0f64);
|
||||
assert_approx_eq!(f64::round_ties_even(1.3f64), 1.0f64);
|
||||
assert_approx_eq!(f64::round_ties_even(1.5f64), 2.0f64);
|
||||
assert_approx_eq!(f64::round_ties_even(1.7f64), 2.0f64);
|
||||
assert_approx_eq!(f64::round_ties_even(0.0f64), 0.0f64);
|
||||
assert_approx_eq!(f64::round_ties_even(-0.0f64), -0.0f64);
|
||||
assert_approx_eq!(f64::round_ties_even(-1.0f64), -1.0f64);
|
||||
assert_approx_eq!(f64::round_ties_even(-1.3f64), -1.0f64);
|
||||
assert_approx_eq!(f64::round_ties_even(-1.5f64), -2.0f64);
|
||||
assert_approx_eq!(f64::round_ties_even(-1.7f64), -2.0f64);
|
||||
assert_approx_eq!(f64::math::round_ties_even(2.5f64), 2.0f64);
|
||||
assert_approx_eq!(f64::math::round_ties_even(1.0f64), 1.0f64);
|
||||
assert_approx_eq!(f64::math::round_ties_even(1.3f64), 1.0f64);
|
||||
assert_approx_eq!(f64::math::round_ties_even(1.5f64), 2.0f64);
|
||||
assert_approx_eq!(f64::math::round_ties_even(1.7f64), 2.0f64);
|
||||
assert_approx_eq!(f64::math::round_ties_even(0.0f64), 0.0f64);
|
||||
assert_approx_eq!(f64::math::round_ties_even(-0.0f64), -0.0f64);
|
||||
assert_approx_eq!(f64::math::round_ties_even(-1.0f64), -1.0f64);
|
||||
assert_approx_eq!(f64::math::round_ties_even(-1.3f64), -1.0f64);
|
||||
assert_approx_eq!(f64::math::round_ties_even(-1.5f64), -2.0f64);
|
||||
assert_approx_eq!(f64::math::round_ties_even(-1.7f64), -2.0f64);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_trunc() {
|
||||
assert_approx_eq!(f64::trunc(1.0f64), 1.0f64);
|
||||
assert_approx_eq!(f64::trunc(1.3f64), 1.0f64);
|
||||
assert_approx_eq!(f64::trunc(1.5f64), 1.0f64);
|
||||
assert_approx_eq!(f64::trunc(1.7f64), 1.0f64);
|
||||
assert_approx_eq!(f64::trunc(0.0f64), 0.0f64);
|
||||
assert_approx_eq!(f64::trunc(-0.0f64), -0.0f64);
|
||||
assert_approx_eq!(f64::trunc(-1.0f64), -1.0f64);
|
||||
assert_approx_eq!(f64::trunc(-1.3f64), -1.0f64);
|
||||
assert_approx_eq!(f64::trunc(-1.5f64), -1.0f64);
|
||||
assert_approx_eq!(f64::trunc(-1.7f64), -1.0f64);
|
||||
assert_approx_eq!(f64::math::trunc(1.0f64), 1.0f64);
|
||||
assert_approx_eq!(f64::math::trunc(1.3f64), 1.0f64);
|
||||
assert_approx_eq!(f64::math::trunc(1.5f64), 1.0f64);
|
||||
assert_approx_eq!(f64::math::trunc(1.7f64), 1.0f64);
|
||||
assert_approx_eq!(f64::math::trunc(0.0f64), 0.0f64);
|
||||
assert_approx_eq!(f64::math::trunc(-0.0f64), -0.0f64);
|
||||
assert_approx_eq!(f64::math::trunc(-1.0f64), -1.0f64);
|
||||
assert_approx_eq!(f64::math::trunc(-1.3f64), -1.0f64);
|
||||
assert_approx_eq!(f64::math::trunc(-1.5f64), -1.0f64);
|
||||
assert_approx_eq!(f64::math::trunc(-1.7f64), -1.0f64);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_fract() {
|
||||
assert_approx_eq!(f64::fract(1.0f64), 0.0f64);
|
||||
assert_approx_eq!(f64::fract(1.3f64), 0.3f64);
|
||||
assert_approx_eq!(f64::fract(1.5f64), 0.5f64);
|
||||
assert_approx_eq!(f64::fract(1.7f64), 0.7f64);
|
||||
assert_approx_eq!(f64::fract(0.0f64), 0.0f64);
|
||||
assert_approx_eq!(f64::fract(-0.0f64), -0.0f64);
|
||||
assert_approx_eq!(f64::fract(-1.0f64), -0.0f64);
|
||||
assert_approx_eq!(f64::fract(-1.3f64), -0.3f64);
|
||||
assert_approx_eq!(f64::fract(-1.5f64), -0.5f64);
|
||||
assert_approx_eq!(f64::fract(-1.7f64), -0.7f64);
|
||||
assert_approx_eq!(f64::math::fract(1.0f64), 0.0f64);
|
||||
assert_approx_eq!(f64::math::fract(1.3f64), 0.3f64);
|
||||
assert_approx_eq!(f64::math::fract(1.5f64), 0.5f64);
|
||||
assert_approx_eq!(f64::math::fract(1.7f64), 0.7f64);
|
||||
assert_approx_eq!(f64::math::fract(0.0f64), 0.0f64);
|
||||
assert_approx_eq!(f64::math::fract(-0.0f64), -0.0f64);
|
||||
assert_approx_eq!(f64::math::fract(-1.0f64), -0.0f64);
|
||||
assert_approx_eq!(f64::math::fract(-1.3f64), -0.3f64);
|
||||
assert_approx_eq!(f64::math::fract(-1.5f64), -0.5f64);
|
||||
assert_approx_eq!(f64::math::fract(-1.7f64), -0.7f64);
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
|
|
|||
|
|
@ -46,7 +46,7 @@ impl f32 {
|
|||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
#[inline]
|
||||
pub fn floor(self) -> f32 {
|
||||
core::f32::floor(self)
|
||||
core::f32::math::floor(self)
|
||||
}
|
||||
|
||||
/// Returns the smallest integer greater than or equal to `self`.
|
||||
|
|
@ -68,7 +68,7 @@ impl f32 {
|
|||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
#[inline]
|
||||
pub fn ceil(self) -> f32 {
|
||||
core::f32::ceil(self)
|
||||
core::f32::math::ceil(self)
|
||||
}
|
||||
|
||||
/// Returns the nearest integer to `self`. If a value is half-way between two
|
||||
|
|
@ -96,7 +96,7 @@ impl f32 {
|
|||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
#[inline]
|
||||
pub fn round(self) -> f32 {
|
||||
core::f32::round(self)
|
||||
core::f32::math::round(self)
|
||||
}
|
||||
|
||||
/// Returns the nearest integer to a number. Rounds half-way cases to the number
|
||||
|
|
@ -122,7 +122,7 @@ impl f32 {
|
|||
#[stable(feature = "round_ties_even", since = "1.77.0")]
|
||||
#[inline]
|
||||
pub fn round_ties_even(self) -> f32 {
|
||||
core::f32::round_ties_even(self)
|
||||
core::f32::math::round_ties_even(self)
|
||||
}
|
||||
|
||||
/// Returns the integer part of `self`.
|
||||
|
|
@ -147,7 +147,7 @@ impl f32 {
|
|||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
#[inline]
|
||||
pub fn trunc(self) -> f32 {
|
||||
core::f32::trunc(self)
|
||||
core::f32::math::trunc(self)
|
||||
}
|
||||
|
||||
/// Returns the fractional part of `self`.
|
||||
|
|
@ -170,7 +170,7 @@ impl f32 {
|
|||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
#[inline]
|
||||
pub fn fract(self) -> f32 {
|
||||
core::f32::fract(self)
|
||||
core::f32::math::fract(self)
|
||||
}
|
||||
|
||||
/// Fused multiply-add. Computes `(self * a) + b` with only one rounding
|
||||
|
|
@ -212,7 +212,7 @@ impl f32 {
|
|||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
#[inline]
|
||||
pub fn mul_add(self, a: f32, b: f32) -> f32 {
|
||||
core::f32::mul_add(self, a, b)
|
||||
core::f32::math::mul_add(self, a, b)
|
||||
}
|
||||
|
||||
/// Calculates Euclidean division, the matching method for `rem_euclid`.
|
||||
|
|
@ -242,7 +242,7 @@ impl f32 {
|
|||
#[inline]
|
||||
#[stable(feature = "euclidean_division", since = "1.38.0")]
|
||||
pub fn div_euclid(self, rhs: f32) -> f32 {
|
||||
core::f32::div_euclid(self, rhs)
|
||||
core::f32::math::div_euclid(self, rhs)
|
||||
}
|
||||
|
||||
/// Calculates the least nonnegative remainder of `self (mod rhs)`.
|
||||
|
|
@ -279,7 +279,7 @@ impl f32 {
|
|||
#[inline]
|
||||
#[stable(feature = "euclidean_division", since = "1.38.0")]
|
||||
pub fn rem_euclid(self, rhs: f32) -> f32 {
|
||||
core::f32::rem_euclid(self, rhs)
|
||||
core::f32::math::rem_euclid(self, rhs)
|
||||
}
|
||||
|
||||
/// Raises a number to an integer power.
|
||||
|
|
@ -307,7 +307,7 @@ impl f32 {
|
|||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
#[inline]
|
||||
pub fn powi(self, n: i32) -> f32 {
|
||||
core::f32::powi(self, n)
|
||||
core::f32::math::powi(self, n)
|
||||
}
|
||||
|
||||
/// Raises a number to a floating point power.
|
||||
|
|
@ -362,7 +362,7 @@ impl f32 {
|
|||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
#[inline]
|
||||
pub fn sqrt(self) -> f32 {
|
||||
core::f32::sqrt(self)
|
||||
core::f32::math::sqrt(self)
|
||||
}
|
||||
|
||||
/// Returns `e^(self)`, (the exponential function).
|
||||
|
|
@ -595,7 +595,7 @@ impl f32 {
|
|||
)]
|
||||
pub fn abs_sub(self, other: f32) -> f32 {
|
||||
#[allow(deprecated)]
|
||||
core::f32::abs_sub(self, other)
|
||||
core::f32::math::abs_sub(self, other)
|
||||
}
|
||||
|
||||
/// Returns the cube root of a number.
|
||||
|
|
@ -622,7 +622,7 @@ impl f32 {
|
|||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
#[inline]
|
||||
pub fn cbrt(self) -> f32 {
|
||||
core::f32::cbrt(self)
|
||||
core::f32::math::cbrt(self)
|
||||
}
|
||||
|
||||
/// Compute the distance between the origin and a point (`x`, `y`) on the
|
||||
|
|
|
|||
|
|
@ -46,7 +46,7 @@ impl f64 {
|
|||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
#[inline]
|
||||
pub fn floor(self) -> f64 {
|
||||
core::f64::floor(self)
|
||||
core::f64::math::floor(self)
|
||||
}
|
||||
|
||||
/// Returns the smallest integer greater than or equal to `self`.
|
||||
|
|
@ -68,7 +68,7 @@ impl f64 {
|
|||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
#[inline]
|
||||
pub fn ceil(self) -> f64 {
|
||||
core::f64::ceil(self)
|
||||
core::f64::math::ceil(self)
|
||||
}
|
||||
|
||||
/// Returns the nearest integer to `self`. If a value is half-way between two
|
||||
|
|
@ -96,7 +96,7 @@ impl f64 {
|
|||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
#[inline]
|
||||
pub fn round(self) -> f64 {
|
||||
core::f64::round(self)
|
||||
core::f64::math::round(self)
|
||||
}
|
||||
|
||||
/// Returns the nearest integer to a number. Rounds half-way cases to the number
|
||||
|
|
@ -122,7 +122,7 @@ impl f64 {
|
|||
#[stable(feature = "round_ties_even", since = "1.77.0")]
|
||||
#[inline]
|
||||
pub fn round_ties_even(self) -> f64 {
|
||||
core::f64::round_ties_even(self)
|
||||
core::f64::math::round_ties_even(self)
|
||||
}
|
||||
|
||||
/// Returns the integer part of `self`.
|
||||
|
|
@ -147,7 +147,7 @@ impl f64 {
|
|||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
#[inline]
|
||||
pub fn trunc(self) -> f64 {
|
||||
core::f64::trunc(self)
|
||||
core::f64::math::trunc(self)
|
||||
}
|
||||
|
||||
/// Returns the fractional part of `self`.
|
||||
|
|
@ -170,7 +170,7 @@ impl f64 {
|
|||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
#[inline]
|
||||
pub fn fract(self) -> f64 {
|
||||
core::f64::fract(self)
|
||||
core::f64::math::fract(self)
|
||||
}
|
||||
|
||||
/// Fused multiply-add. Computes `(self * a) + b` with only one rounding
|
||||
|
|
@ -212,7 +212,7 @@ impl f64 {
|
|||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
#[inline]
|
||||
pub fn mul_add(self, a: f64, b: f64) -> f64 {
|
||||
core::f64::mul_add(self, a, b)
|
||||
core::f64::math::mul_add(self, a, b)
|
||||
}
|
||||
|
||||
/// Calculates Euclidean division, the matching method for `rem_euclid`.
|
||||
|
|
@ -242,7 +242,7 @@ impl f64 {
|
|||
#[inline]
|
||||
#[stable(feature = "euclidean_division", since = "1.38.0")]
|
||||
pub fn div_euclid(self, rhs: f64) -> f64 {
|
||||
core::f64::div_euclid(self, rhs)
|
||||
core::f64::math::div_euclid(self, rhs)
|
||||
}
|
||||
|
||||
/// Calculates the least nonnegative remainder of `self (mod rhs)`.
|
||||
|
|
@ -279,7 +279,7 @@ impl f64 {
|
|||
#[inline]
|
||||
#[stable(feature = "euclidean_division", since = "1.38.0")]
|
||||
pub fn rem_euclid(self, rhs: f64) -> f64 {
|
||||
core::f64::rem_euclid(self, rhs)
|
||||
core::f64::math::rem_euclid(self, rhs)
|
||||
}
|
||||
|
||||
/// Raises a number to an integer power.
|
||||
|
|
@ -307,7 +307,7 @@ impl f64 {
|
|||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
#[inline]
|
||||
pub fn powi(self, n: i32) -> f64 {
|
||||
core::f64::powi(self, n)
|
||||
core::f64::math::powi(self, n)
|
||||
}
|
||||
|
||||
/// Raises a number to a floating point power.
|
||||
|
|
@ -362,7 +362,7 @@ impl f64 {
|
|||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
#[inline]
|
||||
pub fn sqrt(self) -> f64 {
|
||||
core::f64::sqrt(self)
|
||||
core::f64::math::sqrt(self)
|
||||
}
|
||||
|
||||
/// Returns `e^(self)`, (the exponential function).
|
||||
|
|
@ -595,7 +595,7 @@ impl f64 {
|
|||
)]
|
||||
pub fn abs_sub(self, other: f64) -> f64 {
|
||||
#[allow(deprecated)]
|
||||
core::f64::abs_sub(self, other)
|
||||
core::f64::math::abs_sub(self, other)
|
||||
}
|
||||
|
||||
/// Returns the cube root of a number.
|
||||
|
|
@ -622,7 +622,7 @@ impl f64 {
|
|||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
#[inline]
|
||||
pub fn cbrt(self) -> f64 {
|
||||
core::f64::cbrt(self)
|
||||
core::f64::math::cbrt(self)
|
||||
}
|
||||
|
||||
/// Compute the distance between the origin and a point (`x`, `y`) on the
|
||||
|
|
|
|||
|
|
@ -285,8 +285,7 @@ pub fn read<P: AsRef<Path>>(path: P) -> io::Result<Vec<u8>> {
|
|||
fn inner(path: &Path) -> io::Result<Vec<u8>> {
|
||||
let mut file = File::open(path)?;
|
||||
let size = file.metadata().map(|m| m.len() as usize).ok();
|
||||
let mut bytes = Vec::new();
|
||||
bytes.try_reserve_exact(size.unwrap_or(0))?;
|
||||
let mut bytes = Vec::try_with_capacity(size.unwrap_or(0))?;
|
||||
io::default_read_to_end(&mut file, &mut bytes, size)?;
|
||||
Ok(bytes)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1214,7 +1214,7 @@ pub trait Read {
|
|||
where
|
||||
Self: Sized,
|
||||
{
|
||||
Take { inner: self, limit }
|
||||
Take { inner: self, len: limit, limit }
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -2830,6 +2830,7 @@ impl<T, U> SizeHint for Chain<T, U> {
|
|||
#[derive(Debug)]
|
||||
pub struct Take<T> {
|
||||
inner: T,
|
||||
len: u64,
|
||||
limit: u64,
|
||||
}
|
||||
|
||||
|
|
@ -2864,6 +2865,12 @@ impl<T> Take<T> {
|
|||
self.limit
|
||||
}
|
||||
|
||||
/// Returns the number of bytes read so far.
|
||||
#[unstable(feature = "seek_io_take_position", issue = "97227")]
|
||||
pub fn position(&self) -> u64 {
|
||||
self.len - self.limit
|
||||
}
|
||||
|
||||
/// Sets the number of bytes that can be read before this instance will
|
||||
/// return EOF. This is the same as constructing a new `Take` instance, so
|
||||
/// the amount of bytes read and the previous limit value don't matter when
|
||||
|
|
@ -2889,6 +2896,7 @@ impl<T> Take<T> {
|
|||
/// ```
|
||||
#[stable(feature = "take_set_limit", since = "1.27.0")]
|
||||
pub fn set_limit(&mut self, limit: u64) {
|
||||
self.len = limit;
|
||||
self.limit = limit;
|
||||
}
|
||||
|
||||
|
|
@ -3076,6 +3084,49 @@ impl<T> SizeHint for Take<T> {
|
|||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "seek_io_take", since = "CURRENT_RUSTC_VERSION")]
|
||||
impl<T: Seek> Seek for Take<T> {
|
||||
fn seek(&mut self, pos: SeekFrom) -> Result<u64> {
|
||||
let new_position = match pos {
|
||||
SeekFrom::Start(v) => Some(v),
|
||||
SeekFrom::Current(v) => self.position().checked_add_signed(v),
|
||||
SeekFrom::End(v) => self.len.checked_add_signed(v),
|
||||
};
|
||||
let new_position = match new_position {
|
||||
Some(v) if v <= self.len => v,
|
||||
_ => return Err(ErrorKind::InvalidInput.into()),
|
||||
};
|
||||
while new_position != self.position() {
|
||||
if let Some(offset) = new_position.checked_signed_diff(self.position()) {
|
||||
self.inner.seek_relative(offset)?;
|
||||
self.limit = self.limit.wrapping_sub(offset as u64);
|
||||
break;
|
||||
}
|
||||
let offset = if new_position > self.position() { i64::MAX } else { i64::MIN };
|
||||
self.inner.seek_relative(offset)?;
|
||||
self.limit = self.limit.wrapping_sub(offset as u64);
|
||||
}
|
||||
Ok(new_position)
|
||||
}
|
||||
|
||||
fn stream_len(&mut self) -> Result<u64> {
|
||||
Ok(self.len)
|
||||
}
|
||||
|
||||
fn stream_position(&mut self) -> Result<u64> {
|
||||
Ok(self.position())
|
||||
}
|
||||
|
||||
fn seek_relative(&mut self, offset: i64) -> Result<()> {
|
||||
if !self.position().checked_add_signed(offset).is_some_and(|p| p <= self.len) {
|
||||
return Err(ErrorKind::InvalidInput.into());
|
||||
}
|
||||
self.inner.seek_relative(offset)?;
|
||||
self.limit = self.limit.wrapping_sub(offset as u64);
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
/// An iterator over `u8` values of a reader.
|
||||
///
|
||||
/// This struct is generally created by calling [`bytes`] on a reader.
|
||||
|
|
|
|||
|
|
@ -416,6 +416,126 @@ fn seek_position() -> io::Result<()> {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn take_seek() -> io::Result<()> {
|
||||
let mut buf = Cursor::new(b"0123456789");
|
||||
buf.set_position(2);
|
||||
let mut take = buf.by_ref().take(4);
|
||||
let mut buf1 = [0u8; 1];
|
||||
let mut buf2 = [0u8; 2];
|
||||
assert_eq!(take.position(), 0);
|
||||
|
||||
assert_eq!(take.seek(SeekFrom::Start(0))?, 0);
|
||||
take.read_exact(&mut buf2)?;
|
||||
assert_eq!(buf2, [b'2', b'3']);
|
||||
assert_eq!(take.seek(SeekFrom::Start(1))?, 1);
|
||||
take.read_exact(&mut buf2)?;
|
||||
assert_eq!(buf2, [b'3', b'4']);
|
||||
assert_eq!(take.seek(SeekFrom::Start(2))?, 2);
|
||||
take.read_exact(&mut buf2)?;
|
||||
assert_eq!(buf2, [b'4', b'5']);
|
||||
assert_eq!(take.seek(SeekFrom::Start(3))?, 3);
|
||||
take.read_exact(&mut buf1)?;
|
||||
assert_eq!(buf1, [b'5']);
|
||||
assert_eq!(take.seek(SeekFrom::Start(4))?, 4);
|
||||
assert_eq!(take.read(&mut buf1)?, 0);
|
||||
|
||||
assert_eq!(take.seek(SeekFrom::End(0))?, 4);
|
||||
assert_eq!(take.seek(SeekFrom::End(-1))?, 3);
|
||||
take.read_exact(&mut buf1)?;
|
||||
assert_eq!(buf1, [b'5']);
|
||||
assert_eq!(take.seek(SeekFrom::End(-2))?, 2);
|
||||
take.read_exact(&mut buf2)?;
|
||||
assert_eq!(buf2, [b'4', b'5']);
|
||||
assert_eq!(take.seek(SeekFrom::End(-3))?, 1);
|
||||
take.read_exact(&mut buf2)?;
|
||||
assert_eq!(buf2, [b'3', b'4']);
|
||||
assert_eq!(take.seek(SeekFrom::End(-4))?, 0);
|
||||
take.read_exact(&mut buf2)?;
|
||||
assert_eq!(buf2, [b'2', b'3']);
|
||||
|
||||
assert_eq!(take.seek(SeekFrom::Current(0))?, 2);
|
||||
take.read_exact(&mut buf2)?;
|
||||
assert_eq!(buf2, [b'4', b'5']);
|
||||
|
||||
assert_eq!(take.seek(SeekFrom::Current(-3))?, 1);
|
||||
take.read_exact(&mut buf2)?;
|
||||
assert_eq!(buf2, [b'3', b'4']);
|
||||
|
||||
assert_eq!(take.seek(SeekFrom::Current(-1))?, 2);
|
||||
take.read_exact(&mut buf2)?;
|
||||
assert_eq!(buf2, [b'4', b'5']);
|
||||
|
||||
assert_eq!(take.seek(SeekFrom::Current(-4))?, 0);
|
||||
take.read_exact(&mut buf2)?;
|
||||
assert_eq!(buf2, [b'2', b'3']);
|
||||
|
||||
assert_eq!(take.seek(SeekFrom::Current(2))?, 4);
|
||||
assert_eq!(take.read(&mut buf1)?, 0);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn take_seek_error() {
|
||||
let buf = Cursor::new(b"0123456789");
|
||||
let mut take = buf.take(2);
|
||||
assert!(take.seek(SeekFrom::Start(3)).is_err());
|
||||
assert!(take.seek(SeekFrom::End(1)).is_err());
|
||||
assert!(take.seek(SeekFrom::End(-3)).is_err());
|
||||
assert!(take.seek(SeekFrom::Current(-1)).is_err());
|
||||
assert!(take.seek(SeekFrom::Current(3)).is_err());
|
||||
}
|
||||
|
||||
struct ExampleHugeRangeOfZeroes {
|
||||
position: u64,
|
||||
}
|
||||
|
||||
impl Read for ExampleHugeRangeOfZeroes {
|
||||
fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
|
||||
let max = buf.len().min(usize::MAX);
|
||||
for i in 0..max {
|
||||
if self.position == u64::MAX {
|
||||
return Ok(i);
|
||||
}
|
||||
self.position += 1;
|
||||
buf[i] = 0;
|
||||
}
|
||||
Ok(max)
|
||||
}
|
||||
}
|
||||
|
||||
impl Seek for ExampleHugeRangeOfZeroes {
|
||||
fn seek(&mut self, pos: io::SeekFrom) -> io::Result<u64> {
|
||||
match pos {
|
||||
io::SeekFrom::Start(i) => self.position = i,
|
||||
io::SeekFrom::End(i) if i >= 0 => self.position = u64::MAX,
|
||||
io::SeekFrom::End(i) => self.position = self.position - i.unsigned_abs(),
|
||||
io::SeekFrom::Current(i) => {
|
||||
self.position = if i >= 0 {
|
||||
self.position.saturating_add(i.unsigned_abs())
|
||||
} else {
|
||||
self.position.saturating_sub(i.unsigned_abs())
|
||||
};
|
||||
}
|
||||
}
|
||||
Ok(self.position)
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn take_seek_big_offsets() -> io::Result<()> {
|
||||
let inner = ExampleHugeRangeOfZeroes { position: 1 };
|
||||
let mut take = inner.take(u64::MAX - 2);
|
||||
assert_eq!(take.seek(io::SeekFrom::Start(u64::MAX - 2))?, u64::MAX - 2);
|
||||
assert_eq!(take.inner.position, u64::MAX - 1);
|
||||
assert_eq!(take.seek(io::SeekFrom::Start(0))?, 0);
|
||||
assert_eq!(take.inner.position, 1);
|
||||
assert_eq!(take.seek(io::SeekFrom::End(-1))?, u64::MAX - 3);
|
||||
assert_eq!(take.inner.position, u64::MAX - 2);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
// A simple example reader which uses the default implementation of
|
||||
// read_to_end.
|
||||
struct ExampleSliceReader<'a> {
|
||||
|
|
|
|||
|
|
@ -325,6 +325,7 @@
|
|||
#![feature(try_blocks)]
|
||||
#![feature(try_trait_v2)]
|
||||
#![feature(type_alias_impl_trait)]
|
||||
#![feature(unsigned_signed_diff)]
|
||||
// tidy-alphabetical-end
|
||||
//
|
||||
// Library features (core):
|
||||
|
|
|
|||
|
|
@ -136,7 +136,7 @@ cfg_if!(
|
|||
// we only ever read from the tid if `tls_addr` matches the current
|
||||
// TLS address. In that case, either the tid has been set by
|
||||
// the current thread, or by a thread that has terminated before
|
||||
// the current thread was created. In either case, no further
|
||||
// the current thread's `tls_addr` was allocated. In either case, no further
|
||||
// synchronization is needed (as per <https://github.com/rust-lang/miri/issues/3450>)
|
||||
tls_addr: Atomic<usize>,
|
||||
tid: UnsafeCell<u64>,
|
||||
|
|
@ -154,8 +154,12 @@ cfg_if!(
|
|||
// NOTE: This assumes that `owner` is the ID of the current
|
||||
// thread, and may spuriously return `false` if that's not the case.
|
||||
fn contains(&self, owner: ThreadId) -> bool {
|
||||
// We must call `tls_addr()` *before* doing the load to ensure that if we reuse an
|
||||
// earlier thread's address, the `tls_addr.load()` below happens-after everything
|
||||
// that thread did.
|
||||
let tls_addr = tls_addr();
|
||||
// SAFETY: See the comments in the struct definition.
|
||||
self.tls_addr.load(Ordering::Relaxed) == tls_addr()
|
||||
self.tls_addr.load(Ordering::Relaxed) == tls_addr
|
||||
&& unsafe { *self.tid.get() } == owner.as_u64().get()
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -202,6 +202,8 @@ fn home_dir_crt() -> Option<PathBuf> {
|
|||
|buf, mut sz| {
|
||||
// GetUserProfileDirectoryW does not quite use the usual protocol for
|
||||
// negotiating the buffer size, so we have to translate.
|
||||
// FIXME(#141254): We rely on the *undocumented* property that this function will
|
||||
// always set the size, not just on failure.
|
||||
match c::GetUserProfileDirectoryW(
|
||||
ptr::without_provenance_mut(CURRENT_PROCESS_TOKEN),
|
||||
buf,
|
||||
|
|
|
|||
|
|
@ -13,7 +13,6 @@ use std::ffi::{OsStr, OsString};
|
|||
use std::path::PathBuf;
|
||||
use std::{env, fs};
|
||||
|
||||
use crate::Build;
|
||||
#[cfg(not(test))]
|
||||
use crate::builder::Builder;
|
||||
use crate::builder::Kind;
|
||||
|
|
@ -21,6 +20,7 @@ use crate::builder::Kind;
|
|||
use crate::core::build_steps::tool;
|
||||
use crate::core::config::Target;
|
||||
use crate::utils::exec::command;
|
||||
use crate::{Build, Subcommand};
|
||||
|
||||
pub struct Finder {
|
||||
cache: HashMap<OsString, Option<PathBuf>>,
|
||||
|
|
@ -205,6 +205,20 @@ than building it.
|
|||
.map(|s| s.to_string())
|
||||
.collect();
|
||||
|
||||
// Compiler tools like `cc` and `ar` are not configured for cross-targets on certain subcommands
|
||||
// because they are not needed.
|
||||
//
|
||||
// See `cc_detect::find` for more details.
|
||||
let skip_tools_checks = build.config.dry_run()
|
||||
|| matches!(
|
||||
build.config.cmd,
|
||||
Subcommand::Clean { .. }
|
||||
| Subcommand::Check { .. }
|
||||
| Subcommand::Suggest { .. }
|
||||
| Subcommand::Format { .. }
|
||||
| Subcommand::Setup { .. }
|
||||
);
|
||||
|
||||
// We're gonna build some custom C code here and there, host triples
|
||||
// also build some C++ shims for LLVM so we need a C++ compiler.
|
||||
for target in &build.targets {
|
||||
|
|
@ -278,7 +292,7 @@ than building it.
|
|||
}
|
||||
}
|
||||
|
||||
if !build.config.dry_run() {
|
||||
if !skip_tools_checks {
|
||||
cmd_finder.must_have(build.cc(*target));
|
||||
if let Some(ar) = build.ar(*target) {
|
||||
cmd_finder.must_have(ar);
|
||||
|
|
@ -286,7 +300,7 @@ than building it.
|
|||
}
|
||||
}
|
||||
|
||||
if !build.config.dry_run() {
|
||||
if !skip_tools_checks {
|
||||
for host in &build.hosts {
|
||||
cmd_finder.must_have(build.cxx(*host).unwrap());
|
||||
|
||||
|
|
|
|||
|
|
@ -20,7 +20,6 @@ use std::collections::HashMap;
|
|||
use std::hash::{Hash, Hasher};
|
||||
use std::marker::PhantomData;
|
||||
use std::ops::Deref;
|
||||
use std::path::PathBuf;
|
||||
use std::sync::{LazyLock, Mutex};
|
||||
use std::{fmt, mem};
|
||||
|
||||
|
|
@ -51,26 +50,11 @@ impl<T> PartialEq for Interned<T> {
|
|||
}
|
||||
impl<T> Eq for Interned<T> {}
|
||||
|
||||
impl PartialEq<str> for Interned<String> {
|
||||
fn eq(&self, other: &str) -> bool {
|
||||
*self == other
|
||||
}
|
||||
}
|
||||
impl PartialEq<&str> for Interned<String> {
|
||||
fn eq(&self, other: &&str) -> bool {
|
||||
**self == **other
|
||||
}
|
||||
}
|
||||
impl<T> PartialEq<&Interned<T>> for Interned<T> {
|
||||
fn eq(&self, other: &&Self) -> bool {
|
||||
self.0 == other.0
|
||||
}
|
||||
}
|
||||
impl<T> PartialEq<Interned<T>> for &Interned<T> {
|
||||
fn eq(&self, other: &Interned<T>) -> bool {
|
||||
self.0 == other.0
|
||||
}
|
||||
}
|
||||
|
||||
unsafe impl<T> Send for Interned<T> {}
|
||||
unsafe impl<T> Sync for Interned<T> {}
|
||||
|
|
@ -188,8 +172,6 @@ impl<T: Hash + Clone + Eq> TyIntern<T> {
|
|||
#[derive(Default)]
|
||||
pub struct Interner {
|
||||
strs: Mutex<TyIntern<String>>,
|
||||
paths: Mutex<TyIntern<PathBuf>>,
|
||||
lists: Mutex<TyIntern<Vec<String>>>,
|
||||
}
|
||||
|
||||
/// Defines the behavior required for a type to be internable.
|
||||
|
|
@ -210,18 +192,6 @@ impl Internable for String {
|
|||
}
|
||||
}
|
||||
|
||||
impl Internable for PathBuf {
|
||||
fn intern_cache() -> &'static Mutex<TyIntern<Self>> {
|
||||
&INTERNER.paths
|
||||
}
|
||||
}
|
||||
|
||||
impl Internable for Vec<String> {
|
||||
fn intern_cache() -> &'static Mutex<TyIntern<Self>> {
|
||||
&INTERNER.lists
|
||||
}
|
||||
}
|
||||
|
||||
impl Interner {
|
||||
/// Interns a string reference, ensuring it is stored uniquely.
|
||||
///
|
||||
|
|
|
|||
20
src/bootstrap/src/utils/cache/tests.rs
vendored
20
src/bootstrap/src/utils/cache/tests.rs
vendored
|
|
@ -12,26 +12,6 @@ fn test_string_interning() {
|
|||
assert_ne!(s1, s3, "Different strings should have different interned values");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_path_interning() {
|
||||
let p1 = PathBuf::from("/tmp/file").intern();
|
||||
let p2 = PathBuf::from("/tmp/file").intern();
|
||||
let p3 = PathBuf::from("/tmp/other").intern();
|
||||
|
||||
assert_eq!(p1, p2);
|
||||
assert_ne!(p1, p3);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_vec_interning() {
|
||||
let v1 = vec!["a".to_string(), "b".to_string()].intern();
|
||||
let v2 = vec!["a".to_string(), "b".to_string()].intern();
|
||||
let v3 = vec!["c".to_string()].intern();
|
||||
|
||||
assert_eq!(v1, v2);
|
||||
assert_ne!(v1, v3);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_interned_equality() {
|
||||
let s1 = INTERNER.intern_str("test");
|
||||
|
|
|
|||
|
|
@ -42,5 +42,5 @@ if isWindows && isKnownToBeMingwBuild; then
|
|||
|
||||
curl -o mingw.7z "${MIRRORS_BASE}/${mingw_archive}"
|
||||
7z x -y mingw.7z > /dev/null
|
||||
ciCommandAddPath "$(pwd)/${mingw_dir}/bin"
|
||||
ciCommandAddPath "$(cygpath -m "$(pwd)/${mingw_dir}/bin")"
|
||||
fi
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@ if isWindows; then
|
|||
7z x -oninja ninja.zip
|
||||
rm ninja.zip
|
||||
ciCommandSetEnv "RUST_CONFIGURE_ARGS" "${RUST_CONFIGURE_ARGS} --enable-ninja"
|
||||
ciCommandAddPath "$(pwd)/ninja"
|
||||
ciCommandAddPath "$(cygpath -m "$(pwd)/ninja")"
|
||||
elif isMacOS; then
|
||||
brew install ninja
|
||||
fi
|
||||
|
|
|
|||
|
|
@ -15,7 +15,7 @@ elif isWindows; then
|
|||
mkdir -p sccache
|
||||
curl -fo sccache/sccache.exe \
|
||||
"${MIRRORS_BASE}/2025-02-24-sccache-v0.10.0-x86_64-pc-windows-msvc.exe"
|
||||
ciCommandAddPath "$(pwd)/sccache"
|
||||
ciCommandAddPath "$(cygpath -m "$(pwd)/sccache")"
|
||||
fi
|
||||
|
||||
# FIXME: we should probably install sccache outside the containers and then
|
||||
|
|
|
|||
|
|
@ -1 +1 @@
|
|||
Subproject commit d33916341d480caede1d0ae57cbeae23aab23e88
|
||||
Subproject commit 230c68bc1e08f5f3228384a28cc228c81dfbd10d
|
||||
|
|
@ -1 +1 @@
|
|||
Subproject commit 387392674d74656f7cb437c05a96f0c52ea8e601
|
||||
Subproject commit acd0231ebc74849f6a8907b5e646ce86721aad76
|
||||
|
|
@ -1 +1 @@
|
|||
Subproject commit 8a8918c698534547fa8a1a693cb3e7277f0bfb2f
|
||||
Subproject commit c9d151f9147c4808c77f0375ba3fa5d54443cb9e
|
||||
|
|
@ -5,7 +5,9 @@ use std::{fmt, iter};
|
|||
|
||||
use arrayvec::ArrayVec;
|
||||
use rustc_abi::{ExternAbi, VariantIdx};
|
||||
use rustc_attr_parsing::{AttributeKind, ConstStability, Deprecation, Stability, StableSince};
|
||||
use rustc_attr_data_structures::{
|
||||
AttributeKind, ConstStability, Deprecation, Stability, StableSince,
|
||||
};
|
||||
use rustc_data_structures::fx::{FxHashSet, FxIndexMap, FxIndexSet};
|
||||
use rustc_hir::def::{CtorKind, DefKind, Res};
|
||||
use rustc_hir::def_id::{CrateNum, DefId, LOCAL_CRATE, LocalDefId};
|
||||
|
|
@ -403,13 +405,13 @@ impl Item {
|
|||
// versions; the paths that are exposed through it are "deprecated" because they
|
||||
// were never supposed to work at all.
|
||||
let stab = self.stability(tcx)?;
|
||||
if let rustc_attr_parsing::StabilityLevel::Stable {
|
||||
if let rustc_attr_data_structures::StabilityLevel::Stable {
|
||||
allowed_through_unstable_modules: Some(note),
|
||||
..
|
||||
} = stab.level
|
||||
{
|
||||
Some(Deprecation {
|
||||
since: rustc_attr_parsing::DeprecatedSince::Unspecified,
|
||||
since: rustc_attr_data_structures::DeprecatedSince::Unspecified,
|
||||
note: Some(note),
|
||||
suggestion: None,
|
||||
})
|
||||
|
|
@ -777,9 +779,9 @@ impl Item {
|
|||
// don't want it it `Item::attrs`.
|
||||
None
|
||||
}
|
||||
rustc_hir::Attribute::Parsed(rustc_attr_parsing::AttributeKind::Repr(
|
||||
..,
|
||||
)) => {
|
||||
rustc_hir::Attribute::Parsed(
|
||||
rustc_attr_data_structures::AttributeKind::Repr(..),
|
||||
) => {
|
||||
// We have separate pretty-printing logic for `#[repr(..)]` attributes.
|
||||
// For example, there are circumstances where `#[repr(transparent)]`
|
||||
// is applied but should not be publicly shown in rustdoc
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
use std::mem;
|
||||
|
||||
use rustc_attr_parsing::StabilityLevel;
|
||||
use rustc_attr_data_structures::StabilityLevel;
|
||||
use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexMap, FxIndexSet};
|
||||
use rustc_hir::def_id::{CrateNum, DefId, DefIdMap, DefIdSet};
|
||||
use rustc_middle::ty::{self, TyCtxt};
|
||||
|
|
|
|||
|
|
@ -15,7 +15,7 @@ use std::slice;
|
|||
|
||||
use itertools::Either;
|
||||
use rustc_abi::ExternAbi;
|
||||
use rustc_attr_parsing::{ConstStability, StabilityLevel, StableSince};
|
||||
use rustc_attr_data_structures::{ConstStability, StabilityLevel, StableSince};
|
||||
use rustc_data_structures::fx::FxHashSet;
|
||||
use rustc_hir as hir;
|
||||
use rustc_hir::def::DefKind;
|
||||
|
|
|
|||
|
|
@ -49,7 +49,7 @@ use std::{fs, str};
|
|||
|
||||
use askama::Template;
|
||||
use itertools::Either;
|
||||
use rustc_attr_parsing::{
|
||||
use rustc_attr_data_structures::{
|
||||
ConstStability, DeprecatedSince, Deprecation, RustcVersion, StabilityLevel, StableSince,
|
||||
};
|
||||
use rustc_data_structures::fx::{FxHashSet, FxIndexMap, FxIndexSet};
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@
|
|||
|
||||
use rustc_abi::ExternAbi;
|
||||
use rustc_ast::ast;
|
||||
use rustc_attr_parsing::DeprecatedSince;
|
||||
use rustc_attr_data_structures::{self as attrs, DeprecatedSince};
|
||||
use rustc_hir::def::CtorKind;
|
||||
use rustc_hir::def_id::DefId;
|
||||
use rustc_metadata::rendered_const;
|
||||
|
|
@ -153,8 +153,8 @@ where
|
|||
}
|
||||
}
|
||||
|
||||
pub(crate) fn from_deprecation(deprecation: rustc_attr_parsing::Deprecation) -> Deprecation {
|
||||
let rustc_attr_parsing::Deprecation { since, note, suggestion: _ } = deprecation;
|
||||
pub(crate) fn from_deprecation(deprecation: attrs::Deprecation) -> Deprecation {
|
||||
let attrs::Deprecation { since, note, suggestion: _ } = deprecation;
|
||||
let since = match since {
|
||||
DeprecatedSince::RustcVersion(version) => Some(version.to_string()),
|
||||
DeprecatedSince::Future => Some("TBD".to_owned()),
|
||||
|
|
|
|||
|
|
@ -36,6 +36,7 @@ extern crate pulldown_cmark;
|
|||
extern crate rustc_abi;
|
||||
extern crate rustc_ast;
|
||||
extern crate rustc_ast_pretty;
|
||||
extern crate rustc_attr_data_structures;
|
||||
extern crate rustc_attr_parsing;
|
||||
extern crate rustc_data_structures;
|
||||
extern crate rustc_driver;
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@
|
|||
//! [`core::error`] module is marked as stable since 1.81.0, so we want to show
|
||||
//! [`core::error::Error`] as stable since 1.81.0 as well.
|
||||
|
||||
use rustc_attr_parsing::{Stability, StabilityLevel};
|
||||
use rustc_attr_data_structures::{Stability, StabilityLevel};
|
||||
use rustc_hir::def_id::CRATE_DEF_ID;
|
||||
|
||||
use crate::clean::{Crate, Item, ItemId, ItemKind};
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue