From 74eef05e7d029cee7407ab7939c326e6ea71a9c9 Mon Sep 17 00:00:00 2001 From: Keegan McAllister Date: Sun, 7 Sep 2014 13:58:41 -0700 Subject: [PATCH 1/6] Use path helper macros in deriving --- src/libsyntax/ext/deriving/clone.rs | 2 +- src/libsyntax/ext/deriving/cmp/eq.rs | 4 ++-- src/libsyntax/ext/deriving/cmp/ord.rs | 8 ++++---- src/libsyntax/ext/deriving/cmp/totaleq.rs | 2 +- src/libsyntax/ext/deriving/cmp/totalord.rs | 4 ++-- src/libsyntax/ext/deriving/decodable.rs | 2 +- src/libsyntax/ext/deriving/default.rs | 2 +- src/libsyntax/ext/deriving/encodable.rs | 2 +- src/libsyntax/ext/deriving/hash.rs | 6 +++--- src/libsyntax/ext/deriving/mod.rs | 12 ++++++++++++ src/libsyntax/ext/deriving/primitive.rs | 12 +++++------- src/libsyntax/ext/deriving/rand.rs | 4 ++-- src/libsyntax/ext/deriving/show.rs | 6 +++--- 13 files changed, 38 insertions(+), 28 deletions(-) diff --git a/src/libsyntax/ext/deriving/clone.rs b/src/libsyntax/ext/deriving/clone.rs index 6eb18e290238e..847af6427ef35 100644 --- a/src/libsyntax/ext/deriving/clone.rs +++ b/src/libsyntax/ext/deriving/clone.rs @@ -29,7 +29,7 @@ pub fn expand_deriving_clone(cx: &mut ExtCtxt, let trait_def = TraitDef { span: span, attributes: Vec::new(), - path: Path::new(vec!("std", "clone", "Clone")), + path: path!(std::clone::Clone), additional_bounds: Vec::new(), generics: LifetimeBounds::empty(), methods: vec!( diff --git a/src/libsyntax/ext/deriving/cmp/eq.rs b/src/libsyntax/ext/deriving/cmp/eq.rs index 00971b96e9288..65c164fc9a159 100644 --- a/src/libsyntax/ext/deriving/cmp/eq.rs +++ b/src/libsyntax/ext/deriving/cmp/eq.rs @@ -70,7 +70,7 @@ pub fn expand_deriving_eq(cx: &mut ExtCtxt, generics: LifetimeBounds::empty(), explicit_self: borrowed_explicit_self(), args: vec!(borrowed_self()), - ret_ty: Literal(Path::new(vec!("bool"))), + ret_ty: Literal(path!(bool)), attributes: attrs, combine_substructure: combine_substructure(box |a, b, c| { $f(a, b, c) @@ -82,7 +82,7 @@ pub fn expand_deriving_eq(cx: &mut ExtCtxt, let trait_def = TraitDef { span: span, attributes: Vec::new(), - path: Path::new(vec!("std", "cmp", "PartialEq")), + path: path!(std::cmp::PartialEq), additional_bounds: Vec::new(), generics: LifetimeBounds::empty(), methods: vec!( diff --git a/src/libsyntax/ext/deriving/cmp/ord.rs b/src/libsyntax/ext/deriving/cmp/ord.rs index 1f92f8d7b372a..8a706e5c46d64 100644 --- a/src/libsyntax/ext/deriving/cmp/ord.rs +++ b/src/libsyntax/ext/deriving/cmp/ord.rs @@ -36,7 +36,7 @@ pub fn expand_deriving_ord(cx: &mut ExtCtxt, generics: LifetimeBounds::empty(), explicit_self: borrowed_explicit_self(), args: vec!(borrowed_self()), - ret_ty: Literal(Path::new(vec!("bool"))), + ret_ty: Literal(path!(bool)), attributes: attrs, combine_substructure: combine_substructure(box |cx, span, substr| { cs_op($op, $equal, cx, span, substr) @@ -45,8 +45,8 @@ pub fn expand_deriving_ord(cx: &mut ExtCtxt, } } } - let ordering_ty = Literal(Path::new(vec!["std", "cmp", "Ordering"])); - let ret_ty = Literal(Path::new_(vec!["std", "option", "Option"], + let ordering_ty = Literal(path!(std::cmp::Ordering)); + let ret_ty = Literal(Path::new_(pathvec!(std::option::Option), None, vec![box ordering_ty], true)); @@ -69,7 +69,7 @@ pub fn expand_deriving_ord(cx: &mut ExtCtxt, let trait_def = TraitDef { span: span, attributes: vec![], - path: Path::new(vec!["std", "cmp", "PartialOrd"]), + path: path!(std::cmp::PartialOrd), additional_bounds: vec![], generics: LifetimeBounds::empty(), methods: vec![ diff --git a/src/libsyntax/ext/deriving/cmp/totaleq.rs b/src/libsyntax/ext/deriving/cmp/totaleq.rs index 0429db3643bb1..9efae379e1f0f 100644 --- a/src/libsyntax/ext/deriving/cmp/totaleq.rs +++ b/src/libsyntax/ext/deriving/cmp/totaleq.rs @@ -46,7 +46,7 @@ pub fn expand_deriving_totaleq(cx: &mut ExtCtxt, let trait_def = TraitDef { span: span, attributes: Vec::new(), - path: Path::new(vec!("std", "cmp", "Eq")), + path: path!(std::cmp::Eq), additional_bounds: Vec::new(), generics: LifetimeBounds::empty(), methods: vec!( diff --git a/src/libsyntax/ext/deriving/cmp/totalord.rs b/src/libsyntax/ext/deriving/cmp/totalord.rs index e90c1aa6fcee8..7a4b717e817fc 100644 --- a/src/libsyntax/ext/deriving/cmp/totalord.rs +++ b/src/libsyntax/ext/deriving/cmp/totalord.rs @@ -30,7 +30,7 @@ pub fn expand_deriving_totalord(cx: &mut ExtCtxt, let trait_def = TraitDef { span: span, attributes: Vec::new(), - path: Path::new(vec!("std", "cmp", "Ord")), + path: path!(std::cmp::Ord), additional_bounds: Vec::new(), generics: LifetimeBounds::empty(), methods: vec!( @@ -39,7 +39,7 @@ pub fn expand_deriving_totalord(cx: &mut ExtCtxt, generics: LifetimeBounds::empty(), explicit_self: borrowed_explicit_self(), args: vec!(borrowed_self()), - ret_ty: Literal(Path::new(vec!("std", "cmp", "Ordering"))), + ret_ty: Literal(path!(std::cmp::Ordering)), attributes: attrs, combine_substructure: combine_substructure(box |a, b, c| { cs_cmp(a, b, c) diff --git a/src/libsyntax/ext/deriving/decodable.rs b/src/libsyntax/ext/deriving/decodable.rs index 9552dff941d27..e7ef2ff060641 100644 --- a/src/libsyntax/ext/deriving/decodable.rs +++ b/src/libsyntax/ext/deriving/decodable.rs @@ -68,7 +68,7 @@ fn expand_deriving_decodable_imp(cx: &mut ExtCtxt, args: vec!(Ptr(box Literal(Path::new_local("__D")), Borrowed(None, MutMutable))), ret_ty: Literal(Path::new_( - vec!("std", "result", "Result"), + pathvec!(std::result::Result), None, vec!(box Self, box Literal(Path::new_( vec!["__D", "Error"], None, vec![], false diff --git a/src/libsyntax/ext/deriving/default.rs b/src/libsyntax/ext/deriving/default.rs index df5e1863d551d..8f210779d3d13 100644 --- a/src/libsyntax/ext/deriving/default.rs +++ b/src/libsyntax/ext/deriving/default.rs @@ -29,7 +29,7 @@ pub fn expand_deriving_default(cx: &mut ExtCtxt, let trait_def = TraitDef { span: span, attributes: Vec::new(), - path: Path::new(vec!("std", "default", "Default")), + path: path!(std::default::Default), additional_bounds: Vec::new(), generics: LifetimeBounds::empty(), methods: vec!( diff --git a/src/libsyntax/ext/deriving/encodable.rs b/src/libsyntax/ext/deriving/encodable.rs index d0b2c2faf3719..c3d42b6a4f7a7 100644 --- a/src/libsyntax/ext/deriving/encodable.rs +++ b/src/libsyntax/ext/deriving/encodable.rs @@ -144,7 +144,7 @@ fn expand_deriving_encodable_imp(cx: &mut ExtCtxt, args: vec!(Ptr(box Literal(Path::new_local("__S")), Borrowed(None, MutMutable))), ret_ty: Literal(Path::new_( - vec!("std", "result", "Result"), + pathvec!(std::result::Result), None, vec!(box Tuple(Vec::new()), box Literal(Path::new_( vec!["__S", "Error"], None, vec![], false diff --git a/src/libsyntax/ext/deriving/hash.rs b/src/libsyntax/ext/deriving/hash.rs index f8a7af3aa9170..2482ea4b7d40d 100644 --- a/src/libsyntax/ext/deriving/hash.rs +++ b/src/libsyntax/ext/deriving/hash.rs @@ -25,13 +25,13 @@ pub fn expand_deriving_hash(cx: &mut ExtCtxt, F: FnOnce(P), { - let path = Path::new_(vec!("std", "hash", "Hash"), None, + let path = Path::new_(pathvec!(std::hash::Hash), None, vec!(box Literal(Path::new_local("__S"))), true); let generics = LifetimeBounds { lifetimes: Vec::new(), bounds: vec!(("__S", - vec!(Path::new(vec!("std", "hash", "Writer")), - Path::new(vec!("std", "hash", "Hasher"))))), + vec!(path!(std::hash::Writer), + path!(std::hash::Hasher)))), }; let args = Path::new_local("__S"); let inline = cx.meta_word(span, InternedString::new("inline")); diff --git a/src/libsyntax/ext/deriving/mod.rs b/src/libsyntax/ext/deriving/mod.rs index 318b748ad7ff2..657ecc63a38dd 100644 --- a/src/libsyntax/ext/deriving/mod.rs +++ b/src/libsyntax/ext/deriving/mod.rs @@ -18,6 +18,18 @@ use ext::base::ExtCtxt; use codemap::Span; use ptr::P; +macro_rules! pathvec { + ($($x:ident)::+) => ( + vec![ $( stringify!($x) ),+ ] + ) +} + +macro_rules! path { + ($($x:tt)*) => ( + ::ext::deriving::generic::ty::Path::new( pathvec!( $($x)* ) ) + ) +} + pub mod bounds; pub mod clone; pub mod encodable; diff --git a/src/libsyntax/ext/deriving/primitive.rs b/src/libsyntax/ext/deriving/primitive.rs index ae7b20f7853fb..3b5d483017f94 100644 --- a/src/libsyntax/ext/deriving/primitive.rs +++ b/src/libsyntax/ext/deriving/primitive.rs @@ -30,7 +30,7 @@ pub fn expand_deriving_from_primitive(cx: &mut ExtCtxt, let trait_def = TraitDef { span: span, attributes: Vec::new(), - path: Path::new(vec!("std", "num", "FromPrimitive")), + path: path!(std::num::FromPrimitive), additional_bounds: Vec::new(), generics: LifetimeBounds::empty(), methods: vec!( @@ -38,9 +38,8 @@ pub fn expand_deriving_from_primitive(cx: &mut ExtCtxt, name: "from_i64", generics: LifetimeBounds::empty(), explicit_self: None, - args: vec!( - Literal(Path::new(vec!("i64")))), - ret_ty: Literal(Path::new_(vec!("std", "option", "Option"), + args: vec!(Literal(path!(i64))), + ret_ty: Literal(Path::new_(pathvec!(std::option::Option), None, vec!(box Self), true)), @@ -54,9 +53,8 @@ pub fn expand_deriving_from_primitive(cx: &mut ExtCtxt, name: "from_u64", generics: LifetimeBounds::empty(), explicit_self: None, - args: vec!( - Literal(Path::new(vec!("u64")))), - ret_ty: Literal(Path::new_(vec!("std", "option", "Option"), + args: vec!(Literal(path!(u64))), + ret_ty: Literal(Path::new_(pathvec!(std::option::Option), None, vec!(box Self), true)), diff --git a/src/libsyntax/ext/deriving/rand.rs b/src/libsyntax/ext/deriving/rand.rs index c708a09b53c9b..84486f770fa17 100644 --- a/src/libsyntax/ext/deriving/rand.rs +++ b/src/libsyntax/ext/deriving/rand.rs @@ -31,7 +31,7 @@ pub fn expand_deriving_rand(cx: &mut ExtCtxt, let trait_def = TraitDef { span: span, attributes: Vec::new(), - path: Path::new(vec!("std", "rand", "Rand")), + path: path!(std::rand::Rand), additional_bounds: Vec::new(), generics: LifetimeBounds::empty(), methods: vec!( @@ -40,7 +40,7 @@ pub fn expand_deriving_rand(cx: &mut ExtCtxt, generics: LifetimeBounds { lifetimes: Vec::new(), bounds: vec!(("R", - vec!( Path::new(vec!("std", "rand", "Rng")) ))) + vec!( path!(std::rand::Rng) ))), }, explicit_self: None, args: vec!( diff --git a/src/libsyntax/ext/deriving/show.rs b/src/libsyntax/ext/deriving/show.rs index 821fdeaa86a1f..d12035193f839 100644 --- a/src/libsyntax/ext/deriving/show.rs +++ b/src/libsyntax/ext/deriving/show.rs @@ -29,13 +29,13 @@ pub fn expand_deriving_show(cx: &mut ExtCtxt, F: FnOnce(P), { // &mut ::std::fmt::Formatter - let fmtr = Ptr(box Literal(Path::new(vec!("std", "fmt", "Formatter"))), + let fmtr = Ptr(box Literal(path!(std::fmt::Formatter)), Borrowed(None, ast::MutMutable)); let trait_def = TraitDef { span: span, attributes: Vec::new(), - path: Path::new(vec!["std", "fmt", "Debug"]), + path: path!(std::fmt::Debug), additional_bounds: Vec::new(), generics: LifetimeBounds::empty(), methods: vec![ @@ -44,7 +44,7 @@ pub fn expand_deriving_show(cx: &mut ExtCtxt, generics: LifetimeBounds::empty(), explicit_self: borrowed_explicit_self(), args: vec!(fmtr), - ret_ty: Literal(Path::new(vec!("std", "fmt", "Result"))), + ret_ty: Literal(path!(std::fmt::Result)), attributes: Vec::new(), combine_substructure: combine_substructure(box |a, b, c| { show_substructure(a, b, c) From 67350bc8681d6df212817644cad7c748039a6238 Mon Sep 17 00:00:00 2001 From: Keegan McAllister Date: Sun, 7 Sep 2014 14:57:26 -0700 Subject: [PATCH 2/6] Don't use std:: paths in syntax extensions when compiling a #![no_std] crate Fixes #16803. Fixes #14342. Fixes half of #21827 -- slice syntax is still broken. --- src/doc/trpl/unsafe.md | 4 -- src/liballoc/lib.rs | 3 +- src/libcollections/fmt.rs | 56 +++++++++++++++ src/libcollections/lib.rs | 18 ++--- src/libcollections/macros.rs | 16 +++++ src/libcollections/ring_buf.rs | 4 +- src/libcore/iter.rs | 2 +- src/libcore/lib.rs | 24 ++++--- src/liblibc/lib.rs | 3 +- src/librand/lib.rs | 3 +- src/librustc_bitflags/lib.rs | 7 ++ src/libstd/fmt.rs | 24 +------ src/libstd/lib.rs | 14 ++-- src/libstd/macros.rs | 1 + src/libsyntax/ext/base.rs | 5 ++ src/libsyntax/ext/build.rs | 45 +++++++----- src/libsyntax/ext/deriving/bounds.rs | 8 ++- src/libsyntax/ext/deriving/clone.rs | 4 +- src/libsyntax/ext/deriving/cmp/eq.rs | 2 +- src/libsyntax/ext/deriving/cmp/ord.rs | 10 +-- src/libsyntax/ext/deriving/cmp/totaleq.rs | 2 +- src/libsyntax/ext/deriving/cmp/totalord.rs | 8 +-- src/libsyntax/ext/deriving/decodable.rs | 8 ++- src/libsyntax/ext/deriving/default.rs | 4 +- src/libsyntax/ext/deriving/encodable.rs | 8 ++- src/libsyntax/ext/deriving/hash.rs | 8 +-- src/libsyntax/ext/deriving/mod.rs | 16 +++++ src/libsyntax/ext/deriving/primitive.rs | 6 +- src/libsyntax/ext/deriving/rand.rs | 6 ++ src/libsyntax/ext/deriving/show.rs | 6 +- src/libsyntax/ext/env.rs | 4 +- src/libsyntax/ext/expand.rs | 7 +- src/libsyntax/ext/format.rs | 10 +-- src/libsyntax/std_inject.rs | 2 +- src/libunicode/lib.rs | 2 + .../derive-no-std-not-supported.rs | 37 ++++++++++ src/test/pretty/issue-4264.pp | 68 +++++++++---------- src/test/run-make/simd-ffi/simd.rs | 2 +- src/test/run-pass/derive-no-std.rs | 40 +++++++++++ src/test/run-pass/for-loop-no-std.rs | 25 +++++++ src/test/run-pass/format-no-std.rs | 36 ++++++++++ 41 files changed, 413 insertions(+), 145 deletions(-) create mode 100644 src/libcollections/fmt.rs create mode 100644 src/test/compile-fail/derive-no-std-not-supported.rs create mode 100644 src/test/run-pass/derive-no-std.rs create mode 100644 src/test/run-pass/for-loop-no-std.rs create mode 100644 src/test/run-pass/format-no-std.rs diff --git a/src/doc/trpl/unsafe.md b/src/doc/trpl/unsafe.md index 2bd86fa987f4b..3acd1eefe89d0 100644 --- a/src/doc/trpl/unsafe.md +++ b/src/doc/trpl/unsafe.md @@ -576,10 +576,6 @@ extern fn panic_fmt(args: &core::fmt::Arguments, #[lang = "eh_personality"] extern fn eh_personality() {} # #[start] fn start(argc: isize, argv: *const *const u8) -> isize { 0 } # fn main() {} -# mod std { // for-loops -# pub use core::iter; -# pub use core::option; -# } ``` Note that there is one extra lang item here which differs from the examples diff --git a/src/liballoc/lib.rs b/src/liballoc/lib.rs index d99a5e2cc6d4a..b3a7e3dbdebf9 100644 --- a/src/liballoc/lib.rs +++ b/src/liballoc/lib.rs @@ -126,7 +126,8 @@ pub fn oom() -> ! { #[doc(hidden)] pub fn fixme_14344_be_sure_to_link_to_collections() {} -#[cfg(not(test))] +// NOTE: remove after next snapshot +#[cfg(all(stage0, not(test)))] #[doc(hidden)] mod std { pub use core::fmt; diff --git a/src/libcollections/fmt.rs b/src/libcollections/fmt.rs new file mode 100644 index 0000000000000..b3f31f33a3a9e --- /dev/null +++ b/src/libcollections/fmt.rs @@ -0,0 +1,56 @@ +// 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. + +//! Formatting support for `String`. +//! +//! See `core::fmt` and `std::fmt` for full documentation on string +//! formatting. + +#![stable(feature = "rust1", since = "1.0.0")] + +use core::fmt; + +use string; + +/// The format function takes a precompiled format string and a list of +/// arguments, to return the resulting formatted string. +/// +/// # Arguments +/// +/// * args - a structure of arguments generated via the `format_args!` macro. +/// +/// # Example +/// +/// ```rust +/// use std::fmt; +/// +/// let s = fmt::format(format_args!("Hello, {}!", "world")); +/// assert_eq!(s, "Hello, world!".to_string()); +/// ``` +#[stable(feature = "rust1", since = "1.0.0")] +pub fn format(args: fmt::Arguments) -> string::String { + // FIXME #21826 + use core::fmt::Writer; + let mut output = string::String::new(); + let _ = write!(&mut output, "{}", args); + output +} + +#[cfg(test)] +mod tests { + use prelude::*; + use fmt; + + #[test] + fn test_format() { + let s = fmt::format(format_args!("Hello, {}!", "world")); + assert_eq!(s.as_slice(), "Hello, world!"); + } +} diff --git a/src/libcollections/lib.rs b/src/libcollections/lib.rs index 57c799785e82d..05d84eda13d75 100644 --- a/src/libcollections/lib.rs +++ b/src/libcollections/lib.rs @@ -68,6 +68,7 @@ mod bit; mod btree; pub mod dlist; pub mod enum_set; +pub mod fmt; pub mod ring_buf; pub mod slice; pub mod str; @@ -107,15 +108,16 @@ pub fn fixme_14344_be_sure_to_link_to_collections() {} #[cfg(not(test))] mod std { - pub use core::fmt; // necessary for panic!() - pub use core::option; // necessary for panic!() - pub use core::clone; // derive(Clone) - pub use core::cmp; // derive(Eq, Ord, etc.) - pub use core::marker; // derive(Copy) - pub use core::hash; // derive(Hash) + // NOTE: remove after next snapshot + #[cfg(stage0)] pub use core::clone; // derive(Clone) + #[cfg(stage0)] pub use core::cmp; // derive(Eq, Ord, etc.) + #[cfg(stage0)] pub use core::marker; // derive(Copy) + #[cfg(stage0)] pub use core::hash; // derive(Hash) + #[cfg(stage0)] pub use core::iter; + #[cfg(stage0)] pub use core::fmt; // necessary for panic!() + #[cfg(stage0)] pub use core::option; // necessary for panic!() + pub use core::ops; // RangeFull - // for-loops - pub use core::iter; } #[cfg(test)] diff --git a/src/libcollections/macros.rs b/src/libcollections/macros.rs index 15048998592a9..79c86a846f1b9 100644 --- a/src/libcollections/macros.rs +++ b/src/libcollections/macros.rs @@ -22,3 +22,19 @@ macro_rules! vec { ); ($($x:expr,)*) => (vec![$($x),*]) } + +/// Use the syntax described in `std::fmt` to create a value of type `String`. +/// See `std::fmt` for more information. +/// +/// # Example +/// +/// ``` +/// format!("test"); +/// format!("hello {}", "world!"); +/// format!("x = {}, y = {y}", 10, y = 30); +/// ``` +#[macro_export] +#[stable(feature = "rust1", since = "1.0.0")] +macro_rules! format { + ($($arg:tt)*) => ($crate::fmt::format(format_args!($($arg)*))) +} diff --git a/src/libcollections/ring_buf.rs b/src/libcollections/ring_buf.rs index 417493038404a..76849e6ade85a 100644 --- a/src/libcollections/ring_buf.rs +++ b/src/libcollections/ring_buf.rs @@ -27,8 +27,8 @@ use core::ops::{Index, IndexMut}; use core::ptr; use core::raw::Slice as RawSlice; -use std::hash::{Writer, Hash, Hasher}; -use std::cmp; +use core::hash::{Writer, Hash, Hasher}; +use core::cmp; use alloc::heap; diff --git a/src/libcore/iter.rs b/src/libcore/iter.rs index f3b42e4f0a577..5df64cfaadaaa 100644 --- a/src/libcore/iter.rs +++ b/src/libcore/iter.rs @@ -67,7 +67,7 @@ use num::{ToPrimitive, Int}; use ops::{Add, Deref, FnMut}; use option::Option; use option::Option::{Some, None}; -use std::marker::Sized; +use marker::Sized; use usize; /// An interface for dealing with "external iterators". These types of iterators diff --git a/src/libcore/lib.rs b/src/libcore/lib.rs index 5e9793f270ded..4c031b3e7cc93 100644 --- a/src/libcore/lib.rs +++ b/src/libcore/lib.rs @@ -148,17 +148,25 @@ mod array; mod core { pub use panicking; pub use fmt; + #[cfg(not(stage0))] pub use clone; + #[cfg(not(stage0))] pub use cmp; + #[cfg(not(stage0))] pub use hash; + #[cfg(not(stage0))] pub use marker; + #[cfg(not(stage0))] pub use option; + #[cfg(not(stage0))] pub use iter; } #[doc(hidden)] mod std { - pub use clone; - pub use cmp; - pub use fmt; - pub use hash; - pub use marker; + // NOTE: remove after next snapshot + #[cfg(stage0)] pub use clone; + #[cfg(stage0)] pub use cmp; + #[cfg(stage0)] pub use hash; + #[cfg(stage0)] pub use marker; + #[cfg(stage0)] pub use option; + #[cfg(stage0)] pub use fmt; + #[cfg(stage0)] pub use iter; + + // range syntax pub use ops; - pub use option; - // for-loops - pub use iter; } diff --git a/src/liblibc/lib.rs b/src/liblibc/lib.rs index b643b04035f2a..060e7ef403318 100644 --- a/src/liblibc/lib.rs +++ b/src/liblibc/lib.rs @@ -5729,8 +5729,9 @@ pub fn issue_14344_workaround() {} // FIXME #14344 force linkage to happen corre #[test] fn work_on_windows() { } // FIXME #10872 needed for a happy windows +// NOTE: remove after next snapshot #[doc(hidden)] -#[cfg(not(test))] +#[cfg(all(stage0, not(test)))] mod std { pub use core::marker; } diff --git a/src/librand/lib.rs b/src/librand/lib.rs index 0a64da6f137bd..777b1ed8ceb6a 100644 --- a/src/librand/lib.rs +++ b/src/librand/lib.rs @@ -496,7 +496,8 @@ pub struct Open01(pub F); /// ``` pub struct Closed01(pub F); -#[cfg(not(test))] +// NOTE: remove after next snapshot +#[cfg(all(stage0, not(test)))] mod std { pub use core::{option, fmt}; // panic!() pub use core::clone; // derive Clone diff --git a/src/librustc_bitflags/lib.rs b/src/librustc_bitflags/lib.rs index 031607728797e..0139dfbd50b47 100644 --- a/src/librustc_bitflags/lib.rs +++ b/src/librustc_bitflags/lib.rs @@ -281,6 +281,13 @@ macro_rules! bitflags { }; } +// This is a no_std crate. So the test code's invocation of #[derive] etc, via +// bitflags!, will use names from the underlying crates. +#[cfg(test)] +mod core { + pub use std::{fmt, hash, clone, cmp, marker, option}; +} + #[cfg(test)] #[allow(non_upper_case_globals)] mod tests { diff --git a/src/libstd/fmt.rs b/src/libstd/fmt.rs index 47f5d64e2607c..82823f0cb28dc 100644 --- a/src/libstd/fmt.rs +++ b/src/libstd/fmt.rs @@ -403,8 +403,6 @@ #![unstable(feature = "std_misc")] -use string; - pub use core::fmt::{Formatter, Result, Writer, rt}; pub use core::fmt::{Show, String, Octal, Binary}; pub use core::fmt::{Display, Debug}; @@ -413,24 +411,4 @@ pub use core::fmt::{LowerExp, UpperExp}; pub use core::fmt::Error; pub use core::fmt::{ArgumentV1, Arguments, write, radix, Radix, RadixFmt}; -/// The format function takes a precompiled format string and a list of -/// arguments, to return the resulting formatted string. -/// -/// # Arguments -/// -/// * args - a structure of arguments generated via the `format_args!` macro. -/// -/// # Example -/// -/// ```rust -/// use std::fmt; -/// -/// let s = fmt::format(format_args!("Hello, {}!", "world")); -/// assert_eq!(s, "Hello, world!".to_string()); -/// ``` -#[stable(feature = "rust1", since = "1.0.0")] -pub fn format(args: Arguments) -> string::String { - let mut output = string::String::new(); - let _ = write!(&mut output, "{}", args); - output -} +pub use core_collections::fmt::format; diff --git a/src/libstd/lib.rs b/src/libstd/lib.rs index 14e779f9c4a8e..e54086159002e 100644 --- a/src/libstd/lib.rs +++ b/src/libstd/lib.rs @@ -137,7 +137,7 @@ extern crate core; #[macro_use] -#[macro_reexport(vec)] +#[macro_reexport(vec, format)] extern crate "collections" as core_collections; #[allow(deprecated)] extern crate "rand" as core_rand; @@ -285,11 +285,12 @@ mod tuple; // can be resolved within libstd. #[doc(hidden)] mod std { + // NOTE: remove after next snapshot // mods used for deriving - pub use clone; - pub use cmp; - pub use hash; - pub use default; + #[cfg(stage0)] pub use clone; + #[cfg(stage0)] pub use cmp; + #[cfg(stage0)] pub use hash; + #[cfg(stage0)] pub use default; pub use sync; // used for select!() pub use error; // used for try!() @@ -312,5 +313,6 @@ mod std { pub use boxed; // used for vec![] // for-loops - pub use iter; + // NOTE: remove after next snapshot + #[cfg(stage0)] pub use iter; } diff --git a/src/libstd/macros.rs b/src/libstd/macros.rs index e91e8241a55be..6a2aafcf8f396 100644 --- a/src/libstd/macros.rs +++ b/src/libstd/macros.rs @@ -70,6 +70,7 @@ macro_rules! panic { /// format!("hello {}", "world!"); /// format!("x = {}, y = {y}", 10, y = 30); /// ``` +#[cfg(stage0)] // NOTE: remove after snapshot #[macro_export] #[stable(feature = "rust1", since = "1.0.0")] macro_rules! format { diff --git a/src/libsyntax/ext/base.rs b/src/libsyntax/ext/base.rs index b5f6893a8c279..778b2cabea622 100644 --- a/src/libsyntax/ext/base.rs +++ b/src/libsyntax/ext/base.rs @@ -544,6 +544,7 @@ pub struct ExtCtxt<'a> { pub cfg: ast::CrateConfig, pub backtrace: ExpnId, pub ecfg: expand::ExpansionConfig, + pub use_std: bool, pub mod_path: Vec , pub trace_mac: bool, @@ -563,6 +564,7 @@ impl<'a> ExtCtxt<'a> { backtrace: NO_EXPANSION, mod_path: Vec::new(), ecfg: ecfg, + use_std: true, trace_mac: false, exported_macros: Vec::new(), syntax_env: env, @@ -737,6 +739,9 @@ impl<'a> ExtCtxt<'a> { pub fn ident_of(&self, st: &str) -> ast::Ident { str_to_ident(st) } + pub fn ident_of_std(&self, st: &str) -> ast::Ident { + self.ident_of(if self.use_std { "std" } else { st }) + } pub fn name_of(&self, st: &str) -> ast::Name { token::intern(st) } diff --git a/src/libsyntax/ext/build.rs b/src/libsyntax/ext/build.rs index 55faf692e98f3..a7d1baf08beac 100644 --- a/src/libsyntax/ext/build.rs +++ b/src/libsyntax/ext/build.rs @@ -386,7 +386,7 @@ impl<'a> AstBuilder for ExtCtxt<'a> { self.path_all(DUMMY_SP, true, vec!( - self.ident_of("std"), + self.ident_of_std("core"), self.ident_of("option"), self.ident_of("Option") ), @@ -656,7 +656,7 @@ impl<'a> AstBuilder for ExtCtxt<'a> { } fn expr_vec_ng(&self, sp: Span) -> P { self.expr_call_global(sp, - vec!(self.ident_of("std"), + vec!(self.ident_of_std("collections"), self.ident_of("vec"), self.ident_of("Vec"), self.ident_of("new")), @@ -676,7 +676,7 @@ impl<'a> AstBuilder for ExtCtxt<'a> { fn expr_some(&self, sp: Span, expr: P) -> P { let some = vec!( - self.ident_of("std"), + self.ident_of_std("core"), self.ident_of("option"), self.ident_of("Option"), self.ident_of("Some")); @@ -685,7 +685,7 @@ impl<'a> AstBuilder for ExtCtxt<'a> { fn expr_none(&self, sp: Span) -> P { let none = self.path_global(sp, vec!( - self.ident_of("std"), + self.ident_of_std("core"), self.ident_of("option"), self.ident_of("Option"), self.ident_of("None"))); @@ -712,7 +712,7 @@ impl<'a> AstBuilder for ExtCtxt<'a> { self.expr_call_global( span, vec!( - self.ident_of("std"), + self.ident_of_std("core"), self.ident_of("rt"), self.ident_of("begin_unwind")), vec!( @@ -728,7 +728,7 @@ impl<'a> AstBuilder for ExtCtxt<'a> { fn expr_ok(&self, sp: Span, expr: P) -> P { let ok = vec!( - self.ident_of("std"), + self.ident_of_std("core"), self.ident_of("result"), self.ident_of("Result"), self.ident_of("Ok")); @@ -737,7 +737,7 @@ impl<'a> AstBuilder for ExtCtxt<'a> { fn expr_err(&self, sp: Span, expr: P) -> P { let err = vec!( - self.ident_of("std"), + self.ident_of_std("core"), self.ident_of("result"), self.ident_of("Result"), self.ident_of("Err")); @@ -745,10 +745,20 @@ impl<'a> AstBuilder for ExtCtxt<'a> { } fn expr_try(&self, sp: Span, head: P) -> P { - let ok = self.ident_of("Ok"); - let ok_path = self.path_ident(sp, ok); - let err = self.ident_of("Err"); - let err_path = self.path_ident(sp, err); + let ok = vec![ + self.ident_of_std("core"), + self.ident_of("result"), + self.ident_of("Result"), + self.ident_of("Ok") + ]; + let ok_path = self.path_global(sp, ok); + let err = vec![ + self.ident_of_std("core"), + self.ident_of("result"), + self.ident_of("Result"), + self.ident_of("Err") + ]; + let err_path = self.path_global(sp, err); let binding_variable = self.ident_of("__try_var"); let binding_pat = self.pat_ident(sp, binding_variable); @@ -758,8 +768,9 @@ impl<'a> AstBuilder for ExtCtxt<'a> { let ok_pat = self.pat_enum(sp, ok_path, vec!(binding_pat.clone())); // Err(__try_var) (pattern and expression resp.) - let err_pat = self.pat_enum(sp, err_path, vec!(binding_pat)); - let err_inner_expr = self.expr_call_ident(sp, err, vec!(binding_expr.clone())); + let err_pat = self.pat_enum(sp, err_path.clone(), vec!(binding_pat)); + let err_inner_expr = self.expr_call(sp, self.expr_path(err_path), + vec!(binding_expr.clone())); // return Err(__try_var) let err_expr = self.expr(sp, ast::ExprRet(Some(err_inner_expr))); @@ -808,7 +819,7 @@ impl<'a> AstBuilder for ExtCtxt<'a> { fn pat_some(&self, span: Span, pat: P) -> P { let some = vec!( - self.ident_of("std"), + self.ident_of_std("core"), self.ident_of("option"), self.ident_of("Option"), self.ident_of("Some")); @@ -818,7 +829,7 @@ impl<'a> AstBuilder for ExtCtxt<'a> { fn pat_none(&self, span: Span) -> P { let some = vec!( - self.ident_of("std"), + self.ident_of_std("core"), self.ident_of("option"), self.ident_of("Option"), self.ident_of("None")); @@ -828,7 +839,7 @@ impl<'a> AstBuilder for ExtCtxt<'a> { fn pat_ok(&self, span: Span, pat: P) -> P { let some = vec!( - self.ident_of("std"), + self.ident_of_std("core"), self.ident_of("result"), self.ident_of("Result"), self.ident_of("Ok")); @@ -838,7 +849,7 @@ impl<'a> AstBuilder for ExtCtxt<'a> { fn pat_err(&self, span: Span, pat: P) -> P { let some = vec!( - self.ident_of("std"), + self.ident_of_std("core"), self.ident_of("result"), self.ident_of("Result"), self.ident_of("Err")); diff --git a/src/libsyntax/ext/deriving/bounds.rs b/src/libsyntax/ext/deriving/bounds.rs index 1c82ca5d2add7..879718a6399f5 100644 --- a/src/libsyntax/ext/deriving/bounds.rs +++ b/src/libsyntax/ext/deriving/bounds.rs @@ -45,10 +45,16 @@ pub fn expand_deriving_bound(cx: &mut ExtCtxt, } }; + let path = Path::new(vec![ + if cx.use_std { "std" } else { "core" }, + "marker", + name + ]); + let trait_def = TraitDef { span: span, attributes: Vec::new(), - path: Path::new(vec!("std", "marker", name)), + path: path, additional_bounds: Vec::new(), generics: LifetimeBounds::empty(), methods: Vec::new(), diff --git a/src/libsyntax/ext/deriving/clone.rs b/src/libsyntax/ext/deriving/clone.rs index 847af6427ef35..9f009ad4d7869 100644 --- a/src/libsyntax/ext/deriving/clone.rs +++ b/src/libsyntax/ext/deriving/clone.rs @@ -29,7 +29,7 @@ pub fn expand_deriving_clone(cx: &mut ExtCtxt, let trait_def = TraitDef { span: span, attributes: Vec::new(), - path: path!(std::clone::Clone), + path: path_std!(cx, core::clone::Clone), additional_bounds: Vec::new(), generics: LifetimeBounds::empty(), methods: vec!( @@ -58,7 +58,7 @@ fn cs_clone( let ctor_path; let all_fields; let fn_path = vec![ - cx.ident_of("std"), + cx.ident_of_std("core"), cx.ident_of("clone"), cx.ident_of("Clone"), cx.ident_of("clone"), diff --git a/src/libsyntax/ext/deriving/cmp/eq.rs b/src/libsyntax/ext/deriving/cmp/eq.rs index 65c164fc9a159..91212a8695896 100644 --- a/src/libsyntax/ext/deriving/cmp/eq.rs +++ b/src/libsyntax/ext/deriving/cmp/eq.rs @@ -82,7 +82,7 @@ pub fn expand_deriving_eq(cx: &mut ExtCtxt, let trait_def = TraitDef { span: span, attributes: Vec::new(), - path: path!(std::cmp::PartialEq), + path: path_std!(cx, core::cmp::PartialEq), additional_bounds: Vec::new(), generics: LifetimeBounds::empty(), methods: vec!( diff --git a/src/libsyntax/ext/deriving/cmp/ord.rs b/src/libsyntax/ext/deriving/cmp/ord.rs index 8a706e5c46d64..b109850a6bd23 100644 --- a/src/libsyntax/ext/deriving/cmp/ord.rs +++ b/src/libsyntax/ext/deriving/cmp/ord.rs @@ -45,8 +45,8 @@ pub fn expand_deriving_ord(cx: &mut ExtCtxt, } } } - let ordering_ty = Literal(path!(std::cmp::Ordering)); - let ret_ty = Literal(Path::new_(pathvec!(std::option::Option), + let ordering_ty = Literal(path_std!(cx, core::cmp::Ordering)); + let ret_ty = Literal(Path::new_(pathvec_std!(cx, core::option::Option), None, vec![box ordering_ty], true)); @@ -69,7 +69,7 @@ pub fn expand_deriving_ord(cx: &mut ExtCtxt, let trait_def = TraitDef { span: span, attributes: vec![], - path: path!(std::cmp::PartialOrd), + path: path_std!(cx, core::cmp::PartialOrd), additional_bounds: vec![], generics: LifetimeBounds::empty(), methods: vec![ @@ -107,7 +107,7 @@ pub fn cs_partial_cmp(cx: &mut ExtCtxt, span: Span, substr: &Substructure) -> P { let test_id = cx.ident_of("__test"); let ordering = cx.path_global(span, - vec!(cx.ident_of("std"), + vec!(cx.ident_of_std("core"), cx.ident_of("cmp"), cx.ident_of("Ordering"), cx.ident_of("Equal"))); @@ -115,7 +115,7 @@ pub fn cs_partial_cmp(cx: &mut ExtCtxt, span: Span, let equals_expr = cx.expr_some(span, ordering); let partial_cmp_path = vec![ - cx.ident_of("std"), + cx.ident_of_std("core"), cx.ident_of("cmp"), cx.ident_of("PartialOrd"), cx.ident_of("partial_cmp"), diff --git a/src/libsyntax/ext/deriving/cmp/totaleq.rs b/src/libsyntax/ext/deriving/cmp/totaleq.rs index 9efae379e1f0f..31a754a1254bb 100644 --- a/src/libsyntax/ext/deriving/cmp/totaleq.rs +++ b/src/libsyntax/ext/deriving/cmp/totaleq.rs @@ -46,7 +46,7 @@ pub fn expand_deriving_totaleq(cx: &mut ExtCtxt, let trait_def = TraitDef { span: span, attributes: Vec::new(), - path: path!(std::cmp::Eq), + path: path_std!(cx, core::cmp::Eq), additional_bounds: Vec::new(), generics: LifetimeBounds::empty(), methods: vec!( diff --git a/src/libsyntax/ext/deriving/cmp/totalord.rs b/src/libsyntax/ext/deriving/cmp/totalord.rs index 7a4b717e817fc..2f6f99bc1ee46 100644 --- a/src/libsyntax/ext/deriving/cmp/totalord.rs +++ b/src/libsyntax/ext/deriving/cmp/totalord.rs @@ -30,7 +30,7 @@ pub fn expand_deriving_totalord(cx: &mut ExtCtxt, let trait_def = TraitDef { span: span, attributes: Vec::new(), - path: path!(std::cmp::Ord), + path: path_std!(cx, core::cmp::Ord), additional_bounds: Vec::new(), generics: LifetimeBounds::empty(), methods: vec!( @@ -39,7 +39,7 @@ pub fn expand_deriving_totalord(cx: &mut ExtCtxt, generics: LifetimeBounds::empty(), explicit_self: borrowed_explicit_self(), args: vec!(borrowed_self()), - ret_ty: Literal(path!(std::cmp::Ordering)), + ret_ty: Literal(path_std!(cx, core::cmp::Ordering)), attributes: attrs, combine_substructure: combine_substructure(box |a, b, c| { cs_cmp(a, b, c) @@ -65,13 +65,13 @@ pub fn cs_cmp(cx: &mut ExtCtxt, span: Span, substr: &Substructure) -> P { let test_id = cx.ident_of("__test"); let equals_path = cx.path_global(span, - vec!(cx.ident_of("std"), + vec!(cx.ident_of_std("core"), cx.ident_of("cmp"), cx.ident_of("Ordering"), cx.ident_of("Equal"))); let cmp_path = vec![ - cx.ident_of("std"), + cx.ident_of_std("core"), cx.ident_of("cmp"), cx.ident_of("Ord"), cx.ident_of("cmp"), diff --git a/src/libsyntax/ext/deriving/decodable.rs b/src/libsyntax/ext/deriving/decodable.rs index e7ef2ff060641..f003a3453e15e 100644 --- a/src/libsyntax/ext/deriving/decodable.rs +++ b/src/libsyntax/ext/deriving/decodable.rs @@ -49,6 +49,12 @@ fn expand_deriving_decodable_imp(cx: &mut ExtCtxt, krate: &'static str) where F: FnOnce(P), { + if !cx.use_std { + // FIXME(#21880): lift this requirement. + cx.span_err(span, "this trait cannot be derived with #![no_std]"); + return; + } + let trait_def = TraitDef { span: span, attributes: Vec::new(), @@ -68,7 +74,7 @@ fn expand_deriving_decodable_imp(cx: &mut ExtCtxt, args: vec!(Ptr(box Literal(Path::new_local("__D")), Borrowed(None, MutMutable))), ret_ty: Literal(Path::new_( - pathvec!(std::result::Result), + pathvec_std!(cx, core::result::Result), None, vec!(box Self, box Literal(Path::new_( vec!["__D", "Error"], None, vec![], false diff --git a/src/libsyntax/ext/deriving/default.rs b/src/libsyntax/ext/deriving/default.rs index 8f210779d3d13..9b76f4b1658f0 100644 --- a/src/libsyntax/ext/deriving/default.rs +++ b/src/libsyntax/ext/deriving/default.rs @@ -29,7 +29,7 @@ pub fn expand_deriving_default(cx: &mut ExtCtxt, let trait_def = TraitDef { span: span, attributes: Vec::new(), - path: path!(std::default::Default), + path: path_std!(cx, core::default::Default), additional_bounds: Vec::new(), generics: LifetimeBounds::empty(), methods: vec!( @@ -52,7 +52,7 @@ pub fn expand_deriving_default(cx: &mut ExtCtxt, fn default_substructure(cx: &mut ExtCtxt, trait_span: Span, substr: &Substructure) -> P { let default_ident = vec!( - cx.ident_of("std"), + cx.ident_of_std("core"), cx.ident_of("default"), cx.ident_of("Default"), cx.ident_of("default") diff --git a/src/libsyntax/ext/deriving/encodable.rs b/src/libsyntax/ext/deriving/encodable.rs index c3d42b6a4f7a7..dd6094705995e 100644 --- a/src/libsyntax/ext/deriving/encodable.rs +++ b/src/libsyntax/ext/deriving/encodable.rs @@ -125,6 +125,12 @@ fn expand_deriving_encodable_imp(cx: &mut ExtCtxt, krate: &'static str) where F: FnOnce(P), { + if !cx.use_std { + // FIXME(#21880): lift this requirement. + cx.span_err(span, "this trait cannot be derived with #![no_std]"); + return; + } + let trait_def = TraitDef { span: span, attributes: Vec::new(), @@ -144,7 +150,7 @@ fn expand_deriving_encodable_imp(cx: &mut ExtCtxt, args: vec!(Ptr(box Literal(Path::new_local("__S")), Borrowed(None, MutMutable))), ret_ty: Literal(Path::new_( - pathvec!(std::result::Result), + pathvec_std!(cx, core::result::Result), None, vec!(box Tuple(Vec::new()), box Literal(Path::new_( vec!["__S", "Error"], None, vec![], false diff --git a/src/libsyntax/ext/deriving/hash.rs b/src/libsyntax/ext/deriving/hash.rs index 2482ea4b7d40d..5aa9f9a0c3e76 100644 --- a/src/libsyntax/ext/deriving/hash.rs +++ b/src/libsyntax/ext/deriving/hash.rs @@ -25,13 +25,13 @@ pub fn expand_deriving_hash(cx: &mut ExtCtxt, F: FnOnce(P), { - let path = Path::new_(pathvec!(std::hash::Hash), None, + let path = Path::new_(pathvec_std!(cx, core::hash::Hash), None, vec!(box Literal(Path::new_local("__S"))), true); let generics = LifetimeBounds { lifetimes: Vec::new(), bounds: vec!(("__S", - vec!(path!(std::hash::Writer), - path!(std::hash::Hasher)))), + vec!(path_std!(cx, core::hash::Writer), + path_std!(cx, core::hash::Hasher)))), }; let args = Path::new_local("__S"); let inline = cx.meta_word(span, InternedString::new("inline")); @@ -69,7 +69,7 @@ fn hash_substructure(cx: &mut ExtCtxt, trait_span: Span, substr: &Substructure) let call_hash = |span, thing_expr| { let hash_path = { let strs = vec![ - cx.ident_of("std"), + cx.ident_of_std("core"), cx.ident_of("hash"), cx.ident_of("Hash"), cx.ident_of("hash"), diff --git a/src/libsyntax/ext/deriving/mod.rs b/src/libsyntax/ext/deriving/mod.rs index 657ecc63a38dd..9c3fa58ad0960 100644 --- a/src/libsyntax/ext/deriving/mod.rs +++ b/src/libsyntax/ext/deriving/mod.rs @@ -30,6 +30,22 @@ macro_rules! path { ) } +macro_rules! pathvec_std { + ($cx:expr, $first:ident :: $($rest:ident)::+) => ( + if $cx.use_std { + pathvec!(std :: $($rest)::+) + } else { + pathvec!($first :: $($rest)::+) + } + ) +} + +macro_rules! path_std { + ($($x:tt)*) => ( + ::ext::deriving::generic::ty::Path::new( pathvec_std!( $($x)* ) ) + ) +} + pub mod bounds; pub mod clone; pub mod encodable; diff --git a/src/libsyntax/ext/deriving/primitive.rs b/src/libsyntax/ext/deriving/primitive.rs index 3b5d483017f94..bf742263c6d87 100644 --- a/src/libsyntax/ext/deriving/primitive.rs +++ b/src/libsyntax/ext/deriving/primitive.rs @@ -30,7 +30,7 @@ pub fn expand_deriving_from_primitive(cx: &mut ExtCtxt, let trait_def = TraitDef { span: span, attributes: Vec::new(), - path: path!(std::num::FromPrimitive), + path: path_std!(cx, core::num::FromPrimitive), additional_bounds: Vec::new(), generics: LifetimeBounds::empty(), methods: vec!( @@ -39,7 +39,7 @@ pub fn expand_deriving_from_primitive(cx: &mut ExtCtxt, generics: LifetimeBounds::empty(), explicit_self: None, args: vec!(Literal(path!(i64))), - ret_ty: Literal(Path::new_(pathvec!(std::option::Option), + ret_ty: Literal(Path::new_(pathvec_std!(cx, core::option::Option), None, vec!(box Self), true)), @@ -54,7 +54,7 @@ pub fn expand_deriving_from_primitive(cx: &mut ExtCtxt, generics: LifetimeBounds::empty(), explicit_self: None, args: vec!(Literal(path!(u64))), - ret_ty: Literal(Path::new_(pathvec!(std::option::Option), + ret_ty: Literal(Path::new_(pathvec_std!(cx, core::option::Option), None, vec!(box Self), true)), diff --git a/src/libsyntax/ext/deriving/rand.rs b/src/libsyntax/ext/deriving/rand.rs index 84486f770fa17..4c3678d9572da 100644 --- a/src/libsyntax/ext/deriving/rand.rs +++ b/src/libsyntax/ext/deriving/rand.rs @@ -28,6 +28,12 @@ pub fn expand_deriving_rand(cx: &mut ExtCtxt, "`#[derive(Rand)]` is deprecated in favour of `#[derive_Rand]` from \ `rand_macros` on crates.io"); + if !cx.use_std { + // FIXME(#21880): lift this requirement. + cx.span_err(span, "this trait cannot be derived with #![no_std]"); + return; + } + let trait_def = TraitDef { span: span, attributes: Vec::new(), diff --git a/src/libsyntax/ext/deriving/show.rs b/src/libsyntax/ext/deriving/show.rs index d12035193f839..3f5947672e022 100644 --- a/src/libsyntax/ext/deriving/show.rs +++ b/src/libsyntax/ext/deriving/show.rs @@ -29,13 +29,13 @@ pub fn expand_deriving_show(cx: &mut ExtCtxt, F: FnOnce(P), { // &mut ::std::fmt::Formatter - let fmtr = Ptr(box Literal(path!(std::fmt::Formatter)), + let fmtr = Ptr(box Literal(path_std!(cx, core::fmt::Formatter)), Borrowed(None, ast::MutMutable)); let trait_def = TraitDef { span: span, attributes: Vec::new(), - path: path!(std::fmt::Debug), + path: path_std!(cx, core::fmt::Debug), additional_bounds: Vec::new(), generics: LifetimeBounds::empty(), methods: vec![ @@ -44,7 +44,7 @@ pub fn expand_deriving_show(cx: &mut ExtCtxt, generics: LifetimeBounds::empty(), explicit_self: borrowed_explicit_self(), args: vec!(fmtr), - ret_ty: Literal(path!(std::fmt::Result)), + ret_ty: Literal(path_std!(cx, core::fmt::Result)), attributes: Vec::new(), combine_substructure: combine_substructure(box |a, b, c| { show_substructure(a, b, c) diff --git a/src/libsyntax/ext/env.rs b/src/libsyntax/ext/env.rs index 417506cf3aadb..ef9d379987932 100644 --- a/src/libsyntax/ext/env.rs +++ b/src/libsyntax/ext/env.rs @@ -34,7 +34,7 @@ pub fn expand_option_env<'cx>(cx: &'cx mut ExtCtxt, sp: Span, tts: &[ast::TokenT Err(..) => { cx.expr_path(cx.path_all(sp, true, - vec!(cx.ident_of("std"), + vec!(cx.ident_of_std("core"), cx.ident_of("option"), cx.ident_of("Option"), cx.ident_of("None")), @@ -50,7 +50,7 @@ pub fn expand_option_env<'cx>(cx: &'cx mut ExtCtxt, sp: Span, tts: &[ast::TokenT } Ok(s) => { cx.expr_call_global(sp, - vec!(cx.ident_of("std"), + vec!(cx.ident_of_std("core"), cx.ident_of("option"), cx.ident_of("Option"), cx.ident_of("Some")), diff --git a/src/libsyntax/ext/expand.rs b/src/libsyntax/ext/expand.rs index 33712dae900b8..95e015fee6d3c 100644 --- a/src/libsyntax/ext/expand.rs +++ b/src/libsyntax/ext/expand.rs @@ -31,6 +31,7 @@ use ptr::P; use util::small_vector::SmallVector; use visit; use visit::Visitor; +use std_inject; pub fn expand_type(t: P, fld: &mut MacroExpander, @@ -275,7 +276,7 @@ pub fn expand_expr(e: P, fld: &mut MacroExpander) -> P { let match_expr = { let next_path = { let strs = vec![ - fld.cx.ident_of("std"), + fld.cx.ident_of_std("core"), fld.cx.ident_of("iter"), fld.cx.ident_of("Iterator"), fld.cx.ident_of("next"), @@ -308,7 +309,7 @@ pub fn expand_expr(e: P, fld: &mut MacroExpander) -> P { let into_iter_expr = { let into_iter_path = { let strs = vec![ - fld.cx.ident_of("std"), + fld.cx.ident_of_std("core"), fld.cx.ident_of("iter"), fld.cx.ident_of("IntoIterator"), fld.cx.ident_of("into_iter"), @@ -1417,6 +1418,8 @@ pub fn expand_crate(parse_sess: &parse::ParseSess, user_exts: Vec, c: Crate) -> Crate { let mut cx = ExtCtxt::new(parse_sess, c.config.clone(), cfg); + cx.use_std = std_inject::use_std(&c); + let mut expander = MacroExpander::new(&mut cx); for def in imported_macros { diff --git a/src/libsyntax/ext/format.rs b/src/libsyntax/ext/format.rs index 96055e3635a60..170a455a91326 100644 --- a/src/libsyntax/ext/format.rs +++ b/src/libsyntax/ext/format.rs @@ -302,7 +302,7 @@ impl<'a, 'b> Context<'a, 'b> { } fn rtpath(ecx: &ExtCtxt, s: &str) -> Vec { - vec![ecx.ident_of("std"), ecx.ident_of("fmt"), ecx.ident_of("rt"), + vec![ecx.ident_of_std("core"), ecx.ident_of("fmt"), ecx.ident_of("rt"), ecx.ident_of("v1"), ecx.ident_of(s)] } @@ -576,7 +576,7 @@ impl<'a, 'b> Context<'a, 'b> { }; self.ecx.expr_call_global(self.fmtsp, vec!( - self.ecx.ident_of("std"), + self.ecx.ident_of_std("core"), self.ecx.ident_of("fmt"), self.ecx.ident_of("Arguments"), self.ecx.ident_of(fn_name)), fn_args) @@ -607,7 +607,7 @@ impl<'a, 'b> Context<'a, 'b> { } Unsigned => { return ecx.expr_call_global(sp, vec![ - ecx.ident_of("std"), + ecx.ident_of_std("core"), ecx.ident_of("fmt"), ecx.ident_of("ArgumentV1"), ecx.ident_of("from_uint")], vec![arg]) @@ -615,12 +615,12 @@ impl<'a, 'b> Context<'a, 'b> { }; let format_fn = ecx.path_global(sp, vec![ - ecx.ident_of("std"), + ecx.ident_of_std("core"), ecx.ident_of("fmt"), ecx.ident_of(trait_), ecx.ident_of("fmt")]); ecx.expr_call_global(sp, vec![ - ecx.ident_of("std"), + ecx.ident_of_std("core"), ecx.ident_of("fmt"), ecx.ident_of("ArgumentV1"), ecx.ident_of("new")], vec![arg, ecx.expr_path(format_fn)]) diff --git a/src/libsyntax/std_inject.rs b/src/libsyntax/std_inject.rs index d75fbcf199dbe..630b08f005629 100644 --- a/src/libsyntax/std_inject.rs +++ b/src/libsyntax/std_inject.rs @@ -37,7 +37,7 @@ pub fn maybe_inject_prelude(krate: ast::Crate) -> ast::Crate { } } -fn use_std(krate: &ast::Crate) -> bool { +pub fn use_std(krate: &ast::Crate) -> bool { !attr::contains_name(&krate.attrs[], "no_std") } diff --git a/src/libunicode/lib.rs b/src/libunicode/lib.rs index 822dde7eb2c61..60fa8f0db115c 100644 --- a/src/libunicode/lib.rs +++ b/src/libunicode/lib.rs @@ -78,7 +78,9 @@ pub mod str { pub use u_str::{utf16_items, Utf16Encoder}; } +// NOTE: remove after next snapshot // this lets us use #[derive(..)] +#[cfg(stage0)] mod std { pub use core::clone; pub use core::cmp; diff --git a/src/test/compile-fail/derive-no-std-not-supported.rs b/src/test/compile-fail/derive-no-std-not-supported.rs new file mode 100644 index 0000000000000..7dee78e2672f3 --- /dev/null +++ b/src/test/compile-fail/derive-no-std-not-supported.rs @@ -0,0 +1,37 @@ +// 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. + +#![no_std] + +extern crate core; +extern crate rand; +extern crate "serialize" as rustc_serialize; + +#[derive(Rand)] //~ ERROR this trait cannot be derived +//~^ WARNING `#[derive(Rand)]` is deprecated +struct Foo { + x: u32, +} + +#[derive(RustcEncodable)] //~ ERROR this trait cannot be derived +struct Bar { + x: u32, +} + +#[derive(RustcDecodable)] //~ ERROR this trait cannot be derived +struct Baz { + x: u32, +} + +fn main() { + Foo { x: 0 }; + Bar { x: 0 }; + Baz { x: 0 }; +} diff --git a/src/test/pretty/issue-4264.pp b/src/test/pretty/issue-4264.pp index cc8337027b092..a10e3449039d4 100644 --- a/src/test/pretty/issue-4264.pp +++ b/src/test/pretty/issue-4264.pp @@ -41,41 +41,41 @@ ((::std::fmt::format as - fn(core::fmt::Arguments<'_>) -> collections::string::String {std::fmt::format})(((::std::fmt::Arguments::new_v1 - as - fn(&[&str], &[core::fmt::ArgumentV1<'_>]) -> core::fmt::Arguments<'_> {core::fmt::Arguments<'a>::new_v1})(({ - static __STATIC_FMTSTR: - &'static [&'static str] - = - (&([("test" + fn(core::fmt::Arguments<'_>) -> collections::string::String {collections::fmt::format})(((::std::fmt::Arguments::new_v1 + as + fn(&[&str], &[core::fmt::ArgumentV1<'_>]) -> core::fmt::Arguments<'_> {core::fmt::Arguments<'a>::new_v1})(({ + static __STATIC_FMTSTR: + &'static [&'static str] + = + (&([("test" + as + &'static str)] + as + [&'static str; 1]) + as + &'static [&'static str; 1]); + (__STATIC_FMTSTR as - &'static str)] - as - [&'static str; 1]) - as - &'static [&'static str; 1]); - (__STATIC_FMTSTR - as - &'static [&'static str]) - } - as - &[&str]), - (&(match (() - as - ()) - { - () - => - ([] - as - [core::fmt::ArgumentV1<'_>; 0]), - } - as - [core::fmt::ArgumentV1<'_>; 0]) - as - &[core::fmt::ArgumentV1<'_>; 0])) - as - core::fmt::Arguments<'_>)) + &'static [&'static str]) + } + as + &[&str]), + (&(match (() + as + ()) + { + () + => + ([] + as + [core::fmt::ArgumentV1<'_>; 0]), + } + as + [core::fmt::ArgumentV1<'_>; 0]) + as + &[core::fmt::ArgumentV1<'_>; 0])) + as + core::fmt::Arguments<'_>)) as collections::string::String); } pub type Foo = [i32; (3us as usize)]; diff --git a/src/test/run-make/simd-ffi/simd.rs b/src/test/run-make/simd-ffi/simd.rs index 76079ddb8bd91..0195076fde470 100755 --- a/src/test/run-make/simd-ffi/simd.rs +++ b/src/test/run-make/simd-ffi/simd.rs @@ -74,7 +74,7 @@ trait Sized {} #[lang = "copy"] trait Copy {} -mod std { +mod core { pub mod marker { pub use Copy; } diff --git a/src/test/run-pass/derive-no-std.rs b/src/test/run-pass/derive-no-std.rs new file mode 100644 index 0000000000000..c9bbb204ab7f9 --- /dev/null +++ b/src/test/run-pass/derive-no-std.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. + +#![no_std] + +extern crate core; +extern crate rand; +extern crate "serialize" as rustc_serialize; +extern crate collections; + +// Issue #16803 + +#[derive(Clone, Hash, PartialEq, Eq, PartialOrd, Ord, + Debug, Default, Copy)] +struct Foo { + x: u32, +} + +#[derive(Clone, Hash, PartialEq, Eq, PartialOrd, Ord, + Debug, Copy)] +enum Bar { + Qux, + Quux(u32), +} + +#[derive(FromPrimitive)] +enum Baz { A=0, B=5, } + +fn main() { + Foo { x: 0 }; + Bar::Quux(3); + Baz::A; +} diff --git a/src/test/run-pass/for-loop-no-std.rs b/src/test/run-pass/for-loop-no-std.rs new file mode 100644 index 0000000000000..5911e95349f32 --- /dev/null +++ b/src/test/run-pass/for-loop-no-std.rs @@ -0,0 +1,25 @@ +// 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. + +#![no_std] +#![feature(lang_items, start)] + +extern crate "std" as other; + +#[macro_use] extern crate core; +#[macro_use] extern crate collections; + +use core::slice::SliceExt; + +#[start] +fn start(_argc: int, _argv: *const *const u8) -> int { + for _ in [1,2,3].iter() { } + 0 +} diff --git a/src/test/run-pass/format-no-std.rs b/src/test/run-pass/format-no-std.rs new file mode 100644 index 0000000000000..43f7b6f40332f --- /dev/null +++ b/src/test/run-pass/format-no-std.rs @@ -0,0 +1,36 @@ +// 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. + +#![no_std] +#![feature(lang_items, start)] + +extern crate "std" as other; + +#[macro_use] extern crate core; +#[macro_use] extern crate collections; + +use collections::string::ToString; + +#[start] +fn start(_argc: int, _argv: *const *const u8) -> int { + let s = format!("{}", 1i); + assert_eq!(s, "1".to_string()); + + let s = format!("test"); + assert_eq!(s, "test".to_string()); + + let s = format!("{test}", test=3i); + assert_eq!(s, "3".to_string()); + + let s = format!("hello {}", "world"); + assert_eq!(s, "hello world".to_string()); + + 0 +} From d788588dce5525b2bf5674b0c90c791a70582330 Mon Sep 17 00:00:00 2001 From: Keegan McAllister Date: Thu, 5 Feb 2015 16:14:42 -0800 Subject: [PATCH 3/6] Feature-gate #![no_std] Fixes #21833. [breaking-change] --- src/doc/reference.md | 6 ++++++ src/doc/trpl/unsafe.md | 8 +++++--- src/liballoc/lib.rs | 1 + src/libcollections/lib.rs | 1 + src/libcore/lib.rs | 1 + src/liblibc/lib.rs | 1 + src/librand/lib.rs | 1 + src/librustc_bitflags/lib.rs | 1 + src/librustc_driver/test.rs | 2 +- src/libstd/lib.rs | 1 + src/libsyntax/feature_gate.rs | 10 +++++++++- src/libunicode/lib.rs | 1 + src/test/auxiliary/lang-item-public.rs | 1 + src/test/auxiliary/no_std_crate.rs | 1 + src/test/auxiliary/weak-lang-items.rs | 1 + ...sociated-types-ICE-when-projecting-out-of-err.rs | 1 + src/test/compile-fail/bad-mid-path-type-params.rs | 1 + .../compile-fail/derive-no-std-not-supported.rs | 1 + src/test/compile-fail/gated-no-std.rs | 13 +++++++++++++ src/test/compile-fail/issue-19660.rs | 2 +- src/test/compile-fail/lang-item-missing.rs | 2 +- src/test/compile-fail/lint-dead-code-1.rs | 1 + src/test/compile-fail/privacy1.rs | 2 +- src/test/compile-fail/privacy2.rs | 2 +- src/test/compile-fail/privacy3.rs | 2 +- src/test/compile-fail/privacy4.rs | 2 +- ...ns-bounded-method-type-parameters-trait-bound.rs | 2 +- src/test/compile-fail/regions-struct-not-wf.rs | 1 + src/test/compile-fail/required-lang-item.rs | 2 +- src/test/compile-fail/weak-lang-item.rs | 1 + src/test/pretty/issue-4264.pp | 1 + src/test/run-make/mismatching-target-triples/bar.rs | 1 + src/test/run-make/mismatching-target-triples/foo.rs | 1 + src/test/run-make/no-duplicate-libs/bar.rs | 2 +- src/test/run-make/no-duplicate-libs/foo.rs | 2 +- .../run-make/pretty-expanded-hygiene/input.pp.rs | 1 + src/test/run-make/pretty-expanded-hygiene/input.rs | 1 + src/test/run-make/simd-ffi/simd.rs | 1 + src/test/run-make/target-specs/foo.rs | 2 +- src/test/run-pass/derive-no-std.rs | 1 + src/test/run-pass/for-loop-no-std.rs | 2 +- src/test/run-pass/format-no-std.rs | 2 +- src/test/run-pass/lang-item-public.rs | 2 +- src/test/run-pass/no-std-xcrate2.rs | 1 + src/test/run-pass/smallest-hello-world.rs | 2 +- src/test/run-pass/use.rs | 2 +- src/test/run-pass/vec-macro-no-std.rs | 2 +- 47 files changed, 76 insertions(+), 22 deletions(-) create mode 100644 src/test/compile-fail/gated-no-std.rs diff --git a/src/doc/reference.md b/src/doc/reference.md index 9851e1c28fbf0..15ae686d96539 100644 --- a/src/doc/reference.md +++ b/src/doc/reference.md @@ -2467,6 +2467,12 @@ The currently implemented features of the reference compiler are: * `associated_types` - Allows type aliases in traits. Experimental. +* `no_std` - Allows the `#![no_std]` crate attribute, which disables the implicit + `extern crate std`. This typically requires use of the unstable APIs + behind the libstd "facade", such as libcore and libcollections. It + may also cause problems when using syntax extensions, including + `#[derive]`. + If a feature is promoted to a language feature, then all existing programs will start to receive compilation warnings about #[feature] directives which enabled the new feature (because the directive is no longer necessary). However, if a diff --git a/src/doc/trpl/unsafe.md b/src/doc/trpl/unsafe.md index 3acd1eefe89d0..b364d00f95c20 100644 --- a/src/doc/trpl/unsafe.md +++ b/src/doc/trpl/unsafe.md @@ -433,6 +433,7 @@ attribute attached to the crate. ```ignore // a minimal library #![crate_type="lib"] +#![feature(no_std)] #![no_std] # // fn main() {} tricked you, rustdoc! ``` @@ -446,8 +447,8 @@ The function marked `#[start]` is passed the command line parameters in the same format as C: ``` +#![feature(lang_items, start, no_std)] #![no_std] -#![feature(lang_items, start)] // Pull in the system libc library for what crt0.o likely requires extern crate libc; @@ -473,6 +474,7 @@ correct ABI and the correct name, which requires overriding the compiler's name mangling too: ```ignore +#![feature(no_std)] #![no_std] #![no_main] #![feature(lang_items, start)] @@ -528,8 +530,8 @@ As an example, here is a program that will calculate the dot product of two vectors provided from C, using idiomatic Rust practices. ``` +#![feature(lang_items, start, no_std)] #![no_std] -#![feature(lang_items, start)] # extern crate libc; extern crate core; @@ -652,8 +654,8 @@ and one for deallocation. A freestanding program that uses the `Box` sugar for dynamic allocations via `malloc` and `free`: ``` +#![feature(lang_items, box_syntax, start, no_std)] #![no_std] -#![feature(lang_items, box_syntax, start)] extern crate libc; diff --git a/src/liballoc/lib.rs b/src/liballoc/lib.rs index b3a7e3dbdebf9..81391fd63eb85 100644 --- a/src/liballoc/lib.rs +++ b/src/liballoc/lib.rs @@ -65,6 +65,7 @@ html_favicon_url = "http://www.rust-lang.org/favicon.ico", html_root_url = "http://doc.rust-lang.org/nightly/")] +#![feature(no_std)] #![no_std] #![feature(lang_items, unsafe_destructor)] #![feature(box_syntax)] diff --git a/src/libcollections/lib.rs b/src/libcollections/lib.rs index 05d84eda13d75..f220724c42e09 100644 --- a/src/libcollections/lib.rs +++ b/src/libcollections/lib.rs @@ -33,6 +33,7 @@ #![cfg_attr(test, feature(test))] #![cfg_attr(test, allow(deprecated))] // rand +#![feature(no_std)] #![no_std] #[macro_use] diff --git a/src/libcore/lib.rs b/src/libcore/lib.rs index 4c031b3e7cc93..df4942b509b4c 100644 --- a/src/libcore/lib.rs +++ b/src/libcore/lib.rs @@ -56,6 +56,7 @@ html_root_url = "http://doc.rust-lang.org/nightly/", html_playground_url = "http://play.rust-lang.org/")] +#![feature(no_std)] #![no_std] #![allow(raw_pointer_derive)] #![deny(missing_docs)] diff --git a/src/liblibc/lib.rs b/src/liblibc/lib.rs index 060e7ef403318..38d5c5eb27ae2 100644 --- a/src/liblibc/lib.rs +++ b/src/liblibc/lib.rs @@ -16,6 +16,7 @@ #![cfg_attr(not(feature = "cargo-build"), staged_api)] #![cfg_attr(not(feature = "cargo-build"), feature(core))] #![feature(int_uint)] +#![feature(no_std)] #![no_std] #![doc(html_logo_url = "http://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png", html_favicon_url = "http://www.rust-lang.org/favicon.ico", diff --git a/src/librand/lib.rs b/src/librand/lib.rs index 777b1ed8ceb6a..4113718cfd15b 100644 --- a/src/librand/lib.rs +++ b/src/librand/lib.rs @@ -23,6 +23,7 @@ html_root_url = "http://doc.rust-lang.org/nightly/", html_playground_url = "http://play.rust-lang.org/")] #![feature(int_uint)] +#![feature(no_std)] #![no_std] #![unstable(feature = "rand")] #![feature(staged_api)] diff --git a/src/librustc_bitflags/lib.rs b/src/librustc_bitflags/lib.rs index 0139dfbd50b47..370a5d48decae 100644 --- a/src/librustc_bitflags/lib.rs +++ b/src/librustc_bitflags/lib.rs @@ -12,6 +12,7 @@ #![feature(staged_api)] #![staged_api] #![crate_type = "rlib"] +#![feature(no_std)] #![no_std] #![unstable(feature = "rustc_private")] diff --git a/src/librustc_driver/test.rs b/src/librustc_driver/test.rs index 8761b5f72ec57..9df9025846201 100644 --- a/src/librustc_driver/test.rs +++ b/src/librustc_driver/test.rs @@ -43,7 +43,7 @@ struct RH<'a> { sub: &'a [RH<'a>] } -static EMPTY_SOURCE_STR: &'static str = "#![no_std]"; +static EMPTY_SOURCE_STR: &'static str = "#![feature(no_std)] #![no_std]"; struct ExpectErrorEmitter { messages: Vec diff --git a/src/libstd/lib.rs b/src/libstd/lib.rs index e54086159002e..2a523356f62c0 100644 --- a/src/libstd/lib.rs +++ b/src/libstd/lib.rs @@ -124,6 +124,7 @@ #![cfg_attr(test, feature(test))] // Don't link to std. We are std. +#![feature(no_std)] #![no_std] #![deny(missing_docs)] diff --git a/src/libsyntax/feature_gate.rs b/src/libsyntax/feature_gate.rs index 12efd959918e1..c8ab46ff8fd33 100644 --- a/src/libsyntax/feature_gate.rs +++ b/src/libsyntax/feature_gate.rs @@ -122,7 +122,10 @@ static KNOWN_FEATURES: &'static [(&'static str, &'static str, Status)] = &[ ("staged_api", "1.0.0", Active), // Allows using items which are missing stability attributes - ("unmarked_api", "1.0.0", Active) + ("unmarked_api", "1.0.0", Active), + + // Allows using #![no_std] + ("no_std", "1.0.0", Active), ]; enum Status { @@ -466,6 +469,11 @@ impl<'a, 'v> Visitor<'v> for PostExpansionVisitor<'a> { attr.span, "language items are subject to change"); } + + if attr.check_name("no_std") { + self.gate_feature("no_std", attr.span, + "no_std is experimental"); + } } fn visit_pat(&mut self, pattern: &ast::Pat) { diff --git a/src/libunicode/lib.rs b/src/libunicode/lib.rs index 60fa8f0db115c..54c8fcd205b8f 100644 --- a/src/libunicode/lib.rs +++ b/src/libunicode/lib.rs @@ -29,6 +29,7 @@ html_favicon_url = "http://www.rust-lang.org/favicon.ico", html_root_url = "http://doc.rust-lang.org/nightly/", html_playground_url = "http://play.rust-lang.org/")] +#![feature(no_std)] #![no_std] #![feature(slicing_syntax)] #![feature(int_uint)] diff --git a/src/test/auxiliary/lang-item-public.rs b/src/test/auxiliary/lang-item-public.rs index e99a8f0b87737..834667968c85b 100644 --- a/src/test/auxiliary/lang-item-public.rs +++ b/src/test/auxiliary/lang-item-public.rs @@ -8,6 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#![feature(no_std)] #![no_std] #![feature(lang_items)] diff --git a/src/test/auxiliary/no_std_crate.rs b/src/test/auxiliary/no_std_crate.rs index 7cfae6d121da1..d830aef54f5ef 100644 --- a/src/test/auxiliary/no_std_crate.rs +++ b/src/test/auxiliary/no_std_crate.rs @@ -8,6 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#![feature(no_std)] #![no_std] pub fn foo() {} diff --git a/src/test/auxiliary/weak-lang-items.rs b/src/test/auxiliary/weak-lang-items.rs index 39462fdc1e528..fa254cb91ad53 100644 --- a/src/test/auxiliary/weak-lang-items.rs +++ b/src/test/auxiliary/weak-lang-items.rs @@ -13,6 +13,7 @@ // This aux-file will require the eh_personality function to be codegen'd, but // it hasn't been defined just yet. Make sure we don't explode. +#![feature(no_std)] #![no_std] #![crate_type = "rlib"] diff --git a/src/test/compile-fail/associated-types-ICE-when-projecting-out-of-err.rs b/src/test/compile-fail/associated-types-ICE-when-projecting-out-of-err.rs index b35d5131c781a..621f5ec9660fc 100644 --- a/src/test/compile-fail/associated-types-ICE-when-projecting-out-of-err.rs +++ b/src/test/compile-fail/associated-types-ICE-when-projecting-out-of-err.rs @@ -13,6 +13,7 @@ #![crate_type = "lib"] #![feature(lang_items)] +#![feature(no_std)] #![no_std] #[lang="sized"] diff --git a/src/test/compile-fail/bad-mid-path-type-params.rs b/src/test/compile-fail/bad-mid-path-type-params.rs index 79fe4e7165ec3..c91849ca53e1a 100644 --- a/src/test/compile-fail/bad-mid-path-type-params.rs +++ b/src/test/compile-fail/bad-mid-path-type-params.rs @@ -10,6 +10,7 @@ // ignore-tidy-linelength +#![feature(no_std)] #![no_std] #![feature(lang_items)] diff --git a/src/test/compile-fail/derive-no-std-not-supported.rs b/src/test/compile-fail/derive-no-std-not-supported.rs index 7dee78e2672f3..f82e7f3e36a8a 100644 --- a/src/test/compile-fail/derive-no-std-not-supported.rs +++ b/src/test/compile-fail/derive-no-std-not-supported.rs @@ -8,6 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#![feature(no_std)] #![no_std] extern crate core; diff --git a/src/test/compile-fail/gated-no-std.rs b/src/test/compile-fail/gated-no-std.rs new file mode 100644 index 0000000000000..893ba8a8a86e8 --- /dev/null +++ b/src/test/compile-fail/gated-no-std.rs @@ -0,0 +1,13 @@ +// Copyright 2105 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. + +#![no_std] //~ ERROR no_std is experimental + +fn main() {} diff --git a/src/test/compile-fail/issue-19660.rs b/src/test/compile-fail/issue-19660.rs index f83037d47bbb1..14601e67a77c1 100644 --- a/src/test/compile-fail/issue-19660.rs +++ b/src/test/compile-fail/issue-19660.rs @@ -10,7 +10,7 @@ // error-pattern: requires `copy` lang_item -#![feature(lang_items, start)] +#![feature(lang_items, start, no_std)] #![no_std] #[lang = "sized"] diff --git a/src/test/compile-fail/lang-item-missing.rs b/src/test/compile-fail/lang-item-missing.rs index 61d55fd0964e3..c7426fc6fc1b0 100644 --- a/src/test/compile-fail/lang-item-missing.rs +++ b/src/test/compile-fail/lang-item-missing.rs @@ -13,8 +13,8 @@ // error-pattern: requires `sized` lang_item +#![feature(start, no_std)] #![no_std] -#![feature(start)] #[start] fn start(argc: isize, argv: *const *const u8) -> isize { diff --git a/src/test/compile-fail/lint-dead-code-1.rs b/src/test/compile-fail/lint-dead-code-1.rs index b1bb28f7ce716..e91e6efd1cbf0 100644 --- a/src/test/compile-fail/lint-dead-code-1.rs +++ b/src/test/compile-fail/lint-dead-code-1.rs @@ -8,6 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#![feature(no_std)] #![no_std] #![allow(unused_variables)] #![allow(non_camel_case_types)] diff --git a/src/test/compile-fail/privacy1.rs b/src/test/compile-fail/privacy1.rs index b2ee62ddabe55..7ebbcc2809a58 100644 --- a/src/test/compile-fail/privacy1.rs +++ b/src/test/compile-fail/privacy1.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(lang_items, start)] +#![feature(lang_items, start, no_std)] #![no_std] // makes debugging this test *a lot* easier (during resolve) #[lang="sized"] diff --git a/src/test/compile-fail/privacy2.rs b/src/test/compile-fail/privacy2.rs index b3d7321edabd5..7b4a2a3595bf7 100644 --- a/src/test/compile-fail/privacy2.rs +++ b/src/test/compile-fail/privacy2.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(start)] +#![feature(start, no_std)] #![no_std] // makes debugging this test *a lot* easier (during resolve) // Test to make sure that globs don't leak in regular `use` statements. diff --git a/src/test/compile-fail/privacy3.rs b/src/test/compile-fail/privacy3.rs index 245a9c21a6b2e..8c9de1fa25ce7 100644 --- a/src/test/compile-fail/privacy3.rs +++ b/src/test/compile-fail/privacy3.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(start)] +#![feature(start, no_std)] #![no_std] // makes debugging this test *a lot* easier (during resolve) // Test to make sure that private items imported through globs remain private diff --git a/src/test/compile-fail/privacy4.rs b/src/test/compile-fail/privacy4.rs index e35089b8606c2..bcb46663aa849 100644 --- a/src/test/compile-fail/privacy4.rs +++ b/src/test/compile-fail/privacy4.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(lang_items, start)] +#![feature(lang_items, start, no_std)] #![no_std] // makes debugging this test *a lot* easier (during resolve) #[lang = "sized"] pub trait Sized {} diff --git a/src/test/compile-fail/regions-bounded-method-type-parameters-trait-bound.rs b/src/test/compile-fail/regions-bounded-method-type-parameters-trait-bound.rs index acc721f26b394..74c2c6e584b43 100644 --- a/src/test/compile-fail/regions-bounded-method-type-parameters-trait-bound.rs +++ b/src/test/compile-fail/regions-bounded-method-type-parameters-trait-bound.rs @@ -8,8 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#![feature(lang_items, no_std)] #![no_std] -#![feature(lang_items)] // Check that explicit region bounds are allowed on the various // nominal types (but not on other types) and that they are type diff --git a/src/test/compile-fail/regions-struct-not-wf.rs b/src/test/compile-fail/regions-struct-not-wf.rs index 3de137a9efbd7..3b8312a30190c 100644 --- a/src/test/compile-fail/regions-struct-not-wf.rs +++ b/src/test/compile-fail/regions-struct-not-wf.rs @@ -10,6 +10,7 @@ // Various examples of structs whose fields are not well-formed. +#![feature(no_std)] #![no_std] #![allow(dead_code)] diff --git a/src/test/compile-fail/required-lang-item.rs b/src/test/compile-fail/required-lang-item.rs index ae561878e9ba0..7d252604883d6 100644 --- a/src/test/compile-fail/required-lang-item.rs +++ b/src/test/compile-fail/required-lang-item.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(lang_items)] +#![feature(lang_items, no_std)] #![no_std] #[lang="sized"] pub trait Sized {} diff --git a/src/test/compile-fail/weak-lang-item.rs b/src/test/compile-fail/weak-lang-item.rs index baac192cbf022..42df43934a89c 100644 --- a/src/test/compile-fail/weak-lang-item.rs +++ b/src/test/compile-fail/weak-lang-item.rs @@ -13,6 +13,7 @@ // error-pattern: language item required, but not found: `stack_exhausted` // error-pattern: language item required, but not found: `eh_personality` +#![feature(no_std)] #![no_std] extern crate core; diff --git a/src/test/pretty/issue-4264.pp b/src/test/pretty/issue-4264.pp index a10e3449039d4..60660d482742d 100644 --- a/src/test/pretty/issue-4264.pp +++ b/src/test/pretty/issue-4264.pp @@ -1,3 +1,4 @@ +#![feature(no_std)] #![no_std] #[prelude_import] use std::prelude::v1::*; diff --git a/src/test/run-make/mismatching-target-triples/bar.rs b/src/test/run-make/mismatching-target-triples/bar.rs index ed15e5d880a9b..8695ab58e5fe5 100755 --- a/src/test/run-make/mismatching-target-triples/bar.rs +++ b/src/test/run-make/mismatching-target-triples/bar.rs @@ -7,5 +7,6 @@ // , at your // option. This file may not be copied, modified, or distributed // except according to those terms. +#![feature(no_std)] #![no_std] extern crate foo; diff --git a/src/test/run-make/mismatching-target-triples/foo.rs b/src/test/run-make/mismatching-target-triples/foo.rs index 8afa43710dd93..afd4f298a97dd 100755 --- a/src/test/run-make/mismatching-target-triples/foo.rs +++ b/src/test/run-make/mismatching-target-triples/foo.rs @@ -7,5 +7,6 @@ // , at your // option. This file may not be copied, modified, or distributed // except according to those terms. +#![feature(no_std)] #![no_std] #![crate_type = "lib"] diff --git a/src/test/run-make/no-duplicate-libs/bar.rs b/src/test/run-make/no-duplicate-libs/bar.rs index 1183475610584..0bec6148189a9 100644 --- a/src/test/run-make/no-duplicate-libs/bar.rs +++ b/src/test/run-make/no-duplicate-libs/bar.rs @@ -8,8 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#![feature(lang_items, no_std)] #![no_std] -#![feature(lang_items)] #![crate_type = "dylib"] extern crate libc; diff --git a/src/test/run-make/no-duplicate-libs/foo.rs b/src/test/run-make/no-duplicate-libs/foo.rs index 61a2a51da0864..9e8afdc5696ed 100644 --- a/src/test/run-make/no-duplicate-libs/foo.rs +++ b/src/test/run-make/no-duplicate-libs/foo.rs @@ -8,8 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#![feature(lang_items, no_std)] #![no_std] -#![feature(lang_items)] #![crate_type = "dylib"] extern crate libc; diff --git a/src/test/run-make/pretty-expanded-hygiene/input.pp.rs b/src/test/run-make/pretty-expanded-hygiene/input.pp.rs index 6febe2ff7c1d3..6aff4c9b3d5a3 100755 --- a/src/test/run-make/pretty-expanded-hygiene/input.pp.rs +++ b/src/test/run-make/pretty-expanded-hygiene/input.pp.rs @@ -9,6 +9,7 @@ // except according to those terms. // minimal junk +#![feature(no_std)] #![no_std] diff --git a/src/test/run-make/pretty-expanded-hygiene/input.rs b/src/test/run-make/pretty-expanded-hygiene/input.rs index c31b67b8043ae..a46fa12ac0520 100755 --- a/src/test/run-make/pretty-expanded-hygiene/input.rs +++ b/src/test/run-make/pretty-expanded-hygiene/input.rs @@ -9,6 +9,7 @@ // except according to those terms. // minimal junk +#![feature(no_std)] #![no_std] macro_rules! foo { diff --git a/src/test/run-make/simd-ffi/simd.rs b/src/test/run-make/simd-ffi/simd.rs index 0195076fde470..834a2adf01fd3 100755 --- a/src/test/run-make/simd-ffi/simd.rs +++ b/src/test/run-make/simd-ffi/simd.rs @@ -12,6 +12,7 @@ #![crate_type = "lib"] // we can compile to a variety of platforms, because we don't need // cross-compiled standard libraries. +#![feature(no_std)] #![no_std] #![feature(simd, simd_ffi, link_llvm_intrinsics, lang_items)] diff --git a/src/test/run-make/target-specs/foo.rs b/src/test/run-make/target-specs/foo.rs index fd112034f40c5..365fc039a4ec3 100644 --- a/src/test/run-make/target-specs/foo.rs +++ b/src/test/run-make/target-specs/foo.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(lang_items)] +#![feature(lang_items, no_std)] #![no_std] #[lang="copy"] diff --git a/src/test/run-pass/derive-no-std.rs b/src/test/run-pass/derive-no-std.rs index c9bbb204ab7f9..d3034c2d48529 100644 --- a/src/test/run-pass/derive-no-std.rs +++ b/src/test/run-pass/derive-no-std.rs @@ -8,6 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#![feature(no_std)] #![no_std] extern crate core; diff --git a/src/test/run-pass/for-loop-no-std.rs b/src/test/run-pass/for-loop-no-std.rs index 5911e95349f32..30c2aec33ad1b 100644 --- a/src/test/run-pass/for-loop-no-std.rs +++ b/src/test/run-pass/for-loop-no-std.rs @@ -8,8 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#![feature(lang_items, start, no_std)] #![no_std] -#![feature(lang_items, start)] extern crate "std" as other; diff --git a/src/test/run-pass/format-no-std.rs b/src/test/run-pass/format-no-std.rs index 43f7b6f40332f..44d80490e693b 100644 --- a/src/test/run-pass/format-no-std.rs +++ b/src/test/run-pass/format-no-std.rs @@ -8,8 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#![feature(lang_items, start, no_std)] #![no_std] -#![feature(lang_items, start)] extern crate "std" as other; diff --git a/src/test/run-pass/lang-item-public.rs b/src/test/run-pass/lang-item-public.rs index 2d70fa0c81989..350ec68a7d149 100644 --- a/src/test/run-pass/lang-item-public.rs +++ b/src/test/run-pass/lang-item-public.rs @@ -12,8 +12,8 @@ // ignore-android // ignore-windows #13361 +#![feature(lang_items, start, no_std)] #![no_std] -#![feature(lang_items, start)] extern crate "lang-item-public" as lang_lib; diff --git a/src/test/run-pass/no-std-xcrate2.rs b/src/test/run-pass/no-std-xcrate2.rs index dcafb5f451f3d..f5f34607aff7b 100644 --- a/src/test/run-pass/no-std-xcrate2.rs +++ b/src/test/run-pass/no-std-xcrate2.rs @@ -16,6 +16,7 @@ // This tests that libraries built with #[no_std] can be linked to crates with // #[no_std] and actually run. +#![feature(no_std)] #![no_std] extern crate no_std_crate; diff --git a/src/test/run-pass/smallest-hello-world.rs b/src/test/run-pass/smallest-hello-world.rs index 4913b34c4b311..197890c127712 100644 --- a/src/test/run-pass/smallest-hello-world.rs +++ b/src/test/run-pass/smallest-hello-world.rs @@ -12,8 +12,8 @@ // Smallest "hello world" with a libc runtime +#![feature(intrinsics, lang_items, start, no_std)] #![no_std] -#![feature(intrinsics, lang_items, start)] extern crate libc; diff --git a/src/test/run-pass/use.rs b/src/test/run-pass/use.rs index a2e1d8a567167..65a392e63c510 100644 --- a/src/test/run-pass/use.rs +++ b/src/test/run-pass/use.rs @@ -10,7 +10,7 @@ // except according to those terms. #![allow(unused_imports)] -#![feature(start)] +#![feature(start, no_std)] #![no_std] extern crate std; diff --git a/src/test/run-pass/vec-macro-no-std.rs b/src/test/run-pass/vec-macro-no-std.rs index c6c3701734970..47b87fce2abaf 100644 --- a/src/test/run-pass/vec-macro-no-std.rs +++ b/src/test/run-pass/vec-macro-no-std.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(lang_items, start)] +#![feature(lang_items, start, no_std)] #![no_std] extern crate "std" as other; From a246b6542a6660f725441dd016bddd470c761e4c Mon Sep 17 00:00:00 2001 From: Keegan McAllister Date: Thu, 5 Feb 2015 17:04:11 -0800 Subject: [PATCH 4/6] Fake up #![no_std] on pretty-printing; keep it out of AST --- src/libsyntax/print/pprust.rs | 23 ++++++++++++++++++++++- src/libsyntax/std_inject.rs | 13 ------------- 2 files changed, 22 insertions(+), 14 deletions(-) diff --git a/src/libsyntax/print/pprust.rs b/src/libsyntax/print/pprust.rs index c177cd1fafa55..0da15859ea2df 100644 --- a/src/libsyntax/print/pprust.rs +++ b/src/libsyntax/print/pprust.rs @@ -15,17 +15,19 @@ use ast; use ast::{MethodImplItem, RegionTyParamBound, TraitTyParamBound, TraitBoundModifier}; use ast::{RequiredMethod, ProvidedMethod, TypeImplItem, TypeTraitItem}; use ast_util; +use attr; use owned_slice::OwnedSlice; use attr::{AttrMetaMethods, AttributeMethods}; use codemap::{self, CodeMap, BytePos}; use diagnostic; -use parse::token::{self, BinOpToken, Token}; +use parse::token::{self, BinOpToken, Token, InternedString}; use parse::lexer::comments; use parse; use print::pp::{self, break_offset, word, space, zerobreak, hardbreak}; use print::pp::{Breaks, eof}; use print::pp::Breaks::{Consistent, Inconsistent}; use ptr::P; +use std_inject; use std::{ascii, mem}; use std::old_io::{self, IoResult}; @@ -113,6 +115,25 @@ pub fn print_crate<'a>(cm: &'a CodeMap, out, ann, is_expanded); + if is_expanded && std_inject::use_std(krate) { + // We need to print `#![no_std]` (and its feature gate) so that + // compiling pretty-printed source won't inject libstd again. + // However we don't want these attributes in the AST because + // of the feature gate, so we fake them up here. + + let no_std_meta = attr::mk_word_item(InternedString::new("no_std")); + + // #![feature(no_std)] + let fake_attr = attr::mk_attr_inner(attr::mk_attr_id(), + attr::mk_list_item(InternedString::new("feature"), + vec![no_std_meta.clone()])); + try!(s.print_attribute(&fake_attr)); + + // #![no_std] + let fake_attr = attr::mk_attr_inner(attr::mk_attr_id(), no_std_meta); + try!(s.print_attribute(&fake_attr)); + } + try!(s.print_mod(&krate.module, &krate.attrs[])); try!(s.print_remaining_comments()); eof(&mut s.s) diff --git a/src/libsyntax/std_inject.rs b/src/libsyntax/std_inject.rs index 630b08f005629..98c193c7e6b85 100644 --- a/src/libsyntax/std_inject.rs +++ b/src/libsyntax/std_inject.rs @@ -69,9 +69,6 @@ impl<'a> fold::Folder for StandardLibraryInjector<'a> { span: DUMMY_SP })); - // don't add #![no_std] here, that will block the prelude injection later. - // Add it during the prelude injection instead. - krate } } @@ -87,16 +84,6 @@ struct PreludeInjector<'a>; impl<'a> fold::Folder for PreludeInjector<'a> { fn fold_crate(&mut self, mut krate: ast::Crate) -> ast::Crate { - // Add #![no_std] here, so we don't re-inject when compiling pretty-printed source. - // This must happen here and not in StandardLibraryInjector because this - // fold happens second. - - let no_std_attr = attr::mk_attr_inner(attr::mk_attr_id(), - attr::mk_word_item(InternedString::new("no_std"))); - // std_inject runs after feature checking so manually mark this attr - attr::mark_used(&no_std_attr); - krate.attrs.push(no_std_attr); - // only add `use std::prelude::*;` if there wasn't a // `#![no_implicit_prelude]` at the crate level. // fold_mod() will insert glob path. From ea85d43903ead3317bf6153fea9f77a5c4a904f1 Mon Sep 17 00:00:00 2001 From: Keegan McAllister Date: Thu, 5 Feb 2015 21:08:02 -0800 Subject: [PATCH 5/6] Make std::fmt a simple re-export from collections --- src/libcollections/fmt.rs | 410 ++++++++++++++++++++++++++++++++++++- src/libstd/fmt.rs | 414 -------------------------------------- src/libstd/lib.rs | 2 +- 3 files changed, 402 insertions(+), 424 deletions(-) delete mode 100644 src/libstd/fmt.rs diff --git a/src/libcollections/fmt.rs b/src/libcollections/fmt.rs index b3f31f33a3a9e..5f337528d7807 100644 --- a/src/libcollections/fmt.rs +++ b/src/libcollections/fmt.rs @@ -1,4 +1,4 @@ -// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// 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. // @@ -7,15 +7,409 @@ // , at your // option. This file may not be copied, modified, or distributed // except according to those terms. +// +// ignore-lexer-test FIXME #15679 -//! Formatting support for `String`. +//! Utilities for formatting and printing strings +//! +//! This module contains the runtime support for the `format!` syntax extension. +//! This macro is implemented in the compiler to emit calls to this module in +//! order to format arguments at runtime into strings and streams. +//! +//! ## Usage +//! +//! The `format!` macro is intended to be familiar to those coming from C's +//! printf/fprintf functions or Python's `str.format` function. In its current +//! revision, the `format!` macro returns a `String` type which is the result of +//! the formatting. In the future it will also be able to pass in a stream to +//! format arguments directly while performing minimal allocations. +//! +//! Some examples of the `format!` extension are: +//! +//! ``` +//! format!("Hello"); // => "Hello" +//! format!("Hello, {}!", "world"); // => "Hello, world!" +//! format!("The number is {}", 1); // => "The number is 1" +//! format!("{:?}", (3, 4)); // => "(3, 4)" +//! format!("{value}", value=4); // => "4" +//! format!("{} {}", 1, 2u); // => "1 2" +//! ``` +//! +//! From these, you can see that the first argument is a format string. It is +//! required by the compiler for this to be a string literal; it cannot be a +//! variable passed in (in order to perform validity checking). The compiler +//! will then parse the format string and determine if the list of arguments +//! provided is suitable to pass to this format string. +//! +//! ### Positional parameters +//! +//! Each formatting argument is allowed to specify which value argument it's +//! referencing, and if omitted it is assumed to be "the next argument". For +//! example, the format string `{} {} {}` would take three parameters, and they +//! would be formatted in the same order as they're given. The format string +//! `{2} {1} {0}`, however, would format arguments in reverse order. +//! +//! Things can get a little tricky once you start intermingling the two types of +//! positional specifiers. The "next argument" specifier can be thought of as an +//! iterator over the argument. Each time a "next argument" specifier is seen, +//! the iterator advances. This leads to behavior like this: +//! +//! ```rust +//! format!("{1} {} {0} {}", 1, 2); // => "2 1 1 2" +//! ``` +//! +//! The internal iterator over the argument has not been advanced by the time +//! the first `{}` is seen, so it prints the first argument. Then upon reaching +//! the second `{}`, the iterator has advanced forward to the second argument. +//! Essentially, parameters which explicitly name their argument do not affect +//! parameters which do not name an argument in terms of positional specifiers. +//! +//! A format string is required to use all of its arguments, otherwise it is a +//! compile-time error. You may refer to the same argument more than once in the +//! format string, although it must always be referred to with the same type. +//! +//! ### Named parameters +//! +//! Rust itself does not have a Python-like equivalent of named parameters to a +//! function, but the `format!` macro is a syntax extension which allows it to +//! leverage named parameters. Named parameters are listed at the end of the +//! argument list and have the syntax: +//! +//! ```text +//! identifier '=' expression +//! ``` +//! +//! For example, the following `format!` expressions all use named argument: +//! +//! ``` +//! format!("{argument}", argument = "test"); // => "test" +//! format!("{name} {}", 1, name = 2); // => "2 1" +//! format!("{a} {c} {b}", a="a", b='b', c=3); // => "a 3 b" +//! ``` +//! +//! It is illegal to put positional parameters (those without names) after +//! arguments which have names. Like with positional parameters, it is illegal +//! to provide named parameters that are unused by the format string. +//! +//! ### Argument types +//! +//! Each argument's type is dictated by the format string. It is a requirement +//! that every argument is only ever referred to by one type. For example, this +//! is an invalid format string: +//! +//! ```text +//! {0:x} {0:o} +//! ``` +//! +//! This is invalid because the first argument is both referred to as a +//! hexadecimal as well as an +//! octal. +//! +//! There are various parameters which do require a particular type, however. +//! Namely if the syntax `{:.*}` is used, then the number of characters to print +//! precedes the actual object being formatted, and the number of characters +//! must have the type `uint`. Although a `uint` can be printed with `{}`, it is +//! illegal to reference an argument as such. For example this is another +//! invalid format string: +//! +//! ```text +//! {:.*} {0} +//! ``` +//! +//! ### Formatting traits +//! +//! When requesting that an argument be formatted with a particular type, you +//! are actually requesting that an argument ascribes to a particular trait. +//! This allows multiple actual types to be formatted via `{:x}` (like `i8` as +//! well as `int`). The current mapping of types to traits is: +//! +//! * *nothing* ⇒ `Display` +//! * `?` ⇒ `Debug` +//! * `o` ⇒ `Octal` +//! * `x` ⇒ `LowerHex` +//! * `X` ⇒ `UpperHex` +//! * `p` ⇒ `Pointer` +//! * `b` ⇒ `Binary` +//! * `e` ⇒ `LowerExp` +//! * `E` ⇒ `UpperExp` +//! +//! What this means is that any type of argument which implements the +//! `fmt::Binary` trait can then be formatted with `{:b}`. Implementations +//! are provided for these traits for a number of primitive types by the +//! standard library as well. If no format is specified (as in `{}` or `{:6}`), +//! then the format trait used is the `Display` trait. +//! +//! When implementing a format trait for your own type, you will have to +//! implement a method of the signature: +//! +//! ```rust +//! # use std::fmt; +//! # struct Foo; // our custom type +//! # impl fmt::Display for Foo { +//! fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { +//! # write!(f, "testing, testing") +//! # } } +//! ``` +//! +//! Your type will be passed as `self` by-reference, and then the function +//! should emit output into the `f.buf` stream. It is up to each format trait +//! implementation to correctly adhere to the requested formatting parameters. +//! The values of these parameters will be listed in the fields of the +//! `Formatter` struct. In order to help with this, the `Formatter` struct also +//! provides some helper methods. +//! +//! Additionally, the return value of this function is `fmt::Result` which is a +//! typedef to `Result<(), IoError>` (also known as `IoResult<()>`). Formatting +//! implementations should ensure that they return errors from `write!` +//! correctly (propagating errors upward). +//! +//! An example of implementing the formatting traits would look +//! like: +//! +//! ```rust +//! use std::fmt; +//! use std::f64; +//! use std::num::Float; +//! +//! #[derive(Debug)] +//! struct Vector2D { +//! x: int, +//! y: int, +//! } +//! +//! impl fmt::Display for Vector2D { +//! fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { +//! // The `f` value implements the `Writer` trait, which is what the +//! // write! macro is expecting. Note that this formatting ignores the +//! // various flags provided to format strings. +//! write!(f, "({}, {})", self.x, self.y) +//! } +//! } +//! +//! // Different traits allow different forms of output of a type. The meaning +//! // of this format is to print the magnitude of a vector. +//! impl fmt::Binary for Vector2D { +//! fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { +//! let magnitude = (self.x * self.x + self.y * self.y) as f64; +//! 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. +//! let decimals = f.precision().unwrap_or(3); +//! let string = f64::to_str_exact(magnitude, decimals); +//! f.pad_integral(true, "", string.as_slice()) +//! } +//! } +//! +//! fn main() { +//! let myvector = Vector2D { x: 3, y: 4 }; +//! +//! println!("{}", myvector); // => "(3, 4)" +//! println!("{:?}", myvector); // => "Vector2D {x: 3, y:4}" +//! println!("{:10.3b}", myvector); // => " 5.000" +//! } +//! ``` +//! +//! #### fmt::Display vs fmt::Debug +//! +//! These two formatting traits have distinct purposes: +//! +//! - `fmt::Display` implementations assert that the type can be faithfully +//! represented as a UTF-8 string at all times. It is **not** expected that +//! all types implement the `Display` trait. +//! - `fmt::Debug` implementations should be implemented for **all** public types. +//! Output will typically represent the internal state as faithfully as possible. +//! The purpose of the `Debug` trait is to facilitate debugging Rust code. In +//! most cases, using `#[derive(Debug)]` is sufficient and recommended. +//! +//! Some examples of the output from both traits: +//! +//! ``` +//! assert_eq!(format!("{} {:?}", 3i32, 4i32), "3 4"); +//! assert_eq!(format!("{} {:?}", 'a', 'b'), "a 'b'"); +//! assert_eq!(format!("{} {:?}", "foo\n", "bar\n"), "foo\n \"bar\\n\""); +//! ``` +//! +//! ### Related macros +//! +//! There are a number of related macros in the `format!` family. The ones that +//! are currently implemented are: +//! +//! ```ignore +//! format! // described above +//! write! // first argument is a &mut old_io::Writer, the destination +//! writeln! // same as write but appends a newline +//! print! // the format string is printed to the standard output +//! println! // same as print but appends a newline +//! format_args! // described below. +//! ``` +//! +//! #### `write!` +//! +//! This and `writeln` are two macros which are used to emit the format string +//! to a specified stream. This is used to prevent intermediate allocations of +//! format strings and instead directly write the output. Under the hood, this +//! function is actually invoking the `write` function defined in this module. +//! Example usage is: +//! +//! ```rust +//! # #![allow(unused_must_use)] +//! let mut w = Vec::new(); +//! write!(&mut w, "Hello {}!", "world"); +//! ``` +//! +//! #### `print!` +//! +//! This and `println` emit their output to stdout. Similarly to the `write!` +//! macro, the goal of these macros is to avoid intermediate allocations when +//! printing output. Example usage is: +//! +//! ```rust +//! print!("Hello {}!", "world"); +//! println!("I have a newline {}", "character at the end"); +//! ``` +//! +//! #### `format_args!` +//! This is a curious macro which is used to safely pass around +//! an opaque object describing the format string. This object +//! does not require any heap allocations to create, and it only +//! references information on the stack. Under the hood, all of +//! the related macros are implemented in terms of this. First +//! off, some example usage is: +//! +//! ``` +//! use std::fmt; +//! use std::old_io; +//! +//! fmt::format(format_args!("this returns {}", "String")); +//! +//! let mut some_writer = old_io::stdout(); +//! write!(&mut some_writer, "{}", format_args!("print with a {}", "macro")); +//! +//! fn my_fmt_fn(args: fmt::Arguments) { +//! write!(&mut old_io::stdout(), "{}", args); +//! } +//! my_fmt_fn(format_args!("or a {} too", "function")); +//! ``` +//! +//! The result of the `format_args!` macro is a value of type `fmt::Arguments`. +//! This structure can then be passed to the `write` and `format` functions +//! inside this module in order to process the format string. +//! The goal of this macro is to even further prevent intermediate allocations +//! when dealing formatting strings. +//! +//! For example, a logging library could use the standard formatting syntax, but +//! it would internally pass around this structure until it has been determined +//! where output should go to. +//! +//! ## Syntax +//! +//! The syntax for the formatting language used is drawn from other languages, +//! so it should not be too alien. Arguments are formatted with python-like +//! syntax, meaning that arguments are surrounded by `{}` instead of the C-like +//! `%`. The actual grammar for the formatting syntax is: +//! +//! ```text +//! format_string := [ format ] * +//! format := '{' [ argument ] [ ':' format_spec ] '}' +//! argument := integer | identifier +//! +//! format_spec := [[fill]align][sign]['#'][0][width]['.' precision][type] +//! fill := character +//! align := '<' | '^' | '>' +//! sign := '+' | '-' +//! width := count +//! precision := count | '*' +//! type := identifier | '' +//! count := parameter | integer +//! parameter := integer '$' +//! ``` +//! +//! ## Formatting Parameters +//! +//! Each argument being formatted can be transformed by a number of formatting +//! parameters (corresponding to `format_spec` in the syntax above). These +//! parameters affect the string representation of what's being formatted. This +//! syntax draws heavily from Python's, so it may seem a bit familiar. +//! +//! ### Fill/Alignment +//! +//! The fill character is provided normally in conjunction with the `width` +//! parameter. This indicates that if the value being formatted is smaller than +//! `width` some extra characters will be printed around it. The extra +//! characters are specified by `fill`, and the alignment can be one of two +//! options: +//! +//! * `<` - the argument is left-aligned in `width` columns +//! * `^` - the argument is center-aligned in `width` columns +//! * `>` - the argument is right-aligned in `width` columns +//! +//! ### Sign/#/0 +//! +//! These can all be interpreted as flags for a particular formatter. +//! +//! * '+' - This is intended for numeric types and indicates that the sign +//! should always be printed. Positive signs are never printed by +//! default, and the negative sign is only printed by default for the +//! `Signed` trait. This flag indicates that the correct sign (+ or -) +//! should always be printed. +//! * '-' - Currently not used +//! * '#' - This flag is indicates that the "alternate" form of printing should +//! be used. By default, this only applies to the integer formatting +//! traits and performs like: +//! * `x` - precedes the argument with a "0x" +//! * `X` - precedes the argument with a "0x" +//! * `t` - precedes the argument with a "0b" +//! * `o` - precedes the argument with a "0o" +//! * '0' - This is used to indicate for integer formats that the padding should +//! both be done with a `0` character as well as be sign-aware. A format +//! like `{:08d}` would yield `00000001` for the integer `1`, while the +//! same format would yield `-0000001` for the integer `-1`. Notice that +//! the negative version has one fewer zero than the positive version. +//! +//! ### Width +//! +//! This is a parameter for the "minimum width" that the format should take up. +//! If the value's string does not fill up this many characters, then the +//! padding specified by fill/alignment will be used to take up the required +//! space. +//! +//! The default fill/alignment for non-numerics is a space and left-aligned. The +//! defaults for numeric formatters is also a space but with right-alignment. If +//! the '0' flag is specified for numerics, then the implicit fill character is +//! '0'. +//! +//! The value for the width can also be provided as a `uint` in the list of +//! parameters by using the `2$` syntax indicating that the second argument is a +//! `uint` specifying the width. +//! +//! ### Precision +//! +//! For non-numeric types, this can be considered a "maximum width". If the +//! resulting string is longer than this width, then it is truncated down to +//! this many characters and only those are emitted. +//! +//! For integral types, this has no meaning currently. +//! +//! For floating-point types, this indicates how many digits after the decimal +//! point should be printed. +//! +//! ## Escaping //! -//! See `core::fmt` and `std::fmt` for full documentation on string -//! formatting. +//! The literal characters `{` and `}` may be included in a string by preceding +//! them with the same character. For example, the `{` character is escaped with +//! `{{` and the `}` character is escaped with `}}`. -#![stable(feature = "rust1", since = "1.0.0")] +#![unstable(feature = "std_misc")] -use core::fmt; +pub use core::fmt::{Formatter, Result, Writer, rt}; +pub use core::fmt::{Show, String, Octal, Binary}; +pub use core::fmt::{Display, Debug}; +pub use core::fmt::{LowerHex, UpperHex, Pointer}; +pub use core::fmt::{LowerExp, UpperExp}; +pub use core::fmt::Error; +pub use core::fmt::{ArgumentV1, Arguments, write, radix, Radix, RadixFmt}; use string; @@ -35,9 +429,7 @@ use string; /// assert_eq!(s, "Hello, world!".to_string()); /// ``` #[stable(feature = "rust1", since = "1.0.0")] -pub fn format(args: fmt::Arguments) -> string::String { - // FIXME #21826 - use core::fmt::Writer; +pub fn format(args: Arguments) -> string::String { let mut output = string::String::new(); let _ = write!(&mut output, "{}", args); output diff --git a/src/libstd/fmt.rs b/src/libstd/fmt.rs deleted file mode 100644 index 82823f0cb28dc..0000000000000 --- a/src/libstd/fmt.rs +++ /dev/null @@ -1,414 +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 - -//! Utilities for formatting and printing strings -//! -//! This module contains the runtime support for the `format!` syntax extension. -//! This macro is implemented in the compiler to emit calls to this module in -//! order to format arguments at runtime into strings and streams. -//! -//! ## Usage -//! -//! The `format!` macro is intended to be familiar to those coming from C's -//! printf/fprintf functions or Python's `str.format` function. In its current -//! revision, the `format!` macro returns a `String` type which is the result of -//! the formatting. In the future it will also be able to pass in a stream to -//! format arguments directly while performing minimal allocations. -//! -//! Some examples of the `format!` extension are: -//! -//! ``` -//! format!("Hello"); // => "Hello" -//! format!("Hello, {}!", "world"); // => "Hello, world!" -//! format!("The number is {}", 1); // => "The number is 1" -//! format!("{:?}", (3, 4)); // => "(3, 4)" -//! format!("{value}", value=4); // => "4" -//! format!("{} {}", 1, 2u); // => "1 2" -//! ``` -//! -//! From these, you can see that the first argument is a format string. It is -//! required by the compiler for this to be a string literal; it cannot be a -//! variable passed in (in order to perform validity checking). The compiler -//! will then parse the format string and determine if the list of arguments -//! provided is suitable to pass to this format string. -//! -//! ### Positional parameters -//! -//! Each formatting argument is allowed to specify which value argument it's -//! referencing, and if omitted it is assumed to be "the next argument". For -//! example, the format string `{} {} {}` would take three parameters, and they -//! would be formatted in the same order as they're given. The format string -//! `{2} {1} {0}`, however, would format arguments in reverse order. -//! -//! Things can get a little tricky once you start intermingling the two types of -//! positional specifiers. The "next argument" specifier can be thought of as an -//! iterator over the argument. Each time a "next argument" specifier is seen, -//! the iterator advances. This leads to behavior like this: -//! -//! ```rust -//! format!("{1} {} {0} {}", 1, 2); // => "2 1 1 2" -//! ``` -//! -//! The internal iterator over the argument has not been advanced by the time -//! the first `{}` is seen, so it prints the first argument. Then upon reaching -//! the second `{}`, the iterator has advanced forward to the second argument. -//! Essentially, parameters which explicitly name their argument do not affect -//! parameters which do not name an argument in terms of positional specifiers. -//! -//! A format string is required to use all of its arguments, otherwise it is a -//! compile-time error. You may refer to the same argument more than once in the -//! format string, although it must always be referred to with the same type. -//! -//! ### Named parameters -//! -//! Rust itself does not have a Python-like equivalent of named parameters to a -//! function, but the `format!` macro is a syntax extension which allows it to -//! leverage named parameters. Named parameters are listed at the end of the -//! argument list and have the syntax: -//! -//! ```text -//! identifier '=' expression -//! ``` -//! -//! For example, the following `format!` expressions all use named argument: -//! -//! ``` -//! format!("{argument}", argument = "test"); // => "test" -//! format!("{name} {}", 1, name = 2); // => "2 1" -//! format!("{a} {c} {b}", a="a", b='b', c=3); // => "a 3 b" -//! ``` -//! -//! It is illegal to put positional parameters (those without names) after -//! arguments which have names. Like with positional parameters, it is illegal -//! to provide named parameters that are unused by the format string. -//! -//! ### Argument types -//! -//! Each argument's type is dictated by the format string. It is a requirement -//! that every argument is only ever referred to by one type. For example, this -//! is an invalid format string: -//! -//! ```text -//! {0:x} {0:o} -//! ``` -//! -//! This is invalid because the first argument is both referred to as a -//! hexadecimal as well as an -//! octal. -//! -//! There are various parameters which do require a particular type, however. -//! Namely if the syntax `{:.*}` is used, then the number of characters to print -//! precedes the actual object being formatted, and the number of characters -//! must have the type `uint`. Although a `uint` can be printed with `{}`, it is -//! illegal to reference an argument as such. For example this is another -//! invalid format string: -//! -//! ```text -//! {:.*} {0} -//! ``` -//! -//! ### Formatting traits -//! -//! When requesting that an argument be formatted with a particular type, you -//! are actually requesting that an argument ascribes to a particular trait. -//! This allows multiple actual types to be formatted via `{:x}` (like `i8` as -//! well as `int`). The current mapping of types to traits is: -//! -//! * *nothing* ⇒ `Display` -//! * `?` ⇒ `Debug` -//! * `o` ⇒ `Octal` -//! * `x` ⇒ `LowerHex` -//! * `X` ⇒ `UpperHex` -//! * `p` ⇒ `Pointer` -//! * `b` ⇒ `Binary` -//! * `e` ⇒ `LowerExp` -//! * `E` ⇒ `UpperExp` -//! -//! What this means is that any type of argument which implements the -//! `std::fmt::Binary` trait can then be formatted with `{:b}`. Implementations -//! are provided for these traits for a number of primitive types by the -//! standard library as well. If no format is specified (as in `{}` or `{:6}`), -//! then the format trait used is the `Display` trait. -//! -//! When implementing a format trait for your own type, you will have to -//! implement a method of the signature: -//! -//! ```rust -//! # use std::fmt; -//! # struct Foo; // our custom type -//! # impl fmt::Display for Foo { -//! fn fmt(&self, f: &mut std::fmt::Formatter) -> fmt::Result { -//! # write!(f, "testing, testing") -//! # } } -//! ``` -//! -//! Your type will be passed as `self` by-reference, and then the function -//! should emit output into the `f.buf` stream. It is up to each format trait -//! implementation to correctly adhere to the requested formatting parameters. -//! The values of these parameters will be listed in the fields of the -//! `Formatter` struct. In order to help with this, the `Formatter` struct also -//! provides some helper methods. -//! -//! Additionally, the return value of this function is `fmt::Result` which is a -//! typedef to `Result<(), IoError>` (also known as `IoResult<()>`). Formatting -//! implementations should ensure that they return errors from `write!` -//! correctly (propagating errors upward). -//! -//! An example of implementing the formatting traits would look -//! like: -//! -//! ```rust -//! use std::fmt; -//! use std::f64; -//! use std::num::Float; -//! -//! #[derive(Debug)] -//! struct Vector2D { -//! x: int, -//! y: int, -//! } -//! -//! impl fmt::Display for Vector2D { -//! fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { -//! // The `f` value implements the `Writer` trait, which is what the -//! // write! macro is expecting. Note that this formatting ignores the -//! // various flags provided to format strings. -//! write!(f, "({}, {})", self.x, self.y) -//! } -//! } -//! -//! // Different traits allow different forms of output of a type. The meaning -//! // of this format is to print the magnitude of a vector. -//! impl fmt::Binary for Vector2D { -//! fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { -//! let magnitude = (self.x * self.x + self.y * self.y) as f64; -//! 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. -//! let decimals = f.precision().unwrap_or(3); -//! let string = f64::to_str_exact(magnitude, decimals); -//! f.pad_integral(true, "", string.as_slice()) -//! } -//! } -//! -//! fn main() { -//! let myvector = Vector2D { x: 3, y: 4 }; -//! -//! println!("{}", myvector); // => "(3, 4)" -//! println!("{:?}", myvector); // => "Vector2D {x: 3, y:4}" -//! println!("{:10.3b}", myvector); // => " 5.000" -//! } -//! ``` -//! -//! #### fmt::Display vs fmt::Debug -//! -//! These two formatting traits have distinct purposes: -//! -//! - `fmt::Display` implementations assert that the type can be faithfully -//! represented as a UTF-8 string at all times. It is **not** expected that -//! all types implement the `Display` trait. -//! - `fmt::Debug` implementations should be implemented for **all** public types. -//! Output will typically represent the internal state as faithfully as possible. -//! The purpose of the `Debug` trait is to facilitate debugging Rust code. In -//! most cases, using `#[derive(Debug)]` is sufficient and recommended. -//! -//! Some examples of the output from both traits: -//! -//! ``` -//! assert_eq!(format!("{} {:?}", 3i32, 4i32), "3 4"); -//! assert_eq!(format!("{} {:?}", 'a', 'b'), "a 'b'"); -//! assert_eq!(format!("{} {:?}", "foo\n", "bar\n"), "foo\n \"bar\\n\""); -//! ``` -//! -//! ### Related macros -//! -//! There are a number of related macros in the `format!` family. The ones that -//! are currently implemented are: -//! -//! ```ignore -//! format! // described above -//! write! // first argument is a &mut old_io::Writer, the destination -//! writeln! // same as write but appends a newline -//! print! // the format string is printed to the standard output -//! println! // same as print but appends a newline -//! format_args! // described below. -//! ``` -//! -//! #### `write!` -//! -//! This and `writeln` are two macros which are used to emit the format string -//! to a specified stream. This is used to prevent intermediate allocations of -//! format strings and instead directly write the output. Under the hood, this -//! function is actually invoking the `write` function defined in this module. -//! Example usage is: -//! -//! ```rust -//! # #![allow(unused_must_use)] -//! let mut w = Vec::new(); -//! write!(&mut w, "Hello {}!", "world"); -//! ``` -//! -//! #### `print!` -//! -//! This and `println` emit their output to stdout. Similarly to the `write!` -//! macro, the goal of these macros is to avoid intermediate allocations when -//! printing output. Example usage is: -//! -//! ```rust -//! print!("Hello {}!", "world"); -//! println!("I have a newline {}", "character at the end"); -//! ``` -//! -//! #### `format_args!` -//! This is a curious macro which is used to safely pass around -//! an opaque object describing the format string. This object -//! does not require any heap allocations to create, and it only -//! references information on the stack. Under the hood, all of -//! the related macros are implemented in terms of this. First -//! off, some example usage is: -//! -//! ``` -//! use std::fmt; -//! use std::old_io; -//! -//! fmt::format(format_args!("this returns {}", "String")); -//! -//! let mut some_writer = old_io::stdout(); -//! write!(&mut some_writer, "{}", format_args!("print with a {}", "macro")); -//! -//! fn my_fmt_fn(args: fmt::Arguments) { -//! write!(&mut old_io::stdout(), "{}", args); -//! } -//! my_fmt_fn(format_args!("or a {} too", "function")); -//! ``` -//! -//! The result of the `format_args!` macro is a value of type `fmt::Arguments`. -//! This structure can then be passed to the `write` and `format` functions -//! inside this module in order to process the format string. -//! The goal of this macro is to even further prevent intermediate allocations -//! when dealing formatting strings. -//! -//! For example, a logging library could use the standard formatting syntax, but -//! it would internally pass around this structure until it has been determined -//! where output should go to. -//! -//! ## Syntax -//! -//! The syntax for the formatting language used is drawn from other languages, -//! so it should not be too alien. Arguments are formatted with python-like -//! syntax, meaning that arguments are surrounded by `{}` instead of the C-like -//! `%`. The actual grammar for the formatting syntax is: -//! -//! ```text -//! format_string := [ format ] * -//! format := '{' [ argument ] [ ':' format_spec ] '}' -//! argument := integer | identifier -//! -//! format_spec := [[fill]align][sign]['#'][0][width]['.' precision][type] -//! fill := character -//! align := '<' | '^' | '>' -//! sign := '+' | '-' -//! width := count -//! precision := count | '*' -//! type := identifier | '' -//! count := parameter | integer -//! parameter := integer '$' -//! ``` -//! -//! ## Formatting Parameters -//! -//! Each argument being formatted can be transformed by a number of formatting -//! parameters (corresponding to `format_spec` in the syntax above). These -//! parameters affect the string representation of what's being formatted. This -//! syntax draws heavily from Python's, so it may seem a bit familiar. -//! -//! ### Fill/Alignment -//! -//! The fill character is provided normally in conjunction with the `width` -//! parameter. This indicates that if the value being formatted is smaller than -//! `width` some extra characters will be printed around it. The extra -//! characters are specified by `fill`, and the alignment can be one of two -//! options: -//! -//! * `<` - the argument is left-aligned in `width` columns -//! * `^` - the argument is center-aligned in `width` columns -//! * `>` - the argument is right-aligned in `width` columns -//! -//! ### Sign/#/0 -//! -//! These can all be interpreted as flags for a particular formatter. -//! -//! * '+' - This is intended for numeric types and indicates that the sign -//! should always be printed. Positive signs are never printed by -//! default, and the negative sign is only printed by default for the -//! `Signed` trait. This flag indicates that the correct sign (+ or -) -//! should always be printed. -//! * '-' - Currently not used -//! * '#' - This flag is indicates that the "alternate" form of printing should -//! be used. By default, this only applies to the integer formatting -//! traits and performs like: -//! * `x` - precedes the argument with a "0x" -//! * `X` - precedes the argument with a "0x" -//! * `t` - precedes the argument with a "0b" -//! * `o` - precedes the argument with a "0o" -//! * '0' - This is used to indicate for integer formats that the padding should -//! both be done with a `0` character as well as be sign-aware. A format -//! like `{:08d}` would yield `00000001` for the integer `1`, while the -//! same format would yield `-0000001` for the integer `-1`. Notice that -//! the negative version has one fewer zero than the positive version. -//! -//! ### Width -//! -//! This is a parameter for the "minimum width" that the format should take up. -//! If the value's string does not fill up this many characters, then the -//! padding specified by fill/alignment will be used to take up the required -//! space. -//! -//! The default fill/alignment for non-numerics is a space and left-aligned. The -//! defaults for numeric formatters is also a space but with right-alignment. If -//! the '0' flag is specified for numerics, then the implicit fill character is -//! '0'. -//! -//! The value for the width can also be provided as a `uint` in the list of -//! parameters by using the `2$` syntax indicating that the second argument is a -//! `uint` specifying the width. -//! -//! ### Precision -//! -//! For non-numeric types, this can be considered a "maximum width". If the -//! resulting string is longer than this width, then it is truncated down to -//! this many characters and only those are emitted. -//! -//! For integral types, this has no meaning currently. -//! -//! For floating-point types, this indicates how many digits after the decimal -//! point should be printed. -//! -//! ## Escaping -//! -//! The literal characters `{` and `}` may be included in a string by preceding -//! them with the same character. For example, the `{` character is escaped with -//! `{{` and the `}` character is escaped with `}}`. - -#![unstable(feature = "std_misc")] - -pub use core::fmt::{Formatter, Result, Writer, rt}; -pub use core::fmt::{Show, String, Octal, Binary}; -pub use core::fmt::{Display, Debug}; -pub use core::fmt::{LowerHex, UpperHex, Pointer}; -pub use core::fmt::{LowerExp, UpperExp}; -pub use core::fmt::Error; -pub use core::fmt::{ArgumentV1, Arguments, write, radix, Radix, RadixFmt}; - -pub use core_collections::fmt::format; diff --git a/src/libstd/lib.rs b/src/libstd/lib.rs index 2a523356f62c0..9a9a554ec9842 100644 --- a/src/libstd/lib.rs +++ b/src/libstd/lib.rs @@ -181,6 +181,7 @@ pub use core::error; #[cfg(not(test))] pub use alloc::boxed; pub use alloc::rc; +pub use core_collections::fmt; pub use core_collections::slice; pub use core_collections::str; pub use core_collections::string; @@ -246,7 +247,6 @@ pub mod thread_local; pub mod dynamic_lib; pub mod ffi; -pub mod fmt; pub mod old_io; pub mod io; pub mod os; From 312f8bd850ca4d575b1414badabab4f5aee99c67 Mon Sep 17 00:00:00 2001 From: Keegan McAllister Date: Sat, 7 Feb 2015 10:51:25 -0800 Subject: [PATCH 6/6] Fix new test --- src/test/run-make/alloc-extern-crates/fakealloc.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/test/run-make/alloc-extern-crates/fakealloc.rs b/src/test/run-make/alloc-extern-crates/fakealloc.rs index 563a527b94194..6d30956ab2b44 100644 --- a/src/test/run-make/alloc-extern-crates/fakealloc.rs +++ b/src/test/run-make/alloc-extern-crates/fakealloc.rs @@ -9,8 +9,8 @@ // except according to those terms. #![crate_type = "rlib"] +#![feature(no_std, core)] #![no_std] -#![feature(core)] extern crate core;