From f7022180b6bb33860486d37e09898ff5048275bb Mon Sep 17 00:00:00 2001 From: "Felix S. Klock II" Date: Fri, 3 Apr 2015 02:51:38 +0200 Subject: [PATCH 01/25] Check for shadowing between lifetimes and loop labels in function bodies. Note: this Warns rather than error on shadowing problems involving labels. We took this more conservative option mostly due to issues with hygiene being broken for labels and/or lifetimes. Add FIXME regarding non-hygienic comparison. --- src/librustc/middle/resolve_lifetime.rs | 213 ++++++++++++++++++++++-- 1 file changed, 201 insertions(+), 12 deletions(-) diff --git a/src/librustc/middle/resolve_lifetime.rs b/src/librustc/middle/resolve_lifetime.rs index a9da92a768fe6..6f40e17855a78 100644 --- a/src/librustc/middle/resolve_lifetime.rs +++ b/src/librustc/middle/resolve_lifetime.rs @@ -24,6 +24,7 @@ use middle::region; use middle::subst; use middle::ty; use std::fmt; +use std::mem::replace; use syntax::ast; use syntax::codemap::Span; use syntax::parse::token::special_idents; @@ -70,6 +71,9 @@ struct LifetimeContext<'a> { // I'm sorry. trait_ref_hack: bool, + + // List of labels in the function/method currently under analysis. + labels_in_fn: Vec<(ast::Ident, Span)>, } enum ScopeChain<'a> { @@ -97,6 +101,7 @@ pub fn krate(sess: &Session, krate: &ast::Crate, def_map: &DefMap) -> NamedRegio scope: &ROOT_SCOPE, def_map: def_map, trait_ref_hack: false, + labels_in_fn: vec![], }, krate); sess.abort_if_errors(); named_region_map @@ -104,6 +109,10 @@ pub fn krate(sess: &Session, krate: &ast::Crate, def_map: &DefMap) -> NamedRegio impl<'a, 'v> Visitor<'v> for LifetimeContext<'a> { fn visit_item(&mut self, item: &ast::Item) { + // Items save/restore the set of labels. This way innner items + // can freely reuse names, be they loop labels or lifetimes. + let saved = replace(&mut self.labels_in_fn, vec![]); + // Items always introduce a new root scope self.with(RootScope, |_, this| { match item.node { @@ -137,6 +146,9 @@ impl<'a, 'v> Visitor<'v> for LifetimeContext<'a> { } } }); + + // Done traversing the item; restore saved set of labels. + replace(&mut self.labels_in_fn, saved); } fn visit_fn(&mut self, fk: visit::FnKind<'v>, fd: &'v ast::FnDecl, @@ -144,16 +156,16 @@ impl<'a, 'v> Visitor<'v> for LifetimeContext<'a> { match fk { visit::FkItemFn(_, generics, _, _, _) => { self.visit_early_late(subst::FnSpace, generics, |this| { - visit::walk_fn(this, fk, fd, b, s) + this.walk_fn(fk, fd, b, s) }) } visit::FkMethod(_, sig, _) => { self.visit_early_late(subst::FnSpace, &sig.generics, |this| { - visit::walk_fn(this, fk, fd, b, s) + this.walk_fn(fk, fd, b, s) }) } visit::FkFnBlock(..) => { - visit::walk_fn(self, fk, fd, b, s) + self.walk_fn(fk, fd, b, s) } } } @@ -190,6 +202,10 @@ impl<'a, 'v> Visitor<'v> for LifetimeContext<'a> { } fn visit_trait_item(&mut self, trait_item: &ast::TraitItem) { + // We reset the labels on every trait item, so that different + // methods in an impl can reuse label names. + let saved = replace(&mut self.labels_in_fn, vec![]); + if let ast::MethodTraitItem(ref sig, None) = trait_item.node { self.visit_early_late( subst::FnSpace, &sig.generics, @@ -197,6 +213,8 @@ impl<'a, 'v> Visitor<'v> for LifetimeContext<'a> { } else { visit::walk_trait_item(self, trait_item); } + + replace(&mut self.labels_in_fn, saved); } fn visit_block(&mut self, b: &ast::Block) { @@ -286,7 +304,170 @@ impl<'a, 'v> Visitor<'v> for LifetimeContext<'a> { } } +#[derive(Copy, Clone, PartialEq)] +enum ShadowKind { Label, Lifetime } +struct Original { kind: ShadowKind, span: Span } +struct Shadower { kind: ShadowKind, span: Span } + +fn original_label(span: Span) -> Original { + Original { kind: ShadowKind::Label, span: span } +} +fn shadower_label(span: Span) -> Shadower { + Shadower { kind: ShadowKind::Label, span: span } +} +fn original_lifetime(l: &ast::Lifetime) -> Original { + Original { kind: ShadowKind::Lifetime, span: l.span } +} +fn shadower_lifetime(l: &ast::Lifetime) -> Shadower { + Shadower { kind: ShadowKind::Lifetime, span: l.span } +} + +impl ShadowKind { + fn desc(&self) -> &'static str { + match *self { + ShadowKind::Label => "label", + ShadowKind::Lifetime => "lifetime", + } + } +} + +fn signal_shadowing_problem( + sess: &Session, name: ast::Name, orig: Original, shadower: Shadower) { + if let (ShadowKind::Lifetime, ShadowKind::Lifetime) = (orig.kind, shadower.kind) { + // lifetime/lifetime shadowing is an error + sess.span_err(shadower.span, + &format!("{} name `{}` shadows a \ + {} name that is already in scope", + shadower.kind.desc(), name, orig.kind.desc())); + } else { + // shadowing involving a label is only a warning, due to issues with + // labels and lifetimes not being macro-hygienic. + sess.span_warn(shadower.span, + &format!("{} name `{}` shadows a \ + {} name that is already in scope", + shadower.kind.desc(), name, orig.kind.desc())); + } + sess.span_note(orig.span, + &format!("shadowed {} `{}` declared here", + orig.kind.desc(), name)); +} + +// Adds all labels in `b` to `ctxt.labels_in_fn`, signalling a warning +// if one of the label shadows a lifetime or another label. +fn extract_labels<'v, 'a>(ctxt: &mut LifetimeContext<'a>, b: &'v ast::Block) { + + struct GatherLabels<'a> { + sess: &'a Session, + scope: Scope<'a>, + labels_in_fn: &'a mut Vec<(ast::Ident, Span)>, + } + + let mut gather = GatherLabels { + sess: ctxt.sess, + scope: ctxt.scope, + labels_in_fn: &mut ctxt.labels_in_fn, + }; + gather.visit_block(b); + return; + + impl<'v, 'a> Visitor<'v> for GatherLabels<'a> { + fn visit_expr(&mut self, ex: &'v ast::Expr) { + if let Some(label) = expression_label(ex) { + for &(prior, prior_span) in &self.labels_in_fn[..] { + // FIXME (#24278): non-hygienic comparision + if label.name == prior.name { + signal_shadowing_problem(self.sess, + label.name, + original_label(prior_span), + shadower_label(ex.span)); + } + } + + check_if_label_shadows_lifetime(self.sess, + self.scope, + label, + ex.span); + + self.labels_in_fn.push((label, ex.span)); + } + visit::walk_expr(self, ex) + } + + fn visit_item(&mut self, _: &ast::Item) { + // do not recurse into items defined in the block + } + } + + fn expression_label(ex: &ast::Expr) -> Option { + match ex.node { + ast::ExprWhile(_, _, Some(label)) | + ast::ExprWhileLet(_, _, _, Some(label)) | + ast::ExprForLoop(_, _, _, Some(label)) | + ast::ExprLoop(_, Some(label)) => Some(label), + _ => None, + } + } + + fn check_if_label_shadows_lifetime<'a>(sess: &'a Session, + mut scope: Scope<'a>, + label: ast::Ident, + label_span: Span) { + loop { + match *scope { + BlockScope(_, s) => { scope = s; } + RootScope => { return; } + + EarlyScope(_, lifetimes, s) | + LateScope(lifetimes, s) => { + for lifetime_def in lifetimes { + // FIXME (#24278): non-hygienic comparision + if label.name == lifetime_def.lifetime.name { + signal_shadowing_problem( + sess, + label.name, + original_lifetime(&lifetime_def.lifetime), + shadower_label(label_span)); + return; + } + } + scope = s; + } + } + } + } +} + impl<'a> LifetimeContext<'a> { + // This is just like visit::walk_fn, except that it extracts the + // labels of the function body and swaps them in before visiting + // the function body itself. + fn walk_fn<'b>(&mut self, + fk: visit::FnKind, + fd: &ast::FnDecl, + fb: &'b ast::Block, + _span: Span) { + match fk { + visit::FkItemFn(_, generics, _, _, _) => { + visit::walk_fn_decl(self, fd); + self.visit_generics(generics); + } + visit::FkMethod(_, sig, _) => { + visit::walk_fn_decl(self, fd); + self.visit_generics(&sig.generics); + self.visit_explicit_self(&sig.explicit_self); + } + visit::FkFnBlock(..) => { + visit::walk_fn_decl(self, fd); + } + } + + // After inpsecting the decl, add all labels from the body to + // `self.labels_in_fn`. + extract_labels(self, fb); + + self.visit_block(fb); + } + fn with(&mut self, wrap_scope: ScopeChain, f: F) where F: FnOnce(Scope, &mut LifetimeContext), { @@ -297,6 +478,7 @@ impl<'a> LifetimeContext<'a> { scope: &wrap_scope, def_map: self.def_map, trait_ref_hack: self.trait_ref_hack, + labels_in_fn: self.labels_in_fn.clone(), }; debug!("entering scope {:?}", this.scope); f(self.scope, &mut this); @@ -494,6 +676,17 @@ impl<'a> LifetimeContext<'a> { mut old_scope: Scope, lifetime: &ast::Lifetime) { + for &(label, label_span) in &self.labels_in_fn { + // FIXME (#24278): non-hygienic comparision + if lifetime.name == label.name { + signal_shadowing_problem(self.sess, + lifetime.name, + original_label(label_span), + shadower_lifetime(&lifetime)); + return; + } + } + loop { match *old_scope { BlockScope(_, s) => { @@ -507,15 +700,11 @@ impl<'a> LifetimeContext<'a> { EarlyScope(_, lifetimes, s) | LateScope(lifetimes, s) => { if let Some((_, lifetime_def)) = search_lifetimes(lifetimes, lifetime) { - self.sess.span_err( - lifetime.span, - &format!("lifetime name `{}` shadows another \ - lifetime name that is already in scope", - token::get_name(lifetime.name))); - self.sess.span_note( - lifetime_def.span, - &format!("shadowed lifetime `{}` declared here", - token::get_name(lifetime.name))); + signal_shadowing_problem( + self.sess, + lifetime.name, + original_lifetime(&lifetime_def), + shadower_lifetime(&lifetime)); return; } From b2ac06f25053eefd4213bef3b510d051212bafbb Mon Sep 17 00:00:00 2001 From: "Felix S. Klock II" Date: Wed, 8 Apr 2015 18:37:47 +0200 Subject: [PATCH 02/25] Tests for shadowing between lifetimes and loop labels within function bodies. --- .../compile-fail/loop-labeled-break-value.rs | 2 +- .../loops-reject-duplicate-labels-2.rs | 51 ++++++++ .../loops-reject-duplicate-labels.rs | 60 +++++++++ ...loops-reject-labels-shadowing-lifetimes.rs | 120 ++++++++++++++++++ .../loops-reject-lifetime-shadowing-label.rs | 41 ++++++ src/test/compile-fail/shadowed-lifetime.rs | 4 +- 6 files changed, 275 insertions(+), 3 deletions(-) create mode 100644 src/test/compile-fail/loops-reject-duplicate-labels-2.rs create mode 100644 src/test/compile-fail/loops-reject-duplicate-labels.rs create mode 100644 src/test/compile-fail/loops-reject-labels-shadowing-lifetimes.rs create mode 100644 src/test/compile-fail/loops-reject-lifetime-shadowing-label.rs diff --git a/src/test/compile-fail/loop-labeled-break-value.rs b/src/test/compile-fail/loop-labeled-break-value.rs index e1ae3ae464f98..f0792c145d2a2 100644 --- a/src/test/compile-fail/loop-labeled-break-value.rs +++ b/src/test/compile-fail/loop-labeled-break-value.rs @@ -16,6 +16,6 @@ fn main() { let _: i32 = 'inner: loop { break 'inner }; //~ ERROR mismatched types } loop { - let _: i32 = 'inner: loop { loop { break 'inner } }; //~ ERROR mismatched types + let _: i32 = 'inner2: loop { loop { break 'inner2 } }; //~ ERROR mismatched types } } diff --git a/src/test/compile-fail/loops-reject-duplicate-labels-2.rs b/src/test/compile-fail/loops-reject-duplicate-labels-2.rs new file mode 100644 index 0000000000000..68627ecaa718f --- /dev/null +++ b/src/test/compile-fail/loops-reject-duplicate-labels-2.rs @@ -0,0 +1,51 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![feature(rustc_attrs)] + +// ignore-tidy-linelength + +// Issue #21633: reject duplicate loop labels in function bodies. +// +// This is testing the generalization (to the whole function body) +// discussed here: +// http://internals.rust-lang.org/t/psa-rejecting-duplicate-loop-labels/1833 + +pub fn foo() { + { 'fl: for _ in 0..10 { break; } } //~ NOTE shadowed label `'fl` declared here + { 'fl: loop { break; } } //~ WARN label name `'fl` shadows a label name that is already in scope + + { 'lf: loop { break; } } //~ NOTE shadowed label `'lf` declared here + { 'lf: for _ in 0..10 { break; } } //~ WARN label name `'lf` shadows a label name that is already in scope + + { 'wl: while 2 > 1 { break; } } //~ NOTE shadowed label `'wl` declared here + { 'wl: loop { break; } } //~ WARN label name `'wl` shadows a label name that is already in scope + + { 'lw: loop { break; } } //~ NOTE shadowed label `'lw` declared here + { 'lw: while 2 > 1 { break; } } //~ WARN label name `'lw` shadows a label name that is already in scope + + { 'fw: for _ in 0..10 { break; } } //~ NOTE shadowed label `'fw` declared here + { 'fw: while 2 > 1 { break; } } //~ WARN label name `'fw` shadows a label name that is already in scope + + { 'wf: while 2 > 1 { break; } } //~ NOTE shadowed label `'wf` declared here + { 'wf: for _ in 0..10 { break; } } //~ WARN label name `'wf` shadows a label name that is already in scope + + { 'tl: while let Some(_) = None:: { break; } } //~ NOTE shadowed label `'tl` declared here + { 'tl: loop { break; } } //~ WARN label name `'tl` shadows a label name that is already in scope + + { 'lt: loop { break; } } //~ NOTE shadowed label `'lt` declared here + { 'lt: while let Some(_) = None:: { break; } } + //~^ WARN label name `'lt` shadows a label name that is already in scope +} + +#[rustc_error] +pub fn main() { //~ ERROR compilation successful + foo(); +} diff --git a/src/test/compile-fail/loops-reject-duplicate-labels.rs b/src/test/compile-fail/loops-reject-duplicate-labels.rs new file mode 100644 index 0000000000000..15446bf642d4d --- /dev/null +++ b/src/test/compile-fail/loops-reject-duplicate-labels.rs @@ -0,0 +1,60 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![feature(rustc_attrs)] + +// ignore-tidy-linelength + +// Issue #21633: reject duplicate loop labels in function bodies. +// This is testing the exact cases that are in the issue description. + +fn foo() { + 'fl: for _ in 0..10 { break; } //~ NOTE shadowed label `'fl` declared here + 'fl: loop { break; } //~ WARN label name `'fl` shadows a label name that is already in scope + + 'lf: loop { break; } //~ NOTE shadowed label `'lf` declared here + 'lf: for _ in 0..10 { break; } //~ WARN label name `'lf` shadows a label name that is already in scope + + 'wl: while 2 > 1 { break; } //~ NOTE shadowed label `'wl` declared here + 'wl: loop { break; } //~ WARN label name `'wl` shadows a label name that is already in scope + + 'lw: loop { break; } //~ NOTE shadowed label `'lw` declared here + 'lw: while 2 > 1 { break; } //~ WARN label name `'lw` shadows a label name that is already in scope + + 'fw: for _ in 0..10 { break; } //~ NOTE shadowed label `'fw` declared here + 'fw: while 2 > 1 { break; } //~ WARN label name `'fw` shadows a label name that is already in scope + + 'wf: while 2 > 1 { break; } //~ NOTE shadowed label `'wf` declared here + 'wf: for _ in 0..10 { break; } //~ WARN label name `'wf` shadows a label name that is already in scope + + 'tl: while let Some(_) = None:: { break; } //~ NOTE shadowed label `'tl` declared here + 'tl: loop { break; } //~ WARN label name `'tl` shadows a label name that is already in scope + + 'lt: loop { break; } //~ NOTE shadowed label `'lt` declared here + 'lt: while let Some(_) = None:: { break; } + //~^ WARN label name `'lt` shadows a label name that is already in scope +} + +// Note however that it is okay for the same label to be reused in +// different methods of one impl, as illustrated here. + +struct S; +impl S { + fn m1(&self) { 'okay: loop { break 'okay; } } + fn m2(&self) { 'okay: loop { break 'okay; } } +} + +#[rustc_error] +pub fn main() { //~ ERROR compilation successful + let s = S; + s.m1(); + s.m2(); + foo(); +} diff --git a/src/test/compile-fail/loops-reject-labels-shadowing-lifetimes.rs b/src/test/compile-fail/loops-reject-labels-shadowing-lifetimes.rs new file mode 100644 index 0000000000000..bbdd0774ed936 --- /dev/null +++ b/src/test/compile-fail/loops-reject-labels-shadowing-lifetimes.rs @@ -0,0 +1,120 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// Issue #21633: reject duplicate loop labels in function bodies. +// This is testing interaction between lifetime-params and labels. + +#![feature(rustc_attrs)] + +#![allow(dead_code, unused_variables)] + +fn foo() { + fn foo<'a>() { //~ NOTE shadowed lifetime `'a` declared here + 'a: loop { break 'a; } + //~^ WARN label name `'a` shadows a lifetime name that is already in scope + } + + struct Struct<'b, 'c> { _f: &'b i8, _g: &'c i8 } + enum Enum<'d, 'e> { A(&'d i8), B(&'e i8) } + + impl<'d, 'e> Struct<'d, 'e> { + fn meth_okay() { + 'a: loop { break 'a; } + 'b: loop { break 'b; } + 'c: loop { break 'c; } + } + } + + impl <'d, 'e> Enum<'d, 'e> { + fn meth_okay() { + 'a: loop { break 'a; } + 'b: loop { break 'b; } + 'c: loop { break 'c; } + } + } + + impl<'bad, 'c> Struct<'bad, 'c> { //~ NOTE shadowed lifetime `'bad` declared here + fn meth_bad(&self) { + 'bad: loop { break 'bad; } + //~^ WARN label name `'bad` shadows a lifetime name that is already in scope + } + } + + impl<'b, 'bad> Struct<'b, 'bad> { //~ NOTE shadowed lifetime `'bad` declared here + fn meth_bad2(&self) { + 'bad: loop { break 'bad; } + //~^ WARN label name `'bad` shadows a lifetime name that is already in scope + } + } + + impl<'b, 'c> Struct<'b, 'c> { + fn meth_bad3<'bad>(x: &'bad i8) { //~ NOTE shadowed lifetime `'bad` declared here + 'bad: loop { break 'bad; } + //~^ WARN label name `'bad` shadows a lifetime name that is already in scope + } + + fn meth_bad4<'a,'bad>(x: &'a i8, y: &'bad i8) { + //~^ NOTE shadowed lifetime `'bad` declared here + 'bad: loop { break 'bad; } + //~^ WARN label name `'bad` shadows a lifetime name that is already in scope + } + } + + impl <'bad, 'e> Enum<'bad, 'e> { //~ NOTE shadowed lifetime `'bad` declared here + fn meth_bad(&self) { + 'bad: loop { break 'bad; } + //~^ WARN label name `'bad` shadows a lifetime name that is already in scope + } + } + impl <'d, 'bad> Enum<'d, 'bad> { //~ NOTE shadowed lifetime `'bad` declared here + fn meth_bad2(&self) { + 'bad: loop { break 'bad; } + //~^ WARN label name `'bad` shadows a lifetime name that is already in scope + } + } + impl <'d, 'e> Enum<'d, 'e> { + fn meth_bad3<'bad>(x: &'bad i8) { //~ NOTE shadowed lifetime `'bad` declared here + 'bad: loop { break 'bad; } + //~^ WARN label name `'bad` shadows a lifetime name that is already in scope + } + + fn meth_bad4<'a,'bad>(x: &'bad i8) { //~ NOTE shadowed lifetime `'bad` declared here + 'bad: loop { break 'bad; } + //~^ WARN label name `'bad` shadows a lifetime name that is already in scope + } + } + + trait HasDefaultMethod1<'bad> { //~ NOTE shadowed lifetime `'bad` declared here + fn meth_okay() { + 'c: loop { break 'c; } + } + fn meth_bad(&self) { + 'bad: loop { break 'bad; } + //~^ WARN label name `'bad` shadows a lifetime name that is already in scope + } + } + trait HasDefaultMethod2<'a,'bad> { //~ NOTE shadowed lifetime `'bad` declared here + fn meth_bad(&self) { + 'bad: loop { break 'bad; } + //~^ WARN label name `'bad` shadows a lifetime name that is already in scope + } + } + trait HasDefaultMethod3<'a,'b> { + fn meth_bad<'bad>(&self) { //~ NOTE shadowed lifetime `'bad` declared here + 'bad: loop { break 'bad; } + //~^ WARN label name `'bad` shadows a lifetime name that is already in scope + } + } +} + +#[rustc_error] +pub fn main() { //~ ERROR compilation successful + foo(); +} diff --git a/src/test/compile-fail/loops-reject-lifetime-shadowing-label.rs b/src/test/compile-fail/loops-reject-lifetime-shadowing-label.rs new file mode 100644 index 0000000000000..2344d251c9a69 --- /dev/null +++ b/src/test/compile-fail/loops-reject-lifetime-shadowing-label.rs @@ -0,0 +1,41 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![feature(rustc_attrs)] + +#![allow(dead_code, unused_variables)] + +// Issue #21633: reject duplicate loop labels in function bodies. +// +// Test rejection of lifetimes in *expressions* that shadow loop labels. + +fn foo() { + // Reusing lifetime `'a` in function item is okay. + fn foo<'a>(x: &'a i8) -> i8 { *x } + + // So is reusing `'a` in struct item + struct S1<'a> { x: &'a i8 } impl<'a> S1<'a> { fn m(&self) {} } + // and a method item + struct S2; impl S2 { fn m<'a>(&self) {} } + + let z = 3_i8; + + 'a: loop { //~ NOTE shadowed label `'a` declared here + let b = Box::new(|x: &i8| *x) as Box Fn(&'a i8) -> i8>; + //~^ WARN lifetime name `'a` shadows a label name that is already in scope + assert_eq!((*b)(&z), z); + break 'a; + } +} + +#[rustc_error] +pub fn main() { //~ ERROR compilation successful + foo(); +} diff --git a/src/test/compile-fail/shadowed-lifetime.rs b/src/test/compile-fail/shadowed-lifetime.rs index 110b1a0d90c22..8cbab5f830809 100644 --- a/src/test/compile-fail/shadowed-lifetime.rs +++ b/src/test/compile-fail/shadowed-lifetime.rs @@ -15,14 +15,14 @@ struct Foo<'a>(&'a isize); impl<'a> Foo<'a> { //~^ NOTE shadowed lifetime `'a` declared here fn shadow_in_method<'a>(&'a self) -> &'a isize { - //~^ ERROR lifetime name `'a` shadows another lifetime name that is already in scope + //~^ ERROR lifetime name `'a` shadows a lifetime name that is already in scope self.0 } fn shadow_in_type<'b>(&'b self) -> &'b isize { //~^ NOTE shadowed lifetime `'b` declared here let x: for<'b> fn(&'b isize) = panic!(); - //~^ ERROR lifetime name `'b` shadows another lifetime name that is already in scope + //~^ ERROR lifetime name `'b` shadows a lifetime name that is already in scope self.0 } From f1585abdac108810c5079d269d24f2794c221d4c Mon Sep 17 00:00:00 2001 From: "Felix S. Klock II" Date: Tue, 21 Apr 2015 09:58:06 +0200 Subject: [PATCH 03/25] add notes clarifying introduction of warnings for a pair of run-pass tests. --- src/test/run-pass/hygienic-labels-in-let.rs | 8 ++++++++ src/test/run-pass/hygienic-labels.rs | 5 +++++ 2 files changed, 13 insertions(+) diff --git a/src/test/run-pass/hygienic-labels-in-let.rs b/src/test/run-pass/hygienic-labels-in-let.rs index 589d6e1581bde..5b45f1e0d3928 100644 --- a/src/test/run-pass/hygienic-labels-in-let.rs +++ b/src/test/run-pass/hygienic-labels-in-let.rs @@ -10,6 +10,14 @@ // ignore-pretty: pprust doesn't print hygiene output +// Test that labels injected by macros do not break hygiene. This +// checks cases where the macros invocations are under the rhs of a +// let statement. + +// Issue #24278: The label/lifetime shadowing checker from #24162 +// conservatively ignores hygiene, and thus issues warnings that are +// both true- and false-positives for this test. + macro_rules! loop_x { ($e: expr) => { // $e shouldn't be able to interact with this 'x diff --git a/src/test/run-pass/hygienic-labels.rs b/src/test/run-pass/hygienic-labels.rs index df72a5410a2b2..a5882f022920f 100644 --- a/src/test/run-pass/hygienic-labels.rs +++ b/src/test/run-pass/hygienic-labels.rs @@ -8,6 +8,11 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// Test that labels injected by macros do not break hygiene. + +// Issue #24278: The label/lifetime shadowing checker from #24162 +// conservatively ignores hygiene, and thus issues warnings that are +// both true- and false-positives for this test. macro_rules! loop_x { ($e: expr) => { From dd90a5bb976948b58946342ad308f18af13c1a5d Mon Sep 17 00:00:00 2001 From: "Felix S. Klock II" Date: Tue, 14 Apr 2015 08:42:48 +0200 Subject: [PATCH 04/25] typeck: Do high-level structural/signature checks before function body checks. This avoids various ICEs, e.g. premature calls to cat_expr that yield the dreaded "cat_expr Errd" ICE. --- src/librustc_typeck/check/mod.rs | 115 +++++++++++++++++++------------ 1 file changed, 71 insertions(+), 44 deletions(-) diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index 2830090e09871..bff8e002a0af7 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -441,10 +441,11 @@ fn static_inherited_fields<'a, 'tcx>(ccx: &'a CrateCtxt<'a, 'tcx>) } struct CheckItemTypesVisitor<'a, 'tcx: 'a> { ccx: &'a CrateCtxt<'a, 'tcx> } +struct CheckItemBodiesVisitor<'a, 'tcx: 'a> { ccx: &'a CrateCtxt<'a, 'tcx> } impl<'a, 'tcx> Visitor<'tcx> for CheckItemTypesVisitor<'a, 'tcx> { fn visit_item(&mut self, i: &'tcx ast::Item) { - check_item(self.ccx, i); + check_item_type(self.ccx, i); visit::walk_item(self, i); } @@ -460,6 +461,13 @@ impl<'a, 'tcx> Visitor<'tcx> for CheckItemTypesVisitor<'a, 'tcx> { } } +impl<'a, 'tcx> Visitor<'tcx> for CheckItemBodiesVisitor<'a, 'tcx> { + fn visit_item(&mut self, i: &'tcx ast::Item) { + check_item_body(self.ccx, i); + visit::walk_item(self, i); + } +} + pub fn check_item_types(ccx: &CrateCtxt) { let krate = ccx.tcx.map.krate(); let mut visit = wf::CheckTypeWellFormedVisitor::new(ccx); @@ -474,6 +482,11 @@ pub fn check_item_types(ccx: &CrateCtxt) { ccx.tcx.sess.abort_if_errors(); + let mut visit = CheckItemBodiesVisitor { ccx: ccx }; + visit::walk_crate(&mut visit, krate); + + ccx.tcx.sess.abort_if_errors(); + for drop_method_did in ccx.tcx.destructors.borrow().iter() { if drop_method_did.krate == ast::LOCAL_CRATE { let drop_impl_did = ccx.tcx.map.get_parent_did(drop_method_did.node); @@ -713,13 +726,13 @@ pub fn check_struct(ccx: &CrateCtxt, id: ast::NodeId, span: Span) { } } -pub fn check_item<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>, it: &'tcx ast::Item) { - debug!("check_item(it.id={}, it.ident={})", +pub fn check_item_type<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>, it: &'tcx ast::Item) { + debug!("check_item_type(it.id={}, it.ident={})", it.id, ty::item_path_str(ccx.tcx, local_def(it.id))); let _indenter = indenter(); - match it.node { + // Consts can play a role in type-checking, so they are included here. ast::ItemStatic(_, _, ref e) | ast::ItemConst(_, ref e) => check_const(ccx, it.span, &**e, it.id), ast::ItemEnum(ref enum_definition, _) => { @@ -728,16 +741,9 @@ pub fn check_item<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>, it: &'tcx ast::Item) { &enum_definition.variants, it.id); } - ast::ItemFn(ref decl, _, _, _, ref body) => { - let fn_pty = ty::lookup_item_type(ccx.tcx, ast_util::local_def(it.id)); - let param_env = ParameterEnvironment::for_item(ccx.tcx, it.id); - check_bare_fn(ccx, &**decl, &**body, it.id, it.span, fn_pty.ty, param_env); - } + ast::ItemFn(_, _, _, _, _) => {} // entirely within check_item_body ast::ItemImpl(_, _, _, _, _, ref impl_items) => { - debug!("ItemImpl {} with id {}", token::get_ident(it.ident), it.id); - - let impl_pty = ty::lookup_item_type(ccx.tcx, ast_util::local_def(it.id)); - + debug!("ItemImpl {} with id {}", token::get_ident(it.ident), it.id); match ty::impl_trait_ref(ccx.tcx, local_def(it.id)) { Some(impl_trait_ref) => { check_impl_items_against_trait(ccx, @@ -747,39 +753,9 @@ pub fn check_item<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>, it: &'tcx ast::Item) { } None => { } } - - for impl_item in impl_items { - match impl_item.node { - ast::MethodImplItem(ref sig, ref body) => { - check_method_body(ccx, &impl_pty.generics, sig, body, - impl_item.id, impl_item.span); - } - ast::TypeImplItem(_) | - ast::MacImplItem(_) => { - // Nothing to do here. - } - } - } - } - ast::ItemTrait(_, ref generics, _, ref trait_items) => { + ast::ItemTrait(_, ref generics, _, _) => { check_trait_on_unimplemented(ccx, generics, it); - let trait_def = ty::lookup_trait_def(ccx.tcx, local_def(it.id)); - for trait_item in trait_items { - match trait_item.node { - ast::MethodTraitItem(_, None) => { - // Nothing to do, since required methods don't have - // bodies to check. - } - ast::MethodTraitItem(ref sig, Some(ref body)) => { - check_method_body(ccx, &trait_def.generics, sig, body, - trait_item.id, trait_item.span); - } - ast::TypeTraitItem(..) => { - // Nothing to do. - } - } - } } ast::ItemStruct(..) => { check_struct(ccx, it.id, it.span); @@ -814,6 +790,57 @@ pub fn check_item<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>, it: &'tcx ast::Item) { } } +pub fn check_item_body<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>, it: &'tcx ast::Item) { + debug!("check_item_body(it.id={}, it.ident={})", + it.id, + ty::item_path_str(ccx.tcx, local_def(it.id))); + let _indenter = indenter(); + match it.node { + ast::ItemFn(ref decl, _, _, _, ref body) => { + let fn_pty = ty::lookup_item_type(ccx.tcx, ast_util::local_def(it.id)); + let param_env = ParameterEnvironment::for_item(ccx.tcx, it.id); + check_bare_fn(ccx, &**decl, &**body, it.id, it.span, fn_pty.ty, param_env); + } + ast::ItemImpl(_, _, _, _, _, ref impl_items) => { + debug!("ItemImpl {} with id {}", token::get_ident(it.ident), it.id); + + let impl_pty = ty::lookup_item_type(ccx.tcx, ast_util::local_def(it.id)); + + for impl_item in impl_items { + match impl_item.node { + ast::MethodImplItem(ref sig, ref body) => { + check_method_body(ccx, &impl_pty.generics, sig, body, + impl_item.id, impl_item.span); + } + ast::TypeImplItem(_) | + ast::MacImplItem(_) => { + // Nothing to do here. + } + } + } + } + ast::ItemTrait(_, _, _, ref trait_items) => { + let trait_def = ty::lookup_trait_def(ccx.tcx, local_def(it.id)); + for trait_item in trait_items { + match trait_item.node { + ast::MethodTraitItem(_, None) => { + // Nothing to do, since required methods don't have + // bodies to check. + } + ast::MethodTraitItem(ref sig, Some(ref body)) => { + check_method_body(ccx, &trait_def.generics, sig, body, + trait_item.id, trait_item.span); + } + ast::TypeTraitItem(..) => { + // Nothing to do. + } + } + } + } + _ => {/* nothing to do */ } + } +} + fn check_trait_on_unimplemented<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, generics: &ast::Generics, item: &ast::Item) { From 727b72cd38d919a4183a157f3e7ce44d1e6e1958 Mon Sep 17 00:00:00 2001 From: "Felix S. Klock II" Date: Tue, 14 Apr 2015 12:49:26 +0200 Subject: [PATCH 05/25] Regression tests for issues that led me to revise typeck. Close #23729 Close #23827 Close #24356 --- src/test/compile-fail/issue-23729.rs | 43 ++++++++++++++++++++++++++++ src/test/compile-fail/issue-23827.rs | 43 ++++++++++++++++++++++++++++ src/test/compile-fail/issue-24356.rs | 40 ++++++++++++++++++++++++++ 3 files changed, 126 insertions(+) create mode 100644 src/test/compile-fail/issue-23729.rs create mode 100644 src/test/compile-fail/issue-23827.rs create mode 100644 src/test/compile-fail/issue-24356.rs diff --git a/src/test/compile-fail/issue-23729.rs b/src/test/compile-fail/issue-23729.rs new file mode 100644 index 0000000000000..3d77d171acebf --- /dev/null +++ b/src/test/compile-fail/issue-23729.rs @@ -0,0 +1,43 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// Regression test for #23729 + +fn main() { + let fib = { + struct Recurrence { + mem: [u64; 2], + pos: usize, + } + + impl Iterator for Recurrence { + //~^ ERROR not all trait items implemented, missing: `Item` [E0046] + #[inline] + fn next(&mut self) -> Option { + if self.pos < 2 { + let next_val = self.mem[self.pos]; + self.pos += 1; + Some(next_val) + } else { + let next_val = (self.mem[0] + self.mem[1]); + self.mem[0] = self.mem[1]; + self.mem[1] = next_val; + Some(next_val) + } + } + } + + Recurrence { mem: [0, 1], pos: 0 } + }; + + for e in fib.take(10) { + println!("{}", e) + } +} diff --git a/src/test/compile-fail/issue-23827.rs b/src/test/compile-fail/issue-23827.rs new file mode 100644 index 0000000000000..6c42c88bee6d0 --- /dev/null +++ b/src/test/compile-fail/issue-23827.rs @@ -0,0 +1,43 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// Regression test for #23827 + +#![feature(core, unboxed_closures)] + +pub struct Prototype { + pub target: u32 +} + +trait Component { + fn apply(self, e: u32); +} + +impl Fn<(C,)> for Prototype { + extern "rust-call" fn call(&self, (comp,): (C,)) -> Prototype { + comp.apply(self.target); + *self + } +} + +impl FnMut<(C,)> for Prototype { + extern "rust-call" fn call_mut(&mut self, (comp,): (C,)) -> Prototype { + Fn::call(*&self, (comp,)) + } +} + +impl FnOnce<(C,)> for Prototype { + //~^ ERROR not all trait items implemented, missing: `Output` [E0046] + extern "rust-call" fn call_once(self, (comp,): (C,)) -> Prototype { + Fn::call(&self, (comp,)) + } +} + +fn main() {} diff --git a/src/test/compile-fail/issue-24356.rs b/src/test/compile-fail/issue-24356.rs new file mode 100644 index 0000000000000..22f71835336fa --- /dev/null +++ b/src/test/compile-fail/issue-24356.rs @@ -0,0 +1,40 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// Regression test for #24356 + +// ignore-tidy-linelength + +fn main() { + { + use std::ops::Deref; + + struct Thing(i8); + + /* + // Correct impl + impl Deref for Thing { + type Target = i8; + fn deref(&self) -> &i8 { &self.0 } + } + */ + + // Causes ICE + impl Deref for Thing { + //~^ ERROR not all trait items implemented, missing: `Target` [E0046] + fn deref(&self) -> i8 { self.0 } + //~^ ERROR method `deref` has an incompatible type for trait: expected &-ptr, found i8 [E0053] + } + + let thing = Thing(72); + + *thing + }; +} From 399b4ccdbd42bcd52620e20846a34be957cbb415 Mon Sep 17 00:00:00 2001 From: "Felix S. Klock II" Date: Tue, 14 Apr 2015 14:23:02 +0200 Subject: [PATCH 06/25] Fallout from this change. --- ...sociated-types-no-suitable-supertrait-2.rs | 31 +++++++++++++ ...associated-types-no-suitable-supertrait.rs | 14 +++++- src/test/compile-fail/enum-to-float-cast-2.rs | 28 ++++++++++++ src/test/compile-fail/enum-to-float-cast.rs | 4 -- src/test/compile-fail/issue-16048.rs | 2 +- src/test/compile-fail/issue-19244-1.rs | 4 +- src/test/compile-fail/issue-19244-2.rs | 4 +- src/test/compile-fail/issue-2063.rs | 5 ++- .../non-constant-expr-for-fixed-len-vec.rs | 2 +- .../compile-fail/struct-base-wrong-type-2.rs | 31 +++++++++++++ .../compile-fail/struct-base-wrong-type.rs | 21 ++++----- src/test/compile-fail/variadic-ffi-3.rs | 43 +++++++++++++++++++ src/test/compile-fail/variadic-ffi.rs | 29 +++++-------- .../wrong-mul-method-signature.rs | 13 ++---- ...ted-types-projection-to-unrelated-trait.rs | 43 +++++++++++++++++++ 15 files changed, 220 insertions(+), 54 deletions(-) create mode 100644 src/test/compile-fail/associated-types-no-suitable-supertrait-2.rs create mode 100644 src/test/compile-fail/enum-to-float-cast-2.rs create mode 100644 src/test/compile-fail/struct-base-wrong-type-2.rs create mode 100644 src/test/compile-fail/variadic-ffi-3.rs create mode 100644 src/test/run-pass/associated-types-projection-to-unrelated-trait.rs diff --git a/src/test/compile-fail/associated-types-no-suitable-supertrait-2.rs b/src/test/compile-fail/associated-types-no-suitable-supertrait-2.rs new file mode 100644 index 0000000000000..5f1cd2444d3c4 --- /dev/null +++ b/src/test/compile-fail/associated-types-no-suitable-supertrait-2.rs @@ -0,0 +1,31 @@ +// Copyright 2014 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// Check that we get an error when you use `::Value` in +// the trait definition but `Self` does not, in fact, implement `Get`. +// +// See also associated-types-no-suitable-supertrait.rs, which checks +// that we see the same error when making this mistake on an impl +// rather than the default method impl. +// +// See also run-pass/associated-types-projection-to-unrelated-trait.rs, +// which checks that the trait interface itself is not considered an +// error as long as all impls satisfy the constraint. + +trait Get : ::std::marker::MarkerTrait { + type Value; +} + +trait Other { + fn uhoh(&self, foo: U, bar: ::Value) {} + //~^ ERROR the trait `Get` is not implemented for the type `Self` +} + +fn main() { } diff --git a/src/test/compile-fail/associated-types-no-suitable-supertrait.rs b/src/test/compile-fail/associated-types-no-suitable-supertrait.rs index 2b84c38f80b54..24429a482057c 100644 --- a/src/test/compile-fail/associated-types-no-suitable-supertrait.rs +++ b/src/test/compile-fail/associated-types-no-suitable-supertrait.rs @@ -10,6 +10,14 @@ // Check that we get an error when you use `::Value` in // the trait definition but `Self` does not, in fact, implement `Get`. +// +// See also associated-types-no-suitable-supertrait-2.rs, which checks +// that we see the same error if we get around to checking the default +// method body. +// +// See also run-pass/associated-types-projection-to-unrelated-trait.rs, +// which checks that the trait interface itself is not considered an +// error as long as all impls satisfy the constraint. trait Get : ::std::marker::MarkerTrait { type Value; @@ -17,13 +25,15 @@ trait Get : ::std::marker::MarkerTrait { trait Other { fn uhoh(&self, foo: U, bar: ::Value) {} - //~^ ERROR the trait `Get` is not implemented for the type `Self` + // (note that we no longer catch the error here, since the + // error below aborts compilation. + // See also associated-types-no-suitable-supertrait-2.rs + // which checks that this error would be caught eventually.) } impl Other for T { fn uhoh(&self, foo: U, bar: <(T, U) as Get>::Value) {} //~^ ERROR the trait `Get` is not implemented for the type `(T, U)` - //~| ERROR the trait `Get` is not implemented for the type `(T, U)` } fn main() { } diff --git a/src/test/compile-fail/enum-to-float-cast-2.rs b/src/test/compile-fail/enum-to-float-cast-2.rs new file mode 100644 index 0000000000000..7ee671317559b --- /dev/null +++ b/src/test/compile-fail/enum-to-float-cast-2.rs @@ -0,0 +1,28 @@ +// Copyright 2012 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// Tests that enum-to-float casts are disallowed. + +enum E { + L0 = -1, + H0 = 1 +} + +enum F { + L1 = 1, + H1 = 0xFFFFFFFFFFFFFFFF +} + +pub fn main() { + let a = E::L0 as f32; //~ ERROR illegal cast + let c = F::H1 as f32; //~ ERROR illegal cast + assert_eq!(a, -1.0f32); + assert_eq!(c, -1.0f32); +} diff --git a/src/test/compile-fail/enum-to-float-cast.rs b/src/test/compile-fail/enum-to-float-cast.rs index 3ad27906552d7..225b8702302a8 100644 --- a/src/test/compile-fail/enum-to-float-cast.rs +++ b/src/test/compile-fail/enum-to-float-cast.rs @@ -24,12 +24,8 @@ static C0: f32 = E::L0 as f32; //~ ERROR illegal cast static C1: f32 = F::H1 as f32; //~ ERROR illegal cast pub fn main() { - let a = E::L0 as f32; //~ ERROR illegal cast let b = C0; - let c = F::H1 as f32; //~ ERROR illegal cast let d = C1; - assert_eq!(a, -1.0f32); assert_eq!(b, -1.0f32); - assert_eq!(c, -1.0f32); assert_eq!(d, -1.0f32); } diff --git a/src/test/compile-fail/issue-16048.rs b/src/test/compile-fail/issue-16048.rs index dbd3336962b76..46b7b933d8796 100644 --- a/src/test/compile-fail/issue-16048.rs +++ b/src/test/compile-fail/issue-16048.rs @@ -29,7 +29,7 @@ impl<'a> Test<'a> for Foo<'a> { impl<'a> NoLifetime for Foo<'a> { fn get<'p, T : Test<'a>>(&self) -> T { //~^ ERROR lifetime parameters or bounds on method `get` do not match the trait declaration - return *self as T; //~ ERROR non-scalar cast: `Foo<'a>` as `T` + return *self as T; } } diff --git a/src/test/compile-fail/issue-19244-1.rs b/src/test/compile-fail/issue-19244-1.rs index 5c11787d46780..0fa1a15477209 100644 --- a/src/test/compile-fail/issue-19244-1.rs +++ b/src/test/compile-fail/issue-19244-1.rs @@ -12,7 +12,5 @@ const TUP: (usize,) = (42,); fn main() { let a: [isize; TUP.1]; - //~^ ERROR array length constant evaluation error: tuple index out of bounds - //~| ERROR attempted out-of-bounds tuple index - //~| ERROR attempted out-of-bounds tuple index + //~^ ERROR attempted out-of-bounds tuple index } diff --git a/src/test/compile-fail/issue-19244-2.rs b/src/test/compile-fail/issue-19244-2.rs index d896f76865910..7d7d7d7c8ce4d 100644 --- a/src/test/compile-fail/issue-19244-2.rs +++ b/src/test/compile-fail/issue-19244-2.rs @@ -13,7 +13,5 @@ const STRUCT: MyStruct = MyStruct { field: 42 }; fn main() { let a: [isize; STRUCT.nonexistent_field]; - //~^ ERROR array length constant evaluation error: nonexistent struct field - //~| ERROR attempted access of field `nonexistent_field` - //~| ERROR attempted access of field `nonexistent_field` + //~^ ERROR attempted access of field `nonexistent_field` } diff --git a/src/test/compile-fail/issue-2063.rs b/src/test/compile-fail/issue-2063.rs index aed395d17ea9c..9e63cc203f4d5 100644 --- a/src/test/compile-fail/issue-2063.rs +++ b/src/test/compile-fail/issue-2063.rs @@ -28,7 +28,10 @@ impl to_str_2 for t { } fn new_t(x: t) { - x.my_to_string(); //~ ERROR does not implement + x.my_to_string(); + // (there used to be an error emitted right here as well. It was + // spurious, at best; if `t` did exist as a type, it clearly would + // have an impl of the `to_str_2` trait.) } fn main() { diff --git a/src/test/compile-fail/non-constant-expr-for-fixed-len-vec.rs b/src/test/compile-fail/non-constant-expr-for-fixed-len-vec.rs index 59e910ec6afda..b5401f7d124e2 100644 --- a/src/test/compile-fail/non-constant-expr-for-fixed-len-vec.rs +++ b/src/test/compile-fail/non-constant-expr-for-fixed-len-vec.rs @@ -12,8 +12,8 @@ fn main() { fn bar(n: isize) { + // FIXME (#24414): This error message needs improvement. let _x: [isize; n]; //~^ ERROR no type for local variable - //~| ERROR array length constant evaluation error: non-constant path in constant expr } } diff --git a/src/test/compile-fail/struct-base-wrong-type-2.rs b/src/test/compile-fail/struct-base-wrong-type-2.rs new file mode 100644 index 0000000000000..83e73b6bc3ef4 --- /dev/null +++ b/src/test/compile-fail/struct-base-wrong-type-2.rs @@ -0,0 +1,31 @@ +// Copyright 2013 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// Check that `base` in `Fru { field: expr, ..base }` must have right type. +// +// See also struct-base-wrong-type.rs, which tests same condition +// within a const expression. + +struct Foo { a: isize, b: isize } +struct Bar { x: isize } + +fn main() { + let b = Bar { x: 5 }; + let f = Foo { a: 2, ..b }; //~ ERROR mismatched types + //~| expected `Foo` + //~| found `Bar` + //~| expected struct `Foo` + //~| found struct `Bar` + let f__isize = Foo { a: 2, ..4 }; //~ ERROR mismatched types + //~| expected `Foo` + //~| found `_` + //~| expected struct `Foo` + //~| found integral variable +} diff --git a/src/test/compile-fail/struct-base-wrong-type.rs b/src/test/compile-fail/struct-base-wrong-type.rs index a2ad2336d4bc3..c98131560d486 100644 --- a/src/test/compile-fail/struct-base-wrong-type.rs +++ b/src/test/compile-fail/struct-base-wrong-type.rs @@ -8,6 +8,11 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// Check that `base` in `Fru { field: expr, ..base }` must have right type. +// +// See also struct-base-wrong-type-2.rs, which tests same condition +// within a function body. + struct Foo { a: isize, b: isize } struct Bar { x: isize } @@ -25,14 +30,10 @@ static foo_i: Foo = Foo { a: 2, ..4 }; //~ ERROR mismatched types fn main() { let b = Bar { x: 5 }; - let f = Foo { a: 2, ..b }; //~ ERROR mismatched types - //~| expected `Foo` - //~| found `Bar` - //~| expected struct `Foo` - //~| found struct `Bar` - let f__isize = Foo { a: 2, ..4 }; //~ ERROR mismatched types - //~| expected `Foo` - //~| found `_` - //~| expected struct `Foo` - //~| found integral variable + // errors below are no longer caught since error above causes + // compilation to abort before we bother checking function bodies. + // See also struct-base-wrong-type-2.rs, which checks that we + // would catch these errors eventually. + let f = Foo { a: 2, ..b }; + let f__isize = Foo { a: 2, ..4 }; } diff --git a/src/test/compile-fail/variadic-ffi-3.rs b/src/test/compile-fail/variadic-ffi-3.rs new file mode 100644 index 0000000000000..94055450bc6bb --- /dev/null +++ b/src/test/compile-fail/variadic-ffi-3.rs @@ -0,0 +1,43 @@ +// Copyright 2013 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +extern { + fn foo(f: isize, x: u8, ...); +} + +extern "C" fn bar(f: isize, x: u8) {} + +fn main() { + unsafe { + foo(); //~ ERROR: this function takes at least 2 parameters but 0 parameters were supplied + foo(1); //~ ERROR: this function takes at least 2 parameters but 1 parameter was supplied + + let x: unsafe extern "C" fn(f: isize, x: u8) = foo; + //~^ ERROR: mismatched types + //~| expected `unsafe extern "C" fn(isize, u8)` + //~| found `unsafe extern "C" fn(isize, u8, ...)` + //~| expected non-variadic fn + //~| found variadic function + + let y: extern "C" fn(f: isize, x: u8, ...) = bar; + //~^ ERROR: mismatched types + //~| expected `extern "C" fn(isize, u8, ...)` + //~| found `extern "C" fn(isize, u8) {bar}` + //~| expected variadic fn + //~| found non-variadic function + + foo(1, 2, 3f32); //~ ERROR: can't pass an f32 to variadic function, cast to c_double + foo(1, 2, true); //~ ERROR: can't pass bool to variadic function, cast to c_int + foo(1, 2, 1i8); //~ ERROR: can't pass i8 to variadic function, cast to c_int + foo(1, 2, 1u8); //~ ERROR: can't pass u8 to variadic function, cast to c_uint + foo(1, 2, 1i16); //~ ERROR: can't pass i16 to variadic function, cast to c_int + foo(1, 2, 1u16); //~ ERROR: can't pass u16 to variadic function, cast to c_uint + } +} diff --git a/src/test/compile-fail/variadic-ffi.rs b/src/test/compile-fail/variadic-ffi.rs index 2a62ac2ac303a..129421784930b 100644 --- a/src/test/compile-fail/variadic-ffi.rs +++ b/src/test/compile-fail/variadic-ffi.rs @@ -19,29 +19,20 @@ extern { extern "C" fn bar(f: isize, x: u8) {} fn main() { + // errors below are no longer checked because error above aborts + // compilation; see variadic-ffi-3.rs for corresponding test. unsafe { - foo(); //~ ERROR: this function takes at least 2 parameters but 0 parameters were supplied - foo(1); //~ ERROR: this function takes at least 2 parameters but 1 parameter was supplied + foo(); + foo(1); let x: unsafe extern "C" fn(f: isize, x: u8) = foo; - //~^ ERROR: mismatched types - //~| expected `unsafe extern "C" fn(isize, u8)` - //~| found `unsafe extern "C" fn(isize, u8, ...)` - //~| expected non-variadic fn - //~| found variadic function - let y: extern "C" fn(f: isize, x: u8, ...) = bar; - //~^ ERROR: mismatched types - //~| expected `extern "C" fn(isize, u8, ...)` - //~| found `extern "C" fn(isize, u8) {bar}` - //~| expected variadic fn - //~| found non-variadic function - foo(1, 2, 3f32); //~ ERROR: can't pass an f32 to variadic function, cast to c_double - foo(1, 2, true); //~ ERROR: can't pass bool to variadic function, cast to c_int - foo(1, 2, 1i8); //~ ERROR: can't pass i8 to variadic function, cast to c_int - foo(1, 2, 1u8); //~ ERROR: can't pass u8 to variadic function, cast to c_uint - foo(1, 2, 1i16); //~ ERROR: can't pass i16 to variadic function, cast to c_int - foo(1, 2, 1u16); //~ ERROR: can't pass u16 to variadic function, cast to c_uint + foo(1, 2, 3f32); + foo(1, 2, true); + foo(1, 2, 1i8); + foo(1, 2, 1u8); + foo(1, 2, 1i16); + foo(1, 2, 1u16); } } diff --git a/src/test/compile-fail/wrong-mul-method-signature.rs b/src/test/compile-fail/wrong-mul-method-signature.rs index 21c249c0e1fb0..069fd2dec990f 100644 --- a/src/test/compile-fail/wrong-mul-method-signature.rs +++ b/src/test/compile-fail/wrong-mul-method-signature.rs @@ -71,16 +71,9 @@ pub fn main() { let x: Vec1 = Vec1 { x: 1.0 } * 2.0; // this is OK let x: Vec2 = Vec2 { x: 1.0, y: 2.0 } * 2.0; // trait had reversed order - //~^ ERROR mismatched types - //~| expected `Vec2` - //~| found `_` - //~| expected struct `Vec2` - //~| found floating-point variable - //~| ERROR mismatched types - //~| expected `Vec2` - //~| found `f64` - //~| expected struct `Vec2` - //~| found f64 + // (we no longer signal a compile error here, since the + // error in the trait signature will cause compilation to + // abort before we bother looking at function bodies.) let x: i32 = Vec3 { x: 1.0, y: 2.0, z: 3.0 } * 2.0; } diff --git a/src/test/run-pass/associated-types-projection-to-unrelated-trait.rs b/src/test/run-pass/associated-types-projection-to-unrelated-trait.rs new file mode 100644 index 0000000000000..6070cff9a2952 --- /dev/null +++ b/src/test/run-pass/associated-types-projection-to-unrelated-trait.rs @@ -0,0 +1,43 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// Check that we do not get an error when you use `::Value` in +// the trait definition if there is no default method and for every impl, +// `Self` does implement `Get`. +// +// See also compile-fail tests associated-types-no-suitable-supertrait +// and associated-types-no-suitable-supertrait-2, which show how small +// variants of the code below can fail. + +trait Get { + type Value; +} + +trait Other { + fn okay(&self, foo: U, bar: ::Value); +} + +impl Get for () { + type Value = f32; +} + +impl Get for f64 { + type Value = u32; +} + +impl Other for () { + fn okay(&self, _foo: U, _bar: ::Value) { } +} + +impl Other for f64 { + fn okay(&self, _foo: U, _bar: ::Value) { } +} + +fn main() { } From dca98829d9793c03bf56bd57c73d5474adb0c433 Mon Sep 17 00:00:00 2001 From: "Felix S. Klock II" Date: Wed, 15 Apr 2015 02:19:26 +0200 Subject: [PATCH 07/25] factor out useful helper. --- src/librustc_trans/trans/base.rs | 35 ++++++++++++++++++-------------- 1 file changed, 20 insertions(+), 15 deletions(-) diff --git a/src/librustc_trans/trans/base.rs b/src/librustc_trans/trans/base.rs index 93eb24a47de67..023f9e0bda186 100644 --- a/src/librustc_trans/trans/base.rs +++ b/src/librustc_trans/trans/base.rs @@ -566,6 +566,25 @@ fn cast_shift_rhs(op: ast::BinOp_, } } +pub fn llty_and_min_for_signed_ty<'blk, 'tcx>(cx: Block<'blk, 'tcx>, + val_t: Ty<'tcx>) -> (Type, u64) { + match val_t.sty { + ty::ty_int(t) => { + let llty = Type::int_from_ty(cx.ccx(), t); + let min = match t { + ast::TyIs if llty == Type::i32(cx.ccx()) => i32::MIN as u64, + ast::TyIs => i64::MIN as u64, + ast::TyI8 => i8::MIN as u64, + ast::TyI16 => i16::MIN as u64, + ast::TyI32 => i32::MIN as u64, + ast::TyI64 => i64::MIN as u64, + }; + (llty, min) + } + _ => unreachable!(), + } +} + pub fn fail_if_zero_or_overflows<'blk, 'tcx>( cx: Block<'blk, 'tcx>, call_info: NodeIdAndSpan, @@ -620,21 +639,7 @@ pub fn fail_if_zero_or_overflows<'blk, 'tcx>( // signed division/remainder which would trigger overflow. For unsigned // integers, no action beyond checking for zero need be taken. if is_signed { - let (llty, min) = match rhs_t.sty { - ty::ty_int(t) => { - let llty = Type::int_from_ty(cx.ccx(), t); - let min = match t { - ast::TyIs if llty == Type::i32(cx.ccx()) => i32::MIN as u64, - ast::TyIs => i64::MIN as u64, - ast::TyI8 => i8::MIN as u64, - ast::TyI16 => i16::MIN as u64, - ast::TyI32 => i32::MIN as u64, - ast::TyI64 => i64::MIN as u64, - }; - (llty, min) - } - _ => unreachable!(), - }; + let (llty, min) = llty_and_min_for_signed_ty(cx, rhs_t); let minus_one = ICmp(bcx, llvm::IntEQ, rhs, C_integral(llty, !0, false), debug_loc); with_cond(bcx, minus_one, |bcx| { From c343896b86b79b345a94184fa421516a2ae76e58 Mon Sep 17 00:00:00 2001 From: "Felix S. Klock II" Date: Wed, 15 Apr 2015 02:19:52 +0200 Subject: [PATCH 08/25] Add conditional overflow-checking to signed negate operator. --- src/librustc_trans/trans/expr.rs | 21 ++++++++++++++++++--- 1 file changed, 18 insertions(+), 3 deletions(-) diff --git a/src/librustc_trans/trans/expr.rs b/src/librustc_trans/trans/expr.rs index b91f50222a27f..27919d645b695 100644 --- a/src/librustc_trans/trans/expr.rs +++ b/src/librustc_trans/trans/expr.rs @@ -1530,11 +1530,26 @@ fn trans_unary<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, ast::UnNeg => { let datum = unpack_datum!(bcx, trans(bcx, sub_expr)); let val = datum.to_llscalarish(bcx); - let llneg = { + let (bcx, llneg) = { if ty::type_is_fp(un_ty) { - FNeg(bcx, val, debug_loc) + let result = FNeg(bcx, val, debug_loc); + (bcx, result) } else { - Neg(bcx, val, debug_loc) + let is_signed = ty::type_is_signed(un_ty); + let result = Neg(bcx, val, debug_loc); + let bcx = if bcx.ccx().check_overflow() && is_signed { + let (llty, min) = base::llty_and_min_for_signed_ty(bcx, un_ty); + let is_min = ICmp(bcx, llvm::IntEQ, val, + C_integral(llty, min, true), debug_loc); + with_cond(bcx, is_min, |bcx| { + let msg = InternedString::new( + "attempted to negate with overflow"); + controlflow::trans_fail(bcx, expr_info(expr), msg) + }) + } else { + bcx + }; + (bcx, result) } }; immediate_rvalue_bcx(bcx, llneg, un_ty).to_expr_datumblock() From 378fbcd21f8d53e63918ada40befe1b5f62b50c3 Mon Sep 17 00:00:00 2001 From: "Felix S. Klock II" Date: Wed, 15 Apr 2015 12:27:23 +0200 Subject: [PATCH 09/25] side-step potentially panic'ing negate in `fn abs`. --- src/libcore/num/mod.rs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/libcore/num/mod.rs b/src/libcore/num/mod.rs index 9b1a384a0d06a..6dd5b8edcf33f 100644 --- a/src/libcore/num/mod.rs +++ b/src/libcore/num/mod.rs @@ -1261,7 +1261,11 @@ macro_rules! int_impl { #[stable(feature = "rust1", since = "1.0.0")] #[inline] pub fn abs(self) -> $T { - if self.is_negative() { -self } else { self } + if self.is_negative() { + self.wrapping_neg() + } else { + self + } } /// Returns a number representing sign of `self`. From e99cc027bf85f2dc1d2c5b674895a5116b984ebe Mon Sep 17 00:00:00 2001 From: "Felix S. Klock II" Date: Thu, 16 Apr 2015 16:48:14 +0200 Subject: [PATCH 10/25] Workaround deliberate overflowing negation in serialize::json. --- src/libserialize/json.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libserialize/json.rs b/src/libserialize/json.rs index 8f020d0857d7b..b4f679a810989 100644 --- a/src/libserialize/json.rs +++ b/src/libserialize/json.rs @@ -1540,7 +1540,7 @@ impl> Parser { F64Value(res) } else { if neg { - let res = -(res as i64); + let res = (res as i64).wrapping_neg(); // Make sure we didn't underflow. if res > 0 { From be49cb64bcc3a0c975a39f66d7fb4fb752e024d8 Mon Sep 17 00:00:00 2001 From: "Felix S. Klock II" Date: Fri, 17 Apr 2015 15:32:30 +0200 Subject: [PATCH 11/25] unit test for checked overflow during signed negation. --- src/test/run-fail/overflowing-neg.rs | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) create mode 100644 src/test/run-fail/overflowing-neg.rs diff --git a/src/test/run-fail/overflowing-neg.rs b/src/test/run-fail/overflowing-neg.rs new file mode 100644 index 0000000000000..cdb74c7d7e261 --- /dev/null +++ b/src/test/run-fail/overflowing-neg.rs @@ -0,0 +1,19 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// error-pattern:thread '
' panicked at 'attempted to negate with overflow' +// compile-flags: -C debug-assertions + +// (Work around constant-evaluation) +fn value() -> i8 { std::i8::MIN } + +fn main() { + let _x = -value(); +} From 6d4647ba1d87d8bbe08b984f7818ecdd01121a36 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Fri, 17 Apr 2015 14:31:30 -0700 Subject: [PATCH 12/25] std: Add Default/IntoIterator/ToOwned to the prelude This is an implementation of [RFC 1030][rfc] which adds these traits to the prelude and additionally removes all inherent `into_iter` methods on collections in favor of the trait implementation (which is now accessible by default). [rfc]: https://github.com/rust-lang/rfcs/pull/1030 This is technically a breaking change due to the prelude additions and removal of inherent methods, but it is expected that essentially no code breaks in practice. [breaking-change] Closes #24538 --- src/liballoc/arc.rs | 1 - src/liballoc/boxed.rs | 1 - src/libcollections/binary_heap.rs | 44 +++++++++----------- src/libcollections/bit.rs | 3 +- src/libcollections/btree/map.rs | 58 ++++++++++++--------------- src/libcollections/btree/set.rs | 42 +++++++++----------- src/libcollections/enum_set.rs | 2 +- src/libcollections/linked_list.rs | 16 +++----- src/libcollections/string.rs | 4 +- src/libcollections/vec.rs | 64 ++++++++++++++---------------- src/libcollections/vec_deque.rs | 17 +++----- src/libcollections/vec_map.rs | 58 ++++++++++++--------------- src/libcore/hash/mod.rs | 1 - src/libcore/hash/sip.rs | 1 - src/libcore/option.rs | 43 +++++++++++--------- src/libcore/prelude.rs | 5 +-- src/libcore/result.rs | 43 +++++++++++--------- src/librand/reseeding.rs | 2 - src/libstd/collections/hash/map.rs | 51 +++++++++++------------- src/libstd/collections/hash/set.rs | 53 +++++++++++-------------- src/libstd/env.rs | 1 - src/libstd/path.rs | 2 +- src/libstd/prelude/v1.rs | 10 +++-- src/libstd/sys/common/wtf8.rs | 2 +- src/test/run-pass/issue-21245.rs | 6 +-- 25 files changed, 241 insertions(+), 289 deletions(-) diff --git a/src/liballoc/arc.rs b/src/liballoc/arc.rs index 0cfdcd2413fd9..93af336ce0a1a 100644 --- a/src/liballoc/arc.rs +++ b/src/liballoc/arc.rs @@ -77,7 +77,6 @@ use core::atomic; use core::atomic::Ordering::{Relaxed, Release, Acquire, SeqCst}; use core::fmt; use core::cmp::Ordering; -use core::default::Default; use core::mem::{min_align_of, size_of}; use core::mem; use core::nonzero::NonZero; diff --git a/src/liballoc/boxed.rs b/src/liballoc/boxed.rs index 4468e425a852d..e293a024f8e08 100644 --- a/src/liballoc/boxed.rs +++ b/src/liballoc/boxed.rs @@ -50,7 +50,6 @@ use core::prelude::*; use core::any::Any; use core::cmp::Ordering; -use core::default::Default; use core::fmt; use core::hash::{self, Hash}; use core::mem; diff --git a/src/libcollections/binary_heap.rs b/src/libcollections/binary_heap.rs index 3804874a650f6..0f05e5796aa15 100644 --- a/src/libcollections/binary_heap.rs +++ b/src/libcollections/binary_heap.rs @@ -152,8 +152,7 @@ use core::prelude::*; -use core::default::Default; -use core::iter::{FromIterator, IntoIterator}; +use core::iter::{FromIterator}; use core::mem::{zeroed, replace, swap}; use core::ptr; @@ -250,28 +249,6 @@ impl BinaryHeap { Iter { iter: self.data.iter() } } - /// Creates a consuming iterator, that is, one that moves each value out of - /// the binary heap in arbitrary order. The binary heap cannot be used - /// after calling this. - /// - /// # Examples - /// - /// ``` - /// # #![feature(collections)] - /// use std::collections::BinaryHeap; - /// let heap = BinaryHeap::from_vec(vec![1, 2, 3, 4]); - /// - /// // Print 1, 2, 3, 4 in arbitrary order - /// for x in heap.into_iter() { - /// // x has type i32, not &i32 - /// println!("{}", x); - /// } - /// ``` - #[stable(feature = "rust1", since = "1.0.0")] - pub fn into_iter(self) -> IntoIter { - IntoIter { iter: self.data.into_iter() } - } - /// Returns the greatest item in the binary heap, or `None` if it is empty. /// /// # Examples @@ -675,8 +652,25 @@ impl IntoIterator for BinaryHeap { type Item = T; type IntoIter = IntoIter; + /// Creates a consuming iterator, that is, one that moves each value out of + /// the binary heap in arbitrary order. The binary heap cannot be used + /// after calling this. + /// + /// # Examples + /// + /// ``` + /// # #![feature(collections)] + /// use std::collections::BinaryHeap; + /// let heap = BinaryHeap::from_vec(vec![1, 2, 3, 4]); + /// + /// // Print 1, 2, 3, 4 in arbitrary order + /// for x in heap.into_iter() { + /// // x has type i32, not &i32 + /// println!("{}", x); + /// } + /// ``` fn into_iter(self) -> IntoIter { - self.into_iter() + IntoIter { iter: self.data.into_iter() } } } diff --git a/src/libcollections/bit.rs b/src/libcollections/bit.rs index d12b979e084fc..a72f628e10d97 100644 --- a/src/libcollections/bit.rs +++ b/src/libcollections/bit.rs @@ -85,12 +85,11 @@ use core::prelude::*; use core::cmp::Ordering; use core::cmp; -use core::default::Default; use core::fmt; use core::hash; use core::iter::RandomAccessIterator; use core::iter::{Chain, Enumerate, Repeat, Skip, Take, repeat, Cloned}; -use core::iter::{self, FromIterator, IntoIterator}; +use core::iter::{self, FromIterator}; use core::ops::Index; use core::slice; use core::{u8, u32, usize}; diff --git a/src/libcollections/btree/map.rs b/src/libcollections/btree/map.rs index 859d5ea99bf50..bd4028db42e0f 100644 --- a/src/libcollections/btree/map.rs +++ b/src/libcollections/btree/map.rs @@ -20,10 +20,9 @@ use self::Entry::*; use core::prelude::*; use core::cmp::Ordering; -use core::default::Default; use core::fmt::Debug; use core::hash::{Hash, Hasher}; -use core::iter::{Map, FromIterator, IntoIterator}; +use core::iter::{Map, FromIterator}; use core::ops::Index; use core::{iter, fmt, mem, usize}; use Bound::{self, Included, Excluded, Unbounded}; @@ -472,8 +471,32 @@ impl IntoIterator for BTreeMap { type Item = (K, V); type IntoIter = IntoIter; + /// Gets an owning iterator over the entries of the map. + /// + /// # Examples + /// + /// ``` + /// use std::collections::BTreeMap; + /// + /// let mut map = BTreeMap::new(); + /// map.insert(1, "a"); + /// map.insert(2, "b"); + /// map.insert(3, "c"); + /// + /// for (key, value) in map.into_iter() { + /// println!("{}: {}", key, value); + /// } + /// ``` fn into_iter(self) -> IntoIter { - self.into_iter() + let len = self.len(); + let mut lca = VecDeque::new(); + lca.push_back(Traverse::traverse(self.root)); + IntoIter { + inner: AbsIter { + traversals: lca, + size: len, + } + } } } @@ -1264,35 +1287,6 @@ impl BTreeMap { } } - /// Gets an owning iterator over the entries of the map. - /// - /// # Examples - /// - /// ``` - /// use std::collections::BTreeMap; - /// - /// let mut map = BTreeMap::new(); - /// map.insert(1, "a"); - /// map.insert(2, "b"); - /// map.insert(3, "c"); - /// - /// for (key, value) in map.into_iter() { - /// println!("{}: {}", key, value); - /// } - /// ``` - #[stable(feature = "rust1", since = "1.0.0")] - pub fn into_iter(self) -> IntoIter { - let len = self.len(); - let mut lca = VecDeque::new(); - lca.push_back(Traverse::traverse(self.root)); - IntoIter { - inner: AbsIter { - traversals: lca, - size: len, - } - } - } - /// Gets an iterator over the keys of the map. /// /// # Examples diff --git a/src/libcollections/btree/set.rs b/src/libcollections/btree/set.rs index 1abd56fd1458d..fc346151e0b4b 100644 --- a/src/libcollections/btree/set.rs +++ b/src/libcollections/btree/set.rs @@ -14,10 +14,9 @@ use core::prelude::*; use core::cmp::Ordering::{self, Less, Greater, Equal}; -use core::default::Default; use core::fmt::Debug; use core::fmt; -use core::iter::{Peekable, Map, FromIterator, IntoIterator}; +use core::iter::{Peekable, Map, FromIterator}; use core::ops::{BitOr, BitAnd, BitXor, Sub}; use borrow::Borrow; @@ -132,27 +131,6 @@ impl BTreeSet { pub fn iter(&self) -> Iter { Iter { iter: self.map.keys() } } - - /// Gets an iterator for moving out the BtreeSet's contents. - /// - /// # Examples - /// - /// ``` - /// # #![feature(core)] - /// use std::collections::BTreeSet; - /// - /// let set: BTreeSet = [1, 2, 3, 4].iter().cloned().collect(); - /// - /// let v: Vec = set.into_iter().collect(); - /// assert_eq!(v, [1, 2, 3, 4]); - /// ``` - #[stable(feature = "rust1", since = "1.0.0")] - pub fn into_iter(self) -> IntoIter { - fn first((a, _): (A, B)) -> A { a } - let first: fn((T, ())) -> T = first; // coerce to fn pointer - - IntoIter { iter: self.map.into_iter().map(first) } - } } impl BTreeSet { @@ -500,8 +478,24 @@ impl IntoIterator for BTreeSet { type Item = T; type IntoIter = IntoIter; + /// Gets an iterator for moving out the BtreeSet's contents. + /// + /// # Examples + /// + /// ``` + /// # #![feature(core)] + /// use std::collections::BTreeSet; + /// + /// let set: BTreeSet = [1, 2, 3, 4].iter().cloned().collect(); + /// + /// let v: Vec = set.into_iter().collect(); + /// assert_eq!(v, [1, 2, 3, 4]); + /// ``` fn into_iter(self) -> IntoIter { - self.into_iter() + fn first((a, _): (A, B)) -> A { a } + let first: fn((T, ())) -> T = first; // coerce to fn pointer + + IntoIter { iter: self.map.into_iter().map(first) } } } diff --git a/src/libcollections/enum_set.rs b/src/libcollections/enum_set.rs index a3a266669b1bb..e6cdb88d3e174 100644 --- a/src/libcollections/enum_set.rs +++ b/src/libcollections/enum_set.rs @@ -16,7 +16,7 @@ use core::prelude::*; use core::marker; use core::fmt; -use core::iter::{FromIterator, IntoIterator}; +use core::iter::{FromIterator}; use core::ops::{Sub, BitOr, BitAnd, BitXor}; // FIXME(contentions): implement union family of methods? (general design may be wrong here) diff --git a/src/libcollections/linked_list.rs b/src/libcollections/linked_list.rs index 391439bcdf2ff..deb1476c23f09 100644 --- a/src/libcollections/linked_list.rs +++ b/src/libcollections/linked_list.rs @@ -25,10 +25,9 @@ use core::prelude::*; use alloc::boxed::Box; use core::cmp::Ordering; -use core::default::Default; use core::fmt; use core::hash::{Hasher, Hash}; -use core::iter::{self, FromIterator, IntoIterator}; +use core::iter::{self, FromIterator}; use core::mem; use core::ptr; @@ -296,13 +295,6 @@ impl LinkedList { } } - /// Consumes the list into an iterator yielding elements by value. - #[inline] - #[stable(feature = "rust1", since = "1.0.0")] - pub fn into_iter(self) -> IntoIter { - IntoIter{list: self} - } - /// Returns `true` if the `LinkedList` is empty. /// /// This operation should compute in O(1) time. @@ -852,8 +844,10 @@ impl IntoIterator for LinkedList { type Item = T; type IntoIter = IntoIter; + /// Consumes the list into an iterator yielding elements by value. + #[inline] fn into_iter(self) -> IntoIter { - self.into_iter() + IntoIter{list: self} } } @@ -941,7 +935,7 @@ impl Hash for LinkedList { #[cfg(test)] mod test { use std::clone::Clone; - use std::iter::Iterator; + use std::iter::{Iterator, IntoIterator}; use std::option::Option::{Some, None, self}; use std::__rand::{thread_rng, Rng}; use std::thread; diff --git a/src/libcollections/string.rs b/src/libcollections/string.rs index 51ce5564c49c5..864801ab0b730 100644 --- a/src/libcollections/string.rs +++ b/src/libcollections/string.rs @@ -16,14 +16,14 @@ use core::prelude::*; -use core::default::Default; use core::fmt; use core::hash; -use core::iter::{IntoIterator, FromIterator}; +use core::iter::FromIterator; use core::mem; use core::ops::{self, Deref, Add, Index}; use core::ptr; use core::slice; +#[allow(deprecated)] use core::str::Str; use core::str::pattern::Pattern; use unicode::str as unicode_str; use unicode::str::Utf16Item; diff --git a/src/libcollections/vec.rs b/src/libcollections/vec.rs index 4fa91a6a16a52..3e08096e16612 100644 --- a/src/libcollections/vec.rs +++ b/src/libcollections/vec.rs @@ -53,18 +53,17 @@ use alloc::boxed::Box; use alloc::heap::{EMPTY, allocate, reallocate, deallocate}; use core::cmp::max; use core::cmp::Ordering; -use core::default::Default; use core::fmt; use core::hash::{self, Hash}; use core::intrinsics::assume; -use core::iter::{repeat, FromIterator, IntoIterator}; +use core::iter::{repeat, FromIterator}; use core::marker::PhantomData; use core::mem; use core::ops::{Index, IndexMut, Deref, Add}; use core::ops; use core::ptr; use core::ptr::Unique; -use core::slice; +use core::slice::{self, AsSlice}; use core::isize; use core::usize; @@ -450,37 +449,6 @@ impl Vec { &mut self[..] } - /// Creates a consuming iterator, that is, one that moves each value out of - /// the vector (from start to end). The vector cannot be used after calling - /// this. - /// - /// # Examples - /// - /// ``` - /// let v = vec!["a".to_string(), "b".to_string()]; - /// for s in v.into_iter() { - /// // s has type String, not &String - /// println!("{}", s); - /// } - /// ``` - #[inline] - #[stable(feature = "rust1", since = "1.0.0")] - pub fn into_iter(self) -> IntoIter { - unsafe { - let ptr = *self.ptr; - assume(!ptr.is_null()); - let cap = self.cap; - let begin = ptr as *const T; - let end = if mem::size_of::() == 0 { - (ptr as usize + self.len()) as *const T - } else { - ptr.offset(self.len() as isize) as *const T - }; - mem::forget(self); - IntoIter { allocation: ptr, cap: cap, ptr: begin, end: end } - } - } - /// Sets the length of a vector. /// /// This will explicitly set the size of the vector, without actually @@ -1512,8 +1480,34 @@ impl IntoIterator for Vec { type Item = T; type IntoIter = IntoIter; + /// Creates a consuming iterator, that is, one that moves each value out of + /// the vector (from start to end). The vector cannot be used after calling + /// this. + /// + /// # Examples + /// + /// ``` + /// let v = vec!["a".to_string(), "b".to_string()]; + /// for s in v.into_iter() { + /// // s has type String, not &String + /// println!("{}", s); + /// } + /// ``` + #[inline] fn into_iter(self) -> IntoIter { - self.into_iter() + unsafe { + let ptr = *self.ptr; + assume(!ptr.is_null()); + let cap = self.cap; + let begin = ptr as *const T; + let end = if mem::size_of::() == 0 { + (ptr as usize + self.len()) as *const T + } else { + ptr.offset(self.len() as isize) as *const T + }; + mem::forget(self); + IntoIter { allocation: ptr, cap: cap, ptr: begin, end: end } + } } } diff --git a/src/libcollections/vec_deque.rs b/src/libcollections/vec_deque.rs index a66cde81c8ba5..fcb06b5631ab3 100644 --- a/src/libcollections/vec_deque.rs +++ b/src/libcollections/vec_deque.rs @@ -21,9 +21,8 @@ use core::prelude::*; use core::cmp::Ordering; -use core::default::Default; use core::fmt; -use core::iter::{self, repeat, FromIterator, IntoIterator, RandomAccessIterator}; +use core::iter::{self, repeat, FromIterator, RandomAccessIterator}; use core::mem; use core::ops::{Index, IndexMut}; use core::ptr::{self, Unique}; @@ -560,14 +559,6 @@ impl VecDeque { } } - /// Consumes the list into a front-to-back iterator yielding elements by value. - #[stable(feature = "rust1", since = "1.0.0")] - pub fn into_iter(self) -> IntoIter { - IntoIter { - inner: self, - } - } - /// Returns a pair of slices which contain, in order, the contents of the /// `VecDeque`. #[inline] @@ -1731,8 +1722,12 @@ impl IntoIterator for VecDeque { type Item = T; type IntoIter = IntoIter; + /// Consumes the list into a front-to-back iterator yielding elements by + /// value. fn into_iter(self) -> IntoIter { - self.into_iter() + IntoIter { + inner: self, + } } } diff --git a/src/libcollections/vec_map.rs b/src/libcollections/vec_map.rs index cb86e4ab38d3d..d9cffc74dddda 100644 --- a/src/libcollections/vec_map.rs +++ b/src/libcollections/vec_map.rs @@ -18,10 +18,9 @@ use self::Entry::*; use core::prelude::*; use core::cmp::{max, Ordering}; -use core::default::Default; use core::fmt; use core::hash::{Hash, Hasher}; -use core::iter::{Enumerate, FilterMap, Map, FromIterator, IntoIterator}; +use core::iter::{Enumerate, FilterMap, Map, FromIterator}; use core::iter; use core::mem::{replace, swap}; use core::ops::{Index, IndexMut}; @@ -302,35 +301,6 @@ impl VecMap { } } - /// Returns an iterator visiting all key-value pairs in ascending order of - /// the keys, consuming the original `VecMap`. - /// The iterator's element type is `(usize, &'r V)`. - /// - /// # Examples - /// - /// ``` - /// # #![feature(collections)] - /// use std::collections::VecMap; - /// - /// let mut map = VecMap::new(); - /// map.insert(1, "a"); - /// map.insert(3, "c"); - /// map.insert(2, "b"); - /// - /// let vec: Vec<(usize, &str)> = map.into_iter().collect(); - /// - /// assert_eq!(vec, [(1, "a"), (2, "b"), (3, "c")]); - /// ``` - #[stable(feature = "rust1", since = "1.0.0")] - pub fn into_iter(self) -> IntoIter { - fn filter((i, v): (usize, Option)) -> Option<(usize, A)> { - v.map(|v| (i, v)) - } - let filter: fn((usize, Option)) -> Option<(usize, V)> = filter; // coerce to fn ptr - - IntoIter { iter: self.v.into_iter().enumerate().filter_map(filter) } - } - /// Moves all elements from `other` into the map while overwriting existing keys. /// /// # Examples @@ -802,8 +772,32 @@ impl IntoIterator for VecMap { type Item = (usize, T); type IntoIter = IntoIter; + /// Returns an iterator visiting all key-value pairs in ascending order of + /// the keys, consuming the original `VecMap`. + /// The iterator's element type is `(usize, &'r V)`. + /// + /// # Examples + /// + /// ``` + /// # #![feature(collections)] + /// use std::collections::VecMap; + /// + /// let mut map = VecMap::new(); + /// map.insert(1, "a"); + /// map.insert(3, "c"); + /// map.insert(2, "b"); + /// + /// let vec: Vec<(usize, &str)> = map.into_iter().collect(); + /// + /// assert_eq!(vec, [(1, "a"), (2, "b"), (3, "c")]); + /// ``` fn into_iter(self) -> IntoIter { - self.into_iter() + fn filter((i, v): (usize, Option)) -> Option<(usize, A)> { + v.map(|v| (i, v)) + } + let filter: fn((usize, Option)) -> Option<(usize, T)> = filter; // coerce to fn ptr + + IntoIter { iter: self.v.into_iter().enumerate().filter_map(filter) } } } diff --git a/src/libcore/hash/mod.rs b/src/libcore/hash/mod.rs index 553e0c0dfe6e4..e848a44e01ce0 100644 --- a/src/libcore/hash/mod.rs +++ b/src/libcore/hash/mod.rs @@ -62,7 +62,6 @@ use prelude::*; -use default::Default; use mem; pub use self::sip::SipHasher; diff --git a/src/libcore/hash/sip.rs b/src/libcore/hash/sip.rs index 6820a7025fca6..0bff9b0ba42c5 100644 --- a/src/libcore/hash/sip.rs +++ b/src/libcore/hash/sip.rs @@ -15,7 +15,6 @@ #![allow(deprecated)] // until the next snapshot for inherent wrapping ops use prelude::*; -use default::Default; use super::Hasher; /// An implementation of SipHash 2-4. diff --git a/src/libcore/option.rs b/src/libcore/option.rs index 4c784a579da6b..d1bc24bd9baa5 100644 --- a/src/libcore/option.rs +++ b/src/libcore/option.rs @@ -551,25 +551,6 @@ impl Option { IterMut { inner: Item { opt: self.as_mut() } } } - /// Returns a consuming iterator over the possibly contained value. - /// - /// # Examples - /// - /// ``` - /// let x = Some("string"); - /// let v: Vec<&str> = x.into_iter().collect(); - /// assert_eq!(v, ["string"]); - /// - /// let x = None; - /// let v: Vec<&str> = x.into_iter().collect(); - /// assert!(v.is_empty()); - /// ``` - #[inline] - #[stable(feature = "rust1", since = "1.0.0")] - pub fn into_iter(self) -> IntoIter { - IntoIter { inner: Item { opt: self } } - } - ///////////////////////////////////////////////////////////////////////// // Boolean operations on the values, eager and lazy ///////////////////////////////////////////////////////////////////////// @@ -770,6 +751,30 @@ impl Default for Option { fn default() -> Option { None } } +#[stable(feature = "rust1", since = "1.0.0")] +impl IntoIterator for Option { + type Item = T; + type IntoIter = IntoIter; + + /// Returns a consuming iterator over the possibly contained value. + /// + /// # Examples + /// + /// ``` + /// let x = Some("string"); + /// let v: Vec<&str> = x.into_iter().collect(); + /// assert_eq!(v, ["string"]); + /// + /// let x = None; + /// let v: Vec<&str> = x.into_iter().collect(); + /// assert!(v.is_empty()); + /// ``` + #[inline] + fn into_iter(self) -> IntoIter { + IntoIter { inner: Item { opt: self } } + } +} + ///////////////////////////////////////////////////////////////////////////// // The Option Iterators ///////////////////////////////////////////////////////////////////////////// diff --git a/src/libcore/prelude.rs b/src/libcore/prelude.rs index e60bc49408195..a4d529ad47d09 100644 --- a/src/libcore/prelude.rs +++ b/src/libcore/prelude.rs @@ -37,11 +37,10 @@ pub use char::CharExt; pub use clone::Clone; pub use cmp::{PartialEq, PartialOrd, Eq, Ord}; pub use convert::{AsRef, AsMut, Into, From}; +pub use default::Default; +pub use iter::IntoIterator; pub use iter::{Iterator, DoubleEndedIterator, Extend, ExactSizeIterator}; pub use option::Option::{self, Some, None}; pub use result::Result::{self, Ok, Err}; pub use slice::SliceExt; pub use str::StrExt; - -#[allow(deprecated)] pub use slice::AsSlice; -#[allow(deprecated)] pub use str::Str; diff --git a/src/libcore/result.rs b/src/libcore/result.rs index 4c74f4646ac06..8ae212ea721d2 100644 --- a/src/libcore/result.rs +++ b/src/libcore/result.rs @@ -547,25 +547,6 @@ impl Result { IterMut { inner: self.as_mut().ok() } } - /// Returns a consuming iterator over the possibly contained value. - /// - /// # Examples - /// - /// ``` - /// let x: Result = Ok(5); - /// let v: Vec = x.into_iter().collect(); - /// assert_eq!(v, [5]); - /// - /// let x: Result = Err("nothing!"); - /// let v: Vec = x.into_iter().collect(); - /// assert_eq!(v, []); - /// ``` - #[inline] - #[stable(feature = "rust1", since = "1.0.0")] - pub fn into_iter(self) -> IntoIter { - IntoIter { inner: self.ok() } - } - //////////////////////////////////////////////////////////////////////// // Boolean operations on the values, eager and lazy ///////////////////////////////////////////////////////////////////////// @@ -807,6 +788,30 @@ impl AsSlice for Result { } } +#[stable(feature = "rust1", since = "1.0.0")] +impl IntoIterator for Result { + type Item = T; + type IntoIter = IntoIter; + + /// Returns a consuming iterator over the possibly contained value. + /// + /// # Examples + /// + /// ``` + /// let x: Result = Ok(5); + /// let v: Vec = x.into_iter().collect(); + /// assert_eq!(v, [5]); + /// + /// let x: Result = Err("nothing!"); + /// let v: Vec = x.into_iter().collect(); + /// assert_eq!(v, []); + /// ``` + #[inline] + fn into_iter(self) -> IntoIter { + IntoIter { inner: self.ok() } + } +} + ///////////////////////////////////////////////////////////////////////////// // The Result Iterators ///////////////////////////////////////////////////////////////////////////// diff --git a/src/librand/reseeding.rs b/src/librand/reseeding.rs index 287a23cf1d1b6..ea084b2816dd1 100644 --- a/src/librand/reseeding.rs +++ b/src/librand/reseeding.rs @@ -14,7 +14,6 @@ use core::prelude::*; use {Rng, SeedableRng}; -use core::default::Default; /// How many bytes of entropy the underling RNG is allowed to generate /// before it is reseeded. @@ -126,7 +125,6 @@ mod test { use core::iter::{order, repeat}; use super::{ReseedingRng, ReseedWithDefault}; - use std::default::Default; use {SeedableRng, Rng}; struct Counter { diff --git a/src/libstd/collections/hash/map.rs b/src/libstd/collections/hash/map.rs index f554a4f4ed6d1..2da31d3cb2de1 100644 --- a/src/libstd/collections/hash/map.rs +++ b/src/libstd/collections/hash/map.rs @@ -916,33 +916,6 @@ impl HashMap IterMut { inner: self.table.iter_mut() } } - /// Creates a consuming iterator, that is, one that moves each key-value - /// pair out of the map in arbitrary order. The map cannot be used after - /// calling this. - /// - /// # Examples - /// - /// ``` - /// use std::collections::HashMap; - /// - /// let mut map = HashMap::new(); - /// map.insert("a", 1); - /// map.insert("b", 2); - /// map.insert("c", 3); - /// - /// // Not possible with .iter() - /// let vec: Vec<(&str, isize)> = map.into_iter().collect(); - /// ``` - #[stable(feature = "rust1", since = "1.0.0")] - pub fn into_iter(self) -> IntoIter { - fn last_two((_, b, c): (A, B, C)) -> (B, C) { (b, c) } - let last_two: fn((SafeHash, K, V)) -> (K, V) = last_two; - - IntoIter { - inner: self.table.into_iter().map(last_two) - } - } - /// Gets the given key's corresponding entry in the map for in-place manipulation. #[stable(feature = "rust1", since = "1.0.0")] pub fn entry(&mut self, key: K) -> Entry { @@ -1391,8 +1364,30 @@ impl IntoIterator for HashMap type Item = (K, V); type IntoIter = IntoIter; + /// Creates a consuming iterator, that is, one that moves each key-value + /// pair out of the map in arbitrary order. The map cannot be used after + /// calling this. + /// + /// # Examples + /// + /// ``` + /// use std::collections::HashMap; + /// + /// let mut map = HashMap::new(); + /// map.insert("a", 1); + /// map.insert("b", 2); + /// map.insert("c", 3); + /// + /// // Not possible with .iter() + /// let vec: Vec<(&str, isize)> = map.into_iter().collect(); + /// ``` fn into_iter(self) -> IntoIter { - self.into_iter() + fn last_two((_, b, c): (A, B, C)) -> (B, C) { (b, c) } + let last_two: fn((SafeHash, K, V)) -> (K, V) = last_two; + + IntoIter { + inner: self.table.into_iter().map(last_two) + } } } diff --git a/src/libstd/collections/hash/set.rs b/src/libstd/collections/hash/set.rs index 62c03389b24ae..c51fceddd538c 100644 --- a/src/libstd/collections/hash/set.rs +++ b/src/libstd/collections/hash/set.rs @@ -271,34 +271,6 @@ impl HashSet Iter { iter: self.map.keys() } } - /// Creates a consuming iterator, that is, one that moves each value out - /// of the set in arbitrary order. The set cannot be used after calling - /// this. - /// - /// # Examples - /// - /// ``` - /// use std::collections::HashSet; - /// let mut set = HashSet::new(); - /// set.insert("a".to_string()); - /// set.insert("b".to_string()); - /// - /// // Not possible to collect to a Vec with a regular `.iter()`. - /// let v: Vec = set.into_iter().collect(); - /// - /// // Will print in an arbitrary order. - /// for x in v.iter() { - /// println!("{}", x); - /// } - /// ``` - #[stable(feature = "rust1", since = "1.0.0")] - pub fn into_iter(self) -> IntoIter { - fn first((a, _): (A, B)) -> A { a } - let first: fn((T, ())) -> T = first; - - IntoIter { iter: self.map.into_iter().map(first) } - } - /// Visit the values representing the difference. /// /// # Examples @@ -850,8 +822,31 @@ impl IntoIterator for HashSet type Item = T; type IntoIter = IntoIter; + /// Creates a consuming iterator, that is, one that moves each value out + /// of the set in arbitrary order. The set cannot be used after calling + /// this. + /// + /// # Examples + /// + /// ``` + /// use std::collections::HashSet; + /// let mut set = HashSet::new(); + /// set.insert("a".to_string()); + /// set.insert("b".to_string()); + /// + /// // Not possible to collect to a Vec with a regular `.iter()`. + /// let v: Vec = set.into_iter().collect(); + /// + /// // Will print in an arbitrary order. + /// for x in v.iter() { + /// println!("{}", x); + /// } + /// ``` fn into_iter(self) -> IntoIter { - self.into_iter() + fn first((a, _): (A, B)) -> A { a } + let first: fn((T, ())) -> T = first; + + IntoIter { iter: self.map.into_iter().map(first) } } } diff --git a/src/libstd/env.rs b/src/libstd/env.rs index bcc109a71cb04..c66be35f3f6eb 100644 --- a/src/libstd/env.rs +++ b/src/libstd/env.rs @@ -18,7 +18,6 @@ use prelude::v1::*; -use iter::IntoIterator; use error::Error; use ffi::{OsStr, OsString}; use fmt; diff --git a/src/libstd/path.rs b/src/libstd/path.rs index cb78fc56bf20c..46efd378cc680 100644 --- a/src/libstd/path.rs +++ b/src/libstd/path.rs @@ -103,7 +103,7 @@ use core::prelude::*; use ascii::*; use borrow::{Borrow, IntoCow, ToOwned, Cow}; use cmp; -use iter::{self, IntoIterator}; +use iter; use mem; use ops::{self, Deref}; use string::String; diff --git a/src/libstd/prelude/v1.rs b/src/libstd/prelude/v1.rs index c93fc13284b44..6dc11c505a914 100644 --- a/src/libstd/prelude/v1.rs +++ b/src/libstd/prelude/v1.rs @@ -26,17 +26,19 @@ #[stable(feature = "rust1", since = "1.0.0")] #[doc(no_inline)] pub use boxed::Box; #[stable(feature = "rust1", since = "1.0.0")] +#[doc(no_inline)] pub use borrow::ToOwned; +#[stable(feature = "rust1", since = "1.0.0")] #[doc(no_inline)] pub use clone::Clone; #[stable(feature = "rust1", since = "1.0.0")] #[doc(no_inline)] pub use cmp::{PartialEq, PartialOrd, Eq, Ord}; -#[unstable(feature = "convert")] +#[stable(feature = "rust1", since = "1.0.0")] #[doc(no_inline)] pub use convert::{AsRef, AsMut, Into, From}; #[stable(feature = "rust1", since = "1.0.0")] -#[doc(no_inline)] pub use iter::DoubleEndedIterator; +#[doc(no_inline)] pub use default::Default; #[stable(feature = "rust1", since = "1.0.0")] -#[doc(no_inline)] pub use iter::ExactSizeIterator; +#[doc(no_inline)] pub use iter::{Iterator, Extend, IntoIterator}; #[stable(feature = "rust1", since = "1.0.0")] -#[doc(no_inline)] pub use iter::{Iterator, Extend}; +#[doc(no_inline)] pub use iter::{DoubleEndedIterator, ExactSizeIterator}; #[stable(feature = "rust1", since = "1.0.0")] #[doc(no_inline)] pub use option::Option::{self, Some, None}; #[stable(feature = "rust1", since = "1.0.0")] diff --git a/src/libstd/sys/common/wtf8.rs b/src/libstd/sys/common/wtf8.rs index 34a4a773f8ea7..631e47edb78fd 100644 --- a/src/libstd/sys/common/wtf8.rs +++ b/src/libstd/sys/common/wtf8.rs @@ -35,7 +35,7 @@ use borrow::Cow; use cmp; use fmt; use hash::{Hash, Hasher}; -use iter::{FromIterator, IntoIterator}; +use iter::FromIterator; use mem; #[allow(deprecated)] // Int use num::Int; diff --git a/src/test/run-pass/issue-21245.rs b/src/test/run-pass/issue-21245.rs index 75d064a00fa89..e3340d9767d02 100644 --- a/src/test/run-pass/issue-21245.rs +++ b/src/test/run-pass/issue-21245.rs @@ -20,19 +20,19 @@ use std::ptr; trait IntoIterator { type Iter: Iterator; - fn into_iter(self) -> Self::Iter; + fn into_iter2(self) -> Self::Iter; } impl IntoIterator for I where I: Iterator { type Iter = I; - fn into_iter(self) -> I { + fn into_iter2(self) -> I { self } } fn desugared_for_loop_bad(v: Vec) { - match IntoIterator::into_iter(v.iter()) { + match IntoIterator::into_iter2(v.iter()) { mut iter => { loop { match ::std::iter::Iterator::next(&mut iter) { From c0d2553914adffa9ebaab95358aad3a882632a70 Mon Sep 17 00:00:00 2001 From: kwantam Date: Tue, 21 Apr 2015 15:24:50 -0400 Subject: [PATCH 13/25] unstabilize Words struct Words struct was stabilied by mistake. Unstabilize. --- src/libcollections/lib.rs | 1 + src/libunicode/u_str.rs | 3 ++- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/src/libcollections/lib.rs b/src/libcollections/lib.rs index 5179b04f8824d..9462f7a2d9d8f 100644 --- a/src/libcollections/lib.rs +++ b/src/libcollections/lib.rs @@ -38,6 +38,7 @@ #![feature(unsafe_no_drop_flag, filling_drop)] #![feature(step_by)] #![feature(str_char)] +#![feature(str_words)] #![feature(slice_patterns)] #![feature(debug_builders)] #![feature(utf8_error)] diff --git a/src/libunicode/u_str.rs b/src/libunicode/u_str.rs index 701187ed35a6f..0e424ea0d708e 100644 --- a/src/libunicode/u_str.rs +++ b/src/libunicode/u_str.rs @@ -28,7 +28,8 @@ use core::str::Split; use tables::grapheme::GraphemeCat; /// An iterator over the words of a string, separated by a sequence of whitespace -#[stable(feature = "rust1", since = "1.0.0")] +#[unstable(feature = "str_words", + reason = "words() will be replaced by split_whitespace() in 1.1.0")] pub struct Words<'a> { inner: Filter bool>, fn(&&str) -> bool>, } From 53dd775cf3de679cb13bea7ef91769ab9f215784 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Fri, 17 Apr 2015 14:49:49 -0700 Subject: [PATCH 14/25] std: Remove deprecated AsOsStr/Str/AsSlice traits Cleaning out more deprecated items Conflicts: src/libcore/result.rs --- src/libcollections/slice.rs | 2 +- src/libcollections/str.rs | 2 +- src/libcollections/string.rs | 9 ------- src/libcollections/vec.rs | 12 --------- src/libcore/result.rs | 22 ---------------- src/libcore/slice.rs | 31 ----------------------- src/libcore/str/mod.rs | 24 ------------------ src/libstd/ffi/mod.rs | 8 ------ src/libstd/ffi/os_str.rs | 49 ------------------------------------ 9 files changed, 2 insertions(+), 157 deletions(-) diff --git a/src/libcollections/slice.rs b/src/libcollections/slice.rs index 5be9739cb32de..6622d8a9c4063 100644 --- a/src/libcollections/slice.rs +++ b/src/libcollections/slice.rs @@ -98,7 +98,7 @@ use self::Direction::*; use borrow::{Borrow, BorrowMut, ToOwned}; use vec::Vec; -pub use core::slice::{Chunks, AsSlice, Windows}; +pub use core::slice::{Chunks, Windows}; pub use core::slice::{Iter, IterMut}; pub use core::slice::{IntSliceExt, SplitMut, ChunksMut, Split}; pub use core::slice::{SplitN, RSplitN, SplitNMut, RSplitNMut}; diff --git a/src/libcollections/str.rs b/src/libcollections/str.rs index e1da8b3b3bccd..7a28b56b7c1bb 100644 --- a/src/libcollections/str.rs +++ b/src/libcollections/str.rs @@ -69,7 +69,7 @@ use unicode; use vec::Vec; use slice::SliceConcatExt; -pub use core::str::{FromStr, Utf8Error, Str}; +pub use core::str::{FromStr, Utf8Error}; pub use core::str::{Lines, LinesAny, CharRange}; pub use core::str::{Split, RSplit}; pub use core::str::{SplitN, RSplitN}; diff --git a/src/libcollections/string.rs b/src/libcollections/string.rs index 864801ab0b730..3c045c173f1a9 100644 --- a/src/libcollections/string.rs +++ b/src/libcollections/string.rs @@ -839,15 +839,6 @@ impl<'a, 'b> PartialEq> for &'b str { fn ne(&self, other: &Cow<'a, str>) -> bool { PartialEq::ne(&self[..], &other[..]) } } -#[unstable(feature = "collections", reason = "waiting on Str stabilization")] -#[allow(deprecated)] -impl Str for String { - #[inline] - fn as_slice(&self) -> &str { - unsafe { mem::transmute(&*self.vec) } - } -} - #[stable(feature = "rust1", since = "1.0.0")] impl Default for String { #[inline] diff --git a/src/libcollections/vec.rs b/src/libcollections/vec.rs index 3e08096e16612..4bbfabdd72fd1 100644 --- a/src/libcollections/vec.rs +++ b/src/libcollections/vec.rs @@ -1591,18 +1591,6 @@ impl Ord for Vec { } } -#[unstable(feature = "collections", - reason = "will be replaced by slice syntax")] -#[deprecated(since = "1.0.0", reason = "use &mut s[..] instead")] -#[allow(deprecated)] -impl AsSlice for Vec { - /// Deprecated: use `&mut s[..]` instead. - #[inline] - fn as_slice(&self) -> &[T] { - self - } -} - #[unstable(feature = "collections", reason = "recent addition, needs more experience")] impl<'a, T: Clone> Add<&'a [T]> for Vec { diff --git a/src/libcore/result.rs b/src/libcore/result.rs index 8ae212ea721d2..35cb8398cee92 100644 --- a/src/libcore/result.rs +++ b/src/libcore/result.rs @@ -234,8 +234,6 @@ use fmt; use iter::{Iterator, DoubleEndedIterator, FromIterator, ExactSizeIterator, IntoIterator}; use ops::{FnMut, FnOnce}; use option::Option::{self, None, Some}; -#[allow(deprecated)] -use slice::AsSlice; use slice; /// `Result` is a type that represents either success (`Ok`) or failure (`Err`). @@ -768,26 +766,6 @@ impl Result { // Trait implementations ///////////////////////////////////////////////////////////////////////////// -#[unstable(feature = "core", - reason = "waiting on the stability of the trait itself")] -#[deprecated(since = "1.0.0", - reason = "use inherent method instead")] -#[allow(deprecated)] -impl AsSlice for Result { - /// Converts from `Result` to `&[T]` (without copying) - #[inline] - fn as_slice<'a>(&'a self) -> &'a [T] { - match *self { - Ok(ref x) => slice::ref_slice(x), - Err(_) => { - // work around lack of implicit coercion from fixed-size array to slice - let emp: &[_] = &[]; - emp - } - } - } -} - #[stable(feature = "rust1", since = "1.0.0")] impl IntoIterator for Result { type Item = T; diff --git a/src/libcore/slice.rs b/src/libcore/slice.rs index 4b1742a43482a..102a46a6bc874 100644 --- a/src/libcore/slice.rs +++ b/src/libcore/slice.rs @@ -595,37 +595,6 @@ impl ops::IndexMut for [T] { // Common traits //////////////////////////////////////////////////////////////////////////////// -/// Data that is viewable as a slice. -#[unstable(feature = "core", - reason = "will be replaced by slice syntax")] -#[deprecated(since = "1.0.0", - reason = "use std::convert::AsRef<[T]> instead")] -pub trait AsSlice { - /// Work with `self` as a slice. - fn as_slice<'a>(&'a self) -> &'a [T]; -} - -#[unstable(feature = "core", reason = "trait is experimental")] -#[allow(deprecated)] -impl AsSlice for [T] { - #[inline(always)] - fn as_slice<'a>(&'a self) -> &'a [T] { self } -} - -#[unstable(feature = "core", reason = "trait is experimental")] -#[allow(deprecated)] -impl<'a, T, U: ?Sized + AsSlice> AsSlice for &'a U { - #[inline(always)] - fn as_slice(&self) -> &[T] { AsSlice::as_slice(*self) } -} - -#[unstable(feature = "core", reason = "trait is experimental")] -#[allow(deprecated)] -impl<'a, T, U: ?Sized + AsSlice> AsSlice for &'a mut U { - #[inline(always)] - fn as_slice(&self) -> &[T] { AsSlice::as_slice(*self) } -} - #[stable(feature = "rust1", since = "1.0.0")] impl<'a, T> Default for &'a [T] { #[stable(feature = "rust1", since = "1.0.0")] diff --git a/src/libcore/str/mod.rs b/src/libcore/str/mod.rs index 2d6ef39361e8a..9f2adbb9909fc 100644 --- a/src/libcore/str/mod.rs +++ b/src/libcore/str/mod.rs @@ -1465,30 +1465,6 @@ mod traits { } } -/// Any string that can be represented as a slice -#[unstable(feature = "core", - reason = "Instead of taking this bound generically, this trait will be \ - replaced with one of slicing syntax (&foo[..]), deref coercions, or \ - a more generic conversion trait")] -#[deprecated(since = "1.0.0", - reason = "use std::convert::AsRef instead")] -pub trait Str { - /// Work with `self` as a slice. - fn as_slice<'a>(&'a self) -> &'a str; -} - -#[allow(deprecated)] -impl Str for str { - #[inline] - fn as_slice<'a>(&'a self) -> &'a str { self } -} - -#[allow(deprecated)] -impl<'a, S: ?Sized> Str for &'a S where S: Str { - #[inline] - fn as_slice(&self) -> &str { Str::as_slice(*self) } -} - /// Methods for string slices #[allow(missing_docs)] #[doc(hidden)] diff --git a/src/libstd/ffi/mod.rs b/src/libstd/ffi/mod.rs index 99becb67a5a7a..dfe706e077366 100644 --- a/src/libstd/ffi/mod.rs +++ b/src/libstd/ffi/mod.rs @@ -20,11 +20,3 @@ pub use self::os_str::{OsString, OsStr}; mod c_str; mod os_str; - -// FIXME (#21670): these should be defined in the os_str module -/// Freely convertible to an `&OsStr` slice. -#[unstable(feature = "std_misc")] -pub trait AsOsStr { - /// Converts to an `&OsStr` slice. - fn as_os_str(&self) -> &OsStr; -} diff --git a/src/libstd/ffi/os_str.rs b/src/libstd/ffi/os_str.rs index 08b41915d9153..97bf33335b02a 100644 --- a/src/libstd/ffi/os_str.rs +++ b/src/libstd/ffi/os_str.rs @@ -46,7 +46,6 @@ use vec::Vec; use sys::os_str::{Buf, Slice}; use sys_common::{AsInner, IntoInner, FromInner}; -use super::AsOsStr; /// Owned, mutable OS strings. #[derive(Clone)] @@ -226,14 +225,6 @@ impl OsStr { s.as_ref() } - /// Coerces directly from a `&str` slice to a `&OsStr` slice. - #[stable(feature = "rust1", since = "1.0.0")] - #[deprecated(since = "1.0.0", - reason = "use `OsStr::new` instead")] - pub fn from_str(s: &str) -> &OsStr { - unsafe { mem::transmute(Slice::from_str(s)) } - } - /// Yields a `&str` slice if the `OsStr` is valid unicode. /// /// This conversion may entail doing a check for UTF-8 validity. @@ -378,46 +369,6 @@ impl ToOwned for OsStr { fn to_owned(&self) -> OsString { self.to_os_string() } } -#[stable(feature = "rust1", since = "1.0.0")] -#[deprecated(since = "1.0.0", reason = "trait is deprecated")] -impl<'a, T: AsOsStr + ?Sized> AsOsStr for &'a T { - fn as_os_str(&self) -> &OsStr { - (*self).as_os_str() - } -} - -#[stable(feature = "rust1", since = "1.0.0")] -#[deprecated(since = "1.0.0", reason = "trait is deprecated")] -impl AsOsStr for OsStr { - fn as_os_str(&self) -> &OsStr { - self - } -} - -#[stable(feature = "rust1", since = "1.0.0")] -#[deprecated(since = "1.0.0", reason = "trait is deprecated")] -impl AsOsStr for OsString { - fn as_os_str(&self) -> &OsStr { - &self[..] - } -} - -#[stable(feature = "rust1", since = "1.0.0")] -#[deprecated(since = "1.0.0", reason = "trait is deprecated")] -impl AsOsStr for str { - fn as_os_str(&self) -> &OsStr { - unsafe { mem::transmute(Slice::from_str(self)) } - } -} - -#[stable(feature = "rust1", since = "1.0.0")] -#[deprecated(since = "1.0.0", reason = "trait is deprecated")] -impl AsOsStr for String { - fn as_os_str(&self) -> &OsStr { - unsafe { mem::transmute(Slice::from_str(self)) } - } -} - #[stable(feature = "rust1", since = "1.0.0")] impl AsRef for OsStr { fn as_ref(&self) -> &OsStr { From fd685ce2395357c432068dd4611ce60071162364 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Fri, 17 Apr 2015 14:50:42 -0700 Subject: [PATCH 15/25] std: Remove deprecated AsPath trait --- src/libstd/path.rs | 32 -------------------------------- 1 file changed, 32 deletions(-) diff --git a/src/libstd/path.rs b/src/libstd/path.rs index 46efd378cc680..5ef94ee0b66b7 100644 --- a/src/libstd/path.rs +++ b/src/libstd/path.rs @@ -1184,14 +1184,6 @@ impl AsRef for PathBuf { } } -#[stable(feature = "rust1", since = "1.0.0")] -#[deprecated(since = "1.0.0", reason = "trait is deprecated")] -impl AsOsStr for PathBuf { - fn as_os_str(&self) -> &OsStr { - &self.inner[..] - } -} - #[stable(feature = "rust1", since = "1.0.0")] impl Into for PathBuf { fn into(self) -> OsString { @@ -1652,14 +1644,6 @@ impl AsRef for Path { } } -#[stable(feature = "rust1", since = "1.0.0")] -#[deprecated(since = "1.0.0", reason = "trait is deprecated")] -impl AsOsStr for Path { - fn as_os_str(&self) -> &OsStr { - &self.inner - } -} - #[stable(feature = "rust1", since = "1.0.0")] impl fmt::Debug for Path { fn fmt(&self, formatter: &mut fmt::Formatter) -> Result<(), fmt::Error> { @@ -1711,22 +1695,6 @@ impl cmp::Ord for Path { } } -/// Freely convertible to a `Path`. -#[unstable(feature = "std_misc")] -#[deprecated(since = "1.0.0", reason = "use std::convert::AsRef instead")] -pub trait AsPath { - /// Converts to a `Path`. - #[unstable(feature = "std_misc")] - fn as_path(&self) -> &Path; -} - -#[unstable(feature = "std_misc")] -#[deprecated(since = "1.0.0", reason = "use std::convert::AsRef instead")] -#[allow(deprecated)] -impl AsPath for T { - fn as_path(&self) -> &Path { Path::new(self.as_os_str()) } -} - #[stable(feature = "rust1", since = "1.0.0")] impl AsRef for Path { fn as_ref(&self) -> &Path { self } From 0372484acc0270585479caf8cdccc6eb0106d8be Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Fri, 17 Apr 2015 15:32:42 -0700 Subject: [PATCH 16/25] std: Remove deprecated/unstable num functionality This commit removes all the old casting/generic traits from `std::num` that are no longer in use by the standard library. This additionally removes the old `strconv` module which has not seen much use in quite a long time. All generic functionality has been supplanted with traits in the `num` crate and the `strconv` module is supplanted with the [rust-strconv crate][rust-strconv]. [rust-strconv]: https://github.com/lifthrasiir/rust-strconv This is a breaking change due to the removal of these deprecated crates, and the alternative crates are listed above. [breaking-change] Conflicts: src/libstd/num/strconv.rs --- src/libcollections/string.rs | 8 - src/libcore/fmt/float.rs | 43 +- src/libcore/fmt/mod.rs | 24 +- src/libcore/fmt/num.rs | 43 +- src/libcore/iter.rs | 76 +- src/libcore/marker.rs | 81 +- src/libcore/nonzero.rs | 11 +- src/libcore/num/f32.rs | 76 -- src/libcore/num/f64.rs | 76 -- src/libcore/num/mod.rs | 1611 ++------------------------ src/libcore/num/wrapping.rs | 31 - src/libcore/slice.rs | 2 +- src/libcore/str/mod.rs | 1 - src/librand/chacha.rs | 2 - src/librand/distributions/mod.rs | 2 +- src/librand/distributions/range.rs | 10 +- src/librbml/lib.rs | 51 +- src/librustc/lib.rs | 4 + src/librustc/macros.rs | 46 + src/librustc/metadata/common.rs | 64 +- src/librustc/metadata/cstore.rs | 12 +- src/librustc/metadata/decoder.rs | 7 +- src/librustc/middle/astencode.rs | 4 +- src/librustc/middle/const_eval.rs | 2 +- src/librustc/middle/lang_items.rs | 12 +- src/librustc/middle/ty.rs | 2 +- src/librustc/util/num.rs | 98 ++ src/librustc_back/sha2.rs | 7 +- src/librustc_trans/back/lto.rs | 23 +- src/librustc_trans/trans/adt.rs | 2 - src/librustc_trans/trans/type_of.rs | 2 - src/libserialize/json.rs | 28 +- src/libstd/collections/hash/table.rs | 2 +- src/libstd/io/error.rs | 7 - src/libstd/lib.rs | 1 + src/libstd/net/mod.rs | 21 +- src/libstd/num/f32.rs | 434 +------ src/libstd/num/f64.rs | 407 +------ src/libstd/num/mod.rs | 1093 +---------------- src/libstd/num/strconv.rs | 558 --------- src/libstd/path.rs | 2 +- src/libstd/sync/condvar.rs | 8 - src/libstd/sys/common/net.rs | 971 ---------------- src/libstd/sys/common/wtf8.rs | 2 - src/libstd/sys/unix/condvar.rs | 7 +- src/libstd/sys/unix/mod.rs | 24 +- src/libstd/sys/unix/process2.rs | 16 +- src/libstd/thread/mod.rs | 16 - src/libstd/time/duration.rs | 9 +- src/libsyntax/ast.rs | 24 +- src/libsyntax/codemap.rs | 7 +- src/libsyntax/parse/mod.rs | 2 - src/libtest/lib.rs | 5 +- src/libtest/stats.rs | 147 ++- 54 files changed, 623 insertions(+), 5601 deletions(-) create mode 100644 src/librustc/macros.rs create mode 100644 src/librustc/util/num.rs delete mode 100644 src/libstd/num/strconv.rs delete mode 100644 src/libstd/sys/common/net.rs diff --git a/src/libcollections/string.rs b/src/libcollections/string.rs index 3c045c173f1a9..3910c60e75293 100644 --- a/src/libcollections/string.rs +++ b/src/libcollections/string.rs @@ -1049,14 +1049,6 @@ impl<'a> IntoCow<'a, str> for &'a str { } } -#[allow(deprecated)] -impl<'a> Str for Cow<'a, str> { - #[inline] - fn as_slice<'b>(&'b self) -> &'b str { - &**self - } -} - #[stable(feature = "rust1", since = "1.0.0")] impl fmt::Write for String { #[inline] diff --git a/src/libcore/fmt/float.rs b/src/libcore/fmt/float.rs index 72c25c6804022..4b75bd5f67e3d 100644 --- a/src/libcore/fmt/float.rs +++ b/src/libcore/fmt/float.rs @@ -11,15 +11,15 @@ pub use self::ExponentFormat::*; pub use self::SignificantDigits::*; -use char::{self, CharExt}; +use prelude::*; + +use char; use fmt; -use iter::Iterator; -use num::{cast, Float, ToPrimitive}; +use num::Float; use num::FpCategory as Fp; -use ops::FnOnce; -use result::Result::Ok; -use slice::{self, SliceExt}; -use str::{self, StrExt}; +use ops::{Div, Rem, Mul}; +use slice; +use str; /// A flag that specifies whether to use exponential (scientific) notation. pub enum ExponentFormat { @@ -42,6 +42,21 @@ pub enum SignificantDigits { DigExact(usize) } +#[doc(hidden)] +pub trait MyFloat: Float + PartialEq + PartialOrd + Div + + Mul + Rem + Copy { + fn from_u32(u: u32) -> Self; + fn to_i32(&self) -> i32; +} + +macro_rules! doit { + ($($t:ident)*) => ($(impl MyFloat for $t { + fn from_u32(u: u32) -> $t { u as $t } + fn to_i32(&self) -> i32 { *self as i32 } + })*) +} +doit! { f32 f64 } + /// Converts a float number to its string representation. /// This is meant to be a common base implementation for various formatting styles. /// The number is assumed to be non-negative, callers use `Formatter::pad_integral` @@ -63,7 +78,7 @@ pub enum SignificantDigits { /// # Panics /// /// - Panics if `num` is negative. -pub fn float_to_str_bytes_common( +pub fn float_to_str_bytes_common( num: T, digits: SignificantDigits, exp_format: ExponentFormat, @@ -72,10 +87,10 @@ pub fn float_to_str_bytes_common( ) -> U where F: FnOnce(&str) -> U, { - let _0: T = Float::zero(); - let _1: T = Float::one(); + let _0: T = T::zero(); + let _1: T = T::one(); let radix: u32 = 10; - let radix_f: T = cast(radix).unwrap(); + let radix_f = T::from_u32(radix); assert!(num.is_nan() || num >= _0, "float_to_str_bytes_common: number is negative"); @@ -99,7 +114,7 @@ pub fn float_to_str_bytes_common( let (num, exp) = match exp_format { ExpDec if num != _0 => { let exp = num.log10().floor(); - (num / radix_f.powf(exp), cast::(exp).unwrap()) + (num / radix_f.powf(exp), exp.to_i32()) } _ => (num, 0) }; @@ -114,7 +129,7 @@ pub fn float_to_str_bytes_common( deccum = deccum / radix_f; deccum = deccum.trunc(); - let c = char::from_digit(current_digit.to_isize().unwrap() as u32, radix); + let c = char::from_digit(current_digit.to_i32() as u32, radix); buf[end] = c.unwrap() as u8; end += 1; @@ -158,7 +173,7 @@ pub fn float_to_str_bytes_common( let current_digit = deccum.trunc(); - let c = char::from_digit(current_digit.to_isize().unwrap() as u32, radix); + let c = char::from_digit(current_digit.to_i32() as u32, radix); buf[end] = c.unwrap() as u8; end += 1; diff --git a/src/libcore/fmt/mod.rs b/src/libcore/fmt/mod.rs index 80c661b260cbe..5cff0186f2506 100644 --- a/src/libcore/fmt/mod.rs +++ b/src/libcore/fmt/mod.rs @@ -12,21 +12,16 @@ #![stable(feature = "rust1", since = "1.0.0")] +use prelude::*; + use cell::{Cell, RefCell, Ref, RefMut, BorrowState}; -use char::CharExt; -use clone::Clone; -use iter::Iterator; -use marker::{Copy, PhantomData, Sized}; +use marker::PhantomData; use mem; -use num::Float; -use option::Option; -use option::Option::{Some, None}; -use result::Result::Ok; -use ops::{Deref, FnOnce}; +use ops::Deref; use result; -use slice::SliceExt; +use num::Float; use slice; -use str::{self, StrExt}; +use str; use self::rt::v1::Alignment; pub use self::num::radix; @@ -912,7 +907,8 @@ impl<'a, T> Pointer for &'a mut T { } // Common code of floating point Debug and Display. -fn float_to_str_common(num: &T, precision: Option, post: F) -> Result +fn float_to_str_common(num: &T, precision: Option, + post: F) -> Result where F : FnOnce(&str) -> Result { let digits = match precision { Some(i) => float::DigExact(i), @@ -950,8 +946,6 @@ macro_rules! floating { ($ty:ident) => { #[stable(feature = "rust1", since = "1.0.0")] impl LowerExp for $ty { fn fmt(&self, fmt: &mut Formatter) -> Result { - use num::Float; - let digits = match fmt.precision { Some(i) => float::DigExact(i), None => float::DigMax(6), @@ -969,8 +963,6 @@ macro_rules! floating { ($ty:ident) => { #[stable(feature = "rust1", since = "1.0.0")] impl UpperExp for $ty { fn fmt(&self, fmt: &mut Formatter) -> Result { - use num::Float; - let digits = match fmt.precision { Some(i) => float::DigExact(i), None => float::DigMax(6), diff --git a/src/libcore/fmt/num.rs b/src/libcore/fmt/num.rs index 76c975902aabb..122fffc595905 100644 --- a/src/libcore/fmt/num.rs +++ b/src/libcore/fmt/num.rs @@ -14,12 +14,28 @@ #![allow(unsigned_negation)] +use prelude::*; + use fmt; -use iter::Iterator; -use num::{Int, cast}; -use slice::SliceExt; +use num::Zero; +use ops::{Div, Rem, Sub}; use str; +#[doc(hidden)] +trait Int: Zero + PartialEq + PartialOrd + Div + Rem + + Sub + Copy { + fn from_u8(u: u8) -> Self; + fn to_u8(&self) -> u8; +} + +macro_rules! doit { + ($($t:ident)*) => ($(impl Int for $t { + fn from_u8(u: u8) -> $t { u as $t } + fn to_u8(&self) -> u8 { *self as u8 } + })*) +} +doit! { i8 i16 i32 i64 isize u8 u16 u32 u64 usize } + /// A type that represents a specific radix #[doc(hidden)] trait GenericRadix { @@ -33,33 +49,32 @@ trait GenericRadix { fn digit(&self, x: u8) -> u8; /// Format an integer using the radix using a formatter. - #[allow(deprecated)] // Int fn fmt_int(&self, mut x: T, f: &mut fmt::Formatter) -> fmt::Result { // The radix can be as low as 2, so we need a buffer of at least 64 // characters for a base 2 number. - let zero = Int::zero(); + let zero = T::zero(); let is_positive = x >= zero; let mut buf = [0; 64]; let mut curr = buf.len(); - let base = cast(self.base()).unwrap(); + let base = T::from_u8(self.base()); if is_positive { // Accumulate each digit of the number from the least significant // to the most significant figure. for byte in buf.iter_mut().rev() { - let n = x % base; // Get the current place value. - x = x / base; // Deaccumulate the number. - *byte = self.digit(cast(n).unwrap()); // Store the digit in the buffer. + let n = x % base; // Get the current place value. + x = x / base; // Deaccumulate the number. + *byte = self.digit(n.to_u8()); // Store the digit in the buffer. curr -= 1; - if x == zero { break }; // No more digits left to accumulate. + if x == zero { break }; // No more digits left to accumulate. } } else { // Do the same as above, but accounting for two's complement. for byte in buf.iter_mut().rev() { - let n = zero - (x % base); // Get the current place value. - x = x / base; // Deaccumulate the number. - *byte = self.digit(cast(n).unwrap()); // Store the digit in the buffer. + let n = zero - (x % base); // Get the current place value. + x = x / base; // Deaccumulate the number. + *byte = self.digit(n.to_u8()); // Store the digit in the buffer. curr -= 1; - if x == zero { break }; // No more digits left to accumulate. + if x == zero { break }; // No more digits left to accumulate. } } let buf = unsafe { str::from_utf8_unchecked(&buf[curr..]) }; diff --git a/src/libcore/iter.rs b/src/libcore/iter.rs index e44b0d1147cbc..12c0a75e1efe4 100644 --- a/src/libcore/iter.rs +++ b/src/libcore/iter.rs @@ -64,7 +64,7 @@ use cmp::{Ord, PartialOrd, PartialEq}; use default::Default; use marker; use mem; -use num::{Int, Zero, One}; +use num::{Zero, One}; use ops::{self, Add, Sub, FnMut, Mul, RangeFrom}; use option::Option::{self, Some, None}; use marker::Sized; @@ -2646,80 +2646,6 @@ impl Iterator for StepBy> { } } -/// An iterator over the range [start, stop] by `step`. It handles overflow by stopping. -#[derive(Clone)] -#[unstable(feature = "core", - reason = "likely to be replaced by range notation and adapters")] -pub struct RangeStepInclusive { - state: A, - stop: A, - step: A, - rev: bool, - done: bool, -} - -/// Returns an iterator over the range [start, stop] by `step`. -/// -/// It handles overflow by stopping. -/// -/// # Examples -/// -/// ``` -/// # #![feature(core)] -/// use std::iter::range_step_inclusive; -/// -/// for i in range_step_inclusive(0, 10, 2) { -/// println!("{}", i); -/// } -/// ``` -/// -/// This prints: -/// -/// ```text -/// 0 -/// 2 -/// 4 -/// 6 -/// 8 -/// 10 -/// ``` -#[inline] -#[unstable(feature = "core", - reason = "likely to be replaced by range notation and adapters")] -#[allow(deprecated)] -pub fn range_step_inclusive(start: A, stop: A, step: A) -> RangeStepInclusive { - let rev = step < Int::zero(); - RangeStepInclusive { - state: start, - stop: stop, - step: step, - rev: rev, - done: false, - } -} - -#[unstable(feature = "core", - reason = "likely to be replaced by range notation and adapters")] -#[allow(deprecated)] -impl Iterator for RangeStepInclusive { - type Item = A; - - #[inline] - fn next(&mut self) -> Option { - if !self.done && ((self.rev && self.state >= self.stop) || - (!self.rev && self.state <= self.stop)) { - let result = self.state; - match self.state.checked_add(self.step) { - Some(x) => self.state = x, - None => self.done = true - } - Some(result) - } else { - None - } - } -} - macro_rules! range_exact_iter_impl { ($($t:ty)*) => ($( #[stable(feature = "rust1", since = "1.0.0")] diff --git a/src/libcore/marker.rs b/src/libcore/marker.rs index d6a7126a883f7..fdabdbc5ed4ce 100644 --- a/src/libcore/marker.rs +++ b/src/libcore/marker.rs @@ -35,7 +35,16 @@ use hash::Hasher; #[stable(feature = "rust1", since = "1.0.0")] #[lang="send"] #[rustc_on_unimplemented = "`{Self}` cannot be sent between threads safely"] -#[allow(deprecated)] +#[cfg(not(stage0))] +pub unsafe trait Send { + // empty. +} + +/// Types able to be transferred across thread boundaries. +#[stable(feature = "rust1", since = "1.0.0")] +#[lang="send"] +#[rustc_on_unimplemented = "`{Self}` cannot be sent between threads safely"] +#[cfg(stage0)] pub unsafe trait Send : MarkerTrait { // empty. } @@ -51,7 +60,17 @@ impl !Send for Managed { } #[lang="sized"] #[rustc_on_unimplemented = "`{Self}` does not have a constant size known at compile-time"] #[fundamental] // for Default, for example, which requires that `[T]: !Default` be evaluatable -#[allow(deprecated)] +#[cfg(not(stage0))] +pub trait Sized { + // Empty. +} + +/// Types with a constant size known at compile-time. +#[stable(feature = "rust1", since = "1.0.0")] +#[lang="sized"] +#[rustc_on_unimplemented = "`{Self}` does not have a constant size known at compile-time"] +#[fundamental] // for Default, for example, which requires that `[T]: !Default` be evaluatable +#[cfg(stage0)] pub trait Sized : MarkerTrait { // Empty. } @@ -199,13 +218,23 @@ pub trait Copy : Clone { /// the `sync` crate do ensure that any mutation cannot cause data /// races. Hence these types are `Sync`. /// -/// Any types with interior mutability must also use the `std::cell::UnsafeCell` wrapper around the -/// value(s) which can be mutated when behind a `&` reference; not doing this is undefined -/// behaviour (for example, `transmute`-ing from `&T` to `&mut T` is illegal). +/// Any types with interior mutability must also use the `std::cell::UnsafeCell` +/// wrapper around the value(s) which can be mutated when behind a `&` +/// reference; not doing this is undefined behaviour (for example, +/// `transmute`-ing from `&T` to `&mut T` is illegal). +#[cfg(not(stage0))] +#[stable(feature = "rust1", since = "1.0.0")] +#[lang="sync"] +#[rustc_on_unimplemented = "`{Self}` cannot be shared between threads safely"] +pub unsafe trait Sync { + // Empty +} + +/// dox +#[cfg(stage0)] #[stable(feature = "rust1", since = "1.0.0")] #[lang="sync"] #[rustc_on_unimplemented = "`{Self}` cannot be shared between threads safely"] -#[allow(deprecated)] pub unsafe trait Sync : MarkerTrait { // Empty } @@ -272,42 +301,20 @@ macro_rules! impls{ ) } -/// `MarkerTrait` is deprecated and no longer needed. +/// dox #[stable(feature = "rust1", since = "1.0.0")] -#[deprecated(since = "1.0.0", reason = "No longer needed")] -#[allow(deprecated)] #[cfg(stage0)] pub trait MarkerTrait : PhantomFn { } -/// `MarkerTrait` is deprecated and no longer needed. -#[stable(feature = "rust1", since = "1.0.0")] -#[deprecated(since = "1.0.0", reason = "No longer needed")] -#[allow(deprecated)] -#[cfg(not(stage0))] -pub trait MarkerTrait { } - -#[allow(deprecated)] -impl MarkerTrait for T { } +#[cfg(stage0)] +impl MarkerTrait for T {} -/// `PhantomFn` is a deprecated marker trait that is no longer needed. +/// dox #[lang="phantom_fn"] -#[stable(feature = "rust1", since = "1.0.0")] -#[deprecated(since = "1.0.0", reason = "No longer needed")] #[cfg(stage0)] pub trait PhantomFn { } -/// `PhantomFn` is a deprecated marker trait that is no longer needed. -#[stable(feature = "rust1", since = "1.0.0")] -#[deprecated(since = "1.0.0", reason = "No longer needed")] -#[cfg(not(stage0))] -pub trait PhantomFn { -} - -#[allow(deprecated)] -#[cfg(not(stage0))] -impl PhantomFn for T { } - /// `PhantomData` allows you to describe that a type acts as if it stores a value of type `T`, /// even though it does not. This allows you to inform the compiler about certain safety properties /// of your code. @@ -454,8 +461,14 @@ mod impls { #[rustc_reflect_like] #[unstable(feature = "core", reason = "requires RFC and more experience")] #[allow(deprecated)] -pub trait Reflect : MarkerTrait { -} +#[cfg(not(stage0))] +pub trait Reflect {} + +/// dox +#[rustc_reflect_like] +#[unstable(feature = "core", reason = "requires RFC and more experience")] +#[cfg(stage0)] +pub trait Reflect: MarkerTrait {} impl Reflect for .. { } diff --git a/src/libcore/nonzero.rs b/src/libcore/nonzero.rs index db2d1b2f1fdaa..9ea44c39fe9c6 100644 --- a/src/libcore/nonzero.rs +++ b/src/libcore/nonzero.rs @@ -10,12 +10,17 @@ //! Exposes the NonZero lang item which provides optimization hints. -use marker::{Sized, MarkerTrait}; +use marker::Sized; use ops::Deref; +#[cfg(stage0)] use marker::MarkerTrait; /// Unsafe trait to indicate what types are usable with the NonZero struct -#[allow(deprecated)] -pub unsafe trait Zeroable : MarkerTrait {} +#[cfg(not(stage0))] +pub unsafe trait Zeroable {} + +/// Unsafe trait to indicate what types are usable with the NonZero struct +#[cfg(stage0)] +pub unsafe trait Zeroable: MarkerTrait {} unsafe impl Zeroable for *const T {} unsafe impl Zeroable for *mut T {} diff --git a/src/libcore/num/f32.rs b/src/libcore/num/f32.rs index 12b45a766b639..a9afa5078d21f 100644 --- a/src/libcore/num/f32.rs +++ b/src/libcore/num/f32.rs @@ -20,7 +20,6 @@ use intrinsics; use mem; use num::Float; use num::FpCategory as Fp; -use option::Option; #[stable(feature = "rust1", since = "1.0.0")] pub const RADIX: u32 = 2; @@ -33,19 +32,6 @@ pub const DIGITS: u32 = 6; #[stable(feature = "rust1", since = "1.0.0")] pub const EPSILON: f32 = 1.19209290e-07_f32; -/// Smallest finite f32 value -#[stable(feature = "rust1", since = "1.0.0")] -#[deprecated(since = "1.0.0", reason = "use `std::f32::MIN`")] -pub const MIN_VALUE: f32 = -3.40282347e+38_f32; -/// Smallest positive, normalized f32 value -#[stable(feature = "rust1", since = "1.0.0")] -#[deprecated(since = "1.0.0", reason = "use `std::f32::MIN_POSITIVE`")] -pub const MIN_POS_VALUE: f32 = 1.17549435e-38_f32; -/// Largest finite f32 value -#[stable(feature = "rust1", since = "1.0.0")] -#[deprecated(since = "1.0.0", reason = "use `std::f32::MAX`")] -pub const MAX_VALUE: f32 = 3.40282347e+38_f32; - /// Smallest finite f32 value #[stable(feature = "rust1", since = "1.0.0")] pub const MIN: f32 = -3.40282347e+38_f32; @@ -118,26 +104,14 @@ pub mod consts { #[stable(feature = "rust1", since = "1.0.0")] pub const FRAC_2_SQRT_PI: f32 = 1.12837916709551257389615890312154517_f32; - #[stable(feature = "rust1", since = "1.0.0")] - #[deprecated(since = "1.0.0", reason = "renamed to FRAC_2_SQRT_PI")] - pub const FRAC_2_SQRTPI: f32 = 1.12837916709551257389615890312154517_f32; - /// sqrt(2.0) #[stable(feature = "rust1", since = "1.0.0")] pub const SQRT_2: f32 = 1.41421356237309504880168872420969808_f32; - #[stable(feature = "rust1", since = "1.0.0")] - #[deprecated(since = "1.0.0", reason = "renamed to SQRT_2")] - pub const SQRT2: f32 = 1.41421356237309504880168872420969808_f32; - /// 1.0/sqrt(2.0) #[stable(feature = "rust1", since = "1.0.0")] pub const FRAC_1_SQRT_2: f32 = 0.707106781186547524400844362104849039_f32; - #[stable(feature = "rust1", since = "1.0.0")] - #[deprecated(since = "1.0.0", reason = "renamed to FRAC_1_SQRT_2")] - pub const FRAC_1_SQRT2: f32 = 0.707106781186547524400844362104849039_f32; - /// Euler's number #[stable(feature = "rust1", since = "1.0.0")] pub const E: f32 = 2.71828182845904523536028747135266250_f32; @@ -218,56 +192,6 @@ impl Float for f32 { } } - #[inline] - #[unstable(feature = "core")] - #[deprecated(since = "1.0.0")] - fn mantissa_digits(_: Option) -> usize { MANTISSA_DIGITS as usize } - - #[inline] - #[unstable(feature = "core")] - #[deprecated(since = "1.0.0")] - fn digits(_: Option) -> usize { DIGITS as usize } - - #[inline] - #[unstable(feature = "core")] - #[deprecated(since = "1.0.0")] - fn epsilon() -> f32 { EPSILON } - - #[inline] - #[unstable(feature = "core")] - #[deprecated(since = "1.0.0")] - fn min_exp(_: Option) -> isize { MIN_EXP as isize } - - #[inline] - #[unstable(feature = "core")] - #[deprecated(since = "1.0.0")] - fn max_exp(_: Option) -> isize { MAX_EXP as isize } - - #[inline] - #[unstable(feature = "core")] - #[deprecated(since = "1.0.0")] - fn min_10_exp(_: Option) -> isize { MIN_10_EXP as isize } - - #[inline] - #[unstable(feature = "core")] - #[deprecated(since = "1.0.0")] - fn max_10_exp(_: Option) -> isize { MAX_10_EXP as isize } - - #[inline] - #[unstable(feature = "core")] - #[deprecated(since = "1.0.0")] - fn min_value() -> f32 { MIN } - - #[inline] - #[unstable(feature = "core")] - #[deprecated(since = "1.0.0")] - fn min_pos_value(_: Option) -> f32 { MIN_POSITIVE } - - #[inline] - #[unstable(feature = "core")] - #[deprecated(since = "1.0.0")] - fn max_value() -> f32 { MAX } - /// Returns the mantissa, exponent and sign as integers. fn integer_decode(self) -> (u64, i16, i8) { let bits: u32 = unsafe { mem::transmute(self) }; diff --git a/src/libcore/num/f64.rs b/src/libcore/num/f64.rs index 058acedd9c988..fa9660a60e918 100644 --- a/src/libcore/num/f64.rs +++ b/src/libcore/num/f64.rs @@ -20,7 +20,6 @@ use intrinsics; use mem; use num::Float; use num::FpCategory as Fp; -use option::Option; #[stable(feature = "rust1", since = "1.0.0")] pub const RADIX: u32 = 2; @@ -33,19 +32,6 @@ pub const DIGITS: u32 = 15; #[stable(feature = "rust1", since = "1.0.0")] pub const EPSILON: f64 = 2.2204460492503131e-16_f64; -/// Smallest finite f64 value -#[stable(feature = "rust1", since = "1.0.0")] -#[deprecated(since = "1.0.0", reason = "use `std::f64::MIN`")] -pub const MIN_VALUE: f64 = -1.7976931348623157e+308_f64; -/// Smallest positive, normalized f64 value -#[stable(feature = "rust1", since = "1.0.0")] -#[deprecated(since = "1.0.0", reason = "use `std::f64::MIN_POSITIVE`")] -pub const MIN_POS_VALUE: f64 = 2.2250738585072014e-308_f64; -/// Largest finite f64 value -#[stable(feature = "rust1", since = "1.0.0")] -#[deprecated(since = "1.0.0", reason = "use `std::f64::MAX`")] -pub const MAX_VALUE: f64 = 1.7976931348623157e+308_f64; - /// Smallest finite f64 value #[stable(feature = "rust1", since = "1.0.0")] pub const MIN: f64 = -1.7976931348623157e+308_f64; @@ -118,26 +104,14 @@ pub mod consts { #[stable(feature = "rust1", since = "1.0.0")] pub const FRAC_2_SQRT_PI: f64 = 1.12837916709551257389615890312154517_f64; - #[stable(feature = "rust1", since = "1.0.0")] - #[deprecated(since = "1.0.0", reason = "renamed to FRAC_2_SQRT_PI")] - pub const FRAC_2_SQRTPI: f64 = 1.12837916709551257389615890312154517_f64; - /// sqrt(2.0) #[stable(feature = "rust1", since = "1.0.0")] pub const SQRT_2: f64 = 1.41421356237309504880168872420969808_f64; - #[stable(feature = "rust1", since = "1.0.0")] - #[deprecated(since = "1.0.0", reason = "renamed to SQRT_2")] - pub const SQRT2: f64 = 1.41421356237309504880168872420969808_f64; - /// 1.0/sqrt(2.0) #[stable(feature = "rust1", since = "1.0.0")] pub const FRAC_1_SQRT_2: f64 = 0.707106781186547524400844362104849039_f64; - #[stable(feature = "rust1", since = "1.0.0")] - #[deprecated(since = "1.0.0", reason = "renamed to FRAC_1_SQRT_2")] - pub const FRAC_1_SQRT2: f64 = 0.707106781186547524400844362104849039_f64; - /// Euler's number #[stable(feature = "rust1", since = "1.0.0")] pub const E: f64 = 2.71828182845904523536028747135266250_f64; @@ -218,56 +192,6 @@ impl Float for f64 { } } - #[inline] - #[unstable(feature = "core")] - #[deprecated(since = "1.0.0")] - fn mantissa_digits(_: Option) -> usize { MANTISSA_DIGITS as usize } - - #[inline] - #[unstable(feature = "core")] - #[deprecated(since = "1.0.0")] - fn digits(_: Option) -> usize { DIGITS as usize } - - #[inline] - #[unstable(feature = "core")] - #[deprecated(since = "1.0.0")] - fn epsilon() -> f64 { EPSILON } - - #[inline] - #[unstable(feature = "core")] - #[deprecated(since = "1.0.0")] - fn min_exp(_: Option) -> isize { MIN_EXP as isize } - - #[inline] - #[unstable(feature = "core")] - #[deprecated(since = "1.0.0")] - fn max_exp(_: Option) -> isize { MAX_EXP as isize } - - #[inline] - #[unstable(feature = "core")] - #[deprecated(since = "1.0.0")] - fn min_10_exp(_: Option) -> isize { MIN_10_EXP as isize } - - #[inline] - #[unstable(feature = "core")] - #[deprecated(since = "1.0.0")] - fn max_10_exp(_: Option) -> isize { MAX_10_EXP as isize } - - #[inline] - #[unstable(feature = "core")] - #[deprecated(since = "1.0.0")] - fn min_value() -> f64 { MIN } - - #[inline] - #[unstable(feature = "core")] - #[deprecated(since = "1.0.0")] - fn min_pos_value(_: Option) -> f64 { MIN_POSITIVE } - - #[inline] - #[unstable(feature = "core")] - #[deprecated(since = "1.0.0")] - fn max_value() -> f64 { MAX } - /// Returns the mantissa, exponent and sign as integers. fn integer_decode(self) -> (u64, i16, i8) { let bits: u64 = unsafe { mem::transmute(self) }; diff --git a/src/libcore/num/mod.rs b/src/libcore/num/mod.rs index 6dd5b8edcf33f..101ab77a09ef0 100644 --- a/src/libcore/num/mod.rs +++ b/src/libcore/num/mod.rs @@ -15,18 +15,15 @@ #![stable(feature = "rust1", since = "1.0.0")] #![allow(missing_docs)] -use self::wrapping::{OverflowingOps, WrappingOps}; +use self::wrapping::OverflowingOps; use char::CharExt; -use clone::Clone; -use cmp::{PartialEq, Eq, PartialOrd, Ord}; +use cmp::{Eq, PartialOrd}; use fmt; use intrinsics; use iter::Iterator; use marker::Copy; use mem::size_of; -use ops::{Add, Sub, Mul, Div, Rem, Neg}; -use ops::{Not, BitAnd, BitOr, BitXor, Shl, Shr}; use option::Option::{self, Some, None}; use result::Result::{self, Ok, Err}; use str::{FromStr, StrExt}; @@ -100,407 +97,6 @@ macro_rules! zero_one_impl_float { } zero_one_impl_float! { f32 f64 } -/// A built-in signed or unsigned integer. -#[stable(feature = "rust1", since = "1.0.0")] -#[deprecated(since = "1.0.0", - reason = "replaced by inherent methods; for generics, use rust-lang/num")] -#[allow(deprecated)] -pub trait Int - : Copy + Clone - + NumCast - + PartialOrd + Ord - + PartialEq + Eq - + Add - + Sub - + Mul - + Div - + Rem - + Not - + BitAnd - + BitOr - + BitXor - + Shl - + Shr - + WrappingOps - + OverflowingOps -{ - /// Returns the `0` value of this integer type. - // FIXME (#5527): Should be an associated constant - #[unstable(feature = "core", - reason = "unsure about its place in the world")] - fn zero() -> Self; - - /// Returns the `1` value of this integer type. - // FIXME (#5527): Should be an associated constant - #[unstable(feature = "core", - reason = "unsure about its place in the world")] - fn one() -> Self; - - /// Returns the smallest value that can be represented by this integer type. - // FIXME (#5527): Should be and associated constant - #[unstable(feature = "core", - reason = "unsure about its place in the world")] - fn min_value() -> Self; - - /// Returns the largest value that can be represented by this integer type. - // FIXME (#5527): Should be and associated constant - #[unstable(feature = "core", - reason = "unsure about its place in the world")] - fn max_value() -> Self; - - /// Returns the number of ones in the binary representation of `self`. - /// - /// # Examples - /// - /// ``` - /// # #![feature(core)] - /// use std::num::Int; - /// - /// let n = 0b01001100u8; - /// - /// assert_eq!(n.count_ones(), 3); - /// ``` - #[unstable(feature = "core", - reason = "pending integer conventions")] - fn count_ones(self) -> u32; - - /// Returns the number of zeros in the binary representation of `self`. - /// - /// # Examples - /// - /// ``` - /// # #![feature(core)] - /// use std::num::Int; - /// - /// let n = 0b01001100u8; - /// - /// assert_eq!(n.count_zeros(), 5); - /// ``` - #[unstable(feature = "core", - reason = "pending integer conventions")] - #[inline] - fn count_zeros(self) -> u32 { - (!self).count_ones() - } - - /// Returns the number of leading zeros in the binary representation - /// of `self`. - /// - /// # Examples - /// - /// ``` - /// # #![feature(core)] - /// use std::num::Int; - /// - /// let n = 0b0101000u16; - /// - /// assert_eq!(n.leading_zeros(), 10); - /// ``` - #[unstable(feature = "core", - reason = "pending integer conventions")] - fn leading_zeros(self) -> u32; - - /// Returns the number of trailing zeros in the binary representation - /// of `self`. - /// - /// # Examples - /// - /// ``` - /// # #![feature(core)] - /// use std::num::Int; - /// - /// let n = 0b0101000u16; - /// - /// assert_eq!(n.trailing_zeros(), 3); - /// ``` - #[unstable(feature = "core", - reason = "pending integer conventions")] - fn trailing_zeros(self) -> u32; - - /// Shifts the bits to the left by a specified amount, `n`, wrapping - /// the truncated bits to the end of the resulting integer. - /// - /// # Examples - /// - /// ``` - /// # #![feature(core)] - /// use std::num::Int; - /// - /// let n = 0x0123456789ABCDEFu64; - /// let m = 0x3456789ABCDEF012u64; - /// - /// assert_eq!(n.rotate_left(12), m); - /// ``` - #[unstable(feature = "core", - reason = "pending integer conventions")] - fn rotate_left(self, n: u32) -> Self; - - /// Shifts the bits to the right by a specified amount, `n`, wrapping - /// the truncated bits to the beginning of the resulting integer. - /// - /// # Examples - /// - /// ``` - /// # #![feature(core)] - /// use std::num::Int; - /// - /// let n = 0x0123456789ABCDEFu64; - /// let m = 0xDEF0123456789ABCu64; - /// - /// assert_eq!(n.rotate_right(12), m); - /// ``` - #[unstable(feature = "core", - reason = "pending integer conventions")] - fn rotate_right(self, n: u32) -> Self; - - /// Reverses the byte order of the integer. - /// - /// # Examples - /// - /// ``` - /// use std::num::Int; - /// - /// let n = 0x0123456789ABCDEFu64; - /// let m = 0xEFCDAB8967452301u64; - /// - /// assert_eq!(n.swap_bytes(), m); - /// ``` - #[stable(feature = "rust1", since = "1.0.0")] - fn swap_bytes(self) -> Self; - - /// Converts an integer from big endian to the target's endianness. - /// - /// On big endian this is a no-op. On little endian the bytes are swapped. - /// - /// # Examples - /// - /// ``` - /// use std::num::Int; - /// - /// let n = 0x0123456789ABCDEFu64; - /// - /// if cfg!(target_endian = "big") { - /// assert_eq!(Int::from_be(n), n) - /// } else { - /// assert_eq!(Int::from_be(n), n.swap_bytes()) - /// } - /// ``` - #[stable(feature = "rust1", since = "1.0.0")] - #[inline] - fn from_be(x: Self) -> Self { - if cfg!(target_endian = "big") { x } else { x.swap_bytes() } - } - - /// Converts an integer from little endian to the target's endianness. - /// - /// On little endian this is a no-op. On big endian the bytes are swapped. - /// - /// # Examples - /// - /// ``` - /// use std::num::Int; - /// - /// let n = 0x0123456789ABCDEFu64; - /// - /// if cfg!(target_endian = "little") { - /// assert_eq!(Int::from_le(n), n) - /// } else { - /// assert_eq!(Int::from_le(n), n.swap_bytes()) - /// } - /// ``` - #[stable(feature = "rust1", since = "1.0.0")] - #[inline] - fn from_le(x: Self) -> Self { - if cfg!(target_endian = "little") { x } else { x.swap_bytes() } - } - - /// Converts `self` to big endian from the target's endianness. - /// - /// On big endian this is a no-op. On little endian the bytes are swapped. - /// - /// # Examples - /// - /// ``` - /// use std::num::Int; - /// - /// let n = 0x0123456789ABCDEFu64; - /// - /// if cfg!(target_endian = "big") { - /// assert_eq!(n.to_be(), n) - /// } else { - /// assert_eq!(n.to_be(), n.swap_bytes()) - /// } - /// ``` - #[stable(feature = "rust1", since = "1.0.0")] - #[inline] - fn to_be(self) -> Self { // or not to be? - if cfg!(target_endian = "big") { self } else { self.swap_bytes() } - } - - /// Converts `self` to little endian from the target's endianness. - /// - /// On little endian this is a no-op. On big endian the bytes are swapped. - /// - /// # Examples - /// - /// ``` - /// use std::num::Int; - /// - /// let n = 0x0123456789ABCDEFu64; - /// - /// if cfg!(target_endian = "little") { - /// assert_eq!(n.to_le(), n) - /// } else { - /// assert_eq!(n.to_le(), n.swap_bytes()) - /// } - /// ``` - #[stable(feature = "rust1", since = "1.0.0")] - #[inline] - fn to_le(self) -> Self { - if cfg!(target_endian = "little") { self } else { self.swap_bytes() } - } - - /// Checked integer addition. Computes `self + other`, returning `None` if - /// overflow occurred. - /// - /// # Examples - /// - /// ``` - /// use std::num::Int; - /// - /// assert_eq!(5u16.checked_add(65530), Some(65535)); - /// assert_eq!(6u16.checked_add(65530), None); - /// ``` - #[stable(feature = "rust1", since = "1.0.0")] - fn checked_add(self, other: Self) -> Option; - - /// Checked integer subtraction. Computes `self - other`, returning `None` - /// if underflow occurred. - /// - /// # Examples - /// - /// ``` - /// use std::num::Int; - /// - /// assert_eq!((-127i8).checked_sub(1), Some(-128)); - /// assert_eq!((-128i8).checked_sub(1), None); - /// ``` - #[stable(feature = "rust1", since = "1.0.0")] - fn checked_sub(self, other: Self) -> Option; - - /// Checked integer multiplication. Computes `self * other`, returning - /// `None` if underflow or overflow occurred. - /// - /// # Examples - /// - /// ``` - /// use std::num::Int; - /// - /// assert_eq!(5u8.checked_mul(51), Some(255)); - /// assert_eq!(5u8.checked_mul(52), None); - /// ``` - #[stable(feature = "rust1", since = "1.0.0")] - fn checked_mul(self, other: Self) -> Option; - - /// Checked integer division. Computes `self / other`, returning `None` if - /// `other == 0` or the operation results in underflow or overflow. - /// - /// # Examples - /// - /// ``` - /// use std::num::Int; - /// - /// assert_eq!((-127i8).checked_div(-1), Some(127)); - /// assert_eq!((-128i8).checked_div(-1), None); - /// assert_eq!((1i8).checked_div(0), None); - /// ``` - #[stable(feature = "rust1", since = "1.0.0")] - fn checked_div(self, other: Self) -> Option; - - /// Saturating integer addition. Computes `self + other`, saturating at - /// the numeric bounds instead of overflowing. - /// - /// # Examples - /// - /// ``` - /// use std::num::Int; - /// - /// assert_eq!(5u16.saturating_add(65534), 65535); - /// assert_eq!((-5i16).saturating_add(-32767), -32768); - /// assert_eq!(100u32.saturating_add(4294967294), 4294967295); - /// ``` - #[stable(feature = "rust1", since = "1.0.0")] - #[inline] - fn saturating_add(self, other: Self) -> Self { - match self.checked_add(other) { - Some(x) => x, - None if other >= Int::zero() => Int::max_value(), - None => Int::min_value(), - } - } - - /// Saturating integer subtraction. Computes `self - other`, saturating at - /// the numeric bounds instead of overflowing. - /// - /// # Examples - /// - /// ``` - /// use std::num::Int; - /// - /// assert_eq!(5u16.saturating_sub(65534), 0); - /// assert_eq!(5i16.saturating_sub(-32767), 32767); - /// assert_eq!(100u32.saturating_sub(4294967294), 0); - /// ``` - #[stable(feature = "rust1", since = "1.0.0")] - #[inline] - fn saturating_sub(self, other: Self) -> Self { - match self.checked_sub(other) { - Some(x) => x, - None if other >= Int::zero() => Int::min_value(), - None => Int::max_value(), - } - } - - /// Raises self to the power of `exp`, using exponentiation by squaring. - /// - /// # Examples - /// - /// ``` - /// # #![feature(core)] - /// use std::num::Int; - /// - /// assert_eq!(2.pow(4), 16); - /// ``` - #[unstable(feature = "core", - reason = "pending integer conventions")] - #[inline] - fn pow(self, mut exp: u32) -> Self { - let mut base = self; - let mut acc: Self = Int::one(); - - let mut prev_base = self; - let mut base_oflo = false; - while exp > 0 { - if (exp & 1) == 1 { - if base_oflo { - // ensure overflow occurs in the same manner it - // would have otherwise (i.e. signal any exception - // it would have otherwise). - acc = acc * (prev_base * prev_base); - } else { - acc = acc * base; - } - } - prev_base = base; - let (new_base, new_base_oflo) = base.overflowing_mul(base); - base = new_base; - base_oflo = new_base_oflo; - exp /= 2; - } - acc - } -} - macro_rules! checked_op { ($T:ty, $U:ty, $op:path, $x:expr, $y:expr) => {{ let (result, overflowed) = unsafe { $op($x as $U, $y as $U) }; @@ -508,328 +104,13 @@ macro_rules! checked_op { }} } -macro_rules! uint_impl { - ($T:ty = $ActualT:ty, $BITS:expr, - $ctpop:path, - $ctlz:path, - $cttz:path, - $bswap:path, - $add_with_overflow:path, - $sub_with_overflow:path, - $mul_with_overflow:path) => { - #[stable(feature = "rust1", since = "1.0.0")] - #[allow(deprecated)] - impl Int for $T { - #[inline] - fn zero() -> $T { 0 } - - #[inline] - fn one() -> $T { 1 } - - #[inline] - fn min_value() -> $T { 0 } - - #[inline] - fn max_value() -> $T { !0 } - - #[inline] - fn count_ones(self) -> u32 { - unsafe { $ctpop(self as $ActualT) as u32 } - } - - #[inline] - fn leading_zeros(self) -> u32 { - unsafe { $ctlz(self as $ActualT) as u32 } - } - - #[inline] - fn trailing_zeros(self) -> u32 { - unsafe { $cttz(self as $ActualT) as u32 } - } - - #[inline] - fn rotate_left(self, n: u32) -> $T { - // Protect against undefined behaviour for over-long bit shifts - let n = n % $BITS; - (self << n) | (self >> (($BITS - n) % $BITS)) - } - - #[inline] - fn rotate_right(self, n: u32) -> $T { - // Protect against undefined behaviour for over-long bit shifts - let n = n % $BITS; - (self >> n) | (self << (($BITS - n) % $BITS)) - } - - #[inline] - fn swap_bytes(self) -> $T { - unsafe { $bswap(self as $ActualT) as $T } - } - - #[inline] - fn checked_add(self, other: $T) -> Option<$T> { - checked_op!($T, $ActualT, $add_with_overflow, self, other) - } - - #[inline] - fn checked_sub(self, other: $T) -> Option<$T> { - checked_op!($T, $ActualT, $sub_with_overflow, self, other) - } - - #[inline] - fn checked_mul(self, other: $T) -> Option<$T> { - checked_op!($T, $ActualT, $mul_with_overflow, self, other) - } - - #[inline] - fn checked_div(self, v: $T) -> Option<$T> { - match v { - 0 => None, - v => Some(self / v), - } - } - } - } -} - /// Swapping a single byte is a no-op. This is marked as `unsafe` for /// consistency with the other `bswap` intrinsics. unsafe fn bswap8(x: u8) -> u8 { x } -uint_impl! { u8 = u8, 8, - intrinsics::ctpop8, - intrinsics::ctlz8, - intrinsics::cttz8, - bswap8, - intrinsics::u8_add_with_overflow, - intrinsics::u8_sub_with_overflow, - intrinsics::u8_mul_with_overflow } - -uint_impl! { u16 = u16, 16, - intrinsics::ctpop16, - intrinsics::ctlz16, - intrinsics::cttz16, - intrinsics::bswap16, - intrinsics::u16_add_with_overflow, - intrinsics::u16_sub_with_overflow, - intrinsics::u16_mul_with_overflow } - -uint_impl! { u32 = u32, 32, - intrinsics::ctpop32, - intrinsics::ctlz32, - intrinsics::cttz32, - intrinsics::bswap32, - intrinsics::u32_add_with_overflow, - intrinsics::u32_sub_with_overflow, - intrinsics::u32_mul_with_overflow } - -uint_impl! { u64 = u64, 64, - intrinsics::ctpop64, - intrinsics::ctlz64, - intrinsics::cttz64, - intrinsics::bswap64, - intrinsics::u64_add_with_overflow, - intrinsics::u64_sub_with_overflow, - intrinsics::u64_mul_with_overflow } - -#[cfg(target_pointer_width = "32")] -uint_impl! { usize = u32, 32, - intrinsics::ctpop32, - intrinsics::ctlz32, - intrinsics::cttz32, - intrinsics::bswap32, - intrinsics::u32_add_with_overflow, - intrinsics::u32_sub_with_overflow, - intrinsics::u32_mul_with_overflow } - -#[cfg(target_pointer_width = "64")] -uint_impl! { usize = u64, 64, - intrinsics::ctpop64, - intrinsics::ctlz64, - intrinsics::cttz64, - intrinsics::bswap64, - intrinsics::u64_add_with_overflow, - intrinsics::u64_sub_with_overflow, - intrinsics::u64_mul_with_overflow } - -macro_rules! int_impl { - ($T:ty = $ActualT:ty, $UnsignedT:ty, $BITS:expr, - $add_with_overflow:path, - $sub_with_overflow:path, - $mul_with_overflow:path) => { - #[stable(feature = "rust1", since = "1.0.0")] - #[allow(deprecated)] - impl Int for $T { - #[inline] - fn zero() -> $T { 0 } - - #[inline] - fn one() -> $T { 1 } - - #[inline] - fn min_value() -> $T { (-1 as $T) << ($BITS - 1) } - - #[inline] - fn max_value() -> $T { let min: $T = Int::min_value(); !min } - - #[inline] - fn count_ones(self) -> u32 { (self as $UnsignedT).count_ones() } - - #[inline] - fn leading_zeros(self) -> u32 { - (self as $UnsignedT).leading_zeros() - } - - #[inline] - fn trailing_zeros(self) -> u32 { - (self as $UnsignedT).trailing_zeros() - } - - #[inline] - fn rotate_left(self, n: u32) -> $T { - (self as $UnsignedT).rotate_left(n) as $T - } - - #[inline] - fn rotate_right(self, n: u32) -> $T { - (self as $UnsignedT).rotate_right(n) as $T - } - - #[inline] - fn swap_bytes(self) -> $T { - (self as $UnsignedT).swap_bytes() as $T - } - - #[inline] - fn checked_add(self, other: $T) -> Option<$T> { - checked_op!($T, $ActualT, $add_with_overflow, self, other) - } - - #[inline] - fn checked_sub(self, other: $T) -> Option<$T> { - checked_op!($T, $ActualT, $sub_with_overflow, self, other) - } - - #[inline] - fn checked_mul(self, other: $T) -> Option<$T> { - checked_op!($T, $ActualT, $mul_with_overflow, self, other) - } - - #[inline] - fn checked_div(self, v: $T) -> Option<$T> { - match v { - 0 => None, - -1 if self == Int::min_value() - => None, - v => Some(self / v), - } - } - } - } -} - -int_impl! { i8 = i8, u8, 8, - intrinsics::i8_add_with_overflow, - intrinsics::i8_sub_with_overflow, - intrinsics::i8_mul_with_overflow } - -int_impl! { i16 = i16, u16, 16, - intrinsics::i16_add_with_overflow, - intrinsics::i16_sub_with_overflow, - intrinsics::i16_mul_with_overflow } - -int_impl! { i32 = i32, u32, 32, - intrinsics::i32_add_with_overflow, - intrinsics::i32_sub_with_overflow, - intrinsics::i32_mul_with_overflow } - -int_impl! { i64 = i64, u64, 64, - intrinsics::i64_add_with_overflow, - intrinsics::i64_sub_with_overflow, - intrinsics::i64_mul_with_overflow } - -#[cfg(target_pointer_width = "32")] -int_impl! { isize = i32, u32, 32, - intrinsics::i32_add_with_overflow, - intrinsics::i32_sub_with_overflow, - intrinsics::i32_mul_with_overflow } - -#[cfg(target_pointer_width = "64")] -int_impl! { isize = i64, u64, 64, - intrinsics::i64_add_with_overflow, - intrinsics::i64_sub_with_overflow, - intrinsics::i64_mul_with_overflow } - -/// A built-in two's complement integer. -#[stable(feature = "rust1", since = "1.0.0")] -#[deprecated(since = "1.0.0", - reason = "replaced by inherent methods; for generics, use rust-lang/num")] -#[allow(deprecated)] -pub trait SignedInt - : Int - + Neg -{ - /// Computes the absolute value of `self`. `Int::min_value()` will be - /// returned if the number is `Int::min_value()`. - #[unstable(feature = "core", reason = "overflow in debug builds?")] - fn abs(self) -> Self; - - /// Returns a number representing sign of `self`. - /// - /// - `0` if the number is zero - /// - `1` if the number is positive - /// - `-1` if the number is negative - #[stable(feature = "rust1", since = "1.0.0")] - fn signum(self) -> Self; - - /// Returns `true` if `self` is positive and `false` if the number - /// is zero or negative. - #[stable(feature = "rust1", since = "1.0.0")] - fn is_positive(self) -> bool; - - /// Returns `true` if `self` is negative and `false` if the number - /// is zero or positive. - #[stable(feature = "rust1", since = "1.0.0")] - fn is_negative(self) -> bool; -} - -macro_rules! signed_int_impl { - ($T:ty) => { - #[stable(feature = "rust1", since = "1.0.0")] - #[allow(deprecated)] - impl SignedInt for $T { - #[inline] - fn abs(self) -> $T { - if self.is_negative() { -self } else { self } - } - - #[inline] - fn signum(self) -> $T { - match self { - n if n > 0 => 1, - 0 => 0, - _ => -1, - } - } - - #[inline] - fn is_positive(self) -> bool { self > 0 } - - #[inline] - fn is_negative(self) -> bool { self < 0 } - } - } -} - -signed_int_impl! { i8 } -signed_int_impl! { i16 } -signed_int_impl! { i32 } -signed_int_impl! { i64 } -signed_int_impl! { isize } - // `Int` + `SignedInt` implemented for signed integers macro_rules! int_impl { - ($T:ty = $ActualT:ty, $UnsignedT:ty, $BITS:expr, + ($T:ident = $ActualT:ty, $UnsignedT:ty, $BITS:expr, $add_with_overflow:path, $sub_with_overflow:path, $mul_with_overflow:path) => { @@ -842,7 +123,7 @@ macro_rules! int_impl { /// Returns the largest value that can be represented by this integer type. #[stable(feature = "rust1", since = "1.0.0")] pub fn max_value() -> $T { - let min: $T = Int::min_value(); !min + let min = $T::min_value(); !min } /// Converts a string slice in a given base to an integer. @@ -861,7 +142,7 @@ macro_rules! int_impl { #[stable(feature = "rust1", since = "1.0.0")] #[allow(deprecated)] pub fn from_str_radix(src: &str, radix: u32) -> Result<$T, ParseIntError> { - ::from_str_radix(src, radix) + from_str_radix(src, radix) } /// Returns the number of ones in the binary representation of `self`. @@ -1381,7 +662,7 @@ macro_rules! uint_impl { #[stable(feature = "rust1", since = "1.0.0")] #[allow(deprecated)] pub fn from_str_radix(src: &str, radix: u32) -> Result<$T, ParseIntError> { - ::from_str_radix(src, radix) + from_str_radix(src, radix) } /// Returns the number of ones in the binary representation of `self`. @@ -1889,575 +1170,6 @@ impl usize { intrinsics::u64_mul_with_overflow } } -/// A generic trait for converting a value to a number. -#[unstable(feature = "core", reason = "trait is likely to be removed")] -pub trait ToPrimitive { - /// Converts the value of `self` to an `isize`. - #[inline] - #[unstable(feature = "core")] - #[deprecated(since = "1.0.0", reason = "use to_isize")] - fn to_int(&self) -> Option { - self.to_i64().and_then(|x| x.to_isize()) - } - - /// Converts the value of `self` to an `isize`. - #[inline] - fn to_isize(&self) -> Option { - self.to_i64().and_then(|x| x.to_isize()) - } - - /// Converts the value of `self` to an `i8`. - #[inline] - fn to_i8(&self) -> Option { - self.to_i64().and_then(|x| x.to_i8()) - } - - /// Converts the value of `self` to an `i16`. - #[inline] - fn to_i16(&self) -> Option { - self.to_i64().and_then(|x| x.to_i16()) - } - - /// Converts the value of `self` to an `i32`. - #[inline] - fn to_i32(&self) -> Option { - self.to_i64().and_then(|x| x.to_i32()) - } - - /// Converts the value of `self` to an `i64`. - fn to_i64(&self) -> Option; - - /// Converts the value of `self` to an `usize`. - #[inline] - #[unstable(feature = "core")] - #[deprecated(since = "1.0.0", reason = "use to_usize")] - fn to_uint(&self) -> Option { - self.to_u64().and_then(|x| x.to_usize()) - } - - /// Converts the value of `self` to a `usize`. - #[inline] - fn to_usize(&self) -> Option { - self.to_u64().and_then(|x| x.to_usize()) - } - - /// Converts the value of `self` to an `u8`. - #[inline] - fn to_u8(&self) -> Option { - self.to_u64().and_then(|x| x.to_u8()) - } - - /// Converts the value of `self` to an `u16`. - #[inline] - fn to_u16(&self) -> Option { - self.to_u64().and_then(|x| x.to_u16()) - } - - /// Converts the value of `self` to an `u32`. - #[inline] - fn to_u32(&self) -> Option { - self.to_u64().and_then(|x| x.to_u32()) - } - - /// Converts the value of `self` to an `u64`. - #[inline] - fn to_u64(&self) -> Option; - - /// Converts the value of `self` to an `f32`. - #[inline] - fn to_f32(&self) -> Option { - self.to_f64().and_then(|x| x.to_f32()) - } - - /// Converts the value of `self` to an `f64`. - #[inline] - fn to_f64(&self) -> Option { - self.to_i64().and_then(|x| x.to_f64()) - } -} - -macro_rules! impl_to_primitive_int_to_int { - ($SrcT:ty, $DstT:ty, $slf:expr) => ( - { - if size_of::<$SrcT>() <= size_of::<$DstT>() { - Some($slf as $DstT) - } else { - let n = $slf as i64; - let min_value: $DstT = Int::min_value(); - let max_value: $DstT = Int::max_value(); - if min_value as i64 <= n && n <= max_value as i64 { - Some($slf as $DstT) - } else { - None - } - } - } - ) -} - -macro_rules! impl_to_primitive_int_to_uint { - ($SrcT:ty, $DstT:ty, $slf:expr) => ( - { - let zero: $SrcT = Int::zero(); - let max_value: $DstT = Int::max_value(); - if zero <= $slf && $slf as u64 <= max_value as u64 { - Some($slf as $DstT) - } else { - None - } - } - ) -} - -macro_rules! impl_to_primitive_int { - ($T:ty) => ( - impl ToPrimitive for $T { - #[inline] - fn to_int(&self) -> Option { impl_to_primitive_int_to_int!($T, isize, *self) } - #[inline] - fn to_isize(&self) -> Option { impl_to_primitive_int_to_int!($T, isize, *self) } - #[inline] - fn to_i8(&self) -> Option { impl_to_primitive_int_to_int!($T, i8, *self) } - #[inline] - fn to_i16(&self) -> Option { impl_to_primitive_int_to_int!($T, i16, *self) } - #[inline] - fn to_i32(&self) -> Option { impl_to_primitive_int_to_int!($T, i32, *self) } - #[inline] - fn to_i64(&self) -> Option { impl_to_primitive_int_to_int!($T, i64, *self) } - - #[inline] - fn to_uint(&self) -> Option { impl_to_primitive_int_to_uint!($T, usize, *self) } - #[inline] - fn to_usize(&self) -> Option { impl_to_primitive_int_to_uint!($T, usize, *self) } - #[inline] - fn to_u8(&self) -> Option { impl_to_primitive_int_to_uint!($T, u8, *self) } - #[inline] - fn to_u16(&self) -> Option { impl_to_primitive_int_to_uint!($T, u16, *self) } - #[inline] - fn to_u32(&self) -> Option { impl_to_primitive_int_to_uint!($T, u32, *self) } - #[inline] - fn to_u64(&self) -> Option { impl_to_primitive_int_to_uint!($T, u64, *self) } - - #[inline] - fn to_f32(&self) -> Option { Some(*self as f32) } - #[inline] - fn to_f64(&self) -> Option { Some(*self as f64) } - } - ) -} - -impl_to_primitive_int! { isize } -impl_to_primitive_int! { i8 } -impl_to_primitive_int! { i16 } -impl_to_primitive_int! { i32 } -impl_to_primitive_int! { i64 } - -macro_rules! impl_to_primitive_uint_to_int { - ($DstT:ty, $slf:expr) => ( - { - let max_value: $DstT = Int::max_value(); - if $slf as u64 <= max_value as u64 { - Some($slf as $DstT) - } else { - None - } - } - ) -} - -macro_rules! impl_to_primitive_uint_to_uint { - ($SrcT:ty, $DstT:ty, $slf:expr) => ( - { - if size_of::<$SrcT>() <= size_of::<$DstT>() { - Some($slf as $DstT) - } else { - let zero: $SrcT = Int::zero(); - let max_value: $DstT = Int::max_value(); - if zero <= $slf && $slf as u64 <= max_value as u64 { - Some($slf as $DstT) - } else { - None - } - } - } - ) -} - -macro_rules! impl_to_primitive_uint { - ($T:ty) => ( - impl ToPrimitive for $T { - #[inline] - fn to_int(&self) -> Option { impl_to_primitive_uint_to_int!(isize, *self) } - #[inline] - fn to_isize(&self) -> Option { impl_to_primitive_uint_to_int!(isize, *self) } - #[inline] - fn to_i8(&self) -> Option { impl_to_primitive_uint_to_int!(i8, *self) } - #[inline] - fn to_i16(&self) -> Option { impl_to_primitive_uint_to_int!(i16, *self) } - #[inline] - fn to_i32(&self) -> Option { impl_to_primitive_uint_to_int!(i32, *self) } - #[inline] - fn to_i64(&self) -> Option { impl_to_primitive_uint_to_int!(i64, *self) } - - #[inline] - fn to_uint(&self) -> Option { impl_to_primitive_uint_to_uint!($T, usize, *self) } - #[inline] - fn to_usize(&self) -> Option { - impl_to_primitive_uint_to_uint!($T, usize, *self) - } - #[inline] - fn to_u8(&self) -> Option { impl_to_primitive_uint_to_uint!($T, u8, *self) } - #[inline] - fn to_u16(&self) -> Option { impl_to_primitive_uint_to_uint!($T, u16, *self) } - #[inline] - fn to_u32(&self) -> Option { impl_to_primitive_uint_to_uint!($T, u32, *self) } - #[inline] - fn to_u64(&self) -> Option { impl_to_primitive_uint_to_uint!($T, u64, *self) } - - #[inline] - fn to_f32(&self) -> Option { Some(*self as f32) } - #[inline] - fn to_f64(&self) -> Option { Some(*self as f64) } - } - ) -} - -impl_to_primitive_uint! { usize } -impl_to_primitive_uint! { u8 } -impl_to_primitive_uint! { u16 } -impl_to_primitive_uint! { u32 } -impl_to_primitive_uint! { u64 } - -macro_rules! impl_to_primitive_float_to_float { - ($SrcT:ident, $DstT:ident, $slf:expr) => ( - if size_of::<$SrcT>() <= size_of::<$DstT>() { - Some($slf as $DstT) - } else { - let n = $slf as f64; - let max_value: $SrcT = ::$SrcT::MAX; - if -max_value as f64 <= n && n <= max_value as f64 { - Some($slf as $DstT) - } else { - None - } - } - ) -} - -macro_rules! impl_to_primitive_float { - ($T:ident) => ( - impl ToPrimitive for $T { - #[inline] - fn to_int(&self) -> Option { Some(*self as isize) } - #[inline] - fn to_isize(&self) -> Option { Some(*self as isize) } - #[inline] - fn to_i8(&self) -> Option { Some(*self as i8) } - #[inline] - fn to_i16(&self) -> Option { Some(*self as i16) } - #[inline] - fn to_i32(&self) -> Option { Some(*self as i32) } - #[inline] - fn to_i64(&self) -> Option { Some(*self as i64) } - - #[inline] - fn to_uint(&self) -> Option { Some(*self as usize) } - #[inline] - fn to_usize(&self) -> Option { Some(*self as usize) } - #[inline] - fn to_u8(&self) -> Option { Some(*self as u8) } - #[inline] - fn to_u16(&self) -> Option { Some(*self as u16) } - #[inline] - fn to_u32(&self) -> Option { Some(*self as u32) } - #[inline] - fn to_u64(&self) -> Option { Some(*self as u64) } - - #[inline] - fn to_f32(&self) -> Option { impl_to_primitive_float_to_float!($T, f32, *self) } - #[inline] - fn to_f64(&self) -> Option { impl_to_primitive_float_to_float!($T, f64, *self) } - } - ) -} - -impl_to_primitive_float! { f32 } -impl_to_primitive_float! { f64 } - -/// A generic trait for converting a number to a value. -#[unstable(feature = "core", reason = "trait is likely to be removed")] -pub trait FromPrimitive : ::marker::Sized { - /// Converts an `isize` to return an optional value of this type. If the - /// value cannot be represented by this value, the `None` is returned. - #[inline] - #[unstable(feature = "core")] - #[deprecated(since = "1.0.0", reason = "use from_isize")] - fn from_int(n: isize) -> Option { - FromPrimitive::from_i64(n as i64) - } - - /// Converts an `isize` to return an optional value of this type. If the - /// value cannot be represented by this value, the `None` is returned. - #[inline] - fn from_isize(n: isize) -> Option { - FromPrimitive::from_i64(n as i64) - } - - /// Converts an `i8` to return an optional value of this type. If the - /// type cannot be represented by this value, the `None` is returned. - #[inline] - fn from_i8(n: i8) -> Option { - FromPrimitive::from_i64(n as i64) - } - - /// Converts an `i16` to return an optional value of this type. If the - /// type cannot be represented by this value, the `None` is returned. - #[inline] - fn from_i16(n: i16) -> Option { - FromPrimitive::from_i64(n as i64) - } - - /// Converts an `i32` to return an optional value of this type. If the - /// type cannot be represented by this value, the `None` is returned. - #[inline] - fn from_i32(n: i32) -> Option { - FromPrimitive::from_i64(n as i64) - } - - /// Converts an `i64` to return an optional value of this type. If the - /// type cannot be represented by this value, the `None` is returned. - fn from_i64(n: i64) -> Option; - - /// Converts an `usize` to return an optional value of this type. If the - /// type cannot be represented by this value, the `None` is returned. - #[inline] - #[unstable(feature = "core")] - #[deprecated(since = "1.0.0", reason = "use from_usize")] - fn from_uint(n: usize) -> Option { - FromPrimitive::from_u64(n as u64) - } - - /// Converts a `usize` to return an optional value of this type. If the - /// type cannot be represented by this value, the `None` is returned. - #[inline] - fn from_usize(n: usize) -> Option { - FromPrimitive::from_u64(n as u64) - } - - /// Converts an `u8` to return an optional value of this type. If the - /// type cannot be represented by this value, the `None` is returned. - #[inline] - fn from_u8(n: u8) -> Option { - FromPrimitive::from_u64(n as u64) - } - - /// Converts an `u16` to return an optional value of this type. If the - /// type cannot be represented by this value, the `None` is returned. - #[inline] - fn from_u16(n: u16) -> Option { - FromPrimitive::from_u64(n as u64) - } - - /// Converts an `u32` to return an optional value of this type. If the - /// type cannot be represented by this value, the `None` is returned. - #[inline] - fn from_u32(n: u32) -> Option { - FromPrimitive::from_u64(n as u64) - } - - /// Converts an `u64` to return an optional value of this type. If the - /// type cannot be represented by this value, the `None` is returned. - fn from_u64(n: u64) -> Option; - - /// Converts a `f32` to return an optional value of this type. If the - /// type cannot be represented by this value, the `None` is returned. - #[inline] - fn from_f32(n: f32) -> Option { - FromPrimitive::from_f64(n as f64) - } - - /// Converts a `f64` to return an optional value of this type. If the - /// type cannot be represented by this value, the `None` is returned. - #[inline] - fn from_f64(n: f64) -> Option { - FromPrimitive::from_i64(n as i64) - } -} - -/// A utility function that just calls `FromPrimitive::from_int`. -#[unstable(feature = "core", reason = "likely to be removed")] -#[deprecated(since = "1.0.0", reason = "use from_isize")] -pub fn from_int(n: isize) -> Option { - FromPrimitive::from_isize(n) -} - -/// A utility function that just calls `FromPrimitive::from_isize`. -#[unstable(feature = "core", reason = "likely to be removed")] -pub fn from_isize(n: isize) -> Option { - FromPrimitive::from_isize(n) -} - -/// A utility function that just calls `FromPrimitive::from_i8`. -#[unstable(feature = "core", reason = "likely to be removed")] -pub fn from_i8(n: i8) -> Option { - FromPrimitive::from_i8(n) -} - -/// A utility function that just calls `FromPrimitive::from_i16`. -#[unstable(feature = "core", reason = "likely to be removed")] -pub fn from_i16(n: i16) -> Option { - FromPrimitive::from_i16(n) -} - -/// A utility function that just calls `FromPrimitive::from_i32`. -#[unstable(feature = "core", reason = "likely to be removed")] -pub fn from_i32(n: i32) -> Option { - FromPrimitive::from_i32(n) -} - -/// A utility function that just calls `FromPrimitive::from_i64`. -#[unstable(feature = "core", reason = "likely to be removed")] -pub fn from_i64(n: i64) -> Option { - FromPrimitive::from_i64(n) -} - -/// A utility function that just calls `FromPrimitive::from_uint`. -#[unstable(feature = "core", reason = "likely to be removed")] -#[deprecated(since = "1.0.0", reason = "use from_uint")] -pub fn from_uint(n: usize) -> Option { - FromPrimitive::from_usize(n) -} - -/// A utility function that just calls `FromPrimitive::from_usize`. -#[unstable(feature = "core", reason = "likely to be removed")] -pub fn from_usize(n: usize) -> Option { - FromPrimitive::from_usize(n) -} - -/// A utility function that just calls `FromPrimitive::from_u8`. -#[unstable(feature = "core", reason = "likely to be removed")] -pub fn from_u8(n: u8) -> Option { - FromPrimitive::from_u8(n) -} - -/// A utility function that just calls `FromPrimitive::from_u16`. -#[unstable(feature = "core", reason = "likely to be removed")] -pub fn from_u16(n: u16) -> Option { - FromPrimitive::from_u16(n) -} - -/// A utility function that just calls `FromPrimitive::from_u32`. -#[unstable(feature = "core", reason = "likely to be removed")] -pub fn from_u32(n: u32) -> Option { - FromPrimitive::from_u32(n) -} - -/// A utility function that just calls `FromPrimitive::from_u64`. -#[unstable(feature = "core", reason = "likely to be removed")] -pub fn from_u64(n: u64) -> Option { - FromPrimitive::from_u64(n) -} - -/// A utility function that just calls `FromPrimitive::from_f32`. -#[unstable(feature = "core", reason = "likely to be removed")] -pub fn from_f32(n: f32) -> Option { - FromPrimitive::from_f32(n) -} - -/// A utility function that just calls `FromPrimitive::from_f64`. -#[unstable(feature = "core", reason = "likely to be removed")] -pub fn from_f64(n: f64) -> Option { - FromPrimitive::from_f64(n) -} - -macro_rules! impl_from_primitive { - ($T:ty, $to_ty:ident) => ( - #[allow(deprecated)] - impl FromPrimitive for $T { - #[inline] fn from_int(n: isize) -> Option<$T> { n.$to_ty() } - #[inline] fn from_i8(n: i8) -> Option<$T> { n.$to_ty() } - #[inline] fn from_i16(n: i16) -> Option<$T> { n.$to_ty() } - #[inline] fn from_i32(n: i32) -> Option<$T> { n.$to_ty() } - #[inline] fn from_i64(n: i64) -> Option<$T> { n.$to_ty() } - - #[inline] fn from_uint(n: usize) -> Option<$T> { n.$to_ty() } - #[inline] fn from_u8(n: u8) -> Option<$T> { n.$to_ty() } - #[inline] fn from_u16(n: u16) -> Option<$T> { n.$to_ty() } - #[inline] fn from_u32(n: u32) -> Option<$T> { n.$to_ty() } - #[inline] fn from_u64(n: u64) -> Option<$T> { n.$to_ty() } - - #[inline] fn from_f32(n: f32) -> Option<$T> { n.$to_ty() } - #[inline] fn from_f64(n: f64) -> Option<$T> { n.$to_ty() } - } - ) -} - -impl_from_primitive! { isize, to_int } -impl_from_primitive! { i8, to_i8 } -impl_from_primitive! { i16, to_i16 } -impl_from_primitive! { i32, to_i32 } -impl_from_primitive! { i64, to_i64 } -impl_from_primitive! { usize, to_uint } -impl_from_primitive! { u8, to_u8 } -impl_from_primitive! { u16, to_u16 } -impl_from_primitive! { u32, to_u32 } -impl_from_primitive! { u64, to_u64 } -impl_from_primitive! { f32, to_f32 } -impl_from_primitive! { f64, to_f64 } - -/// Casts from one machine scalar to another. -/// -/// # Examples -/// -/// ``` -/// # #![feature(core)] -/// use std::num; -/// -/// let twenty: f32 = num::cast(0x14).unwrap(); -/// assert_eq!(twenty, 20f32); -/// ``` -/// -#[inline] -#[unstable(feature = "core", reason = "likely to be removed")] -pub fn cast(n: T) -> Option { - NumCast::from(n) -} - -/// An interface for casting between machine scalars. -#[unstable(feature = "core", reason = "trait is likely to be removed")] -pub trait NumCast: ToPrimitive { - /// Creates a number from another value that can be converted into a primitive via the - /// `ToPrimitive` trait. - fn from(n: T) -> Option; -} - -macro_rules! impl_num_cast { - ($T:ty, $conv:ident) => ( - impl NumCast for $T { - #[inline] - #[allow(deprecated)] - fn from(n: N) -> Option<$T> { - // `$conv` could be generated using `concat_idents!`, but that - // macro seems to be broken at the moment - n.$conv() - } - } - ) -} - -impl_num_cast! { u8, to_u8 } -impl_num_cast! { u16, to_u16 } -impl_num_cast! { u32, to_u32 } -impl_num_cast! { u64, to_u64 } -impl_num_cast! { usize, to_uint } -impl_num_cast! { i8, to_i8 } -impl_num_cast! { i16, to_i16 } -impl_num_cast! { i32, to_i32 } -impl_num_cast! { i64, to_i64 } -impl_num_cast! { isize, to_int } -impl_num_cast! { f32, to_f32 } -impl_num_cast! { f64, to_f64 } - /// Used for representing the classification of floating point numbers #[derive(Copy, Clone, PartialEq, Debug)] #[stable(feature = "rust1", since = "1.0.0")] @@ -2484,94 +1196,21 @@ pub enum FpCategory { } /// A built-in floating point number. -// FIXME(#5527): In a future version of Rust, many of these functions will -// become constants. -// -// FIXME(#8888): Several of these functions have a parameter named -// `unused_self`. Removing it requires #8888 to be fixed. -#[unstable(feature = "core", - reason = "distribution of methods between core/std is unclear")] #[doc(hidden)] -pub trait Float - : Copy + Clone - + NumCast - + PartialOrd - + PartialEq - + Neg - + Add - + Sub - + Mul - + Div - + Rem -{ +pub trait Float { /// Returns the NaN value. fn nan() -> Self; /// Returns the infinite value. fn infinity() -> Self; /// Returns the negative infinite value. fn neg_infinity() -> Self; - /// Returns the `0` value. - fn zero() -> Self; /// Returns -0.0. fn neg_zero() -> Self; - /// Returns the `1` value. + /// Returns 0.0. + fn zero() -> Self; + /// Returns 1.0. fn one() -> Self; - // FIXME (#5527): These should be associated constants - - /// Returns the number of binary digits of mantissa that this type supports. - #[unstable(feature = "core")] - #[deprecated(since = "1.0.0", - reason = "use `std::f32::MANTISSA_DIGITS` or \ - `std::f64::MANTISSA_DIGITS` as appropriate")] - fn mantissa_digits(unused_self: Option) -> usize; - /// Returns the number of base-10 digits of precision that this type supports. - #[unstable(feature = "core")] - #[deprecated(since = "1.0.0", - reason = "use `std::f32::DIGITS` or `std::f64::DIGITS` as appropriate")] - fn digits(unused_self: Option) -> usize; - /// Returns the difference between 1.0 and the smallest representable number larger than 1.0. - #[unstable(feature = "core")] - #[deprecated(since = "1.0.0", - reason = "use `std::f32::EPSILON` or `std::f64::EPSILON` as appropriate")] - fn epsilon() -> Self; - /// Returns the minimum binary exponent that this type can represent. - #[unstable(feature = "core")] - #[deprecated(since = "1.0.0", - reason = "use `std::f32::MIN_EXP` or `std::f64::MIN_EXP` as appropriate")] - fn min_exp(unused_self: Option) -> isize; - /// Returns the maximum binary exponent that this type can represent. - #[unstable(feature = "core")] - #[deprecated(since = "1.0.0", - reason = "use `std::f32::MAX_EXP` or `std::f64::MAX_EXP` as appropriate")] - fn max_exp(unused_self: Option) -> isize; - /// Returns the minimum base-10 exponent that this type can represent. - #[unstable(feature = "core")] - #[deprecated(since = "1.0.0", - reason = "use `std::f32::MIN_10_EXP` or `std::f64::MIN_10_EXP` as appropriate")] - fn min_10_exp(unused_self: Option) -> isize; - /// Returns the maximum base-10 exponent that this type can represent. - #[unstable(feature = "core")] - #[deprecated(since = "1.0.0", - reason = "use `std::f32::MAX_10_EXP` or `std::f64::MAX_10_EXP` as appropriate")] - fn max_10_exp(unused_self: Option) -> isize; - /// Returns the smallest finite value that this type can represent. - #[unstable(feature = "core")] - #[deprecated(since = "1.0.0", - reason = "use `std::f32::MIN` or `std::f64::MIN` as appropriate")] - fn min_value() -> Self; - /// Returns the smallest normalized positive number that this type can represent. - #[unstable(feature = "core")] - #[deprecated(since = "1.0.0", - reason = "use `std::f32::MIN_POSITIVE` or \ - `std::f64::MIN_POSITIVE` as appropriate")] - fn min_pos_value(unused_self: Option) -> Self; - /// Returns the largest finite value that this type can represent. - #[unstable(feature = "core")] - #[deprecated(since = "1.0.0", - reason = "use `std::f32::MAX` or `std::f64::MAX` as appropriate")] - fn max_value() -> Self; - /// Returns true if this value is NaN and false otherwise. fn is_nan(self) -> bool; /// Returns true if this value is positive infinity or negative infinity and @@ -2587,16 +1226,16 @@ pub trait Float /// Returns the mantissa, exponent and sign as integers, respectively. fn integer_decode(self) -> (u64, i16, i8); - /// Returns the largest integer less than or equal to a number. + /// Return the largest integer less than or equal to a number. fn floor(self) -> Self; - /// Returns the smallest integer greater than or equal to a number. + /// Return the smallest integer greater than or equal to a number. fn ceil(self) -> Self; - /// Returns the nearest integer to a number. Round half-way cases away from + /// Return the nearest integer to a number. Round half-way cases away from /// `0.0`. fn round(self) -> Self; - /// Returns the integer part of a number. + /// Return the integer part of a number. fn trunc(self) -> Self; - /// Returns the fractional part of a number. + /// Return the fractional part of a number. fn fract(self) -> Self; /// Computes the absolute value of `self`. Returns `Float::nan()` if the @@ -2619,21 +1258,21 @@ pub trait Float /// error. This produces a more accurate result with better performance than /// a separate multiplication operation followed by an add. fn mul_add(self, a: Self, b: Self) -> Self; - /// Takes the reciprocal (inverse) of a number, `1/x`. + /// Take the reciprocal (inverse) of a number, `1/x`. fn recip(self) -> Self; - /// Raises a number to an integer power. + /// Raise a number to an integer power. /// /// Using this function is generally faster than using `powf` fn powi(self, n: i32) -> Self; - /// Raises a number to a floating point power. + /// Raise a number to a floating point power. fn powf(self, n: Self) -> Self; - /// Takes the square root of a number. + /// Take the square root of a number. /// /// Returns NaN if `self` is a negative number. fn sqrt(self) -> Self; - /// Takes the reciprocal (inverse) square root of a number, `1/sqrt(x)`. + /// Take the reciprocal (inverse) square root of a number, `1/sqrt(x)`. fn rsqrt(self) -> Self; /// Returns `e^(self)`, (the exponential function). @@ -2649,37 +1288,12 @@ pub trait Float /// Returns the base 10 logarithm of the number. fn log10(self) -> Self; - /// Converts radians to degrees. + /// Convert radians to degrees. fn to_degrees(self) -> Self; - /// Converts degrees to radians. + /// Convert degrees to radians. fn to_radians(self) -> Self; } -/// A generic trait for converting a string with a radix (base) to a value -#[unstable(feature = "core", reason = "needs reevaluation")] -#[deprecated(since = "1.0.0", - reason = "moved to inherent methods; use e.g. i32::from_str_radix")] -pub trait FromStrRadix { - #[unstable(feature = "core", reason = "needs reevaluation")] - #[deprecated(since = "1.0.0", reason = "moved to inherent methods")] - type Err; - - #[unstable(feature = "core", reason = "needs reevaluation")] - #[deprecated(since = "1.0.0", - reason = "moved to inherent methods; use e.g. i32::from_str_radix")] - #[allow(deprecated)] - fn from_str_radix(str: &str, radix: u32) -> Result; -} - -/// A utility function that just calls `FromStrRadix::from_str_radix`. -#[unstable(feature = "core", reason = "needs reevaluation")] -#[deprecated(since = "1.0.0", reason = "use e.g. i32::from_str_radix")] -#[allow(deprecated)] -pub fn from_str_radix(str: &str, radix: u32) - -> Result { - FromStrRadix::from_str_radix(str, radix) -} - macro_rules! from_str_radix_float_impl { ($T:ty) => { #[stable(feature = "rust1", since = "1.0.0")] @@ -2714,39 +1328,9 @@ macro_rules! from_str_radix_float_impl { #[inline] #[allow(deprecated)] fn from_str(src: &str) -> Result<$T, ParseFloatError> { - from_str_radix(src, 10) - } - } - - #[stable(feature = "rust1", since = "1.0.0")] - #[allow(deprecated)] - impl FromStrRadix for $T { - type Err = ParseFloatError; - - /// Converts a string in a given base to a float. - /// - /// Due to possible conflicts, this function does **not** accept - /// the special values `inf`, `-inf`, `+inf` and `NaN`, **nor** - /// does it recognize exponents of any kind. - /// - /// Leading and trailing whitespace represent an error. - /// - /// # Arguments - /// - /// * src - A string - /// * radix - The base to use. Must lie in the range [2 .. 36] - /// - /// # Return value - /// - /// `Err(ParseFloatError)` if the string did not represent a valid number. - /// Otherwise, `Ok(n)` where `n` is the floating-point number represented by `src`. - fn from_str_radix(src: &str, radix: u32) - -> Result<$T, ParseFloatError> { use self::FloatErrorKind::*; use self::ParseFloatError as PFE; - assert!(radix >= 2 && radix <= 36, - "from_str_radix_float: must lie in the range `[2, 36]` - found {}", - radix); + let radix = 10; // Special values match src { @@ -2887,87 +1471,98 @@ from_str_radix_float_impl! { f32 } from_str_radix_float_impl! { f64 } macro_rules! from_str_radix_int_impl { - ($T:ty) => { + ($($T:ident)*) => {$( #[stable(feature = "rust1", since = "1.0.0")] #[allow(deprecated)] impl FromStr for $T { type Err = ParseIntError; - #[inline] fn from_str(src: &str) -> Result<$T, ParseIntError> { from_str_radix(src, 10) } } + )*} +} +from_str_radix_int_impl! { isize i8 i16 i32 i64 usize u8 u16 u32 u64 } - #[stable(feature = "rust1", since = "1.0.0")] - #[allow(deprecated)] - impl FromStrRadix for $T { - type Err = ParseIntError; - fn from_str_radix(src: &str, radix: u32) - -> Result<$T, ParseIntError> { - use self::IntErrorKind::*; - use self::ParseIntError as PIE; - assert!(radix >= 2 && radix <= 36, - "from_str_radix_int: must lie in the range `[2, 36]` - found {}", - radix); - - let is_signed_ty = (0 as $T) > Int::min_value(); - - match src.slice_shift_char() { - Some(('-', "")) => Err(PIE { kind: Empty }), - Some(('-', src)) if is_signed_ty => { - // The number is negative - let mut result = 0; - for c in src.chars() { - let x = match c.to_digit(radix) { - Some(x) => x, - None => return Err(PIE { kind: InvalidDigit }), - }; - result = match result.checked_mul(radix as $T) { - Some(result) => result, - None => return Err(PIE { kind: Underflow }), - }; - result = match result.checked_sub(x as $T) { - Some(result) => result, - None => return Err(PIE { kind: Underflow }), - }; - } - Ok(result) - }, - Some((_, _)) => { - // The number is signed - let mut result = 0; - for c in src.chars() { - let x = match c.to_digit(radix) { - Some(x) => x, - None => return Err(PIE { kind: InvalidDigit }), - }; - result = match result.checked_mul(radix as $T) { - Some(result) => result, - None => return Err(PIE { kind: Overflow }), - }; - result = match result.checked_add(x as $T) { - Some(result) => result, - None => return Err(PIE { kind: Overflow }), - }; - } - Ok(result) - }, - None => Err(ParseIntError { kind: Empty }), - } +#[doc(hidden)] +trait FromStrRadixHelper: PartialOrd + Copy { + fn min_value() -> Self; + fn from_u32(u: u32) -> Self; + fn checked_mul(&self, other: u32) -> Option; + fn checked_sub(&self, other: u32) -> Option; + fn checked_add(&self, other: u32) -> Option; +} + +macro_rules! doit { + ($($t:ident)*) => ($(impl FromStrRadixHelper for $t { + fn min_value() -> Self { <$t>::min_value() } + fn from_u32(u: u32) -> Self { u as $t } + fn checked_mul(&self, other: u32) -> Option { + <$t>::checked_mul(*self, other as $t) + } + fn checked_sub(&self, other: u32) -> Option { + <$t>::checked_sub(*self, other as $t) + } + fn checked_add(&self, other: u32) -> Option { + <$t>::checked_add(*self, other as $t) + } + })*) +} +doit! { i8 i16 i32 i64 isize u8 u16 u32 u64 usize } + +fn from_str_radix(src: &str, radix: u32) + -> Result { + use self::IntErrorKind::*; + use self::ParseIntError as PIE; + assert!(radix >= 2 && radix <= 36, + "from_str_radix_int: must lie in the range `[2, 36]` - found {}", + radix); + + let is_signed_ty = T::from_u32(0) > T::min_value(); + + match src.slice_shift_char() { + Some(('-', "")) => Err(PIE { kind: Empty }), + Some(('-', src)) if is_signed_ty => { + // The number is negative + let mut result = T::from_u32(0); + for c in src.chars() { + let x = match c.to_digit(radix) { + Some(x) => x, + None => return Err(PIE { kind: InvalidDigit }), + }; + result = match result.checked_mul(radix) { + Some(result) => result, + None => return Err(PIE { kind: Underflow }), + }; + result = match result.checked_sub(x) { + Some(result) => result, + None => return Err(PIE { kind: Underflow }), + }; } - } + Ok(result) + }, + Some((_, _)) => { + // The number is signed + let mut result = T::from_u32(0); + for c in src.chars() { + let x = match c.to_digit(radix) { + Some(x) => x, + None => return Err(PIE { kind: InvalidDigit }), + }; + result = match result.checked_mul(radix) { + Some(result) => result, + None => return Err(PIE { kind: Overflow }), + }; + result = match result.checked_add(x) { + Some(result) => result, + None => return Err(PIE { kind: Overflow }), + }; + } + Ok(result) + }, + None => Err(ParseIntError { kind: Empty }), } } -from_str_radix_int_impl! { isize } -from_str_radix_int_impl! { i8 } -from_str_radix_int_impl! { i16 } -from_str_radix_int_impl! { i32 } -from_str_radix_int_impl! { i64 } -from_str_radix_int_impl! { usize } -from_str_radix_int_impl! { u8 } -from_str_radix_int_impl! { u16 } -from_str_radix_int_impl! { u32 } -from_str_radix_int_impl! { u64 } /// An error which can be returned when parsing an integer. #[derive(Debug, Clone, PartialEq)] diff --git a/src/libcore/num/wrapping.rs b/src/libcore/num/wrapping.rs index 28276d0bf0168..28c877872eb2b 100644 --- a/src/libcore/num/wrapping.rs +++ b/src/libcore/num/wrapping.rs @@ -15,8 +15,6 @@ use super::Wrapping; use ops::*; -use intrinsics::{overflowing_add, overflowing_sub, overflowing_mul}; - use intrinsics::{i8_add_with_overflow, u8_add_with_overflow}; use intrinsics::{i16_add_with_overflow, u16_add_with_overflow}; use intrinsics::{i32_add_with_overflow, u32_add_with_overflow}; @@ -32,14 +30,6 @@ use intrinsics::{i64_mul_with_overflow, u64_mul_with_overflow}; use ::{i8,i16,i32,i64}; -#[unstable(feature = "core", reason = "may be removed, renamed, or relocated")] -#[deprecated(since = "1.0.0", reason = "moved to inherent methods")] -pub trait WrappingOps { - fn wrapping_add(self, rhs: Self) -> Self; - fn wrapping_sub(self, rhs: Self) -> Self; - fn wrapping_mul(self, rhs: Self) -> Self; -} - #[unstable(feature = "core", reason = "may be removed, renamed, or relocated")] pub trait OverflowingOps { fn overflowing_add(self, rhs: Self) -> (Self, bool); @@ -98,27 +88,6 @@ sh_impl_all! { u8 u16 u32 u64 usize i8 i16 i32 i64 isize } macro_rules! wrapping_impl { ($($t:ty)*) => ($( - impl WrappingOps for $t { - #[inline(always)] - fn wrapping_add(self, rhs: $t) -> $t { - unsafe { - overflowing_add(self, rhs) - } - } - #[inline(always)] - fn wrapping_sub(self, rhs: $t) -> $t { - unsafe { - overflowing_sub(self, rhs) - } - } - #[inline(always)] - fn wrapping_mul(self, rhs: $t) -> $t { - unsafe { - overflowing_mul(self, rhs) - } - } - } - #[stable(feature = "rust1", since = "1.0.0")] impl Add for Wrapping<$t> { type Output = Wrapping<$t>; diff --git a/src/libcore/slice.rs b/src/libcore/slice.rs index 102a46a6bc874..1e96d761d405a 100644 --- a/src/libcore/slice.rs +++ b/src/libcore/slice.rs @@ -51,7 +51,7 @@ use result::Result::{Ok, Err}; use ptr; use mem; use mem::size_of; -use marker::{Send, Sized, Sync, self}; +use marker::{Send, Sync, self}; use raw::Repr; // Avoid conflicts with *both* the Slice trait (buggy) and the `slice::raw` module. use raw::Slice as RawSlice; diff --git a/src/libcore/str/mod.rs b/src/libcore/str/mod.rs index 9f2adbb9909fc..0bc09e4cf791e 100644 --- a/src/libcore/str/mod.rs +++ b/src/libcore/str/mod.rs @@ -27,7 +27,6 @@ use default::Default; use fmt; use iter::ExactSizeIterator; use iter::{Map, Iterator, DoubleEndedIterator}; -use marker::Sized; use mem; use ops::{Fn, FnMut, FnOnce}; use option::Option::{self, None, Some}; diff --git a/src/librand/chacha.rs b/src/librand/chacha.rs index 44187a4fc9942..9cd3b74e1552d 100644 --- a/src/librand/chacha.rs +++ b/src/librand/chacha.rs @@ -11,8 +11,6 @@ //! The ChaCha random number generator. use core::prelude::*; -use core::num::Int; -use core::num::wrapping::WrappingOps; use {Rng, SeedableRng, Rand}; const KEY_WORDS : usize = 8; // 8 words for the 256-bit key diff --git a/src/librand/distributions/mod.rs b/src/librand/distributions/mod.rs index 77e53248607ca..4ea81b8e61938 100644 --- a/src/librand/distributions/mod.rs +++ b/src/librand/distributions/mod.rs @@ -18,7 +18,7 @@ //! that do not need to record state. use core::prelude::*; -use core::num::{Float, Int}; +use core::num::Float; use core::marker::PhantomData; use {Rng, Rand}; diff --git a/src/librand/distributions/range.rs b/src/librand/distributions/range.rs index 8406c76cc1bbc..c5dd741c80c10 100644 --- a/src/librand/distributions/range.rs +++ b/src/librand/distributions/range.rs @@ -13,8 +13,6 @@ // this is surprisingly complicated to be both generic & correct use core::prelude::PartialOrd; -use core::num::Int; -use core::num::wrapping::WrappingOps; use Rng; use distributions::{Sample, IndependentSample}; @@ -73,7 +71,7 @@ pub trait SampleRange { } macro_rules! integer_impl { - ($ty:ty, $unsigned:ty) => { + ($ty:ident, $unsigned:ident) => { impl SampleRange for $ty { // we play free and fast with unsigned vs signed here // (when $ty is signed), but that's fine, since the @@ -83,7 +81,7 @@ macro_rules! integer_impl { fn construct_range(low: $ty, high: $ty) -> Range<$ty> { let range = (high as $unsigned).wrapping_sub(low as $unsigned); - let unsigned_max: $unsigned = Int::max_value(); + let unsigned_max: $unsigned = $unsigned::max_value(); // this is the largest number that fits into $unsigned // that `range` divides evenly, so, if we've sampled @@ -168,11 +166,11 @@ mod tests { fn test_integers() { let mut rng = ::test::rng(); macro_rules! t { - ($($ty:ty),*) => {{ + ($($ty:ident),*) => {{ $( let v: &[($ty, $ty)] = &[(0, 10), (10, 127), - (Int::min_value(), Int::max_value())]; + ($ty::min_value(), $ty::max_value())]; for &(low, high) in v { let mut sampler: Range<$ty> = Range::new(low, high); for _ in 0..1000 { diff --git a/src/librbml/lib.rs b/src/librbml/lib.rs index e2875ac8ca529..b7938397038b4 100644 --- a/src/librbml/lib.rs +++ b/src/librbml/lib.rs @@ -836,7 +836,6 @@ pub mod writer { use std::io::prelude::*; use std::io::{self, SeekFrom, Cursor}; use std::slice::bytes; - use std::num::ToPrimitive; use super::{ EsVec, EsMap, EsEnum, EsSub8, EsSub32, EsVecElt, EsMapKey, EsU64, EsU32, EsU16, EsU8, EsI64, EsI32, EsI16, EsI8, @@ -1070,10 +1069,10 @@ pub mod writer { impl<'a> Encoder<'a> { // used internally to emit things like the vector length and so on fn _emit_tagged_sub(&mut self, v: usize) -> EncodeResult { - if let Some(v) = v.to_u8() { - self.wr_tagged_raw_u8(EsSub8 as usize, v) - } else if let Some(v) = v.to_u32() { - self.wr_tagged_raw_u32(EsSub32 as usize, v) + if v as u8 as usize == v { + self.wr_tagged_raw_u8(EsSub8 as usize, v as u8) + } else if v as u32 as usize == v { + self.wr_tagged_raw_u32(EsSub32 as usize, v as u32) } else { Err(io::Error::new(io::ErrorKind::Other, &format!("length or variant id too big: {}", @@ -1101,21 +1100,24 @@ pub mod writer { self.emit_u64(v as u64) } fn emit_u64(&mut self, v: u64) -> EncodeResult { - match v.to_u32() { - Some(v) => self.emit_u32(v), - None => self.wr_tagged_raw_u64(EsU64 as usize, v) + if v as u32 as u64 == v { + self.emit_u32(v as u32) + } else { + self.wr_tagged_raw_u64(EsU64 as usize, v) } } fn emit_u32(&mut self, v: u32) -> EncodeResult { - match v.to_u16() { - Some(v) => self.emit_u16(v), - None => self.wr_tagged_raw_u32(EsU32 as usize, v) + if v as u16 as u32 == v { + self.emit_u16(v as u16) + } else { + self.wr_tagged_raw_u32(EsU32 as usize, v) } } fn emit_u16(&mut self, v: u16) -> EncodeResult { - match v.to_u8() { - Some(v) => self.emit_u8(v), - None => self.wr_tagged_raw_u16(EsU16 as usize, v) + if v as u8 as u16 == v { + self.emit_u8(v as u8) + } else { + self.wr_tagged_raw_u16(EsU16 as usize, v) } } fn emit_u8(&mut self, v: u8) -> EncodeResult { @@ -1126,21 +1128,24 @@ pub mod writer { self.emit_i64(v as i64) } fn emit_i64(&mut self, v: i64) -> EncodeResult { - match v.to_i32() { - Some(v) => self.emit_i32(v), - None => self.wr_tagged_raw_i64(EsI64 as usize, v) + if v as i32 as i64 == v { + self.emit_i32(v as i32) + } else { + self.wr_tagged_raw_i64(EsI64 as usize, v) } } fn emit_i32(&mut self, v: i32) -> EncodeResult { - match v.to_i16() { - Some(v) => self.emit_i16(v), - None => self.wr_tagged_raw_i32(EsI32 as usize, v) + if v as i16 as i32 == v { + self.emit_i16(v as i16) + } else { + self.wr_tagged_raw_i32(EsI32 as usize, v) } } fn emit_i16(&mut self, v: i16) -> EncodeResult { - match v.to_i8() { - Some(v) => self.emit_i8(v), - None => self.wr_tagged_raw_i16(EsI16 as usize, v) + if v as i8 as i16 == v { + self.emit_i8(v as i8) + } else { + self.wr_tagged_raw_i16(EsI16 as usize, v) } } fn emit_i8(&mut self, v: i8) -> EncodeResult { diff --git a/src/librustc/lib.rs b/src/librustc/lib.rs index a4bb17bc35476..32794e9793f1b 100644 --- a/src/librustc/lib.rs +++ b/src/librustc/lib.rs @@ -68,6 +68,9 @@ extern crate test; pub use rustc_llvm as llvm; +#[macro_use] +mod macros; + // NB: This module needs to be declared first so diagnostics are // registered before they are used. pub mod diagnostics; @@ -143,6 +146,7 @@ pub mod util { pub mod nodemap; pub mod snapshot_vec; pub mod lev_distance; + pub mod num; } pub mod lib { diff --git a/src/librustc/macros.rs b/src/librustc/macros.rs new file mode 100644 index 0000000000000..ed764ebd9f95d --- /dev/null +++ b/src/librustc/macros.rs @@ -0,0 +1,46 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +macro_rules! enum_from_u32 { + ($(#[$attr:meta])* pub enum $name:ident { + $($variant:ident = $e:expr,)* + }) => { + $(#[$attr])* + pub enum $name { + $($variant = $e),* + } + + impl $name { + pub fn from_u32(u: u32) -> Option<$name> { + $(if u == $name::$variant as u32 { + return Some($name::$variant) + })* + None + } + } + }; + ($(#[$attr:meta])* pub enum $name:ident { + $($variant:ident,)* + }) => { + $(#[$attr])* + pub enum $name { + $($variant,)* + } + + impl $name { + pub fn from_u32(u: u32) -> Option<$name> { + $(if u == $name::$variant as u32 { + return Some($name::$variant) + })* + None + } + } + } +} diff --git a/src/librustc/metadata/common.rs b/src/librustc/metadata/common.rs index cda0084768644..06a40f1dd277d 100644 --- a/src/librustc/metadata/common.rs +++ b/src/librustc/metadata/common.rs @@ -116,37 +116,39 @@ pub const tag_items_data_item_reexport_def_id: usize = 0x47; pub const tag_items_data_item_reexport_name: usize = 0x48; // used to encode crate_ctxt side tables -#[derive(Copy, Clone, PartialEq, FromPrimitive)] -#[repr(usize)] -pub enum astencode_tag { // Reserves 0x50 -- 0x6f - tag_ast = 0x50, - - tag_tree = 0x51, - - tag_id_range = 0x52, - - tag_table = 0x53, - // GAP 0x54, 0x55 - tag_table_def = 0x56, - tag_table_node_type = 0x57, - tag_table_item_subst = 0x58, - tag_table_freevars = 0x59, - tag_table_tcache = 0x5a, - tag_table_param_defs = 0x5b, - tag_table_mutbl = 0x5c, - tag_table_last_use = 0x5d, - tag_table_spill = 0x5e, - tag_table_method_map = 0x5f, - tag_table_vtable_map = 0x60, - tag_table_adjustments = 0x61, - tag_table_moves_map = 0x62, - tag_table_capture_map = 0x63, - tag_table_closure_tys = 0x64, - tag_table_closure_kinds = 0x65, - tag_table_upvar_capture_map = 0x66, - tag_table_capture_modes = 0x67, - tag_table_object_cast_map = 0x68, - tag_table_const_qualif = 0x69, +enum_from_u32! { + #[derive(Copy, Clone, PartialEq)] + #[repr(usize)] + pub enum astencode_tag { // Reserves 0x50 -- 0x6f + tag_ast = 0x50, + + tag_tree = 0x51, + + tag_id_range = 0x52, + + tag_table = 0x53, + // GAP 0x54, 0x55 + tag_table_def = 0x56, + tag_table_node_type = 0x57, + tag_table_item_subst = 0x58, + tag_table_freevars = 0x59, + tag_table_tcache = 0x5a, + tag_table_param_defs = 0x5b, + tag_table_mutbl = 0x5c, + tag_table_last_use = 0x5d, + tag_table_spill = 0x5e, + tag_table_method_map = 0x5f, + tag_table_vtable_map = 0x60, + tag_table_adjustments = 0x61, + tag_table_moves_map = 0x62, + tag_table_capture_map = 0x63, + tag_table_closure_tys = 0x64, + tag_table_closure_kinds = 0x65, + tag_table_upvar_capture_map = 0x66, + tag_table_capture_modes = 0x67, + tag_table_object_cast_map = 0x68, + tag_table_const_qualif = 0x69, + } } pub const tag_item_trait_item_sort: usize = 0x70; diff --git a/src/librustc/metadata/cstore.rs b/src/librustc/metadata/cstore.rs index 811aa21a0b7b9..1f18b13fc46fe 100644 --- a/src/librustc/metadata/cstore.rs +++ b/src/librustc/metadata/cstore.rs @@ -68,11 +68,13 @@ pub enum LinkagePreference { RequireStatic, } -#[derive(Copy, Clone, PartialEq, FromPrimitive)] -pub enum NativeLibraryKind { - NativeStatic, // native static library (.a archive) - NativeFramework, // OSX-specific - NativeUnknown, // default way to specify a dynamic library +enum_from_u32! { + #[derive(Copy, Clone, PartialEq)] + pub enum NativeLibraryKind { + NativeStatic, // native static library (.a archive) + NativeFramework, // OSX-specific + NativeUnknown, // default way to specify a dynamic library + } } // Where a crate came from on the local filesystem. One of these two options diff --git a/src/librustc/metadata/decoder.rs b/src/librustc/metadata/decoder.rs index 6b3bde409f540..cbd542567709c 100644 --- a/src/librustc/metadata/decoder.rs +++ b/src/librustc/metadata/decoder.rs @@ -35,7 +35,6 @@ use std::collections::HashMap; use std::hash::{self, Hash, SipHasher}; use std::io::prelude::*; use std::io; -use std::num::FromPrimitive; use std::rc::Rc; use std::slice::bytes; use std::str; @@ -1349,7 +1348,7 @@ pub fn get_native_libraries(cdata: Cmd) let kind_doc = reader::get_doc(lib_doc, tag_native_libraries_kind); let name_doc = reader::get_doc(lib_doc, tag_native_libraries_name); let kind: cstore::NativeLibraryKind = - FromPrimitive::from_u32(reader::doc_as_u32(kind_doc)).unwrap(); + cstore::NativeLibraryKind::from_u32(reader::doc_as_u32(kind_doc)).unwrap(); let name = name_doc.as_str().to_string(); result.push((kind, name)); true @@ -1359,7 +1358,7 @@ pub fn get_native_libraries(cdata: Cmd) pub fn get_plugin_registrar_fn(data: &[u8]) -> Option { reader::maybe_get_doc(rbml::Doc::new(data), tag_plugin_registrar_fn) - .map(|doc| FromPrimitive::from_u32(reader::doc_as_u32(doc)).unwrap()) + .map(|doc| reader::doc_as_u32(doc)) } pub fn each_exported_macro(data: &[u8], intr: &IdentInterner, mut f: F) where @@ -1407,7 +1406,7 @@ pub fn get_missing_lang_items(cdata: Cmd) let mut result = Vec::new(); reader::tagged_docs(items, tag_lang_items_missing, |missing_docs| { let item: lang_items::LangItem = - FromPrimitive::from_u32(reader::doc_as_u32(missing_docs)).unwrap(); + lang_items::LangItem::from_u32(reader::doc_as_u32(missing_docs)).unwrap(); result.push(item); true }); diff --git a/src/librustc/middle/astencode.rs b/src/librustc/middle/astencode.rs index 2b8540a34b15b..f05f9dc6625df 100644 --- a/src/librustc/middle/astencode.rs +++ b/src/librustc/middle/astencode.rs @@ -41,7 +41,6 @@ use syntax; use std::cell::Cell; use std::io::SeekFrom; use std::io::prelude::*; -use std::num::FromPrimitive; use std::rc::Rc; use std::fmt::Debug; @@ -1708,7 +1707,8 @@ fn decode_side_tables(dcx: &DecodeContext, debug!(">> Side table document with tag 0x{:x} \ found for id {} (orig {})", tag, id, id0); - let decoded_tag: Option = FromPrimitive::from_usize(tag); + let tag = tag as u32; + let decoded_tag: Option = c::astencode_tag::from_u32(tag); match decoded_tag { None => { dcx.tcx.sess.bug( diff --git a/src/librustc/middle/const_eval.rs b/src/librustc/middle/const_eval.rs index 367bcbbe1d8a9..2c6ffb3281fcb 100644 --- a/src/librustc/middle/const_eval.rs +++ b/src/librustc/middle/const_eval.rs @@ -20,6 +20,7 @@ use middle::{astencode, def}; use middle::pat_util::def_to_path; use middle::ty::{self, Ty}; use middle::astconv_util::ast_ty_to_prim_ty; +use util::num::ToPrimitive; use syntax::ast::{self, Expr}; use syntax::codemap::Span; @@ -30,7 +31,6 @@ use syntax::{ast_map, ast_util, codemap}; use std::borrow::{Cow, IntoCow}; use std::num::wrapping::OverflowingOps; -use std::num::ToPrimitive; use std::cmp::Ordering; use std::collections::hash_map::Entry::Vacant; use std::{i8, i16, i32, i64}; diff --git a/src/librustc/middle/lang_items.rs b/src/librustc/middle/lang_items.rs index 89a8625856c2c..c77a43e75cdc0 100644 --- a/src/librustc/middle/lang_items.rs +++ b/src/librustc/middle/lang_items.rs @@ -36,7 +36,6 @@ use syntax::visit::Visitor; use syntax::visit; use std::iter::Enumerate; -use std::num::FromPrimitive; use std::slice; // The actual lang items defined come at the end of this file in one handy table. @@ -46,9 +45,12 @@ macro_rules! lets_do_this { $( $variant:ident, $name:expr, $method:ident; )* ) => { -#[derive(Copy, Clone, FromPrimitive, PartialEq, Eq, Hash)] -pub enum LangItem { - $($variant),* + +enum_from_u32! { + #[derive(Copy, Clone, PartialEq, Eq, Hash)] + pub enum LangItem { + $($variant,)* + } } pub struct LanguageItems { @@ -71,7 +73,7 @@ impl LanguageItems { } pub fn item_name(index: usize) -> &'static str { - let item: Option = FromPrimitive::from_usize(index); + let item: Option = LangItem::from_u32(index as u32); match item { $( Some($variant) => $name, )* None => "???" diff --git a/src/librustc/middle/ty.rs b/src/librustc/middle/ty.rs index 1e817890440f2..2bf4e8d7c31b6 100644 --- a/src/librustc/middle/ty.rs +++ b/src/librustc/middle/ty.rs @@ -63,6 +63,7 @@ use util::ppaux::{Repr, UserString}; use util::common::{memoized, ErrorReported}; use util::nodemap::{NodeMap, NodeSet, DefIdMap, DefIdSet}; use util::nodemap::FnvHashMap; +use util::num::ToPrimitive; use arena::TypedArena; use std::borrow::{Borrow, Cow}; @@ -71,7 +72,6 @@ use std::cmp; use std::fmt; use std::hash::{Hash, SipHasher, Hasher}; use std::mem; -use std::num::ToPrimitive; use std::ops; use std::rc::Rc; use std::vec::IntoIter; diff --git a/src/librustc/util/num.rs b/src/librustc/util/num.rs new file mode 100644 index 0000000000000..da04976a96a37 --- /dev/null +++ b/src/librustc/util/num.rs @@ -0,0 +1,98 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +pub trait ToPrimitive { + fn to_i8(&self) -> Option; + fn to_i16(&self) -> Option; + fn to_i32(&self) -> Option; + fn to_i64(&self) -> Option; + fn to_u8(&self) -> Option; + fn to_u16(&self) -> Option; + fn to_u32(&self) -> Option; + fn to_u64(&self) -> Option; +} + +impl ToPrimitive for i64 { + fn to_i8(&self) -> Option { + if *self < i8::min_value() as i64 || *self > i8::max_value() as i64 { + None + } else { + Some(*self as i8) + } + } + fn to_i16(&self) -> Option { + if *self < i16::min_value() as i64 || *self > i16::max_value() as i64 { + None + } else { + Some(*self as i16) + } + } + fn to_i32(&self) -> Option { + if *self < i32::min_value() as i64 || *self > i32::max_value() as i64 { + None + } else { + Some(*self as i32) + } + } + fn to_i64(&self) -> Option { + Some(*self) + } + fn to_u8(&self) -> Option { + if *self < 0 || *self > u8::max_value() as i64 { + None + } else { + Some(*self as u8) + } + } + fn to_u16(&self) -> Option { + if *self < 0 || *self > u16::max_value() as i64 { + None + } else { + Some(*self as u16) + } + } + fn to_u32(&self) -> Option { + if *self < 0 || *self > u32::max_value() as i64 { + None + } else { + Some(*self as u32) + } + } + fn to_u64(&self) -> Option { + if *self < 0 {None} else {Some(*self as u64)} + } +} + +impl ToPrimitive for u64 { + fn to_i8(&self) -> Option { + if *self > i8::max_value() as u64 {None} else {Some(*self as i8)} + } + fn to_i16(&self) -> Option { + if *self > i16::max_value() as u64 {None} else {Some(*self as i16)} + } + fn to_i32(&self) -> Option { + if *self > i32::max_value() as u64 {None} else {Some(*self as i32)} + } + fn to_i64(&self) -> Option { + if *self > i64::max_value() as u64 {None} else {Some(*self as i64)} + } + fn to_u8(&self) -> Option { + if *self > u8::max_value() as u64 {None} else {Some(*self as u8)} + } + fn to_u16(&self) -> Option { + if *self > u16::max_value() as u64 {None} else {Some(*self as u16)} + } + fn to_u32(&self) -> Option { + if *self > u32::max_value() as u64 {None} else {Some(*self as u32)} + } + fn to_u64(&self) -> Option { + Some(*self) + } +} diff --git a/src/librustc_back/sha2.rs b/src/librustc_back/sha2.rs index 898f20e74518f..c45ce12efb7da 100644 --- a/src/librustc_back/sha2.rs +++ b/src/librustc_back/sha2.rs @@ -12,10 +12,7 @@ //! use. This implementation is not intended for external use or for any use where security is //! important. -#![allow(deprecated)] // to_be32 - use std::iter::repeat; -use std::num::Int; use std::slice::bytes::{MutableByteVector, copy_memory}; use serialize::hex::ToHex; @@ -61,10 +58,10 @@ impl ToBits for u64 { /// Adds the specified number of bytes to the bit count. panic!() if this would cause numeric /// overflow. -fn add_bytes_to_bits(bits: T, bytes: T) -> T { +fn add_bytes_to_bits(bits: u64, bytes: u64) -> u64 { let (new_high_bits, new_low_bits) = bytes.to_bits(); - if new_high_bits > T::zero() { + if new_high_bits > 0 { panic!("numeric overflow occurred.") } diff --git a/src/librustc_trans/back/lto.rs b/src/librustc_trans/back/lto.rs index 4e099a4ca875e..e8752ab14b344 100644 --- a/src/librustc_trans/back/lto.rs +++ b/src/librustc_trans/back/lto.rs @@ -21,9 +21,6 @@ use libc; use flate; use std::ffi::CString; -use std::mem; -#[allow(deprecated)] -use std::num::Int; pub fn run(sess: &session::Session, llmod: ModuleRef, tm: TargetMachineRef, reachable: &[String]) { @@ -198,19 +195,15 @@ fn is_versioned_bytecode_format(bc: &[u8]) -> bool { } fn extract_bytecode_format_version(bc: &[u8]) -> u32 { - return read_from_le_bytes::(bc, link::RLIB_BYTECODE_OBJECT_VERSION_OFFSET); + let pos = link::RLIB_BYTECODE_OBJECT_VERSION_OFFSET; + let byte_data = &bc[pos..pos + 4]; + let data = unsafe { *(byte_data.as_ptr() as *const u32) }; + u32::from_le(data) } fn extract_compressed_bytecode_size_v1(bc: &[u8]) -> u64 { - return read_from_le_bytes::(bc, link::RLIB_BYTECODE_OBJECT_V1_DATASIZE_OFFSET); -} - -#[allow(deprecated)] -fn read_from_le_bytes(bytes: &[u8], position_in_bytes: usize) -> T { - let byte_data = &bytes[position_in_bytes..position_in_bytes + mem::size_of::()]; - let data = unsafe { - *(byte_data.as_ptr() as *const T) - }; - - Int::from_le(data) + let pos = link::RLIB_BYTECODE_OBJECT_V1_DATASIZE_OFFSET; + let byte_data = &bc[pos..pos + 8]; + let data = unsafe { *(byte_data.as_ptr() as *const u64) }; + u64::from_le(data) } diff --git a/src/librustc_trans/trans/adt.rs b/src/librustc_trans/trans/adt.rs index f574b4ed8db90..de2ae970c8a2a 100644 --- a/src/librustc_trans/trans/adt.rs +++ b/src/librustc_trans/trans/adt.rs @@ -45,8 +45,6 @@ pub use self::Repr::*; -#[allow(deprecated)] -use std::num::Int; use std::rc::Rc; use llvm::{ValueRef, True, IntEQ, IntNE}; diff --git a/src/librustc_trans/trans/type_of.rs b/src/librustc_trans/trans/type_of.rs index b3ab58e416f74..9f01521313633 100644 --- a/src/librustc_trans/trans/type_of.rs +++ b/src/librustc_trans/trans/type_of.rs @@ -21,8 +21,6 @@ use util::ppaux::Repr; use trans::type_::Type; -#[allow(deprecated)] -use std::num::Int; use syntax::abi; use syntax::ast; diff --git a/src/libserialize/json.rs b/src/libserialize/json.rs index b4f679a810989..f17ce14f9eff9 100644 --- a/src/libserialize/json.rs +++ b/src/libserialize/json.rs @@ -204,12 +204,10 @@ use std::io::prelude::*; use std::io; use std::mem::swap; use std::num::FpCategory as Fp; -#[allow(deprecated)] -use std::num::wrapping::WrappingOps; use std::ops::Index; use std::str::FromStr; use std::string; -use std::{char, f64, fmt, num, str}; +use std::{char, f64, fmt, str}; use std; use unicode::str as unicode_str; use unicode::str::Utf16Item; @@ -460,8 +458,8 @@ fn spaces(wr: &mut fmt::Write, mut n: usize) -> EncodeResult { fn fmt_number_or_null(v: f64) -> string::String { match v.classify() { Fp::Nan | Fp::Infinite => string::String::from_str("null"), - _ if v.fract() != 0f64 => f64::to_str_digits(v, 6), - _ => f64::to_str_digits(v, 6) + ".0", + _ if v.fract() != 0f64 => v.to_string(), + _ => v.to_string() + ".0", } } @@ -1165,7 +1163,7 @@ impl Json { pub fn as_i64(&self) -> Option { match *self { Json::I64(n) => Some(n), - Json::U64(n) => num::cast(n), + Json::U64(n) => Some(n as i64), _ => None } } @@ -1174,7 +1172,7 @@ impl Json { /// Returns None otherwise. pub fn as_u64(&self) -> Option { match *self { - Json::I64(n) => num::cast(n), + Json::I64(n) => Some(n as u64), Json::U64(n) => Some(n), _ => None } @@ -1184,8 +1182,8 @@ impl Json { /// Returns None otherwise. pub fn as_f64(&self) -> Option { match *self { - Json::I64(n) => num::cast(n), - Json::U64(n) => num::cast(n), + Json::I64(n) => Some(n as f64), + Json::U64(n) => Some(n as f64), Json::F64(n) => Some(n), _ => None } @@ -1556,7 +1554,7 @@ impl> Parser { #[allow(deprecated)] // possible resolve bug is mapping these to traits fn parse_u64(&mut self) -> Result { - let mut accum = 0; + let mut accum = 0u64; let last_accum = 0; // necessary to detect overflow. match self.ch_or_null() { @@ -2121,14 +2119,8 @@ macro_rules! read_primitive { ($name:ident, $ty:ty) => { fn $name(&mut self) -> DecodeResult<$ty> { match self.pop() { - Json::I64(f) => match num::cast(f) { - Some(f) => Ok(f), - None => Err(ExpectedError("Number".to_string(), format!("{}", f))), - }, - Json::U64(f) => match num::cast(f) { - Some(f) => Ok(f), - None => Err(ExpectedError("Number".to_string(), format!("{}", f))), - }, + Json::I64(f) => Ok(f as $ty), + Json::U64(f) => Ok(f as $ty), Json::F64(f) => Err(ExpectedError("Integer".to_string(), format!("{}", f))), // re: #12967.. a type w/ numeric keys (ie HashMap etc) // is going to have a string here, as per JSON spec. diff --git a/src/libstd/collections/hash/table.rs b/src/libstd/collections/hash/table.rs index dec6d1e2209ad..3636457ea2766 100644 --- a/src/libstd/collections/hash/table.rs +++ b/src/libstd/collections/hash/table.rs @@ -19,7 +19,7 @@ use iter::{Iterator, ExactSizeIterator}; use marker::{Copy, Send, Sync, Sized, self}; use mem::{min_align_of, size_of}; use mem; -use num::wrapping::{OverflowingOps, WrappingOps}; +use num::wrapping::OverflowingOps; use ops::{Deref, DerefMut, Drop}; use option::Option; use option::Option::{Some, None}; diff --git a/src/libstd/io/error.rs b/src/libstd/io/error.rs index a49039b1ec4ee..4e36b2438b457 100644 --- a/src/libstd/io/error.rs +++ b/src/libstd/io/error.rs @@ -172,13 +172,6 @@ impl Error { Error { repr: Repr::Os(code) } } - /// Creates a new instance of an `Error` from a particular OS error code. - #[unstable(feature = "io", reason = "deprecated")] - #[deprecated(since = "1.0.0", reason = "renamed to from_raw_os_error")] - pub fn from_os_error(code: i32) -> Error { - Error { repr: Repr::Os(code) } - } - /// Returns the OS error that this error represents (if any). /// /// If this `Error` was constructed via `last_os_error` then this function diff --git a/src/libstd/lib.rs b/src/libstd/lib.rs index b2bcbaa7b1c2b..addd3c4d0a3bd 100644 --- a/src/libstd/lib.rs +++ b/src/libstd/lib.rs @@ -128,6 +128,7 @@ #![feature(std_misc)] #![feature(slice_patterns)] #![feature(debug_builders)] +#![feature(zero_one)] #![cfg_attr(test, feature(test, rustc_private, std_misc))] // Don't link to std. We are std. diff --git a/src/libstd/net/mod.rs b/src/libstd/net/mod.rs index a152b98822a0b..3bfc764e540b2 100644 --- a/src/libstd/net/mod.rs +++ b/src/libstd/net/mod.rs @@ -18,8 +18,6 @@ use prelude::v1::*; use io::{self, Error, ErrorKind}; -#[allow(deprecated)] // Int -use num::Int; use sys_common::net2 as net_imp; pub use self::ip::{IpAddr, Ipv4Addr, Ipv6Addr, Ipv6MulticastScope}; @@ -55,10 +53,21 @@ pub enum Shutdown { Both, } -#[allow(deprecated)] // Int -fn hton(i: I) -> I { i.to_be() } -#[allow(deprecated)] // Int -fn ntoh(i: I) -> I { Int::from_be(i) } +#[doc(hidden)] +trait NetInt { + fn from_be(i: Self) -> Self; + fn to_be(&self) -> Self; +} +macro_rules! doit { + ($($t:ident)*) => ($(impl NetInt for $t { + fn from_be(i: Self) -> Self { <$t>::from_be(i) } + fn to_be(&self) -> Self { <$t>::to_be(*self) } + })*) +} +doit! { i8 i16 i32 i64 isize u8 u16 u32 u64 usize } + +fn hton(i: I) -> I { i.to_be() } +fn ntoh(i: I) -> I { I::from_be(i) } fn each_addr(addr: A, mut f: F) -> io::Result where F: FnMut(&SocketAddr) -> io::Result diff --git a/src/libstd/num/f32.rs b/src/libstd/num/f32.rs index 736f6d2f4f4f8..430fec4ff2e73 100644 --- a/src/libstd/num/f32.rs +++ b/src/libstd/num/f32.rs @@ -15,20 +15,14 @@ #![allow(unsigned_negation)] #![doc(primitive = "f32")] -use prelude::v1::*; - use intrinsics; use libc::c_int; -use num::{Float, FpCategory}; -use num::strconv; -use num::strconv::ExponentFormat::{ExpNone, ExpDec}; -use num::strconv::SignificantDigits::{DigAll, DigMax, DigExact}; -use num::strconv::SignFormat::SignNeg; +use num::FpCategory; use core::num; -pub use core::f32::{RADIX, MANTISSA_DIGITS, DIGITS, EPSILON, MIN_VALUE}; -pub use core::f32::{MIN_POS_VALUE, MAX_VALUE, MIN_EXP, MAX_EXP, MIN_10_EXP}; +pub use core::f32::{RADIX, MANTISSA_DIGITS, DIGITS, EPSILON}; +pub use core::f32::{MIN_EXP, MAX_EXP, MIN_10_EXP}; pub use core::f32::{MAX_10_EXP, NAN, INFINITY, NEG_INFINITY}; pub use core::f32::{MIN, MIN_POSITIVE, MAX}; pub use core::f32::consts; @@ -74,290 +68,6 @@ mod cmath { } } -#[stable(feature = "rust1", since = "1.0.0")] -#[allow(deprecated)] -impl Float for f32 { - #[inline] - fn nan() -> f32 { num::Float::nan() } - #[inline] - fn infinity() -> f32 { num::Float::infinity() } - #[inline] - fn neg_infinity() -> f32 { num::Float::neg_infinity() } - #[inline] - fn zero() -> f32 { num::Float::zero() } - #[inline] - fn neg_zero() -> f32 { num::Float::neg_zero() } - #[inline] - fn one() -> f32 { num::Float::one() } - - #[allow(deprecated)] - #[inline] - fn mantissa_digits(unused_self: Option) -> usize { - num::Float::mantissa_digits(unused_self) - } - #[allow(deprecated)] - #[inline] - fn digits(unused_self: Option) -> usize { num::Float::digits(unused_self) } - #[allow(deprecated)] - #[inline] - fn epsilon() -> f32 { num::Float::epsilon() } - #[allow(deprecated)] - #[inline] - fn min_exp(unused_self: Option) -> isize { num::Float::min_exp(unused_self) } - #[allow(deprecated)] - #[inline] - fn max_exp(unused_self: Option) -> isize { num::Float::max_exp(unused_self) } - #[allow(deprecated)] - #[inline] - fn min_10_exp(unused_self: Option) -> isize { num::Float::min_10_exp(unused_self) } - #[allow(deprecated)] - #[inline] - fn max_10_exp(unused_self: Option) -> isize { num::Float::max_10_exp(unused_self) } - #[allow(deprecated)] - #[inline] - fn min_value() -> f32 { num::Float::min_value() } - #[allow(deprecated)] - #[inline] - fn min_pos_value(unused_self: Option) -> f32 { num::Float::min_pos_value(unused_self) } - #[allow(deprecated)] - #[inline] - fn max_value() -> f32 { num::Float::max_value() } - - #[inline] - fn is_nan(self) -> bool { num::Float::is_nan(self) } - #[inline] - fn is_infinite(self) -> bool { num::Float::is_infinite(self) } - #[inline] - fn is_finite(self) -> bool { num::Float::is_finite(self) } - #[inline] - fn is_normal(self) -> bool { num::Float::is_normal(self) } - #[inline] - fn classify(self) -> FpCategory { num::Float::classify(self) } - - #[inline] - fn integer_decode(self) -> (u64, i16, i8) { num::Float::integer_decode(self) } - - #[inline] - fn floor(self) -> f32 { num::Float::floor(self) } - #[inline] - fn ceil(self) -> f32 { num::Float::ceil(self) } - #[inline] - fn round(self) -> f32 { num::Float::round(self) } - #[inline] - fn trunc(self) -> f32 { num::Float::trunc(self) } - #[inline] - fn fract(self) -> f32 { num::Float::fract(self) } - - #[inline] - fn abs(self) -> f32 { num::Float::abs(self) } - #[inline] - fn signum(self) -> f32 { num::Float::signum(self) } - #[inline] - fn is_positive(self) -> bool { num::Float::is_positive(self) } - #[inline] - fn is_negative(self) -> bool { num::Float::is_negative(self) } - - #[inline] - fn mul_add(self, a: f32, b: f32) -> f32 { num::Float::mul_add(self, a, b) } - #[inline] - fn recip(self) -> f32 { num::Float::recip(self) } - - #[inline] - fn powi(self, n: i32) -> f32 { num::Float::powi(self, n) } - #[inline] - fn powf(self, n: f32) -> f32 { num::Float::powf(self, n) } - - #[inline] - fn sqrt(self) -> f32 { num::Float::sqrt(self) } - #[inline] - fn rsqrt(self) -> f32 { num::Float::rsqrt(self) } - - #[inline] - fn exp(self) -> f32 { num::Float::exp(self) } - #[inline] - fn exp2(self) -> f32 { num::Float::exp2(self) } - #[inline] - fn ln(self) -> f32 { num::Float::ln(self) } - #[inline] - fn log(self, base: f32) -> f32 { num::Float::log(self, base) } - #[inline] - fn log2(self) -> f32 { num::Float::log2(self) } - #[inline] - fn log10(self) -> f32 { num::Float::log10(self) } - #[inline] - fn to_degrees(self) -> f32 { num::Float::to_degrees(self) } - #[inline] - fn to_radians(self) -> f32 { num::Float::to_radians(self) } - - /// Constructs a floating point number by multiplying `x` by 2 raised to the - /// power of `exp` - #[inline] - fn ldexp(self, exp: isize) -> f32 { - unsafe { cmath::ldexpf(self, exp as c_int) } - } - - /// Breaks the number into a normalized fraction and a base-2 exponent, - /// satisfying: - /// - /// - `self = x * pow(2, exp)` - /// - `0.5 <= abs(x) < 1.0` - #[inline] - fn frexp(self) -> (f32, isize) { - unsafe { - let mut exp = 0; - let x = cmath::frexpf(self, &mut exp); - (x, exp as isize) - } - } - - /// Returns the next representable floating-point value in the direction of - /// `other`. - #[inline] - fn next_after(self, other: f32) -> f32 { - unsafe { cmath::nextafterf(self, other) } - } - - #[inline] - fn max(self, other: f32) -> f32 { - unsafe { cmath::fmaxf(self, other) } - } - - #[inline] - fn min(self, other: f32) -> f32 { - unsafe { cmath::fminf(self, other) } - } - - #[inline] - fn abs_sub(self, other: f32) -> f32 { - unsafe { cmath::fdimf(self, other) } - } - - #[inline] - fn cbrt(self) -> f32 { - unsafe { cmath::cbrtf(self) } - } - - #[inline] - fn hypot(self, other: f32) -> f32 { - unsafe { cmath::hypotf(self, other) } - } - - #[inline] - fn sin(self) -> f32 { - unsafe { intrinsics::sinf32(self) } - } - - #[inline] - fn cos(self) -> f32 { - unsafe { intrinsics::cosf32(self) } - } - - #[inline] - fn tan(self) -> f32 { - unsafe { cmath::tanf(self) } - } - - #[inline] - fn asin(self) -> f32 { - unsafe { cmath::asinf(self) } - } - - #[inline] - fn acos(self) -> f32 { - unsafe { cmath::acosf(self) } - } - - #[inline] - fn atan(self) -> f32 { - unsafe { cmath::atanf(self) } - } - - #[inline] - fn atan2(self, other: f32) -> f32 { - unsafe { cmath::atan2f(self, other) } - } - - /// Simultaneously computes the sine and cosine of the number - #[inline] - fn sin_cos(self) -> (f32, f32) { - (self.sin(), self.cos()) - } - - /// Returns the exponential of the number, minus `1`, in a way that is - /// accurate even if the number is close to zero - #[inline] - fn exp_m1(self) -> f32 { - unsafe { cmath::expm1f(self) } - } - - /// Returns the natural logarithm of the number plus `1` (`ln(1+n)`) more - /// accurately than if the operations were performed separately - #[inline] - fn ln_1p(self) -> f32 { - unsafe { cmath::log1pf(self) } - } - - #[inline] - fn sinh(self) -> f32 { - unsafe { cmath::sinhf(self) } - } - - #[inline] - fn cosh(self) -> f32 { - unsafe { cmath::coshf(self) } - } - - #[inline] - fn tanh(self) -> f32 { - unsafe { cmath::tanhf(self) } - } - - /// Inverse hyperbolic sine - /// - /// # Returns - /// - /// - on success, the inverse hyperbolic sine of `self` will be returned - /// - `self` if `self` is `0.0`, `-0.0`, `INFINITY`, or `NEG_INFINITY` - /// - `NAN` if `self` is `NAN` - #[inline] - fn asinh(self) -> f32 { - match self { - NEG_INFINITY => NEG_INFINITY, - x => (x + ((x * x) + 1.0).sqrt()).ln(), - } - } - - /// Inverse hyperbolic cosine - /// - /// # Returns - /// - /// - on success, the inverse hyperbolic cosine of `self` will be returned - /// - `INFINITY` if `self` is `INFINITY` - /// - `NAN` if `self` is `NAN` or `self < 1.0` (including `NEG_INFINITY`) - #[inline] - fn acosh(self) -> f32 { - match self { - x if x < 1.0 => Float::nan(), - x => (x + ((x * x) - 1.0).sqrt()).ln(), - } - } - - /// Inverse hyperbolic tangent - /// - /// # Returns - /// - /// - on success, the inverse hyperbolic tangent of `self` will be returned - /// - `self` if `self` is `0.0` or `-0.0` - /// - `INFINITY` if `self` is `1.0` - /// - `NEG_INFINITY` if `self` is `-1.0` - /// - `NAN` if the `self` is `NAN` or outside the domain of `-1.0 <= self <= 1.0` - /// (including `INFINITY` and `NEG_INFINITY`) - #[inline] - fn atanh(self) -> f32 { - 0.5 * ((2.0 * self) / (1.0 - self)).ln_1p() - } -} - #[cfg(not(test))] #[lang = "f32"] #[stable(feature = "rust1", since = "1.0.0")] @@ -617,11 +327,6 @@ impl f32 { #[inline] pub fn is_sign_positive(self) -> bool { num::Float::is_positive(self) } - #[stable(feature = "rust1", since = "1.0.0")] - #[deprecated(since = "1.0.0", reason = "renamed to is_sign_positive")] - #[inline] - pub fn is_positive(self) -> bool { num::Float::is_positive(self) } - /// Returns `true` if `self`'s sign is negative, including `-0.0` /// and `NEG_INFINITY`. /// @@ -641,11 +346,6 @@ impl f32 { #[inline] pub fn is_sign_negative(self) -> bool { num::Float::is_negative(self) } - #[stable(feature = "rust1", since = "1.0.0")] - #[deprecated(since = "1.0.0", reason = "renamed to is_sign_negative")] - #[inline] - pub fn is_negative(self) -> bool { num::Float::is_negative(self) } - /// Fused multiply-add. Computes `(self * a) + b` with only one rounding /// error. This produces a more accurate result with better performance than /// a separate multiplication operation followed by an add. @@ -729,24 +429,6 @@ impl f32 { #[inline] pub fn sqrt(self) -> f32 { num::Float::sqrt(self) } - /// Takes the reciprocal (inverse) square root of a number, `1/sqrt(x)`. - /// - /// ``` - /// # #![feature(std_misc)] - /// use std::f32; - /// - /// let f = 4.0f32; - /// - /// let abs_difference = (f.rsqrt() - 0.5).abs(); - /// - /// assert!(abs_difference <= f32::EPSILON); - /// ``` - #[unstable(feature = "std_misc", - reason = "unsure about its place in the world")] - #[deprecated(since = "1.0.0", reason = "use self.sqrt().recip() instead")] - #[inline] - pub fn rsqrt(self) -> f32 { num::Float::rsqrt(self) } - /// Returns `e^(self)`, (the exponential function). /// /// ``` @@ -1339,7 +1021,7 @@ impl f32 { #[inline] pub fn acosh(self) -> f32 { match self { - x if x < 1.0 => Float::nan(), + x if x < 1.0 => num::Float::nan(), x => (x + ((x * x) - 1.0).sqrt()).ln(), } } @@ -1363,114 +1045,6 @@ impl f32 { } } -// -// Section: String Conversions -// - -/// Converts a float to a string -/// -/// # Arguments -/// -/// * num - The float value -#[inline] -#[unstable(feature = "std_misc", reason = "may be removed or relocated")] -#[deprecated(since = "1.0.0", reason = "use the ToString trait instead")] -pub fn to_string(num: f32) -> String { - let (r, _) = strconv::float_to_str_common( - num, 10, true, SignNeg, DigAll, ExpNone, false); - r -} - -/// Converts a float to a string in hexadecimal format -/// -/// # Arguments -/// -/// * num - The float value -#[inline] -#[unstable(feature = "std_misc", reason = "may be removed or relocated")] -#[deprecated(since = "1.0.0", reason = "use format! instead")] -pub fn to_str_hex(num: f32) -> String { - let (r, _) = strconv::float_to_str_common( - num, 16, true, SignNeg, DigAll, ExpNone, false); - r -} - -/// Converts a float to a string in a given radix, and a flag indicating -/// whether it's a special value -/// -/// # Arguments -/// -/// * num - The float value -/// * radix - The base to use -#[inline] -#[unstable(feature = "std_misc", reason = "may be removed or relocated")] -#[deprecated(since = "1.0.0", reason = "use format! instead")] -pub fn to_str_radix_special(num: f32, rdx: u32) -> (String, bool) { - strconv::float_to_str_common(num, rdx, true, SignNeg, DigAll, ExpNone, false) -} - -/// Converts a float to a string with exactly the number of -/// provided significant digits -/// -/// # Arguments -/// -/// * num - The float value -/// * digits - The number of significant digits -#[inline] -#[unstable(feature = "std_misc", reason = "may be removed or relocated")] -pub fn to_str_exact(num: f32, dig: usize) -> String { - let (r, _) = strconv::float_to_str_common( - num, 10, true, SignNeg, DigExact(dig), ExpNone, false); - r -} - -/// Converts a float to a string with a maximum number of -/// significant digits -/// -/// # Arguments -/// -/// * num - The float value -/// * digits - The number of significant digits -#[inline] -#[unstable(feature = "std_misc", reason = "may be removed or relocated")] -pub fn to_str_digits(num: f32, dig: usize) -> String { - let (r, _) = strconv::float_to_str_common( - num, 10, true, SignNeg, DigMax(dig), ExpNone, false); - r -} - -/// Converts a float to a string using the exponential notation with exactly the number of -/// provided digits after the decimal point in the significand -/// -/// # Arguments -/// -/// * num - The float value -/// * digits - The number of digits after the decimal point -/// * upper - Use `E` instead of `e` for the exponent sign -#[inline] -#[unstable(feature = "std_misc", reason = "may be removed or relocated")] -pub fn to_str_exp_exact(num: f32, dig: usize, upper: bool) -> String { - let (r, _) = strconv::float_to_str_common( - num, 10, true, SignNeg, DigExact(dig), ExpDec, upper); - r -} - -/// Converts a float to a string using the exponential notation with the maximum number of -/// digits after the decimal point in the significand -/// -/// # Arguments -/// -/// * num - The float value -/// * digits - The number of digits after the decimal point -/// * upper - Use `E` instead of `e` for the exponent sign -#[inline] -#[unstable(feature = "std_misc", reason = "may be removed or relocated")] -pub fn to_str_exp_digits(num: f32, dig: usize, upper: bool) -> String { - let (r, _) = strconv::float_to_str_common( - num, 10, true, SignNeg, DigMax(dig), ExpDec, upper); - r -} - #[cfg(test)] mod tests { use f32::*; diff --git a/src/libstd/num/f64.rs b/src/libstd/num/f64.rs index bb9067eca13dd..bd50a087c71b4 100644 --- a/src/libstd/num/f64.rs +++ b/src/libstd/num/f64.rs @@ -14,20 +14,14 @@ #![allow(missing_docs)] #![doc(primitive = "f64")] -use prelude::v1::*; - use intrinsics; use libc::c_int; -use num::{Float, FpCategory}; -use num::strconv; -use num::strconv::ExponentFormat::{ExpNone, ExpDec}; -use num::strconv::SignificantDigits::{DigAll, DigMax, DigExact}; -use num::strconv::SignFormat::SignNeg; +use num::FpCategory; use core::num; -pub use core::f64::{RADIX, MANTISSA_DIGITS, DIGITS, EPSILON, MIN_VALUE}; -pub use core::f64::{MIN_POS_VALUE, MAX_VALUE, MIN_EXP, MAX_EXP, MIN_10_EXP}; +pub use core::f64::{RADIX, MANTISSA_DIGITS, DIGITS, EPSILON}; +pub use core::f64::{MIN_EXP, MAX_EXP, MIN_10_EXP}; pub use core::f64::{MAX_10_EXP, NAN, INFINITY, NEG_INFINITY}; pub use core::f64::{MIN, MIN_POSITIVE, MAX}; pub use core::f64::consts; @@ -82,291 +76,6 @@ mod cmath { } } -#[stable(feature = "rust1", since = "1.0.0")] -#[allow(deprecated)] -impl Float for f64 { - // inlined methods from `num::Float` - #[inline] - fn nan() -> f64 { num::Float::nan() } - #[inline] - fn infinity() -> f64 { num::Float::infinity() } - #[inline] - fn neg_infinity() -> f64 { num::Float::neg_infinity() } - #[inline] - fn zero() -> f64 { num::Float::zero() } - #[inline] - fn neg_zero() -> f64 { num::Float::neg_zero() } - #[inline] - fn one() -> f64 { num::Float::one() } - - - #[allow(deprecated)] - #[inline] - fn mantissa_digits(unused_self: Option) -> usize { - num::Float::mantissa_digits(unused_self) - } - #[allow(deprecated)] - #[inline] - fn digits(unused_self: Option) -> usize { num::Float::digits(unused_self) } - #[allow(deprecated)] - #[inline] - fn epsilon() -> f64 { num::Float::epsilon() } - #[allow(deprecated)] - #[inline] - fn min_exp(unused_self: Option) -> isize { num::Float::min_exp(unused_self) } - #[allow(deprecated)] - #[inline] - fn max_exp(unused_self: Option) -> isize { num::Float::max_exp(unused_self) } - #[allow(deprecated)] - #[inline] - fn min_10_exp(unused_self: Option) -> isize { num::Float::min_10_exp(unused_self) } - #[allow(deprecated)] - #[inline] - fn max_10_exp(unused_self: Option) -> isize { num::Float::max_10_exp(unused_self) } - #[allow(deprecated)] - #[inline] - fn min_value() -> f64 { num::Float::min_value() } - #[allow(deprecated)] - #[inline] - fn min_pos_value(unused_self: Option) -> f64 { num::Float::min_pos_value(unused_self) } - #[allow(deprecated)] - #[inline] - fn max_value() -> f64 { num::Float::max_value() } - - #[inline] - fn is_nan(self) -> bool { num::Float::is_nan(self) } - #[inline] - fn is_infinite(self) -> bool { num::Float::is_infinite(self) } - #[inline] - fn is_finite(self) -> bool { num::Float::is_finite(self) } - #[inline] - fn is_normal(self) -> bool { num::Float::is_normal(self) } - #[inline] - fn classify(self) -> FpCategory { num::Float::classify(self) } - - #[inline] - fn integer_decode(self) -> (u64, i16, i8) { num::Float::integer_decode(self) } - - #[inline] - fn floor(self) -> f64 { num::Float::floor(self) } - #[inline] - fn ceil(self) -> f64 { num::Float::ceil(self) } - #[inline] - fn round(self) -> f64 { num::Float::round(self) } - #[inline] - fn trunc(self) -> f64 { num::Float::trunc(self) } - #[inline] - fn fract(self) -> f64 { num::Float::fract(self) } - - #[inline] - fn abs(self) -> f64 { num::Float::abs(self) } - #[inline] - fn signum(self) -> f64 { num::Float::signum(self) } - #[inline] - fn is_positive(self) -> bool { num::Float::is_positive(self) } - #[inline] - fn is_negative(self) -> bool { num::Float::is_negative(self) } - - #[inline] - fn mul_add(self, a: f64, b: f64) -> f64 { num::Float::mul_add(self, a, b) } - #[inline] - fn recip(self) -> f64 { num::Float::recip(self) } - - #[inline] - fn powi(self, n: i32) -> f64 { num::Float::powi(self, n) } - #[inline] - fn powf(self, n: f64) -> f64 { num::Float::powf(self, n) } - - #[inline] - fn sqrt(self) -> f64 { num::Float::sqrt(self) } - #[inline] - fn rsqrt(self) -> f64 { num::Float::rsqrt(self) } - - #[inline] - fn exp(self) -> f64 { num::Float::exp(self) } - #[inline] - fn exp2(self) -> f64 { num::Float::exp2(self) } - #[inline] - fn ln(self) -> f64 { num::Float::ln(self) } - #[inline] - fn log(self, base: f64) -> f64 { num::Float::log(self, base) } - #[inline] - fn log2(self) -> f64 { num::Float::log2(self) } - #[inline] - fn log10(self) -> f64 { num::Float::log10(self) } - - #[inline] - fn to_degrees(self) -> f64 { num::Float::to_degrees(self) } - #[inline] - fn to_radians(self) -> f64 { num::Float::to_radians(self) } - - #[inline] - fn ldexp(self, exp: isize) -> f64 { - unsafe { cmath::ldexp(self, exp as c_int) } - } - - /// Breaks the number into a normalized fraction and a base-2 exponent, - /// satisfying: - /// - /// - `self = x * pow(2, exp)` - /// - `0.5 <= abs(x) < 1.0` - #[inline] - fn frexp(self) -> (f64, isize) { - unsafe { - let mut exp = 0; - let x = cmath::frexp(self, &mut exp); - (x, exp as isize) - } - } - - /// Returns the next representable floating-point value in the direction of - /// `other`. - #[inline] - fn next_after(self, other: f64) -> f64 { - unsafe { cmath::nextafter(self, other) } - } - - #[inline] - fn max(self, other: f64) -> f64 { - unsafe { cmath::fmax(self, other) } - } - - #[inline] - fn min(self, other: f64) -> f64 { - unsafe { cmath::fmin(self, other) } - } - - #[inline] - fn abs_sub(self, other: f64) -> f64 { - unsafe { cmath::fdim(self, other) } - } - - #[inline] - fn cbrt(self) -> f64 { - unsafe { cmath::cbrt(self) } - } - - #[inline] - fn hypot(self, other: f64) -> f64 { - unsafe { cmath::hypot(self, other) } - } - - #[inline] - fn sin(self) -> f64 { - unsafe { intrinsics::sinf64(self) } - } - - #[inline] - fn cos(self) -> f64 { - unsafe { intrinsics::cosf64(self) } - } - - #[inline] - fn tan(self) -> f64 { - unsafe { cmath::tan(self) } - } - - #[inline] - fn asin(self) -> f64 { - unsafe { cmath::asin(self) } - } - - #[inline] - fn acos(self) -> f64 { - unsafe { cmath::acos(self) } - } - - #[inline] - fn atan(self) -> f64 { - unsafe { cmath::atan(self) } - } - - #[inline] - fn atan2(self, other: f64) -> f64 { - unsafe { cmath::atan2(self, other) } - } - - /// Simultaneously computes the sine and cosine of the number - #[inline] - fn sin_cos(self) -> (f64, f64) { - (self.sin(), self.cos()) - } - - /// Returns the exponential of the number, minus `1`, in a way that is - /// accurate even if the number is close to zero - #[inline] - fn exp_m1(self) -> f64 { - unsafe { cmath::expm1(self) } - } - - /// Returns the natural logarithm of the number plus `1` (`ln(1+n)`) more - /// accurately than if the operations were performed separately - #[inline] - fn ln_1p(self) -> f64 { - unsafe { cmath::log1p(self) } - } - - #[inline] - fn sinh(self) -> f64 { - unsafe { cmath::sinh(self) } - } - - #[inline] - fn cosh(self) -> f64 { - unsafe { cmath::cosh(self) } - } - - #[inline] - fn tanh(self) -> f64 { - unsafe { cmath::tanh(self) } - } - - /// Inverse hyperbolic sine - /// - /// # Returns - /// - /// - on success, the inverse hyperbolic sine of `self` will be returned - /// - `self` if `self` is `0.0`, `-0.0`, `INFINITY`, or `NEG_INFINITY` - /// - `NAN` if `self` is `NAN` - #[inline] - fn asinh(self) -> f64 { - match self { - NEG_INFINITY => NEG_INFINITY, - x => (x + ((x * x) + 1.0).sqrt()).ln(), - } - } - - /// Inverse hyperbolic cosine - /// - /// # Returns - /// - /// - on success, the inverse hyperbolic cosine of `self` will be returned - /// - `INFINITY` if `self` is `INFINITY` - /// - `NAN` if `self` is `NAN` or `self < 1.0` (including `NEG_INFINITY`) - #[inline] - fn acosh(self) -> f64 { - match self { - x if x < 1.0 => Float::nan(), - x => (x + ((x * x) - 1.0).sqrt()).ln(), - } - } - - /// Inverse hyperbolic tangent - /// - /// # Returns - /// - /// - on success, the inverse hyperbolic tangent of `self` will be returned - /// - `self` if `self` is `0.0` or `-0.0` - /// - `INFINITY` if `self` is `1.0` - /// - `NEG_INFINITY` if `self` is `-1.0` - /// - `NAN` if the `self` is `NAN` or outside the domain of `-1.0 <= self <= 1.0` - /// (including `INFINITY` and `NEG_INFINITY`) - #[inline] - fn atanh(self) -> f64 { - 0.5 * ((2.0 * self) / (1.0 - self)).ln_1p() - } -} - #[cfg(not(test))] #[lang = "f64"] #[stable(feature = "rust1", since = "1.0.0")] @@ -1304,7 +1013,7 @@ impl f64 { #[inline] pub fn acosh(self) -> f64 { match self { - x if x < 1.0 => Float::nan(), + x if x < 1.0 => num::Float::nan(), x => (x + ((x * x) - 1.0).sqrt()).ln(), } } @@ -1328,114 +1037,6 @@ impl f64 { } } -// -// Section: String Conversions -// - -/// Converts a float to a string -/// -/// # Arguments -/// -/// * num - The float value -#[inline] -#[unstable(feature = "std_misc", reason = "may be removed or relocated")] -#[deprecated(since = "1.0.0", reason = "use the ToString trait instead")] -pub fn to_string(num: f64) -> String { - let (r, _) = strconv::float_to_str_common( - num, 10, true, SignNeg, DigAll, ExpNone, false); - r -} - -/// Converts a float to a string in hexadecimal format -/// -/// # Arguments -/// -/// * num - The float value -#[inline] -#[unstable(feature = "std_misc", reason = "may be removed or relocated")] -#[deprecated(since = "1.0.0", reason = "use format! instead")] -pub fn to_str_hex(num: f64) -> String { - let (r, _) = strconv::float_to_str_common( - num, 16, true, SignNeg, DigAll, ExpNone, false); - r -} - -/// Converts a float to a string in a given radix, and a flag indicating -/// whether it's a special value -/// -/// # Arguments -/// -/// * num - The float value -/// * radix - The base to use -#[inline] -#[unstable(feature = "std_misc", reason = "may be removed or relocated")] -#[deprecated(since = "1.0.0", reason = "use format! instead")] -pub fn to_str_radix_special(num: f64, rdx: u32) -> (String, bool) { - strconv::float_to_str_common(num, rdx, true, SignNeg, DigAll, ExpNone, false) -} - -/// Converts a float to a string with exactly the number of -/// provided significant digits -/// -/// # Arguments -/// -/// * num - The float value -/// * digits - The number of significant digits -#[inline] -#[unstable(feature = "std_misc", reason = "may be removed or relocated")] -pub fn to_str_exact(num: f64, dig: usize) -> String { - let (r, _) = strconv::float_to_str_common( - num, 10, true, SignNeg, DigExact(dig), ExpNone, false); - r -} - -/// Converts a float to a string with a maximum number of -/// significant digits -/// -/// # Arguments -/// -/// * num - The float value -/// * digits - The number of significant digits -#[inline] -#[unstable(feature = "std_misc", reason = "may be removed or relocated")] -pub fn to_str_digits(num: f64, dig: usize) -> String { - let (r, _) = strconv::float_to_str_common( - num, 10, true, SignNeg, DigMax(dig), ExpNone, false); - r -} - -/// Converts a float to a string using the exponential notation with exactly the number of -/// provided digits after the decimal point in the significand -/// -/// # Arguments -/// -/// * num - The float value -/// * digits - The number of digits after the decimal point -/// * upper - Use `E` instead of `e` for the exponent sign -#[inline] -#[unstable(feature = "std_misc", reason = "may be removed or relocated")] -pub fn to_str_exp_exact(num: f64, dig: usize, upper: bool) -> String { - let (r, _) = strconv::float_to_str_common( - num, 10, true, SignNeg, DigExact(dig), ExpDec, upper); - r -} - -/// Converts a float to a string using the exponential notation with the maximum number of -/// digits after the decimal point in the significand -/// -/// # Arguments -/// -/// * num - The float value -/// * digits - The number of digits after the decimal point -/// * upper - Use `E` instead of `e` for the exponent sign -#[inline] -#[unstable(feature = "std_misc", reason = "may be removed or relocated")] -pub fn to_str_exp_digits(num: f64, dig: usize, upper: bool) -> String { - let (r, _) = strconv::float_to_str_common( - num, 10, true, SignNeg, DigMax(dig), ExpDec, upper); - r -} - #[cfg(test)] mod tests { use f64::*; diff --git a/src/libstd/num/mod.rs b/src/libstd/num/mod.rs index e0b9c720dbbed..dbe06b773296b 100644 --- a/src/libstd/num/mod.rs +++ b/src/libstd/num/mod.rs @@ -15,1102 +15,13 @@ #![stable(feature = "rust1", since = "1.0.0")] #![allow(missing_docs)] -#![allow(deprecated)] #[cfg(test)] use fmt::Debug; -use ops::{Add, Sub, Mul, Div, Rem, Neg}; - -use marker::Copy; -use clone::Clone; -use cmp::{PartialOrd, PartialEq}; - -pub use core::num::{Int, SignedInt, Zero, One}; -pub use core::num::{cast, FromPrimitive, NumCast, ToPrimitive}; -pub use core::num::{from_int, from_i8, from_i16, from_i32, from_i64}; -pub use core::num::{from_uint, from_u8, from_u16, from_u32, from_u64}; -pub use core::num::{from_f32, from_f64}; -pub use core::num::{FromStrRadix, from_str_radix}; + +pub use core::num::{Zero, One}; pub use core::num::{FpCategory, ParseIntError, ParseFloatError}; pub use core::num::{wrapping, Wrapping}; -use option::Option; - -#[unstable(feature = "std_misc", reason = "likely to be removed")] -pub mod strconv; - -/// Mathematical operations on primitive floating point numbers. -#[stable(feature = "rust1", since = "1.0.0")] -#[deprecated(since = "1.0.0", - reason = "replaced by inherent methods; use rust-lang/num for generics")] -pub trait Float - : Copy + Clone - + NumCast - + PartialOrd - + PartialEq - + Neg - + Add - + Sub - + Mul - + Div - + Rem -{ - // inlined methods from `num::Float` - /// Returns the `NaN` value. - /// - /// ``` - /// # #![feature(std_misc)] - /// use std::num::Float; - /// - /// let nan: f32 = Float::nan(); - /// - /// assert!(nan.is_nan()); - /// ``` - #[unstable(feature = "std_misc", - reason = "unsure about its place in the world")] - fn nan() -> Self; - /// Returns the infinite value. - /// - /// ``` - /// # #![feature(std_misc)] - /// use std::num::Float; - /// use std::f32; - /// - /// let infinity: f32 = Float::infinity(); - /// - /// assert!(infinity.is_infinite()); - /// assert!(!infinity.is_finite()); - /// assert!(infinity > f32::MAX); - /// ``` - #[unstable(feature = "std_misc", - reason = "unsure about its place in the world")] - fn infinity() -> Self; - /// Returns the negative infinite value. - /// - /// ``` - /// # #![feature(std_misc)] - /// use std::num::Float; - /// use std::f32; - /// - /// let neg_infinity: f32 = Float::neg_infinity(); - /// - /// assert!(neg_infinity.is_infinite()); - /// assert!(!neg_infinity.is_finite()); - /// assert!(neg_infinity < f32::MIN); - /// ``` - #[unstable(feature = "std_misc", - reason = "unsure about its place in the world")] - fn neg_infinity() -> Self; - /// Returns `0.0`. - /// - /// ``` - /// # #![feature(std_misc)] - /// use std::num::Float; - /// - /// let inf: f32 = Float::infinity(); - /// let zero: f32 = Float::zero(); - /// let neg_zero: f32 = Float::neg_zero(); - /// - /// assert_eq!(zero, neg_zero); - /// assert_eq!(7.0f32/inf, zero); - /// assert_eq!(zero * 10.0, zero); - /// ``` - #[unstable(feature = "std_misc", - reason = "unsure about its place in the world")] - fn zero() -> Self; - /// Returns `-0.0`. - /// - /// ``` - /// # #![feature(std_misc)] - /// use std::num::Float; - /// - /// let inf: f32 = Float::infinity(); - /// let zero: f32 = Float::zero(); - /// let neg_zero: f32 = Float::neg_zero(); - /// - /// assert_eq!(zero, neg_zero); - /// assert_eq!(7.0f32/inf, zero); - /// assert_eq!(zero * 10.0, zero); - /// ``` - #[unstable(feature = "std_misc", - reason = "unsure about its place in the world")] - fn neg_zero() -> Self; - /// Returns `1.0`. - /// - /// ``` - /// # #![feature(std_misc)] - /// use std::num::Float; - /// - /// let one: f32 = Float::one(); - /// - /// assert_eq!(one, 1.0f32); - /// ``` - #[unstable(feature = "std_misc", - reason = "unsure about its place in the world")] - fn one() -> Self; - - // FIXME (#5527): These should be associated constants - - /// Deprecated: use `std::f32::MANTISSA_DIGITS` or `std::f64::MANTISSA_DIGITS` - /// instead. - #[unstable(feature = "std_misc")] - #[deprecated(since = "1.0.0", - reason = "use `std::f32::MANTISSA_DIGITS` or \ - `std::f64::MANTISSA_DIGITS` as appropriate")] - fn mantissa_digits(unused_self: Option) -> usize; - /// Deprecated: use `std::f32::DIGITS` or `std::f64::DIGITS` instead. - #[unstable(feature = "std_misc")] - #[deprecated(since = "1.0.0", - reason = "use `std::f32::DIGITS` or `std::f64::DIGITS` as appropriate")] - fn digits(unused_self: Option) -> usize; - /// Deprecated: use `std::f32::EPSILON` or `std::f64::EPSILON` instead. - #[unstable(feature = "std_misc")] - #[deprecated(since = "1.0.0", - reason = "use `std::f32::EPSILON` or `std::f64::EPSILON` as appropriate")] - fn epsilon() -> Self; - /// Deprecated: use `std::f32::MIN_EXP` or `std::f64::MIN_EXP` instead. - #[unstable(feature = "std_misc")] - #[deprecated(since = "1.0.0", - reason = "use `std::f32::MIN_EXP` or `std::f64::MIN_EXP` as appropriate")] - fn min_exp(unused_self: Option) -> isize; - /// Deprecated: use `std::f32::MAX_EXP` or `std::f64::MAX_EXP` instead. - #[unstable(feature = "std_misc")] - #[deprecated(since = "1.0.0", - reason = "use `std::f32::MAX_EXP` or `std::f64::MAX_EXP` as appropriate")] - fn max_exp(unused_self: Option) -> isize; - /// Deprecated: use `std::f32::MIN_10_EXP` or `std::f64::MIN_10_EXP` instead. - #[unstable(feature = "std_misc")] - #[deprecated(since = "1.0.0", - reason = "use `std::f32::MIN_10_EXP` or `std::f64::MIN_10_EXP` as appropriate")] - fn min_10_exp(unused_self: Option) -> isize; - /// Deprecated: use `std::f32::MAX_10_EXP` or `std::f64::MAX_10_EXP` instead. - #[unstable(feature = "std_misc")] - #[deprecated(since = "1.0.0", - reason = "use `std::f32::MAX_10_EXP` or `std::f64::MAX_10_EXP` as appropriate")] - fn max_10_exp(unused_self: Option) -> isize; - - /// Returns the smallest finite value that this type can represent. - /// - /// ``` - /// # #![feature(std_misc)] - /// use std::num::Float; - /// use std::f64; - /// - /// let x: f64 = Float::min_value(); - /// - /// assert_eq!(x, f64::MIN); - /// ``` - #[unstable(feature = "std_misc", - reason = "unsure about its place in the world")] - fn min_value() -> Self; - /// Returns the smallest normalized positive number that this type can represent. - #[unstable(feature = "std_misc", - reason = "unsure about its place in the world")] - fn min_pos_value(unused_self: Option) -> Self; - /// Returns the largest finite value that this type can represent. - /// - /// ``` - /// # #![feature(std_misc)] - /// use std::num::Float; - /// use std::f64; - /// - /// let x: f64 = Float::max_value(); - /// assert_eq!(x, f64::MAX); - /// ``` - #[unstable(feature = "std_misc", - reason = "unsure about its place in the world")] - fn max_value() -> Self; - /// Returns `true` if this value is `NaN` and false otherwise. - /// - /// ``` - /// # #![feature(std_misc)] - /// use std::num::Float; - /// use std::f64; - /// - /// let nan = f64::NAN; - /// let f = 7.0; - /// - /// assert!(nan.is_nan()); - /// assert!(!f.is_nan()); - /// ``` - #[unstable(feature = "std_misc", reason = "position is undecided")] - fn is_nan(self) -> bool; - /// Returns `true` if this value is positive infinity or negative infinity and - /// false otherwise. - /// - /// ``` - /// # #![feature(std_misc)] - /// use std::num::Float; - /// use std::f32; - /// - /// let f = 7.0f32; - /// let inf: f32 = Float::infinity(); - /// let neg_inf: f32 = Float::neg_infinity(); - /// let nan: f32 = f32::NAN; - /// - /// assert!(!f.is_infinite()); - /// assert!(!nan.is_infinite()); - /// - /// assert!(inf.is_infinite()); - /// assert!(neg_inf.is_infinite()); - /// ``` - #[unstable(feature = "std_misc", reason = "position is undecided")] - fn is_infinite(self) -> bool; - /// Returns `true` if this number is neither infinite nor `NaN`. - /// - /// ``` - /// # #![feature(std_misc)] - /// use std::num::Float; - /// use std::f32; - /// - /// let f = 7.0f32; - /// let inf: f32 = Float::infinity(); - /// let neg_inf: f32 = Float::neg_infinity(); - /// let nan: f32 = f32::NAN; - /// - /// assert!(f.is_finite()); - /// - /// assert!(!nan.is_finite()); - /// assert!(!inf.is_finite()); - /// assert!(!neg_inf.is_finite()); - /// ``` - #[unstable(feature = "std_misc", reason = "position is undecided")] - fn is_finite(self) -> bool; - - /// Returns `true` if the number is neither zero, infinite, - /// [subnormal][subnormal], or `NaN`. - /// - /// ``` - /// use std::num::Float; - /// use std::f32; - /// - /// let min = f32::MIN_POSITIVE; // 1.17549435e-38f32 - /// let max = f32::MAX; - /// let lower_than_min = 1.0e-40_f32; - /// let zero = 0.0f32; - /// - /// assert!(min.is_normal()); - /// assert!(max.is_normal()); - /// - /// assert!(!zero.is_normal()); - /// assert!(!f32::NAN.is_normal()); - /// assert!(!f32::INFINITY.is_normal()); - /// // Values between `0` and `min` are Subnormal. - /// assert!(!lower_than_min.is_normal()); - /// ``` - /// [subnormal]: http://en.wikipedia.org/wiki/Denormal_number - #[unstable(feature = "std_misc", reason = "position is undecided")] - fn is_normal(self) -> bool; - - /// Returns the floating point category of the number. If only one property - /// is going to be tested, it is generally faster to use the specific - /// predicate instead. - /// - /// ``` - /// use std::num::{Float, FpCategory}; - /// use std::f32; - /// - /// let num = 12.4f32; - /// let inf = f32::INFINITY; - /// - /// assert_eq!(num.classify(), FpCategory::Normal); - /// assert_eq!(inf.classify(), FpCategory::Infinite); - /// ``` - #[stable(feature = "rust1", since = "1.0.0")] - fn classify(self) -> FpCategory; - - /// Returns the mantissa, base 2 exponent, and sign as integers, respectively. - /// The original number can be recovered by `sign * mantissa * 2 ^ exponent`. - /// The floating point encoding is documented in the [Reference][floating-point]. - /// - /// ``` - /// # #![feature(std_misc)] - /// use std::num::Float; - /// - /// let num = 2.0f32; - /// - /// // (8388608, -22, 1) - /// let (mantissa, exponent, sign) = num.integer_decode(); - /// let sign_f = sign as f32; - /// let mantissa_f = mantissa as f32; - /// let exponent_f = num.powf(exponent as f32); - /// - /// // 1 * 8388608 * 2^(-22) == 2 - /// let abs_difference = (sign_f * mantissa_f * exponent_f - num).abs(); - /// - /// assert!(abs_difference < 1e-10); - /// ``` - /// [floating-point]: ../../../../../reference.html#machine-types - #[unstable(feature = "std_misc", reason = "signature is undecided")] - fn integer_decode(self) -> (u64, i16, i8); - - /// Returns the largest integer less than or equal to a number. - /// - /// ``` - /// use std::num::Float; - /// - /// let f = 3.99; - /// let g = 3.0; - /// - /// assert_eq!(f.floor(), 3.0); - /// assert_eq!(g.floor(), 3.0); - /// ``` - #[stable(feature = "rust1", since = "1.0.0")] - fn floor(self) -> Self; - /// Returns the smallest integer greater than or equal to a number. - /// - /// ``` - /// use std::num::Float; - /// - /// let f = 3.01; - /// let g = 4.0; - /// - /// assert_eq!(f.ceil(), 4.0); - /// assert_eq!(g.ceil(), 4.0); - /// ``` - #[stable(feature = "rust1", since = "1.0.0")] - fn ceil(self) -> Self; - /// Returns the nearest integer to a number. Round half-way cases away from - /// `0.0`. - /// - /// ``` - /// use std::num::Float; - /// - /// let f = 3.3; - /// let g = -3.3; - /// - /// assert_eq!(f.round(), 3.0); - /// assert_eq!(g.round(), -3.0); - /// ``` - #[stable(feature = "rust1", since = "1.0.0")] - fn round(self) -> Self; - /// Returns the integer part of a number. - /// - /// ``` - /// use std::num::Float; - /// - /// let f = 3.3; - /// let g = -3.7; - /// - /// assert_eq!(f.trunc(), 3.0); - /// assert_eq!(g.trunc(), -3.0); - /// ``` - #[stable(feature = "rust1", since = "1.0.0")] - fn trunc(self) -> Self; - /// Returns the fractional part of a number. - /// - /// ``` - /// use std::num::Float; - /// - /// let x = 3.5; - /// let y = -3.5; - /// let abs_difference_x = (x.fract() - 0.5).abs(); - /// let abs_difference_y = (y.fract() - (-0.5)).abs(); - /// - /// assert!(abs_difference_x < 1e-10); - /// assert!(abs_difference_y < 1e-10); - /// ``` - #[stable(feature = "rust1", since = "1.0.0")] - fn fract(self) -> Self; - /// Computes the absolute value of `self`. Returns `Float::nan()` if the - /// number is `Float::nan()`. - /// - /// ``` - /// use std::num::Float; - /// use std::f64; - /// - /// let x = 3.5; - /// let y = -3.5; - /// - /// let abs_difference_x = (x.abs() - x).abs(); - /// let abs_difference_y = (y.abs() - (-y)).abs(); - /// - /// assert!(abs_difference_x < 1e-10); - /// assert!(abs_difference_y < 1e-10); - /// - /// assert!(f64::NAN.abs().is_nan()); - /// ``` - #[stable(feature = "rust1", since = "1.0.0")] - fn abs(self) -> Self; - /// Returns a number that represents the sign of `self`. - /// - /// - `1.0` if the number is positive, `+0.0` or `Float::infinity()` - /// - `-1.0` if the number is negative, `-0.0` or `Float::neg_infinity()` - /// - `Float::nan()` if the number is `Float::nan()` - /// - /// ``` - /// use std::num::Float; - /// use std::f64; - /// - /// let f = 3.5; - /// - /// assert_eq!(f.signum(), 1.0); - /// assert_eq!(f64::NEG_INFINITY.signum(), -1.0); - /// - /// assert!(f64::NAN.signum().is_nan()); - /// ``` - #[stable(feature = "rust1", since = "1.0.0")] - fn signum(self) -> Self; - /// Returns `true` if `self` is positive, including `+0.0` and - /// `Float::infinity()`. - /// - /// ``` - /// use std::num::Float; - /// use std::f64; - /// - /// let nan: f64 = f64::NAN; - /// - /// let f = 7.0; - /// let g = -7.0; - /// - /// assert!(f.is_positive()); - /// assert!(!g.is_positive()); - /// // Requires both tests to determine if is `NaN` - /// assert!(!nan.is_positive() && !nan.is_negative()); - /// ``` - #[stable(feature = "rust1", since = "1.0.0")] - fn is_positive(self) -> bool; - /// Returns `true` if `self` is negative, including `-0.0` and - /// `Float::neg_infinity()`. - /// - /// ``` - /// use std::num::Float; - /// use std::f64; - /// - /// let nan = f64::NAN; - /// - /// let f = 7.0; - /// let g = -7.0; - /// - /// assert!(!f.is_negative()); - /// assert!(g.is_negative()); - /// // Requires both tests to determine if is `NaN`. - /// assert!(!nan.is_positive() && !nan.is_negative()); - /// ``` - #[stable(feature = "rust1", since = "1.0.0")] - fn is_negative(self) -> bool; - - /// Fused multiply-add. Computes `(self * a) + b` with only one rounding - /// error. This produces a more accurate result with better performance than - /// a separate multiplication operation followed by an add. - /// - /// ``` - /// # #![feature(std_misc)] - /// use std::num::Float; - /// - /// let m = 10.0; - /// let x = 4.0; - /// let b = 60.0; - /// - /// // 100.0 - /// let abs_difference = (m.mul_add(x, b) - (m*x + b)).abs(); - /// - /// assert!(abs_difference < 1e-10); - /// ``` - #[unstable(feature = "std_misc", - reason = "unsure about its place in the world")] - fn mul_add(self, a: Self, b: Self) -> Self; - /// Takes the reciprocal (inverse) of a number, `1/x`. - /// - /// ``` - /// # #![feature(std_misc)] - /// use std::num::Float; - /// - /// let x = 2.0; - /// let abs_difference = (x.recip() - (1.0/x)).abs(); - /// - /// assert!(abs_difference < 1e-10); - /// ``` - #[unstable(feature = "std_misc", - reason = "unsure about its place in the world")] - fn recip(self) -> Self; - - /// Raises a number to an integer power. - /// - /// Using this function is generally faster than using `powf` - /// - /// ``` - /// use std::num::Float; - /// - /// let x = 2.0; - /// let abs_difference = (x.powi(2) - x*x).abs(); - /// - /// assert!(abs_difference < 1e-10); - /// ``` - #[stable(feature = "rust1", since = "1.0.0")] - fn powi(self, n: i32) -> Self; - /// Raises a number to a floating point power. - /// - /// ``` - /// use std::num::Float; - /// - /// let x = 2.0; - /// let abs_difference = (x.powf(2.0) - x*x).abs(); - /// - /// assert!(abs_difference < 1e-10); - /// ``` - #[stable(feature = "rust1", since = "1.0.0")] - fn powf(self, n: Self) -> Self; - /// Takes the square root of a number. - /// - /// Returns NaN if `self` is a negative number. - /// - /// ``` - /// # #![feature(std_misc)] - /// use std::num::Float; - /// - /// let positive = 4.0; - /// let negative = -4.0; - /// - /// let abs_difference = (positive.sqrt() - 2.0).abs(); - /// - /// assert!(abs_difference < 1e-10); - /// assert!(negative.sqrt().is_nan()); - /// ``` - #[stable(feature = "rust1", since = "1.0.0")] - fn sqrt(self) -> Self; - - /// Takes the reciprocal (inverse) square root of a number, `1/sqrt(x)`. - /// - /// ``` - /// # #![feature(std_misc)] - /// use std::num::Float; - /// - /// let f = 4.0; - /// - /// let abs_difference = (f.rsqrt() - 0.5).abs(); - /// - /// assert!(abs_difference < 1e-10); - /// ``` - #[unstable(feature = "std_misc", - reason = "unsure about its place in the world")] - fn rsqrt(self) -> Self; - - /// Returns `e^(self)`, (the exponential function). - /// - /// ``` - /// use std::num::Float; - /// - /// let one = 1.0; - /// // e^1 - /// let e = one.exp(); - /// - /// // ln(e) - 1 == 0 - /// let abs_difference = (e.ln() - 1.0).abs(); - /// - /// assert!(abs_difference < 1e-10); - /// ``` - #[stable(feature = "rust1", since = "1.0.0")] - fn exp(self) -> Self; - /// Returns `2^(self)`. - /// - /// ``` - /// use std::num::Float; - /// - /// let f = 2.0; - /// - /// // 2^2 - 4 == 0 - /// let abs_difference = (f.exp2() - 4.0).abs(); - /// - /// assert!(abs_difference < 1e-10); - /// ``` - #[stable(feature = "rust1", since = "1.0.0")] - fn exp2(self) -> Self; - /// Returns the natural logarithm of the number. - /// - /// ``` - /// use std::num::Float; - /// - /// let one = 1.0; - /// // e^1 - /// let e = one.exp(); - /// - /// // ln(e) - 1 == 0 - /// let abs_difference = (e.ln() - 1.0).abs(); - /// - /// assert!(abs_difference < 1e-10); - /// ``` - #[stable(feature = "rust1", since = "1.0.0")] - fn ln(self) -> Self; - /// Returns the logarithm of the number with respect to an arbitrary base. - /// - /// ``` - /// use std::num::Float; - /// - /// let ten = 10.0; - /// let two = 2.0; - /// - /// // log10(10) - 1 == 0 - /// let abs_difference_10 = (ten.log(10.0) - 1.0).abs(); - /// - /// // log2(2) - 1 == 0 - /// let abs_difference_2 = (two.log(2.0) - 1.0).abs(); - /// - /// assert!(abs_difference_10 < 1e-10); - /// assert!(abs_difference_2 < 1e-10); - /// ``` - #[stable(feature = "rust1", since = "1.0.0")] - fn log(self, base: Self) -> Self; - /// Returns the base 2 logarithm of the number. - /// - /// ``` - /// use std::num::Float; - /// - /// let two = 2.0; - /// - /// // log2(2) - 1 == 0 - /// let abs_difference = (two.log2() - 1.0).abs(); - /// - /// assert!(abs_difference < 1e-10); - /// ``` - #[stable(feature = "rust1", since = "1.0.0")] - fn log2(self) -> Self; - /// Returns the base 10 logarithm of the number. - /// - /// ``` - /// use std::num::Float; - /// - /// let ten = 10.0; - /// - /// // log10(10) - 1 == 0 - /// let abs_difference = (ten.log10() - 1.0).abs(); - /// - /// assert!(abs_difference < 1e-10); - /// ``` - #[stable(feature = "rust1", since = "1.0.0")] - fn log10(self) -> Self; - - /// Converts radians to degrees. - /// - /// ``` - /// use std::num::Float; - /// use std::f64::consts; - /// - /// let angle = consts::PI; - /// - /// let abs_difference = (angle.to_degrees() - 180.0).abs(); - /// - /// assert!(abs_difference < 1e-10); - /// ``` - #[unstable(feature = "std_misc", reason = "desirability is unclear")] - fn to_degrees(self) -> Self; - /// Converts degrees to radians. - /// - /// ``` - /// # #![feature(std_misc)] - /// use std::num::Float; - /// use std::f64::consts; - /// - /// let angle = 180.0; - /// - /// let abs_difference = (angle.to_radians() - consts::PI).abs(); - /// - /// assert!(abs_difference < 1e-10); - /// ``` - #[unstable(feature = "std_misc", reason = "desirability is unclear")] - fn to_radians(self) -> Self; - /// Constructs a floating point number of `x*2^exp`. - /// - /// ``` - /// # #![feature(std_misc)] - /// use std::num::Float; - /// - /// // 3*2^2 - 12 == 0 - /// let abs_difference = (Float::ldexp(3.0, 2) - 12.0).abs(); - /// - /// assert!(abs_difference < 1e-10); - /// ``` - #[unstable(feature = "std_misc", - reason = "pending integer conventions")] - fn ldexp(self, exp: isize) -> Self; - /// Breaks the number into a normalized fraction and a base-2 exponent, - /// satisfying: - /// - /// * `self = x * 2^exp` - /// * `0.5 <= abs(x) < 1.0` - /// - /// ``` - /// # #![feature(std_misc)] - /// use std::num::Float; - /// - /// let x = 4.0; - /// - /// // (1/2)*2^3 -> 1 * 8/2 -> 4.0 - /// let f = x.frexp(); - /// let abs_difference_0 = (f.0 - 0.5).abs(); - /// let abs_difference_1 = (f.1 as f64 - 3.0).abs(); - /// - /// assert!(abs_difference_0 < 1e-10); - /// assert!(abs_difference_1 < 1e-10); - /// ``` - #[unstable(feature = "std_misc", - reason = "pending integer conventions")] - fn frexp(self) -> (Self, isize); - /// Returns the next representable floating-point value in the direction of - /// `other`. - /// - /// ``` - /// # #![feature(std_misc)] - /// use std::num::Float; - /// - /// let x = 1.0f32; - /// - /// let abs_diff = (x.next_after(2.0) - 1.00000011920928955078125_f32).abs(); - /// - /// assert!(abs_diff < 1e-10); - /// ``` - #[unstable(feature = "std_misc", - reason = "unsure about its place in the world")] - fn next_after(self, other: Self) -> Self; - - /// Returns the maximum of the two numbers. - /// - /// ``` - /// use std::num::Float; - /// - /// let x = 1.0; - /// let y = 2.0; - /// - /// assert_eq!(x.max(y), y); - /// ``` - #[stable(feature = "rust1", since = "1.0.0")] - fn max(self, other: Self) -> Self; - /// Returns the minimum of the two numbers. - /// - /// ``` - /// use std::num::Float; - /// - /// let x = 1.0; - /// let y = 2.0; - /// - /// assert_eq!(x.min(y), x); - /// ``` - #[stable(feature = "rust1", since = "1.0.0")] - fn min(self, other: Self) -> Self; - - /// The positive difference of two numbers. - /// - /// * If `self <= other`: `0:0` - /// * Else: `self - other` - /// - /// ``` - /// # #![feature(std_misc)] - /// use std::num::Float; - /// - /// let x = 3.0; - /// let y = -3.0; - /// - /// let abs_difference_x = (x.abs_sub(1.0) - 2.0).abs(); - /// let abs_difference_y = (y.abs_sub(1.0) - 0.0).abs(); - /// - /// assert!(abs_difference_x < 1e-10); - /// assert!(abs_difference_y < 1e-10); - /// ``` - #[unstable(feature = "std_misc", reason = "may be renamed")] - fn abs_sub(self, other: Self) -> Self; - /// Takes the cubic root of a number. - /// - /// ``` - /// # #![feature(std_misc)] - /// use std::num::Float; - /// - /// let x = 8.0; - /// - /// // x^(1/3) - 2 == 0 - /// let abs_difference = (x.cbrt() - 2.0).abs(); - /// - /// assert!(abs_difference < 1e-10); - /// ``` - #[unstable(feature = "std_misc", reason = "may be renamed")] - fn cbrt(self) -> Self; - /// Calculates the length of the hypotenuse of a right-angle triangle given - /// legs of length `x` and `y`. - /// - /// ``` - /// # #![feature(std_misc)] - /// use std::num::Float; - /// - /// let x = 2.0; - /// let y = 3.0; - /// - /// // sqrt(x^2 + y^2) - /// let abs_difference = (x.hypot(y) - (x.powi(2) + y.powi(2)).sqrt()).abs(); - /// - /// assert!(abs_difference < 1e-10); - /// ``` - #[unstable(feature = "std_misc", - reason = "unsure about its place in the world")] - fn hypot(self, other: Self) -> Self; - - /// Computes the sine of a number (in radians). - /// - /// ``` - /// use std::num::Float; - /// use std::f64; - /// - /// let x = f64::consts::PI/2.0; - /// - /// let abs_difference = (x.sin() - 1.0).abs(); - /// - /// assert!(abs_difference < 1e-10); - /// ``` - #[stable(feature = "rust1", since = "1.0.0")] - fn sin(self) -> Self; - /// Computes the cosine of a number (in radians). - /// - /// ``` - /// use std::num::Float; - /// use std::f64; - /// - /// let x = 2.0*f64::consts::PI; - /// - /// let abs_difference = (x.cos() - 1.0).abs(); - /// - /// assert!(abs_difference < 1e-10); - /// ``` - #[stable(feature = "rust1", since = "1.0.0")] - fn cos(self) -> Self; - /// Computes the tangent of a number (in radians). - /// - /// ``` - /// use std::num::Float; - /// use std::f64; - /// - /// let x = f64::consts::PI/4.0; - /// let abs_difference = (x.tan() - 1.0).abs(); - /// - /// assert!(abs_difference < 1e-14); - /// ``` - #[stable(feature = "rust1", since = "1.0.0")] - fn tan(self) -> Self; - /// Computes the arcsine of a number. Return value is in radians in - /// the range [-pi/2, pi/2] or NaN if the number is outside the range - /// [-1, 1]. - /// - /// ``` - /// use std::num::Float; - /// use std::f64; - /// - /// let f = f64::consts::PI / 2.0; - /// - /// // asin(sin(pi/2)) - /// let abs_difference = (f.sin().asin() - f64::consts::PI / 2.0).abs(); - /// - /// assert!(abs_difference < 1e-10); - /// ``` - #[stable(feature = "rust1", since = "1.0.0")] - fn asin(self) -> Self; - /// Computes the arccosine of a number. Return value is in radians in - /// the range [0, pi] or NaN if the number is outside the range - /// [-1, 1]. - /// - /// ``` - /// use std::num::Float; - /// use std::f64; - /// - /// let f = f64::consts::PI / 4.0; - /// - /// // acos(cos(pi/4)) - /// let abs_difference = (f.cos().acos() - f64::consts::PI / 4.0).abs(); - /// - /// assert!(abs_difference < 1e-10); - /// ``` - #[stable(feature = "rust1", since = "1.0.0")] - fn acos(self) -> Self; - /// Computes the arctangent of a number. Return value is in radians in the - /// range [-pi/2, pi/2]; - /// - /// ``` - /// use std::num::Float; - /// - /// let f = 1.0; - /// - /// // atan(tan(1)) - /// let abs_difference = (f.tan().atan() - 1.0).abs(); - /// - /// assert!(abs_difference < 1e-10); - /// ``` - #[stable(feature = "rust1", since = "1.0.0")] - fn atan(self) -> Self; - /// Computes the four quadrant arctangent of `self` (`y`) and `other` (`x`). - /// - /// * `x = 0`, `y = 0`: `0` - /// * `x >= 0`: `arctan(y/x)` -> `[-pi/2, pi/2]` - /// * `y >= 0`: `arctan(y/x) + pi` -> `(pi/2, pi]` - /// * `y < 0`: `arctan(y/x) - pi` -> `(-pi, -pi/2)` - /// - /// ``` - /// use std::num::Float; - /// use std::f64; - /// - /// let pi = f64::consts::PI; - /// // All angles from horizontal right (+x) - /// // 45 deg counter-clockwise - /// let x1 = 3.0; - /// let y1 = -3.0; - /// - /// // 135 deg clockwise - /// let x2 = -3.0; - /// let y2 = 3.0; - /// - /// let abs_difference_1 = (y1.atan2(x1) - (-pi/4.0)).abs(); - /// let abs_difference_2 = (y2.atan2(x2) - 3.0*pi/4.0).abs(); - /// - /// assert!(abs_difference_1 < 1e-10); - /// assert!(abs_difference_2 < 1e-10); - /// ``` - #[stable(feature = "rust1", since = "1.0.0")] - fn atan2(self, other: Self) -> Self; - /// Simultaneously computes the sine and cosine of the number, `x`. Returns - /// `(sin(x), cos(x))`. - /// - /// ``` - /// use std::num::Float; - /// use std::f64; - /// - /// let x = f64::consts::PI/4.0; - /// let f = x.sin_cos(); - /// - /// let abs_difference_0 = (f.0 - x.sin()).abs(); - /// let abs_difference_1 = (f.1 - x.cos()).abs(); - /// - /// assert!(abs_difference_0 < 1e-10); - /// assert!(abs_difference_0 < 1e-10); - /// ``` - #[stable(feature = "rust1", since = "1.0.0")] - fn sin_cos(self) -> (Self, Self); - - /// Returns `e^(self) - 1` in a way that is accurate even if the - /// number is close to zero. - /// - /// ``` - /// # #![feature(std_misc)] - /// use std::num::Float; - /// - /// let x = 7.0; - /// - /// // e^(ln(7)) - 1 - /// let abs_difference = (x.ln().exp_m1() - 6.0).abs(); - /// - /// assert!(abs_difference < 1e-10); - /// ``` - #[unstable(feature = "std_misc", reason = "may be renamed")] - fn exp_m1(self) -> Self; - /// Returns `ln(1+n)` (natural logarithm) more accurately than if - /// the operations were performed separately. - /// - /// ``` - /// use std::num::Float; - /// use std::f64; - /// - /// let x = f64::consts::E - 1.0; - /// - /// // ln(1 + (e - 1)) == ln(e) == 1 - /// let abs_difference = (x.ln_1p() - 1.0).abs(); - /// - /// assert!(abs_difference < 1e-10); - /// ``` - #[unstable(feature = "std_misc", reason = "may be renamed")] - fn ln_1p(self) -> Self; - - /// Hyperbolic sine function. - /// - /// ``` - /// use std::num::Float; - /// use std::f64; - /// - /// let e = f64::consts::E; - /// let x = 1.0; - /// - /// let f = x.sinh(); - /// // Solving sinh() at 1 gives `(e^2-1)/(2e)` - /// let g = (e*e - 1.0)/(2.0*e); - /// let abs_difference = (f - g).abs(); - /// - /// assert!(abs_difference < 1e-10); - /// ``` - #[stable(feature = "rust1", since = "1.0.0")] - fn sinh(self) -> Self; - /// Hyperbolic cosine function. - /// - /// ``` - /// use std::num::Float; - /// use std::f64; - /// - /// let e = f64::consts::E; - /// let x = 1.0; - /// let f = x.cosh(); - /// // Solving cosh() at 1 gives this result - /// let g = (e*e + 1.0)/(2.0*e); - /// let abs_difference = (f - g).abs(); - /// - /// // Same result - /// assert!(abs_difference < 1.0e-10); - /// ``` - #[stable(feature = "rust1", since = "1.0.0")] - fn cosh(self) -> Self; - /// Hyperbolic tangent function. - /// - /// ``` - /// use std::num::Float; - /// use std::f64; - /// - /// let e = f64::consts::E; - /// let x = 1.0; - /// - /// let f = x.tanh(); - /// // Solving tanh() at 1 gives `(1 - e^(-2))/(1 + e^(-2))` - /// let g = (1.0 - e.powi(-2))/(1.0 + e.powi(-2)); - /// let abs_difference = (f - g).abs(); - /// - /// assert!(abs_difference < 1.0e-10); - /// ``` - #[stable(feature = "rust1", since = "1.0.0")] - fn tanh(self) -> Self; - /// Inverse hyperbolic sine function. - /// - /// ``` - /// use std::num::Float; - /// - /// let x = 1.0; - /// let f = x.sinh().asinh(); - /// - /// let abs_difference = (f - x).abs(); - /// - /// assert!(abs_difference < 1.0e-10); - /// ``` - #[stable(feature = "rust1", since = "1.0.0")] - fn asinh(self) -> Self; - /// Inverse hyperbolic cosine function. - /// - /// ``` - /// use std::num::Float; - /// - /// let x = 1.0; - /// let f = x.cosh().acosh(); - /// - /// let abs_difference = (f - x).abs(); - /// - /// assert!(abs_difference < 1.0e-10); - /// ``` - #[stable(feature = "rust1", since = "1.0.0")] - fn acosh(self) -> Self; - /// Inverse hyperbolic tangent function. - /// - /// ``` - /// use std::num::Float; - /// use std::f64; - /// - /// let e = f64::consts::E; - /// let f = e.tanh().atanh(); - /// - /// let abs_difference = (f - e).abs(); - /// - /// assert!(abs_difference < 1.0e-10); - /// ``` - #[stable(feature = "rust1", since = "1.0.0")] - fn atanh(self) -> Self; -} - /// Helper function for testing numeric operations #[cfg(test)] pub fn test_num(ten: T, two: T) where diff --git a/src/libstd/num/strconv.rs b/src/libstd/num/strconv.rs deleted file mode 100644 index 8ab66f2328fb6..0000000000000 --- a/src/libstd/num/strconv.rs +++ /dev/null @@ -1,558 +0,0 @@ -// Copyright 2013-2014 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. -// -// ignore-lexer-test FIXME #15679 - -#![allow(missing_docs)] -#![allow(deprecated)] - -use self::ExponentFormat::*; -use self::SignificantDigits::*; -use self::SignFormat::*; - -use char; -use num::{self, Int, Float, ToPrimitive}; -use num::FpCategory as Fp; -use ops::FnMut; -use string::String; -use vec::Vec; - -/// A flag that specifies whether to use exponential (scientific) notation. -#[derive(Copy, Clone)] -pub enum ExponentFormat { - /// Do not use exponential notation. - ExpNone, - /// Use exponential notation with the exponent having a base of 10 and the - /// exponent sign being `e` or `E`. For example, 1000 would be printed - /// 1e3. - ExpDec, - /// Use exponential notation with the exponent having a base of 2 and the - /// exponent sign being `p` or `P`. For example, 8 would be printed 1p3. - ExpBin, -} - -/// The number of digits used for emitting the fractional part of a number, if -/// any. -#[derive(Copy, Clone)] -pub enum SignificantDigits { - /// All calculable digits will be printed. - /// - /// Note that bignums or fractions may cause a surprisingly large number - /// of digits to be printed. - DigAll, - - /// At most the given number of digits will be printed, truncating any - /// trailing zeroes. - DigMax(usize), - - /// Precisely the given number of digits will be printed. - DigExact(usize) -} - -/// How to emit the sign of a number. -#[derive(Copy, Clone)] -pub enum SignFormat { - /// No sign will be printed. The exponent sign will also be emitted. - SignNone, - /// `-` will be printed for negative values, but no sign will be emitted - /// for positive numbers. - SignNeg, - /// `+` will be printed for positive values, and `-` will be printed for - /// negative values. - SignAll, -} - -/// Converts an integral number to its string representation as a byte vector. -/// This is meant to be a common base implementation for all integral string -/// conversion functions like `to_string()` or `to_str_radix()`. -/// -/// # Arguments -/// -/// - `num` - The number to convert. Accepts any number that -/// implements the numeric traits. -/// - `radix` - Base to use. Accepts only the values 2-36. -/// - `sign` - How to emit the sign. Options are: -/// - `SignNone`: No sign at all. Basically emits `abs(num)`. -/// - `SignNeg`: Only `-` on negative values. -/// - `SignAll`: Both `+` on positive, and `-` on negative numbers. -/// - `f` - a callback which will be invoked for each ascii character -/// which composes the string representation of this integer -/// -/// # Panics -/// -/// - Panics if `radix` < 2 or `radix` > 36. -fn int_to_str_bytes_common(num: T, radix: usize, sign: SignFormat, mut f: F) where - T: Int, - F: FnMut(u8), -{ - assert!(2 <= radix && radix <= 36); - - let _0: T = Int::zero(); - - let neg = num < _0; - let radix_gen: T = num::cast(radix).unwrap(); - - let mut deccum = num; - // This is just for integral types, the largest of which is a u64. The - // smallest base that we can have is 2, so the most number of digits we're - // ever going to have is 64 - let mut buf = [0; 64]; - let mut cur = 0; - - // Loop at least once to make sure at least a `0` gets emitted. - loop { - // Calculate the absolute value of each digit instead of only - // doing it once for the whole number because a - // representable negative number doesn't necessary have an - // representable additive inverse of the same type - // (See twos complement). But we assume that for the - // numbers [-35 .. 0] we always have [0 .. 35]. - let current_digit_signed = deccum % radix_gen; - let current_digit = if current_digit_signed < _0 { - _0 - current_digit_signed - } else { - current_digit_signed - }; - buf[cur] = match current_digit.to_u8().unwrap() { - i @ 0...9 => b'0' + i, - i => b'a' + (i - 10), - }; - cur += 1; - - deccum = deccum / radix_gen; - // No more digits to calculate for the non-fractional part -> break - if deccum == _0 { break; } - } - - // Decide what sign to put in front - match sign { - SignNeg | SignAll if neg => { f(b'-'); } - SignAll => { f(b'+'); } - _ => () - } - - // We built the number in reverse order, so un-reverse it here - while cur > 0 { - cur -= 1; - f(buf[cur]); - } -} - -/// Converts a number to its string representation as a byte vector. -/// This is meant to be a common base implementation for all numeric string -/// conversion functions like `to_string()` or `to_str_radix()`. -/// -/// # Arguments -/// -/// - `num` - The number to convert. Accepts any number that -/// implements the numeric traits. -/// - `radix` - Base to use. Accepts only the values 2-36. If the exponential notation -/// is used, then this base is only used for the significand. The exponent -/// itself always printed using a base of 10. -/// - `negative_zero` - Whether to treat the special value `-0` as -/// `-0` or as `+0`. -/// - `sign` - How to emit the sign. See `SignFormat`. -/// - `digits` - The amount of digits to use for emitting the fractional -/// part, if any. See `SignificantDigits`. -/// - `exp_format` - Whether or not to use the exponential (scientific) notation. -/// See `ExponentFormat`. -/// - `exp_capital` - Whether or not to use a capital letter for the exponent sign, if -/// exponential notation is desired. -/// -/// # Return value -/// -/// A tuple containing the byte vector, and a boolean flag indicating -/// whether it represents a special value like `inf`, `-inf`, `NaN` or not. -/// It returns a tuple because there can be ambiguity between a special value -/// and a number representation at higher bases. -/// -/// # Panics -/// -/// - Panics if `radix` < 2 or `radix` > 36. -/// - Panics if `radix` > 14 and `exp_format` is `ExpDec` due to conflict -/// between digit and exponent sign `'e'`. -/// - Panics if `radix` > 25 and `exp_format` is `ExpBin` due to conflict -/// between digit and exponent sign `'p'`. -pub fn float_to_str_bytes_common( - num: T, radix: u32, negative_zero: bool, - sign: SignFormat, digits: SignificantDigits, exp_format: ExponentFormat, exp_upper: bool - ) -> (Vec, bool) { - assert!(2 <= radix && radix <= 36); - match exp_format { - ExpDec if radix >= DIGIT_E_RADIX // decimal exponent 'e' - => panic!("float_to_str_bytes_common: radix {} incompatible with \ - use of 'e' as decimal exponent", radix), - ExpBin if radix >= DIGIT_P_RADIX // binary exponent 'p' - => panic!("float_to_str_bytes_common: radix {} incompatible with \ - use of 'p' as binary exponent", radix), - _ => () - } - - let _0: T = Float::zero(); - let _1: T = Float::one(); - - match num.classify() { - Fp::Nan => { return (b"NaN".to_vec(), true); } - Fp::Infinite if num > _0 => { - return match sign { - SignAll => (b"+inf".to_vec(), true), - _ => (b"inf".to_vec(), true) - }; - } - Fp::Infinite if num < _0 => { - return match sign { - SignNone => (b"inf".to_vec(), true), - _ => (b"-inf".to_vec(), true), - }; - } - _ => {} - } - - let neg = num < _0 || (negative_zero && _1 / num == Float::neg_infinity()); - let mut buf = Vec::new(); - let radix_gen: T = num::cast(radix as isize).unwrap(); - - let (num, exp) = match exp_format { - ExpNone => (num, 0), - ExpDec | ExpBin => { - if num == _0 { - (num, 0) - } else { - let (exp, exp_base) = match exp_format { - ExpDec => (num.abs().log10().floor(), num::cast::(10.0f64).unwrap()), - ExpBin => (num.abs().log2().floor(), num::cast::(2.0f64).unwrap()), - ExpNone => unreachable!() - }; - - (num / exp_base.powf(exp), num::cast::(exp).unwrap()) - } - } - }; - - // First emit the non-fractional part, looping at least once to make - // sure at least a `0` gets emitted. - let mut deccum = num.trunc(); - loop { - // Calculate the absolute value of each digit instead of only - // doing it once for the whole number because a - // representable negative number doesn't necessary have an - // representable additive inverse of the same type - // (See twos complement). But we assume that for the - // numbers [-35 .. 0] we always have [0 .. 35]. - let current_digit = (deccum % radix_gen).abs(); - - // Decrease the deccumulator one digit at a time - deccum = deccum / radix_gen; - deccum = deccum.trunc(); - - buf.push(char::from_digit(current_digit.to_isize().unwrap() as u32, radix) - .unwrap() as u8); - - // No more digits to calculate for the non-fractional part -> break - if deccum == _0 { break; } - } - - // If limited digits, calculate one digit more for rounding. - let (limit_digits, digit_count, exact) = match digits { - DigAll => (false, 0, false), - DigMax(count) => (true, count+1, false), - DigExact(count) => (true, count+1, true) - }; - - // Decide what sign to put in front - match sign { - SignNeg | SignAll if neg => { - buf.push(b'-'); - } - SignAll => { - buf.push(b'+'); - } - _ => () - } - - buf.reverse(); - - // Remember start of the fractional digits. - // Points one beyond end of buf if none get generated, - // or at the '.' otherwise. - let start_fractional_digits = buf.len(); - - // Now emit the fractional part, if any - deccum = num.fract(); - if deccum != _0 || (limit_digits && exact && digit_count > 0) { - buf.push(b'.'); - let mut dig = 0; - - // calculate new digits while - // - there is no limit and there are digits left - // - or there is a limit, it's not reached yet and - // - it's exact - // - or it's a maximum, and there are still digits left - while (!limit_digits && deccum != _0) - || (limit_digits && dig < digit_count && ( - exact - || (!exact && deccum != _0) - ) - ) { - // Shift first fractional digit into the integer part - deccum = deccum * radix_gen; - - // Calculate the absolute value of each digit. - // See note in first loop. - let current_digit = deccum.trunc().abs(); - - buf.push(char::from_digit( - current_digit.to_isize().unwrap() as u32, radix).unwrap() as u8); - - // Decrease the deccumulator one fractional digit at a time - deccum = deccum.fract(); - dig += 1; - } - - // If digits are limited, and that limit has been reached, - // cut off the one extra digit, and depending on its value - // round the remaining ones. - if limit_digits && dig == digit_count { - let ascii2value = |chr: u8| { - (chr as char).to_digit(radix).unwrap() - }; - let value2ascii = |val: u32| { - char::from_digit(val, radix).unwrap() as u8 - }; - - let extra_digit = ascii2value(buf.pop().unwrap()); - if extra_digit >= radix / 2 { // -> need to round - let mut i: isize = buf.len() as isize - 1; - loop { - // If reached left end of number, have to - // insert additional digit: - if i < 0 - || buf[i as usize] == b'-' - || buf[i as usize] == b'+' { - buf.insert((i + 1) as usize, value2ascii(1)); - break; - } - - // Skip the '.' - if buf[i as usize] == b'.' { i -= 1; continue; } - - // Either increment the digit, - // or set to 0 if max and carry the 1. - let current_digit = ascii2value(buf[i as usize]); - if current_digit < (radix - 1) { - buf[i as usize] = value2ascii(current_digit+1); - break; - } else { - buf[i as usize] = value2ascii(0); - i -= 1; - } - } - } - } - } - - // if number of digits is not exact, remove all trailing '0's up to - // and including the '.' - if !exact { - let buf_max_i = buf.len() - 1; - - // index to truncate from - let mut i = buf_max_i; - - // discover trailing zeros of fractional part - while i > start_fractional_digits && buf[i] == b'0' { - i -= 1; - } - - // Only attempt to truncate digits if buf has fractional digits - if i >= start_fractional_digits { - // If buf ends with '.', cut that too. - if buf[i] == b'.' { i -= 1 } - - // only resize buf if we actually remove digits - if i < buf_max_i { - buf = buf[.. (i + 1)].to_vec(); - } - } - } // If exact and trailing '.', just cut that - else { - let max_i = buf.len() - 1; - if buf[max_i] == b'.' { - buf = buf[.. max_i].to_vec(); - } - } - - match exp_format { - ExpNone => (), - _ => { - buf.push(match exp_format { - ExpDec if exp_upper => 'E', - ExpDec if !exp_upper => 'e', - ExpBin if exp_upper => 'P', - ExpBin if !exp_upper => 'p', - _ => unreachable!() - } as u8); - - int_to_str_bytes_common(exp, 10, sign, |c| buf.push(c)); - } - } - - (buf, false) -} - -/// Converts a number to its string representation. This is a wrapper for -/// `to_str_bytes_common()`, for details see there. -#[inline] -pub fn float_to_str_common( - num: T, radix: u32, negative_zero: bool, - sign: SignFormat, digits: SignificantDigits, exp_format: ExponentFormat, exp_capital: bool - ) -> (String, bool) { - let (bytes, special) = float_to_str_bytes_common(num, radix, - negative_zero, sign, digits, exp_format, exp_capital); - (String::from_utf8(bytes).unwrap(), special) -} - -// Some constants for from_str_bytes_common's input validation, -// they define minimum radix values for which the character is a valid digit. -const DIGIT_P_RADIX: u32 = ('p' as u32) - ('a' as u32) + 11; -const DIGIT_E_RADIX: u32 = ('e' as u32) - ('a' as u32) + 11; - -#[cfg(test)] -mod tests { - use core::num::wrapping::WrappingOps; - use string::ToString; - - #[test] - fn test_int_to_str_overflow() { - let mut i8_val: i8 = 127; - assert_eq!(i8_val.to_string(), "127"); - - i8_val = i8_val.wrapping_add(1); - assert_eq!(i8_val.to_string(), "-128"); - - let mut i16_val: i16 = 32_767; - assert_eq!(i16_val.to_string(), "32767"); - - i16_val = i16_val.wrapping_add(1); - assert_eq!(i16_val.to_string(), "-32768"); - - let mut i32_val: i32 = 2_147_483_647; - assert_eq!(i32_val.to_string(), "2147483647"); - - i32_val = i32_val.wrapping_add(1); - assert_eq!(i32_val.to_string(), "-2147483648"); - - let mut i64_val: i64 = 9_223_372_036_854_775_807; - assert_eq!(i64_val.to_string(), "9223372036854775807"); - - i64_val = i64_val.wrapping_add(1); - assert_eq!(i64_val.to_string(), "-9223372036854775808"); - } -} - -#[cfg(test)] -mod bench { - #![allow(deprecated)] // rand - extern crate test; - - mod usize { - use super::test::Bencher; - use rand::{thread_rng, Rng}; - use std::fmt; - - #[inline] - fn to_string(x: usize, base: u8) { - format!("{}", fmt::radix(x, base)); - } - - #[bench] - fn to_str_bin(b: &mut Bencher) { - let mut rng = thread_rng(); - b.iter(|| { to_string(rng.gen::(), 2); }) - } - - #[bench] - fn to_str_oct(b: &mut Bencher) { - let mut rng = thread_rng(); - b.iter(|| { to_string(rng.gen::(), 8); }) - } - - #[bench] - fn to_str_dec(b: &mut Bencher) { - let mut rng = thread_rng(); - b.iter(|| { to_string(rng.gen::(), 10); }) - } - - #[bench] - fn to_str_hex(b: &mut Bencher) { - let mut rng = thread_rng(); - b.iter(|| { to_string(rng.gen::(), 16); }) - } - - #[bench] - fn to_str_base_36(b: &mut Bencher) { - let mut rng = thread_rng(); - b.iter(|| { to_string(rng.gen::(), 36); }) - } - } - - mod isize { - use super::test::Bencher; - use rand::{thread_rng, Rng}; - use std::fmt; - - #[inline] - fn to_string(x: isize, base: u8) { - format!("{}", fmt::radix(x, base)); - } - - #[bench] - fn to_str_bin(b: &mut Bencher) { - let mut rng = thread_rng(); - b.iter(|| { to_string(rng.gen::(), 2); }) - } - - #[bench] - fn to_str_oct(b: &mut Bencher) { - let mut rng = thread_rng(); - b.iter(|| { to_string(rng.gen::(), 8); }) - } - - #[bench] - fn to_str_dec(b: &mut Bencher) { - let mut rng = thread_rng(); - b.iter(|| { to_string(rng.gen::(), 10); }) - } - - #[bench] - fn to_str_hex(b: &mut Bencher) { - let mut rng = thread_rng(); - b.iter(|| { to_string(rng.gen::(), 16); }) - } - - #[bench] - fn to_str_base_36(b: &mut Bencher) { - let mut rng = thread_rng(); - b.iter(|| { to_string(rng.gen::(), 36); }) - } - } - - mod f64 { - use super::test::Bencher; - use rand::{thread_rng, Rng}; - use f64; - - #[bench] - fn float_to_string(b: &mut Bencher) { - let mut rng = thread_rng(); - b.iter(|| { f64::to_string(rng.gen()); }) - } - } -} diff --git a/src/libstd/path.rs b/src/libstd/path.rs index 5ef94ee0b66b7..7d4d4bc4c66fd 100644 --- a/src/libstd/path.rs +++ b/src/libstd/path.rs @@ -110,7 +110,7 @@ use string::String; use vec::Vec; use fmt; -use ffi::{OsStr, OsString, AsOsStr}; +use ffi::{OsStr, OsString}; use self::platform::{is_sep_byte, is_verbatim_sep, MAIN_SEP_STR, parse_prefix}; diff --git a/src/libstd/sync/condvar.rs b/src/libstd/sync/condvar.rs index fcb0d2c0b2d38..c2964b7a4f125 100644 --- a/src/libstd/sync/condvar.rs +++ b/src/libstd/sync/condvar.rs @@ -161,14 +161,6 @@ impl Condvar { } } - /// Deprecated: use `wait_timeout_ms` instead. - #[unstable(feature = "std_misc")] - #[deprecated(since = "1.0.0", reason = "use wait_timeout_ms instead")] - pub fn wait_timeout<'a, T>(&self, guard: MutexGuard<'a, T>, dur: Duration) - -> LockResult<(MutexGuard<'a, T>, bool)> { - self.wait_timeout_ms(guard, dur.num_milliseconds() as u32) - } - /// Waits on this condition variable for a notification, timing out after a /// specified duration. /// diff --git a/src/libstd/sys/common/net.rs b/src/libstd/sys/common/net.rs deleted file mode 100644 index fc21effb45a8d..0000000000000 --- a/src/libstd/sys/common/net.rs +++ /dev/null @@ -1,971 +0,0 @@ -// Copyright 2013-2015 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -#![allow(deprecated)] - -use prelude::v1::*; -use self::SocketStatus::*; -use self::InAddr::*; - -use ffi::{CString, CStr}; -use old_io::net::addrinfo; -use old_io::net::ip::{SocketAddr, IpAddr, Ipv4Addr, Ipv6Addr}; -use old_io::{IoResult, IoError}; -use libc::{self, c_char, c_int}; -use mem; -use num::Int; -use ptr::{self, null, null_mut}; -use str; -use sys::{self, retry, c, sock_t, last_error, last_net_error, last_gai_error, close_sock, - wrlen, msglen_t, os, wouldblock, set_nonblocking, timer, ms_to_timeval, - decode_error_detailed}; -use sync::{Arc, Mutex}; -#[cfg(not(target_os = "linux"))] -use sync::MutexGuard; -use sys_common::{self, keep_going, short_write, timeout}; -use cmp; -use old_io; - -// FIXME: move uses of Arc and deadline tracking to std::io - -#[derive(Debug)] -pub enum SocketStatus { - Readable, - Writable, -} - -//////////////////////////////////////////////////////////////////////////////// -// sockaddr and misc bindings -//////////////////////////////////////////////////////////////////////////////// - -pub fn htons(u: u16) -> u16 { - u.to_be() -} -pub fn ntohs(u: u16) -> u16 { - Int::from_be(u) -} - -pub enum InAddr { - In4Addr(libc::in_addr), - In6Addr(libc::in6_addr), -} - -pub fn ip_to_inaddr(ip: IpAddr) -> InAddr { - match ip { - Ipv4Addr(a, b, c, d) => { - let ip = ((a as u32) << 24) | - ((b as u32) << 16) | - ((c as u32) << 8) | - ((d as u32) << 0); - In4Addr(libc::in_addr { - s_addr: Int::from_be(ip) - }) - } - Ipv6Addr(a, b, c, d, e, f, g, h) => { - In6Addr(libc::in6_addr { - s6_addr: [ - htons(a), - htons(b), - htons(c), - htons(d), - htons(e), - htons(f), - htons(g), - htons(h), - ] - }) - } - } -} - -pub fn addr_to_sockaddr(addr: SocketAddr, - storage: &mut libc::sockaddr_storage) - -> libc::socklen_t { - unsafe { - let len = match ip_to_inaddr(addr.ip) { - In4Addr(inaddr) => { - let storage = storage as *mut _ as *mut libc::sockaddr_in; - (*storage).sin_family = libc::AF_INET as libc::sa_family_t; - (*storage).sin_port = htons(addr.port); - (*storage).sin_addr = inaddr; - mem::size_of::() - } - In6Addr(inaddr) => { - let storage = storage as *mut _ as *mut libc::sockaddr_in6; - (*storage).sin6_family = libc::AF_INET6 as libc::sa_family_t; - (*storage).sin6_port = htons(addr.port); - (*storage).sin6_addr = inaddr; - mem::size_of::() - } - }; - return len as libc::socklen_t; - } -} - -pub fn socket(addr: SocketAddr, ty: libc::c_int) -> IoResult { - unsafe { - let fam = match addr.ip { - Ipv4Addr(..) => libc::AF_INET, - Ipv6Addr(..) => libc::AF_INET6, - }; - match libc::socket(fam, ty, 0) as i32 { - -1 => Err(last_net_error()), - fd => Ok(fd as sock_t), - } - } -} - -pub fn setsockopt(fd: sock_t, opt: libc::c_int, val: libc::c_int, - payload: T) -> IoResult<()> { - unsafe { - let payload = &payload as *const T as *const libc::c_void; - let ret = libc::setsockopt(fd, opt, val, - payload, - mem::size_of::() as libc::socklen_t); - if ret != 0 { - Err(last_net_error()) - } else { - Ok(()) - } - } -} - -pub fn getsockopt(fd: sock_t, opt: libc::c_int, - val: libc::c_int) -> IoResult { - unsafe { - let mut slot: T = mem::zeroed(); - let mut len = mem::size_of::() as libc::socklen_t; - let ret = c::getsockopt(fd, opt, val, - &mut slot as *mut _ as *mut _, - &mut len); - if ret != 0 { - Err(last_net_error()) - } else { - assert!(len as usize == mem::size_of::()); - Ok(slot) - } - } -} - -pub fn sockname(fd: sock_t, - f: unsafe extern "system" fn(sock_t, *mut libc::sockaddr, - *mut libc::socklen_t) -> libc::c_int) - -> IoResult -{ - let mut storage: libc::sockaddr_storage = unsafe { mem::zeroed() }; - let mut len = mem::size_of::() as libc::socklen_t; - unsafe { - let storage = &mut storage as *mut libc::sockaddr_storage; - let ret = f(fd, - storage as *mut libc::sockaddr, - &mut len as *mut libc::socklen_t); - if ret != 0 { - return Err(last_net_error()) - } - } - return sockaddr_to_addr(&storage, len as usize); -} - -pub fn sockaddr_to_addr(storage: &libc::sockaddr_storage, - len: usize) -> IoResult { - match storage.ss_family as libc::c_int { - libc::AF_INET => { - assert!(len as usize >= mem::size_of::()); - let storage: &libc::sockaddr_in = unsafe { - mem::transmute(storage) - }; - let ip = (storage.sin_addr.s_addr as u32).to_be(); - let a = (ip >> 24) as u8; - let b = (ip >> 16) as u8; - let c = (ip >> 8) as u8; - let d = (ip >> 0) as u8; - Ok(SocketAddr { - ip: Ipv4Addr(a, b, c, d), - port: ntohs(storage.sin_port), - }) - } - libc::AF_INET6 => { - assert!(len as usize >= mem::size_of::()); - let storage: &libc::sockaddr_in6 = unsafe { - mem::transmute(storage) - }; - let a = ntohs(storage.sin6_addr.s6_addr[0]); - let b = ntohs(storage.sin6_addr.s6_addr[1]); - let c = ntohs(storage.sin6_addr.s6_addr[2]); - let d = ntohs(storage.sin6_addr.s6_addr[3]); - let e = ntohs(storage.sin6_addr.s6_addr[4]); - let f = ntohs(storage.sin6_addr.s6_addr[5]); - let g = ntohs(storage.sin6_addr.s6_addr[6]); - let h = ntohs(storage.sin6_addr.s6_addr[7]); - Ok(SocketAddr { - ip: Ipv6Addr(a, b, c, d, e, f, g, h), - port: ntohs(storage.sin6_port), - }) - } - _ => { - Err(IoError { - kind: old_io::InvalidInput, - desc: "invalid argument", - detail: None, - }) - } - } -} - -//////////////////////////////////////////////////////////////////////////////// -// get_host_addresses -//////////////////////////////////////////////////////////////////////////////// - -extern "system" { - fn getaddrinfo(node: *const c_char, service: *const c_char, - hints: *const libc::addrinfo, - res: *mut *mut libc::addrinfo) -> c_int; - fn freeaddrinfo(res: *mut libc::addrinfo); -} - -pub fn get_host_addresses(host: Option<&str>, servname: Option<&str>, - hint: Option) - -> Result, IoError> -{ - sys::init_net(); - - assert!(host.is_some() || servname.is_some()); - - let c_host = match host { - Some(x) => Some(try!(CString::new(x))), - None => None, - }; - let c_host = c_host.as_ref().map(|x| x.as_ptr()).unwrap_or(null()); - let c_serv = match servname { - Some(x) => Some(try!(CString::new(x))), - None => None, - }; - let c_serv = c_serv.as_ref().map(|x| x.as_ptr()).unwrap_or(null()); - - let hint = hint.map(|hint| { - libc::addrinfo { - ai_flags: hint.flags as c_int, - ai_family: hint.family as c_int, - ai_socktype: 0, - ai_protocol: 0, - ai_addrlen: 0, - ai_canonname: null_mut(), - ai_addr: null_mut(), - ai_next: null_mut() - } - }); - - let hint_ptr = hint.as_ref().map_or(null(), |x| { - x as *const libc::addrinfo - }); - let mut res = null_mut(); - - // Make the call - let s = unsafe { - getaddrinfo(c_host, c_serv, hint_ptr, &mut res) - }; - - // Error? - if s != 0 { - return Err(last_gai_error(s)); - } - - // Collect all the results we found - let mut addrs = Vec::new(); - let mut rp = res; - while !rp.is_null() { - unsafe { - let addr = try!(sockaddr_to_addr(mem::transmute((*rp).ai_addr), - (*rp).ai_addrlen as usize)); - addrs.push(addrinfo::Info { - address: addr, - family: (*rp).ai_family as usize, - socktype: None, - protocol: None, - flags: (*rp).ai_flags as usize - }); - - rp = (*rp).ai_next as *mut libc::addrinfo; - } - } - - unsafe { freeaddrinfo(res); } - - Ok(addrs) -} - -//////////////////////////////////////////////////////////////////////////////// -// get_address_name -//////////////////////////////////////////////////////////////////////////////// - -extern "system" { - fn getnameinfo(sa: *const libc::sockaddr, salen: libc::socklen_t, - host: *mut c_char, hostlen: libc::size_t, - serv: *mut c_char, servlen: libc::size_t, - flags: c_int) -> c_int; -} - -const NI_MAXHOST: usize = 1025; - -pub fn get_address_name(addr: IpAddr) -> Result { - let addr = SocketAddr{ip: addr, port: 0}; - - let mut storage: libc::sockaddr_storage = unsafe { mem::zeroed() }; - let len = addr_to_sockaddr(addr, &mut storage); - - let mut hostbuf = [0 as c_char; NI_MAXHOST]; - - let res = unsafe { - getnameinfo(&storage as *const _ as *const libc::sockaddr, len, - hostbuf.as_mut_ptr(), NI_MAXHOST as libc::size_t, - ptr::null_mut(), 0, - 0) - }; - - if res != 0 { - return Err(last_gai_error(res)); - } - - unsafe { - let data = CStr::from_ptr(hostbuf.as_ptr()); - Ok(str::from_utf8(data.to_bytes()).unwrap().to_string()) - } -} - -//////////////////////////////////////////////////////////////////////////////// -// Timeout helpers -// -// The read/write functions below are the helpers for reading/writing a socket -// with a possible deadline specified. This is generally viewed as a timed out -// I/O operation. -// -// From the application's perspective, timeouts apply to the I/O object, not to -// the underlying file descriptor (it's one timeout per object). This means that -// we can't use the SO_RCVTIMEO and corresponding send timeout option. -// -// The next idea to implement timeouts would be to use nonblocking I/O. An -// invocation of select() would wait (with a timeout) for a socket to be ready. -// Once its ready, we can perform the operation. Note that the operation *must* -// be nonblocking, even though select() says the socket is ready. This is -// because some other thread could have come and stolen our data (handles can be -// cloned). -// -// To implement nonblocking I/O, the first option we have is to use the -// O_NONBLOCK flag. Remember though that this is a global setting, affecting all -// I/O objects, so this was initially viewed as unwise. -// -// It turns out that there's this nifty MSG_DONTWAIT flag which can be passed to -// send/recv, but the niftiness wears off once you realize it only works well on -// Linux [1] [2]. This means that it's pretty easy to get a nonblocking -// operation on Linux (no flag fiddling, no affecting other objects), but not on -// other platforms. -// -// To work around this constraint on other platforms, we end up using the -// original strategy of flipping the O_NONBLOCK flag. As mentioned before, this -// could cause other objects' blocking operations to suddenly become -// nonblocking. To get around this, a "blocking operation" which returns EAGAIN -// falls back to using the same code path as nonblocking operations, but with an -// infinite timeout (select + send/recv). This helps emulate blocking -// reads/writes despite the underlying descriptor being nonblocking, as well as -// optimizing the fast path of just hitting one syscall in the good case. -// -// As a final caveat, this implementation uses a mutex so only one thread is -// doing a nonblocking operation at at time. This is the operation that comes -// after the select() (at which point we think the socket is ready). This is -// done for sanity to ensure that the state of the O_NONBLOCK flag is what we -// expect (wouldn't want someone turning it on when it should be off!). All -// operations performed in the lock are *nonblocking* to avoid holding the mutex -// forever. -// -// So, in summary, Linux uses MSG_DONTWAIT and doesn't need mutexes, everyone -// else uses O_NONBLOCK and mutexes with some trickery to make sure blocking -// reads/writes are still blocking. -// -// Fun, fun! -// -// [1] http://twistedmatrix.com/pipermail/twisted-commits/2012-April/034692.html -// [2] http://stackoverflow.com/questions/19819198/does-send-msg-dontwait - -pub fn read(fd: sock_t, deadline: u64, mut lock: L, mut read: R) -> IoResult where - L: FnMut() -> T, - R: FnMut(bool) -> libc::c_int, -{ - let mut ret = -1; - if deadline == 0 { - ret = retry(|| read(false)); - } - - if deadline != 0 || (ret == -1 && wouldblock()) { - let deadline = match deadline { - 0 => None, - n => Some(n), - }; - loop { - // With a timeout, first we wait for the socket to become - // readable using select(), specifying the relevant timeout for - // our previously set deadline. - try!(await(&[fd], deadline, Readable)); - - // At this point, we're still within the timeout, and we've - // determined that the socket is readable (as returned by - // select). We must still read the socket in *nonblocking* mode - // because some other thread could come steal our data. If we - // fail to read some data, we retry (hence the outer loop) and - // wait for the socket to become readable again. - let _guard = lock(); - match retry(|| read(deadline.is_some())) { - -1 if wouldblock() => {} - -1 => return Err(last_net_error()), - n => { ret = n; break } - } - } - } - - match ret { - 0 => Err(sys_common::eof()), - n if n < 0 => Err(last_net_error()), - n => Ok(n as usize) - } -} - -pub fn write(fd: sock_t, - deadline: u64, - buf: &[u8], - write_everything: bool, - mut lock: L, - mut write: W) -> IoResult where - L: FnMut() -> T, - W: FnMut(bool, *const u8, usize) -> i64, -{ - let mut ret = -1; - let mut written = 0; - if deadline == 0 { - if write_everything { - ret = keep_going(buf, |inner, len| { - written = buf.len() - len; - write(false, inner, len) - }); - } else { - ret = retry(|| { write(false, buf.as_ptr(), buf.len()) }); - if ret > 0 { written = ret as usize; } - } - } - - if deadline != 0 || (ret == -1 && wouldblock()) { - let deadline = match deadline { - 0 => None, - n => Some(n), - }; - while written < buf.len() && (write_everything || written == 0) { - // As with read(), first wait for the socket to be ready for - // the I/O operation. - match await(&[fd], deadline, Writable) { - Err(ref e) if e.kind == old_io::EndOfFile && written > 0 => { - assert!(deadline.is_some()); - return Err(short_write(written, "short write")) - } - Err(e) => return Err(e), - Ok(()) => {} - } - - // Also as with read(), we use MSG_DONTWAIT to guard ourselves - // against unforeseen circumstances. - let _guard = lock(); - let ptr = buf[written..].as_ptr(); - let len = buf.len() - written; - match retry(|| write(deadline.is_some(), ptr, len)) { - -1 if wouldblock() => {} - -1 => return Err(last_net_error()), - n => { written += n as usize; } - } - } - ret = 0; - } - if ret < 0 { - Err(last_net_error()) - } else { - Ok(written) - } -} - -// See http://developerweb.net/viewtopic.php?id=3196 for where this is -// derived from. -pub fn connect_timeout(fd: sock_t, - addrp: *const libc::sockaddr, - len: libc::socklen_t, - timeout_ms: u64) -> IoResult<()> { - #[cfg(unix)] use libc::EINPROGRESS as INPROGRESS; - #[cfg(windows)] use libc::WSAEINPROGRESS as INPROGRESS; - #[cfg(unix)] use libc::EWOULDBLOCK as WOULDBLOCK; - #[cfg(windows)] use libc::WSAEWOULDBLOCK as WOULDBLOCK; - - // Make sure the call to connect() doesn't block - set_nonblocking(fd, true); - - let ret = match unsafe { libc::connect(fd, addrp, len) } { - // If the connection is in progress, then we need to wait for it to - // finish (with a timeout). The current strategy for doing this is - // to use select() with a timeout. - -1 if os::errno() as isize == INPROGRESS as isize || - os::errno() as isize == WOULDBLOCK as isize => { - let mut set: c::fd_set = unsafe { mem::zeroed() }; - c::fd_set(&mut set, fd); - match await(fd, &mut set, timeout_ms) { - 0 => Err(timeout("connection timed out")), - -1 => Err(last_net_error()), - _ => { - let err: libc::c_int = try!( - getsockopt(fd, libc::SOL_SOCKET, libc::SO_ERROR)); - if err == 0 { - Ok(()) - } else { - Err(decode_error_detailed(err)) - } - } - } - } - - -1 => Err(last_net_error()), - _ => Ok(()), - }; - - // be sure to turn blocking I/O back on - set_nonblocking(fd, false); - return ret; - - #[cfg(unix)] - fn await(fd: sock_t, set: &mut c::fd_set, timeout: u64) -> libc::c_int { - let start = timer::now(); - retry(|| unsafe { - // Recalculate the timeout each iteration (it is generally - // undefined what the value of the 'tv' is after select - // returns EINTR). - let mut tv = ms_to_timeval(timeout - (timer::now() - start)); - c::select(fd + 1, ptr::null_mut(), set as *mut _, - ptr::null_mut(), &mut tv) - }) - } - #[cfg(windows)] - fn await(_fd: sock_t, set: &mut c::fd_set, timeout: u64) -> libc::c_int { - let mut tv = ms_to_timeval(timeout); - unsafe { c::select(1, ptr::null_mut(), set, ptr::null_mut(), &mut tv) } - } -} - -pub fn await(fds: &[sock_t], deadline: Option, - status: SocketStatus) -> IoResult<()> { - let mut set: c::fd_set = unsafe { mem::zeroed() }; - let mut max = 0; - for &fd in fds { - c::fd_set(&mut set, fd); - max = cmp::max(max, fd + 1); - } - if cfg!(windows) { - max = fds.len() as sock_t; - } - - let (read, write) = match status { - Readable => (&mut set as *mut _, ptr::null_mut()), - Writable => (ptr::null_mut(), &mut set as *mut _), - }; - let mut tv: libc::timeval = unsafe { mem::zeroed() }; - - match retry(|| { - let now = timer::now(); - let tvp = match deadline { - None => ptr::null_mut(), - Some(deadline) => { - // If we're past the deadline, then pass a 0 timeout to - // select() so we can poll the status - let ms = if deadline < now {0} else {deadline - now}; - tv = ms_to_timeval(ms); - &mut tv as *mut _ - } - }; - let r = unsafe { - c::select(max as libc::c_int, read, write, ptr::null_mut(), tvp) - }; - r - }) { - -1 => Err(last_net_error()), - 0 => Err(timeout("timed out")), - _ => Ok(()), - } -} - -//////////////////////////////////////////////////////////////////////////////// -// Basic socket representation -//////////////////////////////////////////////////////////////////////////////// - -struct Inner { - fd: sock_t, - - // Unused on Linux, where this lock is not necessary. - #[allow(dead_code)] - lock: Mutex<()>, -} - -impl Inner { - fn new(fd: sock_t) -> Inner { - Inner { fd: fd, lock: Mutex::new(()) } - } -} - -impl Drop for Inner { - fn drop(&mut self) { unsafe { close_sock(self.fd); } } -} - -#[cfg(not(target_os = "linux"))] -pub struct Guard<'a> { - pub fd: sock_t, - pub guard: MutexGuard<'a, ()>, -} - -#[cfg(not(target_os = "linux"))] -#[unsafe_destructor] -impl<'a> Drop for Guard<'a> { - fn drop(&mut self) { - set_nonblocking(self.fd, false); - } -} - -//////////////////////////////////////////////////////////////////////////////// -// TCP streams -//////////////////////////////////////////////////////////////////////////////// - -pub struct TcpStream { - inner: Arc, - read_deadline: u64, - write_deadline: u64, -} - -impl TcpStream { - pub fn connect(addr: SocketAddr, timeout: Option) -> IoResult { - sys::init_net(); - - let fd = try!(socket(addr, libc::SOCK_STREAM)); - let ret = TcpStream::new(fd); - - let mut storage = unsafe { mem::zeroed() }; - let len = addr_to_sockaddr(addr, &mut storage); - let addrp = &storage as *const _ as *const libc::sockaddr; - - match timeout { - Some(timeout) => { - try!(connect_timeout(fd, addrp, len, timeout)); - Ok(ret) - }, - None => { - match retry(|| unsafe { libc::connect(fd, addrp, len) }) { - -1 => Err(last_error()), - _ => Ok(ret), - } - } - } - } - - pub fn new(fd: sock_t) -> TcpStream { - TcpStream { - inner: Arc::new(Inner::new(fd)), - read_deadline: 0, - write_deadline: 0, - } - } - - pub fn fd(&self) -> sock_t { self.inner.fd } - - pub fn set_nodelay(&mut self, nodelay: bool) -> IoResult<()> { - setsockopt(self.fd(), libc::IPPROTO_TCP, libc::TCP_NODELAY, - nodelay as libc::c_int) - } - - pub fn set_keepalive(&mut self, seconds: Option) -> IoResult<()> { - let ret = setsockopt(self.fd(), libc::SOL_SOCKET, libc::SO_KEEPALIVE, - seconds.is_some() as libc::c_int); - match seconds { - Some(n) => ret.and_then(|()| self.set_tcp_keepalive(n)), - None => ret, - } - } - - #[cfg(any(target_os = "macos", target_os = "ios"))] - fn set_tcp_keepalive(&mut self, seconds: usize) -> IoResult<()> { - setsockopt(self.fd(), libc::IPPROTO_TCP, libc::TCP_KEEPALIVE, - seconds as libc::c_int) - } - #[cfg(any(target_os = "freebsd", - target_os = "dragonfly"))] - fn set_tcp_keepalive(&mut self, seconds: usize) -> IoResult<()> { - setsockopt(self.fd(), libc::IPPROTO_TCP, libc::TCP_KEEPIDLE, - seconds as libc::c_int) - } - #[cfg(target_os = "openbsd")] - fn set_tcp_keepalive(&mut self, seconds: usize) -> IoResult<()> { - setsockopt(self.fd(), libc::IPPROTO_TCP, libc::SO_KEEPALIVE, - seconds as libc::c_int) - } - #[cfg(not(any(target_os = "macos", - target_os = "ios", - target_os = "freebsd", - target_os = "dragonfly", - target_os = "openbsd")))] - fn set_tcp_keepalive(&mut self, _seconds: usize) -> IoResult<()> { - Ok(()) - } - - #[cfg(target_os = "linux")] - fn lock_nonblocking(&self) {} - - #[cfg(not(target_os = "linux"))] - fn lock_nonblocking<'a>(&'a self) -> Guard<'a> { - let ret = Guard { - fd: self.fd(), - guard: self.inner.lock.lock().unwrap(), - }; - set_nonblocking(self.fd(), true); - ret - } - - pub fn read(&mut self, buf: &mut [u8]) -> IoResult { - let fd = self.fd(); - let dolock = || self.lock_nonblocking(); - let doread = |nb| unsafe { - let flags = if nb {c::MSG_DONTWAIT} else {0}; - libc::recv(fd, - buf.as_mut_ptr() as *mut libc::c_void, - buf.len() as wrlen, - flags) as libc::c_int - }; - read(fd, self.read_deadline, dolock, doread) - } - - pub fn write(&mut self, buf: &[u8]) -> IoResult<()> { - let fd = self.fd(); - let dolock = || self.lock_nonblocking(); - let dowrite = |nb: bool, buf: *const u8, len: usize| unsafe { - let flags = if nb {c::MSG_DONTWAIT} else {0}; - libc::send(fd, - buf as *const _, - len as wrlen, - flags) as i64 - }; - write(fd, self.write_deadline, buf, true, dolock, dowrite).map(|_| ()) - } - pub fn peer_name(&mut self) -> IoResult { - sockname(self.fd(), libc::getpeername) - } - - pub fn close_write(&mut self) -> IoResult<()> { - super::mkerr_libc(unsafe { libc::shutdown(self.fd(), libc::SHUT_WR) }) - } - pub fn close_read(&mut self) -> IoResult<()> { - super::mkerr_libc(unsafe { libc::shutdown(self.fd(), libc::SHUT_RD) }) - } - - pub fn set_timeout(&mut self, timeout: Option) { - let deadline = timeout.map(|a| timer::now() + a).unwrap_or(0); - self.read_deadline = deadline; - self.write_deadline = deadline; - } - pub fn set_read_timeout(&mut self, timeout: Option) { - self.read_deadline = timeout.map(|a| timer::now() + a).unwrap_or(0); - } - pub fn set_write_timeout(&mut self, timeout: Option) { - self.write_deadline = timeout.map(|a| timer::now() + a).unwrap_or(0); - } - - pub fn socket_name(&mut self) -> IoResult { - sockname(self.fd(), libc::getsockname) - } -} - -impl Clone for TcpStream { - fn clone(&self) -> TcpStream { - TcpStream { - inner: self.inner.clone(), - read_deadline: 0, - write_deadline: 0, - } - } -} - -//////////////////////////////////////////////////////////////////////////////// -// UDP -//////////////////////////////////////////////////////////////////////////////// - -pub struct UdpSocket { - inner: Arc, - read_deadline: u64, - write_deadline: u64, -} - -impl UdpSocket { - pub fn bind(addr: SocketAddr) -> IoResult { - sys::init_net(); - - let fd = try!(socket(addr, libc::SOCK_DGRAM)); - let ret = UdpSocket { - inner: Arc::new(Inner::new(fd)), - read_deadline: 0, - write_deadline: 0, - }; - - let mut storage = unsafe { mem::zeroed() }; - let len = addr_to_sockaddr(addr, &mut storage); - let addrp = &storage as *const _ as *const libc::sockaddr; - - match unsafe { libc::bind(fd, addrp, len) } { - -1 => Err(last_error()), - _ => Ok(ret), - } - } - - pub fn fd(&self) -> sock_t { self.inner.fd } - - pub fn set_broadcast(&mut self, on: bool) -> IoResult<()> { - setsockopt(self.fd(), libc::SOL_SOCKET, libc::SO_BROADCAST, - on as libc::c_int) - } - - pub fn set_multicast_loop(&mut self, on: bool) -> IoResult<()> { - setsockopt(self.fd(), libc::IPPROTO_IP, libc::IP_MULTICAST_LOOP, - on as libc::c_int) - } - - pub fn set_membership(&mut self, addr: IpAddr, opt: libc::c_int) -> IoResult<()> { - match ip_to_inaddr(addr) { - In4Addr(addr) => { - let mreq = libc::ip_mreq { - imr_multiaddr: addr, - // interface == INADDR_ANY - imr_interface: libc::in_addr { s_addr: 0x0 }, - }; - setsockopt(self.fd(), libc::IPPROTO_IP, opt, mreq) - } - In6Addr(addr) => { - let mreq = libc::ip6_mreq { - ipv6mr_multiaddr: addr, - ipv6mr_interface: 0, - }; - setsockopt(self.fd(), libc::IPPROTO_IPV6, opt, mreq) - } - } - } - - #[cfg(target_os = "linux")] - fn lock_nonblocking(&self) {} - - #[cfg(not(target_os = "linux"))] - fn lock_nonblocking<'a>(&'a self) -> Guard<'a> { - let ret = Guard { - fd: self.fd(), - guard: self.inner.lock.lock().unwrap(), - }; - set_nonblocking(self.fd(), true); - ret - } - - pub fn socket_name(&mut self) -> IoResult { - sockname(self.fd(), libc::getsockname) - } - - pub fn recv_from(&mut self, buf: &mut [u8]) -> IoResult<(usize, SocketAddr)> { - let fd = self.fd(); - let mut storage: libc::sockaddr_storage = unsafe { mem::zeroed() }; - let storagep = &mut storage as *mut _ as *mut libc::sockaddr; - let mut addrlen: libc::socklen_t = - mem::size_of::() as libc::socklen_t; - - let dolock = || self.lock_nonblocking(); - let n = try!(read(fd, self.read_deadline, dolock, |nb| unsafe { - let flags = if nb {c::MSG_DONTWAIT} else {0}; - libc::recvfrom(fd, - buf.as_mut_ptr() as *mut libc::c_void, - buf.len() as msglen_t, - flags, - storagep, - &mut addrlen) as libc::c_int - })); - Ok((n as usize, sockaddr_to_addr(&storage, addrlen as usize).unwrap())) - } - - pub fn send_to(&mut self, buf: &[u8], dst: SocketAddr) -> IoResult<()> { - let mut storage = unsafe { mem::zeroed() }; - let dstlen = addr_to_sockaddr(dst, &mut storage); - let dstp = &storage as *const _ as *const libc::sockaddr; - - let fd = self.fd(); - let dolock = || self.lock_nonblocking(); - let dowrite = |nb, buf: *const u8, len: usize| unsafe { - let flags = if nb {c::MSG_DONTWAIT} else {0}; - libc::sendto(fd, - buf as *const libc::c_void, - len as msglen_t, - flags, - dstp, - dstlen) as i64 - }; - - let n = try!(write(fd, self.write_deadline, buf, false, dolock, dowrite)); - assert!(n == buf.len(), "UDP packet not completely written."); - Ok(()) - } - - pub fn join_multicast(&mut self, multi: IpAddr) -> IoResult<()> { - match multi { - Ipv4Addr(..) => { - self.set_membership(multi, libc::IP_ADD_MEMBERSHIP) - } - Ipv6Addr(..) => { - self.set_membership(multi, libc::IPV6_ADD_MEMBERSHIP) - } - } - } - pub fn leave_multicast(&mut self, multi: IpAddr) -> IoResult<()> { - match multi { - Ipv4Addr(..) => { - self.set_membership(multi, libc::IP_DROP_MEMBERSHIP) - } - Ipv6Addr(..) => { - self.set_membership(multi, libc::IPV6_DROP_MEMBERSHIP) - } - } - } - - pub fn multicast_time_to_live(&mut self, ttl: isize) -> IoResult<()> { - setsockopt(self.fd(), libc::IPPROTO_IP, libc::IP_MULTICAST_TTL, - ttl as libc::c_int) - } - pub fn time_to_live(&mut self, ttl: isize) -> IoResult<()> { - setsockopt(self.fd(), libc::IPPROTO_IP, libc::IP_TTL, ttl as libc::c_int) - } - - pub fn set_timeout(&mut self, timeout: Option) { - let deadline = timeout.map(|a| timer::now() + a).unwrap_or(0); - self.read_deadline = deadline; - self.write_deadline = deadline; - } - pub fn set_read_timeout(&mut self, timeout: Option) { - self.read_deadline = timeout.map(|a| timer::now() + a).unwrap_or(0); - } - pub fn set_write_timeout(&mut self, timeout: Option) { - self.write_deadline = timeout.map(|a| timer::now() + a).unwrap_or(0); - } -} - -impl Clone for UdpSocket { - fn clone(&self) -> UdpSocket { - UdpSocket { - inner: self.inner.clone(), - read_deadline: 0, - write_deadline: 0, - } - } -} diff --git a/src/libstd/sys/common/wtf8.rs b/src/libstd/sys/common/wtf8.rs index 631e47edb78fd..12282434983c1 100644 --- a/src/libstd/sys/common/wtf8.rs +++ b/src/libstd/sys/common/wtf8.rs @@ -37,8 +37,6 @@ use fmt; use hash::{Hash, Hasher}; use iter::FromIterator; use mem; -#[allow(deprecated)] // Int -use num::Int; use ops; use slice; use str; diff --git a/src/libstd/sys/unix/condvar.rs b/src/libstd/sys/unix/condvar.rs index 90dfebc4c454c..ed6382e000ac9 100644 --- a/src/libstd/sys/unix/condvar.rs +++ b/src/libstd/sys/unix/condvar.rs @@ -17,7 +17,6 @@ use sys::mutex::{self, Mutex}; use sys::time; use sys::sync as ffi; use time::Duration; -use num::{Int, NumCast}; pub struct Condvar { inner: UnsafeCell } @@ -70,8 +69,8 @@ impl Condvar { let r = ffi::gettimeofday(&mut sys_now, ptr::null_mut()); debug_assert_eq!(r, 0); - let seconds = NumCast::from(dur.num_seconds()); - let timeout = match seconds.and_then(|s| sys_now.tv_sec.checked_add(s)) { + let seconds = dur.num_seconds() as libc::time_t; + let timeout = match sys_now.tv_sec.checked_add(seconds) { Some(sec) => { libc::timespec { tv_sec: sec, @@ -81,7 +80,7 @@ impl Condvar { } None => { libc::timespec { - tv_sec: Int::max_value(), + tv_sec: ::max_value(), tv_nsec: 1_000_000_000 - 1, } } diff --git a/src/libstd/sys/unix/mod.rs b/src/libstd/sys/unix/mod.rs index a8a6219f3981d..d99753a6a4c80 100644 --- a/src/libstd/sys/unix/mod.rs +++ b/src/libstd/sys/unix/mod.rs @@ -15,7 +15,8 @@ use prelude::v1::*; use io::{self, ErrorKind}; use libc; -use num::{Int, SignedInt}; +use num::One; +use ops::Neg; pub mod backtrace; pub mod c; @@ -63,23 +64,8 @@ pub fn decode_error_kind(errno: i32) -> ErrorKind { } } -#[inline] -#[allow(deprecated)] -pub fn retry (mut f: F) -> T where - T: SignedInt, - F: FnMut() -> T, -{ - let one: T = Int::one(); - loop { - let n = f(); - if n == -one && os::errno() == libc::EINTR as i32 { } - else { return n } - } -} - -#[allow(deprecated)] -pub fn cvt(t: T) -> io::Result { - let one: T = Int::one(); +pub fn cvt>(t: T) -> io::Result { + let one: T = T::one(); if t == -one { Err(io::Error::last_os_error()) } else { @@ -89,7 +75,7 @@ pub fn cvt(t: T) -> io::Result { #[allow(deprecated)] pub fn cvt_r(mut f: F) -> io::Result - where T: SignedInt, F: FnMut() -> T + where T: One + PartialEq + Neg, F: FnMut() -> T { loop { match cvt(f()) { diff --git a/src/libstd/sys/unix/process2.rs b/src/libstd/sys/unix/process2.rs index caa7b4eb29c7b..4e7c4d241f532 100644 --- a/src/libstd/sys/unix/process2.rs +++ b/src/libstd/sys/unix/process2.rs @@ -19,7 +19,7 @@ use io::{self, Error, ErrorKind}; use libc::{self, pid_t, c_void, c_int, gid_t, uid_t}; use ptr; use sys::pipe2::AnonPipe; -use sys::{self, retry, c, cvt}; +use sys::{self, c, cvt, cvt_r}; use sys::fs2::{File, OpenOptions}; //////////////////////////////////////////////////////////////////////////////// @@ -273,7 +273,7 @@ impl Process { } } }; - retry(|| libc::dup2(fd.raw(), dst)) != -1 + cvt_r(|| libc::dup2(fd.raw(), dst)).is_ok() }; if !setup(in_fd, libc::STDIN_FILENO) { fail(&mut output) } @@ -317,19 +317,19 @@ impl Process { pub fn wait(&self) -> io::Result { let mut status = 0 as c_int; - try!(cvt(retry(|| unsafe { c::waitpid(self.pid, &mut status, 0) }))); + try!(cvt_r(|| unsafe { c::waitpid(self.pid, &mut status, 0) })); Ok(translate_status(status)) } pub fn try_wait(&self) -> Option { let mut status = 0 as c_int; - match retry(|| unsafe { + match cvt_r(|| unsafe { c::waitpid(self.pid, &mut status, c::WNOHANG) }) { - n if n == self.pid => Some(translate_status(status)), - 0 => None, - n => panic!("unknown waitpid error `{}`: {}", n, - io::Error::last_os_error()), + Ok(0) => None, + Ok(n) if n == self.pid => Some(translate_status(status)), + Ok(n) => panic!("unkown pid: {}", n), + Err(e) => panic!("unknown waitpid error: {}", e), } } } diff --git a/src/libstd/thread/mod.rs b/src/libstd/thread/mod.rs index 4fd0340f09ac0..c65377e238f8f 100644 --- a/src/libstd/thread/mod.rs +++ b/src/libstd/thread/mod.rs @@ -497,15 +497,6 @@ pub fn sleep_ms(ms: u32) { imp::sleep(Duration::milliseconds(ms as i64)) } -/// Deprecated: use `sleep_ms` instead. -#[unstable(feature = "thread_sleep", - reason = "recently added, needs an RFC, and `Duration` itself is \ - unstable")] -#[deprecated(since = "1.0.0", reason = "use sleep_ms instead")] -pub fn sleep(dur: Duration) { - imp::sleep(dur) -} - /// Blocks unless or until the current thread's token is made available (may wake spuriously). /// /// See the module doc for more detail. @@ -546,13 +537,6 @@ pub fn park_timeout_ms(ms: u32) { *guard = false; } -/// Deprecated: use `park_timeout_ms` -#[unstable(feature = "std_misc", reason = "recently introduced, depends on Duration")] -#[deprecated(since = "1.0.0", reason = "use park_timeout_ms instead")] -pub fn park_timeout(duration: Duration) { - park_timeout_ms(duration.num_milliseconds() as u32) -} - //////////////////////////////////////////////////////////////////////////////// // Thread //////////////////////////////////////////////////////////////////////////////// diff --git a/src/libstd/time/duration.rs b/src/libstd/time/duration.rs index 9b79b483b28cf..636a0dd697a2b 100644 --- a/src/libstd/time/duration.rs +++ b/src/libstd/time/duration.rs @@ -12,13 +12,10 @@ #![unstable(feature = "std_misc")] +use prelude::v1::*; + use {fmt, i64}; -use ops::{Add, Sub, Mul, Div, Neg, FnOnce}; -use option::Option; -use option::Option::{Some, None}; -#[allow(deprecated)] // Int -use num::Int; -use result::Result::Ok; +use ops::{Add, Sub, Mul, Div, Neg}; /// The number of nanoseconds in a microsecond. const NANOS_PER_MICRO: i32 = 1000; diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs index 26463df187122..399810cb7f501 100644 --- a/src/libsyntax/ast.rs +++ b/src/libsyntax/ast.rs @@ -66,8 +66,6 @@ use parse::lexer; use ptr::P; use std::fmt; -#[allow(deprecated)] -use std::num::Int; use std::rc::Rc; use serialize::{Encodable, Decodable, Encoder, Decoder}; @@ -1142,16 +1140,24 @@ pub enum Sign { } impl Sign { - #[allow(deprecated)] // Int - pub fn new(n: T) -> Sign { - if n < Int::zero() { - Minus - } else { - Plus - } + pub fn new(n: T) -> Sign { + n.sign() } } +pub trait IntSign { + fn sign(&self) -> Sign; +} +macro_rules! doit { + ($($t:ident)*) => ($(impl IntSign for $t { + #[allow(unused_comparisons)] + fn sign(&self) -> Sign { + if *self < 0 {Minus} else {Plus} + } + })*) +} +doit! { i8 i16 i32 i64 isize u8 u16 u32 u64 usize } + #[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug, Copy)] pub enum LitIntType { SignedIntLit(IntTy, Sign), diff --git a/src/libsyntax/codemap.rs b/src/libsyntax/codemap.rs index a0bde8f6c525e..f762822031601 100644 --- a/src/libsyntax/codemap.rs +++ b/src/libsyntax/codemap.rs @@ -22,7 +22,6 @@ pub use self::MacroFormat::*; use std::cell::RefCell; -use std::num::ToPrimitive; use std::ops::{Add, Sub}; use std::rc::Rc; @@ -864,7 +863,11 @@ impl CodeMap { pub fn record_expansion(&self, expn_info: ExpnInfo) -> ExpnId { let mut expansions = self.expansions.borrow_mut(); expansions.push(expn_info); - ExpnId(expansions.len().to_u32().expect("too many ExpnInfo's!") - 1) + let len = expansions.len(); + if len > u32::max_value() as usize { + panic!("too many ExpnInfo's!"); + } + ExpnId(len as u32 - 1) } pub fn with_expn_info(&self, id: ExpnId, f: F) -> T where diff --git a/src/libsyntax/parse/mod.rs b/src/libsyntax/parse/mod.rs index 4b7b7b66582e1..f4b108c435276 100644 --- a/src/libsyntax/parse/mod.rs +++ b/src/libsyntax/parse/mod.rs @@ -22,8 +22,6 @@ use std::cell::{Cell, RefCell}; use std::fs::File; use std::io::Read; use std::iter; -#[allow(deprecated)] // Int -use std::num::Int; use std::path::{Path, PathBuf}; use std::rc::Rc; use std::str; diff --git a/src/libtest/lib.rs b/src/libtest/lib.rs index a9624840f676d..9dd903b769d36 100644 --- a/src/libtest/lib.rs +++ b/src/libtest/lib.rs @@ -75,7 +75,6 @@ use std::fs::File; use std::io::prelude::*; use std::io; use std::iter::repeat; -use std::num::{Float, Int}; use std::path::PathBuf; use std::sync::mpsc::{channel, Sender}; use std::sync::{Arc, Mutex}; @@ -418,7 +417,7 @@ pub fn parse_opts(args: &[String]) -> Option { #[derive(Clone, PartialEq)] pub struct BenchSamples { - ns_iter_summ: stats::Summary, + ns_iter_summ: stats::Summary, mb_s: usize, } @@ -1071,7 +1070,7 @@ impl Bencher { } // This is a more statistics-driven benchmark algorithm - pub fn auto_bench(&mut self, mut f: F) -> stats::Summary where F: FnMut(&mut Bencher) { + pub fn auto_bench(&mut self, mut f: F) -> stats::Summary where F: FnMut(&mut Bencher) { // Initial bench run to get ballpark figure. let mut n = 1; self.bench_n(n, |x| f(x)); diff --git a/src/libtest/stats.rs b/src/libtest/stats.rs index 06e0de76eafd8..341be762601dd 100644 --- a/src/libtest/stats.rs +++ b/src/libtest/stats.rs @@ -13,9 +13,8 @@ use std::cmp::Ordering::{self, Less, Greater, Equal}; use std::mem; -use std::num::{Float, FromPrimitive}; -fn local_cmp(x: T, y: T) -> Ordering { +fn local_cmp(x: f64, y: f64) -> Ordering { // arbitrarily decide that NaNs are larger than everything. if y.is_nan() { Less @@ -30,12 +29,12 @@ fn local_cmp(x: T, y: T) -> Ordering { } } -fn local_sort(v: &mut [T]) { - v.sort_by(|x: &T, y: &T| local_cmp(*x, *y)); +fn local_sort(v: &mut [f64]) { + v.sort_by(|x: &f64, y: &f64| local_cmp(*x, *y)); } /// Trait that provides simple descriptive statistics on a univariate set of numeric samples. -pub trait Stats { +pub trait Stats { /// Sum of the samples. /// @@ -43,24 +42,24 @@ pub trait Stats { /// Depends on IEEE-754 arithmetic guarantees. See proof of correctness at: /// ["Adaptive Precision Floating-Point Arithmetic and Fast Robust Geometric Predicates"] /// (http://www.cs.cmu.edu/~quake-papers/robust-arithmetic.ps) - fn sum(&self) -> T; + fn sum(&self) -> f64; /// Minimum value of the samples. - fn min(&self) -> T; + fn min(&self) -> f64; /// Maximum value of the samples. - fn max(&self) -> T; + fn max(&self) -> f64; /// Arithmetic mean (average) of the samples: sum divided by sample-count. /// /// See: https://en.wikipedia.org/wiki/Arithmetic_mean - fn mean(&self) -> T; + fn mean(&self) -> f64; /// Median of the samples: value separating the lower half of the samples from the higher half. /// Equal to `self.percentile(50.0)`. /// /// See: https://en.wikipedia.org/wiki/Median - fn median(&self) -> T; + fn median(&self) -> f64; /// Variance of the samples: bias-corrected mean of the squares of the differences of each /// sample from the sample mean. Note that this calculates the _sample variance_ rather than the @@ -69,7 +68,7 @@ pub trait Stats { /// than `n`. /// /// See: https://en.wikipedia.org/wiki/Variance - fn var(&self) -> T; + fn var(&self) -> f64; /// Standard deviation: the square root of the sample variance. /// @@ -77,13 +76,13 @@ pub trait Stats { /// `median_abs_dev` for unknown distributions. /// /// See: https://en.wikipedia.org/wiki/Standard_deviation - fn std_dev(&self) -> T; + fn std_dev(&self) -> f64; /// Standard deviation as a percent of the mean value. See `std_dev` and `mean`. /// /// Note: this is not a robust statistic for non-normal distributions. Prefer the /// `median_abs_dev_pct` for unknown distributions. - fn std_dev_pct(&self) -> T; + fn std_dev_pct(&self) -> f64; /// Scaled median of the absolute deviations of each sample from the sample median. This is a /// robust (distribution-agnostic) estimator of sample variability. Use this in preference to @@ -92,10 +91,10 @@ pub trait Stats { /// deviation. /// /// See: http://en.wikipedia.org/wiki/Median_absolute_deviation - fn median_abs_dev(&self) -> T; + fn median_abs_dev(&self) -> f64; /// Median absolute deviation as a percent of the median. See `median_abs_dev` and `median`. - fn median_abs_dev_pct(&self) -> T; + fn median_abs_dev_pct(&self) -> f64; /// Percentile: the value below which `pct` percent of the values in `self` fall. For example, /// percentile(95.0) will return the value `v` such that 95% of the samples `s` in `self` @@ -104,7 +103,7 @@ pub trait Stats { /// Calculated by linear interpolation between closest ranks. /// /// See: http://en.wikipedia.org/wiki/Percentile - fn percentile(&self, pct: T) -> T; + fn percentile(&self, pct: f64) -> f64; /// Quartiles of the sample: three values that divide the sample into four equal groups, each /// with 1/4 of the data. The middle value is the median. See `median` and `percentile`. This @@ -112,36 +111,36 @@ pub trait Stats { /// is otherwise equivalent. /// /// See also: https://en.wikipedia.org/wiki/Quartile - fn quartiles(&self) -> (T,T,T); + fn quartiles(&self) -> (f64,f64,f64); /// Inter-quartile range: the difference between the 25th percentile (1st quartile) and the 75th /// percentile (3rd quartile). See `quartiles`. /// /// See also: https://en.wikipedia.org/wiki/Interquartile_range - fn iqr(&self) -> T; + fn iqr(&self) -> f64; } /// Extracted collection of all the summary statistics of a sample set. #[derive(Clone, PartialEq)] #[allow(missing_docs)] -pub struct Summary { - pub sum: T, - pub min: T, - pub max: T, - pub mean: T, - pub median: T, - pub var: T, - pub std_dev: T, - pub std_dev_pct: T, - pub median_abs_dev: T, - pub median_abs_dev_pct: T, - pub quartiles: (T,T,T), - pub iqr: T, +pub struct Summary { + pub sum: f64, + pub min: f64, + pub max: f64, + pub mean: f64, + pub median: f64, + pub var: f64, + pub std_dev: f64, + pub std_dev_pct: f64, + pub median_abs_dev: f64, + pub median_abs_dev_pct: f64, + pub quartiles: (f64,f64,f64), + pub iqr: f64, } -impl Summary { +impl Summary { /// Construct a new summary of a sample set. - pub fn new(samples: &[T]) -> Summary { + pub fn new(samples: &[f64]) -> Summary { Summary { sum: samples.sum(), min: samples.min(), @@ -159,9 +158,9 @@ impl Summary { } } -impl Stats for [T] { +impl Stats for [f64] { // FIXME #11059 handle NaN, inf and overflow - fn sum(&self) -> T { + fn sum(&self) -> f64 { let mut partials = vec![]; for &x in self { @@ -170,7 +169,7 @@ impl Stats for [T] { // This inner loop applies `hi`/`lo` summation to each // partial so that the list of partial sums remains exact. for i in 0..partials.len() { - let mut y: T = partials[i]; + let mut y: f64 = partials[i]; if x.abs() < y.abs() { mem::swap(&mut x, &mut y); } @@ -178,7 +177,7 @@ impl Stats for [T] { // `lo`. Together `hi+lo` are exactly equal to `x+y`. let hi = x + y; let lo = y - (hi - x); - if lo != Float::zero() { + if lo != 0.0 { partials[j] = lo; j += 1; } @@ -191,35 +190,35 @@ impl Stats for [T] { partials.truncate(j+1); } } - let zero: T = Float::zero(); + let zero: f64 = 0.0; partials.iter().fold(zero, |p, q| p + *q) } - fn min(&self) -> T { + fn min(&self) -> f64 { assert!(!self.is_empty()); self.iter().fold(self[0], |p, q| p.min(*q)) } - fn max(&self) -> T { + fn max(&self) -> f64 { assert!(!self.is_empty()); self.iter().fold(self[0], |p, q| p.max(*q)) } - fn mean(&self) -> T { + fn mean(&self) -> f64 { assert!(!self.is_empty()); - self.sum() / FromPrimitive::from_usize(self.len()).unwrap() + self.sum() / (self.len() as f64) } - fn median(&self) -> T { - self.percentile(FromPrimitive::from_usize(50).unwrap()) + fn median(&self) -> f64 { + self.percentile(50 as f64) } - fn var(&self) -> T { + fn var(&self) -> f64 { if self.len() < 2 { - Float::zero() + 0.0 } else { let mean = self.mean(); - let mut v: T = Float::zero(); + let mut v: f64 = 0.0; for s in self { let x = *s - mean; v = v + x*x; @@ -227,53 +226,53 @@ impl Stats for [T] { // NB: this is _supposed to be_ len-1, not len. If you // change it back to len, you will be calculating a // population variance, not a sample variance. - let denom = FromPrimitive::from_usize(self.len()-1).unwrap(); + let denom = (self.len() - 1) as f64; v/denom } } - fn std_dev(&self) -> T { + fn std_dev(&self) -> f64 { self.var().sqrt() } - fn std_dev_pct(&self) -> T { - let hundred = FromPrimitive::from_usize(100).unwrap(); + fn std_dev_pct(&self) -> f64 { + let hundred = 100 as f64; (self.std_dev() / self.mean()) * hundred } - fn median_abs_dev(&self) -> T { + fn median_abs_dev(&self) -> f64 { let med = self.median(); - let abs_devs: Vec = self.iter().map(|&v| (med - v).abs()).collect(); + let abs_devs: Vec = self.iter().map(|&v| (med - v).abs()).collect(); // This constant is derived by smarter statistics brains than me, but it is // consistent with how R and other packages treat the MAD. - let number = FromPrimitive::from_f64(1.4826).unwrap(); + let number = 1.4826; abs_devs.median() * number } - fn median_abs_dev_pct(&self) -> T { - let hundred = FromPrimitive::from_usize(100).unwrap(); + fn median_abs_dev_pct(&self) -> f64 { + let hundred = 100 as f64; (self.median_abs_dev() / self.median()) * hundred } - fn percentile(&self, pct: T) -> T { + fn percentile(&self, pct: f64) -> f64 { let mut tmp = self.to_vec(); local_sort(&mut tmp); percentile_of_sorted(&tmp, pct) } - fn quartiles(&self) -> (T,T,T) { + fn quartiles(&self) -> (f64,f64,f64) { let mut tmp = self.to_vec(); local_sort(&mut tmp); - let first = FromPrimitive::from_usize(25).unwrap(); + let first = 25f64; let a = percentile_of_sorted(&tmp, first); - let secound = FromPrimitive::from_usize(50).unwrap(); + let secound = 50f64; let b = percentile_of_sorted(&tmp, secound); - let third = FromPrimitive::from_usize(75).unwrap(); + let third = 75f64; let c = percentile_of_sorted(&tmp, third); (a,b,c) } - fn iqr(&self) -> T { + fn iqr(&self) -> f64 { let (a,_,c) = self.quartiles(); c - a } @@ -282,41 +281,41 @@ impl Stats for [T] { // Helper function: extract a value representing the `pct` percentile of a sorted sample-set, using // linear interpolation. If samples are not sorted, return nonsensical value. -fn percentile_of_sorted(sorted_samples: &[T], - pct: T) -> T { +fn percentile_of_sorted(sorted_samples: &[f64], pct: f64) -> f64 { assert!(!sorted_samples.is_empty()); if sorted_samples.len() == 1 { return sorted_samples[0]; } - let zero: T = Float::zero(); + let zero: f64 = 0.0; assert!(zero <= pct); - let hundred = FromPrimitive::from_usize(100).unwrap(); + let hundred = 100f64; assert!(pct <= hundred); if pct == hundred { return sorted_samples[sorted_samples.len() - 1]; } - let length = FromPrimitive::from_usize(sorted_samples.len() - 1).unwrap(); + let length = (sorted_samples.len() - 1) as f64; let rank = (pct / hundred) * length; let lrank = rank.floor(); let d = rank - lrank; - let n = lrank.to_usize().unwrap(); + let n = lrank as usize; let lo = sorted_samples[n]; let hi = sorted_samples[n+1]; lo + (hi - lo) * d } -/// Winsorize a set of samples, replacing values above the `100-pct` percentile and below the `pct` -/// percentile with those percentiles themselves. This is a way of minimizing the effect of -/// outliers, at the cost of biasing the sample. It differs from trimming in that it does not -/// change the number of samples, just changes the values of those that are outliers. +/// Winsorize a set of samples, replacing values above the `100-pct` percentile +/// and below the `pct` percentile with those percentiles themselves. This is a +/// way of minimizing the effect of outliers, at the cost of biasing the sample. +/// It differs from trimming in that it does not change the number of samples, +/// just changes the values of those that are outliers. /// /// See: http://en.wikipedia.org/wiki/Winsorising -pub fn winsorize(samples: &mut [T], pct: T) { +pub fn winsorize(samples: &mut [f64], pct: f64) { let mut tmp = samples.to_vec(); local_sort(&mut tmp); let lo = percentile_of_sorted(&tmp, pct); - let hundred: T = FromPrimitive::from_usize(100).unwrap(); + let hundred = 100 as f64; let hi = percentile_of_sorted(&tmp, hundred-pct); for samp in samples { if *samp > hi { From d8b633527484e0bc4310c23133f2f7a3b260bc4d Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Fri, 17 Apr 2015 22:12:20 -0700 Subject: [PATCH 17/25] test: Fix fallout in tests --- src/test/auxiliary/issue_3907.rs | 6 +-- src/test/auxiliary/private_trait_xc.rs | 4 +- src/test/auxiliary/rustdoc-default-impl.rs | 2 +- src/test/auxiliary/svh-a-base.rs | 7 +-- src/test/auxiliary/svh-a-change-lit.rs | 7 +-- .../auxiliary/svh-a-change-significant-cfg.rs | 7 +-- .../auxiliary/svh-a-change-trait-bound.rs | 7 +-- src/test/auxiliary/svh-a-change-type-arg.rs | 7 +-- src/test/auxiliary/svh-a-change-type-ret.rs | 7 +-- .../auxiliary/svh-a-change-type-static.rs | 6 +-- src/test/auxiliary/svh-a-comment.rs | 7 +-- src/test/auxiliary/svh-a-doc.rs | 7 +-- src/test/auxiliary/svh-a-macro.rs | 7 +-- src/test/auxiliary/svh-a-no-change.rs | 7 +-- src/test/auxiliary/svh-a-redundant-cfg.rs | 7 +-- src/test/auxiliary/svh-a-whitespace.rs | 7 +-- src/test/auxiliary/trait_impl_conflict.rs | 4 +- ...lt_trait_impl_cross_crate_coherence_lib.rs | 4 +- .../associated-types-eq-expr-path.rs | 2 +- .../associated-types-issue-17359.rs | 2 +- ...sociated-types-multiple-types-one-trait.rs | 2 +- ...sociated-types-no-suitable-supertrait-2.rs | 2 +- ...associated-types-no-suitable-supertrait.rs | 2 +- .../associated-types-unconstrained.rs | 2 +- src/test/compile-fail/bad-sized.rs | 2 +- ...nket-conflicts-with-blanket-implemented.rs | 5 +- ...et-conflicts-with-blanket-unimplemented.rs | 4 +- ...herence-conflicting-negative-trait-impl.rs | 2 +- .../coherence-default-trait-impl.rs | 8 ++- ..._copy_like_err_fundamental_struct_tuple.rs | 4 +- .../coherence_copy_like_err_struct.rs | 4 +- .../coherence_copy_like_err_tuple.rs | 4 +- src/test/compile-fail/dst-bad-coerce2.rs | 2 +- src/test/compile-fail/dst-bad-coercions.rs | 4 +- src/test/compile-fail/implicit-method-bind.rs | 4 +- src/test/compile-fail/issue-13853.rs | 4 +- src/test/compile-fail/issue-14853.rs | 3 +- src/test/compile-fail/issue-16747.rs | 4 +- src/test/compile-fail/issue-18107.rs | 4 +- src/test/compile-fail/issue-18389.rs | 7 +-- src/test/compile-fail/issue-18611.rs | 4 +- src/test/compile-fail/issue-18819.rs | 4 +- src/test/compile-fail/issue-2063.rs | 4 +- src/test/compile-fail/issue-20831-debruijn.rs | 3 +- src/test/compile-fail/issue-23080-2.rs | 4 +- src/test/compile-fail/issue-3702-2.rs | 7 ++- src/test/compile-fail/issue-5035-2.rs | 4 +- src/test/compile-fail/issue-5883.rs | 6 +-- src/test/compile-fail/issue-7575.rs | 8 ++- src/test/compile-fail/kindck-copy.rs | 3 +- .../compile-fail/kindck-impl-type-params-2.rs | 4 +- src/test/compile-fail/kindck-send-object.rs | 4 +- src/test/compile-fail/kindck-send-object1.rs | 4 +- src/test/compile-fail/kindck-send-object2.rs | 4 +- .../lint-visible-private-types.rs | 2 +- .../object-does-not-impl-trait.rs | 4 +- .../compile-fail/object-safety-no-static.rs | 2 +- src/test/compile-fail/phantom-oibit.rs | 4 +- src/test/compile-fail/privacy-ns2.rs | 8 ++- .../region-object-lifetime-in-coercion.rs | 2 +- ...gions-close-associated-type-into-object.rs | 4 +- .../regions-close-over-borrowed-ref-in-obj.rs | 4 +- .../trait-as-struct-constructor.rs | 2 +- .../trait-bounds-on-structs-and-enums.rs | 4 +- src/test/compile-fail/trait-bounds-sugar.rs | 4 +- src/test/compile-fail/trait-impl-1.rs | 4 +- .../type-params-in-different-spaces-1.rs | 6 +-- ...-default-trait-impl-constituent-types-2.rs | 4 +- ...ck-default-trait-impl-constituent-types.rs | 4 +- .../typeck-default-trait-impl-negation.rs | 6 +-- .../typeck-default-trait-impl-precedence.rs | 6 +-- .../typeck-default-trait-impl-superregion.rs | 2 - .../typeck-default-trait-impl-supertrait.rs | 4 +- ...k-default-trait-impl-trait-where-clause.rs | 6 +-- src/test/compile-fail/unsized6.rs | 4 +- src/test/compile-fail/unsized7.rs | 4 +- src/test/run-make/save-analysis/foo.rs | 3 -- src/test/run-pass/associated-types-basic.rs | 7 +-- .../run-pass/associated-types-issue-20371.rs | 6 +-- .../associated-types-nested-projections.rs | 3 +- ...iated-types-normalize-in-bounds-binding.rs | 5 +- ...om-type-param-via-bound-in-where-clause.rs | 7 +-- src/test/run-pass/const-binops.rs | 1 - src/test/run-pass/derive-no-std.rs | 1 - src/test/run-pass/deriving-primitive.rs | 39 --------------- src/test/run-pass/early-ret-binop-add.rs | 4 +- src/test/run-pass/exponential-notation.rs | 39 --------------- src/test/run-pass/extern-methods.rs | 7 +-- src/test/run-pass/float-nan.rs | 11 ++--- src/test/run-pass/intrinsics-math.rs | 1 - src/test/run-pass/issue-11736.rs | 3 -- src/test/run-pass/issue-13105.rs | 6 +-- src/test/run-pass/issue-8460.rs | 49 +++++++++---------- ...nomorphized-callees-with-ty-params-3314.rs | 6 +-- .../run-pass/numeric-method-autoexport.rs | 9 ---- src/test/run-pass/overloaded-autoderef.rs | 4 -- src/test/run-pass/syntax-trait-polarity.rs | 6 +-- src/test/run-pass/trait-bounds-basic.rs | 4 +- .../trait-bounds-on-structs-and-enums.rs | 4 +- src/test/run-pass/trait-bounds-recursion.rs | 8 ++- src/test/run-pass/trait-inheritance-num.rs | 11 ++--- src/test/run-pass/trait-inheritance-num0.rs | 5 +- src/test/run-pass/trait-inheritance-num1.rs | 7 ++- src/test/run-pass/trait-inheritance-num2.rs | 9 +--- src/test/run-pass/trait-inheritance-num3.rs | 10 ++-- src/test/run-pass/trait-inheritance-num5.rs | 14 ++++-- .../trait-inheritance-self-in-supertype.rs | 3 -- .../run-pass/trait-inheritance-static2.rs | 7 +-- ...nfer-argument-types-from-expected-bound.rs | 10 ++-- ...rgument-types-from-expected-object-type.rs | 10 ++-- ...-with-bound-regions-from-expected-bound.rs | 10 ++-- src/test/run-pass/utf8_idents.rs | 2 - 112 files changed, 205 insertions(+), 466 deletions(-) delete mode 100644 src/test/run-pass/deriving-primitive.rs delete mode 100644 src/test/run-pass/exponential-notation.rs diff --git a/src/test/auxiliary/issue_3907.rs b/src/test/auxiliary/issue_3907.rs index 3d5e52d709df3..6472c08c22296 100644 --- a/src/test/auxiliary/issue_3907.rs +++ b/src/test/auxiliary/issue_3907.rs @@ -8,10 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(core)] - -use std::marker::MarkerTrait; - -pub trait Foo : MarkerTrait { +pub trait Foo { fn bar(); } diff --git a/src/test/auxiliary/private_trait_xc.rs b/src/test/auxiliary/private_trait_xc.rs index dc08033602c99..37ee10c8d3733 100644 --- a/src/test/auxiliary/private_trait_xc.rs +++ b/src/test/auxiliary/private_trait_xc.rs @@ -8,6 +8,4 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(core)] - -trait Foo : ::std::marker::MarkerTrait {} +trait Foo {} diff --git a/src/test/auxiliary/rustdoc-default-impl.rs b/src/test/auxiliary/rustdoc-default-impl.rs index 8f11629be6cc8..c2ff7a0054f19 100644 --- a/src/test/auxiliary/rustdoc-default-impl.rs +++ b/src/test/auxiliary/rustdoc-default-impl.rs @@ -14,7 +14,7 @@ pub mod bar { use std::marker; - pub trait Bar: marker::MarkerTrait + 'static {} + pub trait Bar: 'static {} impl Bar for .. {} diff --git a/src/test/auxiliary/svh-a-base.rs b/src/test/auxiliary/svh-a-base.rs index 7e10d2158ede0..31a97f695f06c 100644 --- a/src/test/auxiliary/svh-a-base.rs +++ b/src/test/auxiliary/svh-a-base.rs @@ -14,16 +14,13 @@ //! (#14132). #![crate_name = "a"] -#![feature(core)] - -use std::marker::MarkerTrait; macro_rules! three { () => { 3 } } -pub trait U : MarkerTrait {} -pub trait V : MarkerTrait {} +pub trait U {} +pub trait V {} impl U for () {} impl V for () {} diff --git a/src/test/auxiliary/svh-a-change-lit.rs b/src/test/auxiliary/svh-a-change-lit.rs index c5f3880551165..5339fc8295c6f 100644 --- a/src/test/auxiliary/svh-a-change-lit.rs +++ b/src/test/auxiliary/svh-a-change-lit.rs @@ -14,16 +14,13 @@ //! (#14132). #![crate_name = "a"] -#![feature(core)] - -use std::marker::MarkerTrait; macro_rules! three { () => { 3 } } -pub trait U : MarkerTrait {} -pub trait V : MarkerTrait {} +pub trait U {} +pub trait V {} impl U for () {} impl V for () {} diff --git a/src/test/auxiliary/svh-a-change-significant-cfg.rs b/src/test/auxiliary/svh-a-change-significant-cfg.rs index 3168e747eb6e6..2a5d9446f879a 100644 --- a/src/test/auxiliary/svh-a-change-significant-cfg.rs +++ b/src/test/auxiliary/svh-a-change-significant-cfg.rs @@ -14,16 +14,13 @@ //! (#14132). #![crate_name = "a"] -#![feature(core)] - -use std::marker::MarkerTrait; macro_rules! three { () => { 3 } } -pub trait U : MarkerTrait {} -pub trait V : MarkerTrait {} +pub trait U {} +pub trait V {} impl U for () {} impl V for () {} diff --git a/src/test/auxiliary/svh-a-change-trait-bound.rs b/src/test/auxiliary/svh-a-change-trait-bound.rs index f86a43494f78e..61f2f2803ab18 100644 --- a/src/test/auxiliary/svh-a-change-trait-bound.rs +++ b/src/test/auxiliary/svh-a-change-trait-bound.rs @@ -14,16 +14,13 @@ //! (#14132). #![crate_name = "a"] -#![feature(core)] - -use std::marker::MarkerTrait; macro_rules! three { () => { 3 } } -pub trait U : MarkerTrait {} -pub trait V : MarkerTrait {} +pub trait U {} +pub trait V {} impl U for () {} impl V for () {} diff --git a/src/test/auxiliary/svh-a-change-type-arg.rs b/src/test/auxiliary/svh-a-change-type-arg.rs index dc412b700447b..270ce95be2bb6 100644 --- a/src/test/auxiliary/svh-a-change-type-arg.rs +++ b/src/test/auxiliary/svh-a-change-type-arg.rs @@ -14,16 +14,13 @@ //! (#14132). #![crate_name = "a"] -#![feature(core)] - -use std::marker::MarkerTrait; macro_rules! three { () => { 3 } } -pub trait U : MarkerTrait {} -pub trait V : MarkerTrait {} +pub trait U {} +pub trait V {} impl U for () {} impl V for () {} diff --git a/src/test/auxiliary/svh-a-change-type-ret.rs b/src/test/auxiliary/svh-a-change-type-ret.rs index 0cfcbbb0554e6..de4cc85a7dc47 100644 --- a/src/test/auxiliary/svh-a-change-type-ret.rs +++ b/src/test/auxiliary/svh-a-change-type-ret.rs @@ -14,16 +14,13 @@ //! (#14132). #![crate_name = "a"] -#![feature(core)] - -use std::marker::MarkerTrait; macro_rules! three { () => { 3 } } -pub trait U : MarkerTrait {} -pub trait V : MarkerTrait {} +pub trait U {} +pub trait V {} impl U for () {} impl V for () {} diff --git a/src/test/auxiliary/svh-a-change-type-static.rs b/src/test/auxiliary/svh-a-change-type-static.rs index e1e32095b5cb4..62f7986f1c3bd 100644 --- a/src/test/auxiliary/svh-a-change-type-static.rs +++ b/src/test/auxiliary/svh-a-change-type-static.rs @@ -16,14 +16,12 @@ #![crate_name = "a"] #![feature(core)] -use std::marker::MarkerTrait; - macro_rules! three { () => { 3 } } -pub trait U : MarkerTrait {} -pub trait V : MarkerTrait {} +pub trait U {} +pub trait V {} impl U for () {} impl V for () {} diff --git a/src/test/auxiliary/svh-a-comment.rs b/src/test/auxiliary/svh-a-comment.rs index 9fd97376b6681..22e40822eecfc 100644 --- a/src/test/auxiliary/svh-a-comment.rs +++ b/src/test/auxiliary/svh-a-comment.rs @@ -14,16 +14,13 @@ //! (#14132). #![crate_name = "a"] -#![feature(core)] - -use std::marker::MarkerTrait; macro_rules! three { () => { 3 } } -pub trait U : MarkerTrait {} -pub trait V : MarkerTrait {} +pub trait U {} +pub trait V {} impl U for () {} impl V for () {} diff --git a/src/test/auxiliary/svh-a-doc.rs b/src/test/auxiliary/svh-a-doc.rs index e64bde096b016..3d8a728967a4a 100644 --- a/src/test/auxiliary/svh-a-doc.rs +++ b/src/test/auxiliary/svh-a-doc.rs @@ -14,16 +14,13 @@ //! (#14132). #![crate_name = "a"] -#![feature(core)] - -use std::marker::MarkerTrait; macro_rules! three { () => { 3 } } -pub trait U : MarkerTrait {} -pub trait V : MarkerTrait {} +pub trait U {} +pub trait V {} impl U for () {} impl V for () {} diff --git a/src/test/auxiliary/svh-a-macro.rs b/src/test/auxiliary/svh-a-macro.rs index b16338f1e128c..41d7eb7b18645 100644 --- a/src/test/auxiliary/svh-a-macro.rs +++ b/src/test/auxiliary/svh-a-macro.rs @@ -14,16 +14,13 @@ //! (#14132). #![crate_name = "a"] -#![feature(core)] - -use std::marker::MarkerTrait; macro_rules! three { () => { 3 } } -pub trait U : MarkerTrait {} -pub trait V : MarkerTrait {} +pub trait U {} +pub trait V {} impl U for () {} impl V for () {} diff --git a/src/test/auxiliary/svh-a-no-change.rs b/src/test/auxiliary/svh-a-no-change.rs index 7e10d2158ede0..31a97f695f06c 100644 --- a/src/test/auxiliary/svh-a-no-change.rs +++ b/src/test/auxiliary/svh-a-no-change.rs @@ -14,16 +14,13 @@ //! (#14132). #![crate_name = "a"] -#![feature(core)] - -use std::marker::MarkerTrait; macro_rules! three { () => { 3 } } -pub trait U : MarkerTrait {} -pub trait V : MarkerTrait {} +pub trait U {} +pub trait V {} impl U for () {} impl V for () {} diff --git a/src/test/auxiliary/svh-a-redundant-cfg.rs b/src/test/auxiliary/svh-a-redundant-cfg.rs index 8cadd7bdf4174..e405c337abe4a 100644 --- a/src/test/auxiliary/svh-a-redundant-cfg.rs +++ b/src/test/auxiliary/svh-a-redundant-cfg.rs @@ -14,16 +14,13 @@ //! (#14132). #![crate_name = "a"] -#![feature(core)] - -use std::marker::MarkerTrait; macro_rules! three { () => { 3 } } -pub trait U : MarkerTrait {} -pub trait V : MarkerTrait {} +pub trait U {} +pub trait V {} impl U for () {} impl V for () {} diff --git a/src/test/auxiliary/svh-a-whitespace.rs b/src/test/auxiliary/svh-a-whitespace.rs index fcaf77909554d..9ef788c984273 100644 --- a/src/test/auxiliary/svh-a-whitespace.rs +++ b/src/test/auxiliary/svh-a-whitespace.rs @@ -14,16 +14,13 @@ //! (#14132). #![crate_name = "a"] -#![feature(core)] - -use std::marker::MarkerTrait; macro_rules! three { () => { 3 } } -pub trait U : MarkerTrait {} -pub trait V : MarkerTrait {} +pub trait U {} +pub trait V {} impl U for () {} impl V for () {} diff --git a/src/test/auxiliary/trait_impl_conflict.rs b/src/test/auxiliary/trait_impl_conflict.rs index 0adedfd4eeb22..c3ecbb014dc6b 100644 --- a/src/test/auxiliary/trait_impl_conflict.rs +++ b/src/test/auxiliary/trait_impl_conflict.rs @@ -8,9 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(core)] - -pub trait Foo : ::std::marker::MarkerTrait { +pub trait Foo { } impl Foo for isize { diff --git a/src/test/auxiliary/typeck_default_trait_impl_cross_crate_coherence_lib.rs b/src/test/auxiliary/typeck_default_trait_impl_cross_crate_coherence_lib.rs index 5a7a3e7bcc694..2e425ac96c55f 100644 --- a/src/test/auxiliary/typeck_default_trait_impl_cross_crate_coherence_lib.rs +++ b/src/test/auxiliary/typeck_default_trait_impl_cross_crate_coherence_lib.rs @@ -11,9 +11,7 @@ #![feature(optin_builtin_traits, core)] #![crate_type = "rlib"] -use std::marker::MarkerTrait; - -pub trait DefaultedTrait : MarkerTrait { } +pub trait DefaultedTrait { } impl DefaultedTrait for .. { } pub struct Something { t: T } diff --git a/src/test/compile-fail/associated-types-eq-expr-path.rs b/src/test/compile-fail/associated-types-eq-expr-path.rs index 0d68b960f3135..1f9dfdb18470b 100644 --- a/src/test/compile-fail/associated-types-eq-expr-path.rs +++ b/src/test/compile-fail/associated-types-eq-expr-path.rs @@ -10,7 +10,7 @@ // Check that an associated type cannot be bound in an expression path. -trait Foo : ::std::marker::MarkerTrait { +trait Foo { type A; fn bar() -> isize; } diff --git a/src/test/compile-fail/associated-types-issue-17359.rs b/src/test/compile-fail/associated-types-issue-17359.rs index 5c36e3356a5c0..82258f124d323 100644 --- a/src/test/compile-fail/associated-types-issue-17359.rs +++ b/src/test/compile-fail/associated-types-issue-17359.rs @@ -11,7 +11,7 @@ // Test that we do not ICE when an impl is missing an associated type (and that we report // a useful error, of course). -trait Trait : ::std::marker::MarkerTrait { +trait Trait { type Type; } diff --git a/src/test/compile-fail/associated-types-multiple-types-one-trait.rs b/src/test/compile-fail/associated-types-multiple-types-one-trait.rs index 5632f148da67c..9436f825de89d 100644 --- a/src/test/compile-fail/associated-types-multiple-types-one-trait.rs +++ b/src/test/compile-fail/associated-types-multiple-types-one-trait.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -trait Foo : ::std::marker::MarkerTrait { +trait Foo { type X; type Y; } diff --git a/src/test/compile-fail/associated-types-no-suitable-supertrait-2.rs b/src/test/compile-fail/associated-types-no-suitable-supertrait-2.rs index 5f1cd2444d3c4..bda16c8a85de1 100644 --- a/src/test/compile-fail/associated-types-no-suitable-supertrait-2.rs +++ b/src/test/compile-fail/associated-types-no-suitable-supertrait-2.rs @@ -19,7 +19,7 @@ // which checks that the trait interface itself is not considered an // error as long as all impls satisfy the constraint. -trait Get : ::std::marker::MarkerTrait { +trait Get { type Value; } diff --git a/src/test/compile-fail/associated-types-no-suitable-supertrait.rs b/src/test/compile-fail/associated-types-no-suitable-supertrait.rs index 24429a482057c..233532a608580 100644 --- a/src/test/compile-fail/associated-types-no-suitable-supertrait.rs +++ b/src/test/compile-fail/associated-types-no-suitable-supertrait.rs @@ -19,7 +19,7 @@ // which checks that the trait interface itself is not considered an // error as long as all impls satisfy the constraint. -trait Get : ::std::marker::MarkerTrait { +trait Get { type Value; } diff --git a/src/test/compile-fail/associated-types-unconstrained.rs b/src/test/compile-fail/associated-types-unconstrained.rs index 8832028f9aba1..aecbf217a5b25 100644 --- a/src/test/compile-fail/associated-types-unconstrained.rs +++ b/src/test/compile-fail/associated-types-unconstrained.rs @@ -10,7 +10,7 @@ // Check that an associated type cannot be bound in an expression path. -trait Foo : ::std::marker::MarkerTrait { +trait Foo { type A; fn bar() -> isize; } diff --git a/src/test/compile-fail/bad-sized.rs b/src/test/compile-fail/bad-sized.rs index 5878e9a9f649b..fca74e457c21e 100644 --- a/src/test/compile-fail/bad-sized.rs +++ b/src/test/compile-fail/bad-sized.rs @@ -10,7 +10,7 @@ use std::cell::RefCell; -trait Trait : ::std::marker::MarkerTrait {} +trait Trait {} pub fn main() { let x: Vec = Vec::new(); diff --git a/src/test/compile-fail/coherence-blanket-conflicts-with-blanket-implemented.rs b/src/test/compile-fail/coherence-blanket-conflicts-with-blanket-implemented.rs index 98a9c713e84c3..b771b959d3e50 100644 --- a/src/test/compile-fail/coherence-blanket-conflicts-with-blanket-implemented.rs +++ b/src/test/compile-fail/coherence-blanket-conflicts-with-blanket-implemented.rs @@ -10,7 +10,6 @@ use std::fmt::Debug; use std::default::Default; -use std::marker::MarkerTrait; // Test that two blanket impls conflict (at least without negative // bounds). After all, some other crate could implement Even or Odd @@ -20,9 +19,9 @@ trait MyTrait { fn get(&self) -> usize; } -trait Even : MarkerTrait { } +trait Even { } -trait Odd : MarkerTrait { } +trait Odd { } impl Even for isize { } diff --git a/src/test/compile-fail/coherence-blanket-conflicts-with-blanket-unimplemented.rs b/src/test/compile-fail/coherence-blanket-conflicts-with-blanket-unimplemented.rs index 57d25a3bf586d..d3b0e7f10b91b 100644 --- a/src/test/compile-fail/coherence-blanket-conflicts-with-blanket-unimplemented.rs +++ b/src/test/compile-fail/coherence-blanket-conflicts-with-blanket-unimplemented.rs @@ -19,9 +19,9 @@ trait MyTrait { fn get(&self) -> usize; } -trait Even : ::std::marker::MarkerTrait { } +trait Even {} -trait Odd : ::std::marker::MarkerTrait { } +trait Odd {} impl MyTrait for T { //~ ERROR E0119 fn get(&self) -> usize { 0 } diff --git a/src/test/compile-fail/coherence-conflicting-negative-trait-impl.rs b/src/test/compile-fail/coherence-conflicting-negative-trait-impl.rs index a225f6cf47304..55c9ba2a0e89a 100644 --- a/src/test/compile-fail/coherence-conflicting-negative-trait-impl.rs +++ b/src/test/compile-fail/coherence-conflicting-negative-trait-impl.rs @@ -10,7 +10,7 @@ #![feature(optin_builtin_traits)] -trait MyTrait : ::std::marker::MarkerTrait {} +trait MyTrait {} struct TestType(::std::marker::PhantomData); diff --git a/src/test/compile-fail/coherence-default-trait-impl.rs b/src/test/compile-fail/coherence-default-trait-impl.rs index 062a4a43b694b..cccc8b05b3038 100644 --- a/src/test/compile-fail/coherence-default-trait-impl.rs +++ b/src/test/compile-fail/coherence-default-trait-impl.rs @@ -10,21 +10,19 @@ #![feature(optin_builtin_traits)] -use std::marker::MarkerTrait; - -trait MyTrait: MarkerTrait {} +trait MyTrait {} impl MyTrait for .. {} impl MyTrait for .. {} //~^ ERROR conflicting implementations for trait `MyTrait` -trait MySafeTrait: MarkerTrait {} +trait MySafeTrait {} unsafe impl MySafeTrait for .. {} //~^ ERROR implementing the trait `MySafeTrait` is not unsafe -unsafe trait MyUnsafeTrait: MarkerTrait {} +unsafe trait MyUnsafeTrait {} impl MyUnsafeTrait for .. {} //~^ ERROR the trait `MyUnsafeTrait` requires an `unsafe impl` declaration diff --git a/src/test/compile-fail/coherence_copy_like_err_fundamental_struct_tuple.rs b/src/test/compile-fail/coherence_copy_like_err_fundamental_struct_tuple.rs index c4e95e772356a..a6b62d17bc4e6 100644 --- a/src/test/compile-fail/coherence_copy_like_err_fundamental_struct_tuple.rs +++ b/src/test/compile-fail/coherence_copy_like_err_fundamental_struct_tuple.rs @@ -17,11 +17,9 @@ extern crate coherence_copy_like_lib as lib; -use std::marker::MarkerTrait; - struct MyType { x: i32 } -trait MyTrait : MarkerTrait { } +trait MyTrait { } impl MyTrait for T { } //~ ERROR E0119 diff --git a/src/test/compile-fail/coherence_copy_like_err_struct.rs b/src/test/compile-fail/coherence_copy_like_err_struct.rs index f768a475ee820..5a9f440f8bb6a 100644 --- a/src/test/compile-fail/coherence_copy_like_err_struct.rs +++ b/src/test/compile-fail/coherence_copy_like_err_struct.rs @@ -15,11 +15,9 @@ extern crate coherence_copy_like_lib as lib; -use std::marker::MarkerTrait; - struct MyType { x: i32 } -trait MyTrait : MarkerTrait { } +trait MyTrait { } impl MyTrait for T { } //~ ERROR E0119 // `MyStruct` is not declared fundamental, therefore this would diff --git a/src/test/compile-fail/coherence_copy_like_err_tuple.rs b/src/test/compile-fail/coherence_copy_like_err_tuple.rs index 0c78fffd2dfab..ee0d5550fd61f 100644 --- a/src/test/compile-fail/coherence_copy_like_err_tuple.rs +++ b/src/test/compile-fail/coherence_copy_like_err_tuple.rs @@ -15,11 +15,9 @@ extern crate coherence_copy_like_lib as lib; -use std::marker::MarkerTrait; - struct MyType { x: i32 } -trait MyTrait : MarkerTrait { } +trait MyTrait { } impl MyTrait for T { } //~ ERROR E0119 // Tuples are not fundamental, therefore this would require that diff --git a/src/test/compile-fail/dst-bad-coerce2.rs b/src/test/compile-fail/dst-bad-coerce2.rs index aa687266acb8f..160197368d6d9 100644 --- a/src/test/compile-fail/dst-bad-coerce2.rs +++ b/src/test/compile-fail/dst-bad-coerce2.rs @@ -15,7 +15,7 @@ struct Fat { } struct Foo; -trait Bar : ::std::marker::MarkerTrait {} +trait Bar {} impl Bar for Foo {} pub fn main() { diff --git a/src/test/compile-fail/dst-bad-coercions.rs b/src/test/compile-fail/dst-bad-coercions.rs index 8ec1034bc4d28..b30eada162b84 100644 --- a/src/test/compile-fail/dst-bad-coercions.rs +++ b/src/test/compile-fail/dst-bad-coercions.rs @@ -10,10 +10,8 @@ // Test implicit coercions involving DSTs and raw pointers. -use std::marker::MarkerTrait; - struct S; -trait T : MarkerTrait {} +trait T {} impl T for S {} struct Foo { diff --git a/src/test/compile-fail/implicit-method-bind.rs b/src/test/compile-fail/implicit-method-bind.rs index 6a9c304805274..e116966670d2b 100644 --- a/src/test/compile-fail/implicit-method-bind.rs +++ b/src/test/compile-fail/implicit-method-bind.rs @@ -8,8 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use std::num::SignedInt; - fn main() { - let _f = 10.abs; //~ ERROR attempted to take value of method + let _f = 10i32.abs; //~ ERROR attempted to take value of method } diff --git a/src/test/compile-fail/issue-13853.rs b/src/test/compile-fail/issue-13853.rs index cd3f337c4ab65..251da2c6b3ee9 100644 --- a/src/test/compile-fail/issue-13853.rs +++ b/src/test/compile-fail/issue-13853.rs @@ -8,9 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use std::marker::MarkerTrait; - -trait Node : MarkerTrait { +trait Node { fn zomg(); } diff --git a/src/test/compile-fail/issue-14853.rs b/src/test/compile-fail/issue-14853.rs index 0b846651acf46..51deb99a4f2cd 100644 --- a/src/test/compile-fail/issue-14853.rs +++ b/src/test/compile-fail/issue-14853.rs @@ -9,9 +9,8 @@ // except according to those terms. use std::fmt::Debug; -use std::marker::MarkerTrait; -trait Str : MarkerTrait {} +trait Str {} trait Something { fn yay(_: Option, thing: &[T]); diff --git a/src/test/compile-fail/issue-16747.rs b/src/test/compile-fail/issue-16747.rs index b4abef0bd280b..a3529c9ea90b6 100644 --- a/src/test/compile-fail/issue-16747.rs +++ b/src/test/compile-fail/issue-16747.rs @@ -8,9 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use std::marker::MarkerTrait; - -trait ListItem<'a> : MarkerTrait { +trait ListItem<'a> { fn list_name() -> &'a str; } diff --git a/src/test/compile-fail/issue-18107.rs b/src/test/compile-fail/issue-18107.rs index 60ab616d5983b..6300a1dc15d60 100644 --- a/src/test/compile-fail/issue-18107.rs +++ b/src/test/compile-fail/issue-18107.rs @@ -8,9 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use std::marker::MarkerTrait; - -pub trait AbstractRenderer : MarkerTrait {} +pub trait AbstractRenderer {} fn _create_render(_: &()) -> AbstractRenderer diff --git a/src/test/compile-fail/issue-18389.rs b/src/test/compile-fail/issue-18389.rs index 271c31bd37548..41be78dd7b96e 100644 --- a/src/test/compile-fail/issue-18389.rs +++ b/src/test/compile-fail/issue-18389.rs @@ -8,14 +8,11 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(unboxed_closures)] - use std::any::Any; use std::any::TypeId; -use std::marker::MarkerTrait; -pub trait Pt : MarkerTrait {} -pub trait Rt : MarkerTrait {} +pub trait Pt {} +pub trait Rt {} trait Private { fn call(&self, p: P, r: R); diff --git a/src/test/compile-fail/issue-18611.rs b/src/test/compile-fail/issue-18611.rs index e81a576fa63d5..a662e9ca98ee8 100644 --- a/src/test/compile-fail/issue-18611.rs +++ b/src/test/compile-fail/issue-18611.rs @@ -8,13 +8,11 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use std::marker::MarkerTrait; - fn add_state(op: ::State) { //~^ ERROR the trait `HasState` is not implemented for the type `isize` } -trait HasState : MarkerTrait { +trait HasState { type State; } diff --git a/src/test/compile-fail/issue-18819.rs b/src/test/compile-fail/issue-18819.rs index 01fc4fef03b1d..d89b2c6ce8cb0 100644 --- a/src/test/compile-fail/issue-18819.rs +++ b/src/test/compile-fail/issue-18819.rs @@ -8,9 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use std::marker::MarkerTrait; - -trait Foo : MarkerTrait { +trait Foo { type Item; } diff --git a/src/test/compile-fail/issue-2063.rs b/src/test/compile-fail/issue-2063.rs index 9e63cc203f4d5..20bd8af7c3ef5 100644 --- a/src/test/compile-fail/issue-2063.rs +++ b/src/test/compile-fail/issue-2063.rs @@ -12,11 +12,9 @@ // cause compiler to loop. Note that no instances // of such a type could ever be constructed. -use std::marker::MarkerTrait; - struct t(Box); //~ ERROR this type cannot be instantiated -trait to_str_2 : MarkerTrait { +trait to_str_2 { fn my_to_string() -> String; } diff --git a/src/test/compile-fail/issue-20831-debruijn.rs b/src/test/compile-fail/issue-20831-debruijn.rs index 5b623ac377b21..a38278eae2411 100644 --- a/src/test/compile-fail/issue-20831-debruijn.rs +++ b/src/test/compile-fail/issue-20831-debruijn.rs @@ -14,10 +14,9 @@ // away. use std::cell::RefCell; -use std::marker::MarkerTrait; use std::ops::{Shl, Shr}; -pub trait Subscriber : MarkerTrait { +pub trait Subscriber { type Input; } diff --git a/src/test/compile-fail/issue-23080-2.rs b/src/test/compile-fail/issue-23080-2.rs index ff5ac9de8d944..b77230a8b340d 100644 --- a/src/test/compile-fail/issue-23080-2.rs +++ b/src/test/compile-fail/issue-23080-2.rs @@ -12,9 +12,7 @@ #![feature(optin_builtin_traits)] -use std::marker::MarkerTrait; - -unsafe trait Trait: MarkerTrait { +unsafe trait Trait { //~^ error: traits with default impls (`e.g. unsafe impl Trait for ..`) must have no methods or associated items type Output; } diff --git a/src/test/compile-fail/issue-3702-2.rs b/src/test/compile-fail/issue-3702-2.rs index 2b732899ea42f..026ee89c0b2b5 100644 --- a/src/test/compile-fail/issue-3702-2.rs +++ b/src/test/compile-fail/issue-3702-2.rs @@ -8,7 +8,12 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use std::num::ToPrimitive; +pub trait ToPrimitive { + fn to_int(&self) -> isize { 0 } +} + +impl ToPrimitive for i32 {} +impl ToPrimitive for isize {} trait Add { fn to_int(&self) -> isize; diff --git a/src/test/compile-fail/issue-5035-2.rs b/src/test/compile-fail/issue-5035-2.rs index d316b44794ad6..9e324cdd61eb0 100644 --- a/src/test/compile-fail/issue-5035-2.rs +++ b/src/test/compile-fail/issue-5035-2.rs @@ -8,9 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use std::marker::MarkerTrait; - -trait I : MarkerTrait {} +trait I {} type K = I+'static; fn foo(_x: K) {} //~ ERROR: the trait `core::marker::Sized` is not implemented diff --git a/src/test/compile-fail/issue-5883.rs b/src/test/compile-fail/issue-5883.rs index b0db990619535..9ff957b6e6dea 100644 --- a/src/test/compile-fail/issue-5883.rs +++ b/src/test/compile-fail/issue-5883.rs @@ -8,9 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use std::marker::MarkerTrait; - -trait A : MarkerTrait {} +trait A {} struct Struct { r: A+'static @@ -22,6 +20,6 @@ fn new_struct(r: A+'static) Struct { r: r } } -trait Curve : MarkerTrait {} +trait Curve {} enum E {X(Curve+'static)} fn main() {} diff --git a/src/test/compile-fail/issue-7575.rs b/src/test/compile-fail/issue-7575.rs index 9c019f6ec47fb..6b320f400a809 100644 --- a/src/test/compile-fail/issue-7575.rs +++ b/src/test/compile-fail/issue-7575.rs @@ -10,14 +10,12 @@ // Test the mechanism for warning about possible missing `self` declarations. -use std::marker::MarkerTrait; - trait CtxtFn { fn f8(self, usize) -> usize; fn f9(usize) -> usize; //~ NOTE candidate } -trait OtherTrait : MarkerTrait { +trait OtherTrait { fn f9(usize) -> usize; //~ NOTE candidate } @@ -26,7 +24,7 @@ trait OtherTrait : MarkerTrait { // declaration to match against, so we wind up prisizeing it as a // candidate. This seems not unreasonable -- perhaps the user meant to // implement it, after all. -trait UnusedTrait : MarkerTrait { +trait UnusedTrait { fn f9(usize) -> usize; //~ NOTE candidate } @@ -54,7 +52,7 @@ impl Myisize { } } -trait ManyImplTrait : MarkerTrait { +trait ManyImplTrait { fn is_str() -> bool { //~ NOTE candidate false } diff --git a/src/test/compile-fail/kindck-copy.rs b/src/test/compile-fail/kindck-copy.rs index 1925caf6870ee..d43ddff6b9500 100644 --- a/src/test/compile-fail/kindck-copy.rs +++ b/src/test/compile-fail/kindck-copy.rs @@ -10,12 +10,11 @@ // Test which of the builtin types are considered POD. -use std::marker::MarkerTrait; use std::rc::Rc; fn assert_copy() { } -trait Dummy : MarkerTrait { } +trait Dummy { } #[derive(Copy, Clone)] struct MyStruct { diff --git a/src/test/compile-fail/kindck-impl-type-params-2.rs b/src/test/compile-fail/kindck-impl-type-params-2.rs index fd0789421e004..66297d70ef505 100644 --- a/src/test/compile-fail/kindck-impl-type-params-2.rs +++ b/src/test/compile-fail/kindck-impl-type-params-2.rs @@ -10,9 +10,7 @@ #![feature(box_syntax)] -use std::marker::MarkerTrait; - -trait Foo : MarkerTrait { +trait Foo { } impl Foo for T { diff --git a/src/test/compile-fail/kindck-send-object.rs b/src/test/compile-fail/kindck-send-object.rs index 0c68401bb2b95..570f7ad7fe3bf 100644 --- a/src/test/compile-fail/kindck-send-object.rs +++ b/src/test/compile-fail/kindck-send-object.rs @@ -12,10 +12,8 @@ // in this file all test the "kind" violates detected during kindck. // See all `regions-bounded-by-send.rs` -use std::marker::MarkerTrait; - fn assert_send() { } -trait Dummy : MarkerTrait { } +trait Dummy { } trait Message : Send { } // careful with object types, who knows what they close over... diff --git a/src/test/compile-fail/kindck-send-object1.rs b/src/test/compile-fail/kindck-send-object1.rs index f86eac8b16bd2..48d5215b7085b 100644 --- a/src/test/compile-fail/kindck-send-object1.rs +++ b/src/test/compile-fail/kindck-send-object1.rs @@ -12,10 +12,8 @@ // is broken into two parts because some errors occur in distinct // phases in the compiler. See kindck-send-object2.rs as well! -use std::marker::MarkerTrait; - fn assert_send() { } -trait Dummy : MarkerTrait { } +trait Dummy { } // careful with object types, who knows what they close over... fn test51<'a>() { diff --git a/src/test/compile-fail/kindck-send-object2.rs b/src/test/compile-fail/kindck-send-object2.rs index 08516e67318ce..d3d166e2a6916 100644 --- a/src/test/compile-fail/kindck-send-object2.rs +++ b/src/test/compile-fail/kindck-send-object2.rs @@ -10,10 +10,8 @@ // Continue kindck-send-object1.rs. -use std::marker::MarkerTrait; - fn assert_send() { } -trait Dummy : MarkerTrait { } +trait Dummy { } fn test50() { assert_send::<&'static Dummy>(); //~ ERROR the trait `core::marker::Sync` is not implemented diff --git a/src/test/compile-fail/lint-visible-private-types.rs b/src/test/compile-fail/lint-visible-private-types.rs index 918b4ee209ca7..c6dc3b70bef37 100644 --- a/src/test/compile-fail/lint-visible-private-types.rs +++ b/src/test/compile-fail/lint-visible-private-types.rs @@ -105,7 +105,7 @@ impl PrivTrait for (Private,) { fn bar(&self) -> Private { panic!() } } -pub trait ParamTrait : marker::MarkerTrait { +pub trait ParamTrait { fn foo() -> T; } diff --git a/src/test/compile-fail/object-does-not-impl-trait.rs b/src/test/compile-fail/object-does-not-impl-trait.rs index 607ab13d12201..efbf3782f9796 100644 --- a/src/test/compile-fail/object-does-not-impl-trait.rs +++ b/src/test/compile-fail/object-does-not-impl-trait.rs @@ -11,9 +11,7 @@ // Test that an object type `Box` is not considered to implement the // trait `Foo`. Issue #5087. -use std::marker::MarkerTrait; - -trait Foo : MarkerTrait {} +trait Foo {} fn take_foo(f: F) {} fn take_object(f: Box) { take_foo(f); } //~^ ERROR the trait `Foo` is not implemented diff --git a/src/test/compile-fail/object-safety-no-static.rs b/src/test/compile-fail/object-safety-no-static.rs index aae829ec7b563..6a010d49692d2 100644 --- a/src/test/compile-fail/object-safety-no-static.rs +++ b/src/test/compile-fail/object-safety-no-static.rs @@ -11,7 +11,7 @@ // Check that we correctly prevent users from making trait objects // from traits with static methods. -trait Foo : ::std::marker::MarkerTrait { +trait Foo { fn foo(); } diff --git a/src/test/compile-fail/phantom-oibit.rs b/src/test/compile-fail/phantom-oibit.rs index c912d084daa86..071b4db40f86f 100644 --- a/src/test/compile-fail/phantom-oibit.rs +++ b/src/test/compile-fail/phantom-oibit.rs @@ -14,9 +14,9 @@ #![feature(optin_builtin_traits)] -use std::marker::{MarkerTrait, PhantomData}; +use std::marker::{PhantomData}; -unsafe trait Zen: MarkerTrait {} +unsafe trait Zen {} unsafe impl Zen for .. {} diff --git a/src/test/compile-fail/privacy-ns2.rs b/src/test/compile-fail/privacy-ns2.rs index 67bb566ea682c..7fe0574ab7d9a 100644 --- a/src/test/compile-fail/privacy-ns2.rs +++ b/src/test/compile-fail/privacy-ns2.rs @@ -17,9 +17,7 @@ // public type, private value pub mod foo1 { - use std::marker::MarkerTrait; - - pub trait Bar : MarkerTrait { + pub trait Bar { } pub struct Baz; @@ -41,7 +39,7 @@ fn test_list1() { // private type, public value pub mod foo2 { - trait Bar : ::std::marker::MarkerTrait { + trait Bar { } pub struct Baz; @@ -62,7 +60,7 @@ fn test_list2() { // neither public pub mod foo3 { - trait Bar : ::std::marker::MarkerTrait { + trait Bar { } pub struct Baz; diff --git a/src/test/compile-fail/region-object-lifetime-in-coercion.rs b/src/test/compile-fail/region-object-lifetime-in-coercion.rs index 1bb2bb5a15450..f95ee405895a9 100644 --- a/src/test/compile-fail/region-object-lifetime-in-coercion.rs +++ b/src/test/compile-fail/region-object-lifetime-in-coercion.rs @@ -11,7 +11,7 @@ // Test that attempts to implicitly coerce a value into an // object respect the lifetime bound on the object type. -trait Foo : ::std::marker::MarkerTrait {} +trait Foo {} impl<'a> Foo for &'a [u8] {} // FIXME (#22405): Replace `Box::new` with `box` here when/if possible. diff --git a/src/test/compile-fail/regions-close-associated-type-into-object.rs b/src/test/compile-fail/regions-close-associated-type-into-object.rs index f80b0ffa5aadf..fdc97ecaf21e2 100644 --- a/src/test/compile-fail/regions-close-associated-type-into-object.rs +++ b/src/test/compile-fail/regions-close-associated-type-into-object.rs @@ -12,9 +12,7 @@ // FIXME (#22405): Replace `Box::new` with `box` here when/if possible. -use std::marker::MarkerTrait; - -trait X : MarkerTrait {} +trait X {} trait Iter { type Item: X; diff --git a/src/test/compile-fail/regions-close-over-borrowed-ref-in-obj.rs b/src/test/compile-fail/regions-close-over-borrowed-ref-in-obj.rs index 2341d2397c9b0..25b8137d29cad 100644 --- a/src/test/compile-fail/regions-close-over-borrowed-ref-in-obj.rs +++ b/src/test/compile-fail/regions-close-over-borrowed-ref-in-obj.rs @@ -10,9 +10,7 @@ #![feature(box_syntax)] -use std::marker::MarkerTrait; - -trait Foo : MarkerTrait { } +trait Foo { } impl<'a> Foo for &'a isize { } diff --git a/src/test/compile-fail/trait-as-struct-constructor.rs b/src/test/compile-fail/trait-as-struct-constructor.rs index 1fd711ca4fb2c..b864e6ca9578b 100644 --- a/src/test/compile-fail/trait-as-struct-constructor.rs +++ b/src/test/compile-fail/trait-as-struct-constructor.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -trait TraitNotAStruct : ::std::marker::MarkerTrait { } +trait TraitNotAStruct {} fn main() { TraitNotAStruct{ value: 0 }; diff --git a/src/test/compile-fail/trait-bounds-on-structs-and-enums.rs b/src/test/compile-fail/trait-bounds-on-structs-and-enums.rs index ce0a7d3bb36cf..c18c5b386e8b2 100644 --- a/src/test/compile-fail/trait-bounds-on-structs-and-enums.rs +++ b/src/test/compile-fail/trait-bounds-on-structs-and-enums.rs @@ -8,9 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use std::marker::MarkerTrait; - -trait Trait : MarkerTrait {} +trait Trait {} struct Foo { x: T, diff --git a/src/test/compile-fail/trait-bounds-sugar.rs b/src/test/compile-fail/trait-bounds-sugar.rs index e4058a0943aad..0a36fcbed6905 100644 --- a/src/test/compile-fail/trait-bounds-sugar.rs +++ b/src/test/compile-fail/trait-bounds-sugar.rs @@ -10,9 +10,7 @@ // Tests for "default" bounds inferred for traits with no bounds list. -use std::marker::MarkerTrait; - -trait Foo : MarkerTrait {} +trait Foo {} fn a(_x: Box) { } diff --git a/src/test/compile-fail/trait-impl-1.rs b/src/test/compile-fail/trait-impl-1.rs index 2f4793b4d888f..dadcbd5bce710 100644 --- a/src/test/compile-fail/trait-impl-1.rs +++ b/src/test/compile-fail/trait-impl-1.rs @@ -12,9 +12,7 @@ // trait impl is only applied to a trait object, not concrete types which implement // the trait. -use std::marker::MarkerTrait; - -trait T : MarkerTrait {} +trait T {} impl<'a> T+'a { fn foo(&self) {} diff --git a/src/test/compile-fail/type-params-in-different-spaces-1.rs b/src/test/compile-fail/type-params-in-different-spaces-1.rs index 88d8788d63a3d..155b835bbc6e0 100644 --- a/src/test/compile-fail/type-params-in-different-spaces-1.rs +++ b/src/test/compile-fail/type-params-in-different-spaces-1.rs @@ -8,9 +8,9 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use std::num::Int; +use std::ops::Add; -trait BrokenAdd: Int { +trait BrokenAdd: Copy + Add { fn broken_add(&self, rhs: T) -> Self { *self + rhs //~ ERROR mismatched types //~| expected `Self` @@ -20,7 +20,7 @@ trait BrokenAdd: Int { } } -impl BrokenAdd for T {} +impl> BrokenAdd for T {} pub fn main() { let foo: u8 = 0; diff --git a/src/test/compile-fail/typeck-default-trait-impl-constituent-types-2.rs b/src/test/compile-fail/typeck-default-trait-impl-constituent-types-2.rs index 0f3453da43137..a27f7f7ebbe0f 100644 --- a/src/test/compile-fail/typeck-default-trait-impl-constituent-types-2.rs +++ b/src/test/compile-fail/typeck-default-trait-impl-constituent-types-2.rs @@ -10,9 +10,7 @@ #![feature(optin_builtin_traits)] -use std::marker::MarkerTrait; - -trait MyTrait: MarkerTrait {} +trait MyTrait {} impl MyTrait for .. {} diff --git a/src/test/compile-fail/typeck-default-trait-impl-constituent-types.rs b/src/test/compile-fail/typeck-default-trait-impl-constituent-types.rs index 524f467e01700..24819bb4f08d6 100644 --- a/src/test/compile-fail/typeck-default-trait-impl-constituent-types.rs +++ b/src/test/compile-fail/typeck-default-trait-impl-constituent-types.rs @@ -10,9 +10,7 @@ #![feature(optin_builtin_traits)] -use std::marker::MarkerTrait; - -trait MyTrait: MarkerTrait {} +trait MyTrait {} impl MyTrait for .. {} impl !MyTrait for *mut T {} diff --git a/src/test/compile-fail/typeck-default-trait-impl-negation.rs b/src/test/compile-fail/typeck-default-trait-impl-negation.rs index a1ca0e3e0fada..4b91d0b7a736c 100644 --- a/src/test/compile-fail/typeck-default-trait-impl-negation.rs +++ b/src/test/compile-fail/typeck-default-trait-impl-negation.rs @@ -10,13 +10,11 @@ #![feature(optin_builtin_traits)] -use std::marker::MarkerTrait; - -trait MyTrait: MarkerTrait {} +trait MyTrait {} impl MyTrait for .. {} -unsafe trait MyUnsafeTrait: MarkerTrait {} +unsafe trait MyUnsafeTrait {} unsafe impl MyUnsafeTrait for .. {} diff --git a/src/test/compile-fail/typeck-default-trait-impl-precedence.rs b/src/test/compile-fail/typeck-default-trait-impl-precedence.rs index 4006eb2e83ed9..c67fc92313c3a 100644 --- a/src/test/compile-fail/typeck-default-trait-impl-precedence.rs +++ b/src/test/compile-fail/typeck-default-trait-impl-precedence.rs @@ -15,15 +15,13 @@ #![feature(optin_builtin_traits)] -use std::marker::MarkerTrait; - -trait Defaulted : MarkerTrait { } +trait Defaulted { } impl Defaulted for .. { } impl<'a,T:Signed> Defaulted for &'a T { } impl<'a,T:Signed> Defaulted for &'a mut T { } fn is_defaulted() { } -trait Signed : MarkerTrait { } +trait Signed { } impl Signed for i32 { } fn main() { diff --git a/src/test/compile-fail/typeck-default-trait-impl-superregion.rs b/src/test/compile-fail/typeck-default-trait-impl-superregion.rs index 4a6a77ac7b440..aa918119fbcee 100644 --- a/src/test/compile-fail/typeck-default-trait-impl-superregion.rs +++ b/src/test/compile-fail/typeck-default-trait-impl-superregion.rs @@ -13,8 +13,6 @@ #![feature(optin_builtin_traits)] -use std::marker::MarkerTrait; - trait MyTrait : 'static {} impl MyTrait for .. {} diff --git a/src/test/compile-fail/typeck-default-trait-impl-supertrait.rs b/src/test/compile-fail/typeck-default-trait-impl-supertrait.rs index 7f24058e475fa..c9bfdff6c0e49 100644 --- a/src/test/compile-fail/typeck-default-trait-impl-supertrait.rs +++ b/src/test/compile-fail/typeck-default-trait-impl-supertrait.rs @@ -13,9 +13,7 @@ #![feature(optin_builtin_traits)] -use std::marker::MarkerTrait; - -trait NotImplemented: MarkerTrait { } +trait NotImplemented { } trait MyTrait : NotImplemented {} diff --git a/src/test/compile-fail/typeck-default-trait-impl-trait-where-clause.rs b/src/test/compile-fail/typeck-default-trait-impl-trait-where-clause.rs index c970aaaf5d471..4f572e87639f0 100644 --- a/src/test/compile-fail/typeck-default-trait-impl-trait-where-clause.rs +++ b/src/test/compile-fail/typeck-default-trait-impl-trait-where-clause.rs @@ -15,11 +15,9 @@ #![feature(optin_builtin_traits)] -use std::marker::MarkerTrait; +trait NotImplemented { } -trait NotImplemented: MarkerTrait { } - -trait MyTrait: MarkerTrait +trait MyTrait where Option : NotImplemented {} diff --git a/src/test/compile-fail/unsized6.rs b/src/test/compile-fail/unsized6.rs index f31a6ffdc0d7c..3f18f359d306e 100644 --- a/src/test/compile-fail/unsized6.rs +++ b/src/test/compile-fail/unsized6.rs @@ -10,9 +10,7 @@ // Test `?Sized` local variables. -use std::marker; - -trait T : marker::MarkerTrait { } +trait T {} fn f1(x: &X) { let _: X; // <-- this is OK, no bindings created, no initializer. diff --git a/src/test/compile-fail/unsized7.rs b/src/test/compile-fail/unsized7.rs index 6ea3d0720eeeb..0245a1b5cf2c8 100644 --- a/src/test/compile-fail/unsized7.rs +++ b/src/test/compile-fail/unsized7.rs @@ -10,9 +10,7 @@ // Test sized-ness checking in substitution in impls. -use std::marker::MarkerTrait; - -trait T : MarkerTrait {} +trait T {} // I would like these to fail eventually. // impl - bounded diff --git a/src/test/run-make/save-analysis/foo.rs b/src/test/run-make/save-analysis/foo.rs index fe0f32d97d6b1..4d75e58aad938 100644 --- a/src/test/run-make/save-analysis/foo.rs +++ b/src/test/run-make/save-analysis/foo.rs @@ -25,8 +25,6 @@ use sub::sub2 as msalias; use sub::sub2; use sub::sub2::nested_struct as sub_struct; use std::num::One; -use std::num::cast; -use std::num::{from_int,from_i8,from_i32}; use std::mem::size_of; @@ -42,7 +40,6 @@ fn test_alias(i: Option<::Item>) { // import tests fn foo(x: &One) {} - let _: Option = from_i32(45); let x = 42; diff --git a/src/test/run-pass/associated-types-basic.rs b/src/test/run-pass/associated-types-basic.rs index 06521e0ec78e8..2617a05fe2414 100644 --- a/src/test/run-pass/associated-types-basic.rs +++ b/src/test/run-pass/associated-types-basic.rs @@ -8,12 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. - -#![feature(core)] - -use std::marker::MarkerTrait; - -trait Foo : MarkerTrait { +trait Foo { type T; } diff --git a/src/test/run-pass/associated-types-issue-20371.rs b/src/test/run-pass/associated-types-issue-20371.rs index a601dc0739a46..c93a0b76a9560 100644 --- a/src/test/run-pass/associated-types-issue-20371.rs +++ b/src/test/run-pass/associated-types-issue-20371.rs @@ -13,10 +13,6 @@ // pretty-expanded FIXME #23616 -#![feature(core)] - -use std::marker::MarkerTrait; - impl X for f64 { type Y = isize; } -trait X : MarkerTrait { type Y; } +trait X { type Y; } fn main() {} diff --git a/src/test/run-pass/associated-types-nested-projections.rs b/src/test/run-pass/associated-types-nested-projections.rs index a26b428a4eacf..83f0d360e6122 100644 --- a/src/test/run-pass/associated-types-nested-projections.rs +++ b/src/test/run-pass/associated-types-nested-projections.rs @@ -14,10 +14,9 @@ #![feature(core)] -use std::marker::MarkerTrait; use std::slice; -trait Bound : MarkerTrait {} +trait Bound {} impl<'a> Bound for &'a i32 {} diff --git a/src/test/run-pass/associated-types-normalize-in-bounds-binding.rs b/src/test/run-pass/associated-types-normalize-in-bounds-binding.rs index d95ad2e883471..7e2d1aa23149d 100644 --- a/src/test/run-pass/associated-types-normalize-in-bounds-binding.rs +++ b/src/test/run-pass/associated-types-normalize-in-bounds-binding.rs @@ -13,12 +13,9 @@ // pretty-expanded FIXME #23616 -#![feature(core)] #![allow(dead_code)] -use std::marker::MarkerTrait; - -pub trait Integral : MarkerTrait { +pub trait Integral { type Opposite; } diff --git a/src/test/run-pass/associated-types-project-from-type-param-via-bound-in-where-clause.rs b/src/test/run-pass/associated-types-project-from-type-param-via-bound-in-where-clause.rs index dfd468884a167..1830b41d0b506 100644 --- a/src/test/run-pass/associated-types-project-from-type-param-via-bound-in-where-clause.rs +++ b/src/test/run-pass/associated-types-project-from-type-param-via-bound-in-where-clause.rs @@ -12,17 +12,14 @@ // `Item` originates in a where-clause, not the declaration of // `T`. Issue #20300. - -#![feature(core)] - -use std::marker::{MarkerTrait, PhantomData}; +use std::marker::{PhantomData}; use std::sync::atomic::{AtomicUsize, ATOMIC_USIZE_INIT}; use std::sync::atomic::Ordering::SeqCst; static COUNTER: AtomicUsize = ATOMIC_USIZE_INIT; // Preamble. -trait Trait : MarkerTrait { type Item; } +trait Trait { type Item; } struct Struct; impl Trait for Struct { type Item = u32; diff --git a/src/test/run-pass/const-binops.rs b/src/test/run-pass/const-binops.rs index 4b32ee352311d..a29953bea887b 100644 --- a/src/test/run-pass/const-binops.rs +++ b/src/test/run-pass/const-binops.rs @@ -11,7 +11,6 @@ macro_rules! assert_approx_eq { ($a:expr, $b:expr) => ({ - use std::num::Float; let (a, b) = (&$a, &$b); assert!((*a - *b).abs() < 1.0e-6, "{} is not approximately equal to {}", *a, *b); diff --git a/src/test/run-pass/derive-no-std.rs b/src/test/run-pass/derive-no-std.rs index fbc6c28fd4a58..0234d7b0b6376 100644 --- a/src/test/run-pass/derive-no-std.rs +++ b/src/test/run-pass/derive-no-std.rs @@ -31,7 +31,6 @@ enum Bar { Quux(u32), } -#[derive(FromPrimitive)] enum Baz { A=0, B=5, } fn main() { diff --git a/src/test/run-pass/deriving-primitive.rs b/src/test/run-pass/deriving-primitive.rs deleted file mode 100644 index 4399d741cad1e..0000000000000 --- a/src/test/run-pass/deriving-primitive.rs +++ /dev/null @@ -1,39 +0,0 @@ -// Copyright 2013-2014 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -#![feature(core)] - -use std::num::FromPrimitive; -use std::isize; - -#[derive(PartialEq, FromPrimitive, Debug)] -enum A { - Foo = isize::MAX, - Bar = 1, - Baz = 3, - Qux, -} - -pub fn main() { - let x: Option = FromPrimitive::from_int(isize::MAX); - assert_eq!(x, Some(A::Foo)); - - let x: Option = FromPrimitive::from_int(1); - assert_eq!(x, Some(A::Bar)); - - let x: Option = FromPrimitive::from_int(3); - assert_eq!(x, Some(A::Baz)); - - let x: Option = FromPrimitive::from_int(4); - assert_eq!(x, Some(A::Qux)); - - let x: Option = FromPrimitive::from_int(5); - assert_eq!(x, None); -} diff --git a/src/test/run-pass/early-ret-binop-add.rs b/src/test/run-pass/early-ret-binop-add.rs index 7bd292e66f258..0a490466ef73b 100644 --- a/src/test/run-pass/early-ret-binop-add.rs +++ b/src/test/run-pass/early-ret-binop-add.rs @@ -10,8 +10,8 @@ // pretty-expanded FIXME #23616 -use std::num::Int; +use std::ops::Add; -fn wsucc(n: T) -> T { n + { return n } } +fn wsucc + Copy>(n: T) -> T { n + { return n } } pub fn main() { } diff --git a/src/test/run-pass/exponential-notation.rs b/src/test/run-pass/exponential-notation.rs deleted file mode 100644 index 4d54bb4ef7250..0000000000000 --- a/src/test/run-pass/exponential-notation.rs +++ /dev/null @@ -1,39 +0,0 @@ -// Copyright 2014 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - - -#![feature(std_misc)] - -use std::num::strconv::ExponentFormat::{ExpBin, ExpDec}; -use std::num::strconv::SignificantDigits::DigMax; -use std::num::strconv::SignFormat::{SignAll, SignNeg}; -use std::num::strconv::float_to_str_common as to_string; - -macro_rules! t { - ($a:expr, $b:expr) => { { let (r, _) = $a; assert_eq!(r, $b.to_string()); } } -} - -pub fn main() { - // Basic usage - t!(to_string(1.2345678e-5f64, 10, true, SignNeg, DigMax(6), ExpDec, false), - "1.234568e-5"); - - // Hexadecimal output - t!(to_string(7.281738281250e+01f64, 16, true, SignAll, DigMax(6), ExpBin, false), - "+1.2345p+6"); - t!(to_string(-1.777768135071e-02f64, 16, true, SignAll, DigMax(6), ExpBin, false), - "-1.2345p-6"); - - // Some denormals - t!(to_string(4.9406564584124654e-324f64, 10, true, SignNeg, DigMax(6), ExpBin, false), - "1p-1074"); - t!(to_string(2.2250738585072009e-308f64, 10, true, SignNeg, DigMax(6), ExpBin, false), - "1p-1022"); -} diff --git a/src/test/run-pass/extern-methods.rs b/src/test/run-pass/extern-methods.rs index 28a076113d1f0..421b19f2864fe 100644 --- a/src/test/run-pass/extern-methods.rs +++ b/src/test/run-pass/extern-methods.rs @@ -8,12 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. - -#![feature(core)] - -use std::marker::MarkerTrait; - -trait A : MarkerTrait { +trait A { extern "fastcall" fn test1(i: i32); extern fn test2(i: i32); } diff --git a/src/test/run-pass/float-nan.rs b/src/test/run-pass/float-nan.rs index 298f2a4719db9..856599431fd18 100644 --- a/src/test/run-pass/float-nan.rs +++ b/src/test/run-pass/float-nan.rs @@ -8,17 +8,14 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. - -#![feature(std_misc)] - -use std::num::Float; +use std::f64; pub fn main() { - let nan: f64 = Float::nan(); + let nan: f64 = f64::NAN; assert!((nan).is_nan()); - let inf: f64 = Float::infinity(); - let neg_inf: f64 = Float::neg_infinity(); + let inf: f64 = f64::INFINITY; + let neg_inf: f64 = -f64::INFINITY; assert_eq!(-inf, neg_inf); assert!( nan != nan); diff --git a/src/test/run-pass/intrinsics-math.rs b/src/test/run-pass/intrinsics-math.rs index 8db29ebaa6d3e..37ceaae373b94 100644 --- a/src/test/run-pass/intrinsics-math.rs +++ b/src/test/run-pass/intrinsics-math.rs @@ -13,7 +13,6 @@ macro_rules! assert_approx_eq { ($a:expr, $b:expr) => ({ - use std::num::Float; let (a, b) = (&$a, &$b); assert!((*a - *b).abs() < 1.0e-6, "{} is not approximately equal to {}", *a, *b); diff --git a/src/test/run-pass/issue-11736.rs b/src/test/run-pass/issue-11736.rs index fde04efc8bad9..b4621a2d053b1 100644 --- a/src/test/run-pass/issue-11736.rs +++ b/src/test/run-pass/issue-11736.rs @@ -12,10 +12,7 @@ #![feature(collections)] -extern crate collections; - use std::collections::BitVec; -use std::num::Float; fn main() { // Generate sieve of Eratosthenes for n up to 1e6 diff --git a/src/test/run-pass/issue-13105.rs b/src/test/run-pass/issue-13105.rs index 14de9e90306bc..ca68272d2d0f2 100644 --- a/src/test/run-pass/issue-13105.rs +++ b/src/test/run-pass/issue-13105.rs @@ -10,11 +10,7 @@ // pretty-expanded FIXME #23616 -#![feature(core)] - -use std::marker::MarkerTrait; - -trait Foo : MarkerTrait { +trait Foo { fn quux(u8) {} } diff --git a/src/test/run-pass/issue-8460.rs b/src/test/run-pass/issue-8460.rs index 2469dec994727..4ebc43163ede8 100644 --- a/src/test/run-pass/issue-8460.rs +++ b/src/test/run-pass/issue-8460.rs @@ -8,35 +8,30 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#![feature(zero_one)] -#![feature(core)] - -use std::num::Int; +use std::num::Zero; use std::thread; -// Avoid using constants, which would trigger compile-time errors. -fn min_val() -> T { Int::min_value() } -fn zero() -> T { Int::zero() } - fn main() { - assert!(thread::spawn(move|| { min_val::() / -1; }).join().is_err()); - assert!(thread::spawn(move|| { min_val::() / -1; }).join().is_err()); - assert!(thread::spawn(move|| { min_val::() / -1; }).join().is_err()); - assert!(thread::spawn(move|| { min_val::() / -1; }).join().is_err()); - assert!(thread::spawn(move|| { min_val::() / -1; }).join().is_err()); - assert!(thread::spawn(move|| { 1isize / zero::(); }).join().is_err()); - assert!(thread::spawn(move|| { 1i8 / zero::(); }).join().is_err()); - assert!(thread::spawn(move|| { 1i16 / zero::(); }).join().is_err()); - assert!(thread::spawn(move|| { 1i32 / zero::(); }).join().is_err()); - assert!(thread::spawn(move|| { 1i64 / zero::(); }).join().is_err()); - assert!(thread::spawn(move|| { min_val::() % -1; }).join().is_err()); - assert!(thread::spawn(move|| { min_val::() % -1; }).join().is_err()); - assert!(thread::spawn(move|| { min_val::() % -1; }).join().is_err()); - assert!(thread::spawn(move|| { min_val::() % -1; }).join().is_err()); - assert!(thread::spawn(move|| { min_val::() % -1; }).join().is_err()); - assert!(thread::spawn(move|| { 1isize % zero::(); }).join().is_err()); - assert!(thread::spawn(move|| { 1i8 % zero::(); }).join().is_err()); - assert!(thread::spawn(move|| { 1i16 % zero::(); }).join().is_err()); - assert!(thread::spawn(move|| { 1i32 % zero::(); }).join().is_err()); - assert!(thread::spawn(move|| { 1i64 % zero::(); }).join().is_err()); + assert!(thread::spawn(move|| { isize::min_value() / -1; }).join().is_err()); + assert!(thread::spawn(move|| { i8::min_value() / -1; }).join().is_err()); + assert!(thread::spawn(move|| { i16::min_value() / -1; }).join().is_err()); + assert!(thread::spawn(move|| { i32::min_value() / -1; }).join().is_err()); + assert!(thread::spawn(move|| { i64::min_value() / -1; }).join().is_err()); + assert!(thread::spawn(move|| { 1isize / isize::zero(); }).join().is_err()); + assert!(thread::spawn(move|| { 1i8 / i8::zero(); }).join().is_err()); + assert!(thread::spawn(move|| { 1i16 / i16::zero(); }).join().is_err()); + assert!(thread::spawn(move|| { 1i32 / i32::zero(); }).join().is_err()); + assert!(thread::spawn(move|| { 1i64 / i64::zero(); }).join().is_err()); + assert!(thread::spawn(move|| { isize::min_value() % -1; }).join().is_err()); + assert!(thread::spawn(move|| { i8::min_value() % -1; }).join().is_err()); + assert!(thread::spawn(move|| { i16::min_value() % -1; }).join().is_err()); + assert!(thread::spawn(move|| { i32::min_value() % -1; }).join().is_err()); + assert!(thread::spawn(move|| { i64::min_value() % -1; }).join().is_err()); + assert!(thread::spawn(move|| { 1isize % isize::zero(); }).join().is_err()); + assert!(thread::spawn(move|| { 1i8 % i8::zero(); }).join().is_err()); + assert!(thread::spawn(move|| { 1i16 % i16::zero(); }).join().is_err()); + assert!(thread::spawn(move|| { 1i32 % i32::zero(); }).join().is_err()); + assert!(thread::spawn(move|| { 1i64 % i64::zero(); }).join().is_err()); } diff --git a/src/test/run-pass/monomorphized-callees-with-ty-params-3314.rs b/src/test/run-pass/monomorphized-callees-with-ty-params-3314.rs index 12162ba9022ae..b7de1b5f4cbb5 100644 --- a/src/test/run-pass/monomorphized-callees-with-ty-params-3314.rs +++ b/src/test/run-pass/monomorphized-callees-with-ty-params-3314.rs @@ -10,11 +10,7 @@ // pretty-expanded FIXME #23616 -#![feature(core)] - -use std::marker::MarkerTrait; - -trait Serializer : MarkerTrait { +trait Serializer { } trait Serializable { diff --git a/src/test/run-pass/numeric-method-autoexport.rs b/src/test/run-pass/numeric-method-autoexport.rs index d5f64c1c7b1aa..b1d71abc78599 100644 --- a/src/test/run-pass/numeric-method-autoexport.rs +++ b/src/test/run-pass/numeric-method-autoexport.rs @@ -15,11 +15,7 @@ // necessary. Testing the methods of the impls is done within the source // file for each numeric type. - -#![feature(core)] - use std::ops::Add; -use std::num::ToPrimitive; pub fn main() { // ints @@ -37,9 +33,4 @@ pub fn main() { assert_eq!(15_u16.add(6u16), 21_u16); assert_eq!(15_u32.add(6u32), 21_u32); assert_eq!(15_u64.add(6u64), 21_u64); - -// floats - // num - assert_eq!(10_f32.to_i32().unwrap(), 10); - assert_eq!(10_f64.to_i32().unwrap(), 10); } diff --git a/src/test/run-pass/overloaded-autoderef.rs b/src/test/run-pass/overloaded-autoderef.rs index ddd6ae4d0a090..5e924d015b619 100644 --- a/src/test/run-pass/overloaded-autoderef.rs +++ b/src/test/run-pass/overloaded-autoderef.rs @@ -13,7 +13,6 @@ use std::cell::RefCell; use std::rc::Rc; -use std::num::ToPrimitive; #[derive(PartialEq, Debug)] struct Point { @@ -23,9 +22,6 @@ struct Point { pub fn main() { let box_5: Box<_> = box 5_usize; - assert_eq!(Rc::new(5_usize).to_uint(), Some(5)); - // FIXME (#22405): Replace `Box::new` with `box` here when/if possible. - assert_eq!((Box::new(&Box::new(&Rc::new(Box::new(Box::new(&box_5)))))).to_uint(), Some(5)); let point = Rc::new(Point {x: 2, y: 4}); assert_eq!(point.x, 2); assert_eq!(point.y, 4); diff --git a/src/test/run-pass/syntax-trait-polarity.rs b/src/test/run-pass/syntax-trait-polarity.rs index ba8a3f77aacef..f69b857981d78 100644 --- a/src/test/run-pass/syntax-trait-polarity.rs +++ b/src/test/run-pass/syntax-trait-polarity.rs @@ -10,15 +10,13 @@ // pretty-expanded FIXME #23616 -#![feature(optin_builtin_traits, core)] - -use std::marker::{MarkerTrait, Send}; +#![feature(optin_builtin_traits)] struct TestType; impl TestType {} -trait TestTrait : MarkerTrait {} +trait TestTrait {} impl !Send for TestType {} diff --git a/src/test/run-pass/trait-bounds-basic.rs b/src/test/run-pass/trait-bounds-basic.rs index 50c9c43ba2b8b..558e69664ecf9 100644 --- a/src/test/run-pass/trait-bounds-basic.rs +++ b/src/test/run-pass/trait-bounds-basic.rs @@ -10,9 +10,7 @@ // pretty-expanded FIXME #23616 -#![feature(core)] - -trait Foo : ::std::marker::MarkerTrait { +trait Foo { } fn b(_x: Box) { diff --git a/src/test/run-pass/trait-bounds-on-structs-and-enums.rs b/src/test/run-pass/trait-bounds-on-structs-and-enums.rs index 60c1816b1632c..bb8ae8247fa99 100644 --- a/src/test/run-pass/trait-bounds-on-structs-and-enums.rs +++ b/src/test/run-pass/trait-bounds-on-structs-and-enums.rs @@ -12,10 +12,10 @@ #![feature(core)] -trait U : ::std::marker::MarkerTrait {} +trait U {} trait T { fn get(self) -> X; } -trait S2 : ::std::marker::MarkerTrait { +trait S2 { fn m(x: Box+'static>) {} } diff --git a/src/test/run-pass/trait-bounds-recursion.rs b/src/test/run-pass/trait-bounds-recursion.rs index 250390f70b448..d984e9cdc990f 100644 --- a/src/test/run-pass/trait-bounds-recursion.rs +++ b/src/test/run-pass/trait-bounds-recursion.rs @@ -10,21 +10,19 @@ // pretty-expanded FIXME #23616 -#![feature(core)] - trait I { fn i(&self) -> Self; } -trait A : ::std::marker::MarkerTrait { +trait A { fn id(x:T) -> T { x.i() } } trait J { fn j(&self) -> T; } -trait B> : ::std::marker::MarkerTrait { +trait B> { fn id(x:T) -> T { x.j() } } -trait C : ::std::marker::MarkerTrait { +trait C { fn id>(x:T) -> T { x.j() } } diff --git a/src/test/run-pass/trait-inheritance-num.rs b/src/test/run-pass/trait-inheritance-num.rs index 4af049fc0c3af..e5390ac8a6256 100644 --- a/src/test/run-pass/trait-inheritance-num.rs +++ b/src/test/run-pass/trait-inheritance-num.rs @@ -10,16 +10,11 @@ // pretty-expanded FIXME #23616 -#![feature(core)] - -use std::cmp::{PartialEq, PartialOrd}; -use std::num::NumCast; - -pub trait NumExt: NumCast + PartialEq + PartialOrd {} +pub trait NumExt: PartialEq + PartialOrd {} pub trait FloatExt: NumExt {} -fn greater_than_one(n: &T) -> bool { *n > NumCast::from(1).unwrap() } -fn greater_than_one_float(n: &T) -> bool { *n > NumCast::from(1).unwrap() } +fn greater_than_one(n: &T) -> bool { loop {} } +fn greater_than_one_float(n: &T) -> bool { loop {} } pub fn main() {} diff --git a/src/test/run-pass/trait-inheritance-num0.rs b/src/test/run-pass/trait-inheritance-num0.rs index b7f9534935697..83c2a9ad33926 100644 --- a/src/test/run-pass/trait-inheritance-num0.rs +++ b/src/test/run-pass/trait-inheritance-num0.rs @@ -15,7 +15,10 @@ #![feature(core)] use std::cmp::PartialOrd; -use std::num::NumCast; + +pub trait NumCast { + fn from(i: i32) -> Option; +} pub trait Num { fn from_int(i: isize) -> Self; diff --git a/src/test/run-pass/trait-inheritance-num1.rs b/src/test/run-pass/trait-inheritance-num1.rs index 02ebf6bfa5375..14a6a9a0c664c 100644 --- a/src/test/run-pass/trait-inheritance-num1.rs +++ b/src/test/run-pass/trait-inheritance-num1.rs @@ -10,10 +10,9 @@ // pretty-expanded FIXME #23616 -#![feature(core)] - -use std::cmp::PartialOrd; -use std::num::NumCast; +pub trait NumCast { + fn from(i: i32) -> Option; +} pub trait NumExt: NumCast + PartialOrd { } diff --git a/src/test/run-pass/trait-inheritance-num2.rs b/src/test/run-pass/trait-inheritance-num2.rs index 773fc387a2a34..5f8541a6da1e8 100644 --- a/src/test/run-pass/trait-inheritance-num2.rs +++ b/src/test/run-pass/trait-inheritance-num2.rs @@ -10,12 +10,7 @@ // A more complex example of numeric extensions -#![feature(core)] - -use std::cmp::{PartialEq, PartialOrd}; -use std::num::NumCast; - -pub trait TypeExt : ::std::marker::MarkerTrait { } +pub trait TypeExt {} impl TypeExt for u8 {} impl TypeExt for u16 {} @@ -33,7 +28,7 @@ impl TypeExt for f32 {} impl TypeExt for f64 {} -pub trait NumExt: TypeExt + PartialEq + PartialOrd + NumCast {} +pub trait NumExt: TypeExt + PartialEq + PartialOrd {} impl NumExt for u8 {} impl NumExt for u16 {} diff --git a/src/test/run-pass/trait-inheritance-num3.rs b/src/test/run-pass/trait-inheritance-num3.rs index b5cf25bc5a8f4..abf8d2baf8732 100644 --- a/src/test/run-pass/trait-inheritance-num3.rs +++ b/src/test/run-pass/trait-inheritance-num3.rs @@ -8,14 +8,16 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(core)] - -use std::cmp::{PartialEq, PartialOrd}; -use std::num::NumCast; +pub trait NumCast { + fn from(i: i32) -> Option; +} pub trait NumExt: PartialEq + PartialOrd + NumCast {} impl NumExt for f32 {} +impl NumCast for f32 { + fn from(i: i32) -> Option { Some(i as f32) } +} fn num_eq_one(n: T) { println!("{}", n == NumCast::from(1).unwrap()) diff --git a/src/test/run-pass/trait-inheritance-num5.rs b/src/test/run-pass/trait-inheritance-num5.rs index b2c3900bc0282..c6f8a5d4f1d99 100644 --- a/src/test/run-pass/trait-inheritance-num5.rs +++ b/src/test/run-pass/trait-inheritance-num5.rs @@ -10,16 +10,22 @@ // pretty-expanded FIXME #23616 -#![feature(core)] - -use std::cmp::PartialEq; -use std::num::NumCast; +pub trait NumCast { + fn from(i: i32) -> Option; +} pub trait NumExt: PartialEq + NumCast {} impl NumExt for f32 {} impl NumExt for isize {} +impl NumCast for f32 { + fn from(i: i32) -> Option { Some(i as f32) } +} +impl NumCast for isize { + fn from(i: i32) -> Option { Some(i as isize) } +} + fn num_eq_one() -> T { NumCast::from(1).unwrap() } diff --git a/src/test/run-pass/trait-inheritance-self-in-supertype.rs b/src/test/run-pass/trait-inheritance-self-in-supertype.rs index ac9485594eb3e..c7e206cb474b8 100644 --- a/src/test/run-pass/trait-inheritance-self-in-supertype.rs +++ b/src/test/run-pass/trait-inheritance-self-in-supertype.rs @@ -10,9 +10,6 @@ // Test for issue #4183: use of Self in supertraits. - -use std::num::Float as StdFloat; - pub static FUZZY_EPSILON: f64 = 0.1; pub trait FuzzyEq { diff --git a/src/test/run-pass/trait-inheritance-static2.rs b/src/test/run-pass/trait-inheritance-static2.rs index 62feecf045b54..67bea3864a772 100644 --- a/src/test/run-pass/trait-inheritance-static2.rs +++ b/src/test/run-pass/trait-inheritance-static2.rs @@ -8,12 +8,9 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +pub trait MyEq {} -#![feature(core)] - -pub trait MyEq : ::std::marker::MarkerTrait { } - -pub trait MyNum : ::std::marker::MarkerTrait { +pub trait MyNum { fn from_int(isize) -> Self; } diff --git a/src/test/run-pass/unboxed-closures-infer-argument-types-from-expected-bound.rs b/src/test/run-pass/unboxed-closures-infer-argument-types-from-expected-bound.rs index d408612f9b856..c4944548e17f0 100644 --- a/src/test/run-pass/unboxed-closures-infer-argument-types-from-expected-bound.rs +++ b/src/test/run-pass/unboxed-closures-infer-argument-types-from-expected-bound.rs @@ -13,14 +13,18 @@ // pretty-expanded FIXME #23616 -#![feature(unboxed_closures, core)] +pub trait ToPrimitive { + fn to_int(&self) {} +} -use std::num::ToPrimitive; +impl ToPrimitive for isize {} +impl ToPrimitive for i32 {} +impl ToPrimitive for usize {} fn doit(val: T, f: &F) where F : Fn(T) { - f.call((val,)) + f(val) } pub fn main() { diff --git a/src/test/run-pass/unboxed-closures-infer-argument-types-from-expected-object-type.rs b/src/test/run-pass/unboxed-closures-infer-argument-types-from-expected-object-type.rs index c1e1ff3cd8e93..9cad7d61e32c5 100644 --- a/src/test/run-pass/unboxed-closures-infer-argument-types-from-expected-object-type.rs +++ b/src/test/run-pass/unboxed-closures-infer-argument-types-from-expected-object-type.rs @@ -13,11 +13,15 @@ // pretty-expanded FIXME #23616 -#![feature(unboxed_closures, core)] +pub trait ToPrimitive { + fn to_int(&self) {} +} -use std::num::ToPrimitive; +impl ToPrimitive for isize {} +impl ToPrimitive for i32 {} +impl ToPrimitive for usize {} -fn doit(val: T, f: &Fn(T)) { f.call((val,)) } +fn doit(val: T, f: &Fn(T)) { f(val) } pub fn main() { doit(0, &|x /*: isize*/ | { x.to_int(); }); diff --git a/src/test/run-pass/unboxed-closures-infer-argument-types-with-bound-regions-from-expected-bound.rs b/src/test/run-pass/unboxed-closures-infer-argument-types-with-bound-regions-from-expected-bound.rs index 99e2149de966a..bdd1932182bdc 100644 --- a/src/test/run-pass/unboxed-closures-infer-argument-types-with-bound-regions-from-expected-bound.rs +++ b/src/test/run-pass/unboxed-closures-infer-argument-types-with-bound-regions-from-expected-bound.rs @@ -13,14 +13,18 @@ // pretty-expanded FIXME #23616 -#![feature(unboxed_closures, core)] +pub trait ToPrimitive { + fn to_int(&self) {} +} -use std::num::ToPrimitive; +impl ToPrimitive for isize {} +impl ToPrimitive for i32 {} +impl ToPrimitive for usize {} fn doit(val: T, f: &F) where F : Fn(&T) { - f.call((&val,)) + f(&val) } pub fn main() { diff --git a/src/test/run-pass/utf8_idents.rs b/src/test/run-pass/utf8_idents.rs index b11b7e83eb671..9f88d2b5dd466 100644 --- a/src/test/run-pass/utf8_idents.rs +++ b/src/test/run-pass/utf8_idents.rs @@ -12,8 +12,6 @@ #![feature(non_ascii_idents)] -use std::num::Float; - pub fn main() { let ε = 0.00001f64; let Π = 3.14f64; From 1c9aa362292555566e4ff8366f574b70ff59d5c8 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Fri, 17 Apr 2015 23:45:55 -0700 Subject: [PATCH 18/25] std: Bring back f32::from_str_radix as an unstable API This API was exercised in a few tests and mirrors the `from_str_radix` functionality of the integer types. Conflicts: src/doc/trpl/traits.md src/libstd/sys/windows/fs2.rs --- src/doc/trpl/traits.md | 75 ---- src/libcollections/bit.rs | 1 - src/libcollections/fmt.rs | 8 +- src/libcore/iter.rs | 3 +- src/libcore/lib.rs | 1 + src/libcore/num/f32.rs | 9 +- src/libcore/num/f64.rs | 9 +- src/libcore/num/float_macros.rs | 142 ++++++ src/libcore/num/mod.rs | 250 +---------- src/libcoretest/cmp.rs | 2 - src/libcoretest/iter.rs | 11 - src/libcoretest/lib.rs | 6 +- src/libcoretest/num/int_macros.rs | 67 ++- src/libcoretest/num/mod.rs | 31 +- src/libcoretest/num/uint_macros.rs | 27 +- src/librand/distributions/range.rs | 1 - src/librustc_back/sha2.rs | 4 +- src/libstd/collections/hash/map.rs | 4 +- src/libstd/env.rs | 6 +- src/libstd/lib.rs | 1 + src/libstd/num/f32.rs | 230 +++++----- src/libstd/num/f64.rs | 242 +++++------ src/libstd/num/mod.rs | 552 +++--------------------- src/libstd/num/uint_macros.rs | 21 +- src/libstd/rand/reader.rs | 13 +- src/libstd/sys/windows/fs2.rs | 3 +- src/libstd/sys/windows/mod.rs | 8 +- src/libstd/sys/windows/net.rs | 15 +- src/libstd/sys/windows/process2.rs | 4 +- src/libtest/stats.rs | 3 +- src/test/bench/noise.rs | 1 - src/test/bench/shootout-binarytrees.rs | 3 +- src/test/bench/shootout-fasta.rs | 1 - src/test/bench/shootout-nbody.rs | 21 +- src/test/bench/shootout-spectralnorm.rs | 1 - src/test/bench/sudoku.rs | 1 - src/test/pretty/default-trait-impl.rs | 6 +- 37 files changed, 561 insertions(+), 1222 deletions(-) diff --git a/src/doc/trpl/traits.md b/src/doc/trpl/traits.md index 25f5c7cacc771..d7bf3ef5f4ab7 100644 --- a/src/doc/trpl/traits.md +++ b/src/doc/trpl/traits.md @@ -389,81 +389,6 @@ This shows off the additional feature of `where` clauses: they allow bounds where the left-hand side is an arbitrary type (`i32` in this case), not just a plain type parameter (like `T`). -## Our `inverse` Example - -Back in [Generics](generics.html), we were trying to write code like this: - -```{rust,ignore} -fn inverse(x: T) -> Result { - if x == 0.0 { return Err("x cannot be zero!".to_string()); } - - Ok(1.0 / x) -} -``` - -If we try to compile it, we get this error: - -```text -error: binary operation `==` cannot be applied to type `T` -``` - -This is because `T` is too generic: we don't know if a random `T` can be -compared. For that, we can use trait bounds. It doesn't quite work, but try -this: - -```{rust,ignore} -fn inverse(x: T) -> Result { - if x == 0.0 { return Err("x cannot be zero!".to_string()); } - - Ok(1.0 / x) -} -``` - -You should get this error: - -```text -error: mismatched types: - expected `T`, - found `_` -(expected type parameter, - found floating-point variable) -``` - -So this won't work. While our `T` is `PartialEq`, we expected to have another `T`, -but instead, we found a floating-point variable. We need a different bound. `Float` -to the rescue: - -``` -# #![feature(std_misc)] -use std::num::Float; - -fn inverse(x: T) -> Result { - if x == Float::zero() { return Err("x cannot be zero!".to_string()) } - - let one: T = Float::one(); - Ok(one / x) -} -``` - -We've had to replace our generic `0.0` and `1.0` with the appropriate methods -from the `Float` trait. Both `f32` and `f64` implement `Float`, so our function -works just fine: - -``` -# #![feature(std_misc)] -# use std::num::Float; -# fn inverse(x: T) -> Result { -# if x == Float::zero() { return Err("x cannot be zero!".to_string()) } -# let one: T = Float::one(); -# Ok(one / x) -# } -println!("the inverse of {} is {:?}", 2.0f32, inverse(2.0f32)); -println!("the inverse of {} is {:?}", 2.0f64, inverse(2.0f64)); - -println!("the inverse of {} is {:?}", 0.0f32, inverse(0.0f32)); -println!("the inverse of {} is {:?}", 0.0f64, inverse(0.0f64)); -``` - ## Default methods There's one last feature of traits we should cover: default methods. It's diff --git a/src/libcollections/bit.rs b/src/libcollections/bit.rs index a72f628e10d97..d9151298a35e3 100644 --- a/src/libcollections/bit.rs +++ b/src/libcollections/bit.rs @@ -40,7 +40,6 @@ //! ``` //! # #![feature(collections, core, step_by)] //! use std::collections::{BitSet, BitVec}; -//! use std::num::Float; //! use std::iter; //! //! let max_prime = 10000; diff --git a/src/libcollections/fmt.rs b/src/libcollections/fmt.rs index 46b1ad2138bd8..a59a88ffe30e4 100644 --- a/src/libcollections/fmt.rs +++ b/src/libcollections/fmt.rs @@ -177,7 +177,6 @@ //! # #![feature(core, std_misc)] //! use std::fmt; //! use std::f64; -//! use std::num::Float; //! //! #[derive(Debug)] //! struct Vector2D { @@ -202,10 +201,11 @@ //! let magnitude = magnitude.sqrt(); //! //! // Respect the formatting flags by using the helper method -//! // `pad_integral` on the Formatter object. See the method documentation -//! // for details, and the function `pad` can be used to pad strings. +//! // `pad_integral` on the Formatter object. See the method +//! // documentation for details, and the function `pad` can be used +//! // to pad strings. //! let decimals = f.precision().unwrap_or(3); -//! let string = f64::to_str_exact(magnitude, decimals); +//! let string = format!("{:.*}", decimals, magnitude); //! f.pad_integral(true, "", &string) //! } //! } diff --git a/src/libcore/iter.rs b/src/libcore/iter.rs index 12c0a75e1efe4..7a955e2e70ad7 100644 --- a/src/libcore/iter.rs +++ b/src/libcore/iter.rs @@ -2326,9 +2326,8 @@ impl RandomAccessIterator for Inspect /// An iterator that yields sequential Fibonacci numbers, and stops on overflow. /// /// ``` -/// # #![feature(core)] +/// #![feature(core)] /// use std::iter::Unfold; -/// use std::num::Int; // For `.checked_add()` /// /// // This iterator will yield up to the last Fibonacci number before the max /// // value of `u32`. You can simply change `u32` to `u64` in this line if diff --git a/src/libcore/lib.rs b/src/libcore/lib.rs index 164d3e49385e7..249f0a0c389a3 100644 --- a/src/libcore/lib.rs +++ b/src/libcore/lib.rs @@ -108,6 +108,7 @@ mod uint_macros; #[path = "num/f32.rs"] pub mod f32; #[path = "num/f64.rs"] pub mod f64; +#[macro_use] pub mod num; /* The libcore prelude, not as all-encompassing as the libstd prelude */ diff --git a/src/libcore/num/f32.rs b/src/libcore/num/f32.rs index a9afa5078d21f..50dd3f1661adf 100644 --- a/src/libcore/num/f32.rs +++ b/src/libcore/num/f32.rs @@ -16,9 +16,11 @@ #![stable(feature = "rust1", since = "1.0.0")] +use prelude::*; + use intrinsics; use mem; -use num::Float; +use num::{Float, ParseFloatError}; use num::FpCategory as Fp; #[stable(feature = "rust1", since = "1.0.0")] @@ -153,6 +155,8 @@ impl Float for f32 { #[inline] fn one() -> f32 { 1.0 } + from_str_radix_float_impl! { f32 } + /// Returns `true` if the number is NaN. #[inline] fn is_nan(self) -> bool { self != self } @@ -234,9 +238,6 @@ impl Float for f32 { /// The fractional part of the number, satisfying: /// /// ``` - /// # #![feature(core)] - /// use std::num::Float; - /// /// let x = 1.65f32; /// assert!(x == x.trunc() + x.fract()) /// ``` diff --git a/src/libcore/num/f64.rs b/src/libcore/num/f64.rs index fa9660a60e918..62b566e7eb40c 100644 --- a/src/libcore/num/f64.rs +++ b/src/libcore/num/f64.rs @@ -16,10 +16,12 @@ #![stable(feature = "rust1", since = "1.0.0")] +use prelude::*; + use intrinsics; use mem; -use num::Float; use num::FpCategory as Fp; +use num::{Float, ParseFloatError}; #[stable(feature = "rust1", since = "1.0.0")] pub const RADIX: u32 = 2; @@ -153,6 +155,8 @@ impl Float for f64 { #[inline] fn one() -> f64 { 1.0 } + from_str_radix_float_impl! { f64 } + /// Returns `true` if the number is NaN. #[inline] fn is_nan(self) -> bool { self != self } @@ -234,9 +238,6 @@ impl Float for f64 { /// The fractional part of the number, satisfying: /// /// ``` - /// # #![feature(core)] - /// use std::num::Float; - /// /// let x = 1.65f64; /// assert!(x == x.trunc() + x.fract()) /// ``` diff --git a/src/libcore/num/float_macros.rs b/src/libcore/num/float_macros.rs index b3adef53dabee..5ee0dc19f9bf6 100644 --- a/src/libcore/num/float_macros.rs +++ b/src/libcore/num/float_macros.rs @@ -18,3 +18,145 @@ macro_rules! assert_approx_eq { "{} is not approximately equal to {}", *a, *b); }) } + +macro_rules! from_str_radix_float_impl { + ($T:ty) => { + fn from_str_radix(src: &str, radix: u32) + -> Result<$T, ParseFloatError> { + use num::FloatErrorKind::*; + use num::ParseFloatError as PFE; + + // Special values + match src { + "inf" => return Ok(Float::infinity()), + "-inf" => return Ok(Float::neg_infinity()), + "NaN" => return Ok(Float::nan()), + _ => {}, + } + + let (is_positive, src) = match src.slice_shift_char() { + None => return Err(PFE { kind: Empty }), + Some(('-', "")) => return Err(PFE { kind: Empty }), + Some(('-', src)) => (false, src), + Some((_, _)) => (true, src), + }; + + // The significand to accumulate + let mut sig = if is_positive { 0.0 } else { -0.0 }; + // Necessary to detect overflow + let mut prev_sig = sig; + let mut cs = src.chars().enumerate(); + // Exponent prefix and exponent index offset + let mut exp_info = None::<(char, usize)>; + + // Parse the integer part of the significand + for (i, c) in cs.by_ref() { + match c.to_digit(radix) { + Some(digit) => { + // shift significand one digit left + sig = sig * (radix as $T); + + // add/subtract current digit depending on sign + if is_positive { + sig = sig + ((digit as isize) as $T); + } else { + sig = sig - ((digit as isize) as $T); + } + + // Detect overflow by comparing to last value, except + // if we've not seen any non-zero digits. + if prev_sig != 0.0 { + if is_positive && sig <= prev_sig + { return Ok(Float::infinity()); } + if !is_positive && sig >= prev_sig + { return Ok(Float::neg_infinity()); } + + // Detect overflow by reversing the shift-and-add process + if is_positive && (prev_sig != (sig - digit as $T) / radix as $T) + { return Ok(Float::infinity()); } + if !is_positive && (prev_sig != (sig + digit as $T) / radix as $T) + { return Ok(Float::neg_infinity()); } + } + prev_sig = sig; + }, + None => match c { + 'e' | 'E' | 'p' | 'P' => { + exp_info = Some((c, i + 1)); + break; // start of exponent + }, + '.' => { + break; // start of fractional part + }, + _ => { + return Err(PFE { kind: Invalid }); + }, + }, + } + } + + // If we are not yet at the exponent parse the fractional + // part of the significand + if exp_info.is_none() { + let mut power = 1.0; + for (i, c) in cs.by_ref() { + match c.to_digit(radix) { + Some(digit) => { + // Decrease power one order of magnitude + power = power / (radix as $T); + // add/subtract current digit depending on sign + sig = if is_positive { + sig + (digit as $T) * power + } else { + sig - (digit as $T) * power + }; + // Detect overflow by comparing to last value + if is_positive && sig < prev_sig + { return Ok(Float::infinity()); } + if !is_positive && sig > prev_sig + { return Ok(Float::neg_infinity()); } + prev_sig = sig; + }, + None => match c { + 'e' | 'E' | 'p' | 'P' => { + exp_info = Some((c, i + 1)); + break; // start of exponent + }, + _ => { + return Err(PFE { kind: Invalid }); + }, + }, + } + } + } + + // Parse and calculate the exponent + let exp = match exp_info { + Some((c, offset)) => { + let base = match c { + 'E' | 'e' if radix == 10 => 10.0, + 'P' | 'p' if radix == 16 => 2.0, + _ => return Err(PFE { kind: Invalid }), + }; + + // Parse the exponent as decimal integer + let src = &src[offset..]; + let (is_positive, exp) = match src.slice_shift_char() { + Some(('-', src)) => (false, src.parse::()), + Some(('+', src)) => (true, src.parse::()), + Some((_, _)) => (true, src.parse::()), + None => return Err(PFE { kind: Invalid }), + }; + + match (is_positive, exp) { + (true, Ok(exp)) => base.powi(exp as i32), + (false, Ok(exp)) => 1.0 / base.powi(exp as i32), + (_, Err(_)) => return Err(PFE { kind: Invalid }), + } + }, + None => 1.0, // no exponent + }; + + Ok(sig * exp) + } + } +} diff --git a/src/libcore/num/mod.rs b/src/libcore/num/mod.rs index 101ab77a09ef0..89e6330f07b09 100644 --- a/src/libcore/num/mod.rs +++ b/src/libcore/num/mod.rs @@ -21,7 +21,6 @@ use char::CharExt; use cmp::{Eq, PartialOrd}; use fmt; use intrinsics; -use iter::Iterator; use marker::Copy; use mem::size_of; use option::Option::{self, Some, None}; @@ -150,9 +149,6 @@ macro_rules! int_impl { /// # Examples /// /// ```rust - /// # #![feature(core)] - /// use std::num::Int; - /// /// let n = 0b01001100u8; /// /// assert_eq!(n.count_ones(), 3); @@ -166,9 +162,6 @@ macro_rules! int_impl { /// # Examples /// /// ```rust - /// # #![feature(core)] - /// use std::num::Int; - /// /// let n = 0b01001100u8; /// /// assert_eq!(n.count_zeros(), 5); @@ -185,9 +178,6 @@ macro_rules! int_impl { /// # Examples /// /// ```rust - /// # #![feature(core)] - /// use std::num::Int; - /// /// let n = 0b0101000u16; /// /// assert_eq!(n.leading_zeros(), 10); @@ -204,9 +194,6 @@ macro_rules! int_impl { /// # Examples /// /// ```rust - /// # #![feature(core)] - /// use std::num::Int; - /// /// let n = 0b0101000u16; /// /// assert_eq!(n.trailing_zeros(), 3); @@ -223,9 +210,6 @@ macro_rules! int_impl { /// # Examples /// /// ```rust - /// # #![feature(core)] - /// use std::num::Int; - /// /// let n = 0x0123456789ABCDEFu64; /// let m = 0x3456789ABCDEF012u64; /// @@ -244,9 +228,6 @@ macro_rules! int_impl { /// # Examples /// /// ```rust - /// # #![feature(core)] - /// use std::num::Int; - /// /// let n = 0x0123456789ABCDEFu64; /// let m = 0xDEF0123456789ABCu64; /// @@ -263,8 +244,6 @@ macro_rules! int_impl { /// # Examples /// /// ```rust - /// use std::num::Int; - /// /// let n = 0x0123456789ABCDEFu64; /// let m = 0xEFCDAB8967452301u64; /// @@ -284,14 +263,12 @@ macro_rules! int_impl { /// # Examples /// /// ```rust - /// use std::num::Int; - /// /// let n = 0x0123456789ABCDEFu64; /// /// if cfg!(target_endian = "big") { - /// assert_eq!(Int::from_be(n), n) + /// assert_eq!(u64::from_be(n), n) /// } else { - /// assert_eq!(Int::from_be(n), n.swap_bytes()) + /// assert_eq!(u64::from_be(n), n.swap_bytes()) /// } /// ``` #[stable(feature = "rust1", since = "1.0.0")] @@ -308,14 +285,12 @@ macro_rules! int_impl { /// # Examples /// /// ```rust - /// use std::num::Int; - /// /// let n = 0x0123456789ABCDEFu64; /// /// if cfg!(target_endian = "little") { - /// assert_eq!(Int::from_le(n), n) + /// assert_eq!(u64::from_le(n), n) /// } else { - /// assert_eq!(Int::from_le(n), n.swap_bytes()) + /// assert_eq!(u64::from_le(n), n.swap_bytes()) /// } /// ``` #[stable(feature = "rust1", since = "1.0.0")] @@ -332,8 +307,6 @@ macro_rules! int_impl { /// # Examples /// /// ```rust - /// use std::num::Int; - /// /// let n = 0x0123456789ABCDEFu64; /// /// if cfg!(target_endian = "big") { @@ -356,8 +329,6 @@ macro_rules! int_impl { /// # Examples /// /// ```rust - /// use std::num::Int; - /// /// let n = 0x0123456789ABCDEFu64; /// /// if cfg!(target_endian = "little") { @@ -378,8 +349,6 @@ macro_rules! int_impl { /// # Examples /// /// ```rust - /// use std::num::Int; - /// /// assert_eq!(5u16.checked_add(65530), Some(65535)); /// assert_eq!(6u16.checked_add(65530), None); /// ``` @@ -395,8 +364,6 @@ macro_rules! int_impl { /// # Examples /// /// ```rust - /// use std::num::Int; - /// /// assert_eq!((-127i8).checked_sub(1), Some(-128)); /// assert_eq!((-128i8).checked_sub(1), None); /// ``` @@ -412,8 +379,6 @@ macro_rules! int_impl { /// # Examples /// /// ```rust - /// use std::num::Int; - /// /// assert_eq!(5u8.checked_mul(51), Some(255)); /// assert_eq!(5u8.checked_mul(52), None); /// ``` @@ -429,8 +394,6 @@ macro_rules! int_impl { /// # Examples /// /// ```rust - /// use std::num::Int; - /// /// assert_eq!((-127i8).checked_div(-1), Some(127)); /// assert_eq!((-128i8).checked_div(-1), None); /// assert_eq!((1i8).checked_div(0), None); @@ -670,9 +633,6 @@ macro_rules! uint_impl { /// # Examples /// /// ```rust - /// # #![feature(core)] - /// use std::num::Int; - /// /// let n = 0b01001100u8; /// /// assert_eq!(n.count_ones(), 3); @@ -688,9 +648,6 @@ macro_rules! uint_impl { /// # Examples /// /// ```rust - /// # #![feature(core)] - /// use std::num::Int; - /// /// let n = 0b01001100u8; /// /// assert_eq!(n.count_zeros(), 5); @@ -707,9 +664,6 @@ macro_rules! uint_impl { /// # Examples /// /// ```rust - /// # #![feature(core)] - /// use std::num::Int; - /// /// let n = 0b0101000u16; /// /// assert_eq!(n.leading_zeros(), 10); @@ -726,9 +680,6 @@ macro_rules! uint_impl { /// # Examples /// /// ```rust - /// # #![feature(core)] - /// use std::num::Int; - /// /// let n = 0b0101000u16; /// /// assert_eq!(n.trailing_zeros(), 3); @@ -745,9 +696,6 @@ macro_rules! uint_impl { /// # Examples /// /// ```rust - /// # #![feature(core)] - /// use std::num::Int; - /// /// let n = 0x0123456789ABCDEFu64; /// let m = 0x3456789ABCDEF012u64; /// @@ -768,9 +716,6 @@ macro_rules! uint_impl { /// # Examples /// /// ```rust - /// # #![feature(core)] - /// use std::num::Int; - /// /// let n = 0x0123456789ABCDEFu64; /// let m = 0xDEF0123456789ABCu64; /// @@ -789,8 +734,6 @@ macro_rules! uint_impl { /// # Examples /// /// ```rust - /// use std::num::Int; - /// /// let n = 0x0123456789ABCDEFu64; /// let m = 0xEFCDAB8967452301u64; /// @@ -810,14 +753,12 @@ macro_rules! uint_impl { /// # Examples /// /// ```rust - /// use std::num::Int; - /// /// let n = 0x0123456789ABCDEFu64; /// /// if cfg!(target_endian = "big") { - /// assert_eq!(Int::from_be(n), n) + /// assert_eq!(u64::from_be(n), n) /// } else { - /// assert_eq!(Int::from_be(n), n.swap_bytes()) + /// assert_eq!(u64::from_be(n), n.swap_bytes()) /// } /// ``` #[stable(feature = "rust1", since = "1.0.0")] @@ -834,14 +775,12 @@ macro_rules! uint_impl { /// # Examples /// /// ```rust - /// use std::num::Int; - /// /// let n = 0x0123456789ABCDEFu64; /// /// if cfg!(target_endian = "little") { - /// assert_eq!(Int::from_le(n), n) + /// assert_eq!(u64::from_le(n), n) /// } else { - /// assert_eq!(Int::from_le(n), n.swap_bytes()) + /// assert_eq!(u64::from_le(n), n.swap_bytes()) /// } /// ``` #[stable(feature = "rust1", since = "1.0.0")] @@ -858,8 +797,6 @@ macro_rules! uint_impl { /// # Examples /// /// ```rust - /// use std::num::Int; - /// /// let n = 0x0123456789ABCDEFu64; /// /// if cfg!(target_endian = "big") { @@ -882,8 +819,6 @@ macro_rules! uint_impl { /// # Examples /// /// ```rust - /// use std::num::Int; - /// /// let n = 0x0123456789ABCDEFu64; /// /// if cfg!(target_endian = "little") { @@ -904,8 +839,6 @@ macro_rules! uint_impl { /// # Examples /// /// ```rust - /// use std::num::Int; - /// /// assert_eq!(5u16.checked_add(65530), Some(65535)); /// assert_eq!(6u16.checked_add(65530), None); /// ``` @@ -921,8 +854,6 @@ macro_rules! uint_impl { /// # Examples /// /// ```rust - /// use std::num::Int; - /// /// assert_eq!((-127i8).checked_sub(1), Some(-128)); /// assert_eq!((-128i8).checked_sub(1), None); /// ``` @@ -938,8 +869,6 @@ macro_rules! uint_impl { /// # Examples /// /// ```rust - /// use std::num::Int; - /// /// assert_eq!(5u8.checked_mul(51), Some(255)); /// assert_eq!(5u8.checked_mul(52), None); /// ``` @@ -955,8 +884,6 @@ macro_rules! uint_impl { /// # Examples /// /// ```rust - /// use std::num::Int; - /// /// assert_eq!((-127i8).checked_div(-1), Some(127)); /// assert_eq!((-128i8).checked_div(-1), None); /// assert_eq!((1i8).checked_div(0), None); @@ -1029,10 +956,7 @@ macro_rules! uint_impl { /// # Examples /// /// ```rust - /// # #![feature(core)] - /// use std::num::Int; - /// - /// assert_eq!(2.pow(4), 16); + /// assert_eq!(2i32.pow(4), 16); /// ``` #[stable(feature = "rust1", since = "1.0.0")] #[inline] @@ -1210,6 +1134,8 @@ pub trait Float { fn zero() -> Self; /// Returns 1.0. fn one() -> Self; + /// Parses the string `s` with the radix `r` as a float. + fn from_str_radix(s: &str, r: u32) -> Result; /// Returns true if this value is NaN and false otherwise. fn is_nan(self) -> bool; @@ -1294,8 +1220,8 @@ pub trait Float { fn to_radians(self) -> Self; } -macro_rules! from_str_radix_float_impl { - ($T:ty) => { +macro_rules! from_str_float_impl { + ($T:ident) => { #[stable(feature = "rust1", since = "1.0.0")] impl FromStr for $T { type Err = ParseFloatError; @@ -1323,152 +1249,19 @@ macro_rules! from_str_radix_float_impl { /// /// # Return value /// - /// `Err(ParseFloatError)` if the string did not represent a valid number. - /// Otherwise, `Ok(n)` where `n` is the floating-point number represented by `src`. + /// `Err(ParseFloatError)` if the string did not represent a valid + /// number. Otherwise, `Ok(n)` where `n` is the floating-point + /// number represented by `src`. #[inline] #[allow(deprecated)] fn from_str(src: &str) -> Result<$T, ParseFloatError> { - use self::FloatErrorKind::*; - use self::ParseFloatError as PFE; - let radix = 10; - - // Special values - match src { - "inf" => return Ok(Float::infinity()), - "-inf" => return Ok(Float::neg_infinity()), - "NaN" => return Ok(Float::nan()), - _ => {}, - } - - let (is_positive, src) = match src.slice_shift_char() { - None => return Err(PFE { kind: Empty }), - Some(('-', "")) => return Err(PFE { kind: Empty }), - Some(('-', src)) => (false, src), - Some((_, _)) => (true, src), - }; - - // The significand to accumulate - let mut sig = if is_positive { 0.0 } else { -0.0 }; - // Necessary to detect overflow - let mut prev_sig = sig; - let mut cs = src.chars().enumerate(); - // Exponent prefix and exponent index offset - let mut exp_info = None::<(char, usize)>; - - // Parse the integer part of the significand - for (i, c) in cs.by_ref() { - match c.to_digit(radix) { - Some(digit) => { - // shift significand one digit left - sig = sig * (radix as $T); - - // add/subtract current digit depending on sign - if is_positive { - sig = sig + ((digit as isize) as $T); - } else { - sig = sig - ((digit as isize) as $T); - } - - // Detect overflow by comparing to last value, except - // if we've not seen any non-zero digits. - if prev_sig != 0.0 { - if is_positive && sig <= prev_sig - { return Ok(Float::infinity()); } - if !is_positive && sig >= prev_sig - { return Ok(Float::neg_infinity()); } - - // Detect overflow by reversing the shift-and-add process - if is_positive && (prev_sig != (sig - digit as $T) / radix as $T) - { return Ok(Float::infinity()); } - if !is_positive && (prev_sig != (sig + digit as $T) / radix as $T) - { return Ok(Float::neg_infinity()); } - } - prev_sig = sig; - }, - None => match c { - 'e' | 'E' | 'p' | 'P' => { - exp_info = Some((c, i + 1)); - break; // start of exponent - }, - '.' => { - break; // start of fractional part - }, - _ => { - return Err(PFE { kind: Invalid }); - }, - }, - } - } - - // If we are not yet at the exponent parse the fractional - // part of the significand - if exp_info.is_none() { - let mut power = 1.0; - for (i, c) in cs.by_ref() { - match c.to_digit(radix) { - Some(digit) => { - // Decrease power one order of magnitude - power = power / (radix as $T); - // add/subtract current digit depending on sign - sig = if is_positive { - sig + (digit as $T) * power - } else { - sig - (digit as $T) * power - }; - // Detect overflow by comparing to last value - if is_positive && sig < prev_sig - { return Ok(Float::infinity()); } - if !is_positive && sig > prev_sig - { return Ok(Float::neg_infinity()); } - prev_sig = sig; - }, - None => match c { - 'e' | 'E' | 'p' | 'P' => { - exp_info = Some((c, i + 1)); - break; // start of exponent - }, - _ => { - return Err(PFE { kind: Invalid }); - }, - }, - } - } - } - - // Parse and calculate the exponent - let exp = match exp_info { - Some((c, offset)) => { - let base = match c { - 'E' | 'e' if radix == 10 => 10.0, - 'P' | 'p' if radix == 16 => 2.0, - _ => return Err(PFE { kind: Invalid }), - }; - - // Parse the exponent as decimal integer - let src = &src[offset..]; - let (is_positive, exp) = match src.slice_shift_char() { - Some(('-', src)) => (false, src.parse::()), - Some(('+', src)) => (true, src.parse::()), - Some((_, _)) => (true, src.parse::()), - None => return Err(PFE { kind: Invalid }), - }; - - match (is_positive, exp) { - (true, Ok(exp)) => base.powi(exp as i32), - (false, Ok(exp)) => 1.0 / base.powi(exp as i32), - (_, Err(_)) => return Err(PFE { kind: Invalid }), - } - }, - None => 1.0, // no exponent - }; - - Ok(sig * exp) + $T::from_str_radix(src, 10) } } } } -from_str_radix_float_impl! { f32 } -from_str_radix_float_impl! { f64 } +from_str_float_impl!(f32); +from_str_float_impl!(f64); macro_rules! from_str_radix_int_impl { ($($T:ident)*) => {$( @@ -1598,11 +1391,10 @@ impl fmt::Display for ParseIntError { /// An error which can be returned when parsing a float. #[derive(Debug, Clone, PartialEq)] -#[stable(feature = "rust1", since = "1.0.0")] -pub struct ParseFloatError { kind: FloatErrorKind } +pub struct ParseFloatError { pub kind: FloatErrorKind } #[derive(Debug, Clone, PartialEq)] -enum FloatErrorKind { +pub enum FloatErrorKind { Empty, Invalid, } diff --git a/src/libcoretest/cmp.rs b/src/libcoretest/cmp.rs index 9ed1508c3eb78..e0d396c68b4c4 100644 --- a/src/libcoretest/cmp.rs +++ b/src/libcoretest/cmp.rs @@ -110,8 +110,6 @@ fn test_partial_max() { #[test] fn test_user_defined_eq() { - use core::num::SignedInt; - // Our type. struct SketchyNum { num : isize diff --git a/src/libcoretest/iter.rs b/src/libcoretest/iter.rs index a56820c61ccbb..2866c193c3b15 100644 --- a/src/libcoretest/iter.rs +++ b/src/libcoretest/iter.rs @@ -11,7 +11,6 @@ use core::iter::*; use core::iter::order::*; use core::iter::MinMaxResult::*; -use core::num::SignedInt; use core::usize; use core::cmp; @@ -783,16 +782,6 @@ fn test_range_step() { assert_eq!((200..200).step_by(1).collect::>(), []); } -#[test] -fn test_range_step_inclusive() { - assert_eq!(range_step_inclusive(0, 20, 5).collect::>(), [0, 5, 10, 15, 20]); - assert_eq!(range_step_inclusive(20, 0, -5).collect::>(), [20, 15, 10, 5, 0]); - assert_eq!(range_step_inclusive(20, 0, -6).collect::>(), [20, 14, 8, 2]); - assert_eq!(range_step_inclusive(200, 255, 50).collect::>(), [200, 250]); - assert_eq!(range_step_inclusive(200, -5, 1).collect::>(), []); - assert_eq!(range_step_inclusive(200, 200, 1).collect::>(), [200]); -} - #[test] fn test_reverse() { let mut ys = [1, 2, 3, 4, 5]; diff --git a/src/libcoretest/lib.rs b/src/libcoretest/lib.rs index 7ae0dcbb5f9d4..7a66fa0f10406 100644 --- a/src/libcoretest/lib.rs +++ b/src/libcoretest/lib.rs @@ -10,8 +10,8 @@ // Do not remove on snapshot creation. Needed for bootstrap. (Issue #22364) #![cfg_attr(stage0, feature(custom_attribute))] + #![feature(box_syntax)] -#![feature(int_uint)] #![feature(unboxed_closures)] #![feature(unsafe_destructor)] #![feature(core)] @@ -21,13 +21,11 @@ #![feature(std_misc)] #![feature(libc)] #![feature(hash)] -#![feature(io)] -#![feature(collections)] #![feature(debug_builders)] #![feature(unique)] #![feature(step_by)] #![feature(slice_patterns)] -#![allow(deprecated)] // rand +#![feature(float_from_str_radix)] extern crate core; extern crate test; diff --git a/src/libcoretest/num/int_macros.rs b/src/libcoretest/num/int_macros.rs index cb2359873e9dc..b1c8aec3c35e9 100644 --- a/src/libcoretest/num/int_macros.rs +++ b/src/libcoretest/num/int_macros.rs @@ -8,12 +8,11 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -macro_rules! int_module { ($T:ty, $T_i:ident) => ( +macro_rules! int_module { ($T:ident, $T_i:ident) => ( #[cfg(test)] mod tests { use core::$T_i::*; use core::isize; - use core::num::{FromStrRadix, Int, SignedInt}; use core::ops::{Shl, Shr, Not, BitXor, BitAnd, BitOr}; use num; @@ -129,30 +128,30 @@ mod tests { #[test] fn test_le() { - assert_eq!(Int::from_le(A.to_le()), A); - assert_eq!(Int::from_le(B.to_le()), B); - assert_eq!(Int::from_le(C.to_le()), C); - assert_eq!(Int::from_le(_0), _0); - assert_eq!(Int::from_le(_1), _1); + assert_eq!($T::from_le(A.to_le()), A); + assert_eq!($T::from_le(B.to_le()), B); + assert_eq!($T::from_le(C.to_le()), C); + assert_eq!($T::from_le(_0), _0); + assert_eq!($T::from_le(_1), _1); assert_eq!(_0.to_le(), _0); assert_eq!(_1.to_le(), _1); } #[test] fn test_be() { - assert_eq!(Int::from_be(A.to_be()), A); - assert_eq!(Int::from_be(B.to_be()), B); - assert_eq!(Int::from_be(C.to_be()), C); - assert_eq!(Int::from_be(_0), _0); - assert_eq!(Int::from_be(_1), _1); + assert_eq!($T::from_be(A.to_be()), A); + assert_eq!($T::from_be(B.to_be()), B); + assert_eq!($T::from_be(C.to_be()), C); + assert_eq!($T::from_be(_0), _0); + assert_eq!($T::from_be(_1), _1); assert_eq!(_0.to_be(), _0); assert_eq!(_1.to_be(), _1); } #[test] fn test_signed_checked_div() { - assert!(10.checked_div(2) == Some(5)); - assert!(5.checked_div(0) == None); + assert!((10 as $T).checked_div(2) == Some(5)); + assert!((5 as $T).checked_div(0) == None); assert!(isize::MIN.checked_div(-1) == None); } @@ -180,26 +179,26 @@ mod tests { #[test] fn test_from_str_radix() { - assert_eq!(FromStrRadix::from_str_radix("123", 10), Ok(123 as $T)); - assert_eq!(FromStrRadix::from_str_radix("1001", 2), Ok(9 as $T)); - assert_eq!(FromStrRadix::from_str_radix("123", 8), Ok(83 as $T)); - assert_eq!(FromStrRadix::from_str_radix("123", 16), Ok(291 as i32)); - assert_eq!(FromStrRadix::from_str_radix("ffff", 16), Ok(65535 as i32)); - assert_eq!(FromStrRadix::from_str_radix("FFFF", 16), Ok(65535 as i32)); - assert_eq!(FromStrRadix::from_str_radix("z", 36), Ok(35 as $T)); - assert_eq!(FromStrRadix::from_str_radix("Z", 36), Ok(35 as $T)); - - assert_eq!(FromStrRadix::from_str_radix("-123", 10), Ok(-123 as $T)); - assert_eq!(FromStrRadix::from_str_radix("-1001", 2), Ok(-9 as $T)); - assert_eq!(FromStrRadix::from_str_radix("-123", 8), Ok(-83 as $T)); - assert_eq!(FromStrRadix::from_str_radix("-123", 16), Ok(-291 as i32)); - assert_eq!(FromStrRadix::from_str_radix("-ffff", 16), Ok(-65535 as i32)); - assert_eq!(FromStrRadix::from_str_radix("-FFFF", 16), Ok(-65535 as i32)); - assert_eq!(FromStrRadix::from_str_radix("-z", 36), Ok(-35 as $T)); - assert_eq!(FromStrRadix::from_str_radix("-Z", 36), Ok(-35 as $T)); - - assert_eq!(FromStrRadix::from_str_radix("Z", 35).ok(), None::<$T>); - assert_eq!(FromStrRadix::from_str_radix("-9", 2).ok(), None::<$T>); + assert_eq!($T::from_str_radix("123", 10), Ok(123 as $T)); + assert_eq!($T::from_str_radix("1001", 2), Ok(9 as $T)); + assert_eq!($T::from_str_radix("123", 8), Ok(83 as $T)); + assert_eq!(i32::from_str_radix("123", 16), Ok(291 as i32)); + assert_eq!(i32::from_str_radix("ffff", 16), Ok(65535 as i32)); + assert_eq!(i32::from_str_radix("FFFF", 16), Ok(65535 as i32)); + assert_eq!($T::from_str_radix("z", 36), Ok(35 as $T)); + assert_eq!($T::from_str_radix("Z", 36), Ok(35 as $T)); + + assert_eq!($T::from_str_radix("-123", 10), Ok(-123 as $T)); + assert_eq!($T::from_str_radix("-1001", 2), Ok(-9 as $T)); + assert_eq!($T::from_str_radix("-123", 8), Ok(-83 as $T)); + assert_eq!(i32::from_str_radix("-123", 16), Ok(-291 as i32)); + assert_eq!(i32::from_str_radix("-ffff", 16), Ok(-65535 as i32)); + assert_eq!(i32::from_str_radix("-FFFF", 16), Ok(-65535 as i32)); + assert_eq!($T::from_str_radix("-z", 36), Ok(-35 as $T)); + assert_eq!($T::from_str_radix("-Z", 36), Ok(-35 as $T)); + + assert_eq!($T::from_str_radix("Z", 35).ok(), None::<$T>); + assert_eq!($T::from_str_radix("-9", 2).ok(), None::<$T>); } #[test] diff --git a/src/libcoretest/num/mod.rs b/src/libcoretest/num/mod.rs index 9087b87f640cb..85ca547da8526 100644 --- a/src/libcoretest/num/mod.rs +++ b/src/libcoretest/num/mod.rs @@ -10,7 +10,6 @@ use core::cmp::PartialEq; use core::fmt::Debug; -use core::num::{NumCast, cast}; use core::ops::{Add, Sub, Mul, Div, Rem}; use core::marker::Copy; @@ -32,18 +31,12 @@ mod u64; /// Helper function for testing numeric operations pub fn test_num(ten: T, two: T) where - T: PartialEq + NumCast + T: PartialEq + Add + Sub + Mul + Div + Rem + Debug + Copy { - assert_eq!(ten.add(two), cast(12).unwrap()); - assert_eq!(ten.sub(two), cast(8).unwrap()); - assert_eq!(ten.mul(two), cast(20).unwrap()); - assert_eq!(ten.div(two), cast(5).unwrap()); - assert_eq!(ten.rem(two), cast(0).unwrap()); - assert_eq!(ten.add(two), ten + two); assert_eq!(ten.sub(two), ten - two); assert_eq!(ten.mul(two), ten * two); @@ -56,33 +49,33 @@ mod test { use core::option::Option; use core::option::Option::{Some, None}; use core::num::Float; - use core::num::from_str_radix; #[test] fn from_str_issue7588() { - let u : Option = from_str_radix("1000", 10).ok(); + let u : Option = u8::from_str_radix("1000", 10).ok(); assert_eq!(u, None); - let s : Option = from_str_radix("80000", 10).ok(); + let s : Option = i16::from_str_radix("80000", 10).ok(); assert_eq!(s, None); - let f : Option = from_str_radix("10000000000000000000000000000000000000000", 10).ok(); + let s = "10000000000000000000000000000000000000000"; + let f : Option = f32::from_str_radix(s, 10).ok(); assert_eq!(f, Some(Float::infinity())); - let fe : Option = from_str_radix("1e40", 10).ok(); + let fe : Option = f32::from_str_radix("1e40", 10).ok(); assert_eq!(fe, Some(Float::infinity())); } #[test] fn test_from_str_radix_float() { - let x1 : Option = from_str_radix("-123.456", 10).ok(); + let x1 : Option = f64::from_str_radix("-123.456", 10).ok(); assert_eq!(x1, Some(-123.456)); - let x2 : Option = from_str_radix("123.456", 10).ok(); + let x2 : Option = f32::from_str_radix("123.456", 10).ok(); assert_eq!(x2, Some(123.456)); - let x3 : Option = from_str_radix("-0.0", 10).ok(); + let x3 : Option = f32::from_str_radix("-0.0", 10).ok(); assert_eq!(x3, Some(-0.0)); - let x4 : Option = from_str_radix("0.0", 10).ok(); + let x4 : Option = f32::from_str_radix("0.0", 10).ok(); assert_eq!(x4, Some(0.0)); - let x4 : Option = from_str_radix("1.0", 10).ok(); + let x4 : Option = f32::from_str_radix("1.0", 10).ok(); assert_eq!(x4, Some(1.0)); - let x5 : Option = from_str_radix("-1.0", 10).ok(); + let x5 : Option = f32::from_str_radix("-1.0", 10).ok(); assert_eq!(x5, Some(-1.0)); } diff --git a/src/libcoretest/num/uint_macros.rs b/src/libcoretest/num/uint_macros.rs index 5e00692766d90..1712345f9d9a7 100644 --- a/src/libcoretest/num/uint_macros.rs +++ b/src/libcoretest/num/uint_macros.rs @@ -8,11 +8,10 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -macro_rules! uint_module { ($T:ty, $T_i:ident) => ( +macro_rules! uint_module { ($T:ident, $T_i:ident) => ( #[cfg(test)] mod tests { use core::$T_i::*; - use core::num::Int; use num; use core::ops::{BitOr, BitAnd, BitXor, Shl, Shr, Not}; @@ -97,30 +96,30 @@ mod tests { #[test] fn test_le() { - assert_eq!(Int::from_le(A.to_le()), A); - assert_eq!(Int::from_le(B.to_le()), B); - assert_eq!(Int::from_le(C.to_le()), C); - assert_eq!(Int::from_le(_0), _0); - assert_eq!(Int::from_le(_1), _1); + assert_eq!($T::from_le(A.to_le()), A); + assert_eq!($T::from_le(B.to_le()), B); + assert_eq!($T::from_le(C.to_le()), C); + assert_eq!($T::from_le(_0), _0); + assert_eq!($T::from_le(_1), _1); assert_eq!(_0.to_le(), _0); assert_eq!(_1.to_le(), _1); } #[test] fn test_be() { - assert_eq!(Int::from_be(A.to_be()), A); - assert_eq!(Int::from_be(B.to_be()), B); - assert_eq!(Int::from_be(C.to_be()), C); - assert_eq!(Int::from_be(_0), _0); - assert_eq!(Int::from_be(_1), _1); + assert_eq!($T::from_be(A.to_be()), A); + assert_eq!($T::from_be(B.to_be()), B); + assert_eq!($T::from_be(C.to_be()), C); + assert_eq!($T::from_be(_0), _0); + assert_eq!($T::from_be(_1), _1); assert_eq!(_0.to_be(), _0); assert_eq!(_1.to_be(), _1); } #[test] fn test_unsigned_checked_div() { - assert!(10.checked_div(2) == Some(5)); - assert!(5.checked_div(0) == None); + assert!((10 as $T).checked_div(2) == Some(5)); + assert!((5 as $T).checked_div(0) == None); } } diff --git a/src/librand/distributions/range.rs b/src/librand/distributions/range.rs index c5dd741c80c10..4916e305b70e3 100644 --- a/src/librand/distributions/range.rs +++ b/src/librand/distributions/range.rs @@ -146,7 +146,6 @@ float_impl! { f64 } #[cfg(test)] mod tests { - use std::num::Int; use std::prelude::v1::*; use distributions::{Sample, IndependentSample}; use super::Range as Range; diff --git a/src/librustc_back/sha2.rs b/src/librustc_back/sha2.rs index c45ce12efb7da..9ed827da8b2e4 100644 --- a/src/librustc_back/sha2.rs +++ b/src/librustc_back/sha2.rs @@ -540,14 +540,14 @@ mod tests { // A normal addition - no overflow occurs #[test] fn test_add_bytes_to_bits_ok() { - assert!(super::add_bytes_to_bits::(100, 10) == 180); + assert!(super::add_bytes_to_bits(100, 10) == 180); } // A simple failure case - adding 1 to the max value #[test] #[should_panic] fn test_add_bytes_to_bits_overflow() { - super::add_bytes_to_bits::(u64::MAX, 1); + super::add_bytes_to_bits(u64::MAX, 1); } struct Test { diff --git a/src/libstd/collections/hash/map.rs b/src/libstd/collections/hash/map.rs index 2da31d3cb2de1..c28094d35e401 100644 --- a/src/libstd/collections/hash/map.rs +++ b/src/libstd/collections/hash/map.rs @@ -1624,7 +1624,7 @@ mod test_map { use super::HashMap; use super::Entry::{Occupied, Vacant}; - use iter::{range_inclusive, range_step_inclusive, repeat}; + use iter::{range_inclusive, repeat}; use cell::RefCell; use rand::{thread_rng, Rng}; @@ -1860,7 +1860,7 @@ mod test_map { } // remove backwards - for i in range_step_inclusive(1000, 1, -1) { + for i in (1..1001).rev() { assert!(m.remove(&i).is_some()); for j in range_inclusive(i, 1000) { diff --git a/src/libstd/env.rs b/src/libstd/env.rs index c66be35f3f6eb..114d0dd79a0a3 100644 --- a/src/libstd/env.rs +++ b/src/libstd/env.rs @@ -771,7 +771,7 @@ mod tests { } fn eq(a: Option, b: Option<&str>) { - assert_eq!(a.as_ref().map(|s| &**s), b.map(OsStr::from_str).map(|s| &*s)); + assert_eq!(a.as_ref().map(|s| &**s), b.map(OsStr::new).map(|s| &*s)); } #[test] @@ -894,7 +894,7 @@ mod tests { fn join_paths_unix() { fn test_eq(input: &[&str], output: &str) -> bool { &*join_paths(input.iter().cloned()).unwrap() == - OsStr::from_str(output) + OsStr::new(output) } assert!(test_eq(&[], "")); @@ -910,7 +910,7 @@ mod tests { fn join_paths_windows() { fn test_eq(input: &[&str], output: &str) -> bool { &*join_paths(input.iter().cloned()).unwrap() == - OsStr::from_str(output) + OsStr::new(output) } assert!(test_eq(&[], "")); diff --git a/src/libstd/lib.rs b/src/libstd/lib.rs index addd3c4d0a3bd..7821ebede02ec 100644 --- a/src/libstd/lib.rs +++ b/src/libstd/lib.rs @@ -129,6 +129,7 @@ #![feature(slice_patterns)] #![feature(debug_builders)] #![feature(zero_one)] +#![cfg_attr(test, feature(float_from_str_radix))] #![cfg_attr(test, feature(test, rustc_private, std_misc))] // Don't link to std. We are std. diff --git a/src/libstd/num/f32.rs b/src/libstd/num/f32.rs index 430fec4ff2e73..0efc04ef83c68 100644 --- a/src/libstd/num/f32.rs +++ b/src/libstd/num/f32.rs @@ -15,11 +15,13 @@ #![allow(unsigned_negation)] #![doc(primitive = "f32")] -use intrinsics; -use libc::c_int; -use num::FpCategory; +use prelude::v1::*; use core::num; +use intrinsics; +use libc::c_int; +use num::{FpCategory, ParseFloatError}; +use sys_common::FromInner; pub use core::f32::{RADIX, MANTISSA_DIGITS, DIGITS, EPSILON}; pub use core::f32::{MIN_EXP, MAX_EXP, MIN_10_EXP}; @@ -72,6 +74,12 @@ mod cmath { #[lang = "f32"] #[stable(feature = "rust1", since = "1.0.0")] impl f32 { + /// Parses a float as with a given radix + #[unstable(feature = "float_from_str_radix", reason = "recently moved API")] + pub fn from_str_radix(s: &str, radix: u32) -> Result { + num::Float::from_str_radix(s, radix).map_err(FromInner::from_inner) + } + /// Returns `true` if this value is `NaN` and false otherwise. /// /// ``` @@ -1021,7 +1029,7 @@ impl f32 { #[inline] pub fn acosh(self) -> f32 { match self { - x if x < 1.0 => num::Float::nan(), + x if x < 1.0 => ::f32::NAN, x => (x + ((x * x) - 1.0).sqrt()).ln(), } } @@ -1047,6 +1055,7 @@ impl f32 { #[cfg(test)] mod tests { + use f32; use f32::*; use num::*; use num::FpCategory as Fp; @@ -1070,7 +1079,7 @@ mod tests { #[test] fn test_nan() { - let nan: f32 = Float::nan(); + let nan: f32 = f32::NAN; assert!(nan.is_nan()); assert!(!nan.is_infinite()); assert!(!nan.is_finite()); @@ -1082,7 +1091,7 @@ mod tests { #[test] fn test_infinity() { - let inf: f32 = Float::infinity(); + let inf: f32 = f32::INFINITY; assert!(inf.is_infinite()); assert!(!inf.is_finite()); assert!(inf.is_sign_positive()); @@ -1094,7 +1103,7 @@ mod tests { #[test] fn test_neg_infinity() { - let neg_inf: f32 = Float::neg_infinity(); + let neg_inf: f32 = f32::NEG_INFINITY; assert!(neg_inf.is_infinite()); assert!(!neg_inf.is_finite()); assert!(!neg_inf.is_sign_positive()); @@ -1106,7 +1115,7 @@ mod tests { #[test] fn test_zero() { - let zero: f32 = Float::zero(); + let zero: f32 = 0.0f32; assert_eq!(0.0, zero); assert!(!zero.is_infinite()); assert!(zero.is_finite()); @@ -1119,7 +1128,7 @@ mod tests { #[test] fn test_neg_zero() { - let neg_zero: f32 = Float::neg_zero(); + let neg_zero: f32 = -0.0; assert_eq!(0.0, neg_zero); assert!(!neg_zero.is_infinite()); assert!(neg_zero.is_finite()); @@ -1132,7 +1141,7 @@ mod tests { #[test] fn test_one() { - let one: f32 = Float::one(); + let one: f32 = 1.0f32; assert_eq!(1.0, one); assert!(!one.is_infinite()); assert!(one.is_finite()); @@ -1145,9 +1154,9 @@ mod tests { #[test] fn test_is_nan() { - let nan: f32 = Float::nan(); - let inf: f32 = Float::infinity(); - let neg_inf: f32 = Float::neg_infinity(); + let nan: f32 = f32::NAN; + let inf: f32 = f32::INFINITY; + let neg_inf: f32 = f32::NEG_INFINITY; assert!(nan.is_nan()); assert!(!0.0f32.is_nan()); assert!(!5.3f32.is_nan()); @@ -1158,9 +1167,9 @@ mod tests { #[test] fn test_is_infinite() { - let nan: f32 = Float::nan(); - let inf: f32 = Float::infinity(); - let neg_inf: f32 = Float::neg_infinity(); + let nan: f32 = f32::NAN; + let inf: f32 = f32::INFINITY; + let neg_inf: f32 = f32::NEG_INFINITY; assert!(!nan.is_infinite()); assert!(inf.is_infinite()); assert!(neg_inf.is_infinite()); @@ -1171,9 +1180,9 @@ mod tests { #[test] fn test_is_finite() { - let nan: f32 = Float::nan(); - let inf: f32 = Float::infinity(); - let neg_inf: f32 = Float::neg_infinity(); + let nan: f32 = f32::NAN; + let inf: f32 = f32::INFINITY; + let neg_inf: f32 = f32::NEG_INFINITY; assert!(!nan.is_finite()); assert!(!inf.is_finite()); assert!(!neg_inf.is_finite()); @@ -1184,11 +1193,11 @@ mod tests { #[test] fn test_is_normal() { - let nan: f32 = Float::nan(); - let inf: f32 = Float::infinity(); - let neg_inf: f32 = Float::neg_infinity(); - let zero: f32 = Float::zero(); - let neg_zero: f32 = Float::neg_zero(); + let nan: f32 = f32::NAN; + let inf: f32 = f32::INFINITY; + let neg_inf: f32 = f32::NEG_INFINITY; + let zero: f32 = 0.0f32; + let neg_zero: f32 = -0.0; assert!(!nan.is_normal()); assert!(!inf.is_normal()); assert!(!neg_inf.is_normal()); @@ -1201,11 +1210,11 @@ mod tests { #[test] fn test_classify() { - let nan: f32 = Float::nan(); - let inf: f32 = Float::infinity(); - let neg_inf: f32 = Float::neg_infinity(); - let zero: f32 = Float::zero(); - let neg_zero: f32 = Float::neg_zero(); + let nan: f32 = f32::NAN; + let inf: f32 = f32::INFINITY; + let neg_inf: f32 = f32::NEG_INFINITY; + let zero: f32 = 0.0f32; + let neg_zero: f32 = -0.0; assert_eq!(nan.classify(), Fp::Nan); assert_eq!(inf.classify(), Fp::Infinite); assert_eq!(neg_inf.classify(), Fp::Infinite); @@ -1348,9 +1357,9 @@ mod tests { #[test] fn test_mul_add() { - let nan: f32 = Float::nan(); - let inf: f32 = Float::infinity(); - let neg_inf: f32 = Float::neg_infinity(); + let nan: f32 = f32::NAN; + let inf: f32 = f32::INFINITY; + let neg_inf: f32 = f32::NEG_INFINITY; assert_approx_eq!(12.3f32.mul_add(4.5, 6.7), 62.05); assert_approx_eq!((-12.3f32).mul_add(-4.5, -6.7), 48.65); assert_approx_eq!(0.0f32.mul_add(8.9, 1.2), 1.2); @@ -1364,9 +1373,9 @@ mod tests { #[test] fn test_recip() { - let nan: f32 = Float::nan(); - let inf: f32 = Float::infinity(); - let neg_inf: f32 = Float::neg_infinity(); + let nan: f32 = f32::NAN; + let inf: f32 = f32::INFINITY; + let neg_inf: f32 = f32::NEG_INFINITY; assert_eq!(1.0f32.recip(), 1.0); assert_eq!(2.0f32.recip(), 0.5); assert_eq!((-0.4f32).recip(), -2.5); @@ -1378,9 +1387,9 @@ mod tests { #[test] fn test_powi() { - let nan: f32 = Float::nan(); - let inf: f32 = Float::infinity(); - let neg_inf: f32 = Float::neg_infinity(); + let nan: f32 = f32::NAN; + let inf: f32 = f32::INFINITY; + let neg_inf: f32 = f32::NEG_INFINITY; assert_eq!(1.0f32.powi(1), 1.0); assert_approx_eq!((-3.1f32).powi(2), 9.61); assert_approx_eq!(5.9f32.powi(-2), 0.028727); @@ -1392,9 +1401,9 @@ mod tests { #[test] fn test_powf() { - let nan: f32 = Float::nan(); - let inf: f32 = Float::infinity(); - let neg_inf: f32 = Float::neg_infinity(); + let nan: f32 = f32::NAN; + let inf: f32 = f32::INFINITY; + let neg_inf: f32 = f32::NEG_INFINITY; assert_eq!(1.0f32.powf(1.0), 1.0); assert_approx_eq!(3.4f32.powf(4.5), 246.408218); assert_approx_eq!(2.7f32.powf(-3.2), 0.041652); @@ -1417,30 +1426,15 @@ mod tests { assert_eq!(INFINITY.sqrt(), INFINITY); } - #[test] - fn test_rsqrt() { - let nan: f32 = Float::nan(); - let inf: f32 = Float::infinity(); - let neg_inf: f32 = Float::neg_infinity(); - assert!(nan.rsqrt().is_nan()); - assert_eq!(inf.rsqrt(), 0.0); - assert!(neg_inf.rsqrt().is_nan()); - assert!((-1.0f32).rsqrt().is_nan()); - assert_eq!((-0.0f32).rsqrt(), neg_inf); - assert_eq!(0.0f32.rsqrt(), inf); - assert_eq!(1.0f32.rsqrt(), 1.0); - assert_eq!(4.0f32.rsqrt(), 0.5); - } - #[test] fn test_exp() { assert_eq!(1.0, 0.0f32.exp()); assert_approx_eq!(2.718282, 1.0f32.exp()); assert_approx_eq!(148.413162, 5.0f32.exp()); - let inf: f32 = Float::infinity(); - let neg_inf: f32 = Float::neg_infinity(); - let nan: f32 = Float::nan(); + let inf: f32 = f32::INFINITY; + let neg_inf: f32 = f32::NEG_INFINITY; + let nan: f32 = f32::NAN; assert_eq!(inf, inf.exp()); assert_eq!(0.0, neg_inf.exp()); assert!(nan.exp().is_nan()); @@ -1451,9 +1445,9 @@ mod tests { assert_eq!(32.0, 5.0f32.exp2()); assert_eq!(1.0, 0.0f32.exp2()); - let inf: f32 = Float::infinity(); - let neg_inf: f32 = Float::neg_infinity(); - let nan: f32 = Float::nan(); + let inf: f32 = f32::INFINITY; + let neg_inf: f32 = f32::NEG_INFINITY; + let nan: f32 = f32::NAN; assert_eq!(inf, inf.exp2()); assert_eq!(0.0, neg_inf.exp2()); assert!(nan.exp2().is_nan()); @@ -1461,9 +1455,9 @@ mod tests { #[test] fn test_ln() { - let nan: f32 = Float::nan(); - let inf: f32 = Float::infinity(); - let neg_inf: f32 = Float::neg_infinity(); + let nan: f32 = f32::NAN; + let inf: f32 = f32::INFINITY; + let neg_inf: f32 = f32::NEG_INFINITY; assert_approx_eq!(1.0f32.exp().ln(), 1.0); assert!(nan.ln().is_nan()); assert_eq!(inf.ln(), inf); @@ -1476,12 +1470,12 @@ mod tests { #[test] fn test_log() { - let nan: f32 = Float::nan(); - let inf: f32 = Float::infinity(); - let neg_inf: f32 = Float::neg_infinity(); + let nan: f32 = f32::NAN; + let inf: f32 = f32::INFINITY; + let neg_inf: f32 = f32::NEG_INFINITY; assert_eq!(10.0f32.log(10.0), 1.0); assert_approx_eq!(2.3f32.log(3.5), 0.664858); - assert_eq!(1.0f32.exp().log(1.0.exp()), 1.0); + assert_eq!(1.0f32.exp().log(1.0f32.exp()), 1.0); assert!(1.0f32.log(1.0).is_nan()); assert!(1.0f32.log(-13.9).is_nan()); assert!(nan.log(2.3).is_nan()); @@ -1494,9 +1488,9 @@ mod tests { #[test] fn test_log2() { - let nan: f32 = Float::nan(); - let inf: f32 = Float::infinity(); - let neg_inf: f32 = Float::neg_infinity(); + let nan: f32 = f32::NAN; + let inf: f32 = f32::INFINITY; + let neg_inf: f32 = f32::NEG_INFINITY; assert_approx_eq!(10.0f32.log2(), 3.321928); assert_approx_eq!(2.3f32.log2(), 1.201634); assert_approx_eq!(1.0f32.exp().log2(), 1.442695); @@ -1510,9 +1504,9 @@ mod tests { #[test] fn test_log10() { - let nan: f32 = Float::nan(); - let inf: f32 = Float::infinity(); - let neg_inf: f32 = Float::neg_infinity(); + let nan: f32 = f32::NAN; + let inf: f32 = f32::INFINITY; + let neg_inf: f32 = f32::NEG_INFINITY; assert_eq!(10.0f32.log10(), 1.0); assert_approx_eq!(2.3f32.log10(), 0.361728); assert_approx_eq!(1.0f32.exp().log10(), 0.434294); @@ -1528,9 +1522,9 @@ mod tests { #[test] fn test_to_degrees() { let pi: f32 = consts::PI; - let nan: f32 = Float::nan(); - let inf: f32 = Float::infinity(); - let neg_inf: f32 = Float::neg_infinity(); + let nan: f32 = f32::NAN; + let inf: f32 = f32::INFINITY; + let neg_inf: f32 = f32::NEG_INFINITY; assert_eq!(0.0f32.to_degrees(), 0.0); assert_approx_eq!((-5.8f32).to_degrees(), -332.315521); assert_eq!(pi.to_degrees(), 180.0); @@ -1542,9 +1536,9 @@ mod tests { #[test] fn test_to_radians() { let pi: f32 = consts::PI; - let nan: f32 = Float::nan(); - let inf: f32 = Float::infinity(); - let neg_inf: f32 = Float::neg_infinity(); + let nan: f32 = f32::NAN; + let inf: f32 = f32::INFINITY; + let neg_inf: f32 = f32::NEG_INFINITY; assert_eq!(0.0f32.to_radians(), 0.0); assert_approx_eq!(154.6f32.to_radians(), 2.698279); assert_approx_eq!((-332.31f32).to_radians(), -5.799903); @@ -1558,40 +1552,40 @@ mod tests { fn test_ldexp() { // We have to use from_str until base-2 exponents // are supported in floating-point literals - let f1: f32 = FromStrRadix::from_str_radix("1p-123", 16).unwrap(); - let f2: f32 = FromStrRadix::from_str_radix("1p-111", 16).unwrap(); - let f3: f32 = FromStrRadix::from_str_radix("1.Cp-12", 16).unwrap(); - assert_eq!(1f32.ldexp(-123), f1); - assert_eq!(1f32.ldexp(-111), f2); - assert_eq!(Float::ldexp(1.75f32, -12), f3); + let f1: f32 = f32::from_str_radix("1p-123", 16).unwrap(); + let f2: f32 = f32::from_str_radix("1p-111", 16).unwrap(); + let f3: f32 = f32::from_str_radix("1.Cp-12", 16).unwrap(); + assert_eq!(f32::ldexp(1f32, -123), f1); + assert_eq!(f32::ldexp(1f32, -111), f2); + assert_eq!(f32::ldexp(1.75f32, -12), f3); - assert_eq!(Float::ldexp(0f32, -123), 0f32); - assert_eq!(Float::ldexp(-0f32, -123), -0f32); + assert_eq!(f32::ldexp(0f32, -123), 0f32); + assert_eq!(f32::ldexp(-0f32, -123), -0f32); - let inf: f32 = Float::infinity(); - let neg_inf: f32 = Float::neg_infinity(); - let nan: f32 = Float::nan(); - assert_eq!(Float::ldexp(inf, -123), inf); - assert_eq!(Float::ldexp(neg_inf, -123), neg_inf); - assert!(Float::ldexp(nan, -123).is_nan()); + let inf: f32 = f32::INFINITY; + let neg_inf: f32 = f32::NEG_INFINITY; + let nan: f32 = f32::NAN; + assert_eq!(f32::ldexp(inf, -123), inf); + assert_eq!(f32::ldexp(neg_inf, -123), neg_inf); + assert!(f32::ldexp(nan, -123).is_nan()); } #[test] fn test_frexp() { // We have to use from_str until base-2 exponents // are supported in floating-point literals - let f1: f32 = FromStrRadix::from_str_radix("1p-123", 16).unwrap(); - let f2: f32 = FromStrRadix::from_str_radix("1p-111", 16).unwrap(); - let f3: f32 = FromStrRadix::from_str_radix("1.Cp-123", 16).unwrap(); + let f1: f32 = f32::from_str_radix("1p-123", 16).unwrap(); + let f2: f32 = f32::from_str_radix("1p-111", 16).unwrap(); + let f3: f32 = f32::from_str_radix("1.Cp-123", 16).unwrap(); let (x1, exp1) = f1.frexp(); let (x2, exp2) = f2.frexp(); let (x3, exp3) = f3.frexp(); assert_eq!((x1, exp1), (0.5f32, -122)); assert_eq!((x2, exp2), (0.5f32, -110)); assert_eq!((x3, exp3), (0.875f32, -122)); - assert_eq!(Float::ldexp(x1, exp1), f1); - assert_eq!(Float::ldexp(x2, exp2), f2); - assert_eq!(Float::ldexp(x3, exp3), f3); + assert_eq!(f32::ldexp(x1, exp1), f1); + assert_eq!(f32::ldexp(x2, exp2), f2); + assert_eq!(f32::ldexp(x3, exp3), f3); assert_eq!(0f32.frexp(), (0f32, 0)); assert_eq!((-0f32).frexp(), (-0f32, 0)); @@ -1599,9 +1593,9 @@ mod tests { #[test] #[cfg_attr(windows, ignore)] // FIXME #8755 fn test_frexp_nowin() { - let inf: f32 = Float::infinity(); - let neg_inf: f32 = Float::neg_infinity(); - let nan: f32 = Float::nan(); + let inf: f32 = f32::INFINITY; + let neg_inf: f32 = f32::NEG_INFINITY; + let nan: f32 = f32::NAN; assert_eq!(match inf.frexp() { (x, _) => x }, inf); assert_eq!(match neg_inf.frexp() { (x, _) => x }, neg_inf); assert!(match nan.frexp() { (x, _) => x.is_nan() }) @@ -1630,9 +1624,9 @@ mod tests { assert_eq!(0.0f32.asinh(), 0.0f32); assert_eq!((-0.0f32).asinh(), -0.0f32); - let inf: f32 = Float::infinity(); - let neg_inf: f32 = Float::neg_infinity(); - let nan: f32 = Float::nan(); + let inf: f32 = f32::INFINITY; + let neg_inf: f32 = f32::NEG_INFINITY; + let nan: f32 = f32::NAN; assert_eq!(inf.asinh(), inf); assert_eq!(neg_inf.asinh(), neg_inf); assert!(nan.asinh().is_nan()); @@ -1645,9 +1639,9 @@ mod tests { assert_eq!(1.0f32.acosh(), 0.0f32); assert!(0.999f32.acosh().is_nan()); - let inf: f32 = Float::infinity(); - let neg_inf: f32 = Float::neg_infinity(); - let nan: f32 = Float::nan(); + let inf: f32 = f32::INFINITY; + let neg_inf: f32 = f32::NEG_INFINITY; + let nan: f32 = f32::NAN; assert_eq!(inf.acosh(), inf); assert!(neg_inf.acosh().is_nan()); assert!(nan.acosh().is_nan()); @@ -1660,17 +1654,17 @@ mod tests { assert_eq!(0.0f32.atanh(), 0.0f32); assert_eq!((-0.0f32).atanh(), -0.0f32); - let inf32: f32 = Float::infinity(); - let neg_inf32: f32 = Float::neg_infinity(); + let inf32: f32 = f32::INFINITY; + let neg_inf32: f32 = f32::NEG_INFINITY; assert_eq!(1.0f32.atanh(), inf32); assert_eq!((-1.0f32).atanh(), neg_inf32); assert!(2f64.atanh().atanh().is_nan()); assert!((-2f64).atanh().atanh().is_nan()); - let inf64: f32 = Float::infinity(); - let neg_inf64: f32 = Float::neg_infinity(); - let nan32: f32 = Float::nan(); + let inf64: f32 = f32::INFINITY; + let neg_inf64: f32 = f32::NEG_INFINITY; + let nan32: f32 = f32::NAN; assert!(inf64.atanh().is_nan()); assert!(neg_inf64.atanh().is_nan()); assert!(nan32.atanh().is_nan()); @@ -1692,9 +1686,9 @@ mod tests { let frac_pi_8: f32 = consts::FRAC_PI_8; let frac_1_pi: f32 = consts::FRAC_1_PI; let frac_2_pi: f32 = consts::FRAC_2_PI; - let frac_2_sqrtpi: f32 = consts::FRAC_2_SQRTPI; - let sqrt2: f32 = consts::SQRT2; - let frac_1_sqrt2: f32 = consts::FRAC_1_SQRT2; + let frac_2_sqrtpi: f32 = consts::FRAC_2_SQRT_PI; + let sqrt2: f32 = consts::SQRT_2; + let frac_1_sqrt2: f32 = consts::FRAC_1_SQRT_2; let e: f32 = consts::E; let log2_e: f32 = consts::LOG2_E; let log10_e: f32 = consts::LOG10_E; diff --git a/src/libstd/num/f64.rs b/src/libstd/num/f64.rs index bd50a087c71b4..e1497f3958dab 100644 --- a/src/libstd/num/f64.rs +++ b/src/libstd/num/f64.rs @@ -14,11 +14,13 @@ #![allow(missing_docs)] #![doc(primitive = "f64")] -use intrinsics; -use libc::c_int; -use num::FpCategory; +use prelude::v1::*; use core::num; +use intrinsics; +use libc::c_int; +use num::{FpCategory, ParseFloatError}; +use sys_common::FromInner; pub use core::f64::{RADIX, MANTISSA_DIGITS, DIGITS, EPSILON}; pub use core::f64::{MIN_EXP, MAX_EXP, MIN_10_EXP}; @@ -80,6 +82,12 @@ mod cmath { #[lang = "f64"] #[stable(feature = "rust1", since = "1.0.0")] impl f64 { + /// Parses a float as with a given radix + #[unstable(feature = "float_from_str_radix", reason = "recently moved API")] + pub fn from_str_radix(s: &str, radix: u32) -> Result { + num::Float::from_str_radix(s, radix).map_err(FromInner::from_inner) + } + /// Returns `true` if this value is `NaN` and false otherwise. /// /// ``` @@ -435,22 +443,6 @@ impl f64 { #[inline] pub fn sqrt(self) -> f64 { num::Float::sqrt(self) } - /// Takes the reciprocal (inverse) square root of a number, `1/sqrt(x)`. - /// - /// ``` - /// # #![feature(std_misc)] - /// let f = 4.0_f64; - /// - /// let abs_difference = (f.rsqrt() - 0.5).abs(); - /// - /// assert!(abs_difference < 1e-10); - /// ``` - #[unstable(feature = "std_misc", - reason = "unsure about its place in the world")] - #[deprecated(since = "1.0.0", reason = "use self.sqrt().recip() instead")] - #[inline] - pub fn rsqrt(self) -> f64 { num::Float::rsqrt(self) } - /// Returns `e^(self)`, (the exponential function). /// /// ``` @@ -1013,7 +1005,7 @@ impl f64 { #[inline] pub fn acosh(self) -> f64 { match self { - x if x < 1.0 => num::Float::nan(), + x if x < 1.0 => NAN, x => (x + ((x * x) - 1.0).sqrt()).ln(), } } @@ -1039,6 +1031,7 @@ impl f64 { #[cfg(test)] mod tests { + use f64; use f64::*; use num::*; use num::FpCategory as Fp; @@ -1062,7 +1055,7 @@ mod tests { #[test] fn test_nan() { - let nan: f64 = Float::nan(); + let nan: f64 = NAN; assert!(nan.is_nan()); assert!(!nan.is_infinite()); assert!(!nan.is_finite()); @@ -1074,7 +1067,7 @@ mod tests { #[test] fn test_infinity() { - let inf: f64 = Float::infinity(); + let inf: f64 = INFINITY; assert!(inf.is_infinite()); assert!(!inf.is_finite()); assert!(inf.is_sign_positive()); @@ -1086,7 +1079,7 @@ mod tests { #[test] fn test_neg_infinity() { - let neg_inf: f64 = Float::neg_infinity(); + let neg_inf: f64 = NEG_INFINITY; assert!(neg_inf.is_infinite()); assert!(!neg_inf.is_finite()); assert!(!neg_inf.is_sign_positive()); @@ -1098,7 +1091,7 @@ mod tests { #[test] fn test_zero() { - let zero: f64 = Float::zero(); + let zero: f64 = 0.0f64; assert_eq!(0.0, zero); assert!(!zero.is_infinite()); assert!(zero.is_finite()); @@ -1111,7 +1104,7 @@ mod tests { #[test] fn test_neg_zero() { - let neg_zero: f64 = Float::neg_zero(); + let neg_zero: f64 = -0.0; assert_eq!(0.0, neg_zero); assert!(!neg_zero.is_infinite()); assert!(neg_zero.is_finite()); @@ -1124,7 +1117,7 @@ mod tests { #[test] fn test_one() { - let one: f64 = Float::one(); + let one: f64 = 1.0f64; assert_eq!(1.0, one); assert!(!one.is_infinite()); assert!(one.is_finite()); @@ -1137,9 +1130,9 @@ mod tests { #[test] fn test_is_nan() { - let nan: f64 = Float::nan(); - let inf: f64 = Float::infinity(); - let neg_inf: f64 = Float::neg_infinity(); + let nan: f64 = NAN; + let inf: f64 = INFINITY; + let neg_inf: f64 = NEG_INFINITY; assert!(nan.is_nan()); assert!(!0.0f64.is_nan()); assert!(!5.3f64.is_nan()); @@ -1150,9 +1143,9 @@ mod tests { #[test] fn test_is_infinite() { - let nan: f64 = Float::nan(); - let inf: f64 = Float::infinity(); - let neg_inf: f64 = Float::neg_infinity(); + let nan: f64 = NAN; + let inf: f64 = INFINITY; + let neg_inf: f64 = NEG_INFINITY; assert!(!nan.is_infinite()); assert!(inf.is_infinite()); assert!(neg_inf.is_infinite()); @@ -1163,9 +1156,9 @@ mod tests { #[test] fn test_is_finite() { - let nan: f64 = Float::nan(); - let inf: f64 = Float::infinity(); - let neg_inf: f64 = Float::neg_infinity(); + let nan: f64 = NAN; + let inf: f64 = INFINITY; + let neg_inf: f64 = NEG_INFINITY; assert!(!nan.is_finite()); assert!(!inf.is_finite()); assert!(!neg_inf.is_finite()); @@ -1176,11 +1169,11 @@ mod tests { #[test] fn test_is_normal() { - let nan: f64 = Float::nan(); - let inf: f64 = Float::infinity(); - let neg_inf: f64 = Float::neg_infinity(); - let zero: f64 = Float::zero(); - let neg_zero: f64 = Float::neg_zero(); + let nan: f64 = NAN; + let inf: f64 = INFINITY; + let neg_inf: f64 = NEG_INFINITY; + let zero: f64 = 0.0f64; + let neg_zero: f64 = -0.0; assert!(!nan.is_normal()); assert!(!inf.is_normal()); assert!(!neg_inf.is_normal()); @@ -1193,11 +1186,11 @@ mod tests { #[test] fn test_classify() { - let nan: f64 = Float::nan(); - let inf: f64 = Float::infinity(); - let neg_inf: f64 = Float::neg_infinity(); - let zero: f64 = Float::zero(); - let neg_zero: f64 = Float::neg_zero(); + let nan: f64 = NAN; + let inf: f64 = INFINITY; + let neg_inf: f64 = NEG_INFINITY; + let zero: f64 = 0.0f64; + let neg_zero: f64 = -0.0; assert_eq!(nan.classify(), Fp::Nan); assert_eq!(inf.classify(), Fp::Infinite); assert_eq!(neg_inf.classify(), Fp::Infinite); @@ -1339,9 +1332,9 @@ mod tests { #[test] fn test_mul_add() { - let nan: f64 = Float::nan(); - let inf: f64 = Float::infinity(); - let neg_inf: f64 = Float::neg_infinity(); + let nan: f64 = NAN; + let inf: f64 = INFINITY; + let neg_inf: f64 = NEG_INFINITY; assert_approx_eq!(12.3f64.mul_add(4.5, 6.7), 62.05); assert_approx_eq!((-12.3f64).mul_add(-4.5, -6.7), 48.65); assert_approx_eq!(0.0f64.mul_add(8.9, 1.2), 1.2); @@ -1355,9 +1348,9 @@ mod tests { #[test] fn test_recip() { - let nan: f64 = Float::nan(); - let inf: f64 = Float::infinity(); - let neg_inf: f64 = Float::neg_infinity(); + let nan: f64 = NAN; + let inf: f64 = INFINITY; + let neg_inf: f64 = NEG_INFINITY; assert_eq!(1.0f64.recip(), 1.0); assert_eq!(2.0f64.recip(), 0.5); assert_eq!((-0.4f64).recip(), -2.5); @@ -1369,9 +1362,9 @@ mod tests { #[test] fn test_powi() { - let nan: f64 = Float::nan(); - let inf: f64 = Float::infinity(); - let neg_inf: f64 = Float::neg_infinity(); + let nan: f64 = NAN; + let inf: f64 = INFINITY; + let neg_inf: f64 = NEG_INFINITY; assert_eq!(1.0f64.powi(1), 1.0); assert_approx_eq!((-3.1f64).powi(2), 9.61); assert_approx_eq!(5.9f64.powi(-2), 0.028727); @@ -1383,9 +1376,9 @@ mod tests { #[test] fn test_powf() { - let nan: f64 = Float::nan(); - let inf: f64 = Float::infinity(); - let neg_inf: f64 = Float::neg_infinity(); + let nan: f64 = NAN; + let inf: f64 = INFINITY; + let neg_inf: f64 = NEG_INFINITY; assert_eq!(1.0f64.powf(1.0), 1.0); assert_approx_eq!(3.4f64.powf(4.5), 246.408183); assert_approx_eq!(2.7f64.powf(-3.2), 0.041652); @@ -1408,30 +1401,15 @@ mod tests { assert_eq!(INFINITY.sqrt(), INFINITY); } - #[test] - fn test_rsqrt() { - let nan: f64 = Float::nan(); - let inf: f64 = Float::infinity(); - let neg_inf: f64 = Float::neg_infinity(); - assert!(nan.rsqrt().is_nan()); - assert_eq!(inf.rsqrt(), 0.0); - assert!(neg_inf.rsqrt().is_nan()); - assert!((-1.0f64).rsqrt().is_nan()); - assert_eq!((-0.0f64).rsqrt(), neg_inf); - assert_eq!(0.0f64.rsqrt(), inf); - assert_eq!(1.0f64.rsqrt(), 1.0); - assert_eq!(4.0f64.rsqrt(), 0.5); - } - #[test] fn test_exp() { assert_eq!(1.0, 0.0f64.exp()); assert_approx_eq!(2.718282, 1.0f64.exp()); assert_approx_eq!(148.413159, 5.0f64.exp()); - let inf: f64 = Float::infinity(); - let neg_inf: f64 = Float::neg_infinity(); - let nan: f64 = Float::nan(); + let inf: f64 = INFINITY; + let neg_inf: f64 = NEG_INFINITY; + let nan: f64 = NAN; assert_eq!(inf, inf.exp()); assert_eq!(0.0, neg_inf.exp()); assert!(nan.exp().is_nan()); @@ -1442,9 +1420,9 @@ mod tests { assert_eq!(32.0, 5.0f64.exp2()); assert_eq!(1.0, 0.0f64.exp2()); - let inf: f64 = Float::infinity(); - let neg_inf: f64 = Float::neg_infinity(); - let nan: f64 = Float::nan(); + let inf: f64 = INFINITY; + let neg_inf: f64 = NEG_INFINITY; + let nan: f64 = NAN; assert_eq!(inf, inf.exp2()); assert_eq!(0.0, neg_inf.exp2()); assert!(nan.exp2().is_nan()); @@ -1452,9 +1430,9 @@ mod tests { #[test] fn test_ln() { - let nan: f64 = Float::nan(); - let inf: f64 = Float::infinity(); - let neg_inf: f64 = Float::neg_infinity(); + let nan: f64 = NAN; + let inf: f64 = INFINITY; + let neg_inf: f64 = NEG_INFINITY; assert_approx_eq!(1.0f64.exp().ln(), 1.0); assert!(nan.ln().is_nan()); assert_eq!(inf.ln(), inf); @@ -1467,12 +1445,12 @@ mod tests { #[test] fn test_log() { - let nan: f64 = Float::nan(); - let inf: f64 = Float::infinity(); - let neg_inf: f64 = Float::neg_infinity(); + let nan: f64 = NAN; + let inf: f64 = INFINITY; + let neg_inf: f64 = NEG_INFINITY; assert_eq!(10.0f64.log(10.0), 1.0); assert_approx_eq!(2.3f64.log(3.5), 0.664858); - assert_eq!(1.0f64.exp().log(1.0.exp()), 1.0); + assert_eq!(1.0f64.exp().log(1.0f64.exp()), 1.0); assert!(1.0f64.log(1.0).is_nan()); assert!(1.0f64.log(-13.9).is_nan()); assert!(nan.log(2.3).is_nan()); @@ -1485,9 +1463,9 @@ mod tests { #[test] fn test_log2() { - let nan: f64 = Float::nan(); - let inf: f64 = Float::infinity(); - let neg_inf: f64 = Float::neg_infinity(); + let nan: f64 = NAN; + let inf: f64 = INFINITY; + let neg_inf: f64 = NEG_INFINITY; assert_approx_eq!(10.0f64.log2(), 3.321928); assert_approx_eq!(2.3f64.log2(), 1.201634); assert_approx_eq!(1.0f64.exp().log2(), 1.442695); @@ -1501,9 +1479,9 @@ mod tests { #[test] fn test_log10() { - let nan: f64 = Float::nan(); - let inf: f64 = Float::infinity(); - let neg_inf: f64 = Float::neg_infinity(); + let nan: f64 = NAN; + let inf: f64 = INFINITY; + let neg_inf: f64 = NEG_INFINITY; assert_eq!(10.0f64.log10(), 1.0); assert_approx_eq!(2.3f64.log10(), 0.361728); assert_approx_eq!(1.0f64.exp().log10(), 0.434294); @@ -1519,9 +1497,9 @@ mod tests { #[test] fn test_to_degrees() { let pi: f64 = consts::PI; - let nan: f64 = Float::nan(); - let inf: f64 = Float::infinity(); - let neg_inf: f64 = Float::neg_infinity(); + let nan: f64 = NAN; + let inf: f64 = INFINITY; + let neg_inf: f64 = NEG_INFINITY; assert_eq!(0.0f64.to_degrees(), 0.0); assert_approx_eq!((-5.8f64).to_degrees(), -332.315521); assert_eq!(pi.to_degrees(), 180.0); @@ -1533,9 +1511,9 @@ mod tests { #[test] fn test_to_radians() { let pi: f64 = consts::PI; - let nan: f64 = Float::nan(); - let inf: f64 = Float::infinity(); - let neg_inf: f64 = Float::neg_infinity(); + let nan: f64 = NAN; + let inf: f64 = INFINITY; + let neg_inf: f64 = NEG_INFINITY; assert_eq!(0.0f64.to_radians(), 0.0); assert_approx_eq!(154.6f64.to_radians(), 2.698279); assert_approx_eq!((-332.31f64).to_radians(), -5.799903); @@ -1549,40 +1527,40 @@ mod tests { fn test_ldexp() { // We have to use from_str until base-2 exponents // are supported in floating-point literals - let f1: f64 = FromStrRadix::from_str_radix("1p-123", 16).unwrap(); - let f2: f64 = FromStrRadix::from_str_radix("1p-111", 16).unwrap(); - let f3: f64 = FromStrRadix::from_str_radix("1.Cp-12", 16).unwrap(); - assert_eq!(1f64.ldexp(-123), f1); - assert_eq!(1f64.ldexp(-111), f2); - assert_eq!(Float::ldexp(1.75f64, -12), f3); + let f1: f64 = f64::from_str_radix("1p-123", 16).unwrap(); + let f2: f64 = f64::from_str_radix("1p-111", 16).unwrap(); + let f3: f64 = f64::from_str_radix("1.Cp-12", 16).unwrap(); + assert_eq!(f64::ldexp(1f64, -123), f1); + assert_eq!(f64::ldexp(1f64, -111), f2); + assert_eq!(f64::ldexp(1.75f64, -12), f3); - assert_eq!(Float::ldexp(0f64, -123), 0f64); - assert_eq!(Float::ldexp(-0f64, -123), -0f64); + assert_eq!(f64::ldexp(0f64, -123), 0f64); + assert_eq!(f64::ldexp(-0f64, -123), -0f64); - let inf: f64 = Float::infinity(); - let neg_inf: f64 = Float::neg_infinity(); - let nan: f64 = Float::nan(); - assert_eq!(Float::ldexp(inf, -123), inf); - assert_eq!(Float::ldexp(neg_inf, -123), neg_inf); - assert!(Float::ldexp(nan, -123).is_nan()); + let inf: f64 = INFINITY; + let neg_inf: f64 = NEG_INFINITY; + let nan: f64 = NAN; + assert_eq!(f64::ldexp(inf, -123), inf); + assert_eq!(f64::ldexp(neg_inf, -123), neg_inf); + assert!(f64::ldexp(nan, -123).is_nan()); } #[test] fn test_frexp() { // We have to use from_str until base-2 exponents // are supported in floating-point literals - let f1: f64 = FromStrRadix::from_str_radix("1p-123", 16).unwrap(); - let f2: f64 = FromStrRadix::from_str_radix("1p-111", 16).unwrap(); - let f3: f64 = FromStrRadix::from_str_radix("1.Cp-123", 16).unwrap(); + let f1: f64 = f64::from_str_radix("1p-123", 16).unwrap(); + let f2: f64 = f64::from_str_radix("1p-111", 16).unwrap(); + let f3: f64 = f64::from_str_radix("1.Cp-123", 16).unwrap(); let (x1, exp1) = f1.frexp(); let (x2, exp2) = f2.frexp(); let (x3, exp3) = f3.frexp(); assert_eq!((x1, exp1), (0.5f64, -122)); assert_eq!((x2, exp2), (0.5f64, -110)); assert_eq!((x3, exp3), (0.875f64, -122)); - assert_eq!(Float::ldexp(x1, exp1), f1); - assert_eq!(Float::ldexp(x2, exp2), f2); - assert_eq!(Float::ldexp(x3, exp3), f3); + assert_eq!(f64::ldexp(x1, exp1), f1); + assert_eq!(f64::ldexp(x2, exp2), f2); + assert_eq!(f64::ldexp(x3, exp3), f3); assert_eq!(0f64.frexp(), (0f64, 0)); assert_eq!((-0f64).frexp(), (-0f64, 0)); @@ -1590,9 +1568,9 @@ mod tests { #[test] #[cfg_attr(windows, ignore)] // FIXME #8755 fn test_frexp_nowin() { - let inf: f64 = Float::infinity(); - let neg_inf: f64 = Float::neg_infinity(); - let nan: f64 = Float::nan(); + let inf: f64 = INFINITY; + let neg_inf: f64 = NEG_INFINITY; + let nan: f64 = NAN; assert_eq!(match inf.frexp() { (x, _) => x }, inf); assert_eq!(match neg_inf.frexp() { (x, _) => x }, neg_inf); assert!(match nan.frexp() { (x, _) => x.is_nan() }) @@ -1621,9 +1599,9 @@ mod tests { assert_eq!(0.0f64.asinh(), 0.0f64); assert_eq!((-0.0f64).asinh(), -0.0f64); - let inf: f64 = Float::infinity(); - let neg_inf: f64 = Float::neg_infinity(); - let nan: f64 = Float::nan(); + let inf: f64 = INFINITY; + let neg_inf: f64 = NEG_INFINITY; + let nan: f64 = NAN; assert_eq!(inf.asinh(), inf); assert_eq!(neg_inf.asinh(), neg_inf); assert!(nan.asinh().is_nan()); @@ -1636,9 +1614,9 @@ mod tests { assert_eq!(1.0f64.acosh(), 0.0f64); assert!(0.999f64.acosh().is_nan()); - let inf: f64 = Float::infinity(); - let neg_inf: f64 = Float::neg_infinity(); - let nan: f64 = Float::nan(); + let inf: f64 = INFINITY; + let neg_inf: f64 = NEG_INFINITY; + let nan: f64 = NAN; assert_eq!(inf.acosh(), inf); assert!(neg_inf.acosh().is_nan()); assert!(nan.acosh().is_nan()); @@ -1651,9 +1629,9 @@ mod tests { assert_eq!(0.0f64.atanh(), 0.0f64); assert_eq!((-0.0f64).atanh(), -0.0f64); - let inf: f64 = Float::infinity(); - let neg_inf: f64 = Float::neg_infinity(); - let nan: f64 = Float::nan(); + let inf: f64 = INFINITY; + let neg_inf: f64 = NEG_INFINITY; + let nan: f64 = NAN; assert_eq!(1.0f64.atanh(), inf); assert_eq!((-1.0f64).atanh(), neg_inf); assert!(2f64.atanh().atanh().is_nan()); @@ -1677,9 +1655,9 @@ mod tests { let frac_pi_8: f64 = consts::FRAC_PI_8; let frac_1_pi: f64 = consts::FRAC_1_PI; let frac_2_pi: f64 = consts::FRAC_2_PI; - let frac_2_sqrtpi: f64 = consts::FRAC_2_SQRTPI; - let sqrt2: f64 = consts::SQRT2; - let frac_1_sqrt2: f64 = consts::FRAC_1_SQRT2; + let frac_2_sqrtpi: f64 = consts::FRAC_2_SQRT_PI; + let sqrt2: f64 = consts::SQRT_2; + let frac_1_sqrt2: f64 = consts::FRAC_1_SQRT_2; let e: f64 = consts::E; let log2_e: f64 = consts::LOG2_E; let log10_e: f64 = consts::LOG10_E; diff --git a/src/libstd/num/mod.rs b/src/libstd/num/mod.rs index dbe06b773296b..cd26be013c41e 100644 --- a/src/libstd/num/mod.rs +++ b/src/libstd/num/mod.rs @@ -16,27 +16,26 @@ #![stable(feature = "rust1", since = "1.0.0")] #![allow(missing_docs)] -#[cfg(test)] use fmt::Debug; +use fmt; +use core::num; pub use core::num::{Zero, One}; -pub use core::num::{FpCategory, ParseIntError, ParseFloatError}; +pub use core::num::{FpCategory, ParseIntError}; pub use core::num::{wrapping, Wrapping}; +#[cfg(test)] use ops::{Add, Sub, Mul, Div, Rem}; +#[cfg(test)] use cmp::PartialEq; +#[cfg(test)] use marker::Copy; + /// Helper function for testing numeric operations #[cfg(test)] pub fn test_num(ten: T, two: T) where - T: PartialEq + NumCast + T: PartialEq + Add + Sub + Mul + Div - + Rem + Debug + + Rem + fmt::Debug + Copy { - assert_eq!(ten.add(two), cast(12).unwrap()); - assert_eq!(ten.sub(two), cast(8).unwrap()); - assert_eq!(ten.mul(two), cast(20).unwrap()); - assert_eq!(ten.div(two), cast(5).unwrap()); - assert_eq!(ten.rem(two), cast(0).unwrap()); - assert_eq!(ten.add(two), ten + two); assert_eq!(ten.sub(two), ten - two); assert_eq!(ten.mul(two), ten * two); @@ -44,6 +43,31 @@ pub fn test_num(ten: T, two: T) where assert_eq!(ten.rem(two), ten % two); } +/// An error which can be returned when parsing a float. +#[derive(Debug, Clone, PartialEq)] +#[stable(feature = "rust1", since = "1.0.0")] +pub struct ParseFloatError { inner: num::ParseFloatError } + +impl ::sys_common::FromInner for ParseFloatError { + fn from_inner(inner: num::ParseFloatError) -> ParseFloatError { + ParseFloatError { inner: inner } + } +} + +impl ParseFloatError { + #[unstable(feature = "core", reason = "available through Error trait")] + pub fn description(&self) -> &str { + self.inner.description() + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl fmt::Display for ParseFloatError { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + self.description().fmt(f) + } +} + #[cfg(test)] mod tests { use core::prelude::*; @@ -59,432 +83,7 @@ mod tests { use u64; use usize; use string::ToString; - - macro_rules! test_cast_20 { - ($_20:expr) => ({ - let _20 = $_20; - - assert_eq!(20usize, _20.to_uint().unwrap()); - assert_eq!(20u8, _20.to_u8().unwrap()); - assert_eq!(20u16, _20.to_u16().unwrap()); - assert_eq!(20u32, _20.to_u32().unwrap()); - assert_eq!(20u64, _20.to_u64().unwrap()); - assert_eq!(20, _20.to_int().unwrap()); - assert_eq!(20i8, _20.to_i8().unwrap()); - assert_eq!(20i16, _20.to_i16().unwrap()); - assert_eq!(20i32, _20.to_i32().unwrap()); - assert_eq!(20i64, _20.to_i64().unwrap()); - assert_eq!(20f32, _20.to_f32().unwrap()); - assert_eq!(20f64, _20.to_f64().unwrap()); - - assert_eq!(_20, NumCast::from(20usize).unwrap()); - assert_eq!(_20, NumCast::from(20u8).unwrap()); - assert_eq!(_20, NumCast::from(20u16).unwrap()); - assert_eq!(_20, NumCast::from(20u32).unwrap()); - assert_eq!(_20, NumCast::from(20u64).unwrap()); - assert_eq!(_20, NumCast::from(20).unwrap()); - assert_eq!(_20, NumCast::from(20i8).unwrap()); - assert_eq!(_20, NumCast::from(20i16).unwrap()); - assert_eq!(_20, NumCast::from(20i32).unwrap()); - assert_eq!(_20, NumCast::from(20i64).unwrap()); - assert_eq!(_20, NumCast::from(20f32).unwrap()); - assert_eq!(_20, NumCast::from(20f64).unwrap()); - - assert_eq!(_20, cast(20usize).unwrap()); - assert_eq!(_20, cast(20u8).unwrap()); - assert_eq!(_20, cast(20u16).unwrap()); - assert_eq!(_20, cast(20u32).unwrap()); - assert_eq!(_20, cast(20u64).unwrap()); - assert_eq!(_20, cast(20).unwrap()); - assert_eq!(_20, cast(20i8).unwrap()); - assert_eq!(_20, cast(20i16).unwrap()); - assert_eq!(_20, cast(20i32).unwrap()); - assert_eq!(_20, cast(20i64).unwrap()); - assert_eq!(_20, cast(20f32).unwrap()); - assert_eq!(_20, cast(20f64).unwrap()); - }) - } - - #[test] fn test_u8_cast() { test_cast_20!(20u8) } - #[test] fn test_u16_cast() { test_cast_20!(20u16) } - #[test] fn test_u32_cast() { test_cast_20!(20u32) } - #[test] fn test_u64_cast() { test_cast_20!(20u64) } - #[test] fn test_uint_cast() { test_cast_20!(20usize) } - #[test] fn test_i8_cast() { test_cast_20!(20i8) } - #[test] fn test_i16_cast() { test_cast_20!(20i16) } - #[test] fn test_i32_cast() { test_cast_20!(20i32) } - #[test] fn test_i64_cast() { test_cast_20!(20i64) } - #[test] fn test_int_cast() { test_cast_20!(20) } - #[test] fn test_f32_cast() { test_cast_20!(20f32) } - #[test] fn test_f64_cast() { test_cast_20!(20f64) } - - #[test] - fn test_cast_range_int_min() { - assert_eq!(isize::MIN.to_int(), Some(isize::MIN as isize)); - assert_eq!(isize::MIN.to_i8(), None); - assert_eq!(isize::MIN.to_i16(), None); - // isize::MIN.to_i32() is word-size specific - assert_eq!(isize::MIN.to_i64(), Some(isize::MIN as i64)); - assert_eq!(isize::MIN.to_uint(), None); - assert_eq!(isize::MIN.to_u8(), None); - assert_eq!(isize::MIN.to_u16(), None); - assert_eq!(isize::MIN.to_u32(), None); - assert_eq!(isize::MIN.to_u64(), None); - - #[cfg(target_pointer_width = "32")] - fn check_word_size() { - assert_eq!(isize::MIN.to_i32(), Some(isize::MIN as i32)); - } - - #[cfg(target_pointer_width = "64")] - fn check_word_size() { - assert_eq!(isize::MIN.to_i32(), None); - } - - check_word_size(); - } - - #[test] - fn test_cast_range_i8_min() { - assert_eq!(i8::MIN.to_int(), Some(i8::MIN as isize)); - assert_eq!(i8::MIN.to_i8(), Some(i8::MIN as i8)); - assert_eq!(i8::MIN.to_i16(), Some(i8::MIN as i16)); - assert_eq!(i8::MIN.to_i32(), Some(i8::MIN as i32)); - assert_eq!(i8::MIN.to_i64(), Some(i8::MIN as i64)); - assert_eq!(i8::MIN.to_uint(), None); - assert_eq!(i8::MIN.to_u8(), None); - assert_eq!(i8::MIN.to_u16(), None); - assert_eq!(i8::MIN.to_u32(), None); - assert_eq!(i8::MIN.to_u64(), None); - } - - #[test] - fn test_cast_range_i16_min() { - assert_eq!(i16::MIN.to_int(), Some(i16::MIN as isize)); - assert_eq!(i16::MIN.to_i8(), None); - assert_eq!(i16::MIN.to_i16(), Some(i16::MIN as i16)); - assert_eq!(i16::MIN.to_i32(), Some(i16::MIN as i32)); - assert_eq!(i16::MIN.to_i64(), Some(i16::MIN as i64)); - assert_eq!(i16::MIN.to_uint(), None); - assert_eq!(i16::MIN.to_u8(), None); - assert_eq!(i16::MIN.to_u16(), None); - assert_eq!(i16::MIN.to_u32(), None); - assert_eq!(i16::MIN.to_u64(), None); - } - - #[test] - fn test_cast_range_i32_min() { - assert_eq!(i32::MIN.to_int(), Some(i32::MIN as isize)); - assert_eq!(i32::MIN.to_i8(), None); - assert_eq!(i32::MIN.to_i16(), None); - assert_eq!(i32::MIN.to_i32(), Some(i32::MIN as i32)); - assert_eq!(i32::MIN.to_i64(), Some(i32::MIN as i64)); - assert_eq!(i32::MIN.to_uint(), None); - assert_eq!(i32::MIN.to_u8(), None); - assert_eq!(i32::MIN.to_u16(), None); - assert_eq!(i32::MIN.to_u32(), None); - assert_eq!(i32::MIN.to_u64(), None); - } - - #[test] - fn test_cast_range_i64_min() { - // i64::MIN.to_int() is word-size specific - assert_eq!(i64::MIN.to_i8(), None); - assert_eq!(i64::MIN.to_i16(), None); - assert_eq!(i64::MIN.to_i32(), None); - assert_eq!(i64::MIN.to_i64(), Some(i64::MIN as i64)); - assert_eq!(i64::MIN.to_uint(), None); - assert_eq!(i64::MIN.to_u8(), None); - assert_eq!(i64::MIN.to_u16(), None); - assert_eq!(i64::MIN.to_u32(), None); - assert_eq!(i64::MIN.to_u64(), None); - - #[cfg(target_pointer_width = "32")] - fn check_word_size() { - assert_eq!(i64::MIN.to_int(), None); - } - - #[cfg(target_pointer_width = "64")] - fn check_word_size() { - assert_eq!(i64::MIN.to_int(), Some(i64::MIN as isize)); - } - - check_word_size(); - } - - #[test] - fn test_cast_range_int_max() { - assert_eq!(isize::MAX.to_int(), Some(isize::MAX as isize)); - assert_eq!(isize::MAX.to_i8(), None); - assert_eq!(isize::MAX.to_i16(), None); - // isize::MAX.to_i32() is word-size specific - assert_eq!(isize::MAX.to_i64(), Some(isize::MAX as i64)); - assert_eq!(isize::MAX.to_u8(), None); - assert_eq!(isize::MAX.to_u16(), None); - // isize::MAX.to_u32() is word-size specific - assert_eq!(isize::MAX.to_u64(), Some(isize::MAX as u64)); - - #[cfg(target_pointer_width = "32")] - fn check_word_size() { - assert_eq!(isize::MAX.to_i32(), Some(isize::MAX as i32)); - assert_eq!(isize::MAX.to_u32(), Some(isize::MAX as u32)); - } - - #[cfg(target_pointer_width = "64")] - fn check_word_size() { - assert_eq!(isize::MAX.to_i32(), None); - assert_eq!(isize::MAX.to_u32(), None); - } - - check_word_size(); - } - - #[test] - fn test_cast_range_i8_max() { - assert_eq!(i8::MAX.to_int(), Some(i8::MAX as isize)); - assert_eq!(i8::MAX.to_i8(), Some(i8::MAX as i8)); - assert_eq!(i8::MAX.to_i16(), Some(i8::MAX as i16)); - assert_eq!(i8::MAX.to_i32(), Some(i8::MAX as i32)); - assert_eq!(i8::MAX.to_i64(), Some(i8::MAX as i64)); - assert_eq!(i8::MAX.to_uint(), Some(i8::MAX as usize)); - assert_eq!(i8::MAX.to_u8(), Some(i8::MAX as u8)); - assert_eq!(i8::MAX.to_u16(), Some(i8::MAX as u16)); - assert_eq!(i8::MAX.to_u32(), Some(i8::MAX as u32)); - assert_eq!(i8::MAX.to_u64(), Some(i8::MAX as u64)); - } - - #[test] - fn test_cast_range_i16_max() { - assert_eq!(i16::MAX.to_int(), Some(i16::MAX as isize)); - assert_eq!(i16::MAX.to_i8(), None); - assert_eq!(i16::MAX.to_i16(), Some(i16::MAX as i16)); - assert_eq!(i16::MAX.to_i32(), Some(i16::MAX as i32)); - assert_eq!(i16::MAX.to_i64(), Some(i16::MAX as i64)); - assert_eq!(i16::MAX.to_uint(), Some(i16::MAX as usize)); - assert_eq!(i16::MAX.to_u8(), None); - assert_eq!(i16::MAX.to_u16(), Some(i16::MAX as u16)); - assert_eq!(i16::MAX.to_u32(), Some(i16::MAX as u32)); - assert_eq!(i16::MAX.to_u64(), Some(i16::MAX as u64)); - } - - #[test] - fn test_cast_range_i32_max() { - assert_eq!(i32::MAX.to_int(), Some(i32::MAX as isize)); - assert_eq!(i32::MAX.to_i8(), None); - assert_eq!(i32::MAX.to_i16(), None); - assert_eq!(i32::MAX.to_i32(), Some(i32::MAX as i32)); - assert_eq!(i32::MAX.to_i64(), Some(i32::MAX as i64)); - assert_eq!(i32::MAX.to_uint(), Some(i32::MAX as usize)); - assert_eq!(i32::MAX.to_u8(), None); - assert_eq!(i32::MAX.to_u16(), None); - assert_eq!(i32::MAX.to_u32(), Some(i32::MAX as u32)); - assert_eq!(i32::MAX.to_u64(), Some(i32::MAX as u64)); - } - - #[test] - fn test_cast_range_i64_max() { - // i64::MAX.to_int() is word-size specific - assert_eq!(i64::MAX.to_i8(), None); - assert_eq!(i64::MAX.to_i16(), None); - assert_eq!(i64::MAX.to_i32(), None); - assert_eq!(i64::MAX.to_i64(), Some(i64::MAX as i64)); - // i64::MAX.to_uint() is word-size specific - assert_eq!(i64::MAX.to_u8(), None); - assert_eq!(i64::MAX.to_u16(), None); - assert_eq!(i64::MAX.to_u32(), None); - assert_eq!(i64::MAX.to_u64(), Some(i64::MAX as u64)); - - #[cfg(target_pointer_width = "32")] - fn check_word_size() { - assert_eq!(i64::MAX.to_int(), None); - assert_eq!(i64::MAX.to_uint(), None); - } - - #[cfg(target_pointer_width = "64")] - fn check_word_size() { - assert_eq!(i64::MAX.to_int(), Some(i64::MAX as isize)); - assert_eq!(i64::MAX.to_uint(), Some(i64::MAX as usize)); - } - - check_word_size(); - } - - #[test] - fn test_cast_range_uint_min() { - assert_eq!(usize::MIN.to_int(), Some(usize::MIN as isize)); - assert_eq!(usize::MIN.to_i8(), Some(usize::MIN as i8)); - assert_eq!(usize::MIN.to_i16(), Some(usize::MIN as i16)); - assert_eq!(usize::MIN.to_i32(), Some(usize::MIN as i32)); - assert_eq!(usize::MIN.to_i64(), Some(usize::MIN as i64)); - assert_eq!(usize::MIN.to_uint(), Some(usize::MIN as usize)); - assert_eq!(usize::MIN.to_u8(), Some(usize::MIN as u8)); - assert_eq!(usize::MIN.to_u16(), Some(usize::MIN as u16)); - assert_eq!(usize::MIN.to_u32(), Some(usize::MIN as u32)); - assert_eq!(usize::MIN.to_u64(), Some(usize::MIN as u64)); - } - - #[test] - fn test_cast_range_u8_min() { - assert_eq!(u8::MIN.to_int(), Some(u8::MIN as isize)); - assert_eq!(u8::MIN.to_i8(), Some(u8::MIN as i8)); - assert_eq!(u8::MIN.to_i16(), Some(u8::MIN as i16)); - assert_eq!(u8::MIN.to_i32(), Some(u8::MIN as i32)); - assert_eq!(u8::MIN.to_i64(), Some(u8::MIN as i64)); - assert_eq!(u8::MIN.to_uint(), Some(u8::MIN as usize)); - assert_eq!(u8::MIN.to_u8(), Some(u8::MIN as u8)); - assert_eq!(u8::MIN.to_u16(), Some(u8::MIN as u16)); - assert_eq!(u8::MIN.to_u32(), Some(u8::MIN as u32)); - assert_eq!(u8::MIN.to_u64(), Some(u8::MIN as u64)); - } - - #[test] - fn test_cast_range_u16_min() { - assert_eq!(u16::MIN.to_int(), Some(u16::MIN as isize)); - assert_eq!(u16::MIN.to_i8(), Some(u16::MIN as i8)); - assert_eq!(u16::MIN.to_i16(), Some(u16::MIN as i16)); - assert_eq!(u16::MIN.to_i32(), Some(u16::MIN as i32)); - assert_eq!(u16::MIN.to_i64(), Some(u16::MIN as i64)); - assert_eq!(u16::MIN.to_uint(), Some(u16::MIN as usize)); - assert_eq!(u16::MIN.to_u8(), Some(u16::MIN as u8)); - assert_eq!(u16::MIN.to_u16(), Some(u16::MIN as u16)); - assert_eq!(u16::MIN.to_u32(), Some(u16::MIN as u32)); - assert_eq!(u16::MIN.to_u64(), Some(u16::MIN as u64)); - } - - #[test] - fn test_cast_range_u32_min() { - assert_eq!(u32::MIN.to_int(), Some(u32::MIN as isize)); - assert_eq!(u32::MIN.to_i8(), Some(u32::MIN as i8)); - assert_eq!(u32::MIN.to_i16(), Some(u32::MIN as i16)); - assert_eq!(u32::MIN.to_i32(), Some(u32::MIN as i32)); - assert_eq!(u32::MIN.to_i64(), Some(u32::MIN as i64)); - assert_eq!(u32::MIN.to_uint(), Some(u32::MIN as usize)); - assert_eq!(u32::MIN.to_u8(), Some(u32::MIN as u8)); - assert_eq!(u32::MIN.to_u16(), Some(u32::MIN as u16)); - assert_eq!(u32::MIN.to_u32(), Some(u32::MIN as u32)); - assert_eq!(u32::MIN.to_u64(), Some(u32::MIN as u64)); - } - - #[test] - fn test_cast_range_u64_min() { - assert_eq!(u64::MIN.to_int(), Some(u64::MIN as isize)); - assert_eq!(u64::MIN.to_i8(), Some(u64::MIN as i8)); - assert_eq!(u64::MIN.to_i16(), Some(u64::MIN as i16)); - assert_eq!(u64::MIN.to_i32(), Some(u64::MIN as i32)); - assert_eq!(u64::MIN.to_i64(), Some(u64::MIN as i64)); - assert_eq!(u64::MIN.to_uint(), Some(u64::MIN as usize)); - assert_eq!(u64::MIN.to_u8(), Some(u64::MIN as u8)); - assert_eq!(u64::MIN.to_u16(), Some(u64::MIN as u16)); - assert_eq!(u64::MIN.to_u32(), Some(u64::MIN as u32)); - assert_eq!(u64::MIN.to_u64(), Some(u64::MIN as u64)); - } - - #[test] - fn test_cast_range_uint_max() { - assert_eq!(usize::MAX.to_int(), None); - assert_eq!(usize::MAX.to_i8(), None); - assert_eq!(usize::MAX.to_i16(), None); - assert_eq!(usize::MAX.to_i32(), None); - // usize::MAX.to_i64() is word-size specific - assert_eq!(usize::MAX.to_u8(), None); - assert_eq!(usize::MAX.to_u16(), None); - // usize::MAX.to_u32() is word-size specific - assert_eq!(usize::MAX.to_u64(), Some(usize::MAX as u64)); - - #[cfg(target_pointer_width = "32")] - fn check_word_size() { - assert_eq!(usize::MAX.to_u32(), Some(usize::MAX as u32)); - assert_eq!(usize::MAX.to_i64(), Some(usize::MAX as i64)); - } - - #[cfg(target_pointer_width = "64")] - fn check_word_size() { - assert_eq!(usize::MAX.to_u32(), None); - assert_eq!(usize::MAX.to_i64(), None); - } - - check_word_size(); - } - - #[test] - fn test_cast_range_u8_max() { - assert_eq!(u8::MAX.to_int(), Some(u8::MAX as isize)); - assert_eq!(u8::MAX.to_i8(), None); - assert_eq!(u8::MAX.to_i16(), Some(u8::MAX as i16)); - assert_eq!(u8::MAX.to_i32(), Some(u8::MAX as i32)); - assert_eq!(u8::MAX.to_i64(), Some(u8::MAX as i64)); - assert_eq!(u8::MAX.to_uint(), Some(u8::MAX as usize)); - assert_eq!(u8::MAX.to_u8(), Some(u8::MAX as u8)); - assert_eq!(u8::MAX.to_u16(), Some(u8::MAX as u16)); - assert_eq!(u8::MAX.to_u32(), Some(u8::MAX as u32)); - assert_eq!(u8::MAX.to_u64(), Some(u8::MAX as u64)); - } - - #[test] - fn test_cast_range_u16_max() { - assert_eq!(u16::MAX.to_int(), Some(u16::MAX as isize)); - assert_eq!(u16::MAX.to_i8(), None); - assert_eq!(u16::MAX.to_i16(), None); - assert_eq!(u16::MAX.to_i32(), Some(u16::MAX as i32)); - assert_eq!(u16::MAX.to_i64(), Some(u16::MAX as i64)); - assert_eq!(u16::MAX.to_uint(), Some(u16::MAX as usize)); - assert_eq!(u16::MAX.to_u8(), None); - assert_eq!(u16::MAX.to_u16(), Some(u16::MAX as u16)); - assert_eq!(u16::MAX.to_u32(), Some(u16::MAX as u32)); - assert_eq!(u16::MAX.to_u64(), Some(u16::MAX as u64)); - } - - #[test] - fn test_cast_range_u32_max() { - // u32::MAX.to_int() is word-size specific - assert_eq!(u32::MAX.to_i8(), None); - assert_eq!(u32::MAX.to_i16(), None); - assert_eq!(u32::MAX.to_i32(), None); - assert_eq!(u32::MAX.to_i64(), Some(u32::MAX as i64)); - assert_eq!(u32::MAX.to_uint(), Some(u32::MAX as usize)); - assert_eq!(u32::MAX.to_u8(), None); - assert_eq!(u32::MAX.to_u16(), None); - assert_eq!(u32::MAX.to_u32(), Some(u32::MAX as u32)); - assert_eq!(u32::MAX.to_u64(), Some(u32::MAX as u64)); - - #[cfg(target_pointer_width = "32")] - fn check_word_size() { - assert_eq!(u32::MAX.to_int(), None); - } - - #[cfg(target_pointer_width = "64")] - fn check_word_size() { - assert_eq!(u32::MAX.to_int(), Some(u32::MAX as isize)); - } - - check_word_size(); - } - - #[test] - fn test_cast_range_u64_max() { - assert_eq!(u64::MAX.to_int(), None); - assert_eq!(u64::MAX.to_i8(), None); - assert_eq!(u64::MAX.to_i16(), None); - assert_eq!(u64::MAX.to_i32(), None); - assert_eq!(u64::MAX.to_i64(), None); - // u64::MAX.to_uint() is word-size specific - assert_eq!(u64::MAX.to_u8(), None); - assert_eq!(u64::MAX.to_u16(), None); - assert_eq!(u64::MAX.to_u32(), None); - assert_eq!(u64::MAX.to_u64(), Some(u64::MAX as u64)); - - #[cfg(target_pointer_width = "32")] - fn check_word_size() { - assert_eq!(u64::MAX.to_uint(), None); - } - - #[cfg(target_pointer_width = "64")] - fn check_word_size() { - assert_eq!(u64::MAX.to_uint(), Some(u64::MAX as usize)); - } - - check_word_size(); - } + use ops::Mul; #[test] fn test_saturating_add_uint() { @@ -507,23 +106,23 @@ mod tests { #[test] fn test_saturating_add_int() { use isize::{MIN,MAX}; - assert_eq!(3.saturating_add(5), 8); - assert_eq!(3.saturating_add(MAX-1), MAX); + assert_eq!(3i32.saturating_add(5), 8); + assert_eq!(3isize.saturating_add(MAX-1), MAX); assert_eq!(MAX.saturating_add(MAX), MAX); assert_eq!((MAX-2).saturating_add(1), MAX-1); - assert_eq!(3.saturating_add(-5), -2); + assert_eq!(3i32.saturating_add(-5), -2); assert_eq!(MIN.saturating_add(-1), MIN); - assert_eq!((-2).saturating_add(-MAX), MIN); + assert_eq!((-2isize).saturating_add(-MAX), MIN); } #[test] fn test_saturating_sub_int() { use isize::{MIN,MAX}; - assert_eq!(3.saturating_sub(5), -2); + assert_eq!(3i32.saturating_sub(5), -2); assert_eq!(MIN.saturating_sub(1), MIN); - assert_eq!((-2).saturating_sub(MAX), MIN); - assert_eq!(3.saturating_sub(-5), 8); - assert_eq!(3.saturating_sub(-(MAX-1)), MAX); + assert_eq!((-2isize).saturating_sub(MAX), MIN); + assert_eq!(3i32.saturating_sub(-5), 8); + assert_eq!(3isize.saturating_sub(-(MAX-1)), MAX); assert_eq!(MAX.saturating_sub(-MAX), MAX); assert_eq!((MAX-2).saturating_sub(-1), MAX-1); } @@ -627,56 +226,10 @@ mod tests { test_checked_next_power_of_two! { test_checked_next_power_of_two_u64, u64 } test_checked_next_power_of_two! { test_checked_next_power_of_two_uint, usize } - #[derive(PartialEq, Debug)] - struct Value { x: isize } - - impl ToPrimitive for Value { - fn to_i64(&self) -> Option { self.x.to_i64() } - fn to_u64(&self) -> Option { self.x.to_u64() } - } - - impl FromPrimitive for Value { - fn from_i64(n: i64) -> Option { Some(Value { x: n as isize }) } - fn from_u64(n: u64) -> Option { Some(Value { x: n as isize }) } - } - - #[test] - fn test_to_primitive() { - let value = Value { x: 5 }; - assert_eq!(value.to_int(), Some(5)); - assert_eq!(value.to_i8(), Some(5)); - assert_eq!(value.to_i16(), Some(5)); - assert_eq!(value.to_i32(), Some(5)); - assert_eq!(value.to_i64(), Some(5)); - assert_eq!(value.to_uint(), Some(5)); - assert_eq!(value.to_u8(), Some(5)); - assert_eq!(value.to_u16(), Some(5)); - assert_eq!(value.to_u32(), Some(5)); - assert_eq!(value.to_u64(), Some(5)); - assert_eq!(value.to_f32(), Some(5f32)); - assert_eq!(value.to_f64(), Some(5f64)); - } - - #[test] - fn test_from_primitive() { - assert_eq!(from_int(5), Some(Value { x: 5 })); - assert_eq!(from_i8(5), Some(Value { x: 5 })); - assert_eq!(from_i16(5), Some(Value { x: 5 })); - assert_eq!(from_i32(5), Some(Value { x: 5 })); - assert_eq!(from_i64(5), Some(Value { x: 5 })); - assert_eq!(from_uint(5), Some(Value { x: 5 })); - assert_eq!(from_u8(5), Some(Value { x: 5 })); - assert_eq!(from_u16(5), Some(Value { x: 5 })); - assert_eq!(from_u32(5), Some(Value { x: 5 })); - assert_eq!(from_u64(5), Some(Value { x: 5 })); - assert_eq!(from_f32(5f32), Some(Value { x: 5 })); - assert_eq!(from_f64(5f64), Some(Value { x: 5 })); - } - #[test] fn test_pow() { - fn naive_pow(base: T, exp: usize) -> T { - let one: T = Int::one(); + fn naive_pow + One + Copy>(base: T, exp: usize) -> T { + let one: T = T::one(); (0..exp).fold(one, |acc, _| acc * base) } macro_rules! assert_pow { @@ -686,11 +239,11 @@ mod tests { assert_eq!(result, naive_pow($num, $exp)); }} } - assert_pow!((3, 0 ) => 1); - assert_pow!((5, 1 ) => 5); - assert_pow!((-4, 2 ) => 16); - assert_pow!((8, 3 ) => 512); - assert_pow!((2u64, 50) => 1125899906842624); + assert_pow!((3u32, 0 ) => 1); + assert_pow!((5u32, 1 ) => 5); + assert_pow!((-4i32, 2 ) => 16); + assert_pow!((8u32, 3 ) => 512); + assert_pow!((2u64, 50) => 1125899906842624); } #[test] @@ -765,12 +318,11 @@ mod tests { mod bench { extern crate test; use self::test::Bencher; - use num::Int; use prelude::v1::*; #[bench] fn bench_pow_function(b: &mut Bencher) { - let v = (0..1024).collect::>(); - b.iter(|| {v.iter().fold(0, |old, new| old.pow(*new as u32));}); + let v = (0..1024).collect::>(); + b.iter(|| {v.iter().fold(0u32, |old, new| old.pow(*new as u32));}); } } diff --git a/src/libstd/num/uint_macros.rs b/src/libstd/num/uint_macros.rs index c9e6a8f66d1d2..96b0ba1c77f8d 100644 --- a/src/libstd/num/uint_macros.rs +++ b/src/libstd/num/uint_macros.rs @@ -12,12 +12,11 @@ #![doc(hidden)] #![allow(unsigned_negation)] -macro_rules! uint_module { ($T:ty) => ( +macro_rules! uint_module { ($T:ident) => ( #[cfg(test)] mod tests { use prelude::v1::*; - use num::FromStrRadix; fn from_str(t: &str) -> Option { ::str::FromStr::from_str(t).ok() @@ -38,15 +37,15 @@ mod tests { #[test] pub fn test_parse_bytes() { - assert_eq!(FromStrRadix::from_str_radix("123", 10), Ok(123 as $T)); - assert_eq!(FromStrRadix::from_str_radix("1001", 2), Ok(9 as $T)); - assert_eq!(FromStrRadix::from_str_radix("123", 8), Ok(83 as $T)); - assert_eq!(FromStrRadix::from_str_radix("123", 16), Ok(291 as u16)); - assert_eq!(FromStrRadix::from_str_radix("ffff", 16), Ok(65535 as u16)); - assert_eq!(FromStrRadix::from_str_radix("z", 36), Ok(35 as $T)); - - assert_eq!(FromStrRadix::from_str_radix("Z", 10).ok(), None::<$T>); - assert_eq!(FromStrRadix::from_str_radix("_", 2).ok(), None::<$T>); + assert_eq!($T::from_str_radix("123", 10), Ok(123 as $T)); + assert_eq!($T::from_str_radix("1001", 2), Ok(9 as $T)); + assert_eq!($T::from_str_radix("123", 8), Ok(83 as $T)); + assert_eq!(u16::from_str_radix("123", 16), Ok(291 as u16)); + assert_eq!(u16::from_str_radix("ffff", 16), Ok(65535 as u16)); + assert_eq!($T::from_str_radix("z", 36), Ok(35 as $T)); + + assert_eq!($T::from_str_radix("Z", 10).ok(), None::<$T>); + assert_eq!($T::from_str_radix("_", 2).ok(), None::<$T>); } } diff --git a/src/libstd/rand/reader.rs b/src/libstd/rand/reader.rs index f8dd6a00c7f1d..2837bac445697 100644 --- a/src/libstd/rand/reader.rs +++ b/src/libstd/rand/reader.rs @@ -67,7 +67,6 @@ mod test { use prelude::v1::*; use super::ReaderRng; - use num::Int; use rand::Rng; #[test] @@ -78,18 +77,18 @@ mod test { 0, 0, 0, 0, 0, 0, 0, 3][..]; let mut rng = ReaderRng::new(v); - assert_eq!(rng.next_u64(), 1.to_be()); - assert_eq!(rng.next_u64(), 2.to_be()); - assert_eq!(rng.next_u64(), 3.to_be()); + assert_eq!(rng.next_u64(), 1u64.to_be()); + assert_eq!(rng.next_u64(), 2u64.to_be()); + assert_eq!(rng.next_u64(), 3u64.to_be()); } #[test] fn test_reader_rng_u32() { let v = &[0, 0, 0, 1, 0, 0, 0, 2, 0, 0, 0, 3][..]; let mut rng = ReaderRng::new(v); - assert_eq!(rng.next_u32(), 1.to_be()); - assert_eq!(rng.next_u32(), 2.to_be()); - assert_eq!(rng.next_u32(), 3.to_be()); + assert_eq!(rng.next_u32(), 1u32.to_be()); + assert_eq!(rng.next_u32(), 2u32.to_be()); + assert_eq!(rng.next_u32(), 3u32.to_be()); } #[test] fn test_reader_rng_fill_bytes() { diff --git a/src/libstd/sys/windows/fs2.rs b/src/libstd/sys/windows/fs2.rs index 9645c51ec0b23..7a41f02d27028 100644 --- a/src/libstd/sys/windows/fs2.rs +++ b/src/libstd/sys/windows/fs2.rs @@ -13,7 +13,8 @@ use io::prelude::*; use os::windows::prelude::*; use default::Default; -use ffi::{OsString, AsOsStr}; +use ffi::OsString; +use fmt; use io::{self, Error, SeekFrom}; use libc::{self, HANDLE}; use mem; diff --git a/src/libstd/sys/windows/mod.rs b/src/libstd/sys/windows/mod.rs index 1171c6c068b12..5ae5f6f201bad 100644 --- a/src/libstd/sys/windows/mod.rs +++ b/src/libstd/sys/windows/mod.rs @@ -17,8 +17,7 @@ use prelude::v1::*; use ffi::{OsStr, OsString}; use io::{self, ErrorKind}; use libc; -#[allow(deprecated)] -use num::Int; +use num::Zero; use os::windows::ffi::{OsStrExt, OsStringExt}; use path::PathBuf; @@ -144,9 +143,8 @@ pub fn truncate_utf16_at_nul<'a>(v: &'a [u16]) -> &'a [u16] { } } -#[allow(deprecated)] -fn cvt(i: I) -> io::Result { - if i == Int::zero() { +fn cvt(i: I) -> io::Result { + if i == I::zero() { Err(io::Error::last_os_error()) } else { Ok(i) diff --git a/src/libstd/sys/windows/net.rs b/src/libstd/sys/windows/net.rs index cbc3876dbb116..6bbcd968157ab 100644 --- a/src/libstd/sys/windows/net.rs +++ b/src/libstd/sys/windows/net.rs @@ -15,8 +15,8 @@ use libc::consts::os::extra::INVALID_SOCKET; use libc::{self, c_int, c_void}; use mem; use net::SocketAddr; -#[allow(deprecated)] -use num::{SignedInt, Int}; +use num::One; +use ops::Neg; use rt; use sync::{Once, ONCE_INIT}; use sys::c; @@ -49,11 +49,8 @@ fn last_error() -> io::Error { /// Checks if the signed integer is the Windows constant `SOCKET_ERROR` (-1) /// and if so, returns the last error from the Windows socket interface. . This /// function must be called before another call to the socket API is made. -/// -/// FIXME: generics needed? -#[allow(deprecated)] -pub fn cvt(t: T) -> io::Result { - let one: T = Int::one(); +pub fn cvt + PartialEq>(t: T) -> io::Result { + let one: T = T::one(); if t == -one { Err(last_error()) } else { @@ -70,7 +67,9 @@ pub fn cvt_gai(err: c_int) -> io::Result<()> { /// Provides the functionality of `cvt` for a closure. #[allow(deprecated)] -pub fn cvt_r(mut f: F) -> io::Result where F: FnMut() -> T { +pub fn cvt_r(mut f: F) -> io::Result + where F: FnMut() -> T, T: One + Neg + PartialEq +{ cvt(f()) } diff --git a/src/libstd/sys/windows/process2.rs b/src/libstd/sys/windows/process2.rs index 16c2a9125eaa7..5ddcf3d1ea299 100644 --- a/src/libstd/sys/windows/process2.rs +++ b/src/libstd/sys/windows/process2.rs @@ -140,7 +140,7 @@ impl Process { // read the *child's* PATH if one is provided. See #15149 for more details. let program = cfg.env.as_ref().and_then(|env| { for (key, v) in env { - if OsStr::from_str("PATH") != &**key { continue } + if OsStr::new("PATH") != &**key { continue } // Split the value and test each path to see if the // program exists. @@ -463,7 +463,7 @@ mod tests { fn test_make_command_line() { fn test_wrapper(prog: &str, args: &[&str]) -> String { String::from_utf16( - &make_command_line(OsStr::from_str(prog), + &make_command_line(OsStr::new(prog), &args.iter() .map(|a| OsString::from(a)) .collect::>())).unwrap() diff --git a/src/libtest/stats.rs b/src/libtest/stats.rs index 341be762601dd..c1ba1260f67e1 100644 --- a/src/libtest/stats.rs +++ b/src/libtest/stats.rs @@ -338,14 +338,13 @@ mod tests { macro_rules! assert_approx_eq { ($a:expr, $b:expr) => ({ - use std::num::Float; let (a, b) = (&$a, &$b); assert!((*a - *b).abs() < 1.0e-6, "{} is not approximately equal to {}", *a, *b); }) } - fn check(samples: &[f64], summ: &Summary) { + fn check(samples: &[f64], summ: &Summary) { let summ2 = Summary::new(samples); diff --git a/src/test/bench/noise.rs b/src/test/bench/noise.rs index c21470d4bb3e7..bcfdf23e705d1 100644 --- a/src/test/bench/noise.rs +++ b/src/test/bench/noise.rs @@ -15,7 +15,6 @@ #![feature(rand, core)] use std::f32::consts::PI; -use std::num::Float; use std::__rand::{Rng, thread_rng}; #[derive(Copy, Clone)] diff --git a/src/test/bench/shootout-binarytrees.rs b/src/test/bench/shootout-binarytrees.rs index 61fe6593dc398..c576eea3602cb 100644 --- a/src/test/bench/shootout-binarytrees.rs +++ b/src/test/bench/shootout-binarytrees.rs @@ -109,8 +109,7 @@ fn main() { let long_lived_tree = bottom_up_tree(&long_lived_arena, 0, max_depth); let messages = (min_depth..max_depth + 1).step_by(2).map(|depth| { - use std::num::Int; - let iterations = 2.pow((max_depth - depth + min_depth) as u32); + let iterations = 2i32.pow((max_depth - depth + min_depth) as u32); thread::spawn(move || inner(depth, iterations)) }).collect::>(); diff --git a/src/test/bench/shootout-fasta.rs b/src/test/bench/shootout-fasta.rs index 0474cfb6fc819..accf525b4e638 100644 --- a/src/test/bench/shootout-fasta.rs +++ b/src/test/bench/shootout-fasta.rs @@ -43,7 +43,6 @@ use std::env; use std::fs::File; use std::io::{self, BufWriter}; use std::io::prelude::*; -use std::num::Float; const LINE_LENGTH: usize = 60; const IM: u32 = 139968; diff --git a/src/test/bench/shootout-nbody.rs b/src/test/bench/shootout-nbody.rs index de7fb737958f2..368dbbb931c26 100644 --- a/src/test/bench/shootout-nbody.rs +++ b/src/test/bench/shootout-nbody.rs @@ -38,9 +38,7 @@ // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED // OF THE POSSIBILITY OF SUCH DAMAGE. -#![feature(core)] - -use std::num::Float; +use std::mem; const PI: f64 = 3.141592653589793; const SOLAR_MASS: f64 = 4.0 * PI * PI; @@ -193,16 +191,9 @@ fn main() { /// longer contain the mutable reference. This is a safe operation because the /// two mutable borrows are entirely disjoint. fn shift_mut_ref<'a, T>(r: &mut &'a mut [T]) -> Option<&'a mut T> { - use std::mem; - use std::raw::Repr; - - if r.is_empty() { return None } - unsafe { - let mut raw = r.repr(); - let ret = raw.data as *mut T; - raw.data = raw.data.offset(1); - raw.len -= 1; - *r = mem::transmute(raw); - Some({ &mut *ret }) - } + let res = mem::replace(r, &mut []); + if res.is_empty() { return None } + let (a, b) = res.split_at_mut(1); + *r = b; + Some(&mut a[0]) } diff --git a/src/test/bench/shootout-spectralnorm.rs b/src/test/bench/shootout-spectralnorm.rs index b0e8c39567323..0fa22abde3cbd 100644 --- a/src/test/bench/shootout-spectralnorm.rs +++ b/src/test/bench/shootout-spectralnorm.rs @@ -46,7 +46,6 @@ use std::iter::repeat; use std::thread; use std::mem; -use std::num::Float; use std::os; use std::env; use std::raw::Repr; diff --git a/src/test/bench/sudoku.rs b/src/test/bench/sudoku.rs index 3913de3a3f99f..16742f0a6e1a5 100644 --- a/src/test/bench/sudoku.rs +++ b/src/test/bench/sudoku.rs @@ -16,7 +16,6 @@ use std::io::prelude::*; use std::io; use std::iter::repeat; -use std::num::Int; use std::env; // Computes a single solution to a given 9x9 sudoku diff --git a/src/test/pretty/default-trait-impl.rs b/src/test/pretty/default-trait-impl.rs index 509bee9def273..a5246b9300c91 100644 --- a/src/test/pretty/default-trait-impl.rs +++ b/src/test/pretty/default-trait-impl.rs @@ -8,13 +8,11 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(optin_builtin_traits, core)] +#![feature(optin_builtin_traits)] // pp-exact -use std::marker::MarkerTrait; - -trait MyTrait: MarkerTrait { } +trait MyTrait { } impl MyTrait for .. { } From 95d02a226de8c1525e6c9666412e3f08fac9714d Mon Sep 17 00:00:00 2001 From: Brian Anderson Date: Mon, 20 Apr 2015 17:00:35 -0700 Subject: [PATCH 19/25] Make stability attributes an error. #22830 Conflicts: src/librustc_data_structures/lib.rs --- src/librustc/middle/stability.rs | 6 +++--- .../compile-fail/stability-attribute-non-staged.rs | 10 +++------- 2 files changed, 6 insertions(+), 10 deletions(-) diff --git a/src/librustc/middle/stability.rs b/src/librustc/middle/stability.rs index e7c25d8215093..d75dc861e8330 100644 --- a/src/librustc/middle/stability.rs +++ b/src/librustc/middle/stability.rs @@ -95,9 +95,9 @@ impl<'a> Annotator<'a> { let tag = attr.name(); if tag == "unstable" || tag == "stable" || tag == "deprecated" { attr::mark_used(attr); - self.sess.span_warn(attr.span(), - "stability attributes are deprecated \ - and will soon become errors"); + self.sess.span_err(attr.span(), + "stability attributes may not be used outside \ + of the standard library"); } } f(self); diff --git a/src/test/compile-fail/stability-attribute-non-staged.rs b/src/test/compile-fail/stability-attribute-non-staged.rs index db16e7c013824..b0efdfd1818bd 100644 --- a/src/test/compile-fail/stability-attribute-non-staged.rs +++ b/src/test/compile-fail/stability-attribute-non-staged.rs @@ -8,11 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// These two generate an error to satisfy the compile-fail test -#![deny(warnings)] -#![feature(blah)] //~ ERROR - -#[unstable] //~ WARNING: stability attributes are deprecated -#[stable] //~ WARNING: stability attributes are deprecated -#[deprecated] //~ WARNING: stability attributes are deprecated +#[unstable] //~ ERROR: stability attributes may not be used +#[stable] //~ ERROR: stability attributes may not be used +#[deprecated] //~ ERROR: stability attributes may not be used fn main() { } From fc74ba2bb0f99c43ae5aee115602dff25fc2494d Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Tue, 21 Apr 2015 15:59:14 -0700 Subject: [PATCH 20/25] Test fixes and rebase conflicts, round 1 Conflicts: src/test/run-pass/task-stderr.rs --- src/libcollections/string.rs | 1 - src/libcollections/vec.rs | 2 +- src/libstd/dynamic_lib.rs | 9 ++------- src/libstd/sys/windows/fs2.rs | 1 - src/test/run-pass/task-stderr.rs | 5 +---- 5 files changed, 4 insertions(+), 14 deletions(-) diff --git a/src/libcollections/string.rs b/src/libcollections/string.rs index 3910c60e75293..0f0254a32b1a4 100644 --- a/src/libcollections/string.rs +++ b/src/libcollections/string.rs @@ -23,7 +23,6 @@ use core::mem; use core::ops::{self, Deref, Add, Index}; use core::ptr; use core::slice; -#[allow(deprecated)] use core::str::Str; use core::str::pattern::Pattern; use unicode::str as unicode_str; use unicode::str::Utf16Item; diff --git a/src/libcollections/vec.rs b/src/libcollections/vec.rs index 4bbfabdd72fd1..526150915a705 100644 --- a/src/libcollections/vec.rs +++ b/src/libcollections/vec.rs @@ -63,7 +63,7 @@ use core::ops::{Index, IndexMut, Deref, Add}; use core::ops; use core::ptr; use core::ptr::Unique; -use core::slice::{self, AsSlice}; +use core::slice; use core::isize; use core::usize; diff --git a/src/libstd/dynamic_lib.rs b/src/libstd/dynamic_lib.rs index c69df6435c498..8ca462f5a3870 100644 --- a/src/libstd/dynamic_lib.rs +++ b/src/libstd/dynamic_lib.rs @@ -259,19 +259,14 @@ mod dl { #[cfg(target_os = "windows")] mod dl { + use prelude::v1::*; + use ffi::OsStr; - use iter::Iterator; use libc; use libc::consts::os::extra::ERROR_CALL_NOT_IMPLEMENTED; - use ops::FnOnce; use sys::os; use os::windows::prelude::*; - use option::Option::{self, Some, None}; use ptr; - use result::Result; - use result::Result::{Ok, Err}; - use string::String; - use vec::Vec; use sys::c::compat::kernel32::SetThreadErrorMode; pub fn open(filename: Option<&OsStr>) -> Result<*mut u8, String> { diff --git a/src/libstd/sys/windows/fs2.rs b/src/libstd/sys/windows/fs2.rs index 7a41f02d27028..4be937460493c 100644 --- a/src/libstd/sys/windows/fs2.rs +++ b/src/libstd/sys/windows/fs2.rs @@ -12,7 +12,6 @@ use core::prelude::*; use io::prelude::*; use os::windows::prelude::*; -use default::Default; use ffi::OsString; use fmt; use io::{self, Error, SeekFrom}; diff --git a/src/test/run-pass/task-stderr.rs b/src/test/run-pass/task-stderr.rs index 7bcde7b83cd1b..4a1bb5a5916f0 100644 --- a/src/test/run-pass/task-stderr.rs +++ b/src/test/run-pass/task-stderr.rs @@ -8,10 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// pretty-expanded FIXME #23616 - -#![allow(unknown_features)] -#![feature(box_syntax, old_io, std_misc, io, set_panic, set_stdio)] +#![feature(box_syntax, set_stdio)] use std::io::prelude::*; use std::io; From 8b5482e5ab2b180a1943c4d0cf130cd2e3d74731 Mon Sep 17 00:00:00 2001 From: Kevin Ballard Date: Mon, 6 Apr 2015 16:30:18 -0700 Subject: [PATCH 21/25] Add `Sync` to the bounds in `io::Error` This allows `io::Error` values to be stored in `Arc` properly. Because this requires `Sync` of any value passed to `io::Error::new()` and modifies the relevant `convert::From` impls, this is a [breaking-change] Fixes #24049. --- src/libstd/error.rs | 14 +++++++------- src/libstd/io/error.rs | 11 ++++++++--- 2 files changed, 15 insertions(+), 10 deletions(-) diff --git a/src/libstd/error.rs b/src/libstd/error.rs index 96087bf1183df..9f09f464cfc68 100644 --- a/src/libstd/error.rs +++ b/src/libstd/error.rs @@ -50,7 +50,7 @@ use boxed::Box; use convert::From; use fmt::{self, Debug, Display}; -use marker::Send; +use marker::{Send, Sync}; use num; use option::Option; use option::Option::None; @@ -81,15 +81,15 @@ impl<'a, E: Error + 'a> From for Box { } #[stable(feature = "rust1", since = "1.0.0")] -impl<'a, E: Error + Send + 'a> From for Box { - fn from(err: E) -> Box { +impl<'a, E: Error + Send + Sync + 'a> From for Box { + fn from(err: E) -> Box { Box::new(err) } } #[stable(feature = "rust1", since = "1.0.0")] -impl From for Box { - fn from(err: String) -> Box { +impl From for Box { + fn from(err: String) -> Box { #[derive(Debug)] struct StringError(String); @@ -108,8 +108,8 @@ impl From for Box { } #[stable(feature = "rust1", since = "1.0.0")] -impl<'a, 'b> From<&'b str> for Box { - fn from(err: &'b str) -> Box { +impl<'a, 'b> From<&'b str> for Box { + fn from(err: &'b str) -> Box { From::from(String::from_str(err)) } } diff --git a/src/libstd/io/error.rs b/src/libstd/io/error.rs index 4e36b2438b457..97c5a29d308a1 100644 --- a/src/libstd/io/error.rs +++ b/src/libstd/io/error.rs @@ -12,7 +12,7 @@ use boxed::Box; use convert::Into; use error; use fmt; -use marker::Send; +use marker::{Send, Sync}; use option::Option::{self, Some, None}; use result; use sys; @@ -46,7 +46,7 @@ enum Repr { #[derive(Debug)] struct Custom { kind: ErrorKind, - error: Box, + error: Box, } /// A list specifying general categories of I/O error. @@ -146,7 +146,7 @@ impl Error { /// ``` #[stable(feature = "rust1", since = "1.0.0")] pub fn new(kind: ErrorKind, error: E) -> Error - where E: Into> + where E: Into> { Error { repr: Repr::Custom(Box::new(Custom { @@ -216,3 +216,8 @@ impl error::Error for Error { } } } + +fn _assert_error_is_sync_send() { + fn _is_sync_send() {} + _is_sync_send::(); +} From c4dae0520bde0e2fb28d43feccb29f960d2c2021 Mon Sep 17 00:00:00 2001 From: Niko Matsakis Date: Wed, 15 Apr 2015 09:13:20 -0400 Subject: [PATCH 22/25] Create a struct to represent early-bound regions --- src/librustc/metadata/tydecode.rs | 7 ++++++- src/librustc/metadata/tyencode.rs | 10 +++++----- src/librustc/middle/astencode.rs | 9 +++++++-- src/librustc/middle/region.rs | 9 +++------ src/librustc/middle/subst.rs | 15 ++++++++------- src/librustc/middle/ty.rs | 23 ++++++++++++++++------- src/librustc/util/ppaux.rs | 18 +++++++++--------- src/librustc_typeck/astconv.rs | 7 ++++++- src/librustc_typeck/collect.rs | 24 ++++++++++++++++-------- src/librustc_typeck/variance.rs | 6 +++--- 10 files changed, 79 insertions(+), 49 deletions(-) diff --git a/src/librustc/metadata/tydecode.rs b/src/librustc/metadata/tydecode.rs index cce31b1f4c249..955905ee2634d 100644 --- a/src/librustc/metadata/tydecode.rs +++ b/src/librustc/metadata/tydecode.rs @@ -341,7 +341,12 @@ fn parse_region_(st: &mut PState, conv: &mut F) -> ty::Region where let index = parse_u32(st); assert_eq!(next(st), '|'); let nm = token::str_to_ident(&parse_str(st, ']')); - ty::ReEarlyBound(node_id, space, index, nm.name) + ty::ReEarlyBound(ty::EarlyBoundRegion { + param_id: node_id, + space: space, + index: index, + name: nm.name + }) } 'f' => { assert_eq!(next(st), '['); diff --git a/src/librustc/metadata/tyencode.rs b/src/librustc/metadata/tyencode.rs index 90a905f184071..8a27881128255 100644 --- a/src/librustc/metadata/tyencode.rs +++ b/src/librustc/metadata/tyencode.rs @@ -241,12 +241,12 @@ pub fn enc_region(w: &mut Encoder, cx: &ctxt, r: ty::Region) { enc_bound_region(w, cx, br); mywrite!(w, "]"); } - ty::ReEarlyBound(node_id, space, index, name) => { + ty::ReEarlyBound(ref data) => { mywrite!(w, "B[{}|{}|{}|{}]", - node_id, - space.to_uint(), - index, - token::get_name(name)); + data.param_id, + data.space.to_uint(), + data.index, + token::get_name(data.name)); } ty::ReFree(ref fr) => { mywrite!(w, "f["); diff --git a/src/librustc/middle/astencode.rs b/src/librustc/middle/astencode.rs index f05f9dc6625df..ee8373279d976 100644 --- a/src/librustc/middle/astencode.rs +++ b/src/librustc/middle/astencode.rs @@ -495,8 +495,13 @@ impl tr for ty::Region { ty::ReLateBound(debruijn, br) => { ty::ReLateBound(debruijn, br.tr(dcx)) } - ty::ReEarlyBound(id, space, index, ident) => { - ty::ReEarlyBound(dcx.tr_id(id), space, index, ident) + ty::ReEarlyBound(data) => { + ty::ReEarlyBound(ty::EarlyBoundRegion { + param_id: dcx.tr_id(data.param_id), + space: data.space, + index: data.index, + name: data.name, + }) } ty::ReScope(scope) => { ty::ReScope(scope.tr(dcx)) diff --git a/src/librustc/middle/region.rs b/src/librustc/middle/region.rs index 5131322dc41ea..2f7296051c566 100644 --- a/src/librustc/middle/region.rs +++ b/src/librustc/middle/region.rs @@ -603,14 +603,11 @@ impl RegionMaps { self.sub_free_region(sub_fr, super_fr) } - (ty::ReEarlyBound(param_id_a, param_space_a, index_a, _), - ty::ReEarlyBound(param_id_b, param_space_b, index_b, _)) => { + (ty::ReEarlyBound(data_a), ty::ReEarlyBound(data_b)) => { // This case is used only to make sure that explicitly- // specified `Self` types match the real self type in - // implementations. - param_id_a == param_id_b && - param_space_a == param_space_b && - index_a == index_b + // implementations. Yuck. + data_a == data_b } _ => { diff --git a/src/librustc/middle/subst.rs b/src/librustc/middle/subst.rs index d9cdf0fa1cb36..29f718fd09769 100644 --- a/src/librustc/middle/subst.rs +++ b/src/librustc/middle/subst.rs @@ -622,11 +622,11 @@ impl<'a, 'tcx> TypeFolder<'tcx> for SubstFolder<'a, 'tcx> { // regions that appear in a function signature is done using // the specialized routine `ty::replace_late_regions()`. match r { - ty::ReEarlyBound(_, space, i, region_name) => { + ty::ReEarlyBound(data) => { match self.substs.regions { ErasedRegions => ty::ReStatic, NonerasedRegions(ref regions) => - match regions.opt_get(space, i as usize) { + match regions.opt_get(data.space, data.index as usize) { Some(&r) => { self.shift_region_through_binders(r) } @@ -635,11 +635,12 @@ impl<'a, 'tcx> TypeFolder<'tcx> for SubstFolder<'a, 'tcx> { self.tcx().sess.span_bug( span, &format!("Type parameter out of range \ - when substituting in region {} (root type={}) \ - (space={:?}, index={})", - region_name.as_str(), - self.root_ty.repr(self.tcx()), - space, i)); + when substituting in region {} (root type={}) \ + (space={:?}, index={})", + data.name.as_str(), + self.root_ty.repr(self.tcx()), + data.space, + data.index)); } } } diff --git a/src/librustc/middle/ty.rs b/src/librustc/middle/ty.rs index 2bf4e8d7c31b6..d72004a930605 100644 --- a/src/librustc/middle/ty.rs +++ b/src/librustc/middle/ty.rs @@ -1134,10 +1134,7 @@ pub enum Region { // Region bound in a type or fn declaration which will be // substituted 'early' -- that is, at the same time when type // parameters are substituted. - ReEarlyBound(/* param id */ ast::NodeId, - subst::ParamSpace, - /*index*/ u32, - ast::Name), + ReEarlyBound(EarlyBoundRegion), // Region bound in a function scope, which will be substituted when the // function is called. @@ -1169,6 +1166,14 @@ pub enum Region { ReEmpty, } +#[derive(Copy, Clone, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable, Debug)] +pub struct EarlyBoundRegion { + pub param_id: ast::NodeId, + pub space: subst::ParamSpace, + pub index: u32, + pub name: ast::Name, +} + /// Upvars do not get their own node-id. Instead, we use the pair of /// the original var id (that is, the root variable that is referenced /// by the upvar) and the id of the closure expression. @@ -1761,7 +1766,12 @@ pub struct RegionParameterDef { impl RegionParameterDef { pub fn to_early_bound_region(&self) -> ty::Region { - ty::ReEarlyBound(self.def_id.node, self.space, self.index, self.name) + ty::ReEarlyBound(ty::EarlyBoundRegion { + param_id: self.def_id.node, + space: self.space, + index: self.index, + name: self.name, + }) } pub fn to_bound_region(&self) -> ty::BoundRegion { ty::BoundRegion::BrNamed(self.def_id, self.name) @@ -7071,8 +7081,7 @@ pub fn make_substs_for_receiver_types<'tcx>(tcx: &ty::ctxt<'tcx>, let meth_regions: Vec = method.generics.regions.get_slice(subst::FnSpace) .iter() - .map(|def| ty::ReEarlyBound(def.def_id.node, def.space, - def.index, def.name)) + .map(|def| def.to_early_bound_region()) .collect(); trait_ref.substs.clone().with_method(meth_tps, meth_regions) } diff --git a/src/librustc/util/ppaux.rs b/src/librustc/util/ppaux.rs index fe076b904caef..6e0fe3e5a71c4 100644 --- a/src/librustc/util/ppaux.rs +++ b/src/librustc/util/ppaux.rs @@ -163,8 +163,8 @@ pub fn explain_region_and_span(cx: &ctxt, region: ty::Region) ReEmpty => { ("the empty lifetime".to_string(), None) } - ReEarlyBound(_, _, _, name) => { - (format!("{}", token::get_name(name)), None) + ReEarlyBound(ref data) => { + (format!("{}", token::get_name(data.name)), None) } // I believe these cases should not occur (except when debugging, @@ -223,8 +223,8 @@ pub fn region_to_string(cx: &ctxt, prefix: &str, space: bool, region: Region) -> // `explain_region()` or `note_and_explain_region()`. match region { ty::ReScope(_) => prefix.to_string(), - ty::ReEarlyBound(_, _, _, name) => { - token::get_name(name).to_string() + ty::ReEarlyBound(ref data) => { + token::get_name(data.name).to_string() } ty::ReLateBound(_, br) => bound_region_to_string(cx, prefix, space, br), ty::ReFree(ref fr) => bound_region_to_string(cx, prefix, space, fr.bound_region), @@ -899,12 +899,12 @@ impl<'tcx> Repr<'tcx> for ty::BoundRegion { impl<'tcx> Repr<'tcx> for ty::Region { fn repr(&self, tcx: &ctxt) -> String { match *self { - ty::ReEarlyBound(id, space, index, name) => { + ty::ReEarlyBound(ref data) => { format!("ReEarlyBound({}, {:?}, {}, {})", - id, - space, - index, - token::get_name(name)) + data.param_id, + data.space, + data.index, + token::get_name(data.name)) } ty::ReLateBound(binder_id, ref bound_region) => { diff --git a/src/librustc_typeck/astconv.rs b/src/librustc_typeck/astconv.rs index e37e9c970185c..171c83d00e465 100644 --- a/src/librustc_typeck/astconv.rs +++ b/src/librustc_typeck/astconv.rs @@ -161,7 +161,12 @@ pub fn ast_region_to_region(tcx: &ty::ctxt, lifetime: &ast::Lifetime) } Some(&rl::DefEarlyBoundRegion(space, index, id)) => { - ty::ReEarlyBound(id, space, index, lifetime.name) + ty::ReEarlyBound(ty::EarlyBoundRegion { + param_id: id, + space: space, + index: index, + name: lifetime.name + }) } Some(&rl::DefFreeRegion(scope, id)) => { diff --git a/src/librustc_typeck/collect.rs b/src/librustc_typeck/collect.rs index e5022b98918f7..72adad75865ee 100644 --- a/src/librustc_typeck/collect.rs +++ b/src/librustc_typeck/collect.rs @@ -1217,10 +1217,12 @@ fn trait_def_of_item<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, generics.lifetimes .iter() .enumerate() - .map(|(i, def)| ty::ReEarlyBound(def.lifetime.id, - TypeSpace, - i as u32, - def.lifetime.name)) + .map(|(i, def)| ty::ReEarlyBound(ty::EarlyBoundRegion { + param_id: def.lifetime.id, + space: TypeSpace, + index: i as u32, + name: def.lifetime.name + })) .collect(); // Start with the generics in the type parameters... @@ -1691,7 +1693,13 @@ fn ty_generic_predicates<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>, let early_lifetimes = early_bound_lifetimes_from_generics(space, ast_generics); for (index, param) in early_lifetimes.iter().enumerate() { let index = index as u32; - let region = ty::ReEarlyBound(param.lifetime.id, space, index, param.lifetime.name); + let region = + ty::ReEarlyBound(ty::EarlyBoundRegion { + param_id: param.lifetime.id, + space: space, + index: index, + name: param.lifetime.name + }); for bound in ¶m.bounds { let bound_region = ast_region_to_region(ccx.tcx, bound); let outlives = ty::Binder(ty::OutlivesPredicate(region, bound_region)); @@ -2168,10 +2176,10 @@ fn check_method_self_type<'a, 'tcx, RS:RegionScope>( ty_fold::fold_regions(tcx, value, |region, _| { match region { - ty::ReEarlyBound(id, _, _, name) => { - let def_id = local_def(id); + ty::ReEarlyBound(data) => { + let def_id = local_def(data.param_id); ty::ReFree(ty::FreeRegion { scope: scope, - bound_region: ty::BrNamed(def_id, name) }) + bound_region: ty::BrNamed(def_id, data.name) }) } _ => region } diff --git a/src/librustc_typeck/variance.rs b/src/librustc_typeck/variance.rs index da2de731d648a..7575f12878a56 100644 --- a/src/librustc_typeck/variance.rs +++ b/src/librustc_typeck/variance.rs @@ -1046,9 +1046,9 @@ impl<'a, 'tcx> ConstraintContext<'a, 'tcx> { region: ty::Region, variance: VarianceTermPtr<'a>) { match region { - ty::ReEarlyBound(param_id, _, _, _) => { - if self.is_to_be_inferred(param_id) { - let index = self.inferred_index(param_id); + ty::ReEarlyBound(ref data) => { + if self.is_to_be_inferred(data.param_id) { + let index = self.inferred_index(data.param_id); self.add_constraint(index, variance); } } From a4d37bcd687eef8659ff61eec2931c92a09e0caa Mon Sep 17 00:00:00 2001 From: Niko Matsakis Date: Wed, 15 Apr 2015 06:11:18 -0400 Subject: [PATCH 23/25] Augment the constrainted parameter check to ensure that all regions which get mentioned in an associated type are constrained. Arguably we should just require that all regions are constrained, but that is more of a breaking change. Conflicts: src/librustc_typeck/collect.rs --- src/librustc_typeck/collect.rs | 80 ++++++++++++++++--- .../impl-unused-rps-in-assoc-type.rs | 28 +++++++ src/test/compile-fail/issue-22886.rs | 31 +++++++ 3 files changed, 128 insertions(+), 11 deletions(-) create mode 100644 src/test/compile-fail/impl-unused-rps-in-assoc-type.rs create mode 100644 src/test/compile-fail/issue-22886.rs diff --git a/src/librustc_typeck/collect.rs b/src/librustc_typeck/collect.rs index 72adad75865ee..1d338b47b292b 100644 --- a/src/librustc_typeck/collect.rs +++ b/src/librustc_typeck/collect.rs @@ -902,9 +902,10 @@ fn convert_item(ccx: &CrateCtxt, it: &ast::Item) { tcx.impl_trait_refs.borrow_mut().insert(it.id, trait_ref); } - enforce_impl_ty_params_are_constrained(tcx, - generics, - local_def(it.id)); + enforce_impl_params_are_constrained(tcx, + generics, + local_def(it.id), + impl_items); }, ast::ItemTrait(_, _, _, ref trait_items) => { let trait_def = trait_def_of_item(ccx, it); @@ -2188,9 +2189,10 @@ fn check_method_self_type<'a, 'tcx, RS:RegionScope>( } /// Checks that all the type parameters on an impl -fn enforce_impl_ty_params_are_constrained<'tcx>(tcx: &ty::ctxt<'tcx>, - ast_generics: &ast::Generics, - impl_def_id: ast::DefId) +fn enforce_impl_params_are_constrained<'tcx>(tcx: &ty::ctxt<'tcx>, + ast_generics: &ast::Generics, + impl_def_id: ast::DefId, + impl_items: &[P]) { let impl_scheme = ty::lookup_item_type(tcx, impl_def_id); let impl_predicates = ty::lookup_predicates(tcx, impl_def_id); @@ -2216,11 +2218,67 @@ fn enforce_impl_ty_params_are_constrained<'tcx>(tcx: &ty::ctxt<'tcx>, let param_ty = ty::ParamTy { space: TypeSpace, idx: index as u32, name: ty_param.ident.name }; - if !input_parameters.contains(¶m_ty) { - span_err!(tcx.sess, ty_param.span, E0207, - "the type parameter `{}` is not constrained by the \ - impl trait, self type, or predicates", - param_ty.user_string(tcx)); + if !input_parameters.contains(&ctp::Parameter::Type(param_ty)) { + report_unused_parameter(tcx, ty_param.span, "type", ¶m_ty.user_string(tcx)); + } + } + + // Every lifetime used in an associated type must be constrained. + + let lifetimes_in_associated_types: HashSet<_> = + impl_items.iter() + .filter_map(|item| match item.node { + ast::TypeImplItem(..) => Some(ty::node_id_to_type(tcx, item.id)), + ast::MethodImplItem(..) | ast::MacImplItem(..) => None, + }) + .flat_map(|ty| ctp::parameters_for_type(ty).into_iter()) + .filter_map(|p| match p { + ctp::Parameter::Type(_) => None, + ctp::Parameter::Region(r) => Some(r), + }) + .collect(); + + for (index, lifetime_def) in ast_generics.lifetimes.iter().enumerate() { + let region = ty::EarlyBoundRegion { param_id: lifetime_def.lifetime.id, + space: TypeSpace, + index: index as u32, + name: lifetime_def.lifetime.name }; + if + lifetimes_in_associated_types.contains(®ion) && // (*) + !input_parameters.contains(&ctp::Parameter::Region(region)) + { + report_unused_parameter(tcx, lifetime_def.lifetime.span, + "lifetime", ®ion.name.user_string(tcx)); } } + + // (*) This is a horrible concession to reality. I think it'd be + // better to just ban unconstrianed lifetimes outright, but in + // practice people do non-hygenic macros like: + // + // ``` + // macro_rules! __impl_slice_eq1 { + // ($Lhs: ty, $Rhs: ty, $Bound: ident) => { + // impl<'a, 'b, A: $Bound, B> PartialEq<$Rhs> for $Lhs where A: PartialEq { + // .... + // } + // } + // } + // ``` + // + // In a concession to backwards compatbility, we continue to + // permit those, so long as the lifetimes aren't used in + // associated types. I believe this is sound, because lifetimes + // used elsewhere are not projected back out. +} + +fn report_unused_parameter(tcx: &ty::ctxt, + span: Span, + kind: &str, + name: &str) +{ + span_err!(tcx.sess, span, E0207, + "the {} parameter `{}` is not constrained by the \ + impl trait, self type, or predicates", + kind, name); } diff --git a/src/test/compile-fail/impl-unused-rps-in-assoc-type.rs b/src/test/compile-fail/impl-unused-rps-in-assoc-type.rs new file mode 100644 index 0000000000000..23401db21d890 --- /dev/null +++ b/src/test/compile-fail/impl-unused-rps-in-assoc-type.rs @@ -0,0 +1,28 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// Test that lifetime parameters must be constrained if they appear in +// an associated type def'n. Issue #22077. + +trait Fun { + type Output; + fn call<'x>(&'x self) -> Self::Output; +} + +struct Holder { x: String } + +impl<'a> Fun for Holder { //~ ERROR E0207 + type Output = &'a str; + fn call<'b>(&'b self) -> &'b str { + &self.x[..] + } +} + +fn main() { } diff --git a/src/test/compile-fail/issue-22886.rs b/src/test/compile-fail/issue-22886.rs new file mode 100644 index 0000000000000..4aa2571cad0cc --- /dev/null +++ b/src/test/compile-fail/issue-22886.rs @@ -0,0 +1,31 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// Regression test for #22886. + +fn crash_please() { + let mut iter = Newtype(Some(Box::new(0))); + let saved = iter.next().unwrap(); + println!("{}", saved); + iter.0 = None; + println!("{}", saved); +} + +struct Newtype(Option>); + +impl<'a> Iterator for Newtype { //~ ERROR E0207 + type Item = &'a Box; + + fn next(&mut self) -> Option<&Box> { + self.0.as_ref() + } +} + +fn main() { } From 96d927ac7230b6e61b4328e8d6040ffd85fba708 Mon Sep 17 00:00:00 2001 From: Niko Matsakis Date: Wed, 15 Apr 2015 09:13:52 -0400 Subject: [PATCH 24/25] Rewrite constrained type params code to operate generically over multiple kinds of parameters (regions and types, specifically) Conflicts: src/librustc_typeck/collect.rs --- src/librustc_typeck/check/wf.rs | 13 +-- src/librustc_typeck/collect.rs | 22 ++--- .../constrained_type_params.rs | 92 +++++++++++++++---- 3 files changed, 89 insertions(+), 38 deletions(-) diff --git a/src/librustc_typeck/check/wf.rs b/src/librustc_typeck/check/wf.rs index 7f2af1d1b6262..83e0c398590f5 100644 --- a/src/librustc_typeck/check/wf.rs +++ b/src/librustc_typeck/check/wf.rs @@ -10,7 +10,7 @@ use astconv::AstConv; use check::{FnCtxt, Inherited, blank_fn_ctxt, vtable, regionck}; -use constrained_type_params::identify_constrained_type_params; +use constrained_type_params::{identify_constrained_type_params, Parameter}; use CrateCtxt; use middle::region; use middle::subst::{self, TypeSpace, FnSpace, ParamSpace, SelfSpace}; @@ -287,10 +287,11 @@ impl<'ccx, 'tcx> CheckTypeWellFormedVisitor<'ccx, 'tcx> { let mut constrained_parameters: HashSet<_> = variances.types - .iter_enumerated() - .filter(|&(_, _, &variance)| variance != ty::Bivariant) - .map(|(space, index, _)| self.param_ty(ast_generics, space, index)) - .collect(); + .iter_enumerated() + .filter(|&(_, _, &variance)| variance != ty::Bivariant) + .map(|(space, index, _)| self.param_ty(ast_generics, space, index)) + .map(|p| Parameter::Type(p)) + .collect(); identify_constrained_type_params(self.tcx(), ty_predicates.predicates.as_slice(), @@ -299,7 +300,7 @@ impl<'ccx, 'tcx> CheckTypeWellFormedVisitor<'ccx, 'tcx> { for (space, index, _) in variances.types.iter_enumerated() { let param_ty = self.param_ty(ast_generics, space, index); - if constrained_parameters.contains(¶m_ty) { + if constrained_parameters.contains(&Parameter::Type(param_ty)) { continue; } let span = self.ty_param_span(ast_generics, item, space, index); diff --git a/src/librustc_typeck/collect.rs b/src/librustc_typeck/collect.rs index 1d338b47b292b..5ed93703d977f 100644 --- a/src/librustc_typeck/collect.rs +++ b/src/librustc_typeck/collect.rs @@ -66,7 +66,7 @@ There are some shortcomings in this design: use astconv::{self, AstConv, ty_of_arg, ast_ty_to_ty, ast_region_to_region}; use middle::def; -use constrained_type_params::identify_constrained_type_params; +use constrained_type_params as ctp; use middle::lang_items::SizedTraitLangItem; use middle::region; use middle::resolve_lifetime; @@ -2202,17 +2202,15 @@ fn enforce_impl_params_are_constrained<'tcx>(tcx: &ty::ctxt<'tcx>, // reachable from there, to start (if this is an inherent impl, // then just examine the self type). let mut input_parameters: HashSet<_> = - impl_trait_ref.iter() - .flat_map(|t| t.input_types().iter()) // Types in trait ref, if any - .chain(Some(impl_scheme.ty).iter()) // Self type, always - .flat_map(|t| t.walk()) - .filter_map(|t| t.as_opt_param_ty()) - .collect(); - - identify_constrained_type_params(tcx, - impl_predicates.predicates.as_slice(), - impl_trait_ref, - &mut input_parameters); + ctp::parameters_for_type(impl_scheme.ty).into_iter().collect(); + if let Some(ref trait_ref) = impl_trait_ref { + input_parameters.extend(ctp::parameters_for_trait_ref(trait_ref)); + } + + ctp::identify_constrained_type_params(tcx, + impl_predicates.predicates.as_slice(), + impl_trait_ref, + &mut input_parameters); for (index, ty_param) in ast_generics.ty_params.iter().enumerate() { let param_ty = ty::ParamTy { space: TypeSpace, diff --git a/src/librustc_typeck/constrained_type_params.rs b/src/librustc_typeck/constrained_type_params.rs index 83d7e98500007..fad8fbef2a4d4 100644 --- a/src/librustc_typeck/constrained_type_params.rs +++ b/src/librustc_typeck/constrained_type_params.rs @@ -8,49 +8,101 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use middle::ty::{self}; +use middle::subst; +use middle::ty::{self, Ty}; use std::collections::HashSet; use std::rc::Rc; +#[derive(Clone, PartialEq, Eq, Hash, Debug)] +pub enum Parameter { + Type(ty::ParamTy), + Region(ty::EarlyBoundRegion), +} + +pub fn parameters_for_type<'tcx>(ty: Ty<'tcx>) -> Vec { + ty.walk() + .flat_map(|ty| parameters_for_type_shallow(ty).into_iter()) + .collect() +} + +pub fn parameters_for_trait_ref<'tcx>(trait_ref: &Rc>) -> Vec { + let mut region_parameters = + parameters_for_regions_in_substs(&trait_ref.substs); + + let type_parameters = + trait_ref.substs.types.iter() + .flat_map(|ty| parameters_for_type(ty).into_iter()); + + region_parameters.extend(type_parameters); + + region_parameters +} + +fn parameters_for_type_shallow<'tcx>(ty: Ty<'tcx>) -> Vec { + match ty.sty { + ty::ty_param(ref d) => + vec![Parameter::Type(d.clone())], + ty::ty_rptr(region, _) => + parameters_for_region(region).into_iter().collect(), + ty::ty_struct(_, substs) | + ty::ty_enum(_, substs) => + parameters_for_regions_in_substs(substs), + ty::ty_trait(ref data) => + parameters_for_regions_in_substs(&data.principal.skip_binder().substs), + _ => + vec![], + } +} + +fn parameters_for_regions_in_substs(substs: &subst::Substs) -> Vec { + substs.regions() + .iter() + .filter_map(|r| parameters_for_region(r)) + .collect() +} + +fn parameters_for_region(region: &ty::Region) -> Option { + match *region { + ty::ReEarlyBound(data) => Some(Parameter::Region(data)), + _ => None, + } +} + pub fn identify_constrained_type_params<'tcx>(_tcx: &ty::ctxt<'tcx>, predicates: &[ty::Predicate<'tcx>], impl_trait_ref: Option>>, - input_parameters: &mut HashSet) + input_parameters: &mut HashSet) { loop { let num_inputs = input_parameters.len(); - let projection_predicates = + let poly_projection_predicates = // : iterator over PolyProjectionPredicate predicates.iter() .filter_map(|predicate| { match *predicate { - // Ignore higher-ranked binders. For the purposes - // of this check, they don't matter because they - // only affect named regions, and we're just - // concerned about type parameters here. - ty::Predicate::Projection(ref data) => Some(data.0.clone()), + ty::Predicate::Projection(ref data) => Some(data.clone()), _ => None, } }); - for projection in projection_predicates { + for poly_projection in poly_projection_predicates { + // Note that we can skip binder here because the impl + // trait ref never contains any late-bound regions. + let projection = poly_projection.skip_binder(); + // Special case: watch out for some kind of sneaky attempt - // to project out an associated type defined by this very trait. - if Some(projection.projection_ty.trait_ref.clone()) == impl_trait_ref { + // to project out an associated type defined by this very + // trait. + let unbound_trait_ref = &projection.projection_ty.trait_ref; + if Some(unbound_trait_ref.clone()) == impl_trait_ref { continue; } - let relies_only_on_inputs = - projection.projection_ty.trait_ref.input_types() - .iter() - .flat_map(|t| t.walk()) - .filter_map(|t| t.as_opt_param_ty()) - .all(|t| input_parameters.contains(&t)); - + let inputs = parameters_for_trait_ref(&projection.projection_ty.trait_ref); + let relies_only_on_inputs = inputs.iter().all(|p| input_parameters.contains(&p)); if relies_only_on_inputs { - input_parameters.extend( - projection.ty.walk().filter_map(|t| t.as_opt_param_ty())); + input_parameters.extend(parameters_for_type(projection.ty)); } } From 9b1573c1125fee0b409fbf28d862c81e44b2faa0 Mon Sep 17 00:00:00 2001 From: Niko Matsakis Date: Fri, 17 Apr 2015 10:05:25 -0400 Subject: [PATCH 25/25] Fix some missing cases --- src/librustc_driver/test.rs | 7 ++++++- src/librustdoc/clean/mod.rs | 2 +- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/src/librustc_driver/test.rs b/src/librustc_driver/test.rs index f9be71561e384..12b16e95a71a4 100644 --- a/src/librustc_driver/test.rs +++ b/src/librustc_driver/test.rs @@ -290,7 +290,12 @@ impl<'a, 'tcx> Env<'a, 'tcx> { -> ty::Region { let name = token::intern(name); - ty::ReEarlyBound(ast::DUMMY_NODE_ID, space, index, name) + ty::ReEarlyBound(ty::EarlyBoundRegion { + param_id: ast::DUMMY_NODE_ID, + space: space, + index: index, + name: name + }) } pub fn re_late_bound_with_debruijn(&self, id: u32, debruijn: ty::DebruijnIndex) -> ty::Region { diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index 72702dc8d9472..243db610070a6 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -755,7 +755,7 @@ impl Clean> for ty::Region { ty::ReStatic => Some(Lifetime::statik()), ty::ReLateBound(_, ty::BrNamed(_, name)) => Some(Lifetime(token::get_name(name).to_string())), - ty::ReEarlyBound(_, _, _, name) => Some(Lifetime(name.clean(cx))), + ty::ReEarlyBound(ref data) => Some(Lifetime(data.name.clean(cx))), ty::ReLateBound(..) | ty::ReFree(..) |