about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
authorManish Goregaokar <manishsmail@gmail.com>2015-01-28 23:03:36 +0530
committerManish Goregaokar <manishsmail@gmail.com>2015-01-28 23:31:03 +0530
commitc709ed2faf4ea28df1395a924453b5298b87fa57 (patch)
tree9567cea197e37b96607f471b18dd1c77908c8965 /src
parent249c29fe2746d251dc8aab63cd8730df9ff8434c (diff)
parenta45e117733b866302fa99390553d1c548508dcca (diff)
downloadrust-c709ed2faf4ea28df1395a924453b5298b87fa57.tar.gz
rust-c709ed2faf4ea28df1395a924453b5298b87fa57.zip
Merge remote-tracking branch 'origin/master' into rollup
Conflicts:
	src/libcollections/slice.rs
	src/libcore/nonzero.rs
	src/libcore/ops.rs
Diffstat (limited to 'src')
-rw-r--r--src/compiletest/compiletest.rs10
-rw-r--r--src/doc/reference.md71
-rw-r--r--src/driver/driver.rs4
-rw-r--r--src/etc/featureck.py243
-rw-r--r--src/liballoc/arc.rs49
-rw-r--r--src/liballoc/boxed.rs46
-rw-r--r--src/liballoc/heap.rs2
-rw-r--r--src/liballoc/lib.rs7
-rw-r--r--src/liballoc/rc.rs60
-rw-r--r--src/libarena/lib.rs8
-rw-r--r--src/libcollections/binary_heap.rs67
-rw-r--r--src/libcollections/bit.rs141
-rw-r--r--src/libcollections/btree/map.rs133
-rw-r--r--src/libcollections/btree/node.rs2
-rw-r--r--src/libcollections/btree/set.rs94
-rw-r--r--src/libcollections/dlist.rs90
-rw-r--r--src/libcollections/enum_set.rs30
-rw-r--r--src/libcollections/lib.rs19
-rw-r--r--src/libcollections/macros.rs2
-rw-r--r--src/libcollections/ring_buf.rs138
-rw-r--r--src/libcollections/slice.rs158
-rw-r--r--src/libcollections/str.rs157
-rw-r--r--src/libcollections/string.rs124
-rw-r--r--src/libcollections/vec.rs155
-rw-r--r--src/libcollections/vec_map.rs91
-rw-r--r--src/libcore/any.rs18
-rw-r--r--src/libcore/array.rs18
-rw-r--r--src/libcore/atomic.rs96
-rw-r--r--src/libcore/borrow.rs19
-rw-r--r--src/libcore/cell.rs72
-rw-r--r--src/libcore/char.rs64
-rw-r--r--src/libcore/clone.rs16
-rw-r--r--src/libcore/cmp.rs92
-rw-r--r--src/libcore/default.rs10
-rw-r--r--src/libcore/error.rs10
-rw-r--r--src/libcore/finally.rs10
-rw-r--r--src/libcore/fmt/mod.rs151
-rw-r--r--src/libcore/fmt/num.rs17
-rw-r--r--src/libcore/fmt/rt.rs3
-rw-r--r--src/libcore/hash/mod.rs6
-rw-r--r--src/libcore/hash/sip.rs3
-rw-r--r--src/libcore/intrinsics.rs13
-rw-r--r--src/libcore/iter.rs368
-rw-r--r--src/libcore/lib.rs3
-rw-r--r--src/libcore/macros.rs14
-rw-r--r--src/libcore/marker.rs42
-rw-r--r--src/libcore/mem.rs40
-rw-r--r--src/libcore/nonzero.rs4
-rw-r--r--src/libcore/num/f32.rs65
-rw-r--r--src/libcore/num/f64.rs63
-rw-r--r--src/libcore/num/i16.rs2
-rw-r--r--src/libcore/num/i32.rs2
-rw-r--r--src/libcore/num/i64.rs2
-rw-r--r--src/libcore/num/i8.rs2
-rw-r--r--src/libcore/num/int.rs3
-rw-r--r--src/libcore/num/int_macros.rs8
-rw-r--r--src/libcore/num/isize.rs2
-rw-r--r--src/libcore/num/mod.rs188
-rw-r--r--src/libcore/num/u16.rs2
-rw-r--r--src/libcore/num/u32.rs2
-rw-r--r--src/libcore/num/u64.rs2
-rw-r--r--src/libcore/num/u8.rs2
-rw-r--r--src/libcore/num/uint.rs3
-rw-r--r--src/libcore/num/uint_macros.rs8
-rw-r--r--src/libcore/num/usize.rs2
-rw-r--r--src/libcore/ops.rs244
-rw-r--r--src/libcore/option.rs96
-rw-r--r--src/libcore/ptr.rs110
-rw-r--r--src/libcore/raw.rs2
-rw-r--r--src/libcore/result.rs85
-rw-r--r--src/libcore/simd.rs21
-rw-r--r--src/libcore/slice.rs160
-rw-r--r--src/libcore/str/mod.rs125
-rw-r--r--src/libcore/tuple.rs16
-rw-r--r--src/libcoretest/cell.rs1
-rw-r--r--src/libcoretest/lib.rs1
-rw-r--r--src/libflate/lib.rs7
-rw-r--r--src/libfmt_macros/lib.rs7
-rw-r--r--src/libgetopts/lib.rs12
-rw-r--r--src/libgraphviz/lib.rs8
-rw-r--r--src/libgraphviz/maybe_owned_vec.rs3
-rw-r--r--src/liblibc/lib.rs8
-rw-r--r--src/liblog/lib.rs11
-rw-r--r--src/librand/distributions/mod.rs2
-rw-r--r--src/librand/lib.rs5
-rw-r--r--src/librand/reseeding.rs4
-rw-r--r--src/librbml/lib.rs11
-rw-r--r--src/librustc/lib.rs15
-rw-r--r--src/librustc/lint/builtin.rs148
-rw-r--r--src/librustc/lint/context.rs13
-rw-r--r--src/librustc/middle/astencode.rs8
-rw-r--r--src/librustc/middle/infer/mod.rs9
-rw-r--r--src/librustc/middle/infer/type_variable.rs11
-rw-r--r--src/librustc/middle/infer/unify.rs121
-rw-r--r--src/librustc/middle/stability.rs296
-rw-r--r--src/librustc/middle/traits/error_reporting.rs2
-rw-r--r--src/librustc/middle/traits/fulfill.rs2
-rw-r--r--src/librustc/middle/traits/mod.rs61
-rw-r--r--src/librustc/middle/traits/object_safety.rs8
-rw-r--r--src/librustc/middle/traits/project.rs271
-rw-r--r--src/librustc/middle/traits/select.rs155
-rw-r--r--src/librustc/middle/traits/util.rs63
-rw-r--r--src/librustc/middle/ty.rs142
-rw-r--r--src/librustc/middle/ty_fold.rs6
-rw-r--r--src/librustc/session/mod.rs12
-rw-r--r--src/librustc/util/common.rs3
-rw-r--r--src/librustc/util/ppaux.rs141
-rw-r--r--src/librustc/util/snapshot_vec.rs36
-rw-r--r--src/librustc_back/lib.rs11
-rw-r--r--src/librustc_back/target/mod.rs2
-rw-r--r--src/librustc_bitflags/lib.rs4
-rw-r--r--src/librustc_borrowck/lib.rs8
-rw-r--r--src/librustc_driver/driver.rs25
-rw-r--r--src/librustc_driver/lib.rs13
-rw-r--r--src/librustc_driver/test.rs4
-rw-r--r--src/librustc_llvm/lib.rs10
-rw-r--r--src/librustc_privacy/lib.rs7
-rw-r--r--src/librustc_resolve/lib.rs10
-rw-r--r--src/librustc_trans/back/write.rs2
-rw-r--r--src/librustc_trans/lib.rs15
-rw-r--r--src/librustc_trans/trans/meth.rs30
-rw-r--r--src/librustc_trans/trans/type_of.rs4
-rw-r--r--src/librustc_typeck/astconv.rs35
-rw-r--r--src/librustc_typeck/check/closure.rs88
-rw-r--r--src/librustc_typeck/check/compare_method.rs15
-rw-r--r--src/librustc_typeck/check/demand.rs3
-rw-r--r--src/librustc_typeck/check/method/confirm.rs4
-rw-r--r--src/librustc_typeck/check/method/probe.rs23
-rw-r--r--src/librustc_typeck/check/mod.rs62
-rw-r--r--src/librustc_typeck/check/regionck.rs2
-rw-r--r--src/librustc_typeck/check/wf.rs1
-rw-r--r--src/librustc_typeck/lib.rs8
-rw-r--r--src/librustc_typeck/variance.rs6
-rw-r--r--src/librustdoc/clean/mod.rs26
-rw-r--r--src/librustdoc/core.rs2
-rw-r--r--src/librustdoc/html/format.rs22
-rw-r--r--src/librustdoc/lib.rs15
-rw-r--r--src/librustdoc/stability_summary.rs27
-rw-r--r--src/librustdoc/test.rs4
-rw-r--r--src/libserialize/lib.rs13
-rw-r--r--src/libstd/ascii.rs30
-rw-r--r--src/libstd/bool.rs2
-rw-r--r--src/libstd/collections/hash/map.rs129
-rw-r--r--src/libstd/collections/hash/set.rs105
-rw-r--r--src/libstd/collections/hash/table.rs1
-rw-r--r--src/libstd/collections/mod.rs8
-rw-r--r--src/libstd/dynamic_lib.rs2
-rw-r--r--src/libstd/failure.rs2
-rw-r--r--src/libstd/ffi/c_str.rs2
-rw-r--r--src/libstd/ffi/mod.rs5
-rw-r--r--src/libstd/ffi/os_str.rs3
-rw-r--r--src/libstd/fmt.rs7
-rw-r--r--src/libstd/lib.rs14
-rw-r--r--src/libstd/macros.rs14
-rw-r--r--src/libstd/num/f32.rs18
-rw-r--r--src/libstd/num/f64.rs18
-rw-r--r--src/libstd/num/float_macros.rs2
-rw-r--r--src/libstd/num/i16.rs2
-rw-r--r--src/libstd/num/i32.rs2
-rw-r--r--src/libstd/num/i64.rs2
-rw-r--r--src/libstd/num/i8.rs2
-rw-r--r--src/libstd/num/int.rs3
-rw-r--r--src/libstd/num/int_macros.rs2
-rw-r--r--src/libstd/num/isize.rs2
-rw-r--r--src/libstd/num/mod.rs175
-rw-r--r--src/libstd/num/u16.rs2
-rw-r--r--src/libstd/num/u32.rs2
-rw-r--r--src/libstd/num/u64.rs2
-rw-r--r--src/libstd/num/u8.rs2
-rw-r--r--src/libstd/num/uint.rs3
-rw-r--r--src/libstd/num/uint_macros.rs2
-rw-r--r--src/libstd/num/usize.rs2
-rw-r--r--src/libstd/old_io/buffered.rs8
-rw-r--r--src/libstd/old_io/comm_adapters.rs2
-rw-r--r--src/libstd/old_io/mem.rs4
-rw-r--r--src/libstd/old_io/mod.rs18
-rw-r--r--src/libstd/old_io/net/ip.rs4
-rw-r--r--src/libstd/old_io/net/pipe.rs19
-rw-r--r--src/libstd/old_io/net/tcp.rs26
-rw-r--r--src/libstd/old_io/net/udp.rs22
-rw-r--r--src/libstd/old_io/process.rs7
-rw-r--r--src/libstd/os.rs4
-rw-r--r--src/libstd/path/mod.rs6
-rw-r--r--src/libstd/path/posix.rs2
-rw-r--r--src/libstd/path/windows.rs2
-rw-r--r--src/libstd/prelude/mod.rs3
-rw-r--r--src/libstd/prelude/v1.rs59
-rw-r--r--src/libstd/rand/mod.rs2
-rw-r--r--src/libstd/rt/mod.rs2
-rw-r--r--src/libstd/rt/unwind.rs2
-rw-r--r--src/libstd/rtdeps.rs2
-rw-r--r--src/libstd/sync/barrier.rs8
-rw-r--r--src/libstd/sync/condvar.rs40
-rw-r--r--src/libstd/sync/future.rs7
-rw-r--r--src/libstd/sync/mod.rs2
-rw-r--r--src/libstd/sync/mpsc/mod.rs66
-rw-r--r--src/libstd/sync/mpsc/mpsc_queue.rs4
-rw-r--r--src/libstd/sync/mpsc/select.rs13
-rw-r--r--src/libstd/sync/mpsc/spsc_queue.rs2
-rw-r--r--src/libstd/sync/mutex.rs33
-rw-r--r--src/libstd/sync/once.rs6
-rw-r--r--src/libstd/sync/poison.rs29
-rw-r--r--src/libstd/sync/rwlock.rs49
-rw-r--r--src/libstd/sync/semaphore.rs7
-rw-r--r--src/libstd/sync/task_pool.rs9
-rw-r--r--src/libstd/sys/unix/ext.rs2
-rw-r--r--src/libstd/sys/windows/ext.rs2
-rw-r--r--src/libstd/thread.rs58
-rw-r--r--src/libstd/thread_local/mod.rs18
-rw-r--r--src/libstd/thread_local/scoped.rs5
-rw-r--r--src/libstd/thunk.rs1
-rw-r--r--src/libstd/time/duration.rs4
-rw-r--r--src/libstd/tuple.rs2
-rw-r--r--src/libstd/unit.rs2
-rw-r--r--src/libsyntax/ast.rs3
-rw-r--r--src/libsyntax/attr.rs156
-rw-r--r--src/libsyntax/diagnostic.rs12
-rw-r--r--src/libsyntax/ext/base.rs4
-rw-r--r--src/libsyntax/ext/tt/macro_parser.rs14
-rw-r--r--src/libsyntax/ext/tt/macro_rules.rs2
-rw-r--r--src/libsyntax/feature_gate.rs183
-rw-r--r--src/libsyntax/fold.rs5
-rw-r--r--src/libsyntax/lib.rs14
-rw-r--r--src/libsyntax/parse/lexer/mod.rs2
-rw-r--r--src/libsyntax/parse/mod.rs2
-rw-r--r--src/libsyntax/parse/parser.rs7
-rw-r--r--src/libsyntax/test.rs95
-rw-r--r--src/libsyntax/util/small_vector.rs3
-rw-r--r--src/libterm/lib.rs13
-rw-r--r--src/libtest/lib.rs12
-rw-r--r--src/libunicode/lib.rs7
-rw-r--r--src/libunicode/u_char.rs102
-rw-r--r--src/libunicode/u_str.rs2
-rw-r--r--src/rustbook/main.rs7
-rw-r--r--src/test/auxiliary/inherited_stability.rs41
-rwxr-xr-xsrc/test/auxiliary/lint_output_format.rs9
-rw-r--r--src/test/auxiliary/lint_stability.rs153
-rw-r--r--src/test/auxiliary/stability_cfg1.rs3
-rw-r--r--src/test/auxiliary/stability_cfg2.rs5
-rw-r--r--src/test/bench/shootout-mandelbrot.rs1
-rw-r--r--src/test/compile-fail/associated-type-projection-from-supertrait.rs4
-rw-r--r--src/test/compile-fail/associated-types-path-2.rs4
-rw-r--r--src/test/compile-fail/borrowck-overloaded-call.rs12
-rw-r--r--src/test/compile-fail/enable-unstable-lib-feature.rs23
-rw-r--r--src/test/compile-fail/extern-wrong-value-type.rs4
-rw-r--r--src/test/compile-fail/fail-no-dead-code-core.rs2
-rw-r--r--src/test/compile-fail/feature-gate-unboxed-closures-manual-impls.rs26
-rw-r--r--src/test/compile-fail/fn-trait-formatting.rs4
-rw-r--r--src/test/compile-fail/issue-15094.rs4
-rw-r--r--src/test/compile-fail/issue-17337.rs4
-rw-r--r--src/test/compile-fail/issue-17545.rs2
-rw-r--r--src/test/compile-fail/issue-17999.rs2
-rw-r--r--src/test/compile-fail/issue-18400.rs5
-rw-r--r--src/test/compile-fail/issue-20711-2.rs2
-rw-r--r--src/test/compile-fail/issue-20711.rs2
-rw-r--r--src/test/compile-fail/issue-21160.rs2
-rw-r--r--src/test/compile-fail/issue-21356.rs2
-rw-r--r--src/test/compile-fail/lint-ctypes.rs2
-rw-r--r--src/test/compile-fail/lint-dead-code-1.rs2
-rw-r--r--src/test/compile-fail/lint-dead-code-3.rs2
-rw-r--r--src/test/compile-fail/lint-dead-code-4.rs4
-rw-r--r--src/test/compile-fail/lint-exceeding-bitshifts.rs2
-rw-r--r--src/test/compile-fail/lint-forbid-attr.rs4
-rw-r--r--src/test/compile-fail/lint-forbid-cmdline.rs5
-rw-r--r--src/test/compile-fail/lint-output-format.rs8
-rw-r--r--src/test/compile-fail/lint-stability.rs335
-rw-r--r--src/test/compile-fail/lint-unknown-feature-default.rs15
-rw-r--r--src/test/compile-fail/lint-unknown-feature.rs4
-rw-r--r--src/test/compile-fail/lint-unused-extern-crate.rs4
-rw-r--r--src/test/compile-fail/lint-uppercase-variables.rs3
-rw-r--r--src/test/compile-fail/liveness-unused.rs3
-rw-r--r--src/test/compile-fail/missing_debug_impls.rs3
-rw-r--r--src/test/compile-fail/overloaded-calls-bad.rs4
-rw-r--r--src/test/compile-fail/overloaded-calls-nontuple.rs3
-rw-r--r--src/test/compile-fail/regions-infer-invariance-due-to-mutability-4.rs8
-rw-r--r--src/test/compile-fail/shift-various-bad-types.rs2
-rw-r--r--src/test/compile-fail/simd-binop.rs1
-rw-r--r--src/test/compile-fail/slice-mut.rs3
-rw-r--r--src/test/compile-fail/stability-attribute-sanity.rs95
-rw-r--r--src/test/compile-fail/staged_api.rs (renamed from src/test/compile-fail/simd-experimental.rs)10
-rw-r--r--src/test/compile-fail/traits-multidispatch-bad.rs2
-rw-r--r--src/test/compile-fail/unboxed-closure-feature-gate.rs3
-rw-r--r--src/test/compile-fail/unboxed-closure-sugar-default.rs11
-rw-r--r--src/test/compile-fail/unboxed-closure-sugar-equiv.rs30
-rw-r--r--src/test/compile-fail/unboxed-closure-sugar-lifetime-elision.rs9
-rw-r--r--src/test/compile-fail/unboxed-closure-sugar-not-used-on-fn.rs4
-rw-r--r--src/test/compile-fail/unboxed-closure-sugar-region.rs12
-rw-r--r--src/test/compile-fail/unboxed-closure-sugar-used-on-struct-1.rs5
-rw-r--r--src/test/compile-fail/unboxed-closure-sugar-used-on-struct.rs5
-rw-r--r--src/test/compile-fail/unboxed-closure-sugar-wrong-number-number-type-parameters-1.rs2
-rw-r--r--src/test/compile-fail/unboxed-closure-sugar-wrong-trait.rs2
-rw-r--r--src/test/compile-fail/unboxed-closures-fnmut-as-fn.rs8
-rw-r--r--src/test/compile-fail/unboxed-closures-unsafe-extern-fn.rs4
-rw-r--r--src/test/compile-fail/unboxed-closures-vtable-mismatch.rs6
-rw-r--r--src/test/compile-fail/unboxed-closures-wrong-abi.rs4
-rw-r--r--src/test/compile-fail/unboxed-closures-wrong-arg-type-extern-fn.rs4
-rw-r--r--src/test/compile-fail/unboxed-closures-wrong-trait.rs1
-rw-r--r--src/test/compile-fail/unused-attr.rs2
-rw-r--r--src/test/compile-fail/variance-object-types.rs24
-rw-r--r--src/test/debuginfo/simd.rs1
-rw-r--r--src/test/run-make/allow-non-lint-warnings-cmdline/10
-rw-r--r--src/test/run-make/allow-non-lint-warnings-cmdline/Makefile12
-rw-r--r--src/test/run-make/allow-non-lint-warnings-cmdline/foo.rs15
-rw-r--r--src/test/run-make/allow-warnings-cmdline-stability/10
-rw-r--r--src/test/run-make/allow-warnings-cmdline-stability/Makefile19
-rw-r--r--src/test/run-make/allow-warnings-cmdline-stability/bar.rs16
-rw-r--r--src/test/run-make/allow-warnings-cmdline-stability/foo.rs13
-rw-r--r--src/test/run-pass/associated-types-issue-21212.rs28
-rw-r--r--src/test/run-pass/associated-types-normalize-in-bounds-binding.rs42
-rw-r--r--src/test/run-pass/associated-types-normalize-unifield-struct.rs1
-rw-r--r--src/test/run-pass/bare-fn-implements-fn-mut.rs4
-rw-r--r--src/test/run-pass/hrtb-parse.rs16
-rw-r--r--src/test/run-pass/hrtb-trait-object-paren-notation.rs2
-rw-r--r--src/test/run-pass/ifmt.rs1
-rw-r--r--src/test/run-pass/into-iterator-type-inference-shift.rs41
-rw-r--r--src/test/run-pass/issue-11958.rs1
-rw-r--r--src/test/run-pass/issue-13655.rs3
-rw-r--r--src/test/run-pass/issue-14958.rs3
-rw-r--r--src/test/run-pass/issue-14959.rs4
-rw-r--r--src/test/run-pass/issue-16668.rs2
-rw-r--r--src/test/run-pass/issue-16671.rs1
-rw-r--r--src/test/run-pass/issue-16739.rs23
-rw-r--r--src/test/run-pass/issue-19499.rs20
-rw-r--r--src/test/run-pass/issue-21058.rs1
-rw-r--r--src/test/run-pass/issue-21245.rs62
-rw-r--r--src/test/run-pass/object-method-numbering.rs36
-rw-r--r--src/test/run-pass/overloaded-calls-param-vtables.rs8
-rw-r--r--src/test/run-pass/overloaded-calls-simple.rs27
-rw-r--r--src/test/run-pass/overloaded-calls-zero-args.rs9
-rw-r--r--src/test/run-pass/simd-binop.rs1
-rw-r--r--src/test/run-pass/simd-issue-10604.rs1
-rw-r--r--src/test/run-pass/tcp-connect-timeouts.rs1
-rw-r--r--src/test/run-pass/unboxed-closures-boxed.rs6
-rw-r--r--src/test/run-pass/unboxed-closures-fn-as-fnmut-and-fnonce.rs11
-rw-r--r--src/test/run-pass/unboxed-closures-fnmut-as-fnonce.rs10
-rw-r--r--src/test/run-pass/unboxed-closures-generic.rs4
-rw-r--r--src/test/run-pass/unboxed-closures-manual-impl.rs10
-rw-r--r--src/test/run-pass/unboxed-closures-monomorphization.rs6
-rw-r--r--src/test/run-pass/unboxed-closures-sugar-object.rs2
339 files changed, 5764 insertions, 3761 deletions
diff --git a/src/compiletest/compiletest.rs b/src/compiletest/compiletest.rs
index b95e956aca2..eedff1d1176 100644
--- a/src/compiletest/compiletest.rs
+++ b/src/compiletest/compiletest.rs
@@ -13,7 +13,15 @@
 #![feature(slicing_syntax, unboxed_closures)]
 #![feature(box_syntax)]
 #![feature(int_uint)]
-#![allow(unstable)]
+#![feature(test)]
+#![feature(rustc_private)]
+#![feature(std_misc)]
+#![feature(path)]
+#![feature(io)]
+#![feature(core)]
+#![feature(collections)]
+#![feature(os)]
+#![feature(unicode)]
 
 #![deny(warnings)]
 
diff --git a/src/doc/reference.md b/src/doc/reference.md
index d40a2a1bcfe..59ac173f97a 100644
--- a/src/doc/reference.md
+++ b/src/doc/reference.md
@@ -2359,77 +2359,6 @@ Supported traits for `derive` are:
 * `Show`, to format a value using the `{}` formatter.
 * `Zero`, to create a zero instance of a numeric data type.
 
-### Stability
-
-One can indicate the stability of an API using the following attributes:
-
-* `deprecated`: This item should no longer be used, e.g. it has been
-  replaced. No guarantee of backwards-compatibility.
-* `experimental`: This item was only recently introduced or is
-  otherwise in a state of flux. It may change significantly, or even
-  be removed. No guarantee of backwards-compatibility.
-* `unstable`: This item is still under development, but requires more
-  testing to be considered stable. No guarantee of backwards-compatibility.
-* `stable`: This item is considered stable, and will not change
-  significantly. Guarantee of backwards-compatibility.
-* `frozen`: This item is very stable, and is unlikely to
-  change. Guarantee of backwards-compatibility.
-* `locked`: This item will never change unless a serious bug is
-  found. Guarantee of backwards-compatibility.
-
-These levels are directly inspired by
-[Node.js' "stability index"](http://nodejs.org/api/documentation.html).
-
-Stability levels are inherited, so an item's stability attribute is the default
-stability for everything nested underneath it.
-
-There are lints for disallowing items marked with certain levels: `deprecated`,
-`experimental` and `unstable`. For now, only `deprecated` warns by default, but
-this will change once the standard library has been stabilized. Stability
-levels are meant to be promises at the crate level, so these lints only apply
-when referencing items from an _external_ crate, not to items defined within
-the current crate. Items with no stability level are considered to be unstable
-for the purposes of the lint. One can give an optional string that will be
-displayed when the lint flags the use of an item.
-
-For example, if we define one crate called `stability_levels`:
-
-```{.ignore}
-#[deprecated="replaced by `best`"]
-pub fn bad() {
-    // delete everything
-}
-
-pub fn better() {
-    // delete fewer things
-}
-
-#[stable]
-pub fn best() {
-    // delete nothing
-}
-```
-
-then the lints will work as follows for a client crate:
-
-```{.ignore}
-#![warn(unstable)]
-extern crate stability_levels;
-use stability_levels::{bad, better, best};
-
-fn main() {
-    bad(); // "warning: use of deprecated item: replaced by `best`"
-
-    better(); // "warning: use of unmarked item"
-
-    best(); // no warning
-}
-```
-
-> **Note:** Currently these are only checked when applied to individual
-> functions, structs, methods and enum variants, *not* to entire modules,
-> traits, impls or enums themselves.
-
 ### Compiler Features
 
 Certain aspects of Rust may be implemented in the compiler, but they're not
diff --git a/src/driver/driver.rs b/src/driver/driver.rs
index 5f086280a65..601f130341b 100644
--- a/src/driver/driver.rs
+++ b/src/driver/driver.rs
@@ -8,7 +8,9 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#![allow(unstable)]
+#![allow(unknown_features)]
+#![cfg_attr(rustc, feature(rustc_private))]
+#![cfg_attr(rustdoc, feature(rustdoc))]
 
 #[cfg(rustdoc)]
 extern crate "rustdoc" as this;
diff --git a/src/etc/featureck.py b/src/etc/featureck.py
new file mode 100644
index 00000000000..064cf1d40ab
--- /dev/null
+++ b/src/etc/featureck.py
@@ -0,0 +1,243 @@
+# 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 <LICENSE-APACHE or
+# http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+# <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+# option. This file may not be copied, modified, or distributed
+# except according to those terms.
+
+# This script does a tree-wide sanity checks against stability
+# attributes, currently:
+#   * For all feature_name/level pairs the 'since' field is the same
+#   * That no features are both stable and unstable.
+#   * That lib features don't have the same name as lang features
+#     unless they are on the 'joint_features' whitelist
+#   * That features that exist in both lang and lib and are stable
+#     since the same version
+#   * Prints information about features
+
+import sys, os, re
+
+src_dir = sys.argv[1]
+
+# Features that are allowed to exist in both the language and the library
+joint_features = [ ]
+
+# Grab the list of language features from the compiler
+language_gate_statuses = [ "Active", "Deprecated", "Removed", "Accepted" ]
+feature_gate_source = os.path.join(src_dir, "libsyntax", "feature_gate.rs")
+language_features = []
+language_feature_names = []
+with open(feature_gate_source, 'r') as f:
+    for line in f:
+        original_line = line
+        line = line.strip()
+        is_feature_line = False
+        for status in language_gate_statuses:
+            if status in line and line.startswith("("):
+                is_feature_line = True
+
+        if is_feature_line:
+            line = line.replace("(", "").replace("),", "").replace(")", "")
+            parts = line.split(",")
+            if len(parts) != 3:
+                print "error: unexpected number of components in line: " + original_line
+                sys.exit(1)
+            feature_name = parts[0].strip().replace('"', "")
+            since = parts[1].strip().replace('"', "")
+            status = parts[2].strip()
+            assert len(feature_name) > 0
+            assert len(since) > 0
+            assert len(status) > 0
+
+            language_feature_names += [feature_name]
+            language_features += [(feature_name, since, status)]
+
+assert len(language_features) > 0
+
+errors = False
+
+lib_features = { }
+lib_features_and_level = { }
+for (dirpath, dirnames, filenames) in os.walk(src_dir):
+    # Don't look for feature names in tests
+    if "src/test" in dirpath:
+        continue
+
+    # Takes a long time to traverse LLVM
+    if "src/llvm" in dirpath:
+        continue
+
+    for filename in filenames:
+        if not filename.endswith(".rs"):
+            continue
+
+        path = os.path.join(dirpath, filename)
+        with open(path, 'r') as f:
+            line_num = 0
+            for line in f:
+                line_num += 1
+                level = None
+                if "[unstable(" in line:
+                    level = "unstable"
+                elif "[stable(" in line:
+                    level = "stable"
+                else:
+                    continue
+
+                # This is a stability attribute. For the purposes of this
+                # script we expect both the 'feature' and 'since' attributes on
+                # the same line, e.g.
+                # `#[unstable(feature = "foo", since = "1.0.0")]`
+
+                p = re.compile('(unstable|stable).*feature *= *"(\w*)"')
+                m = p.search(line)
+                if not m is None:
+                    feature_name = m.group(2)
+                    since = None
+                    if re.compile("\[ *stable").search(line) is not None:
+                        pp = re.compile('since *= *"([\w\.]*)"')
+                        mm = pp.search(line)
+                        if not mm is None:
+                            since = mm.group(1)
+                        else:
+                            print "error: misformed stability attribute"
+                            print "line " + str(line_num) + " of " + path + ":"
+                            print line
+                            errors = True
+
+                    lib_features[feature_name] = feature_name
+                    if lib_features_and_level.get((feature_name, level)) is None:
+                        # Add it to the observed features
+                        lib_features_and_level[(feature_name, level)] = \
+                            (since, path, line_num, line)
+                    else:
+                        # Verify that for this combination of feature_name and level the 'since'
+                        # attribute matches.
+                        (expected_since, source_path, source_line_num, source_line) = \
+                            lib_features_and_level.get((feature_name, level))
+                        if since != expected_since:
+                            print "error: mismatch in " + level + " feature '" + feature_name + "'"
+                            print "line " + str(source_line_num) + " of " + source_path + ":"
+                            print source_line
+                            print "line " + str(line_num) + " of " + path + ":"
+                            print line
+                            errors = True
+
+                    # Verify that this lib feature doesn't duplicate a lang feature
+                    if feature_name in language_feature_names:
+                        print "error: lib feature '" + feature_name + "' duplicates a lang feature"
+                        print "line " + str(line_num) + " of " + path + ":"
+                        print line
+                        errors = True
+
+                else:
+                    print "error: misformed stability attribute"
+                    print "line " + str(line_num) + " of " + path + ":"
+                    print line
+                    errors = True
+
+# Merge data about both lists
+# name, lang, lib, status, stable since
+
+language_feature_stats = {}
+
+for f in language_features:
+    name = f[0]
+    lang = True
+    lib = False
+    status = "unstable"
+    stable_since = None
+
+    if f[2] == "Accepted":
+        status = "stable"
+    if status == "stable":
+        stable_since = f[1]
+
+    language_feature_stats[name] = (name, lang, lib, status, stable_since)
+
+lib_feature_stats = {}
+
+for f in lib_features:
+    name = f
+    lang = False
+    lib = True
+    status = "unstable"
+    stable_since = None
+
+    is_stable = lib_features_and_level.get((name, "stable")) is not None
+    is_unstable = lib_features_and_level.get((name, "unstable")) is not None
+
+    if is_stable and is_unstable:
+        print "error: feature '" + name + "' is both stable and unstable"
+        errors = True
+
+    if is_stable:
+        status = "stable"
+        stable_since = lib_features_and_level[(name, "stable")][0]
+    elif is_unstable:
+        status = "unstable"
+
+    lib_feature_stats[name] = (name, lang, lib, status, stable_since)
+
+# Check for overlap in two sets
+merged_stats = { }
+
+for name in lib_feature_stats:
+    if language_feature_stats.get(name) is not None:
+        if not name in joint_features:
+            print "error: feature '" + name + "' is both a lang and lib feature but not whitelisted"
+            errors = True
+        lang_status = lang_feature_stats[name][3]
+        lib_status = lib_feature_stats[name][3]
+        lang_stable_since = lang_feature_stats[name][4]
+        lib_stable_since = lib_feature_stats[name][4]
+
+        if lang_status != lib_status and lib_status != "deprecated":
+            print "error: feature '" + name + "' has lang status " + lang_status + \
+                  " but lib status " + lib_status
+            errors = True
+
+        if lang_stable_since != lib_stable_since:
+            print "error: feature '" + name + "' has lang stable since " + lang_stable_since + \
+                  " but lib stable since " + lib_stable_since
+            errors = True
+
+        merged_stats[name] = (name, True, True, lang_status, lang_stable_since)
+
+        del language_feature_stats[name]
+        del lib_feature_stats[name]
+
+if errors:
+    sys.exit(1)
+
+# Finally, display the stats
+stats = {}
+stats.update(language_feature_stats)
+stats.update(lib_feature_stats)
+stats.update(merged_stats)
+lines = []
+for s in stats:
+    s = stats[s]
+    type_ = "lang"
+    if s[1] and s[2]:
+        type_ = "lang/lib"
+    elif s[2]:
+        type_ = "lib"
+    line = "{: <32}".format(s[0]) + \
+           "{: <8}".format(type_) + \
+           "{: <12}".format(s[3]) + \
+           "{: <8}".format(str(s[4]))
+    lines += [line]
+
+lines.sort()
+
+print
+print "Rust feature summary:"
+print
+for line in lines:
+    print line
+print
+
diff --git a/src/liballoc/arc.rs b/src/liballoc/arc.rs
index 5f8cd6baf9a..1b75289c64f 100644
--- a/src/liballoc/arc.rs
+++ b/src/liballoc/arc.rs
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#![stable]
+#![stable(feature = "rust1", since = "1.0.0")]
 
 //! Threadsafe reference-counted boxes (the `Arc<T>` type).
 //!
@@ -110,7 +110,7 @@ use heap::deallocate;
 /// }
 /// ```
 #[unsafe_no_drop_flag]
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 pub struct Arc<T> {
     // FIXME #12808: strange name to try to avoid interfering with
     // field accesses of the contained type via Deref
@@ -126,7 +126,8 @@ unsafe impl<T: Sync + Send> Sync for Arc<T> { }
 /// Weak pointers will not keep the data inside of the `Arc` alive, and can be used to break cycles
 /// between `Arc` pointers.
 #[unsafe_no_drop_flag]
-#[unstable = "Weak pointers may not belong in this module."]
+#[unstable(feature = "alloc",
+           reason = "Weak pointers may not belong in this module.")]
 pub struct Weak<T> {
     // FIXME #12808: strange name to try to avoid interfering with
     // field accesses of the contained type via Deref
@@ -156,7 +157,7 @@ impl<T> Arc<T> {
     /// let five = Arc::new(5i);
     /// ```
     #[inline]
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     pub fn new(data: T) -> Arc<T> {
         // Start the weak pointer count as 1 which is the weak pointer that's
         // held by all the strong pointers (kinda), see std/rc.rs for more info
@@ -179,7 +180,8 @@ impl<T> Arc<T> {
     ///
     /// let weak_five = five.downgrade();
     /// ```
-    #[unstable = "Weak pointers may not belong in this module."]
+    #[unstable(feature = "alloc",
+               reason = "Weak pointers may not belong in this module.")]
     pub fn downgrade(&self) -> Weak<T> {
         // See the clone() impl for why this is relaxed
         self.inner().weak.fetch_add(1, Relaxed);
@@ -200,15 +202,15 @@ impl<T> Arc<T> {
 
 /// Get the number of weak references to this value.
 #[inline]
-#[unstable]
+#[unstable(feature = "alloc")]
 pub fn weak_count<T>(this: &Arc<T>) -> uint { this.inner().weak.load(SeqCst) - 1 }
 
 /// Get the number of strong references to this value.
 #[inline]
-#[unstable]
+#[unstable(feature = "alloc")]
 pub fn strong_count<T>(this: &Arc<T>) -> uint { this.inner().strong.load(SeqCst) }
 
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl<T> Clone for Arc<T> {
     /// Makes a clone of the `Arc<T>`.
     ///
@@ -245,7 +247,7 @@ impl<T> BorrowFrom<Arc<T>> for T {
     }
 }
 
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl<T> Deref for Arc<T> {
     type Target = T;
 
@@ -271,7 +273,7 @@ impl<T: Send + Sync + Clone> Arc<T> {
     /// let mut_five = five.make_unique();
     /// ```
     #[inline]
-    #[unstable]
+    #[unstable(feature = "alloc")]
     pub fn make_unique(&mut self) -> &mut T {
         // Note that we hold a strong reference, which also counts as a weak reference, so we only
         // clone if there is an additional reference of either kind.
@@ -289,7 +291,7 @@ impl<T: Send + Sync + Clone> Arc<T> {
 }
 
 #[unsafe_destructor]
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl<T: Sync + Send> Drop for Arc<T> {
     /// Drops the `Arc<T>`.
     ///
@@ -355,7 +357,8 @@ impl<T: Sync + Send> Drop for Arc<T> {
     }
 }
 
-#[unstable = "Weak pointers may not belong in this module."]
+#[unstable(feature = "alloc",
+           reason = "Weak pointers may not belong in this module.")]
 impl<T: Sync + Send> Weak<T> {
     /// Upgrades a weak reference to a strong reference.
     ///
@@ -393,7 +396,8 @@ impl<T: Sync + Send> Weak<T> {
     }
 }
 
-#[unstable = "Weak pointers may not belong in this module."]
+#[unstable(feature = "alloc",
+           reason = "Weak pointers may not belong in this module.")]
 impl<T: Sync + Send> Clone for Weak<T> {
     /// Makes a clone of the `Weak<T>`.
     ///
@@ -417,7 +421,7 @@ impl<T: Sync + Send> Clone for Weak<T> {
 }
 
 #[unsafe_destructor]
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl<T: Sync + Send> Drop for Weak<T> {
     /// Drops the `Weak<T>`.
     ///
@@ -460,7 +464,7 @@ impl<T: Sync + Send> Drop for Weak<T> {
     }
 }
 
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl<T: PartialEq> PartialEq for Arc<T> {
     /// Equality for two `Arc<T>`s.
     ///
@@ -492,7 +496,7 @@ impl<T: PartialEq> PartialEq for Arc<T> {
     /// ```
     fn ne(&self, other: &Arc<T>) -> bool { *(*self) != *(*other) }
 }
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl<T: PartialOrd> PartialOrd for Arc<T> {
     /// Partial comparison for two `Arc<T>`s.
     ///
@@ -571,30 +575,30 @@ impl<T: PartialOrd> PartialOrd for Arc<T> {
     /// ```
     fn ge(&self, other: &Arc<T>) -> bool { *(*self) >= *(*other) }
 }
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl<T: Ord> Ord for Arc<T> {
     fn cmp(&self, other: &Arc<T>) -> Ordering { (**self).cmp(&**other) }
 }
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl<T: Eq> Eq for Arc<T> {}
 
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl<T: fmt::Display> fmt::Display for Arc<T> {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         fmt::Display::fmt(&**self, f)
     }
 }
 
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl<T: fmt::Debug> fmt::Debug for Arc<T> {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         fmt::Debug::fmt(&**self, f)
     }
 }
 
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl<T: Default + Sync + Send> Default for Arc<T> {
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     fn default() -> Arc<T> { Arc::new(Default::default()) }
 }
 
@@ -605,7 +609,6 @@ impl<H: Hasher, T: Hash<H>> Hash<H> for Arc<T> {
 }
 
 #[cfg(test)]
-#[allow(unstable)]
 mod tests {
     use std::clone::Clone;
     use std::sync::mpsc::channel;
diff --git a/src/liballoc/boxed.rs b/src/liballoc/boxed.rs
index c4abedf3fe8..51e5fc5820c 100644
--- a/src/liballoc/boxed.rs
+++ b/src/liballoc/boxed.rs
@@ -43,7 +43,7 @@
 //!
 //! This will print `Cons(1i32, Box(Cons(2i32, Box(Nil))))`.
 
-#![stable]
+#![stable(feature = "rust1", since = "1.0.0")]
 
 use core::any::Any;
 use core::clone::Clone;
@@ -77,14 +77,15 @@ use core::result::Result;
 /// }
 /// ```
 #[lang = "exchange_heap"]
-#[unstable = "may be renamed; uncertain about custom allocator design"]
+#[unstable(feature = "alloc",
+           reason = "may be renamed; uncertain about custom allocator design")]
 pub static HEAP: () = ();
 
 /// A pointer type for heap allocation.
 ///
 /// See the [module-level documentation](../../std/boxed/index.html) for more.
 #[lang = "owned_box"]
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 pub struct Box<T>(Unique<T>);
 
 impl<T> Box<T> {
@@ -95,25 +96,25 @@ impl<T> Box<T> {
     /// ```
     /// let x = Box::new(5);
     /// ```
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     pub fn new(x: T) -> Box<T> {
         box x
     }
 }
 
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl<T: Default> Default for Box<T> {
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     fn default() -> Box<T> { box Default::default() }
 }
 
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl<T> Default for Box<[T]> {
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     fn default() -> Box<[T]> { box [] }
 }
 
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl<T: Clone> Clone for Box<T> {
     /// Returns a new box with a `clone()` of this box's contents.
     ///
@@ -144,14 +145,14 @@ impl<T: Clone> Clone for Box<T> {
     }
 }
 
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl<T: ?Sized + PartialEq> PartialEq for Box<T> {
     #[inline]
     fn eq(&self, other: &Box<T>) -> bool { PartialEq::eq(&**self, &**other) }
     #[inline]
     fn ne(&self, other: &Box<T>) -> bool { PartialEq::ne(&**self, &**other) }
 }
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl<T: ?Sized + PartialOrd> PartialOrd for Box<T> {
     #[inline]
     fn partial_cmp(&self, other: &Box<T>) -> Option<Ordering> {
@@ -166,14 +167,14 @@ impl<T: ?Sized + PartialOrd> PartialOrd for Box<T> {
     #[inline]
     fn gt(&self, other: &Box<T>) -> bool { PartialOrd::gt(&**self, &**other) }
 }
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl<T: ?Sized + Ord> Ord for Box<T> {
     #[inline]
     fn cmp(&self, other: &Box<T>) -> Ordering {
         Ord::cmp(&**self, &**other)
     }
 }
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl<T: ?Sized + Eq> Eq for Box<T> {}
 
 impl<S: hash::Hasher, T: ?Sized + Hash<S>> Hash<S> for Box<T> {
@@ -184,19 +185,20 @@ impl<S: hash::Hasher, T: ?Sized + Hash<S>> Hash<S> for Box<T> {
 }
 
 /// Extension methods for an owning `Any` trait object.
-#[unstable = "this trait will likely disappear once compiler bugs blocking \
-              a direct impl on `Box<Any>` have been fixed "]
+#[unstable(feature = "alloc",
+           reason = "this trait will likely disappear once compiler bugs blocking \
+                     a direct impl on `Box<Any>` have been fixed ")]
 // FIXME(#18737): this should be a direct impl on `Box<Any>`. If you're
 //                removing this please make sure that you can downcase on
 //                `Box<Any + Send>` as well as `Box<Any>`
 pub trait BoxAny {
     /// Returns the boxed value if it is of type `T`, or
     /// `Err(Self)` if it isn't.
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     fn downcast<T: 'static>(self) -> Result<Box<T>, Self>;
 }
 
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl BoxAny for Box<Any> {
     #[inline]
     fn downcast<T: 'static>(self) -> Result<Box<T>, Box<Any>> {
@@ -215,35 +217,35 @@ impl BoxAny for Box<Any> {
     }
 }
 
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl<T: fmt::Display + ?Sized> fmt::Display for Box<T> {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         fmt::Display::fmt(&**self, f)
     }
 }
 
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl<T: fmt::Debug + ?Sized> fmt::Debug for Box<T> {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         fmt::Debug::fmt(&**self, f)
     }
 }
 
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl fmt::Debug for Box<Any> {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         f.pad("Box<Any>")
     }
 }
 
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl<T: ?Sized> Deref for Box<T> {
     type Target = T;
 
     fn deref(&self) -> &T { &**self }
 }
 
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl<T: ?Sized> DerefMut for Box<T> {
     fn deref_mut(&mut self) -> &mut T { &mut **self }
 }
diff --git a/src/liballoc/heap.rs b/src/liballoc/heap.rs
index a2643f4d0f7..dcbd4d57cf9 100644
--- a/src/liballoc/heap.rs
+++ b/src/liballoc/heap.rs
@@ -80,7 +80,7 @@ pub fn usable_size(size: uint, align: uint) -> uint {
 ///
 /// These statistics may be inconsistent if other threads use the allocator
 /// during the call.
-#[unstable]
+#[unstable(feature = "alloc")]
 pub fn stats_print() {
     imp::stats_print();
 }
diff --git a/src/liballoc/lib.rs b/src/liballoc/lib.rs
index 231ef6e7e74..6830a1c33df 100644
--- a/src/liballoc/lib.rs
+++ b/src/liballoc/lib.rs
@@ -57,7 +57,8 @@
 //! default global allocator. It is not compatible with the libc allocator API.
 
 #![crate_name = "alloc"]
-#![unstable]
+#![unstable(feature = "alloc")]
+#![feature(staged_api)]
 #![staged_api]
 #![crate_type = "rlib"]
 #![doc(html_logo_url = "http://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
@@ -66,13 +67,15 @@
 
 #![no_std]
 #![allow(unknown_features)]
-#![allow(unstable)]
 #![feature(lang_items, unsafe_destructor)]
 #![feature(box_syntax)]
 #![feature(optin_builtin_traits)]
 // FIXME(#21363) remove `old_impl_check` when bug is fixed
 #![feature(old_impl_check)]
 #![allow(unknown_features)] #![feature(int_uint)]
+#![feature(core)]
+#![feature(hash)]
+#![feature(libc)]
 
 #[macro_use]
 extern crate core;
diff --git a/src/liballoc/rc.rs b/src/liballoc/rc.rs
index 5e82c4f1ade..d41673f56ed 100644
--- a/src/liballoc/rc.rs
+++ b/src/liballoc/rc.rs
@@ -142,7 +142,7 @@
 //! }
 //! ```
 
-#![stable]
+#![stable(feature = "rust1", since = "1.0.0")]
 
 use core::borrow::BorrowFrom;
 use core::cell::Cell;
@@ -173,7 +173,7 @@ struct RcBox<T> {
 ///
 /// See the [module level documentation](../index.html) for more details.
 #[unsafe_no_drop_flag]
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 pub struct Rc<T> {
     // FIXME #12808: strange names to try to avoid interfering with field accesses of the contained
     // type via Deref
@@ -185,7 +185,6 @@ impl<T> !marker::Send for Rc<T> {}
 impl<T> !marker::Sync for Rc<T> {}
 
 impl<T> Rc<T> {
-
     /// Constructs a new `Rc<T>`.
     ///
     /// # Examples
@@ -195,7 +194,7 @@ impl<T> Rc<T> {
     ///
     /// let five = Rc::new(5i);
     /// ```
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     pub fn new(value: T) -> Rc<T> {
         unsafe {
             Rc {
@@ -222,7 +221,8 @@ impl<T> Rc<T> {
     ///
     /// let weak_five = five.downgrade();
     /// ```
-    #[unstable = "Weak pointers may not belong in this module"]
+    #[unstable(feature = "alloc",
+               reason = "Weak pointers may not belong in this module")]
     pub fn downgrade(&self) -> Weak<T> {
         self.inc_weak();
         Weak { _ptr: self._ptr }
@@ -231,12 +231,12 @@ impl<T> Rc<T> {
 
 /// Get the number of weak references to this value.
 #[inline]
-#[unstable]
+#[unstable(feature = "alloc")]
 pub fn weak_count<T>(this: &Rc<T>) -> uint { this.weak() - 1 }
 
 /// Get the number of strong references to this value.
 #[inline]
-#[unstable]
+#[unstable(feature = "alloc")]
 pub fn strong_count<T>(this: &Rc<T>) -> uint { this.strong() }
 
 /// Returns true if there are no other `Rc` or `Weak<T>` values that share the same inner value.
@@ -252,7 +252,7 @@ pub fn strong_count<T>(this: &Rc<T>) -> uint { this.strong() }
 /// rc::is_unique(&five);
 /// ```
 #[inline]
-#[unstable]
+#[unstable(feature = "alloc")]
 pub fn is_unique<T>(rc: &Rc<T>) -> bool {
     weak_count(rc) == 0 && strong_count(rc) == 1
 }
@@ -274,7 +274,7 @@ pub fn is_unique<T>(rc: &Rc<T>) -> bool {
 /// assert_eq!(rc::try_unwrap(x), Err(Rc::new(4u)));
 /// ```
 #[inline]
-#[unstable]
+#[unstable(feature = "alloc")]
 pub fn try_unwrap<T>(rc: Rc<T>) -> Result<T, Rc<T>> {
     if is_unique(&rc) {
         unsafe {
@@ -308,7 +308,7 @@ pub fn try_unwrap<T>(rc: Rc<T>) -> Result<T, Rc<T>> {
 /// assert!(rc::get_mut(&mut x).is_none());
 /// ```
 #[inline]
-#[unstable]
+#[unstable(feature = "alloc")]
 pub fn get_mut<'a, T>(rc: &'a mut Rc<T>) -> Option<&'a mut T> {
     if is_unique(rc) {
         let inner = unsafe { &mut **rc._ptr };
@@ -334,7 +334,7 @@ impl<T: Clone> Rc<T> {
     /// let mut_five = five.make_unique();
     /// ```
     #[inline]
-    #[unstable]
+    #[unstable(feature = "alloc")]
     pub fn make_unique(&mut self) -> &mut T {
         if !is_unique(self) {
             *self = Rc::new((**self).clone())
@@ -354,7 +354,7 @@ impl<T> BorrowFrom<Rc<T>> for T {
     }
 }
 
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl<T> Deref for Rc<T> {
     type Target = T;
 
@@ -365,7 +365,7 @@ impl<T> Deref for Rc<T> {
 }
 
 #[unsafe_destructor]
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl<T> Drop for Rc<T> {
     /// Drops the `Rc<T>`.
     ///
@@ -413,7 +413,7 @@ impl<T> Drop for Rc<T> {
     }
 }
 
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl<T> Clone for Rc<T> {
 
     /// Makes a clone of the `Rc<T>`.
@@ -436,7 +436,7 @@ impl<T> Clone for Rc<T> {
     }
 }
 
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl<T: Default> Default for Rc<T> {
     /// Creates a new `Rc<T>`, with the `Default` value for `T`.
     ///
@@ -449,13 +449,13 @@ impl<T: Default> Default for Rc<T> {
     /// let x: Rc<int> = Default::default();
     /// ```
     #[inline]
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     fn default() -> Rc<T> {
         Rc::new(Default::default())
     }
 }
 
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl<T: PartialEq> PartialEq for Rc<T> {
     /// Equality for two `Rc<T>`s.
     ///
@@ -490,10 +490,10 @@ impl<T: PartialEq> PartialEq for Rc<T> {
     fn ne(&self, other: &Rc<T>) -> bool { **self != **other }
 }
 
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl<T: Eq> Eq for Rc<T> {}
 
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl<T: PartialOrd> PartialOrd for Rc<T> {
     /// Partial comparison for two `Rc<T>`s.
     ///
@@ -578,7 +578,7 @@ impl<T: PartialOrd> PartialOrd for Rc<T> {
     fn ge(&self, other: &Rc<T>) -> bool { **self >= **other }
 }
 
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl<T: Ord> Ord for Rc<T> {
     /// Comparison for two `Rc<T>`s.
     ///
@@ -605,14 +605,14 @@ impl<S: hash::Hasher, T: Hash<S>> Hash<S> for Rc<T> {
     }
 }
 
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl<T: fmt::Display> fmt::Display for Rc<T> {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         fmt::Display::fmt(&**self, f)
     }
 }
 
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl<T: fmt::Debug> fmt::Debug for Rc<T> {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         fmt::Debug::fmt(&**self, f)
@@ -625,21 +625,21 @@ impl<T: fmt::Debug> fmt::Debug for Rc<T> {
 ///
 /// See the [module level documentation](../index.html) for more.
 #[unsafe_no_drop_flag]
-#[unstable = "Weak pointers may not belong in this module."]
+#[unstable(feature = "alloc",
+           reason = "Weak pointers may not belong in this module.")]
 pub struct Weak<T> {
     // FIXME #12808: strange names to try to avoid interfering with
     // field accesses of the contained type via Deref
     _ptr: NonZero<*mut RcBox<T>>,
 }
 
-#[allow(unstable)]
 impl<T> !marker::Send for Weak<T> {}
 
-#[allow(unstable)]
 impl<T> !marker::Sync for Weak<T> {}
 
 
-#[unstable = "Weak pointers may not belong in this module."]
+#[unstable(feature = "alloc",
+           reason = "Weak pointers may not belong in this module.")]
 impl<T> Weak<T> {
 
     /// Upgrades a weak reference to a strong reference.
@@ -670,7 +670,7 @@ impl<T> Weak<T> {
 }
 
 #[unsafe_destructor]
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl<T> Drop for Weak<T> {
     /// Drops the `Weak<T>`.
     ///
@@ -713,7 +713,8 @@ impl<T> Drop for Weak<T> {
     }
 }
 
-#[unstable = "Weak pointers may not belong in this module."]
+#[unstable(feature = "alloc",
+           reason = "Weak pointers may not belong in this module.")]
 impl<T> Clone for Weak<T> {
 
     /// Makes a clone of the `Weak<T>`.
@@ -736,7 +737,7 @@ impl<T> Clone for Weak<T> {
     }
 }
 
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl<T: fmt::Debug> fmt::Debug for Weak<T> {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         write!(f, "(Weak)")
@@ -777,7 +778,6 @@ impl<T> RcBoxPtr<T> for Weak<T> {
 }
 
 #[cfg(test)]
-#[allow(unstable)]
 mod tests {
     use super::{Rc, Weak, weak_count, strong_count};
     use std::cell::RefCell;
diff --git a/src/libarena/lib.rs b/src/libarena/lib.rs
index 7458cc60c15..9396e2d6fb2 100644
--- a/src/libarena/lib.rs
+++ b/src/libarena/lib.rs
@@ -20,7 +20,8 @@
 //! more complex, slower arena which can hold objects of any type.
 
 #![crate_name = "arena"]
-#![unstable]
+#![unstable(feature = "rustc_private")]
+#![feature(staged_api)]
 #![staged_api]
 #![crate_type = "rlib"]
 #![crate_type = "dylib"]
@@ -34,7 +35,10 @@
 #![feature(box_syntax)]
 #![allow(unknown_features)] #![feature(int_uint)]
 #![allow(missing_docs)]
-#![allow(unstable)]
+#![feature(alloc)]
+#![feature(core)]
+#![cfg_attr(test, feature(test))]
+#![cfg_attr(test, feature(collections))]
 
 extern crate alloc;
 
diff --git a/src/libcollections/binary_heap.rs b/src/libcollections/binary_heap.rs
index 01693391abe..13a37882ed9 100644
--- a/src/libcollections/binary_heap.rs
+++ b/src/libcollections/binary_heap.rs
@@ -148,7 +148,7 @@
 //! ```
 
 #![allow(missing_docs)]
-#![stable]
+#![stable(feature = "rust1", since = "1.0.0")]
 
 use core::prelude::*;
 
@@ -164,12 +164,12 @@ use vec::{self, Vec};
 ///
 /// This will be a max-heap.
 #[derive(Clone)]
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 pub struct BinaryHeap<T> {
     data: Vec<T>,
 }
 
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl<T: Ord> Default for BinaryHeap<T> {
     #[inline]
     fn default() -> BinaryHeap<T> { BinaryHeap::new() }
@@ -185,7 +185,7 @@ impl<T: Ord> BinaryHeap<T> {
     /// let mut heap = BinaryHeap::new();
     /// heap.push(4u);
     /// ```
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     pub fn new() -> BinaryHeap<T> { BinaryHeap { data: vec![] } }
 
     /// Creates an empty `BinaryHeap` with a specific capacity.
@@ -200,7 +200,7 @@ impl<T: Ord> BinaryHeap<T> {
     /// let mut heap = BinaryHeap::with_capacity(10);
     /// heap.push(4u);
     /// ```
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     pub fn with_capacity(capacity: uint) -> BinaryHeap<T> {
         BinaryHeap { data: Vec::with_capacity(capacity) }
     }
@@ -238,7 +238,7 @@ impl<T: Ord> BinaryHeap<T> {
     ///     println!("{}", x);
     /// }
     /// ```
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     pub fn iter(&self) -> Iter<T> {
         Iter { iter: self.data.iter() }
     }
@@ -259,7 +259,7 @@ impl<T: Ord> BinaryHeap<T> {
     ///     println!("{}", x);
     /// }
     /// ```
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     pub fn into_iter(self) -> IntoIter<T> {
         IntoIter { iter: self.data.into_iter() }
     }
@@ -279,7 +279,7 @@ impl<T: Ord> BinaryHeap<T> {
     /// assert_eq!(heap.peek(), Some(&5));
     ///
     /// ```
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     pub fn peek(&self) -> Option<&T> {
         self.data.get(0)
     }
@@ -294,7 +294,7 @@ impl<T: Ord> BinaryHeap<T> {
     /// assert!(heap.capacity() >= 100);
     /// heap.push(4u);
     /// ```
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     pub fn capacity(&self) -> uint { self.data.capacity() }
 
     /// Reserves the minimum capacity for exactly `additional` more elements to be inserted in the
@@ -317,7 +317,7 @@ impl<T: Ord> BinaryHeap<T> {
     /// assert!(heap.capacity() >= 100);
     /// heap.push(4u);
     /// ```
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     pub fn reserve_exact(&mut self, additional: uint) {
         self.data.reserve_exact(additional);
     }
@@ -338,13 +338,13 @@ impl<T: Ord> BinaryHeap<T> {
     /// assert!(heap.capacity() >= 100);
     /// heap.push(4u);
     /// ```
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     pub fn reserve(&mut self, additional: uint) {
         self.data.reserve(additional);
     }
 
     /// Discards as much additional capacity as possible.
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     pub fn shrink_to_fit(&mut self) {
         self.data.shrink_to_fit();
     }
@@ -362,7 +362,7 @@ impl<T: Ord> BinaryHeap<T> {
     /// assert_eq!(heap.pop(), Some(1));
     /// assert_eq!(heap.pop(), None);
     /// ```
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     pub fn pop(&mut self) -> Option<T> {
         self.data.pop().map(|mut item| {
             if !self.is_empty() {
@@ -387,7 +387,7 @@ impl<T: Ord> BinaryHeap<T> {
     /// assert_eq!(heap.len(), 3);
     /// assert_eq!(heap.peek(), Some(&5));
     /// ```
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     pub fn push(&mut self, item: T) {
         let old_len = self.len();
         self.data.push(item);
@@ -542,40 +542,41 @@ impl<T: Ord> BinaryHeap<T> {
     }
 
     /// Returns the length of the binary heap.
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     pub fn len(&self) -> uint { self.data.len() }
 
     /// Checks if the binary heap is empty.
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     pub fn is_empty(&self) -> bool { self.len() == 0 }
 
     /// Clears the binary heap, returning an iterator over the removed elements.
     #[inline]
-    #[unstable = "matches collection reform specification, waiting for dust to settle"]
+    #[unstable(feature = "collections",
+               reason = "matches collection reform specification, waiting for dust to settle")]
     pub fn drain(&mut self) -> Drain<T> {
         Drain { iter: self.data.drain() }
     }
 
     /// Drops all items from the binary heap.
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     pub fn clear(&mut self) { self.drain(); }
 }
 
 /// `BinaryHeap` iterator.
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 pub struct Iter <'a, T: 'a> {
     iter: slice::Iter<'a, T>,
 }
 
 // FIXME(#19839) Remove in favor of `#[derive(Clone)]`
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl<'a, T> Clone for Iter<'a, T> {
     fn clone(&self) -> Iter<'a, T> {
         Iter { iter: self.iter.clone() }
     }
 }
 
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl<'a, T> Iterator for Iter<'a, T> {
     type Item = &'a T;
 
@@ -586,22 +587,22 @@ impl<'a, T> Iterator for Iter<'a, T> {
     fn size_hint(&self) -> (uint, Option<uint>) { self.iter.size_hint() }
 }
 
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl<'a, T> DoubleEndedIterator for Iter<'a, T> {
     #[inline]
     fn next_back(&mut self) -> Option<&'a T> { self.iter.next_back() }
 }
 
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl<'a, T> ExactSizeIterator for Iter<'a, T> {}
 
 /// An iterator that moves out of a `BinaryHeap`.
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 pub struct IntoIter<T> {
     iter: vec::IntoIter<T>,
 }
 
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl<T> Iterator for IntoIter<T> {
     type Item = T;
 
@@ -612,22 +613,22 @@ impl<T> Iterator for IntoIter<T> {
     fn size_hint(&self) -> (uint, Option<uint>) { self.iter.size_hint() }
 }
 
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl<T> DoubleEndedIterator for IntoIter<T> {
     #[inline]
     fn next_back(&mut self) -> Option<T> { self.iter.next_back() }
 }
 
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl<T> ExactSizeIterator for IntoIter<T> {}
 
 /// An iterator that drains a `BinaryHeap`.
-#[unstable = "recent addition"]
+#[unstable(feature = "collections", reason = "recent addition")]
 pub struct Drain<'a, T: 'a> {
     iter: vec::Drain<'a, T>,
 }
 
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl<'a, T: 'a> Iterator for Drain<'a, T> {
     type Item = T;
 
@@ -638,23 +639,23 @@ impl<'a, T: 'a> Iterator for Drain<'a, T> {
     fn size_hint(&self) -> (uint, Option<uint>) { self.iter.size_hint() }
 }
 
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl<'a, T: 'a> DoubleEndedIterator for Drain<'a, T> {
     #[inline]
     fn next_back(&mut self) -> Option<T> { self.iter.next_back() }
 }
 
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl<'a, T: 'a> ExactSizeIterator for Drain<'a, T> {}
 
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl<T: Ord> FromIterator<T> for BinaryHeap<T> {
     fn from_iter<Iter: Iterator<Item=T>>(iter: Iter) -> BinaryHeap<T> {
         BinaryHeap::from_vec(iter.collect())
     }
 }
 
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl<T: Ord> Extend<T> for BinaryHeap<T> {
     fn extend<Iter: Iterator<Item=T>>(&mut self, mut iter: Iter) {
         let (lower, _) = iter.size_hint();
diff --git a/src/libcollections/bit.rs b/src/libcollections/bit.rs
index 4c07f5b31e6..2c9a502a209 100644
--- a/src/libcollections/bit.rs
+++ b/src/libcollections/bit.rs
@@ -156,7 +156,8 @@ static FALSE: bool = false;
 /// println!("{:?}", bv);
 /// println!("total bits set to true: {}", bv.iter().filter(|x| *x).count());
 /// ```
-#[unstable = "RFC 509"]
+#[unstable(feature = "collections",
+           reason = "RFC 509")]
 pub struct Bitv {
     /// Internal representation of the bit vector
     storage: Vec<u32>,
@@ -252,7 +253,7 @@ impl Bitv {
     /// use std::collections::Bitv;
     /// let mut bv = Bitv::new();
     /// ```
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     pub fn new() -> Bitv {
         Bitv { storage: Vec::new(), nbits: 0 }
     }
@@ -288,7 +289,7 @@ impl Bitv {
     ///
     /// It is important to note that this function does not specify the
     /// *length* of the returned bitvector, but only the *capacity*.
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     pub fn with_capacity(nbits: uint) -> Bitv {
         Bitv {
             storage: Vec::with_capacity(blocks_for_bits(nbits)),
@@ -374,7 +375,7 @@ impl Bitv {
     /// assert_eq!(bv[1], true);
     /// ```
     #[inline]
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     pub fn get(&self, i: uint) -> Option<bool> {
         if i >= self.nbits {
             return None;
@@ -402,7 +403,8 @@ impl Bitv {
     /// assert_eq!(bv[3], true);
     /// ```
     #[inline]
-    #[unstable = "panic semantics are likely to change in the future"]
+    #[unstable(feature = "collections",
+               reason = "panic semantics are likely to change in the future")]
     pub fn set(&mut self, i: uint, x: bool) {
         assert!(i < self.nbits);
         let w = i / u32::BITS;
@@ -585,7 +587,7 @@ impl Bitv {
     /// assert_eq!(bv.iter().filter(|x| *x).count(), 7);
     /// ```
     #[inline]
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     pub fn iter(&self) -> Iter {
         Iter { bitv: self, next_idx: 0, end_idx: self.nbits }
     }
@@ -706,7 +708,7 @@ impl Bitv {
     /// bv.truncate(2);
     /// assert!(bv.eq_vec(&[false, true]));
     /// ```
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     pub fn truncate(&mut self, len: uint) {
         if len < self.len() {
             self.nbits = len;
@@ -733,7 +735,7 @@ impl Bitv {
     /// assert_eq!(bv.len(), 3);
     /// assert!(bv.capacity() >= 13);
     /// ```
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     pub fn reserve(&mut self, additional: uint) {
         let desired_cap = self.len().checked_add(additional).expect("capacity overflow");
         let storage_len = self.storage.len();
@@ -763,7 +765,7 @@ impl Bitv {
     /// assert_eq!(bv.len(), 3);
     /// assert!(bv.capacity() >= 13);
     /// ```
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     pub fn reserve_exact(&mut self, additional: uint) {
         let desired_cap = self.len().checked_add(additional).expect("capacity overflow");
         let storage_len = self.storage.len();
@@ -785,7 +787,7 @@ impl Bitv {
     /// assert!(bv.capacity() >= 10);
     /// ```
     #[inline]
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     pub fn capacity(&self) -> uint {
         self.storage.capacity().checked_mul(u32::BITS).unwrap_or(uint::MAX)
     }
@@ -856,7 +858,7 @@ impl Bitv {
     /// assert_eq!(bv.pop(), Some(false));
     /// assert_eq!(bv.len(), 6);
     /// ```
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     pub fn pop(&mut self) -> Option<bool> {
         if self.is_empty() {
             None
@@ -886,7 +888,7 @@ impl Bitv {
     /// bv.push(false);
     /// assert!(bv.eq_vec(&[true, false]));
     /// ```
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     pub fn push(&mut self, elem: bool) {
         if self.nbits % u32::BITS == 0 {
             self.storage.push(0);
@@ -898,29 +900,29 @@ impl Bitv {
 
     /// Return the total number of bits in this vector
     #[inline]
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     pub fn len(&self) -> uint { self.nbits }
 
     /// Returns true if there are no bits in this vector
     #[inline]
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     pub fn is_empty(&self) -> bool { self.len() == 0 }
 
     /// Clears all bits in this vector.
     #[inline]
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     pub fn clear(&mut self) {
         for w in self.storage.iter_mut() { *w = 0u32; }
     }
 }
 
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl Default for Bitv {
     #[inline]
     fn default() -> Bitv { Bitv::new() }
 }
 
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl FromIterator<bool> for Bitv {
     fn from_iter<I:Iterator<Item=bool>>(iterator: I) -> Bitv {
         let mut ret = Bitv::new();
@@ -929,7 +931,7 @@ impl FromIterator<bool> for Bitv {
     }
 }
 
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl Extend<bool> for Bitv {
     #[inline]
     fn extend<I: Iterator<Item=bool>>(&mut self, mut iterator: I) {
@@ -941,7 +943,7 @@ impl Extend<bool> for Bitv {
     }
 }
 
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl Clone for Bitv {
     #[inline]
     fn clone(&self) -> Bitv {
@@ -955,7 +957,7 @@ impl Clone for Bitv {
     }
 }
 
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl PartialOrd for Bitv {
     #[inline]
     fn partial_cmp(&self, other: &Bitv) -> Option<Ordering> {
@@ -963,7 +965,7 @@ impl PartialOrd for Bitv {
     }
 }
 
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl Ord for Bitv {
     #[inline]
     fn cmp(&self, other: &Bitv) -> Ordering {
@@ -971,7 +973,7 @@ impl Ord for Bitv {
     }
 }
 
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl fmt::Debug for Bitv {
     fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
         for bit in self.iter() {
@@ -981,7 +983,7 @@ impl fmt::Debug for Bitv {
     }
 }
 
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl<S: hash::Writer + hash::Hasher> hash::Hash<S> for Bitv {
     fn hash(&self, state: &mut S) {
         self.nbits.hash(state);
@@ -991,7 +993,7 @@ impl<S: hash::Writer + hash::Hasher> hash::Hash<S> for Bitv {
     }
 }
 
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl cmp::PartialEq for Bitv {
     #[inline]
     fn eq(&self, other: &Bitv) -> bool {
@@ -1002,11 +1004,11 @@ impl cmp::PartialEq for Bitv {
     }
 }
 
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl cmp::Eq for Bitv {}
 
 /// An iterator for `Bitv`.
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 #[derive(Clone)]
 pub struct Iter<'a> {
     bitv: &'a Bitv,
@@ -1014,7 +1016,7 @@ pub struct Iter<'a> {
     end_idx: uint,
 }
 
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl<'a> Iterator for Iter<'a> {
     type Item = bool;
 
@@ -1035,7 +1037,7 @@ impl<'a> Iterator for Iter<'a> {
     }
 }
 
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl<'a> DoubleEndedIterator for Iter<'a> {
     #[inline]
     fn next_back(&mut self) -> Option<bool> {
@@ -1048,10 +1050,10 @@ impl<'a> DoubleEndedIterator for Iter<'a> {
     }
 }
 
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl<'a> ExactSizeIterator for Iter<'a> {}
 
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl<'a> RandomAccessIterator for Iter<'a> {
     #[inline]
     fn indexable(&self) -> uint {
@@ -1107,18 +1109,19 @@ impl<'a> RandomAccessIterator for Iter<'a> {
 /// assert!(bv[3]);
 /// ```
 #[derive(Clone)]
-#[unstable = "RFC 509"]
+#[unstable(feature = "collections",
+           reason = "RFC 509")]
 pub struct BitvSet {
     bitv: Bitv,
 }
 
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl Default for BitvSet {
     #[inline]
     fn default() -> BitvSet { BitvSet::new() }
 }
 
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl FromIterator<uint> for BitvSet {
     fn from_iter<I:Iterator<Item=uint>>(iterator: I) -> BitvSet {
         let mut ret = BitvSet::new();
@@ -1127,7 +1130,7 @@ impl FromIterator<uint> for BitvSet {
     }
 }
 
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl Extend<uint> for BitvSet {
     #[inline]
     fn extend<I: Iterator<Item=uint>>(&mut self, mut iterator: I) {
@@ -1137,7 +1140,7 @@ impl Extend<uint> for BitvSet {
     }
 }
 
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl PartialOrd for BitvSet {
     #[inline]
     fn partial_cmp(&self, other: &BitvSet) -> Option<Ordering> {
@@ -1146,7 +1149,7 @@ impl PartialOrd for BitvSet {
     }
 }
 
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl Ord for BitvSet {
     #[inline]
     fn cmp(&self, other: &BitvSet) -> Ordering {
@@ -1155,7 +1158,7 @@ impl Ord for BitvSet {
     }
 }
 
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl cmp::PartialEq for BitvSet {
     #[inline]
     fn eq(&self, other: &BitvSet) -> bool {
@@ -1164,7 +1167,7 @@ impl cmp::PartialEq for BitvSet {
     }
 }
 
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl cmp::Eq for BitvSet {}
 
 impl BitvSet {
@@ -1178,7 +1181,7 @@ impl BitvSet {
     /// let mut s = BitvSet::new();
     /// ```
     #[inline]
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     pub fn new() -> BitvSet {
         BitvSet { bitv: Bitv::new() }
     }
@@ -1195,7 +1198,7 @@ impl BitvSet {
     /// assert!(s.capacity() >= 100);
     /// ```
     #[inline]
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     pub fn with_capacity(nbits: uint) -> BitvSet {
         let bitv = Bitv::from_elem(nbits, false);
         BitvSet::from_bitv(bitv)
@@ -1233,7 +1236,7 @@ impl BitvSet {
     /// assert!(s.capacity() >= 100);
     /// ```
     #[inline]
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     pub fn capacity(&self) -> uint {
         self.bitv.capacity()
     }
@@ -1254,7 +1257,7 @@ impl BitvSet {
     /// s.reserve_len(10);
     /// assert!(s.capacity() >= 10);
     /// ```
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     pub fn reserve_len(&mut self, len: uint) {
         let cur_len = self.bitv.len();
         if len >= cur_len {
@@ -1280,7 +1283,7 @@ impl BitvSet {
     /// s.reserve_len_exact(10);
     /// assert!(s.capacity() >= 10);
     /// ```
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     pub fn reserve_len_exact(&mut self, len: uint) {
         let cur_len = self.bitv.len();
         if len >= cur_len {
@@ -1374,7 +1377,7 @@ impl BitvSet {
     /// println!("new capacity: {}", s.capacity());
     /// ```
     #[inline]
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     pub fn shrink_to_fit(&mut self) {
         let bitv = &mut self.bitv;
         // Obtain original length
@@ -1402,7 +1405,7 @@ impl BitvSet {
     /// }
     /// ```
     #[inline]
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     pub fn iter(&self) -> bitv_set::Iter {
         SetIter {set: self, next_idx: 0u}
     }
@@ -1424,7 +1427,7 @@ impl BitvSet {
     /// }
     /// ```
     #[inline]
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     pub fn union<'a>(&'a self, other: &'a BitvSet) -> Union<'a> {
         fn or(w1: u32, w2: u32) -> u32 { w1 | w2 }
 
@@ -1454,7 +1457,7 @@ impl BitvSet {
     /// }
     /// ```
     #[inline]
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     pub fn intersection<'a>(&'a self, other: &'a BitvSet) -> Intersection<'a> {
         fn bitand(w1: u32, w2: u32) -> u32 { w1 & w2 }
         let min = cmp::min(self.bitv.len(), other.bitv.len());
@@ -1491,7 +1494,7 @@ impl BitvSet {
     /// }
     /// ```
     #[inline]
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     pub fn difference<'a>(&'a self, other: &'a BitvSet) -> Difference<'a> {
         fn diff(w1: u32, w2: u32) -> u32 { w1 & !w2 }
 
@@ -1522,7 +1525,7 @@ impl BitvSet {
     /// }
     /// ```
     #[inline]
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     pub fn symmetric_difference<'a>(&'a self, other: &'a BitvSet) -> SymmetricDifference<'a> {
         fn bitxor(w1: u32, w2: u32) -> u32 { w1 ^ w2 }
 
@@ -1639,28 +1642,28 @@ impl BitvSet {
 
     /// Return the number of set bits in this set.
     #[inline]
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     pub fn len(&self) -> uint  {
         self.bitv.blocks().fold(0, |acc, n| acc + n.count_ones())
     }
 
     /// Returns whether there are no bits set in this set
     #[inline]
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     pub fn is_empty(&self) -> bool {
         self.bitv.none()
     }
 
     /// Clears all bits in this set
     #[inline]
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     pub fn clear(&mut self) {
         self.bitv.clear();
     }
 
     /// Returns `true` if this set contains the specified integer.
     #[inline]
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     pub fn contains(&self, value: &uint) -> bool {
         let bitv = &self.bitv;
         *value < bitv.nbits && bitv[*value]
@@ -1669,14 +1672,14 @@ impl BitvSet {
     /// Returns `true` if the set has no elements in common with `other`.
     /// This is equivalent to checking for an empty intersection.
     #[inline]
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     pub fn is_disjoint(&self, other: &BitvSet) -> bool {
         self.intersection(other).next().is_none()
     }
 
     /// Returns `true` if the set is a subset of another.
     #[inline]
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     pub fn is_subset(&self, other: &BitvSet) -> bool {
         let self_bitv = &self.bitv;
         let other_bitv = &other.bitv;
@@ -1690,14 +1693,14 @@ impl BitvSet {
 
     /// Returns `true` if the set is a superset of another.
     #[inline]
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     pub fn is_superset(&self, other: &BitvSet) -> bool {
         other.is_subset(self)
     }
 
     /// Adds a value to the set. Returns `true` if the value was not already
     /// present in the set.
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     pub fn insert(&mut self, value: uint) -> bool {
         if self.contains(&value) {
             return false;
@@ -1715,7 +1718,7 @@ impl BitvSet {
 
     /// Removes a value from the set. Returns `true` if the value was
     /// present in the set.
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     pub fn remove(&mut self, value: &uint) -> bool {
         if !self.contains(value) {
             return false;
@@ -1752,7 +1755,7 @@ impl<S: hash::Writer + hash::Hasher> hash::Hash<S> for BitvSet {
 
 /// An iterator for `BitvSet`.
 #[derive(Clone)]
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 pub struct SetIter<'a> {
     set: &'a BitvSet,
     next_idx: uint
@@ -1768,16 +1771,16 @@ struct TwoBitPositions<'a> {
     next_idx: uint
 }
 
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 pub struct Union<'a>(TwoBitPositions<'a>);
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 pub struct Intersection<'a>(Take<TwoBitPositions<'a>>);
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 pub struct Difference<'a>(TwoBitPositions<'a>);
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 pub struct SymmetricDifference<'a>(TwoBitPositions<'a>);
 
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl<'a> Iterator for SetIter<'a> {
     type Item = uint;
 
@@ -1800,7 +1803,7 @@ impl<'a> Iterator for SetIter<'a> {
     }
 }
 
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl<'a> Iterator for TwoBitPositions<'a> {
     type Item = uint;
 
@@ -1838,7 +1841,7 @@ impl<'a> Iterator for TwoBitPositions<'a> {
     }
 }
 
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl<'a> Iterator for Union<'a> {
     type Item = uint;
 
@@ -1846,7 +1849,7 @@ impl<'a> Iterator for Union<'a> {
     #[inline] fn size_hint(&self) -> (uint, Option<uint>) { self.0.size_hint() }
 }
 
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl<'a> Iterator for Intersection<'a> {
     type Item = uint;
 
@@ -1854,7 +1857,7 @@ impl<'a> Iterator for Intersection<'a> {
     #[inline] fn size_hint(&self) -> (uint, Option<uint>) { self.0.size_hint() }
 }
 
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl<'a> Iterator for Difference<'a> {
     type Item = uint;
 
@@ -1862,7 +1865,7 @@ impl<'a> Iterator for Difference<'a> {
     #[inline] fn size_hint(&self) -> (uint, Option<uint>) { self.0.size_hint() }
 }
 
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl<'a> Iterator for SymmetricDifference<'a> {
     type Item = uint;
 
diff --git a/src/libcollections/btree/map.rs b/src/libcollections/btree/map.rs
index 8c2f00a5695..17d26ed1a21 100644
--- a/src/libcollections/btree/map.rs
+++ b/src/libcollections/btree/map.rs
@@ -81,7 +81,7 @@ use super::node::{self, Node, Found, GoDown};
 /// done on each operation isn't *catastrophic*, and *is* still bounded by O(B log<sub>B</sub>n),
 /// it is certainly much slower when it does.
 #[derive(Clone)]
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 pub struct BTreeMap<K, V> {
     root: Node<K, V>,
     length: uint,
@@ -96,31 +96,31 @@ struct AbsIter<T> {
 }
 
 /// An iterator over a BTreeMap's entries.
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 pub struct Iter<'a, K: 'a, V: 'a> {
     inner: AbsIter<Traversal<'a, K, V>>
 }
 
 /// A mutable iterator over a BTreeMap's entries.
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 pub struct IterMut<'a, K: 'a, V: 'a> {
     inner: AbsIter<MutTraversal<'a, K, V>>
 }
 
 /// An owning iterator over a BTreeMap's entries.
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 pub struct IntoIter<K, V> {
     inner: AbsIter<MoveTraversal<K, V>>
 }
 
 /// An iterator over a BTreeMap's keys.
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 pub struct Keys<'a, K: 'a, V: 'a> {
     inner: Map<(&'a K, &'a V), &'a K, Iter<'a, K, V>, fn((&'a K, &'a V)) -> &'a K>
 }
 
 /// An iterator over a BTreeMap's values.
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 pub struct Values<'a, K: 'a, V: 'a> {
     inner: Map<(&'a K, &'a V), &'a V, Iter<'a, K, V>, fn((&'a K, &'a V)) -> &'a V>
 }
@@ -136,7 +136,8 @@ pub struct RangeMut<'a, K: 'a, V: 'a> {
 }
 
 /// A view into a single entry in a map, which may either be vacant or occupied.
-#[unstable = "precise API still under development"]
+#[unstable(feature = "collections",
+           reason = "precise API still under development")]
 pub enum Entry<'a, K:'a, V:'a> {
     /// A vacant Entry
     Vacant(VacantEntry<'a, K, V>),
@@ -145,21 +146,23 @@ pub enum Entry<'a, K:'a, V:'a> {
 }
 
 /// A vacant Entry.
-#[unstable = "precise API still under development"]
+#[unstable(feature = "collections",
+           reason = "precise API still under development")]
 pub struct VacantEntry<'a, K:'a, V:'a> {
     key: K,
     stack: stack::SearchStack<'a, K, V, node::handle::Edge, node::handle::Leaf>,
 }
 
 /// An occupied Entry.
-#[unstable = "precise API still under development"]
+#[unstable(feature = "collections",
+           reason = "precise API still under development")]
 pub struct OccupiedEntry<'a, K:'a, V:'a> {
     stack: stack::SearchStack<'a, K, V, node::handle::KV, node::handle::LeafOrInternal>,
 }
 
 impl<K: Ord, V> BTreeMap<K, V> {
     /// Makes a new empty BTreeMap with a reasonable choice for B.
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     pub fn new() -> BTreeMap<K, V> {
         //FIXME(Gankro): Tune this as a function of size_of<K/V>?
         BTreeMap::with_b(6)
@@ -190,7 +193,7 @@ impl<K: Ord, V> BTreeMap<K, V> {
     /// a.clear();
     /// assert!(a.is_empty());
     /// ```
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     pub fn clear(&mut self) {
         let b = self.b;
         // avoid recursive destructors by manually traversing the tree
@@ -220,7 +223,7 @@ impl<K: Ord, V> BTreeMap<K, V> {
     /// assert_eq!(map.get(&1), Some(&"a"));
     /// assert_eq!(map.get(&2), None);
     /// ```
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     pub fn get<Q: ?Sized>(&self, key: &Q) -> Option<&V> where Q: BorrowFrom<K> + Ord {
         let mut cur_node = &self.root;
         loop {
@@ -252,7 +255,7 @@ impl<K: Ord, V> BTreeMap<K, V> {
     /// assert_eq!(map.contains_key(&1), true);
     /// assert_eq!(map.contains_key(&2), false);
     /// ```
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     pub fn contains_key<Q: ?Sized>(&self, key: &Q) -> bool where Q: BorrowFrom<K> + Ord {
         self.get(key).is_some()
     }
@@ -276,7 +279,7 @@ impl<K: Ord, V> BTreeMap<K, V> {
     /// assert_eq!(map[1], "b");
     /// ```
     // See `get` for implementation notes, this is basically a copy-paste with mut's added
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     pub fn get_mut<Q: ?Sized>(&mut self, key: &Q) -> Option<&mut V> where Q: BorrowFrom<K> + Ord {
         // temp_node is a Borrowck hack for having a mutable value outlive a loop iteration
         let mut temp_node = &mut self.root;
@@ -337,7 +340,7 @@ impl<K: Ord, V> BTreeMap<K, V> {
     /// assert_eq!(map.insert(37, "c"), Some("b"));
     /// assert_eq!(map[37], "c");
     /// ```
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     pub fn insert(&mut self, mut key: K, mut value: V) -> Option<V> {
         // This is a stack of rawptrs to nodes paired with indices, respectively
         // representing the nodes and edges of our search path. We have to store rawptrs
@@ -446,7 +449,7 @@ impl<K: Ord, V> BTreeMap<K, V> {
     /// assert_eq!(map.remove(&1), Some("a"));
     /// assert_eq!(map.remove(&1), None);
     /// ```
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     pub fn remove<Q: ?Sized>(&mut self, key: &Q) -> Option<V> where Q: BorrowFrom<K> + Ord {
         // See `swap` for a more thorough description of the stuff going on in here
         let mut stack = stack::PartialSearchStack::new(self);
@@ -807,7 +810,7 @@ mod stack {
     }
 }
 
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl<K: Ord, V> FromIterator<(K, V)> for BTreeMap<K, V> {
     fn from_iter<T: Iterator<Item=(K, V)>>(iter: T) -> BTreeMap<K, V> {
         let mut map = BTreeMap::new();
@@ -816,7 +819,7 @@ impl<K: Ord, V> FromIterator<(K, V)> for BTreeMap<K, V> {
     }
 }
 
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl<K: Ord, V> Extend<(K, V)> for BTreeMap<K, V> {
     #[inline]
     fn extend<T: Iterator<Item=(K, V)>>(&mut self, mut iter: T) {
@@ -826,7 +829,7 @@ impl<K: Ord, V> Extend<(K, V)> for BTreeMap<K, V> {
     }
 }
 
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl<S: Hasher, K: Hash<S>, V: Hash<S>> Hash<S> for BTreeMap<K, V> {
     fn hash(&self, state: &mut S) {
         for elt in self.iter() {
@@ -835,15 +838,15 @@ impl<S: Hasher, K: Hash<S>, V: Hash<S>> Hash<S> for BTreeMap<K, V> {
     }
 }
 
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl<K: Ord, V> Default for BTreeMap<K, V> {
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     fn default() -> BTreeMap<K, V> {
         BTreeMap::new()
     }
 }
 
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl<K: PartialEq, V: PartialEq> PartialEq for BTreeMap<K, V> {
     fn eq(&self, other: &BTreeMap<K, V>) -> bool {
         self.len() == other.len() &&
@@ -851,10 +854,10 @@ impl<K: PartialEq, V: PartialEq> PartialEq for BTreeMap<K, V> {
     }
 }
 
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl<K: Eq, V: Eq> Eq for BTreeMap<K, V> {}
 
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl<K: PartialOrd, V: PartialOrd> PartialOrd for BTreeMap<K, V> {
     #[inline]
     fn partial_cmp(&self, other: &BTreeMap<K, V>) -> Option<Ordering> {
@@ -862,7 +865,7 @@ impl<K: PartialOrd, V: PartialOrd> PartialOrd for BTreeMap<K, V> {
     }
 }
 
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl<K: Ord, V: Ord> Ord for BTreeMap<K, V> {
     #[inline]
     fn cmp(&self, other: &BTreeMap<K, V>) -> Ordering {
@@ -870,7 +873,7 @@ impl<K: Ord, V: Ord> Ord for BTreeMap<K, V> {
     }
 }
 
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl<K: Debug, V: Debug> Debug for BTreeMap<K, V> {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         try!(write!(f, "BTreeMap {{"));
@@ -884,7 +887,7 @@ impl<K: Debug, V: Debug> Debug for BTreeMap<K, V> {
     }
 }
 
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl<K: Ord, Q: ?Sized, V> Index<Q> for BTreeMap<K, V>
     where Q: BorrowFrom<K> + Ord
 {
@@ -895,7 +898,7 @@ impl<K: Ord, Q: ?Sized, V> Index<Q> for BTreeMap<K, V>
     }
 }
 
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl<K: Ord, Q: ?Sized, V> IndexMut<Q> for BTreeMap<K, V>
     where Q: BorrowFrom<K> + Ord
 {
@@ -1006,75 +1009,75 @@ impl<K, V, E, T> DoubleEndedIterator for AbsIter<T> where
     }
 }
 
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl<'a, K, V> Iterator for Iter<'a, K, V> {
     type Item = (&'a K, &'a V);
 
     fn next(&mut self) -> Option<(&'a K, &'a V)> { self.inner.next() }
     fn size_hint(&self) -> (uint, Option<uint>) { self.inner.size_hint() }
 }
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl<'a, K, V> DoubleEndedIterator for Iter<'a, K, V> {
     fn next_back(&mut self) -> Option<(&'a K, &'a V)> { self.inner.next_back() }
 }
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl<'a, K, V> ExactSizeIterator for Iter<'a, K, V> {}
 
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl<'a, K, V> Iterator for IterMut<'a, K, V> {
     type Item = (&'a K, &'a mut V);
 
     fn next(&mut self) -> Option<(&'a K, &'a mut V)> { self.inner.next() }
     fn size_hint(&self) -> (uint, Option<uint>) { self.inner.size_hint() }
 }
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl<'a, K, V> DoubleEndedIterator for IterMut<'a, K, V> {
     fn next_back(&mut self) -> Option<(&'a K, &'a mut V)> { self.inner.next_back() }
 }
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl<'a, K, V> ExactSizeIterator for IterMut<'a, K, V> {}
 
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl<K, V> Iterator for IntoIter<K, V> {
     type Item = (K, V);
 
     fn next(&mut self) -> Option<(K, V)> { self.inner.next() }
     fn size_hint(&self) -> (uint, Option<uint>) { self.inner.size_hint() }
 }
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl<K, V> DoubleEndedIterator for IntoIter<K, V> {
     fn next_back(&mut self) -> Option<(K, V)> { self.inner.next_back() }
 }
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl<K, V> ExactSizeIterator for IntoIter<K, V> {}
 
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl<'a, K, V> Iterator for Keys<'a, K, V> {
     type Item = &'a K;
 
     fn next(&mut self) -> Option<(&'a K)> { self.inner.next() }
     fn size_hint(&self) -> (uint, Option<uint>) { self.inner.size_hint() }
 }
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl<'a, K, V> DoubleEndedIterator for Keys<'a, K, V> {
     fn next_back(&mut self) -> Option<(&'a K)> { self.inner.next_back() }
 }
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl<'a, K, V> ExactSizeIterator for Keys<'a, K, V> {}
 
 
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl<'a, K, V> Iterator for Values<'a, K, V> {
     type Item = &'a V;
 
     fn next(&mut self) -> Option<(&'a V)> { self.inner.next() }
     fn size_hint(&self) -> (uint, Option<uint>) { self.inner.size_hint() }
 }
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl<'a, K, V> DoubleEndedIterator for Values<'a, K, V> {
     fn next_back(&mut self) -> Option<(&'a V)> { self.inner.next_back() }
 }
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl<'a, K, V> ExactSizeIterator for Values<'a, K, V> {}
 
 impl<'a, K, V> Iterator for Range<'a, K, V> {
@@ -1096,7 +1099,8 @@ impl<'a, K, V> DoubleEndedIterator for RangeMut<'a, K, V> {
 }
 
 impl<'a, K: Ord, V> Entry<'a, K, V> {
-    #[unstable = "matches collection reform v2 specification, waiting for dust to settle"]
+    #[unstable(feature = "collections",
+               reason = "matches collection reform v2 specification, waiting for dust to settle")]
     /// Returns a mutable reference to the entry if occupied, or the VacantEntry if vacant
     pub fn get(self) -> Result<&'a mut V, VacantEntry<'a, K, V>> {
         match self {
@@ -1109,7 +1113,8 @@ impl<'a, K: Ord, V> Entry<'a, K, V> {
 impl<'a, K: Ord, V> VacantEntry<'a, K, V> {
     /// Sets the value of the entry with the VacantEntry's key,
     /// and returns a mutable reference to it.
-    #[unstable = "matches collection reform v2 specification, waiting for dust to settle"]
+    #[unstable(feature = "collections",
+               reason = "matches collection reform v2 specification, waiting for dust to settle")]
     pub fn insert(self, value: V) -> &'a mut V {
         self.stack.insert(self.key, value)
     }
@@ -1117,33 +1122,38 @@ impl<'a, K: Ord, V> VacantEntry<'a, K, V> {
 
 impl<'a, K: Ord, V> OccupiedEntry<'a, K, V> {
     /// Gets a reference to the value in the entry.
-    #[unstable = "matches collection reform v2 specification, waiting for dust to settle"]
+    #[unstable(feature = "collections",
+               reason = "matches collection reform v2 specification, waiting for dust to settle")]
     pub fn get(&self) -> &V {
         self.stack.peek()
     }
 
     /// Gets a mutable reference to the value in the entry.
-    #[unstable = "matches collection reform v2 specification, waiting for dust to settle"]
+    #[unstable(feature = "collections",
+               reason = "matches collection reform v2 specification, waiting for dust to settle")]
     pub fn get_mut(&mut self) -> &mut V {
         self.stack.peek_mut()
     }
 
     /// Converts the entry into a mutable reference to its value.
-    #[unstable = "matches collection reform v2 specification, waiting for dust to settle"]
+    #[unstable(feature = "collections",
+               reason = "matches collection reform v2 specification, waiting for dust to settle")]
     pub fn into_mut(self) -> &'a mut V {
         self.stack.into_top()
     }
 
     /// Sets the value of the entry with the OccupiedEntry's key,
     /// and returns the entry's old value.
-    #[unstable = "matches collection reform v2 specification, waiting for dust to settle"]
+    #[unstable(feature = "collections",
+               reason = "matches collection reform v2 specification, waiting for dust to settle")]
     pub fn insert(&mut self, mut value: V) -> V {
         mem::swap(self.stack.peek_mut(), &mut value);
         value
     }
 
     /// Takes the value of the entry out of the map, and returns it.
-    #[unstable = "matches collection reform v2 specification, waiting for dust to settle"]
+    #[unstable(feature = "collections",
+               reason = "matches collection reform v2 specification, waiting for dust to settle")]
     pub fn remove(self) -> V {
         self.stack.remove()
     }
@@ -1169,7 +1179,7 @@ impl<K, V> BTreeMap<K, V> {
     /// let (first_key, first_value) = map.iter().next().unwrap();
     /// assert_eq!((*first_key, *first_value), (1u, "a"));
     /// ```
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     pub fn iter(&self) -> Iter<K, V> {
         let len = self.len();
         // NB. The initial capacity for ringbuf is large enough to avoid reallocs in many cases.
@@ -1202,7 +1212,7 @@ impl<K, V> BTreeMap<K, V> {
     ///     }
     /// }
     /// ```
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     pub fn iter_mut(&mut self) -> IterMut<K, V> {
         let len = self.len();
         let mut lca = RingBuf::new();
@@ -1231,7 +1241,7 @@ impl<K, V> BTreeMap<K, V> {
     ///     println!("{}: {}", key, value);
     /// }
     /// ```
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     pub fn into_iter(self) -> IntoIter<K, V> {
         let len = self.len();
         let mut lca = RingBuf::new();
@@ -1258,7 +1268,7 @@ impl<K, V> BTreeMap<K, V> {
     /// let keys: Vec<uint> = a.keys().cloned().collect();
     /// assert_eq!(keys, vec![1u,2,]);
     /// ```
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     pub fn keys<'a>(&'a self) -> Keys<'a, K, V> {
         fn first<A, B>((a, _): (A, B)) -> A { a }
         let first: fn((&'a K, &'a V)) -> &'a K = first; // coerce to fn pointer
@@ -1280,7 +1290,7 @@ impl<K, V> BTreeMap<K, V> {
     /// let values: Vec<&str> = a.values().cloned().collect();
     /// assert_eq!(values, vec!["a","b"]);
     /// ```
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     pub fn values<'a>(&'a self) -> Values<'a, K, V> {
         fn second<A, B>((_, b): (A, B)) -> B { b }
         let second: fn((&'a K, &'a V)) -> &'a V = second; // coerce to fn pointer
@@ -1300,7 +1310,7 @@ impl<K, V> BTreeMap<K, V> {
     /// a.insert(1u, "a");
     /// assert_eq!(a.len(), 1);
     /// ```
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     pub fn len(&self) -> uint { self.length }
 
     /// Return true if the map contains no elements.
@@ -1315,7 +1325,7 @@ impl<K, V> BTreeMap<K, V> {
     /// a.insert(1u, "a");
     /// assert!(!a.is_empty());
     /// ```
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     pub fn is_empty(&self) -> bool { self.len() == 0 }
 }
 
@@ -1470,7 +1480,8 @@ impl<K: Ord, V> BTreeMap<K, V> {
     /// }
     /// assert_eq!(Some((&5u, &"b")), map.range(Included(&4), Unbounded).next());
     /// ```
-    #[unstable = "matches collection reform specification, waiting for dust to settle"]
+    #[unstable(feature = "collections",
+               reason = "matches collection reform specification, waiting for dust to settle")]
     pub fn range<'a>(&'a self, min: Bound<&K>, max: Bound<&K>) -> Range<'a, K, V> {
         range_impl!(&self.root, min, max, as_slices_internal, iter, Range, edges, [])
     }
@@ -1496,7 +1507,8 @@ impl<K: Ord, V> BTreeMap<K, V> {
     ///     println!("{} => {}", name, balance);
     /// }
     /// ```
-    #[unstable = "matches collection reform specification, waiting for dust to settle"]
+    #[unstable(feature = "collections",
+               reason = "matches collection reform specification, waiting for dust to settle")]
     pub fn range_mut<'a>(&'a mut self, min: Bound<&K>, max: Bound<&K>) -> RangeMut<'a, K, V> {
         range_impl!(&mut self.root, min, max, as_slices_internal_mut, iter_mut, RangeMut,
                                                                       edges_mut, [mut])
@@ -1528,7 +1540,8 @@ impl<K: Ord, V> BTreeMap<K, V> {
     /// assert_eq!(count["a"], 3u);
     /// ```
     /// The key must have the same ordering before or after `.to_owned()` is called.
-    #[unstable = "precise API still under development"]
+    #[unstable(feature = "collections",
+               reason = "precise API still under development")]
     pub fn entry<'a>(&'a mut self, mut key: K) -> Entry<'a, K, V> {
         // same basic logic of `swap` and `pop`, blended together
         let mut stack = stack::PartialSearchStack::new(self);
diff --git a/src/libcollections/btree/node.rs b/src/libcollections/btree/node.rs
index 50857c78469..95e424fb7a0 100644
--- a/src/libcollections/btree/node.rs
+++ b/src/libcollections/btree/node.rs
@@ -420,7 +420,7 @@ impl<K, V> Node<K, V> {
 }
 
 // FIXME(gereeter) Write an efficient clone_from
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl<K: Clone, V: Clone> Clone for Node<K, V> {
     fn clone(&self) -> Node<K, V> {
         let mut ret = if self.is_leaf() {
diff --git a/src/libcollections/btree/set.rs b/src/libcollections/btree/set.rs
index d307b7dbde7..a090e4f24ce 100644
--- a/src/libcollections/btree/set.rs
+++ b/src/libcollections/btree/set.rs
@@ -31,19 +31,19 @@ use Bound;
 /// See BTreeMap's documentation for a detailed discussion of this collection's performance
 /// benefits and drawbacks.
 #[derive(Clone, Hash, PartialEq, Eq, Ord, PartialOrd)]
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 pub struct BTreeSet<T>{
     map: BTreeMap<T, ()>,
 }
 
 /// An iterator over a BTreeSet's items.
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 pub struct Iter<'a, T: 'a> {
     iter: Keys<'a, T, ()>
 }
 
 /// An owning iterator over a BTreeSet's items.
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 pub struct IntoIter<T> {
     iter: Map<(T, ()), T, ::btree_map::IntoIter<T, ()>, fn((T, ())) -> T>
 }
@@ -54,28 +54,28 @@ pub struct Range<'a, T: 'a> {
 }
 
 /// A lazy iterator producing elements in the set difference (in-order).
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 pub struct Difference<'a, T:'a> {
     a: Peekable<&'a T, Iter<'a, T>>,
     b: Peekable<&'a T, Iter<'a, T>>,
 }
 
 /// A lazy iterator producing elements in the set symmetric difference (in-order).
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 pub struct SymmetricDifference<'a, T:'a> {
     a: Peekable<&'a T, Iter<'a, T>>,
     b: Peekable<&'a T, Iter<'a, T>>,
 }
 
 /// A lazy iterator producing elements in the set intersection (in-order).
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 pub struct Intersection<'a, T:'a> {
     a: Peekable<&'a T, Iter<'a, T>>,
     b: Peekable<&'a T, Iter<'a, T>>,
 }
 
 /// A lazy iterator producing elements in the set union (in-order).
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 pub struct Union<'a, T:'a> {
     a: Peekable<&'a T, Iter<'a, T>>,
     b: Peekable<&'a T, Iter<'a, T>>,
@@ -91,7 +91,7 @@ impl<T: Ord> BTreeSet<T> {
     ///
     /// let mut set: BTreeSet<int> = BTreeSet::new();
     /// ```
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     pub fn new() -> BTreeSet<T> {
         BTreeSet { map: BTreeMap::new() }
     }
@@ -99,7 +99,8 @@ impl<T: Ord> BTreeSet<T> {
     /// Makes a new BTreeSet with the given B.
     ///
     /// B cannot be less than 2.
-    #[unstable = "probably want this to be on the type, eventually"]
+    #[unstable(feature = "collections",
+               reason = "probably want this to be on the type, eventually")]
     pub fn with_b(b: uint) -> BTreeSet<T> {
         BTreeSet { map: BTreeMap::with_b(b) }
     }
@@ -122,7 +123,7 @@ impl<T> BTreeSet<T> {
     /// let v: Vec<uint> = set.iter().map(|&x| x).collect();
     /// assert_eq!(v, vec![1u,2,3,4]);
     /// ```
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     pub fn iter(&self) -> Iter<T> {
         Iter { iter: self.map.keys() }
     }
@@ -139,7 +140,7 @@ impl<T> BTreeSet<T> {
     /// let v: Vec<uint> = set.into_iter().collect();
     /// assert_eq!(v, vec![1u,2,3,4]);
     /// ```
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     pub fn into_iter(self) -> IntoIter<T> {
         fn first<A, B>((a, _): (A, B)) -> A { a }
         let first: fn((T, ())) -> T = first; // coerce to fn pointer
@@ -169,7 +170,8 @@ impl<T: Ord> BTreeSet<T> {
     /// }
     /// assert_eq!(Some(&5u), set.range(Included(&4), Unbounded).next());
     /// ```
-    #[unstable = "matches collection reform specification, waiting for dust to settle"]
+    #[unstable(feature = "collections",
+               reason = "matches collection reform specification, waiting for dust to settle")]
     pub fn range<'a>(&'a self, min: Bound<&T>, max: Bound<&T>) -> Range<'a, T> {
         fn first<A, B>((a, _): (A, B)) -> A { a }
         let first: fn((&'a T, &'a ())) -> &'a T = first; // coerce to fn pointer
@@ -197,7 +199,7 @@ impl<T: Ord> BTreeSet<T> {
     /// let diff: Vec<uint> = a.difference(&b).cloned().collect();
     /// assert_eq!(diff, vec![1u]);
     /// ```
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     pub fn difference<'a>(&'a self, other: &'a BTreeSet<T>) -> Difference<'a, T> {
         Difference{a: self.iter().peekable(), b: other.iter().peekable()}
     }
@@ -220,7 +222,7 @@ impl<T: Ord> BTreeSet<T> {
     /// let sym_diff: Vec<uint> = a.symmetric_difference(&b).cloned().collect();
     /// assert_eq!(sym_diff, vec![1u,3]);
     /// ```
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     pub fn symmetric_difference<'a>(&'a self, other: &'a BTreeSet<T>)
         -> SymmetricDifference<'a, T> {
         SymmetricDifference{a: self.iter().peekable(), b: other.iter().peekable()}
@@ -244,7 +246,7 @@ impl<T: Ord> BTreeSet<T> {
     /// let intersection: Vec<uint> = a.intersection(&b).cloned().collect();
     /// assert_eq!(intersection, vec![2u]);
     /// ```
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     pub fn intersection<'a>(&'a self, other: &'a BTreeSet<T>)
         -> Intersection<'a, T> {
         Intersection{a: self.iter().peekable(), b: other.iter().peekable()}
@@ -266,7 +268,7 @@ impl<T: Ord> BTreeSet<T> {
     /// let union: Vec<uint> = a.union(&b).cloned().collect();
     /// assert_eq!(union, vec![1u,2]);
     /// ```
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     pub fn union<'a>(&'a self, other: &'a BTreeSet<T>) -> Union<'a, T> {
         Union{a: self.iter().peekable(), b: other.iter().peekable()}
     }
@@ -283,7 +285,7 @@ impl<T: Ord> BTreeSet<T> {
     /// v.insert(1i);
     /// assert_eq!(v.len(), 1);
     /// ```
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     pub fn len(&self) -> uint { self.map.len() }
 
     /// Returns true if the set contains no elements
@@ -298,7 +300,7 @@ impl<T: Ord> BTreeSet<T> {
     /// v.insert(1i);
     /// assert!(!v.is_empty());
     /// ```
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     pub fn is_empty(&self) -> bool { self.len() == 0 }
 
     /// Clears the set, removing all values.
@@ -313,7 +315,7 @@ impl<T: Ord> BTreeSet<T> {
     /// v.clear();
     /// assert!(v.is_empty());
     /// ```
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     pub fn clear(&mut self) {
         self.map.clear()
     }
@@ -333,7 +335,7 @@ impl<T: Ord> BTreeSet<T> {
     /// assert_eq!(set.contains(&1), true);
     /// assert_eq!(set.contains(&4), false);
     /// ```
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     pub fn contains<Q: ?Sized>(&self, value: &Q) -> bool where Q: BorrowFrom<T> + Ord {
         self.map.contains_key(value)
     }
@@ -355,7 +357,7 @@ impl<T: Ord> BTreeSet<T> {
     /// b.insert(1);
     /// assert_eq!(a.is_disjoint(&b), false);
     /// ```
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     pub fn is_disjoint(&self, other: &BTreeSet<T>) -> bool {
         self.intersection(other).next().is_none()
     }
@@ -376,7 +378,7 @@ impl<T: Ord> BTreeSet<T> {
     /// set.insert(4);
     /// assert_eq!(set.is_subset(&sup), false);
     /// ```
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     pub fn is_subset(&self, other: &BTreeSet<T>) -> bool {
         // Stolen from TreeMap
         let mut x = self.iter();
@@ -421,7 +423,7 @@ impl<T: Ord> BTreeSet<T> {
     /// set.insert(2);
     /// assert_eq!(set.is_superset(&sub), true);
     /// ```
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     pub fn is_superset(&self, other: &BTreeSet<T>) -> bool {
         other.is_subset(self)
     }
@@ -440,7 +442,7 @@ impl<T: Ord> BTreeSet<T> {
     /// assert_eq!(set.insert(2i), false);
     /// assert_eq!(set.len(), 1);
     /// ```
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     pub fn insert(&mut self, value: T) -> bool {
         self.map.insert(value, ()).is_none()
     }
@@ -463,13 +465,13 @@ impl<T: Ord> BTreeSet<T> {
     /// assert_eq!(set.remove(&2), true);
     /// assert_eq!(set.remove(&2), false);
     /// ```
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     pub fn remove<Q: ?Sized>(&mut self, value: &Q) -> bool where Q: BorrowFrom<T> + Ord {
         self.map.remove(value).is_some()
     }
 }
 
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl<T: Ord> FromIterator<T> for BTreeSet<T> {
     fn from_iter<Iter: Iterator<Item=T>>(iter: Iter) -> BTreeSet<T> {
         let mut set = BTreeSet::new();
@@ -478,7 +480,7 @@ impl<T: Ord> FromIterator<T> for BTreeSet<T> {
     }
 }
 
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl<T: Ord> Extend<T> for BTreeSet<T> {
     #[inline]
     fn extend<Iter: Iterator<Item=T>>(&mut self, mut iter: Iter) {
@@ -488,15 +490,15 @@ impl<T: Ord> Extend<T> for BTreeSet<T> {
     }
 }
 
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl<T: Ord> Default for BTreeSet<T> {
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     fn default() -> BTreeSet<T> {
         BTreeSet::new()
     }
 }
 
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl<'a, 'b, T: Ord + Clone> Sub<&'b BTreeSet<T>> for &'a BTreeSet<T> {
     type Output = BTreeSet<T>;
 
@@ -519,7 +521,7 @@ impl<'a, 'b, T: Ord + Clone> Sub<&'b BTreeSet<T>> for &'a BTreeSet<T> {
     }
 }
 
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl<'a, 'b, T: Ord + Clone> BitXor<&'b BTreeSet<T>> for &'a BTreeSet<T> {
     type Output = BTreeSet<T>;
 
@@ -542,7 +544,7 @@ impl<'a, 'b, T: Ord + Clone> BitXor<&'b BTreeSet<T>> for &'a BTreeSet<T> {
     }
 }
 
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl<'a, 'b, T: Ord + Clone> BitAnd<&'b BTreeSet<T>> for &'a BTreeSet<T> {
     type Output = BTreeSet<T>;
 
@@ -565,7 +567,7 @@ impl<'a, 'b, T: Ord + Clone> BitAnd<&'b BTreeSet<T>> for &'a BTreeSet<T> {
     }
 }
 
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl<'a, 'b, T: Ord + Clone> BitOr<&'b BTreeSet<T>> for &'a BTreeSet<T> {
     type Output = BTreeSet<T>;
 
@@ -588,7 +590,7 @@ impl<'a, 'b, T: Ord + Clone> BitOr<&'b BTreeSet<T>> for &'a BTreeSet<T> {
     }
 }
 
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl<T: Debug> Debug for BTreeSet<T> {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         try!(write!(f, "BTreeSet {{"));
@@ -602,33 +604,33 @@ impl<T: Debug> Debug for BTreeSet<T> {
     }
 }
 
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl<'a, T> Iterator for Iter<'a, T> {
     type Item = &'a T;
 
     fn next(&mut self) -> Option<&'a T> { self.iter.next() }
     fn size_hint(&self) -> (uint, Option<uint>) { self.iter.size_hint() }
 }
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl<'a, T> DoubleEndedIterator for Iter<'a, T> {
     fn next_back(&mut self) -> Option<&'a T> { self.iter.next_back() }
 }
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl<'a, T> ExactSizeIterator for Iter<'a, T> {}
 
 
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl<T> Iterator for IntoIter<T> {
     type Item = T;
 
     fn next(&mut self) -> Option<T> { self.iter.next() }
     fn size_hint(&self) -> (uint, Option<uint>) { self.iter.size_hint() }
 }
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl<T> DoubleEndedIterator for IntoIter<T> {
     fn next_back(&mut self) -> Option<T> { self.iter.next_back() }
 }
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl<T> ExactSizeIterator for IntoIter<T> {}
 
 
@@ -651,7 +653,7 @@ fn cmp_opt<T: Ord>(x: Option<&T>, y: Option<&T>,
     }
 }
 
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl<'a, T: Ord> Iterator for Difference<'a, T> {
     type Item = &'a T;
 
@@ -666,7 +668,7 @@ impl<'a, T: Ord> Iterator for Difference<'a, T> {
     }
 }
 
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl<'a, T: Ord> Iterator for SymmetricDifference<'a, T> {
     type Item = &'a T;
 
@@ -681,7 +683,7 @@ impl<'a, T: Ord> Iterator for SymmetricDifference<'a, T> {
     }
 }
 
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl<'a, T: Ord> Iterator for Intersection<'a, T> {
     type Item = &'a T;
 
@@ -702,7 +704,7 @@ impl<'a, T: Ord> Iterator for Intersection<'a, T> {
     }
 }
 
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl<'a, T: Ord> Iterator for Union<'a, T> {
     type Item = &'a T;
 
@@ -756,7 +758,9 @@ mod test {
         expected: &'b [int],
     }
 
-    impl<'a, 'b, 'c> FnMut(&'c int) -> bool for Counter<'a, 'b> {
+    impl<'a, 'b, 'c> FnMut<(&'c int,)> for Counter<'a, 'b> {
+        type Output = bool;
+
         extern "rust-call" fn call_mut(&mut self, (&x,): (&'c int,)) -> bool {
             assert_eq!(x, self.expected[*self.i]);
             *self.i += 1;
diff --git a/src/libcollections/dlist.rs b/src/libcollections/dlist.rs
index 73fd806c907..08f7cea4e92 100644
--- a/src/libcollections/dlist.rs
+++ b/src/libcollections/dlist.rs
@@ -19,7 +19,7 @@
 // Backlinks over DList::prev are raw pointers that form a full chain in
 // the reverse direction.
 
-#![stable]
+#![stable(feature = "rust1", since = "1.0.0")]
 
 use core::prelude::*;
 
@@ -33,7 +33,7 @@ use core::mem;
 use core::ptr;
 
 /// A doubly-linked list.
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 pub struct DList<T> {
     length: uint,
     list_head: Link<T>,
@@ -57,7 +57,7 @@ struct Node<T> {
 }
 
 /// An iterator over references to the items of a `DList`.
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 pub struct Iter<'a, T:'a> {
     head: &'a Link<T>,
     tail: Rawlink<Node<T>>,
@@ -65,7 +65,7 @@ pub struct Iter<'a, T:'a> {
 }
 
 // FIXME #19839: deriving is too aggressive on the bounds (T doesn't need to be Clone).
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl<'a, T> Clone for Iter<'a, T> {
     fn clone(&self) -> Iter<'a, T> {
         Iter {
@@ -77,7 +77,7 @@ impl<'a, T> Clone for Iter<'a, T> {
 }
 
 /// An iterator over mutable references to the items of a `DList`.
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 pub struct IterMut<'a, T:'a> {
     list: &'a mut DList<T>,
     head: Rawlink<Node<T>>,
@@ -87,7 +87,7 @@ pub struct IterMut<'a, T:'a> {
 
 /// An iterator over mutable references to the items of a `DList`.
 #[derive(Clone)]
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 pub struct IntoIter<T> {
     list: DList<T>
 }
@@ -206,17 +206,17 @@ impl<T> DList<T> {
     }
 }
 
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl<T> Default for DList<T> {
     #[inline]
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     fn default() -> DList<T> { DList::new() }
 }
 
 impl<T> DList<T> {
     /// Creates an empty `DList`.
     #[inline]
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     pub fn new() -> DList<T> {
         DList{list_head: None, list_tail: Rawlink::none(), length: 0}
     }
@@ -273,14 +273,14 @@ impl<T> DList<T> {
 
     /// Provides a forward iterator.
     #[inline]
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     pub fn iter(&self) -> Iter<T> {
         Iter{nelem: self.len(), head: &self.list_head, tail: self.list_tail}
     }
 
     /// Provides a forward iterator with mutable references.
     #[inline]
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     pub fn iter_mut(&mut self) -> IterMut<T> {
         let head_raw = match self.list_head {
             Some(ref mut h) => Rawlink::some(&mut **h),
@@ -296,7 +296,7 @@ impl<T> DList<T> {
 
     /// Consumes the list into an iterator yielding elements by value.
     #[inline]
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     pub fn into_iter(self) -> IntoIter<T> {
         IntoIter{list: self}
     }
@@ -317,7 +317,7 @@ impl<T> DList<T> {
     /// assert!(!dl.is_empty());
     /// ```
     #[inline]
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     pub fn is_empty(&self) -> bool {
         self.list_head.is_none()
     }
@@ -344,7 +344,7 @@ impl<T> DList<T> {
     ///
     /// ```
     #[inline]
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     pub fn len(&self) -> uint {
         self.length
     }
@@ -371,7 +371,7 @@ impl<T> DList<T> {
     ///
     /// ```
     #[inline]
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     pub fn clear(&mut self) {
         *self = DList::new()
     }
@@ -392,7 +392,7 @@ impl<T> DList<T> {
     ///
     /// ```
     #[inline]
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     pub fn front(&self) -> Option<&T> {
         self.list_head.as_ref().map(|head| &head.value)
     }
@@ -419,7 +419,7 @@ impl<T> DList<T> {
     ///
     /// ```
     #[inline]
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     pub fn front_mut(&mut self) -> Option<&mut T> {
         self.list_head.as_mut().map(|head| &mut head.value)
     }
@@ -440,7 +440,7 @@ impl<T> DList<T> {
     ///
     /// ```
     #[inline]
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     pub fn back(&self) -> Option<&T> {
         self.list_tail.resolve_immut().as_ref().map(|tail| &tail.value)
     }
@@ -467,7 +467,7 @@ impl<T> DList<T> {
     ///
     /// ```
     #[inline]
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     pub fn back_mut(&mut self) -> Option<&mut T> {
         self.list_tail.resolve().map(|tail| &mut tail.value)
     }
@@ -490,7 +490,7 @@ impl<T> DList<T> {
     /// assert_eq!(dl.front().unwrap(), &1);
     ///
     /// ```
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     pub fn push_front(&mut self, elt: T) {
         self.push_front_node(box Node::new(elt))
     }
@@ -516,7 +516,7 @@ impl<T> DList<T> {
     ///
     /// ```
     ///
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     pub fn pop_front(&mut self) -> Option<T> {
         self.pop_front_node().map(|box Node{value, ..}| value)
     }
@@ -533,7 +533,7 @@ impl<T> DList<T> {
     /// d.push_back(3);
     /// assert_eq!(3, *d.back().unwrap());
     /// ```
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     pub fn push_back(&mut self, elt: T) {
         self.push_back_node(box Node::new(elt))
     }
@@ -552,7 +552,7 @@ impl<T> DList<T> {
     /// d.push_back(3);
     /// assert_eq!(d.pop_back(), Some(3));
     /// ```
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     pub fn pop_back(&mut self) -> Option<T> {
         self.pop_back_node().map(|box Node{value, ..}| value)
     }
@@ -577,7 +577,7 @@ impl<T> DList<T> {
     /// assert_eq!(splitted.pop_front(), Some(1));
     /// assert_eq!(splitted.pop_front(), None);
     /// ```
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     pub fn split_off(&mut self, at: uint) -> DList<T> {
         let len = self.len();
         assert!(at < len, "Cannot split off at a nonexistent index");
@@ -620,7 +620,7 @@ impl<T> DList<T> {
 }
 
 #[unsafe_destructor]
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl<T> Drop for DList<T> {
     fn drop(&mut self) {
         // Dissolve the dlist in backwards direction
@@ -642,7 +642,7 @@ impl<T> Drop for DList<T> {
     }
 }
 
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl<'a, A> Iterator for Iter<'a, A> {
     type Item = &'a A;
 
@@ -664,7 +664,7 @@ impl<'a, A> Iterator for Iter<'a, A> {
     }
 }
 
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl<'a, A> DoubleEndedIterator for Iter<'a, A> {
     #[inline]
     fn next_back(&mut self) -> Option<&'a A> {
@@ -679,10 +679,10 @@ impl<'a, A> DoubleEndedIterator for Iter<'a, A> {
     }
 }
 
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl<'a, A> ExactSizeIterator for Iter<'a, A> {}
 
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl<'a, A> Iterator for IterMut<'a, A> {
     type Item = &'a mut A;
     #[inline]
@@ -706,7 +706,7 @@ impl<'a, A> Iterator for IterMut<'a, A> {
     }
 }
 
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl<'a, A> DoubleEndedIterator for IterMut<'a, A> {
     #[inline]
     fn next_back(&mut self) -> Option<&'a mut A> {
@@ -721,7 +721,7 @@ impl<'a, A> DoubleEndedIterator for IterMut<'a, A> {
     }
 }
 
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl<'a, A> ExactSizeIterator for IterMut<'a, A> {}
 
 // private methods for IterMut
@@ -770,7 +770,8 @@ impl<'a, A> IterMut<'a, A> {
     /// }
     /// ```
     #[inline]
-    #[unstable = "this is probably better handled by a cursor type -- we'll see"]
+    #[unstable(feature = "collections",
+               reason = "this is probably better handled by a cursor type -- we'll see")]
     pub fn insert_next(&mut self, elt: A) {
         self.insert_next_node(box Node::new(elt))
     }
@@ -791,7 +792,8 @@ impl<'a, A> IterMut<'a, A> {
     /// assert_eq!(it.next().unwrap(), &2);
     /// ```
     #[inline]
-    #[unstable = "this is probably better handled by a cursor type -- we'll see"]
+    #[unstable(feature = "collections",
+               reason = "this is probably better handled by a cursor type -- we'll see")]
     pub fn peek_next(&mut self) -> Option<&mut A> {
         if self.nelem == 0 {
             return None
@@ -800,7 +802,7 @@ impl<'a, A> IterMut<'a, A> {
     }
 }
 
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl<A> Iterator for IntoIter<A> {
     type Item = A;
 
@@ -813,13 +815,13 @@ impl<A> Iterator for IntoIter<A> {
     }
 }
 
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl<A> DoubleEndedIterator for IntoIter<A> {
     #[inline]
     fn next_back(&mut self) -> Option<A> { self.list.pop_back() }
 }
 
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl<A> FromIterator<A> for DList<A> {
     fn from_iter<T: Iterator<Item=A>>(iterator: T) -> DList<A> {
         let mut ret = DList::new();
@@ -828,14 +830,14 @@ impl<A> FromIterator<A> for DList<A> {
     }
 }
 
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl<A> Extend<A> for DList<A> {
     fn extend<T: Iterator<Item=A>>(&mut self, mut iterator: T) {
         for elt in iterator { self.push_back(elt); }
     }
 }
 
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl<A: PartialEq> PartialEq for DList<A> {
     fn eq(&self, other: &DList<A>) -> bool {
         self.len() == other.len() &&
@@ -848,17 +850,17 @@ impl<A: PartialEq> PartialEq for DList<A> {
     }
 }
 
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl<A: Eq> Eq for DList<A> {}
 
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl<A: PartialOrd> PartialOrd for DList<A> {
     fn partial_cmp(&self, other: &DList<A>) -> Option<Ordering> {
         iter::order::partial_cmp(self.iter(), other.iter())
     }
 }
 
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl<A: Ord> Ord for DList<A> {
     #[inline]
     fn cmp(&self, other: &DList<A>) -> Ordering {
@@ -866,14 +868,14 @@ impl<A: Ord> Ord for DList<A> {
     }
 }
 
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl<A: Clone> Clone for DList<A> {
     fn clone(&self) -> DList<A> {
         self.iter().map(|x| x.clone()).collect()
     }
 }
 
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl<A: fmt::Debug> fmt::Debug for DList<A> {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         try!(write!(f, "DList ["));
@@ -887,7 +889,7 @@ impl<A: fmt::Debug> fmt::Debug for DList<A> {
     }
 }
 
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl<S: Writer + Hasher, A: Hash<S>> Hash<S> for DList<A> {
     fn hash(&self, state: &mut S) {
         self.len().hash(state);
diff --git a/src/libcollections/enum_set.rs b/src/libcollections/enum_set.rs
index a40a590c51a..f36da6f82eb 100644
--- a/src/libcollections/enum_set.rs
+++ b/src/libcollections/enum_set.rs
@@ -82,19 +82,22 @@ fn bit<E:CLike>(e: &E) -> uint {
 
 impl<E:CLike> EnumSet<E> {
     /// Returns an empty `EnumSet`.
-    #[unstable = "matches collection reform specification, waiting for dust to settle"]
+    #[unstable(feature = "collections",
+               reason = "matches collection reform specification, waiting for dust to settle")]
     pub fn new() -> EnumSet<E> {
         EnumSet {bits: 0}
     }
 
     /// Returns the number of elements in the given `EnumSet`.
-    #[unstable = "matches collection reform specification, waiting for dust to settle"]
+    #[unstable(feature = "collections",
+               reason = "matches collection reform specification, waiting for dust to settle")]
     pub fn len(&self) -> uint {
         self.bits.count_ones()
     }
 
     /// Returns true if the `EnumSet` is empty.
-    #[unstable = "matches collection reform specification, waiting for dust to settle"]
+    #[unstable(feature = "collections",
+               reason = "matches collection reform specification, waiting for dust to settle")]
     pub fn is_empty(&self) -> bool {
         self.bits == 0
     }
@@ -104,19 +107,22 @@ impl<E:CLike> EnumSet<E> {
     }
 
     /// Returns `false` if the `EnumSet` contains any enum of the given `EnumSet`.
-    #[unstable = "matches collection reform specification, waiting for dust to settle"]
+    #[unstable(feature = "collections",
+               reason = "matches collection reform specification, waiting for dust to settle")]
     pub fn is_disjoint(&self, other: &EnumSet<E>) -> bool {
         (self.bits & other.bits) == 0
     }
 
     /// Returns `true` if a given `EnumSet` is included in this `EnumSet`.
-    #[unstable = "matches collection reform specification, waiting for dust to settle"]
+    #[unstable(feature = "collections",
+               reason = "matches collection reform specification, waiting for dust to settle")]
     pub fn is_superset(&self, other: &EnumSet<E>) -> bool {
         (self.bits & other.bits) == other.bits
     }
 
     /// Returns `true` if this `EnumSet` is included in the given `EnumSet`.
-    #[unstable = "matches collection reform specification, waiting for dust to settle"]
+    #[unstable(feature = "collections",
+               reason = "matches collection reform specification, waiting for dust to settle")]
     pub fn is_subset(&self, other: &EnumSet<E>) -> bool {
         other.is_superset(self)
     }
@@ -132,7 +138,8 @@ impl<E:CLike> EnumSet<E> {
     }
 
     /// Adds an enum to the `EnumSet`, and returns `true` if it wasn't there before
-    #[unstable = "matches collection reform specification, waiting for dust to settle"]
+    #[unstable(feature = "collections",
+               reason = "matches collection reform specification, waiting for dust to settle")]
     pub fn insert(&mut self, e: E) -> bool {
         let result = !self.contains(&e);
         self.bits |= bit(&e);
@@ -140,7 +147,8 @@ impl<E:CLike> EnumSet<E> {
     }
 
     /// Removes an enum from the EnumSet
-    #[unstable = "matches collection reform specification, waiting for dust to settle"]
+    #[unstable(feature = "collections",
+               reason = "matches collection reform specification, waiting for dust to settle")]
     pub fn remove(&mut self, e: &E) -> bool {
         let result = self.contains(e);
         self.bits &= !bit(e);
@@ -148,13 +156,15 @@ impl<E:CLike> EnumSet<E> {
     }
 
     /// Returns `true` if an `EnumSet` contains a given enum.
-    #[unstable = "matches collection reform specification, waiting for dust to settle"]
+    #[unstable(feature = "collections",
+               reason = "matches collection reform specification, waiting for dust to settle")]
     pub fn contains(&self, e: &E) -> bool {
         (self.bits & bit(e)) != 0
     }
 
     /// Returns an iterator over an `EnumSet`.
-    #[unstable = "matches collection reform specification, waiting for dust to settle"]
+    #[unstable(feature = "collections",
+               reason = "matches collection reform specification, waiting for dust to settle")]
     pub fn iter(&self) -> Iter<E> {
         Iter::new(self.bits)
     }
diff --git a/src/libcollections/lib.rs b/src/libcollections/lib.rs
index 6a182add000..954de14a50a 100644
--- a/src/libcollections/lib.rs
+++ b/src/libcollections/lib.rs
@@ -14,7 +14,8 @@
 
 
 #![crate_name = "collections"]
-#![unstable]
+#![unstable(feature = "collections")]
+#![feature(staged_api)]
 #![staged_api]
 #![crate_type = "rlib"]
 #![doc(html_logo_url = "http://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
@@ -27,8 +28,12 @@
 #![feature(box_syntax)]
 #![feature(unboxed_closures)]
 #![allow(unknown_features)] #![feature(int_uint)]
-#![allow(unstable)]
 #![no_std]
+#![feature(core)]
+#![feature(alloc)]
+#![feature(unicode)]
+#![feature(hash)]
+#![cfg_attr(test, feature(test))]
 
 #[macro_use]
 extern crate core;
@@ -70,23 +75,25 @@ pub mod string;
 pub mod vec;
 pub mod vec_map;
 
-#[unstable = "RFC 509"]
+#[unstable(feature = "collections",
+           reason = "RFC 509")]
 pub mod bitv {
     pub use bit::{Bitv, Iter};
 }
 
-#[unstable = "RFC 509"]
+#[unstable(feature = "collections",
+           reason = "RFC 509")]
 pub mod bitv_set {
     pub use bit::{BitvSet, Union, Intersection, Difference, SymmetricDifference};
     pub use bit::SetIter as Iter;
 }
 
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 pub mod btree_map {
     pub use btree::map::*;
 }
 
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 pub mod btree_set {
     pub use btree::set::*;
 }
diff --git a/src/libcollections/macros.rs b/src/libcollections/macros.rs
index 85aedaeb010..15048998592 100644
--- a/src/libcollections/macros.rs
+++ b/src/libcollections/macros.rs
@@ -10,7 +10,7 @@
 
 /// Creates a `Vec` containing the arguments.
 #[macro_export]
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 macro_rules! vec {
     ($x:expr; $y:expr) => (
         <[_] as $crate::slice::SliceExt>::into_vec(
diff --git a/src/libcollections/ring_buf.rs b/src/libcollections/ring_buf.rs
index 338166c2f0b..2e3f6198112 100644
--- a/src/libcollections/ring_buf.rs
+++ b/src/libcollections/ring_buf.rs
@@ -12,7 +12,7 @@
 //! ends of the container. It also has `O(1)` indexing like a vector. The contained elements are
 //! not required to be copyable, and the queue will be sendable if the contained type is sendable.
 
-#![stable]
+#![stable(feature = "rust1", since = "1.0.0")]
 
 use core::prelude::*;
 
@@ -36,7 +36,7 @@ static INITIAL_CAPACITY: uint = 7u; // 2^3 - 1
 static MINIMUM_CAPACITY: uint = 1u; // 2 - 1
 
 /// `RingBuf` is a circular buffer, which can be used as a double-ended queue efficiently.
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 pub struct RingBuf<T> {
     // tail and head are pointers into the buffer. Tail always points
     // to the first element that could be read, Head always points
@@ -50,13 +50,13 @@ pub struct RingBuf<T> {
     ptr: *mut T
 }
 
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 unsafe impl<T: Send> Send for RingBuf<T> {}
 
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 unsafe impl<T: Sync> Sync for RingBuf<T> {}
 
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl<T: Clone> Clone for RingBuf<T> {
     fn clone(&self) -> RingBuf<T> {
         self.iter().map(|t| t.clone()).collect()
@@ -64,7 +64,7 @@ impl<T: Clone> Clone for RingBuf<T> {
 }
 
 #[unsafe_destructor]
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl<T> Drop for RingBuf<T> {
     fn drop(&mut self) {
         self.clear();
@@ -78,7 +78,7 @@ impl<T> Drop for RingBuf<T> {
     }
 }
 
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl<T> Default for RingBuf<T> {
     #[inline]
     fn default() -> RingBuf<T> { RingBuf::new() }
@@ -146,13 +146,13 @@ impl<T> RingBuf<T> {
 
 impl<T> RingBuf<T> {
     /// Creates an empty `RingBuf`.
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     pub fn new() -> RingBuf<T> {
         RingBuf::with_capacity(INITIAL_CAPACITY)
     }
 
     /// Creates an empty `RingBuf` with space for at least `n` elements.
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     pub fn with_capacity(n: uint) -> RingBuf<T> {
         // +1 since the ringbuffer always leaves one space empty
         let cap = cmp::max(n + 1, MINIMUM_CAPACITY + 1).next_power_of_two();
@@ -191,7 +191,7 @@ impl<T> RingBuf<T> {
     /// buf.push_back(5);
     /// assert_eq!(buf.get(1).unwrap(), &4);
     /// ```
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     pub fn get(&self, i: uint) -> Option<&T> {
         if i < self.len() {
             let idx = self.wrap_index(self.tail + i);
@@ -221,7 +221,7 @@ impl<T> RingBuf<T> {
     ///
     /// assert_eq!(buf[1], 7);
     /// ```
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     pub fn get_mut(&mut self, i: uint) -> Option<&mut T> {
         if i < self.len() {
             let idx = self.wrap_index(self.tail + i);
@@ -250,7 +250,7 @@ impl<T> RingBuf<T> {
     /// assert_eq!(buf[0], 5);
     /// assert_eq!(buf[2], 3);
     /// ```
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     pub fn swap(&mut self, i: uint, j: uint) {
         assert!(i < self.len());
         assert!(j < self.len());
@@ -273,7 +273,7 @@ impl<T> RingBuf<T> {
     /// assert!(buf.capacity() >= 10);
     /// ```
     #[inline]
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     pub fn capacity(&self) -> uint { self.cap - 1 }
 
     /// Reserves the minimum capacity for exactly `additional` more elements to be inserted in the
@@ -296,7 +296,7 @@ impl<T> RingBuf<T> {
     /// buf.reserve_exact(10);
     /// assert!(buf.capacity() >= 11);
     /// ```
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     pub fn reserve_exact(&mut self, additional: uint) {
         self.reserve(additional);
     }
@@ -317,7 +317,7 @@ impl<T> RingBuf<T> {
     /// buf.reserve(10);
     /// assert!(buf.capacity() >= 11);
     /// ```
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     pub fn reserve(&mut self, additional: uint) {
         let new_len = self.len() + additional;
         assert!(new_len + 1 > self.len(), "capacity overflow");
@@ -480,7 +480,8 @@ impl<T> RingBuf<T> {
     /// assert_eq!(buf.len(), 1);
     /// assert_eq!(Some(&5), buf.get(0));
     /// ```
-    #[unstable = "matches collection reform specification; waiting on panic semantics"]
+    #[unstable(feature = "collections",
+               reason = "matches collection reform specification; waiting on panic semantics")]
     pub fn truncate(&mut self, len: uint) {
         for _ in range(len, self.len()) {
             self.pop_back();
@@ -501,7 +502,7 @@ impl<T> RingBuf<T> {
     /// let b: &[_] = &[&5, &3, &4];
     /// assert_eq!(buf.iter().collect::<Vec<&int>>().as_slice(), b);
     /// ```
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     pub fn iter(&self) -> Iter<T> {
         Iter {
             tail: self.tail,
@@ -527,7 +528,7 @@ impl<T> RingBuf<T> {
     /// let b: &[_] = &[&mut 3, &mut 1, &mut 2];
     /// assert_eq!(&buf.iter_mut().collect::<Vec<&mut int>>()[], b);
     /// ```
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     pub fn iter_mut<'a>(&'a mut self) -> IterMut<'a, T> {
         IterMut {
             tail: self.tail,
@@ -539,7 +540,7 @@ impl<T> RingBuf<T> {
     }
 
     /// Consumes the list into an iterator yielding elements by value.
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     pub fn into_iter(self) -> IntoIter<T> {
         IntoIter {
             inner: self,
@@ -549,7 +550,8 @@ impl<T> RingBuf<T> {
     /// Returns a pair of slices which contain, in order, the contents of the
     /// `RingBuf`.
     #[inline]
-    #[unstable = "matches collection reform specification, waiting for dust to settle"]
+    #[unstable(feature = "collections",
+               reason = "matches collection reform specification, waiting for dust to settle")]
     pub fn as_slices<'a>(&'a self) -> (&'a [T], &'a [T]) {
         unsafe {
             let contiguous = self.is_contiguous();
@@ -568,7 +570,8 @@ impl<T> RingBuf<T> {
     /// Returns a pair of slices which contain, in order, the contents of the
     /// `RingBuf`.
     #[inline]
-    #[unstable = "matches collection reform specification, waiting for dust to settle"]
+    #[unstable(feature = "collections",
+               reason = "matches collection reform specification, waiting for dust to settle")]
     pub fn as_mut_slices<'a>(&'a mut self) -> (&'a mut [T], &'a mut [T]) {
         unsafe {
             let contiguous = self.is_contiguous();
@@ -600,7 +603,7 @@ impl<T> RingBuf<T> {
     /// v.push_back(1i);
     /// assert_eq!(v.len(), 1);
     /// ```
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     pub fn len(&self) -> uint { count(self.tail, self.head, self.cap) }
 
     /// Returns true if the buffer contains no elements
@@ -615,7 +618,7 @@ impl<T> RingBuf<T> {
     /// v.push_front(1i);
     /// assert!(!v.is_empty());
     /// ```
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     pub fn is_empty(&self) -> bool { self.len() == 0 }
 
     /// Creates a draining iterator that clears the `RingBuf` and iterates over
@@ -632,7 +635,8 @@ impl<T> RingBuf<T> {
     /// assert!(v.is_empty());
     /// ```
     #[inline]
-    #[unstable = "matches collection reform specification, waiting for dust to settle"]
+    #[unstable(feature = "collections",
+               reason = "matches collection reform specification, waiting for dust to settle")]
     pub fn drain(&mut self) -> Drain<T> {
         Drain {
             inner: self,
@@ -651,7 +655,7 @@ impl<T> RingBuf<T> {
     /// v.clear();
     /// assert!(v.is_empty());
     /// ```
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     #[inline]
     pub fn clear(&mut self) {
         self.drain();
@@ -672,7 +676,7 @@ impl<T> RingBuf<T> {
     /// d.push_back(2i);
     /// assert_eq!(d.front(), Some(&1i));
     /// ```
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     pub fn front(&self) -> Option<&T> {
         if !self.is_empty() { Some(&self[0]) } else { None }
     }
@@ -696,7 +700,7 @@ impl<T> RingBuf<T> {
     /// }
     /// assert_eq!(d.front(), Some(&9i));
     /// ```
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     pub fn front_mut(&mut self) -> Option<&mut T> {
         if !self.is_empty() { Some(&mut self[0]) } else { None }
     }
@@ -716,7 +720,7 @@ impl<T> RingBuf<T> {
     /// d.push_back(2i);
     /// assert_eq!(d.back(), Some(&2i));
     /// ```
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     pub fn back(&self) -> Option<&T> {
         if !self.is_empty() { Some(&self[self.len() - 1]) } else { None }
     }
@@ -740,7 +744,7 @@ impl<T> RingBuf<T> {
     /// }
     /// assert_eq!(d.back(), Some(&9i));
     /// ```
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     pub fn back_mut(&mut self) -> Option<&mut T> {
         let len = self.len();
         if !self.is_empty() { Some(&mut self[len - 1]) } else { None }
@@ -762,7 +766,7 @@ impl<T> RingBuf<T> {
     /// assert_eq!(d.pop_front(), Some(2i));
     /// assert_eq!(d.pop_front(), None);
     /// ```
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     pub fn pop_front(&mut self) -> Option<T> {
         if self.is_empty() {
             None
@@ -785,7 +789,7 @@ impl<T> RingBuf<T> {
     /// d.push_front(2i);
     /// assert_eq!(d.front(), Some(&2i));
     /// ```
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     pub fn push_front(&mut self, t: T) {
         if self.is_full() {
             self.reserve(1);
@@ -809,7 +813,7 @@ impl<T> RingBuf<T> {
     /// buf.push_back(3);
     /// assert_eq!(3, *buf.back().unwrap());
     /// ```
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     pub fn push_back(&mut self, t: T) {
         if self.is_full() {
             self.reserve(1);
@@ -835,7 +839,7 @@ impl<T> RingBuf<T> {
     /// buf.push_back(3);
     /// assert_eq!(buf.pop_back(), Some(3));
     /// ```
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     pub fn pop_back(&mut self) -> Option<T> {
         if self.is_empty() {
             None
@@ -872,7 +876,8 @@ impl<T> RingBuf<T> {
     /// buf.push_back(10);
     /// assert_eq!(buf.swap_back_remove(1), Some(99));
     /// ```
-    #[unstable = "the naming of this function may be altered"]
+    #[unstable(feature = "collections",
+               reason = "the naming of this function may be altered")]
     pub fn swap_back_remove(&mut self, index: uint) -> Option<T> {
         let length = self.len();
         if length > 0 && index < length - 1 {
@@ -904,7 +909,8 @@ impl<T> RingBuf<T> {
     /// buf.push_back(20i);
     /// assert_eq!(buf.swap_front_remove(3), Some(99));
     /// ```
-    #[unstable = "the naming of this function may be altered"]
+    #[unstable(feature = "collections",
+               reason = "the naming of this function may be altered")]
     pub fn swap_front_remove(&mut self, index: uint) -> Option<T> {
         let length = self.len();
         if length > 0 && index < length && index != 0 {
@@ -1137,7 +1143,7 @@ impl<T> RingBuf<T> {
     /// buf.remove(2);
     /// assert_eq!(Some(&15), buf.get(2));
     /// ```
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     pub fn remove(&mut self, i: uint) -> Option<T> {
         if self.is_empty() || self.len() <= i {
             return None;
@@ -1304,7 +1310,8 @@ impl<T: Clone> RingBuf<T> {
     ///     assert_eq!(a, b);
     /// }
     /// ```
-    #[unstable = "matches collection reform specification; waiting on panic semantics"]
+    #[unstable(feature = "collections",
+               reason = "matches collection reform specification; waiting on panic semantics")]
     pub fn resize(&mut self, new_len: uint, value: T) {
         let len = self.len();
 
@@ -1331,7 +1338,7 @@ fn count(tail: uint, head: uint, size: uint) -> uint {
 }
 
 /// `RingBuf` iterator.
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 pub struct Iter<'a, T:'a> {
     ring: &'a [T],
     tail: uint,
@@ -1349,7 +1356,7 @@ impl<'a, T> Clone for Iter<'a, T> {
     }
 }
 
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl<'a, T> Iterator for Iter<'a, T> {
     type Item = &'a T;
 
@@ -1370,7 +1377,7 @@ impl<'a, T> Iterator for Iter<'a, T> {
     }
 }
 
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl<'a, T> DoubleEndedIterator for Iter<'a, T> {
     #[inline]
     fn next_back(&mut self) -> Option<&'a T> {
@@ -1382,10 +1389,10 @@ impl<'a, T> DoubleEndedIterator for Iter<'a, T> {
     }
 }
 
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl<'a, T> ExactSizeIterator for Iter<'a, T> {}
 
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl<'a, T> RandomAccessIterator for Iter<'a, T> {
     #[inline]
     fn indexable(&self) -> uint {
@@ -1408,7 +1415,7 @@ impl<'a, T> RandomAccessIterator for Iter<'a, T> {
 //       with returning the mutable reference. I couldn't find a way to
 //       make the lifetime checker happy so, but there should be a way.
 /// `RingBuf` mutable iterator.
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 pub struct IterMut<'a, T:'a> {
     ptr: *mut T,
     tail: uint,
@@ -1417,7 +1424,7 @@ pub struct IterMut<'a, T:'a> {
     marker: marker::ContravariantLifetime<'a>,
 }
 
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl<'a, T> Iterator for IterMut<'a, T> {
     type Item = &'a mut T;
 
@@ -1441,7 +1448,7 @@ impl<'a, T> Iterator for IterMut<'a, T> {
     }
 }
 
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl<'a, T> DoubleEndedIterator for IterMut<'a, T> {
     #[inline]
     fn next_back(&mut self) -> Option<&'a mut T> {
@@ -1456,16 +1463,16 @@ impl<'a, T> DoubleEndedIterator for IterMut<'a, T> {
     }
 }
 
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl<'a, T> ExactSizeIterator for IterMut<'a, T> {}
 
 /// A by-value RingBuf iterator
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 pub struct IntoIter<T> {
     inner: RingBuf<T>,
 }
 
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl<T> Iterator for IntoIter<T> {
     type Item = T;
 
@@ -1481,7 +1488,7 @@ impl<T> Iterator for IntoIter<T> {
     }
 }
 
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl<T> DoubleEndedIterator for IntoIter<T> {
     #[inline]
     fn next_back(&mut self) -> Option<T> {
@@ -1489,17 +1496,18 @@ impl<T> DoubleEndedIterator for IntoIter<T> {
     }
 }
 
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl<T> ExactSizeIterator for IntoIter<T> {}
 
 /// A draining RingBuf iterator
-#[unstable = "matches collection reform specification, waiting for dust to settle"]
+#[unstable(feature = "collections",
+           reason = "matches collection reform specification, waiting for dust to settle")]
 pub struct Drain<'a, T: 'a> {
     inner: &'a mut RingBuf<T>,
 }
 
 #[unsafe_destructor]
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl<'a, T: 'a> Drop for Drain<'a, T> {
     fn drop(&mut self) {
         for _ in *self {}
@@ -1508,7 +1516,7 @@ impl<'a, T: 'a> Drop for Drain<'a, T> {
     }
 }
 
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl<'a, T: 'a> Iterator for Drain<'a, T> {
     type Item = T;
 
@@ -1524,7 +1532,7 @@ impl<'a, T: 'a> Iterator for Drain<'a, T> {
     }
 }
 
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl<'a, T: 'a> DoubleEndedIterator for Drain<'a, T> {
     #[inline]
     fn next_back(&mut self) -> Option<T> {
@@ -1532,10 +1540,10 @@ impl<'a, T: 'a> DoubleEndedIterator for Drain<'a, T> {
     }
 }
 
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl<'a, T: 'a> ExactSizeIterator for Drain<'a, T> {}
 
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl<A: PartialEq> PartialEq for RingBuf<A> {
     fn eq(&self, other: &RingBuf<A>) -> bool {
         self.len() == other.len() &&
@@ -1543,17 +1551,17 @@ impl<A: PartialEq> PartialEq for RingBuf<A> {
     }
 }
 
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl<A: Eq> Eq for RingBuf<A> {}
 
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl<A: PartialOrd> PartialOrd for RingBuf<A> {
     fn partial_cmp(&self, other: &RingBuf<A>) -> Option<Ordering> {
         iter::order::partial_cmp(self.iter(), other.iter())
     }
 }
 
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl<A: Ord> Ord for RingBuf<A> {
     #[inline]
     fn cmp(&self, other: &RingBuf<A>) -> Ordering {
@@ -1561,7 +1569,7 @@ impl<A: Ord> Ord for RingBuf<A> {
     }
 }
 
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl<S: Writer + Hasher, A: Hash<S>> Hash<S> for RingBuf<A> {
     fn hash(&self, state: &mut S) {
         self.len().hash(state);
@@ -1571,7 +1579,7 @@ impl<S: Writer + Hasher, A: Hash<S>> Hash<S> for RingBuf<A> {
     }
 }
 
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl<A> Index<uint> for RingBuf<A> {
     type Output = A;
 
@@ -1581,7 +1589,7 @@ impl<A> Index<uint> for RingBuf<A> {
     }
 }
 
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl<A> IndexMut<uint> for RingBuf<A> {
     type Output = A;
 
@@ -1591,7 +1599,7 @@ impl<A> IndexMut<uint> for RingBuf<A> {
     }
 }
 
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl<A> FromIterator<A> for RingBuf<A> {
     fn from_iter<T: Iterator<Item=A>>(iterator: T) -> RingBuf<A> {
         let (lower, _) = iterator.size_hint();
@@ -1601,7 +1609,7 @@ impl<A> FromIterator<A> for RingBuf<A> {
     }
 }
 
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl<A> Extend<A> for RingBuf<A> {
     fn extend<T: Iterator<Item=A>>(&mut self, mut iterator: T) {
         for elt in iterator {
@@ -1610,7 +1618,7 @@ impl<A> Extend<A> for RingBuf<A> {
     }
 }
 
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl<T: fmt::Debug> fmt::Debug for RingBuf<T> {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         try!(write!(f, "RingBuf ["));
diff --git a/src/libcollections/slice.rs b/src/libcollections/slice.rs
index 300c1d0323b..b3bf55be46b 100644
--- a/src/libcollections/slice.rs
+++ b/src/libcollections/slice.rs
@@ -86,7 +86,7 @@
 //! * Further iterators exist that split, chunk or permute the slice.
 
 #![doc(primitive = "slice")]
-#![stable]
+#![stable(feature = "rust1", since = "1.0.0")]
 
 use alloc::boxed::Box;
 use core::borrow::{BorrowFrom, BorrowFromMut, ToOwned};
@@ -120,9 +120,9 @@ pub use core::slice::{from_raw_buf, from_raw_mut_buf};
 ////////////////////////////////////////////////////////////////////////////////
 
 /// Allocating extension methods for slices.
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 pub trait SliceExt {
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     type Item;
 
     /// Sorts the slice, in place, using `compare` to compare
@@ -142,7 +142,7 @@ pub trait SliceExt {
     /// v.sort_by(|a, b| b.cmp(a));
     /// assert!(v == [5, 4, 3, 2, 1]);
     /// ```
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     fn sort_by<F>(&mut self, compare: F) where F: FnMut(&Self::Item, &Self::Item) -> Ordering;
 
     /// Consumes `src` and moves as many elements as it can into `self`
@@ -166,19 +166,26 @@ pub trait SliceExt {
     /// assert_eq!(num_moved, 3);
     /// assert!(a == [6i, 7, 8, 4, 5]);
     /// ```
-    #[unstable = "uncertain about this API approach"]
+    #[unstable(feature = "collections",
+               reason = "uncertain about this API approach")]
     fn move_from(&mut self, src: Vec<Self::Item>, start: uint, end: uint) -> uint;
 
     /// Deprecated: use `&s[start .. end]` notation instead.
-    #[deprecated = "use &s[start .. end] instead"]
+    #[unstable(feature = "collections",
+               reason = "will be replaced by slice syntax")]
+    #[deprecated(since = "1.0.0", reason = "use &s[start .. end] instead")]
     fn slice(&self, start: uint, end: uint) -> &[Self::Item];
 
     /// Deprecated: use `&s[start..]` notation instead.
-    #[deprecated = "use &s[start..] instead"]
+    #[unstable(feature = "collections",
+               reason = "will be replaced by slice syntax")]
+    #[deprecated(since = "1.0.0", reason = "use &s[start..] instead")]
     fn slice_from(&self, start: uint) -> &[Self::Item];
 
     /// Deprecated: use `&s[..end]` notation instead.
-    #[deprecated = "use &s[..end] instead"]
+    #[unstable(feature = "collections",
+               reason = "will be replaced by slice syntax")]
+    #[deprecated(since = "1.0.0", reason = "use &s[..end] instead")]
     fn slice_to(&self, end: uint) -> &[Self::Item];
 
     /// Divides one slice into two at an index.
@@ -197,11 +204,11 @@ pub trait SliceExt {
     /// assert_eq!([10, 40], v1);
     /// assert_eq!([30, 20, 50], v2);
     /// ```
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     fn split_at(&self, mid: uint) -> (&[Self::Item], &[Self::Item]);
 
     /// Returns an iterator over the slice.
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     fn iter(&self) -> Iter<Self::Item>;
 
     /// Returns an iterator over subslices separated by elements that match
@@ -218,7 +225,7 @@ pub trait SliceExt {
     ///     println!("{:?}", group);
     /// }
     /// ```
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     fn split<F>(&self, pred: F) -> Split<Self::Item, F>
                 where F: FnMut(&Self::Item) -> bool;
 
@@ -237,7 +244,7 @@ pub trait SliceExt {
     ///     println!("{:?}", group);
     /// }
     /// ```
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     fn splitn<F>(&self, n: uint, pred: F) -> SplitN<Self::Item, F>
                  where F: FnMut(&Self::Item) -> bool;
 
@@ -257,7 +264,7 @@ pub trait SliceExt {
     ///     println!("{:?}", group);
     /// }
     /// ```
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     fn rsplitn<F>(&self, n: uint, pred: F) -> RSplitN<Self::Item, F>
                   where F: FnMut(&Self::Item) -> bool;
 
@@ -280,7 +287,7 @@ pub trait SliceExt {
     ///     println!("{:?}", win);
     /// }
     /// ```
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     fn windows(&self, size: uint) -> Windows<Self::Item>;
 
     /// Returns an iterator over `size` elements of the slice at a
@@ -303,7 +310,7 @@ pub trait SliceExt {
     ///     println!("{:?}", win);
     /// }
     /// ```
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     fn chunks(&self, size: uint) -> Chunks<Self::Item>;
 
     /// Returns the element of a slice at the given index, or `None` if the
@@ -316,7 +323,7 @@ pub trait SliceExt {
     /// assert_eq!(Some(&40), v.get(1));
     /// assert_eq!(None, v.get(3));
     /// ```
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     fn get(&self, index: uint) -> Option<&Self::Item>;
 
     /// Returns the first element of a slice, or `None` if it is empty.
@@ -330,15 +337,15 @@ pub trait SliceExt {
     /// let w: &[i32] = &[];
     /// assert_eq!(None, w.first());
     /// ```
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     fn first(&self) -> Option<&Self::Item>;
 
     /// Returns all but the first element of a slice.
-    #[unstable = "likely to be renamed"]
+    #[unstable(feature = "collections", reason = "likely to be renamed")]
     fn tail(&self) -> &[Self::Item];
 
     /// Returns all but the last element of a slice.
-    #[unstable = "likely to be renamed"]
+    #[unstable(feature = "collections", reason = "likely to be renamed")]
     fn init(&self) -> &[Self::Item];
 
     /// Returns the last element of a slice, or `None` if it is empty.
@@ -352,12 +359,12 @@ pub trait SliceExt {
     /// let w: &[i32] = &[];
     /// assert_eq!(None, w.last());
     /// ```
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     fn last(&self) -> Option<&Self::Item>;
 
     /// Returns a pointer to the element at the given index, without doing
     /// bounds checking.
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     unsafe fn get_unchecked(&self, index: uint) -> &Self::Item;
 
     /// Returns an unsafe pointer to the slice's buffer
@@ -367,7 +374,7 @@ pub trait SliceExt {
     ///
     /// Modifying the slice may cause its buffer to be reallocated, which
     /// would also make any pointers to it invalid.
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     fn as_ptr(&self) -> *const Self::Item;
 
     /// Binary search a sorted slice with a comparator function.
@@ -402,7 +409,7 @@ pub trait SliceExt {
     /// let r = s.binary_search_by(|probe| probe.cmp(&seek));
     /// assert!(match r { Ok(1...4) => true, _ => false, });
     /// ```
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     fn binary_search_by<F>(&self, f: F) -> Result<uint, uint> where
         F: FnMut(&Self::Item) -> Ordering;
 
@@ -414,7 +421,7 @@ pub trait SliceExt {
     /// let a = [1i, 2, 3];
     /// assert_eq!(a.len(), 3);
     /// ```
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     fn len(&self) -> uint;
 
     /// Returns true if the slice has a length of 0
@@ -426,60 +433,68 @@ pub trait SliceExt {
     /// assert!(!a.is_empty());
     /// ```
     #[inline]
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     fn is_empty(&self) -> bool { self.len() == 0 }
     /// Returns a mutable reference to the element at the given index,
     /// or `None` if the index is out of bounds
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     fn get_mut(&mut self, index: uint) -> Option<&mut Self::Item>;
 
     /// Work with `self` as a mut slice.
     /// Primarily intended for getting a &mut [T] from a [T; N].
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     fn as_mut_slice(&mut self) -> &mut [Self::Item];
 
     /// Deprecated: use `&mut s[start .. end]` instead.
-    #[deprecated = "use &mut s[start .. end] instead"]
+    #[unstable(feature = "collections",
+               reason = "will be replaced by slice syntax")]
+    #[deprecated(since = "1.0.0", reason = "use &mut s[start .. end] instead")]
     fn slice_mut(&mut self, start: uint, end: uint) -> &mut [Self::Item];
 
     /// Deprecated: use `&mut s[start ..]` instead.
-    #[deprecated = "use &mut s[start ..] instead"]
+    #[unstable(feature = "collections",
+               reason = "will be replaced by slice syntax")]
+    #[deprecated(since = "1.0.0", reason = "use &mut s[start ..] instead")]
     fn slice_from_mut(&mut self, start: uint) -> &mut [Self::Item];
 
     /// Deprecated: use `&mut s[.. end]` instead.
-    #[deprecated = "use &mut s[.. end] instead"]
+    #[unstable(feature = "collections",
+               reason = "will be replaced by slice syntax")]
+    #[deprecated(since = "1.0.0", reason = "use &mut s[.. end] instead")]
     fn slice_to_mut(&mut self, end: uint) -> &mut [Self::Item];
 
     /// Returns an iterator that allows modifying each value
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     fn iter_mut(&mut self) -> IterMut<Self::Item>;
 
     /// Returns a mutable pointer to the first element of a slice, or `None` if it is empty
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     fn first_mut(&mut self) -> Option<&mut Self::Item>;
 
     /// Returns all but the first element of a mutable slice
-    #[unstable = "likely to be renamed or removed"]
+    #[unstable(feature = "collections",
+               reason = "likely to be renamed or removed")]
     fn tail_mut(&mut self) -> &mut [Self::Item];
 
     /// Returns all but the last element of a mutable slice
-    #[unstable = "likely to be renamed or removed"]
+    #[unstable(feature = "collections",
+               reason = "likely to be renamed or removed")]
     fn init_mut(&mut self) -> &mut [Self::Item];
 
     /// Returns a mutable pointer to the last item in the slice.
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     fn last_mut(&mut self) -> Option<&mut Self::Item>;
 
     /// Returns an iterator over mutable subslices separated by elements that
     /// match `pred`.  The matched element is not contained in the subslices.
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     fn split_mut<F>(&mut self, pred: F) -> SplitMut<Self::Item, F>
                     where F: FnMut(&Self::Item) -> bool;
 
     /// Returns an iterator over subslices separated by elements that match
     /// `pred`, limited to splitting at most `n` times.  The matched element is
     /// not contained in the subslices.
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     fn splitn_mut<F>(&mut self, n: uint, pred: F) -> SplitNMut<Self::Item, F>
                      where F: FnMut(&Self::Item) -> bool;
 
@@ -487,7 +502,7 @@ pub trait SliceExt {
     /// `pred` limited to splitting at most `n` times. This starts at the end of
     /// the slice and works backwards.  The matched element is not contained in
     /// the subslices.
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     fn rsplitn_mut<F>(&mut self,  n: uint, pred: F) -> RSplitNMut<Self::Item, F>
                       where F: FnMut(&Self::Item) -> bool;
 
@@ -499,7 +514,7 @@ pub trait SliceExt {
     /// # Panics
     ///
     /// Panics if `chunk_size` is 0.
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     fn chunks_mut(&mut self, chunk_size: uint) -> ChunksMut<Self::Item>;
 
     /// Swaps two elements in a slice.
@@ -520,7 +535,7 @@ pub trait SliceExt {
     /// v.swap(1, 3);
     /// assert!(v == ["a", "d", "c", "b"]);
     /// ```
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     fn swap(&mut self, a: uint, b: uint);
 
     /// Divides one `&mut` into two at an index.
@@ -557,7 +572,7 @@ pub trait SliceExt {
     ///     assert!(right == []);
     /// }
     /// ```
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     fn split_at_mut(&mut self, mid: uint) -> (&mut [Self::Item], &mut [Self::Item]);
 
     /// Reverse the order of elements in a slice, in place.
@@ -569,11 +584,11 @@ pub trait SliceExt {
     /// v.reverse();
     /// assert!(v == [3i, 2, 1]);
     /// ```
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     fn reverse(&mut self);
 
     /// Returns an unsafe mutable pointer to the element in index
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     unsafe fn get_unchecked_mut(&mut self, index: uint) -> &mut Self::Item;
 
     /// Return an unsafe mutable pointer to the slice's buffer.
@@ -584,11 +599,11 @@ pub trait SliceExt {
     /// Modifying the slice may cause its buffer to be reallocated, which
     /// would also make any pointers to it invalid.
     #[inline]
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     fn as_mut_ptr(&mut self) -> *mut Self::Item;
 
     /// Copies `self` into a new `Vec`.
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     fn to_vec(&self) -> Vec<Self::Item> where Self::Item: Clone;
 
     /// Creates an iterator that yields every possible permutation of the
@@ -615,7 +630,7 @@ pub trait SliceExt {
     /// assert_eq!(Some(vec![1i, 3, 2]), perms.next());
     /// assert_eq!(Some(vec![3i, 1, 2]), perms.next());
     /// ```
-    #[unstable]
+    #[unstable(feature = "collections")]
     fn permutations(&self) -> Permutations<Self::Item> where Self::Item: Clone;
 
     /// Copies as many elements from `src` as it can into `self` (the
@@ -635,7 +650,7 @@ pub trait SliceExt {
     /// assert!(dst.clone_from_slice(&src2) == 3);
     /// assert!(dst == [3i, 4, 5]);
     /// ```
-    #[unstable]
+    #[unstable(feature = "collections")]
     fn clone_from_slice(&mut self, &[Self::Item]) -> uint where Self::Item: Clone;
 
     /// Sorts the slice, in place.
@@ -650,7 +665,7 @@ pub trait SliceExt {
     /// v.sort();
     /// assert!(v == [-5i, -3, 1, 2, 4]);
     /// ```
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     fn sort(&mut self) where Self::Item: Ord;
 
     /// Binary search a sorted slice for a given element.
@@ -676,11 +691,12 @@ pub trait SliceExt {
     /// let r = s.binary_search(&1);
     /// assert!(match r { Ok(1...4) => true, _ => false, });
     /// ```
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     fn binary_search(&self, x: &Self::Item) -> Result<uint, uint> where Self::Item: Ord;
 
     /// Deprecated: use `binary_search` instead.
-    #[deprecated = "use binary_search instead"]
+    #[unstable(feature = "collections")]
+    #[deprecated(since = "1.0.0", reason = "use binary_search instead")]
     fn binary_search_elem(&self, x: &Self::Item) -> Result<uint, uint> where Self::Item: Ord {
         self.binary_search(x)
     }
@@ -701,7 +717,8 @@ pub trait SliceExt {
     /// let b: &mut [_] = &mut [1i, 0, 2];
     /// assert!(v == b);
     /// ```
-    #[unstable = "uncertain if this merits inclusion in std"]
+    #[unstable(feature = "collections",
+               reason = "uncertain if this merits inclusion in std")]
     fn next_permutation(&mut self) -> bool where Self::Item: Ord;
 
     /// Mutates the slice to the previous lexicographic permutation.
@@ -720,15 +737,16 @@ pub trait SliceExt {
     /// let b: &mut [_] = &mut [0i, 1, 2];
     /// assert!(v == b);
     /// ```
-    #[unstable = "uncertain if this merits inclusion in std"]
+    #[unstable(feature = "collections",
+               reason = "uncertain if this merits inclusion in std")]
     fn prev_permutation(&mut self) -> bool where Self::Item: Ord;
 
     /// Find the first index containing a matching value.
-    #[unstable]
+    #[unstable(feature = "collections")]
     fn position_elem(&self, t: &Self::Item) -> Option<uint> where Self::Item: PartialEq;
 
     /// Find the last index containing a matching value.
-    #[unstable]
+    #[unstable(feature = "collections")]
     fn rposition_elem(&self, t: &Self::Item) -> Option<uint> where Self::Item: PartialEq;
 
     /// Returns true if the slice contains an element with the given value.
@@ -740,7 +758,7 @@ pub trait SliceExt {
     /// assert!(v.contains(&30));
     /// assert!(!v.contains(&50));
     /// ```
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     fn contains(&self, x: &Self::Item) -> bool where Self::Item: PartialEq;
 
     /// Returns true if `needle` is a prefix of the slice.
@@ -754,7 +772,7 @@ pub trait SliceExt {
     /// assert!(!v.starts_with(&[50]));
     /// assert!(!v.starts_with(&[10, 50]));
     /// ```
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     fn starts_with(&self, needle: &[Self::Item]) -> bool where Self::Item: PartialEq;
 
     /// Returns true if `needle` is a suffix of the slice.
@@ -768,15 +786,15 @@ pub trait SliceExt {
     /// assert!(!v.ends_with(&[50]));
     /// assert!(!v.ends_with(&[50, 30]));
     /// ```
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     fn ends_with(&self, needle: &[Self::Item]) -> bool where Self::Item: PartialEq;
 
     /// Convert `self` into a vector without clones or allocation.
-    #[unstable]
+    #[unstable(feature = "collections")]
     fn into_vec(self: Box<Self>) -> Vec<Self::Item>;
 }
 
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl<T> SliceExt for [T] {
     type Item = T;
 
@@ -1064,7 +1082,7 @@ impl<T> SliceExt for [T] {
 ////////////////////////////////////////////////////////////////////////////////
 // Extension traits for slices over specific kinds of data
 ////////////////////////////////////////////////////////////////////////////////
-#[unstable = "U should be an associated type"]
+#[unstable(feature = "collections", reason = "U should be an associated type")]
 /// An extension trait for concatenating slices
 pub trait SliceConcatExt<T: ?Sized, U> {
     /// Flattens a slice of `T` into a single value `U`.
@@ -1078,7 +1096,7 @@ pub trait SliceConcatExt<T: ?Sized, U> {
     ///
     /// println!("{}", s); // prints "helloworld"
     /// ```
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     fn concat(&self) -> U;
 
     /// Flattens a slice of `T` into a single value `U`, placing a given separator between each.
@@ -1092,7 +1110,7 @@ pub trait SliceConcatExt<T: ?Sized, U> {
     ///
     /// println!("{}", s); // prints "hello world"
     /// ```
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     fn connect(&self, sep: &T) -> U;
 }
 
@@ -1128,7 +1146,7 @@ impl<T: Clone, V: AsSlice<T>> SliceConcatExt<T, Vec<T>> for [V] {
 ///
 /// The last generated swap is always (0, 1), and it returns the
 /// sequence to its initial order.
-#[unstable]
+#[unstable(feature = "collections")]
 #[derive(Clone)]
 pub struct ElementSwaps {
     sdir: Vec<SizeDirection>,
@@ -1140,7 +1158,7 @@ pub struct ElementSwaps {
 
 impl ElementSwaps {
     /// Creates an `ElementSwaps` iterator for a sequence of `length` elements.
-    #[unstable]
+    #[unstable(feature = "collections")]
     pub fn new(length: uint) -> ElementSwaps {
         // Initialize `sdir` with a direction that position should move in
         // (all negative at the beginning) and the `size` of the
@@ -1157,17 +1175,17 @@ impl ElementSwaps {
 // Standard trait implementations for slices
 ////////////////////////////////////////////////////////////////////////////////
 
-#[unstable = "trait is unstable"]
+#[unstable(feature = "collections", reason = "trait is unstable")]
 impl<T> BorrowFrom<Vec<T>> for [T] {
     fn borrow_from(owned: &Vec<T>) -> &[T] { &owned[] }
 }
 
-#[unstable = "trait is unstable"]
+#[unstable(feature = "collections", reason = "trait is unstable")]
 impl<T> BorrowFromMut<Vec<T>> for [T] {
     fn borrow_from_mut(owned: &mut Vec<T>) -> &mut [T] { &mut owned[] }
 }
 
-#[unstable = "trait is unstable"]
+#[unstable(feature = "collections", reason = "trait is unstable")]
 impl<T: Clone> ToOwned<Vec<T>> for [T] {
     fn to_owned(&self) -> Vec<T> { self.to_vec() }
 }
@@ -1186,7 +1204,7 @@ struct SizeDirection {
     dir: Direction,
 }
 
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl Iterator for ElementSwaps {
     type Item = (uint, uint);
 
@@ -1249,13 +1267,13 @@ impl Iterator for ElementSwaps {
 /// swap applied.
 ///
 /// Generates even and odd permutations alternately.
-#[unstable]
+#[unstable(feature = "collections")]
 pub struct Permutations<T> {
     swaps: ElementSwaps,
     v: Vec<T>,
 }
 
-#[unstable = "trait is unstable"]
+#[unstable(feature = "collections", reason = "trait is unstable")]
 impl<T: Clone> Iterator for Permutations<T> {
     type Item = Vec<T>;
 
diff --git a/src/libcollections/str.rs b/src/libcollections/str.rs
index 6608d0ee9a7..63ae743b421 100644
--- a/src/libcollections/str.rs
+++ b/src/libcollections/str.rs
@@ -50,7 +50,7 @@
 //! is the same as `&[u8]`.
 
 #![doc(primitive = "str")]
-#![stable]
+#![stable(feature = "rust1", since = "1.0.0")]
 
 use self::RecompositionState::*;
 use self::DecompositionType::*;
@@ -165,7 +165,7 @@ enum DecompositionType {
 /// External iterator for a string's decomposition's characters.
 /// Use with the `std::iter` module.
 #[derive(Clone)]
-#[unstable]
+#[unstable(feature = "collections")]
 pub struct Decompositions<'a> {
     kind: DecompositionType,
     iter: Chars<'a>,
@@ -173,7 +173,7 @@ pub struct Decompositions<'a> {
     sorted: bool
 }
 
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl<'a> Iterator for Decompositions<'a> {
     type Item = char;
 
@@ -255,7 +255,7 @@ enum RecompositionState {
 /// External iterator for a string's recomposition's characters.
 /// Use with the `std::iter` module.
 #[derive(Clone)]
-#[unstable]
+#[unstable(feature = "collections")]
 pub struct Recompositions<'a> {
     iter: Decompositions<'a>,
     state: RecompositionState,
@@ -264,7 +264,7 @@ pub struct Recompositions<'a> {
     last_ccc: Option<u8>
 }
 
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl<'a> Iterator for Recompositions<'a> {
     type Item = char;
 
@@ -352,12 +352,12 @@ impl<'a> Iterator for Recompositions<'a> {
 /// External iterator for a string's UTF16 codeunits.
 /// Use with the `std::iter` module.
 #[derive(Clone)]
-#[unstable]
+#[unstable(feature = "collections")]
 pub struct Utf16Units<'a> {
     encoder: Utf16Encoder<Chars<'a>>
 }
 
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl<'a> Iterator for Utf16Units<'a> {
     type Item = u16;
 
@@ -384,12 +384,12 @@ macro_rules! utf8_acc_cont_byte {
     ($ch:expr, $byte:expr) => (($ch << 6) | ($byte & 63u8) as u32)
 }
 
-#[unstable = "trait is unstable"]
+#[unstable(feature = "collections", reason = "trait is unstable")]
 impl BorrowFrom<String> for str {
     fn borrow_from(owned: &String) -> &str { &owned[] }
 }
 
-#[unstable = "trait is unstable"]
+#[unstable(feature = "collections", reason = "trait is unstable")]
 impl ToOwned<String> for str {
     fn to_owned(&self) -> String {
         unsafe {
@@ -407,16 +407,18 @@ Section: Trait implementations
 */
 
 /// Any string that can be represented as a slice.
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 pub trait StrExt: Index<FullRange, Output = str> {
     /// Escapes each char in `s` with `char::escape_default`.
-    #[unstable = "return type may change to be an iterator"]
+    #[unstable(feature = "collections",
+               reason = "return type may change to be an iterator")]
     fn escape_default(&self) -> String {
         self.chars().flat_map(|c| c.escape_default()).collect()
     }
 
     /// Escapes each char in `s` with `char::escape_unicode`.
-    #[unstable = "return type may change to be an iterator"]
+    #[unstable(feature = "collections",
+               reason = "return type may change to be an iterator")]
     fn escape_unicode(&self) -> String {
         self.chars().flat_map(|c| c.escape_unicode()).collect()
     }
@@ -445,7 +447,7 @@ pub trait StrExt: Index<FullRange, Output = str> {
     /// // not found, so no change.
     /// assert_eq!(s.replace("cookie monster", "little lamb"), s);
     /// ```
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     fn replace(&self, from: &str, to: &str) -> String {
         let mut result = String::new();
         let mut last_end = 0;
@@ -461,7 +463,8 @@ pub trait StrExt: Index<FullRange, Output = str> {
     /// Returns an iterator over the string in Unicode Normalization Form D
     /// (canonical decomposition).
     #[inline]
-    #[unstable = "this functionality may be moved to libunicode"]
+    #[unstable(feature = "collections",
+               reason = "this functionality may be moved to libunicode")]
     fn nfd_chars<'a>(&'a self) -> Decompositions<'a> {
         Decompositions {
             iter: self[].chars(),
@@ -474,7 +477,8 @@ pub trait StrExt: Index<FullRange, Output = str> {
     /// Returns an iterator over the string in Unicode Normalization Form KD
     /// (compatibility decomposition).
     #[inline]
-    #[unstable = "this functionality may be moved to libunicode"]
+    #[unstable(feature = "collections",
+               reason = "this functionality may be moved to libunicode")]
     fn nfkd_chars<'a>(&'a self) -> Decompositions<'a> {
         Decompositions {
             iter: self[].chars(),
@@ -487,7 +491,8 @@ pub trait StrExt: Index<FullRange, Output = str> {
     /// An Iterator over the string in Unicode Normalization Form C
     /// (canonical decomposition followed by canonical composition).
     #[inline]
-    #[unstable = "this functionality may be moved to libunicode"]
+    #[unstable(feature = "collections",
+               reason = "this functionality may be moved to libunicode")]
     fn nfc_chars<'a>(&'a self) -> Recompositions<'a> {
         Recompositions {
             iter: self.nfd_chars(),
@@ -501,7 +506,8 @@ pub trait StrExt: Index<FullRange, Output = str> {
     /// An Iterator over the string in Unicode Normalization Form KC
     /// (compatibility decomposition followed by canonical composition).
     #[inline]
-    #[unstable = "this functionality may be moved to libunicode"]
+    #[unstable(feature = "collections",
+               reason = "this functionality may be moved to libunicode")]
     fn nfkc_chars<'a>(&'a self) -> Recompositions<'a> {
         Recompositions {
             iter: self.nfkd_chars(),
@@ -523,7 +529,7 @@ pub trait StrExt: Index<FullRange, Output = str> {
     /// ```rust
     /// assert!("bananas".contains("nana"));
     /// ```
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     fn contains(&self, pat: &str) -> bool {
         core_str::StrExt::contains(&self[], pat)
     }
@@ -539,7 +545,8 @@ pub trait StrExt: Index<FullRange, Output = str> {
     /// ```rust
     /// assert!("hello".contains_char('e'));
     /// ```
-    #[unstable = "might get removed in favour of a more generic contains()"]
+    #[unstable(feature = "collections",
+               reason = "might get removed in favour of a more generic contains()")]
     fn contains_char<P: CharEq>(&self, pat: P) -> bool {
         core_str::StrExt::contains_char(&self[], pat)
     }
@@ -553,7 +560,7 @@ pub trait StrExt: Index<FullRange, Output = str> {
     /// let v: Vec<char> = "abc åäö".chars().collect();
     /// assert_eq!(v, vec!['a', 'b', 'c', ' ', 'å', 'ä', 'ö']);
     /// ```
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     fn chars(&self) -> Chars {
         core_str::StrExt::chars(&self[])
     }
@@ -566,13 +573,13 @@ pub trait StrExt: Index<FullRange, Output = str> {
     /// let v: Vec<u8> = "bors".bytes().collect();
     /// assert_eq!(v, b"bors".to_vec());
     /// ```
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     fn bytes(&self) -> Bytes {
         core_str::StrExt::bytes(&self[])
     }
 
     /// An iterator over the characters of `self` and their byte offsets.
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     fn char_indices(&self) -> CharIndices {
         core_str::StrExt::char_indices(&self[])
     }
@@ -595,7 +602,7 @@ pub trait StrExt: Index<FullRange, Output = str> {
     /// let v: Vec<&str> = "".split('X').collect();
     /// assert_eq!(v, vec![""]);
     /// ```
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     fn split<P: CharEq>(&self, pat: P) -> Split<P> {
         core_str::StrExt::split(&self[], pat)
     }
@@ -622,7 +629,7 @@ pub trait StrExt: Index<FullRange, Output = str> {
     /// let v: Vec<&str> = "".splitn(1, 'X').collect();
     /// assert_eq!(v, vec![""]);
     /// ```
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     fn splitn<P: CharEq>(&self, count: uint, pat: P) -> SplitN<P> {
         core_str::StrExt::splitn(&self[], count, pat)
     }
@@ -651,7 +658,7 @@ pub trait StrExt: Index<FullRange, Output = str> {
     /// let v: Vec<&str> = "lionXXtigerXleopard".split('X').rev().collect();
     /// assert_eq!(v, vec!["leopard", "tiger", "", "lion"]);
     /// ```
-    #[unstable = "might get removed"]
+    #[unstable(feature = "collections", reason = "might get removed")]
     fn split_terminator<P: CharEq>(&self, pat: P) -> SplitTerminator<P> {
         core_str::StrExt::split_terminator(&self[], pat)
     }
@@ -672,7 +679,7 @@ pub trait StrExt: Index<FullRange, Output = str> {
     /// let v: Vec<&str> = "lionXXtigerXleopard".rsplitn(2, 'X').collect();
     /// assert_eq!(v, vec!["leopard", "tiger", "lionX"]);
     /// ```
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     fn rsplitn<P: CharEq>(&self, count: uint, pat: P) -> RSplitN<P> {
         core_str::StrExt::rsplitn(&self[], count, pat)
     }
@@ -697,7 +704,8 @@ pub trait StrExt: Index<FullRange, Output = str> {
     /// let v: Vec<(uint, uint)> = "ababa".match_indices("aba").collect();
     /// assert_eq!(v, vec![(0, 3)]); // only the first `aba`
     /// ```
-    #[unstable = "might have its iterator type changed"]
+    #[unstable(feature = "collections",
+               reason = "might have its iterator type changed")]
     fn match_indices<'a>(&'a self, pat: &'a str) -> MatchIndices<'a> {
         core_str::StrExt::match_indices(&self[], pat)
     }
@@ -713,7 +721,8 @@ pub trait StrExt: Index<FullRange, Output = str> {
     /// let v: Vec<&str> = "1abcabc2".split_str("abc").collect();
     /// assert_eq!(v, vec!["1", "", "2"]);
     /// ```
-    #[unstable = "might get removed in the future in favor of a more generic split()"]
+    #[unstable(feature = "collections",
+               reason = "might get removed in the future in favor of a more generic split()")]
     fn split_str<'a>(&'a self, pat: &'a str) -> SplitStr<'a> {
         core_str::StrExt::split_str(&self[], pat)
     }
@@ -729,7 +738,7 @@ pub trait StrExt: Index<FullRange, Output = str> {
     /// let v: Vec<&str> = four_lines.lines().collect();
     /// assert_eq!(v, vec!["foo", "bar", "", "baz"]);
     /// ```
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     fn lines(&self) -> Lines {
         core_str::StrExt::lines(&self[])
     }
@@ -745,21 +754,27 @@ pub trait StrExt: Index<FullRange, Output = str> {
     /// let v: Vec<&str> = four_lines.lines_any().collect();
     /// assert_eq!(v, vec!["foo", "bar", "", "baz"]);
     /// ```
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     fn lines_any(&self) -> LinesAny {
         core_str::StrExt::lines_any(&self[])
     }
 
     /// Deprecated: use `s[a .. b]` instead.
-    #[deprecated = "use slice notation [a..b] instead"]
+    #[unstable(feature = "collections",
+               reason = "use slice notation [a..b] instead")]
+    #[deprecated(since = "1.0.0", reason = "use slice notation [a..b] instead")]
     fn slice(&self, begin: uint, end: uint) -> &str;
 
     /// Deprecated: use `s[a..]` instead.
-    #[deprecated = "use slice notation [a..] instead"]
+    #[unstable(feature = "collections",
+               reason = "use slice notation [a..b] instead")]
+    #[deprecated(since = "1.0.0", reason = "use slice notation [a..] instead")]
     fn slice_from(&self, begin: uint) -> &str;
 
     /// Deprecated: use `s[..a]` instead.
-    #[deprecated = "use slice notation [..a] instead"]
+    #[unstable(feature = "collections",
+               reason = "use slice notation [a..b] instead")]
+    #[deprecated(since = "1.0.0", reason = "use slice notation [..a] instead")]
     fn slice_to(&self, end: uint) -> &str;
 
     /// Returns a slice of the string from the character range
@@ -785,7 +800,8 @@ pub trait StrExt: Index<FullRange, Output = str> {
     /// assert_eq!(s.slice_chars(0, 4), "Löwe");
     /// assert_eq!(s.slice_chars(5, 7), "老虎");
     /// ```
-    #[unstable = "may have yet to prove its worth"]
+    #[unstable(feature = "collections",
+               reason = "may have yet to prove its worth")]
     fn slice_chars(&self, begin: uint, end: uint) -> &str {
         core_str::StrExt::slice_chars(&self[], begin, end)
     }
@@ -796,7 +812,7 @@ pub trait StrExt: Index<FullRange, Output = str> {
     ///
     /// Caller must check both UTF-8 character boundaries and the boundaries of
     /// the entire slice as well.
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     unsafe fn slice_unchecked(&self, begin: uint, end: uint) -> &str {
         core_str::StrExt::slice_unchecked(&self[], begin, end)
     }
@@ -808,7 +824,7 @@ pub trait StrExt: Index<FullRange, Output = str> {
     /// ```rust
     /// assert!("banana".starts_with("ba"));
     /// ```
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     fn starts_with(&self, pat: &str) -> bool {
         core_str::StrExt::starts_with(&self[], pat)
     }
@@ -820,7 +836,7 @@ pub trait StrExt: Index<FullRange, Output = str> {
     /// ```rust
     /// assert!("banana".ends_with("nana"));
     /// ```
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     fn ends_with(&self, pat: &str) -> bool {
         core_str::StrExt::ends_with(&self[], pat)
     }
@@ -840,7 +856,7 @@ pub trait StrExt: Index<FullRange, Output = str> {
     /// assert_eq!("12foo1bar12".trim_matches(x), "foo1bar");
     /// assert_eq!("123foo1bar123".trim_matches(|&: c: char| c.is_numeric()), "foo1bar");
     /// ```
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     fn trim_matches<P: CharEq>(&self, pat: P) -> &str {
         core_str::StrExt::trim_matches(&self[], pat)
     }
@@ -860,7 +876,7 @@ pub trait StrExt: Index<FullRange, Output = str> {
     /// assert_eq!("12foo1bar12".trim_left_matches(x), "foo1bar12");
     /// assert_eq!("123foo1bar123".trim_left_matches(|&: c: char| c.is_numeric()), "foo1bar123");
     /// ```
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     fn trim_left_matches<P: CharEq>(&self, pat: P) -> &str {
         core_str::StrExt::trim_left_matches(&self[], pat)
     }
@@ -880,7 +896,7 @@ pub trait StrExt: Index<FullRange, Output = str> {
     /// assert_eq!("12foo1bar12".trim_right_matches(x), "12foo1bar");
     /// assert_eq!("123foo1bar123".trim_right_matches(|&: c: char| c.is_numeric()), "123foo1bar");
     /// ```
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     fn trim_right_matches<P: CharEq>(&self, pat: P) -> &str {
         core_str::StrExt::trim_right_matches(&self[], pat)
     }
@@ -908,7 +924,8 @@ pub trait StrExt: Index<FullRange, Output = str> {
     /// // third byte of `老`
     /// assert!(!s.is_char_boundary(8));
     /// ```
-    #[unstable = "naming is uncertain with container conventions"]
+    #[unstable(feature = "collections",
+               reason = "naming is uncertain with container conventions")]
     fn is_char_boundary(&self, index: uint) -> bool {
         core_str::StrExt::is_char_boundary(&self[], index)
     }
@@ -966,7 +983,8 @@ pub trait StrExt: Index<FullRange, Output = str> {
     ///
     /// If `i` is greater than or equal to the length of the string.
     /// If `i` is not the index of the beginning of a valid UTF-8 character.
-    #[unstable = "naming is uncertain with container conventions"]
+    #[unstable(feature = "collections",
+               reason = "naming is uncertain with container conventions")]
     fn char_range_at(&self, start: uint) -> CharRange {
         core_str::StrExt::char_range_at(&self[], start)
     }
@@ -981,7 +999,8 @@ pub trait StrExt: Index<FullRange, Output = str> {
     ///
     /// If `i` is greater than the length of the string.
     /// If `i` is not an index following a valid UTF-8 character.
-    #[unstable = "naming is uncertain with container conventions"]
+    #[unstable(feature = "collections",
+               reason = "naming is uncertain with container conventions")]
     fn char_range_at_reverse(&self, start: uint) -> CharRange {
         core_str::StrExt::char_range_at_reverse(&self[], start)
     }
@@ -1001,7 +1020,8 @@ pub trait StrExt: Index<FullRange, Output = str> {
     ///
     /// If `i` is greater than or equal to the length of the string.
     /// If `i` is not the index of the beginning of a valid UTF-8 character.
-    #[unstable = "naming is uncertain with container conventions"]
+    #[unstable(feature = "collections",
+               reason = "naming is uncertain with container conventions")]
     fn char_at(&self, i: uint) -> char {
         core_str::StrExt::char_at(&self[], i)
     }
@@ -1012,7 +1032,8 @@ pub trait StrExt: Index<FullRange, Output = str> {
     ///
     /// If `i` is greater than the length of the string.
     /// If `i` is not an index following a valid UTF-8 character.
-    #[unstable = "naming is uncertain with container conventions"]
+    #[unstable(feature = "collections",
+               reason = "naming is uncertain with container conventions")]
     fn char_at_reverse(&self, i: uint) -> char {
         core_str::StrExt::char_at_reverse(&self[], i)
     }
@@ -1024,7 +1045,7 @@ pub trait StrExt: Index<FullRange, Output = str> {
     /// ```rust
     /// assert_eq!("bors".as_bytes(), b"bors");
     /// ```
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     fn as_bytes(&self) -> &[u8] {
         core_str::StrExt::as_bytes(&self[])
     }
@@ -1052,7 +1073,7 @@ pub trait StrExt: Index<FullRange, Output = str> {
     /// let x: &[_] = &['1', '2'];
     /// assert_eq!(s.find(x), None);
     /// ```
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     fn find<P: CharEq>(&self, pat: P) -> Option<uint> {
         core_str::StrExt::find(&self[], pat)
     }
@@ -1080,7 +1101,7 @@ pub trait StrExt: Index<FullRange, Output = str> {
     /// let x: &[_] = &['1', '2'];
     /// assert_eq!(s.rfind(x), None);
     /// ```
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     fn rfind<P: CharEq>(&self, pat: P) -> Option<uint> {
         core_str::StrExt::rfind(&self[], pat)
     }
@@ -1104,7 +1125,8 @@ pub trait StrExt: Index<FullRange, Output = str> {
     /// assert_eq!(s.find_str("老虎 L"), Some(6));
     /// assert_eq!(s.find_str("muffin man"), None);
     /// ```
-    #[unstable = "might get removed in favor of a more generic find in the future"]
+    #[unstable(feature = "collections",
+               reason = "might get removed in favor of a more generic find in the future")]
     fn find_str(&self, needle: &str) -> Option<uint> {
         core_str::StrExt::find_str(&self[], needle)
     }
@@ -1127,7 +1149,8 @@ pub trait StrExt: Index<FullRange, Output = str> {
     /// assert_eq!(c, 'ö');
     /// assert_eq!(s2, "we 老虎 Léopard");
     /// ```
-    #[unstable = "awaiting conventions about shifting and slices"]
+    #[unstable(feature = "collections",
+               reason = "awaiting conventions about shifting and slices")]
     fn slice_shift_char(&self) -> Option<(char, &str)> {
         core_str::StrExt::slice_shift_char(&self[])
     }
@@ -1146,7 +1169,8 @@ pub trait StrExt: Index<FullRange, Output = str> {
     /// assert!(string.subslice_offset(lines[1]) == 2); // &"b"
     /// assert!(string.subslice_offset(lines[2]) == 4); // &"c"
     /// ```
-    #[unstable = "awaiting convention about comparability of arbitrary slices"]
+    #[unstable(feature = "collections",
+               reason = "awaiting convention about comparability of arbitrary slices")]
     fn subslice_offset(&self, inner: &str) -> uint {
         core_str::StrExt::subslice_offset(&self[], inner)
     }
@@ -1156,14 +1180,15 @@ pub trait StrExt: Index<FullRange, Output = str> {
     /// The caller must ensure that the string outlives this pointer,
     /// and that it is not reallocated (e.g. by pushing to the
     /// string).
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     #[inline]
     fn as_ptr(&self) -> *const u8 {
         core_str::StrExt::as_ptr(&self[])
     }
 
     /// Return an iterator of `u16` over the string encoded as UTF-16.
-    #[unstable = "this functionality may only be provided by libunicode"]
+    #[unstable(feature = "collections",
+               reason = "this functionality may only be provided by libunicode")]
     fn utf16_units(&self) -> Utf16Units {
         Utf16Units { encoder: Utf16Encoder::new(self[].chars()) }
     }
@@ -1176,7 +1201,7 @@ pub trait StrExt: Index<FullRange, Output = str> {
     /// assert_eq!("foo".len(), 3);
     /// assert_eq!("ƒoo".len(), 4);
     /// ```
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     #[inline]
     fn len(&self) -> uint {
         core_str::StrExt::len(&self[])
@@ -1190,7 +1215,7 @@ pub trait StrExt: Index<FullRange, Output = str> {
     /// assert!("".is_empty());
     /// ```
     #[inline]
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     fn is_empty(&self) -> bool {
         core_str::StrExt::is_empty(&self[])
     }
@@ -1204,7 +1229,8 @@ pub trait StrExt: Index<FullRange, Output = str> {
     /// assert_eq!("j".parse::<u32>(), None);
     /// ```
     #[inline]
-    #[unstable = "this method was just created"]
+    #[unstable(feature = "collections",
+               reason = "this method was just created")]
     fn parse<F: FromStr>(&self) -> Option<F> {
         core_str::StrExt::parse(&self[])
     }
@@ -1228,7 +1254,8 @@ pub trait StrExt: Index<FullRange, Output = str> {
     /// let b: &[_] = &["a", "\r\n", "b", "🇷🇺🇸🇹"];
     /// assert_eq!(gr2.as_slice(), b);
     /// ```
-    #[unstable = "this functionality may only be provided by libunicode"]
+    #[unstable(feature = "collections",
+               reason = "this functionality may only be provided by libunicode")]
     fn graphemes(&self, is_extended: bool) -> Graphemes {
         UnicodeStr::graphemes(&self[], is_extended)
     }
@@ -1243,7 +1270,8 @@ pub trait StrExt: Index<FullRange, Output = str> {
     /// let b: &[_] = &[(0u, "a̐"), (3, "é"), (6, "ö̲"), (11, "\r\n")];
     /// assert_eq!(gr_inds.as_slice(), b);
     /// ```
-    #[unstable = "this functionality may only be provided by libunicode"]
+    #[unstable(feature = "collections",
+               reason = "this functionality may only be provided by libunicode")]
     fn grapheme_indices(&self, is_extended: bool) -> GraphemeIndices {
         UnicodeStr::grapheme_indices(&self[], is_extended)
     }
@@ -1259,7 +1287,7 @@ pub trait StrExt: Index<FullRange, Output = str> {
     /// let v: Vec<&str> = some_words.words().collect();
     /// assert_eq!(v, vec!["Mary", "had", "a", "little", "lamb"]);
     /// ```
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     fn words(&self) -> Words {
         UnicodeStr::words(&self[])
     }
@@ -1273,31 +1301,32 @@ pub trait StrExt: Index<FullRange, Output = str> {
     /// [Unicode Standard Annex #11](http://www.unicode.org/reports/tr11/)
     /// recommends that these characters be treated as 1 column (i.e.,
     /// `is_cjk` = `false`) if the locale is unknown.
-    #[unstable = "this functionality may only be provided by libunicode"]
+    #[unstable(feature = "collections",
+               reason = "this functionality may only be provided by libunicode")]
     fn width(&self, is_cjk: bool) -> uint {
         UnicodeStr::width(&self[], is_cjk)
     }
 
     /// Returns a string with leading and trailing whitespace removed.
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     fn trim(&self) -> &str {
         UnicodeStr::trim(&self[])
     }
 
     /// Returns a string with leading whitespace removed.
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     fn trim_left(&self) -> &str {
         UnicodeStr::trim_left(&self[])
     }
 
     /// Returns a string with trailing whitespace removed.
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     fn trim_right(&self) -> &str {
         UnicodeStr::trim_right(&self[])
     }
 }
 
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl StrExt for str {
     fn slice(&self, begin: uint, end: uint) -> &str {
         &self[begin..end]
diff --git a/src/libcollections/string.rs b/src/libcollections/string.rs
index 562189370d6..5189b825f16 100644
--- a/src/libcollections/string.rs
+++ b/src/libcollections/string.rs
@@ -12,7 +12,7 @@
 
 //! An owned, growable string that enforces that its contents are valid UTF-8.
 
-#![stable]
+#![stable(feature = "rust1", since = "1.0.0")]
 
 use core::prelude::*;
 
@@ -34,13 +34,13 @@ use vec::{DerefVec, Vec, as_vec};
 
 /// A growable string stored as a UTF-8 encoded buffer.
 #[derive(Clone, PartialOrd, Eq, Ord)]
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 pub struct String {
     vec: Vec<u8>,
 }
 
 /// A possible error value from the `String::from_utf8` function.
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 #[derive(Show)]
 pub struct FromUtf8Error {
     bytes: Vec<u8>,
@@ -48,7 +48,7 @@ pub struct FromUtf8Error {
 }
 
 /// A possible error value from the `String::from_utf16` function.
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 #[allow(missing_copy_implementations)]
 #[derive(Show)]
 pub struct FromUtf16Error(());
@@ -62,7 +62,7 @@ impl String {
     /// let mut s = String::new();
     /// ```
     #[inline]
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     pub fn new() -> String {
         String {
             vec: Vec::new(),
@@ -79,7 +79,7 @@ impl String {
     /// let mut s = String::with_capacity(10);
     /// ```
     #[inline]
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     pub fn with_capacity(capacity: uint) -> String {
         String {
             vec: Vec::with_capacity(capacity),
@@ -95,7 +95,8 @@ impl String {
     /// assert_eq!(s.as_slice(), "hello");
     /// ```
     #[inline]
-    #[unstable = "needs investigation to see if to_string() can match perf"]
+    #[unstable(feature = "collections",
+               reason = "needs investigation to see if to_string() can match perf")]
     pub fn from_str(string: &str) -> String {
         String { vec: ::slice::SliceExt::to_vec(string.as_bytes()) }
     }
@@ -123,7 +124,7 @@ impl String {
     /// assert_eq!(s.into_bytes(), vec![240, 144, 128]);
     /// ```
     #[inline]
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     pub fn from_utf8(vec: Vec<u8>) -> Result<String, FromUtf8Error> {
         match str::from_utf8(vec.as_slice()) {
             Ok(..) => Ok(String { vec: vec }),
@@ -141,7 +142,7 @@ impl String {
     /// let output = String::from_utf8_lossy(input);
     /// assert_eq!(output.as_slice(), "Hello \u{FFFD}World");
     /// ```
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     pub fn from_utf8_lossy<'a>(v: &'a [u8]) -> CowString<'a> {
         let mut i = 0;
         match str::from_utf8(v) {
@@ -279,7 +280,7 @@ impl String {
     /// v[4] = 0xD800;
     /// assert!(String::from_utf16(v).is_err());
     /// ```
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     pub fn from_utf16(v: &[u16]) -> Result<String, FromUtf16Error> {
         let mut s = String::with_capacity(v.len());
         for c in unicode_str::utf16_items(v) {
@@ -306,7 +307,7 @@ impl String {
     ///            "𝄞mus\u{FFFD}ic\u{FFFD}".to_string());
     /// ```
     #[inline]
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     pub fn from_utf16_lossy(v: &[u16]) -> String {
         unicode_str::utf16_items(v).map(|c| c.to_char_lossy()).collect()
     }
@@ -317,7 +318,7 @@ impl String {
     /// * We call `Vec::from_raw_parts` to get a `Vec<u8>`;
     /// * We assume that the `Vec` contains valid UTF-8.
     #[inline]
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     pub unsafe fn from_raw_parts(buf: *mut u8, length: uint, capacity: uint) -> String {
         String {
             vec: Vec::from_raw_parts(buf, length, capacity),
@@ -328,7 +329,7 @@ impl String {
     /// it contains valid UTF-8. This is unsafe because it assumes that
     /// the UTF-8-ness of the vector has already been validated.
     #[inline]
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     pub unsafe fn from_utf8_unchecked(bytes: Vec<u8>) -> String {
         String { vec: bytes }
     }
@@ -343,7 +344,7 @@ impl String {
     /// assert_eq!(bytes, vec![104, 101, 108, 108, 111]);
     /// ```
     #[inline]
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     pub fn into_bytes(self) -> Vec<u8> {
         self.vec
     }
@@ -358,7 +359,7 @@ impl String {
     /// assert_eq!(s.as_slice(), "foobar");
     /// ```
     #[inline]
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     pub fn push_str(&mut self, string: &str) {
         self.vec.push_all(string.as_bytes())
     }
@@ -373,7 +374,7 @@ impl String {
     /// assert!(s.capacity() >= 10);
     /// ```
     #[inline]
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     pub fn capacity(&self) -> uint {
         self.vec.capacity()
     }
@@ -394,7 +395,7 @@ impl String {
     /// assert!(s.capacity() >= 10);
     /// ```
     #[inline]
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     pub fn reserve(&mut self, additional: uint) {
         self.vec.reserve(additional)
     }
@@ -419,7 +420,7 @@ impl String {
     /// assert!(s.capacity() >= 10);
     /// ```
     #[inline]
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     pub fn reserve_exact(&mut self, additional: uint) {
         self.vec.reserve_exact(additional)
     }
@@ -436,7 +437,7 @@ impl String {
     /// assert_eq!(s.capacity(), 3);
     /// ```
     #[inline]
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     pub fn shrink_to_fit(&mut self) {
         self.vec.shrink_to_fit()
     }
@@ -453,7 +454,7 @@ impl String {
     /// assert_eq!(s.as_slice(), "abc123");
     /// ```
     #[inline]
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     pub fn push(&mut self, ch: char) {
         if (ch as u32) < 0x80 {
             self.vec.push(ch as u8);
@@ -486,7 +487,7 @@ impl String {
     /// assert_eq!(s.as_bytes(), b);
     /// ```
     #[inline]
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     pub fn as_bytes<'a>(&'a self) -> &'a [u8] {
         self.vec.as_slice()
     }
@@ -506,7 +507,7 @@ impl String {
     /// assert_eq!(s.as_slice(), "he");
     /// ```
     #[inline]
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     pub fn truncate(&mut self, new_len: uint) {
         assert!(self.is_char_boundary(new_len));
         self.vec.truncate(new_len)
@@ -525,7 +526,7 @@ impl String {
     /// assert_eq!(s.pop(), None);
     /// ```
     #[inline]
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     pub fn pop(&mut self) -> Option<char> {
         let len = self.len();
         if len == 0 {
@@ -561,7 +562,7 @@ impl String {
     /// assert_eq!(s.remove(0), 'o');
     /// ```
     #[inline]
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     pub fn remove(&mut self, idx: uint) -> char {
         let len = self.len();
         assert!(idx <= len);
@@ -588,7 +589,7 @@ impl String {
     /// If `idx` does not lie on a character boundary or is out of bounds, then
     /// this function will panic.
     #[inline]
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     pub fn insert(&mut self, idx: uint, ch: char) {
         let len = self.len();
         assert!(idx <= len);
@@ -625,7 +626,7 @@ impl String {
     /// assert_eq!(s.as_slice(), "olleh");
     /// ```
     #[inline]
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     pub unsafe fn as_mut_vec<'a>(&'a mut self) -> &'a mut Vec<u8> {
         &mut self.vec
     }
@@ -639,7 +640,7 @@ impl String {
     /// assert_eq!(a.len(), 3);
     /// ```
     #[inline]
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     pub fn len(&self) -> uint { self.vec.len() }
 
     /// Returns true if the string contains no bytes
@@ -653,7 +654,7 @@ impl String {
     /// assert!(!v.is_empty());
     /// ```
     #[inline]
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     pub fn is_empty(&self) -> bool { self.len() == 0 }
 
     /// Truncates the string, returning it to 0 length.
@@ -666,7 +667,7 @@ impl String {
     /// assert!(s.is_empty());
     /// ```
     #[inline]
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     pub fn clear(&mut self) {
         self.vec.clear()
     }
@@ -675,39 +676,39 @@ impl String {
 impl FromUtf8Error {
     /// Consume this error, returning the bytes that were attempted to make a
     /// `String` with.
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     pub fn into_bytes(self) -> Vec<u8> { self.bytes }
 
     /// Access the underlying UTF8-error that was the cause of this error.
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     pub fn utf8_error(&self) -> Utf8Error { self.error }
 }
 
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl fmt::Display for FromUtf8Error {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         fmt::Display::fmt(&self.error, f)
     }
 }
 
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl Error for FromUtf8Error {
     fn description(&self) -> &str { "invalid utf-8" }
 }
 
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl fmt::Display for FromUtf16Error {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         fmt::Display::fmt("invalid utf-16: lone surrogate found", f)
     }
 }
 
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl Error for FromUtf16Error {
     fn description(&self) -> &str { "invalid utf-16" }
 }
 
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl FromIterator<char> for String {
     fn from_iter<I:Iterator<Item=char>>(iterator: I) -> String {
         let mut buf = String::new();
@@ -716,7 +717,7 @@ impl FromIterator<char> for String {
     }
 }
 
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl<'a> FromIterator<&'a str> for String {
     fn from_iter<I:Iterator<Item=&'a str>>(iterator: I) -> String {
         let mut buf = String::new();
@@ -725,7 +726,8 @@ impl<'a> FromIterator<&'a str> for String {
     }
 }
 
-#[unstable = "waiting on Extend stabilization"]
+#[unstable(feature = "collections",
+           reason = "waiting on Extend stabilization")]
 impl Extend<char> for String {
     fn extend<I:Iterator<Item=char>>(&mut self, mut iterator: I) {
         let (lower_bound, _) = iterator.size_hint();
@@ -736,7 +738,8 @@ impl Extend<char> for String {
     }
 }
 
-#[unstable = "waiting on Extend stabilization"]
+#[unstable(feature = "collections",
+           reason = "waiting on Extend stabilization")]
 impl<'a> Extend<&'a str> for String {
     fn extend<I: Iterator<Item=&'a str>>(&mut self, mut iterator: I) {
         // A guess that at least one byte per iterator element will be needed.
@@ -748,7 +751,7 @@ impl<'a> Extend<&'a str> for String {
     }
 }
 
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl PartialEq for String {
     #[inline]
     fn eq(&self, other: &String) -> bool { PartialEq::eq(&**self, &**other) }
@@ -758,7 +761,7 @@ impl PartialEq for String {
 
 macro_rules! impl_eq {
     ($lhs:ty, $rhs: ty) => {
-        #[stable]
+        #[stable(feature = "rust1", since = "1.0.0")]
         impl<'a> PartialEq<$rhs> for $lhs {
             #[inline]
             fn eq(&self, other: &$rhs) -> bool { PartialEq::eq(&**self, &**other) }
@@ -766,7 +769,7 @@ macro_rules! impl_eq {
             fn ne(&self, other: &$rhs) -> bool { PartialEq::ne(&**self, &**other) }
         }
 
-        #[stable]
+        #[stable(feature = "rust1", since = "1.0.0")]
         impl<'a> PartialEq<$lhs> for $rhs {
             #[inline]
             fn eq(&self, other: &$lhs) -> bool { PartialEq::eq(&**self, &**other) }
@@ -780,7 +783,7 @@ macro_rules! impl_eq {
 impl_eq! { String, &'a str }
 impl_eq! { CowString<'a>, String }
 
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl<'a, 'b> PartialEq<&'b str> for CowString<'a> {
     #[inline]
     fn eq(&self, other: &&'b str) -> bool { PartialEq::eq(&**self, &**other) }
@@ -788,7 +791,7 @@ impl<'a, 'b> PartialEq<&'b str> for CowString<'a> {
     fn ne(&self, other: &&'b str) -> bool { PartialEq::ne(&**self, &**other) }
 }
 
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl<'a, 'b> PartialEq<CowString<'a>> for &'b str {
     #[inline]
     fn eq(&self, other: &CowString<'a>) -> bool { PartialEq::eq(&**self, &**other) }
@@ -796,25 +799,25 @@ impl<'a, 'b> PartialEq<CowString<'a>> for &'b str {
     fn ne(&self, other: &CowString<'a>) -> bool { PartialEq::ne(&**self, &**other) }
 }
 
-#[unstable = "waiting on Str stabilization"]
+#[unstable(feature = "collections", reason = "waiting on Str stabilization")]
 impl Str for String {
     #[inline]
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     fn as_slice<'a>(&'a self) -> &'a str {
         unsafe { mem::transmute(self.vec.as_slice()) }
     }
 }
 
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl Default for String {
     #[inline]
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     fn default() -> String {
         String::new()
     }
 }
 
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl fmt::Display for String {
     #[inline]
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
@@ -822,7 +825,7 @@ impl fmt::Display for String {
     }
 }
 
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl fmt::Debug for String {
     #[inline]
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
@@ -830,7 +833,7 @@ impl fmt::Debug for String {
     }
 }
 
-#[unstable = "waiting on Hash stabilization"]
+#[unstable(feature = "collections", reason = "waiting on Hash stabilization")]
 impl<H: hash::Writer + hash::Hasher> hash::Hash<H> for String {
     #[inline]
     fn hash(&self, hasher: &mut H) {
@@ -838,7 +841,8 @@ impl<H: hash::Writer + hash::Hasher> hash::Hash<H> for String {
     }
 }
 
-#[unstable = "recent addition, needs more experience"]
+#[unstable(feature = "collections",
+           reason = "recent addition, needs more experience")]
 impl<'a> Add<&'a str> for String {
     type Output = String;
 
@@ -849,7 +853,7 @@ impl<'a> Add<&'a str> for String {
     }
 }
 
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl ops::Index<ops::Range<uint>> for String {
     type Output = str;
     #[inline]
@@ -857,7 +861,7 @@ impl ops::Index<ops::Range<uint>> for String {
         &self[][*index]
     }
 }
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl ops::Index<ops::RangeTo<uint>> for String {
     type Output = str;
     #[inline]
@@ -865,7 +869,7 @@ impl ops::Index<ops::RangeTo<uint>> for String {
         &self[][*index]
     }
 }
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl ops::Index<ops::RangeFrom<uint>> for String {
     type Output = str;
     #[inline]
@@ -873,7 +877,7 @@ impl ops::Index<ops::RangeFrom<uint>> for String {
         &self[][*index]
     }
 }
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl ops::Index<ops::FullRange> for String {
     type Output = str;
     #[inline]
@@ -882,7 +886,7 @@ impl ops::Index<ops::FullRange> for String {
     }
 }
 
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl ops::Deref for String {
     type Target = str;
 
@@ -893,7 +897,7 @@ impl ops::Deref for String {
 }
 
 /// Wrapper type providing a `&String` reference via `Deref`.
-#[unstable]
+#[unstable(feature = "collections")]
 pub struct DerefString<'a> {
     x: DerefVec<'a, u8>
 }
@@ -921,7 +925,7 @@ impl<'a> Deref for DerefString<'a> {
 /// let string = as_string("foo").clone();
 /// string_consumer(string);
 /// ```
-#[unstable]
+#[unstable(feature = "collections")]
 pub fn as_string<'a>(x: &'a str) -> DerefString<'a> {
     DerefString { x: as_vec(x.as_bytes()) }
 }
@@ -965,7 +969,7 @@ impl<'a> IntoCow<'a, String, str> for &'a str {
 }
 
 /// A clone-on-write string
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 pub type CowString<'a> = Cow<'a, String, str>;
 
 impl<'a> Str for CowString<'a> {
diff --git a/src/libcollections/vec.rs b/src/libcollections/vec.rs
index 03736b3a3ff..367ab28e47b 100644
--- a/src/libcollections/vec.rs
+++ b/src/libcollections/vec.rs
@@ -44,7 +44,7 @@
 //! let two = xs.pop();
 //! ```
 
-#![stable]
+#![stable(feature = "rust1", since = "1.0.0")]
 
 use core::prelude::*;
 
@@ -134,7 +134,7 @@ use core::uint;
 /// to reallocate, which can be slow. For this reason, it is recommended to use
 /// `Vec::with_capacity` whenever possible to specify how big the vector is expected to get.
 #[unsafe_no_drop_flag]
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 pub struct Vec<T> {
     ptr: NonZero<*mut T>,
     len: uint,
@@ -159,7 +159,7 @@ impl<T> Vec<T> {
     /// let mut vec: Vec<int> = Vec::new();
     /// ```
     #[inline]
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     pub fn new() -> Vec<T> {
         // We want ptr to never be NULL so instead we set it to some arbitrary
         // non-null value which is fine since we never call deallocate on the ptr
@@ -194,7 +194,7 @@ impl<T> Vec<T> {
     /// vec.push(11);
     /// ```
     #[inline]
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     pub fn with_capacity(capacity: uint) -> Vec<T> {
         if mem::size_of::<T>() == 0 {
             Vec { ptr: unsafe { NonZero::new(EMPTY as *mut T) }, len: 0, cap: uint::MAX }
@@ -243,7 +243,7 @@ impl<T> Vec<T> {
     ///     }
     /// }
     /// ```
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     pub unsafe fn from_raw_parts(ptr: *mut T, length: uint,
                                  capacity: uint) -> Vec<T> {
         Vec { ptr: NonZero::new(ptr), len: length, cap: capacity }
@@ -255,7 +255,8 @@ impl<T> Vec<T> {
     /// owned by the returned `Vec<T>`. The elements of the buffer are copied into the vector
     /// without cloning, as if `ptr::read()` were called on them.
     #[inline]
-    #[unstable = "may be better expressed via composition"]
+    #[unstable(feature = "collections",
+               reason = "may be better expressed via composition")]
     pub unsafe fn from_raw_buf(ptr: *const T, elts: uint) -> Vec<T> {
         let mut dst = Vec::with_capacity(elts);
         dst.set_len(elts);
@@ -273,7 +274,7 @@ impl<T> Vec<T> {
     /// assert_eq!(vec.capacity(), 10);
     /// ```
     #[inline]
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     pub fn capacity(&self) -> uint {
         self.cap
     }
@@ -292,7 +293,7 @@ impl<T> Vec<T> {
     /// vec.reserve(10);
     /// assert!(vec.capacity() >= 11);
     /// ```
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     pub fn reserve(&mut self, additional: uint) {
         if self.cap - self.len < additional {
             let err_msg = "Vec::reserve: `uint` overflow";
@@ -321,7 +322,7 @@ impl<T> Vec<T> {
     /// vec.reserve_exact(10);
     /// assert!(vec.capacity() >= 11);
     /// ```
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     pub fn reserve_exact(&mut self, additional: uint) {
         if self.cap - self.len < additional {
             match self.len.checked_add(additional) {
@@ -345,7 +346,7 @@ impl<T> Vec<T> {
     /// vec.shrink_to_fit();
     /// assert!(vec.capacity() >= 3);
     /// ```
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     pub fn shrink_to_fit(&mut self) {
         if mem::size_of::<T>() == 0 { return }
 
@@ -376,7 +377,7 @@ impl<T> Vec<T> {
     /// Note that this will drop any excess capacity. Calling this and
     /// converting back to a vector with `into_vec()` is equivalent to calling
     /// `shrink_to_fit()`.
-    #[unstable]
+    #[unstable(feature = "collections")]
     pub fn into_boxed_slice(mut self) -> Box<[T]> {
         self.shrink_to_fit();
         unsafe {
@@ -398,7 +399,7 @@ impl<T> Vec<T> {
     /// vec.truncate(2);
     /// assert_eq!(vec, vec![1, 2]);
     /// ```
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     pub fn truncate(&mut self, len: uint) {
         unsafe {
             // drop any extra elements
@@ -422,7 +423,7 @@ impl<T> Vec<T> {
     /// foo(vec.as_mut_slice());
     /// ```
     #[inline]
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     pub fn as_mut_slice<'a>(&'a mut self) -> &'a mut [T] {
         unsafe {
             mem::transmute(RawSlice {
@@ -446,7 +447,7 @@ impl<T> Vec<T> {
     /// }
     /// ```
     #[inline]
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     pub fn into_iter(self) -> IntoIter<T> {
         unsafe {
             let ptr = *self.ptr;
@@ -477,7 +478,7 @@ impl<T> Vec<T> {
     /// }
     /// ```
     #[inline]
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     pub unsafe fn set_len(&mut self, len: uint) {
         self.len = len;
     }
@@ -503,7 +504,7 @@ impl<T> Vec<T> {
     /// assert_eq!(v, vec!["baz", "qux"]);
     /// ```
     #[inline]
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     pub fn swap_remove(&mut self, index: uint) -> T {
         let length = self.len();
         self.swap(index, length - 1);
@@ -527,7 +528,7 @@ impl<T> Vec<T> {
     /// vec.insert(4, 5);
     /// assert_eq!(vec, vec![1, 4, 2, 3, 5]);
     /// ```
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     pub fn insert(&mut self, index: uint, element: T) {
         let len = self.len();
         assert!(index <= len);
@@ -563,7 +564,7 @@ impl<T> Vec<T> {
     /// assert_eq!(v.remove(1), 2);
     /// assert_eq!(v, vec![1, 3]);
     /// ```
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     pub fn remove(&mut self, index: uint) -> T {
         let len = self.len();
         assert!(index < len);
@@ -597,7 +598,7 @@ impl<T> Vec<T> {
     /// vec.retain(|&x| x%2 == 0);
     /// assert_eq!(vec, vec![2, 4]);
     /// ```
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     pub fn retain<F>(&mut self, mut f: F) where F: FnMut(&T) -> bool {
         let len = self.len();
         let mut del = 0u;
@@ -631,7 +632,7 @@ impl<T> Vec<T> {
     /// assert_eq!(vec, vec!(1, 2, 3));
     /// ```
     #[inline]
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     pub fn push(&mut self, value: T) {
         if mem::size_of::<T>() == 0 {
             // zero-size types consume no memory, so we can't rely on the
@@ -669,7 +670,7 @@ impl<T> Vec<T> {
     /// assert_eq!(vec, vec![1, 2]);
     /// ```
     #[inline]
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     pub fn pop(&mut self) -> Option<T> {
         if self.len == 0 {
             None
@@ -696,7 +697,8 @@ impl<T> Vec<T> {
     /// assert_eq!(vec2, vec![]);
     /// ```
     #[inline]
-    #[unstable = "new API, waiting for dust to settle"]
+    #[unstable(feature = "collections",
+               reason = "new API, waiting for dust to settle")]
     pub fn append(&mut self, other: &mut Self) {
         if mem::size_of::<T>() == 0 {
             // zero-size types consume no memory, so we can't rely on the
@@ -732,7 +734,8 @@ impl<T> Vec<T> {
     /// assert!(v.is_empty());
     /// ```
     #[inline]
-    #[unstable = "matches collection reform specification, waiting for dust to settle"]
+    #[unstable(feature = "collections",
+               reason = "matches collection reform specification, waiting for dust to settle")]
     pub fn drain<'a>(&'a mut self) -> Drain<'a, T> {
         unsafe {
             let begin = *self.ptr as *const T;
@@ -762,7 +765,7 @@ impl<T> Vec<T> {
     /// assert!(v.is_empty());
     /// ```
     #[inline]
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     pub fn clear(&mut self) {
         self.truncate(0)
     }
@@ -776,7 +779,7 @@ impl<T> Vec<T> {
     /// assert_eq!(a.len(), 3);
     /// ```
     #[inline]
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     pub fn len(&self) -> uint { self.len }
 
     /// Returns `true` if the vector contains no elements.
@@ -790,7 +793,7 @@ impl<T> Vec<T> {
     /// v.push(1i);
     /// assert!(!v.is_empty());
     /// ```
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     pub fn is_empty(&self) -> bool { self.len() == 0 }
 
     /// Converts a `Vec<T>` to a `Vec<U>` where `T` and `U` have the same
@@ -814,7 +817,8 @@ impl<T> Vec<T> {
     /// let newtyped_bytes = bytes.map_in_place(|x| Newtype(x));
     /// assert_eq!(newtyped_bytes.as_slice(), [Newtype(0x11), Newtype(0x22)].as_slice());
     /// ```
-    #[unstable = "API may change to provide stronger guarantees"]
+    #[unstable(feature = "collections",
+               reason = "API may change to provide stronger guarantees")]
     pub fn map_in_place<U, F>(self, mut f: F) -> Vec<U> where F: FnMut(T) -> U {
         // FIXME: Assert statically that the types `T` and `U` have the same
         // size.
@@ -1005,7 +1009,8 @@ impl<T> Vec<T> {
     /// assert_eq!(vec2, vec![2, 3]);
     /// ```
     #[inline]
-    #[unstable = "new API, waiting for dust to settle"]
+    #[unstable(feature = "collections",
+               reason = "new API, waiting for dust to settle")]
     pub fn split_off(&mut self, at: usize) -> Self {
         assert!(at < self.len(), "`at` out of bounds");
 
@@ -1044,7 +1049,8 @@ impl<T: Clone> Vec<T> {
     /// vec.resize(2, 0);
     /// assert_eq!(vec, vec![1, 2]);
     /// ```
-    #[unstable = "matches collection reform specification; waiting for dust to settle"]
+    #[unstable(feature = "collections",
+               reason = "matches collection reform specification; waiting for dust to settle")]
     pub fn resize(&mut self, new_len: uint, value: T) {
         let len = self.len();
 
@@ -1068,7 +1074,8 @@ impl<T: Clone> Vec<T> {
     /// assert_eq!(vec, vec![1, 2, 3, 4]);
     /// ```
     #[inline]
-    #[unstable = "likely to be replaced by a more optimized extend"]
+    #[unstable(feature = "collections",
+               reason = "likely to be replaced by a more optimized extend")]
     pub fn push_all(&mut self, other: &[T]) {
         self.reserve(other.len());
 
@@ -1102,7 +1109,7 @@ impl<T: PartialEq> Vec<T> {
     ///
     /// assert_eq!(vec, vec![1i, 2, 3, 2]);
     /// ```
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     pub fn dedup(&mut self) {
         unsafe {
             // Although we have a mutable reference to `self`, we cannot make
@@ -1236,7 +1243,7 @@ unsafe fn dealloc<T>(ptr: *mut T, len: uint) {
 // Common trait implementations for Vec
 ////////////////////////////////////////////////////////////////////////////////
 
-#[unstable]
+#[unstable(feature = "collections")]
 impl<T:Clone> Clone for Vec<T> {
     fn clone(&self) -> Vec<T> { ::slice::SliceExt::to_vec(self.as_slice()) }
 
@@ -1265,7 +1272,7 @@ impl<S: hash::Writer + hash::Hasher, T: Hash<S>> Hash<S> for Vec<T> {
     }
 }
 
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl<T> Index<uint> for Vec<T> {
     type Output = T;
 
@@ -1275,7 +1282,7 @@ impl<T> Index<uint> for Vec<T> {
     }
 }
 
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl<T> IndexMut<uint> for Vec<T> {
     type Output = T;
 
@@ -1286,7 +1293,7 @@ impl<T> IndexMut<uint> for Vec<T> {
 }
 
 
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl<T> ops::Index<ops::Range<uint>> for Vec<T> {
     type Output = [T];
     #[inline]
@@ -1294,7 +1301,7 @@ impl<T> ops::Index<ops::Range<uint>> for Vec<T> {
         self.as_slice().index(index)
     }
 }
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl<T> ops::Index<ops::RangeTo<uint>> for Vec<T> {
     type Output = [T];
     #[inline]
@@ -1302,7 +1309,7 @@ impl<T> ops::Index<ops::RangeTo<uint>> for Vec<T> {
         self.as_slice().index(index)
     }
 }
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl<T> ops::Index<ops::RangeFrom<uint>> for Vec<T> {
     type Output = [T];
     #[inline]
@@ -1310,7 +1317,7 @@ impl<T> ops::Index<ops::RangeFrom<uint>> for Vec<T> {
         self.as_slice().index(index)
     }
 }
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl<T> ops::Index<ops::FullRange> for Vec<T> {
     type Output = [T];
     #[inline]
@@ -1319,7 +1326,7 @@ impl<T> ops::Index<ops::FullRange> for Vec<T> {
     }
 }
 
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl<T> ops::IndexMut<ops::Range<uint>> for Vec<T> {
     type Output = [T];
     #[inline]
@@ -1327,7 +1334,7 @@ impl<T> ops::IndexMut<ops::Range<uint>> for Vec<T> {
         self.as_mut_slice().index_mut(index)
     }
 }
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl<T> ops::IndexMut<ops::RangeTo<uint>> for Vec<T> {
     type Output = [T];
     #[inline]
@@ -1335,7 +1342,7 @@ impl<T> ops::IndexMut<ops::RangeTo<uint>> for Vec<T> {
         self.as_mut_slice().index_mut(index)
     }
 }
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl<T> ops::IndexMut<ops::RangeFrom<uint>> for Vec<T> {
     type Output = [T];
     #[inline]
@@ -1343,7 +1350,7 @@ impl<T> ops::IndexMut<ops::RangeFrom<uint>> for Vec<T> {
         self.as_mut_slice().index_mut(index)
     }
 }
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl<T> ops::IndexMut<ops::FullRange> for Vec<T> {
     type Output = [T];
     #[inline]
@@ -1352,19 +1359,19 @@ impl<T> ops::IndexMut<ops::FullRange> for Vec<T> {
     }
 }
 
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl<T> ops::Deref for Vec<T> {
     type Target = [T];
 
     fn deref<'a>(&'a self) -> &'a [T] { self.as_slice() }
 }
 
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl<T> ops::DerefMut for Vec<T> {
     fn deref_mut<'a>(&'a mut self) -> &'a mut [T] { self.as_mut_slice() }
 }
 
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl<T> FromIterator<T> for Vec<T> {
     #[inline]
     fn from_iter<I:Iterator<Item=T>>(mut iterator: I) -> Vec<T> {
@@ -1377,7 +1384,7 @@ impl<T> FromIterator<T> for Vec<T> {
     }
 }
 
-#[unstable = "waiting on Extend stability"]
+#[unstable(feature = "collections", reason = "waiting on Extend stability")]
 impl<T> Extend<T> for Vec<T> {
     #[inline]
     fn extend<I: Iterator<Item=T>>(&mut self, mut iterator: I) {
@@ -1452,7 +1459,8 @@ macro_rules! impl_eq_for_cowvec {
 impl_eq_for_cowvec! { &'b [B] }
 impl_eq_for_cowvec! { &'b mut [B] }
 
-#[unstable = "waiting on PartialOrd stability"]
+#[unstable(feature = "collections",
+           reason = "waiting on PartialOrd stability")]
 impl<T: PartialOrd> PartialOrd for Vec<T> {
     #[inline]
     fn partial_cmp(&self, other: &Vec<T>) -> Option<Ordering> {
@@ -1460,10 +1468,10 @@ impl<T: PartialOrd> PartialOrd for Vec<T> {
     }
 }
 
-#[unstable = "waiting on Eq stability"]
+#[unstable(feature = "collections", reason = "waiting on Eq stability")]
 impl<T: Eq> Eq for Vec<T> {}
 
-#[unstable = "waiting on Ord stability"]
+#[unstable(feature = "collections", reason = "waiting on Ord stability")]
 impl<T: Ord> Ord for Vec<T> {
     #[inline]
     fn cmp(&self, other: &Vec<T>) -> Ordering {
@@ -1483,7 +1491,7 @@ impl<T> AsSlice<T> for Vec<T> {
     /// foo(vec.as_slice());
     /// ```
     #[inline]
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     fn as_slice<'a>(&'a self) -> &'a [T] {
         unsafe {
             mem::transmute(RawSlice {
@@ -1494,7 +1502,8 @@ impl<T> AsSlice<T> for Vec<T> {
     }
 }
 
-#[unstable = "recent addition, needs more experience"]
+#[unstable(feature = "collections",
+           reason = "recent addition, needs more experience")]
 impl<'a, T: Clone> Add<&'a [T]> for Vec<T> {
     type Output = Vec<T>;
 
@@ -1506,7 +1515,7 @@ impl<'a, T: Clone> Add<&'a [T]> for Vec<T> {
 }
 
 #[unsafe_destructor]
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl<T> Drop for Vec<T> {
     fn drop(&mut self) {
         // This is (and should always remain) a no-op if the fields are
@@ -1522,15 +1531,15 @@ impl<T> Drop for Vec<T> {
     }
 }
 
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl<T> Default for Vec<T> {
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     fn default() -> Vec<T> {
         Vec::new()
     }
 }
 
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl<T: fmt::Debug> fmt::Debug for Vec<T> {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         fmt::Debug::fmt(self.as_slice(), f)
@@ -1548,11 +1557,12 @@ impl<'a> fmt::Writer for Vec<u8> {
 // Clone-on-write
 ////////////////////////////////////////////////////////////////////////////////
 
-#[unstable = "unclear how valuable this alias is"]
+#[unstable(feature = "collections",
+           reason = "unclear how valuable this alias is")]
 /// A clone-on-write vector
 pub type CowVec<'a, T> = Cow<'a, Vec<T>, [T]>;
 
-#[unstable]
+#[unstable(feature = "collections")]
 impl<'a, T> FromIterator<T> for CowVec<'a, T> where T: Clone {
     fn from_iter<I: Iterator<Item=T>>(it: I) -> CowVec<'a, T> {
         Cow::Owned(FromIterator::from_iter(it))
@@ -1576,7 +1586,7 @@ impl<'a, T> IntoCow<'a, Vec<T>, [T]> for &'a [T] where T: Clone {
 ////////////////////////////////////////////////////////////////////////////////
 
 /// An iterator that moves out of a vector.
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 pub struct IntoIter<T> {
     allocation: *mut T, // the block of memory allocated for the vector
     cap: uint, // the capacity of the vector
@@ -1590,7 +1600,7 @@ unsafe impl<T: Sync> Sync for IntoIter<T> { }
 impl<T> IntoIter<T> {
     #[inline]
     /// Drops all items that have not yet been moved and returns the empty vector.
-    #[unstable]
+    #[unstable(feature = "collections")]
     pub fn into_inner(mut self) -> Vec<T> {
         unsafe {
             for _x in self { }
@@ -1601,7 +1611,7 @@ impl<T> IntoIter<T> {
     }
 }
 
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl<T> Iterator for IntoIter<T> {
     type Item = T;
 
@@ -1638,7 +1648,7 @@ impl<T> Iterator for IntoIter<T> {
     }
 }
 
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl<T> DoubleEndedIterator for IntoIter<T> {
     #[inline]
     fn next_back<'a>(&'a mut self) -> Option<T> {
@@ -1662,11 +1672,11 @@ impl<T> DoubleEndedIterator for IntoIter<T> {
     }
 }
 
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl<T> ExactSizeIterator for IntoIter<T> {}
 
 #[unsafe_destructor]
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl<T> Drop for IntoIter<T> {
     fn drop(&mut self) {
         // destroy the remaining elements
@@ -1681,14 +1691,15 @@ impl<T> Drop for IntoIter<T> {
 
 /// An iterator that drains a vector.
 #[unsafe_no_drop_flag]
-#[unstable = "recently added as part of collections reform 2"]
+#[unstable(feature = "collections",
+           reason = "recently added as part of collections reform 2")]
 pub struct Drain<'a, T> {
     ptr: *const T,
     end: *const T,
     marker: ContravariantLifetime<'a>,
 }
 
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl<'a, T> Iterator for Drain<'a, T> {
     type Item = T;
 
@@ -1725,7 +1736,7 @@ impl<'a, T> Iterator for Drain<'a, T> {
     }
 }
 
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl<'a, T> DoubleEndedIterator for Drain<'a, T> {
     #[inline]
     fn next_back(&mut self) -> Option<T> {
@@ -1749,11 +1760,11 @@ impl<'a, T> DoubleEndedIterator for Drain<'a, T> {
     }
 }
 
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl<'a, T> ExactSizeIterator for Drain<'a, T> {}
 
 #[unsafe_destructor]
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl<'a, T> Drop for Drain<'a, T> {
     fn drop(&mut self) {
         // self.ptr == self.end == null if drop has already been called,
@@ -1769,13 +1780,13 @@ impl<'a, T> Drop for Drain<'a, T> {
 ////////////////////////////////////////////////////////////////////////////////
 
 /// Wrapper type providing a `&Vec<T>` reference via `Deref`.
-#[unstable]
+#[unstable(feature = "collections")]
 pub struct DerefVec<'a, T> {
     x: Vec<T>,
     l: ContravariantLifetime<'a>
 }
 
-#[unstable]
+#[unstable(feature = "collections")]
 impl<'a, T> Deref for DerefVec<'a, T> {
     type Target = Vec<T>;
 
@@ -1786,7 +1797,7 @@ impl<'a, T> Deref for DerefVec<'a, T> {
 
 // Prevent the inner `Vec<T>` from attempting to deallocate memory.
 #[unsafe_destructor]
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl<'a, T> Drop for DerefVec<'a, T> {
     fn drop(&mut self) {
         self.x.len = 0;
@@ -1795,7 +1806,7 @@ impl<'a, T> Drop for DerefVec<'a, T> {
 }
 
 /// Convert a slice to a wrapper type providing a `&Vec<T>` reference.
-#[unstable]
+#[unstable(feature = "collections")]
 pub fn as_vec<'a, T>(x: &'a [T]) -> DerefVec<'a, T> {
     unsafe {
         DerefVec {
diff --git a/src/libcollections/vec_map.rs b/src/libcollections/vec_map.rs
index f178d5bc7e9..3d28284c9bf 100644
--- a/src/libcollections/vec_map.rs
+++ b/src/libcollections/vec_map.rs
@@ -66,9 +66,9 @@ pub struct VecMap<V> {
     v: Vec<Option<V>>,
 }
 
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl<V> Default for VecMap<V> {
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     #[inline]
     fn default() -> VecMap<V> { VecMap::new() }
 }
@@ -107,7 +107,7 @@ impl<V> VecMap<V> {
     /// use std::collections::VecMap;
     /// let mut map: VecMap<&str> = VecMap::new();
     /// ```
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     pub fn new() -> VecMap<V> { VecMap { v: vec![] } }
 
     /// Creates an empty `VecMap` with space for at least `capacity`
@@ -119,7 +119,7 @@ impl<V> VecMap<V> {
     /// use std::collections::VecMap;
     /// let mut map: VecMap<&str> = VecMap::with_capacity(10);
     /// ```
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     pub fn with_capacity(capacity: uint) -> VecMap<V> {
         VecMap { v: Vec::with_capacity(capacity) }
     }
@@ -135,7 +135,7 @@ impl<V> VecMap<V> {
     /// assert!(map.capacity() >= 10);
     /// ```
     #[inline]
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     pub fn capacity(&self) -> uint {
         self.v.capacity()
     }
@@ -154,7 +154,7 @@ impl<V> VecMap<V> {
     /// map.reserve_len(10);
     /// assert!(map.capacity() >= 10);
     /// ```
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     pub fn reserve_len(&mut self, len: uint) {
         let cur_len = self.v.len();
         if len >= cur_len {
@@ -178,7 +178,7 @@ impl<V> VecMap<V> {
     /// map.reserve_len_exact(10);
     /// assert!(map.capacity() >= 10);
     /// ```
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     pub fn reserve_len_exact(&mut self, len: uint) {
         let cur_len = self.v.len();
         if len >= cur_len {
@@ -188,7 +188,7 @@ impl<V> VecMap<V> {
 
     /// Returns an iterator visiting all keys in ascending order of the keys.
     /// The iterator's element type is `uint`.
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     pub fn keys<'r>(&'r self) -> Keys<'r, V> {
         fn first<A, B>((a, _): (A, B)) -> A { a }
         let first: fn((uint, &'r V)) -> uint = first; // coerce to fn pointer
@@ -198,7 +198,7 @@ impl<V> VecMap<V> {
 
     /// Returns an iterator visiting all values in ascending order of the keys.
     /// The iterator's element type is `&'r V`.
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     pub fn values<'r>(&'r self) -> Values<'r, V> {
         fn second<A, B>((_, b): (A, B)) -> B { b }
         let second: fn((uint, &'r V)) -> &'r V = second; // coerce to fn pointer
@@ -224,7 +224,7 @@ impl<V> VecMap<V> {
     ///     println!("{}: {}", key, value);
     /// }
     /// ```
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     pub fn iter<'r>(&'r self) -> Iter<'r, V> {
         Iter {
             front: 0,
@@ -255,7 +255,7 @@ impl<V> VecMap<V> {
     ///     assert_eq!(value, &"x");
     /// }
     /// ```
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     pub fn iter_mut<'r>(&'r mut self) -> IterMut<'r, V> {
         IterMut {
             front: 0,
@@ -282,7 +282,7 @@ impl<V> VecMap<V> {
     ///
     /// assert_eq!(vec, vec![(1, "a"), (2, "b"), (3, "c")]);
     /// ```
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     pub fn into_iter(self) -> IntoIter<V> {
         fn filter<A>((i, v): (uint, Option<A>)) -> Option<(uint, A)> {
             v.map(|v| (i, v))
@@ -310,7 +310,8 @@ impl<V> VecMap<V> {
     ///
     /// assert_eq!(vec, vec![(1, "a"), (2, "b"), (3, "c")]);
     /// ```
-    #[unstable = "matches collection reform specification, waiting for dust to settle"]
+    #[unstable(feature = "collections",
+               reason = "matches collection reform specification, waiting for dust to settle")]
     pub fn drain<'a>(&'a mut self) -> Drain<'a, V> {
         fn filter<A>((i, v): (uint, Option<A>)) -> Option<(uint, A)> {
             v.map(|v| (i, v))
@@ -332,7 +333,7 @@ impl<V> VecMap<V> {
     /// a.insert(1, "a");
     /// assert_eq!(a.len(), 1);
     /// ```
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     pub fn len(&self) -> uint {
         self.v.iter().filter(|elt| elt.is_some()).count()
     }
@@ -349,7 +350,7 @@ impl<V> VecMap<V> {
     /// a.insert(1, "a");
     /// assert!(!a.is_empty());
     /// ```
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     pub fn is_empty(&self) -> bool {
         self.v.iter().all(|elt| elt.is_none())
     }
@@ -366,7 +367,7 @@ impl<V> VecMap<V> {
     /// a.clear();
     /// assert!(a.is_empty());
     /// ```
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     pub fn clear(&mut self) { self.v.clear() }
 
     /// Returns a reference to the value corresponding to the key.
@@ -381,7 +382,7 @@ impl<V> VecMap<V> {
     /// assert_eq!(map.get(&1), Some(&"a"));
     /// assert_eq!(map.get(&2), None);
     /// ```
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     pub fn get(&self, key: &uint) -> Option<&V> {
         if *key < self.v.len() {
             match self.v[*key] {
@@ -406,7 +407,7 @@ impl<V> VecMap<V> {
     /// assert_eq!(map.contains_key(&2), false);
     /// ```
     #[inline]
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     pub fn contains_key(&self, key: &uint) -> bool {
         self.get(key).is_some()
     }
@@ -426,7 +427,7 @@ impl<V> VecMap<V> {
     /// }
     /// assert_eq!(map[1], "b");
     /// ```
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     pub fn get_mut(&mut self, key: &uint) -> Option<&mut V> {
         if *key < self.v.len() {
             match *(&mut self.v[*key]) {
@@ -454,7 +455,7 @@ impl<V> VecMap<V> {
     /// assert_eq!(map.insert(37, "c"), Some("b"));
     /// assert_eq!(map[37], "c");
     /// ```
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     pub fn insert(&mut self, key: uint, value: V) -> Option<V> {
         let len = self.v.len();
         if len <= key {
@@ -476,7 +477,7 @@ impl<V> VecMap<V> {
     /// assert_eq!(map.remove(&1), Some("a"));
     /// assert_eq!(map.remove(&1), None);
     /// ```
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     pub fn remove(&mut self, key: &uint) -> Option<V> {
         if *key >= self.v.len() {
             return None;
@@ -486,17 +487,17 @@ impl<V> VecMap<V> {
     }
 }
 
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl<V: PartialEq> PartialEq for VecMap<V> {
     fn eq(&self, other: &VecMap<V>) -> bool {
         iter::order::eq(self.iter(), other.iter())
     }
 }
 
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl<V: Eq> Eq for VecMap<V> {}
 
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl<V: PartialOrd> PartialOrd for VecMap<V> {
     #[inline]
     fn partial_cmp(&self, other: &VecMap<V>) -> Option<Ordering> {
@@ -504,7 +505,7 @@ impl<V: PartialOrd> PartialOrd for VecMap<V> {
     }
 }
 
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl<V: Ord> Ord for VecMap<V> {
     #[inline]
     fn cmp(&self, other: &VecMap<V>) -> Ordering {
@@ -512,7 +513,7 @@ impl<V: Ord> Ord for VecMap<V> {
     }
 }
 
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl<V: fmt::Debug> fmt::Debug for VecMap<V> {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         try!(write!(f, "VecMap {{"));
@@ -526,7 +527,7 @@ impl<V: fmt::Debug> fmt::Debug for VecMap<V> {
     }
 }
 
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl<V> FromIterator<(uint, V)> for VecMap<V> {
     fn from_iter<Iter: Iterator<Item=(uint, V)>>(iter: Iter) -> VecMap<V> {
         let mut map = VecMap::new();
@@ -535,7 +536,7 @@ impl<V> FromIterator<(uint, V)> for VecMap<V> {
     }
 }
 
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl<V> Extend<(uint, V)> for VecMap<V> {
     fn extend<Iter: Iterator<Item=(uint, V)>>(&mut self, mut iter: Iter) {
         for (k, v) in iter {
@@ -553,7 +554,7 @@ impl<V> Index<uint> for VecMap<V> {
     }
 }
 
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl<V> IndexMut<uint> for VecMap<V> {
     type Output = V;
 
@@ -565,7 +566,7 @@ impl<V> IndexMut<uint> for VecMap<V> {
 
 macro_rules! iterator {
     (impl $name:ident -> $elem:ty, $($getter:ident),+) => {
-        #[stable]
+        #[stable(feature = "rust1", since = "1.0.0")]
         impl<'a, V> Iterator for $name<'a, V> {
             type Item = $elem;
 
@@ -600,7 +601,7 @@ macro_rules! iterator {
 
 macro_rules! double_ended_iterator {
     (impl $name:ident -> $elem:ty, $($getter:ident),+) => {
-        #[stable]
+        #[stable(feature = "rust1", since = "1.0.0")]
         impl<'a, V> DoubleEndedIterator for $name<'a, V> {
             #[inline]
             fn next_back(&mut self) -> Option<$elem> {
@@ -626,7 +627,7 @@ macro_rules! double_ended_iterator {
 }
 
 /// An iterator over the key-value pairs of a map.
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 pub struct Iter<'a, V:'a> {
     front: uint,
     back: uint,
@@ -649,7 +650,7 @@ double_ended_iterator! { impl Iter -> (uint, &'a V), as_ref }
 
 /// An iterator over the key-value pairs of a map, with the
 /// values being mutable.
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 pub struct IterMut<'a, V:'a> {
     front: uint,
     back: uint,
@@ -660,7 +661,7 @@ iterator! { impl IterMut -> (uint, &'a mut V), as_mut }
 double_ended_iterator! { impl IterMut -> (uint, &'a mut V), as_mut }
 
 /// An iterator over the keys of a map.
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 pub struct Keys<'a, V: 'a> {
     iter: Map<(uint, &'a V), uint, Iter<'a, V>, fn((uint, &'a V)) -> uint>
 }
@@ -675,7 +676,7 @@ impl<'a, V> Clone for Keys<'a, V> {
 }
 
 /// An iterator over the values of a map.
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 pub struct Values<'a, V: 'a> {
     iter: Map<(uint, &'a V), &'a V, Iter<'a, V>, fn((uint, &'a V)) -> &'a V>
 }
@@ -690,7 +691,7 @@ impl<'a, V> Clone for Values<'a, V> {
 }
 
 /// A consuming iterator over the key-value pairs of a map.
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 pub struct IntoIter<V> {
     iter: FilterMap<
     (uint, Option<V>),
@@ -699,7 +700,7 @@ pub struct IntoIter<V> {
     fn((uint, Option<V>)) -> Option<(uint, V)>>
 }
 
-#[unstable]
+#[unstable(feature = "collections")]
 pub struct Drain<'a, V> {
     iter: FilterMap<
     (uint, Option<V>),
@@ -708,7 +709,7 @@ pub struct Drain<'a, V> {
     fn((uint, Option<V>)) -> Option<(uint, V)>>
 }
 
-#[unstable]
+#[unstable(feature = "collections")]
 impl<'a, V> Iterator for Drain<'a, V> {
     type Item = (uint, V);
 
@@ -716,43 +717,43 @@ impl<'a, V> Iterator for Drain<'a, V> {
     fn size_hint(&self) -> (uint, Option<uint>) { self.iter.size_hint() }
 }
 
-#[unstable]
+#[unstable(feature = "collections")]
 impl<'a, V> DoubleEndedIterator for Drain<'a, V> {
     fn next_back(&mut self) -> Option<(uint, V)> { self.iter.next_back() }
 }
 
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl<'a, V> Iterator for Keys<'a, V> {
     type Item = uint;
 
     fn next(&mut self) -> Option<uint> { self.iter.next() }
     fn size_hint(&self) -> (uint, Option<uint>) { self.iter.size_hint() }
 }
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl<'a, V> DoubleEndedIterator for Keys<'a, V> {
     fn next_back(&mut self) -> Option<uint> { self.iter.next_back() }
 }
 
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl<'a, V> Iterator for Values<'a, V> {
     type Item = &'a V;
 
     fn next(&mut self) -> Option<(&'a V)> { self.iter.next() }
     fn size_hint(&self) -> (uint, Option<uint>) { self.iter.size_hint() }
 }
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl<'a, V> DoubleEndedIterator for Values<'a, V> {
     fn next_back(&mut self) -> Option<(&'a V)> { self.iter.next_back() }
 }
 
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl<V> Iterator for IntoIter<V> {
     type Item = (uint, V);
 
     fn next(&mut self) -> Option<(uint, V)> { self.iter.next() }
     fn size_hint(&self) -> (uint, Option<uint>) { self.iter.size_hint() }
 }
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl<V> DoubleEndedIterator for IntoIter<V> {
     fn next_back(&mut self) -> Option<(uint, V)> { self.iter.next_back() }
 }
diff --git a/src/libcore/any.rs b/src/libcore/any.rs
index 9966f0d4bf7..87030ed778d 100644
--- a/src/libcore/any.rs
+++ b/src/libcore/any.rs
@@ -69,7 +69,7 @@
 //! }
 //! ```
 
-#![stable]
+#![stable(feature = "rust1", since = "1.0.0")]
 
 use mem::transmute;
 use option::Option::{self, Some, None};
@@ -86,10 +86,11 @@ use marker::Sized;
 ///
 /// Every type with no non-`'static` references implements `Any`, so `Any` can
 /// be used as a trait object to emulate the effects dynamic typing.
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 pub trait Any: 'static {
     /// Get the `TypeId` of `self`
-    #[unstable = "this method will likely be replaced by an associated static"]
+    #[unstable(feature = "core",
+               reason = "this method will likely be replaced by an associated static")]
     fn get_type_id(&self) -> TypeId;
 }
 
@@ -103,7 +104,7 @@ impl<T: 'static> Any for T {
 
 impl Any {
     /// Returns true if the boxed type is the same as `T`
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     #[inline]
     pub fn is<T: 'static>(&self) -> bool {
         // Get TypeId of the type this function is instantiated with
@@ -118,7 +119,7 @@ impl Any {
 
     /// Returns some reference to the boxed value if it is of type `T`, or
     /// `None` if it isn't.
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     #[inline]
     pub fn downcast_ref<T: 'static>(&self) -> Option<&T> {
         if self.is::<T>() {
@@ -136,7 +137,7 @@ impl Any {
 
     /// Returns some mutable reference to the boxed value if it is of type `T`, or
     /// `None` if it isn't.
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     #[inline]
     pub fn downcast_mut<T: 'static>(&mut self) -> Option<&mut T> {
         if self.is::<T>() {
@@ -167,7 +168,7 @@ impl Any {
 /// but this limitation may be removed in the future.
 #[cfg_attr(stage0, lang = "type_id")]
 #[derive(Clone, Copy, PartialEq, Eq, Show, Hash)]
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 pub struct TypeId {
     t: u64,
 }
@@ -175,7 +176,8 @@ pub struct TypeId {
 impl TypeId {
     /// Returns the `TypeId` of the type this generic function has been
     /// instantiated with
-    #[unstable = "may grow a `Reflect` bound soon via marker traits"]
+    #[unstable(feature = "core",
+               reason = "may grow a `Reflect` bound soon via marker traits")]
     pub fn of<T: ?Sized + 'static>() -> TypeId {
         TypeId {
             t: unsafe { intrinsics::type_id::<T>() },
diff --git a/src/libcore/array.rs b/src/libcore/array.rs
index a83537e12f7..44541c34ee2 100644
--- a/src/libcore/array.rs
+++ b/src/libcore/array.rs
@@ -12,7 +12,7 @@
 //! up to a certain length. Eventually we should able to generalize
 //! to all lengths.
 
-#![unstable] // not yet reviewed
+#![unstable(feature = "core")] // not yet reviewed
 
 use clone::Clone;
 use cmp::{PartialEq, Eq, PartialOrd, Ord, Ordering};
@@ -26,7 +26,7 @@ use option::Option;
 macro_rules! array_impls {
     ($($N:expr)+) => {
         $(
-            #[stable]
+            #[stable(feature = "rust1", since = "1.0.0")]
             impl<T:Copy> Clone for [T; $N] {
                 fn clone(&self) -> [T; $N] {
                     *self
@@ -39,14 +39,14 @@ macro_rules! array_impls {
                 }
             }
 
-            #[stable]
+            #[stable(feature = "rust1", since = "1.0.0")]
             impl<T: fmt::Debug> fmt::Debug for [T; $N] {
                 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
                     fmt::Debug::fmt(&&self[], f)
                 }
             }
 
-            #[stable]
+            #[stable(feature = "rust1", since = "1.0.0")]
             impl<A, B> PartialEq<[B; $N]> for [A; $N] where A: PartialEq<B> {
                 #[inline]
                 fn eq(&self, other: &[B; $N]) -> bool {
@@ -58,7 +58,7 @@ macro_rules! array_impls {
                 }
             }
 
-            #[stable]
+            #[stable(feature = "rust1", since = "1.0.0")]
             impl<'a, A, B, Rhs> PartialEq<Rhs> for [A; $N] where
                 A: PartialEq<B>,
                 Rhs: Deref<Target=[B]>,
@@ -73,7 +73,7 @@ macro_rules! array_impls {
                 }
             }
 
-            #[stable]
+            #[stable(feature = "rust1", since = "1.0.0")]
             impl<'a, A, B, Lhs> PartialEq<[B; $N]> for Lhs where
                 A: PartialEq<B>,
                 Lhs: Deref<Target=[A]>
@@ -88,10 +88,10 @@ macro_rules! array_impls {
                 }
             }
 
-            #[stable]
+            #[stable(feature = "rust1", since = "1.0.0")]
             impl<T:Eq> Eq for [T; $N] { }
 
-            #[stable]
+            #[stable(feature = "rust1", since = "1.0.0")]
             impl<T:PartialOrd> PartialOrd for [T; $N] {
                 #[inline]
                 fn partial_cmp(&self, other: &[T; $N]) -> Option<Ordering> {
@@ -115,7 +115,7 @@ macro_rules! array_impls {
                 }
             }
 
-            #[stable]
+            #[stable(feature = "rust1", since = "1.0.0")]
             impl<T:Ord> Ord for [T; $N] {
                 #[inline]
                 fn cmp(&self, other: &[T; $N]) -> Ordering {
diff --git a/src/libcore/atomic.rs b/src/libcore/atomic.rs
index e75481198d4..cf2854be016 100644
--- a/src/libcore/atomic.rs
+++ b/src/libcore/atomic.rs
@@ -68,7 +68,7 @@
 //! println!("live tasks: {}", old_task_count + 1);
 //! ```
 
-#![stable]
+#![stable(feature = "rust1", since = "1.0.0")]
 
 use self::Ordering::*;
 
@@ -78,7 +78,7 @@ use intrinsics;
 use cell::UnsafeCell;
 
 /// A boolean type which can be safely shared between threads.
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 pub struct AtomicBool {
     v: UnsafeCell<usize>,
 }
@@ -86,7 +86,7 @@ pub struct AtomicBool {
 unsafe impl Sync for AtomicBool {}
 
 /// A signed integer type which can be safely shared between threads.
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 pub struct AtomicIsize {
     v: UnsafeCell<isize>,
 }
@@ -94,7 +94,7 @@ pub struct AtomicIsize {
 unsafe impl Sync for AtomicIsize {}
 
 /// An unsigned integer type which can be safely shared between threads.
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 pub struct AtomicUsize {
     v: UnsafeCell<usize>,
 }
@@ -102,7 +102,7 @@ pub struct AtomicUsize {
 unsafe impl Sync for AtomicUsize {}
 
 /// A raw pointer type which can be safely shared between threads.
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 pub struct AtomicPtr<T> {
     p: UnsafeCell<usize>,
 }
@@ -119,42 +119,42 @@ unsafe impl<T> Sync for AtomicPtr<T> {}
 ///
 /// Rust's memory orderings are [the same as
 /// C++'s](http://gcc.gnu.org/wiki/Atomic/GCCMM/AtomicSync).
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 #[derive(Copy)]
 pub enum Ordering {
     /// No ordering constraints, only atomic operations.
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     Relaxed,
     /// When coupled with a store, all previous writes become visible
     /// to another thread that performs a load with `Acquire` ordering
     /// on the same value.
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     Release,
     /// When coupled with a load, all subsequent loads will see data
     /// written before a store with `Release` ordering on the same value
     /// in another thread.
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     Acquire,
     /// When coupled with a load, uses `Acquire` ordering, and with a store
     /// `Release` ordering.
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     AcqRel,
     /// Like `AcqRel` with the additional guarantee that all threads see all
     /// sequentially consistent operations in the same order.
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     SeqCst,
 }
 
 /// An `AtomicBool` initialized to `false`.
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 pub const ATOMIC_BOOL_INIT: AtomicBool =
         AtomicBool { v: UnsafeCell { value: 0 } };
 /// An `AtomicIsize` initialized to `0`.
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 pub const ATOMIC_ISIZE_INIT: AtomicIsize =
         AtomicIsize { v: UnsafeCell { value: 0 } };
 /// An `AtomicUsize` initialized to `0`.
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 pub const ATOMIC_USIZE_INIT: AtomicUsize =
         AtomicUsize { v: UnsafeCell { value: 0, } };
 
@@ -173,7 +173,7 @@ impl AtomicBool {
     /// let atomic_false = AtomicBool::new(false);
     /// ```
     #[inline]
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     pub fn new(v: bool) -> AtomicBool {
         let val = if v { UINT_TRUE } else { 0 };
         AtomicBool { v: UnsafeCell::new(val) }
@@ -197,7 +197,7 @@ impl AtomicBool {
     /// let value = some_bool.load(Ordering::Relaxed);
     /// ```
     #[inline]
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     pub fn load(&self, order: Ordering) -> bool {
         unsafe { atomic_load(self.v.get(), order) > 0 }
     }
@@ -220,7 +220,7 @@ impl AtomicBool {
     ///
     /// Panics if `order` is `Acquire` or `AcqRel`.
     #[inline]
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     pub fn store(&self, val: bool, order: Ordering) {
         let val = if val { UINT_TRUE } else { 0 };
 
@@ -241,7 +241,7 @@ impl AtomicBool {
     /// let value = some_bool.swap(false, Ordering::Relaxed);
     /// ```
     #[inline]
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     pub fn swap(&self, val: bool, order: Ordering) -> bool {
         let val = if val { UINT_TRUE } else { 0 };
 
@@ -265,7 +265,7 @@ impl AtomicBool {
     /// let value = some_bool.store(false, Ordering::Relaxed);
     /// ```
     #[inline]
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     pub fn compare_and_swap(&self, old: bool, new: bool, order: Ordering) -> bool {
         let old = if old { UINT_TRUE } else { 0 };
         let new = if new { UINT_TRUE } else { 0 };
@@ -298,7 +298,7 @@ impl AtomicBool {
     /// assert_eq!(false, foo.load(Ordering::SeqCst));
     /// ```
     #[inline]
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     pub fn fetch_and(&self, val: bool, order: Ordering) -> bool {
         let val = if val { UINT_TRUE } else { 0 };
 
@@ -331,7 +331,7 @@ impl AtomicBool {
     /// assert_eq!(true, foo.load(Ordering::SeqCst));
     /// ```
     #[inline]
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     pub fn fetch_nand(&self, val: bool, order: Ordering) -> bool {
         let val = if val { UINT_TRUE } else { 0 };
 
@@ -363,7 +363,7 @@ impl AtomicBool {
     /// assert_eq!(false, foo.load(Ordering::SeqCst));
     /// ```
     #[inline]
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     pub fn fetch_or(&self, val: bool, order: Ordering) -> bool {
         let val = if val { UINT_TRUE } else { 0 };
 
@@ -395,7 +395,7 @@ impl AtomicBool {
     /// assert_eq!(false, foo.load(Ordering::SeqCst));
     /// ```
     #[inline]
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     pub fn fetch_xor(&self, val: bool, order: Ordering) -> bool {
         let val = if val { UINT_TRUE } else { 0 };
 
@@ -403,7 +403,7 @@ impl AtomicBool {
     }
 }
 
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl AtomicIsize {
     /// Creates a new `AtomicIsize`.
     ///
@@ -580,7 +580,7 @@ impl AtomicIsize {
     }
 }
 
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl AtomicUsize {
     /// Creates a new `AtomicUsize`.
     ///
@@ -769,7 +769,7 @@ impl<T> AtomicPtr<T> {
     /// let atomic_ptr  = AtomicPtr::new(ptr);
     /// ```
     #[inline]
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     pub fn new(p: *mut T) -> AtomicPtr<T> {
         AtomicPtr { p: UnsafeCell::new(p as usize) }
     }
@@ -793,7 +793,7 @@ impl<T> AtomicPtr<T> {
     /// let value = some_ptr.load(Ordering::Relaxed);
     /// ```
     #[inline]
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     pub fn load(&self, order: Ordering) -> *mut T {
         unsafe {
             atomic_load(self.p.get(), order) as *mut T
@@ -821,7 +821,7 @@ impl<T> AtomicPtr<T> {
     ///
     /// Panics if `order` is `Acquire` or `AcqRel`.
     #[inline]
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     pub fn store(&self, ptr: *mut T, order: Ordering) {
         unsafe { atomic_store(self.p.get(), ptr as usize, order); }
     }
@@ -843,7 +843,7 @@ impl<T> AtomicPtr<T> {
     /// let value = some_ptr.swap(other_ptr, Ordering::Relaxed);
     /// ```
     #[inline]
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     pub fn swap(&self, ptr: *mut T, order: Ordering) -> *mut T {
         unsafe { atomic_swap(self.p.get(), ptr as usize, order) as *mut T }
     }
@@ -869,7 +869,7 @@ impl<T> AtomicPtr<T> {
     /// let value = some_ptr.compare_and_swap(other_ptr, another_ptr, Ordering::Relaxed);
     /// ```
     #[inline]
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     pub fn compare_and_swap(&self, old: *mut T, new: *mut T, order: Ordering) -> *mut T {
         unsafe {
             atomic_compare_and_swap(self.p.get(), old as usize,
@@ -890,7 +890,7 @@ unsafe fn atomic_store<T>(dst: *mut T, val: T, order:Ordering) {
 }
 
 #[inline]
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 unsafe fn atomic_load<T>(dst: *const T, order:Ordering) -> T {
     match order {
         Acquire => intrinsics::atomic_load_acq(dst),
@@ -902,7 +902,7 @@ unsafe fn atomic_load<T>(dst: *const T, order:Ordering) -> T {
 }
 
 #[inline]
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 unsafe fn atomic_swap<T>(dst: *mut T, val: T, order: Ordering) -> T {
     match order {
         Acquire => intrinsics::atomic_xchg_acq(dst, val),
@@ -915,7 +915,7 @@ unsafe fn atomic_swap<T>(dst: *mut T, val: T, order: Ordering) -> T {
 
 /// Returns the old value (like __sync_fetch_and_add).
 #[inline]
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 unsafe fn atomic_add<T>(dst: *mut T, val: T, order: Ordering) -> T {
     match order {
         Acquire => intrinsics::atomic_xadd_acq(dst, val),
@@ -928,7 +928,7 @@ unsafe fn atomic_add<T>(dst: *mut T, val: T, order: Ordering) -> T {
 
 /// Returns the old value (like __sync_fetch_and_sub).
 #[inline]
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 unsafe fn atomic_sub<T>(dst: *mut T, val: T, order: Ordering) -> T {
     match order {
         Acquire => intrinsics::atomic_xsub_acq(dst, val),
@@ -940,7 +940,7 @@ unsafe fn atomic_sub<T>(dst: *mut T, val: T, order: Ordering) -> T {
 }
 
 #[inline]
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 unsafe fn atomic_compare_and_swap<T>(dst: *mut T, old:T, new:T, order: Ordering) -> T {
     match order {
         Acquire => intrinsics::atomic_cxchg_acq(dst, old, new),
@@ -952,7 +952,7 @@ unsafe fn atomic_compare_and_swap<T>(dst: *mut T, old:T, new:T, order: Ordering)
 }
 
 #[inline]
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 unsafe fn atomic_and<T>(dst: *mut T, val: T, order: Ordering) -> T {
     match order {
         Acquire => intrinsics::atomic_and_acq(dst, val),
@@ -964,7 +964,7 @@ unsafe fn atomic_and<T>(dst: *mut T, val: T, order: Ordering) -> T {
 }
 
 #[inline]
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 unsafe fn atomic_nand<T>(dst: *mut T, val: T, order: Ordering) -> T {
     match order {
         Acquire => intrinsics::atomic_nand_acq(dst, val),
@@ -977,7 +977,7 @@ unsafe fn atomic_nand<T>(dst: *mut T, val: T, order: Ordering) -> T {
 
 
 #[inline]
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 unsafe fn atomic_or<T>(dst: *mut T, val: T, order: Ordering) -> T {
     match order {
         Acquire => intrinsics::atomic_or_acq(dst, val),
@@ -990,7 +990,7 @@ unsafe fn atomic_or<T>(dst: *mut T, val: T, order: Ordering) -> T {
 
 
 #[inline]
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 unsafe fn atomic_xor<T>(dst: *mut T, val: T, order: Ordering) -> T {
     match order {
         Acquire => intrinsics::atomic_xor_acq(dst, val),
@@ -1023,7 +1023,7 @@ unsafe fn atomic_xor<T>(dst: *mut T, val: T, order: Ordering) -> T {
 ///
 /// Panics if `order` is `Relaxed`.
 #[inline]
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 pub fn fence(order: Ordering) {
     unsafe {
         match order {
@@ -1036,7 +1036,9 @@ pub fn fence(order: Ordering) {
     }
 }
 
-#[deprecated="renamed to AtomicIsize"]
+#[unstable(feature = "core")]
+#[deprecated(since = "1.0.0",
+             reason = "renamed to AtomicIsize")]
 #[allow(missing_docs)]
 pub struct AtomicInt {
     v: UnsafeCell<int>,
@@ -1044,7 +1046,9 @@ pub struct AtomicInt {
 
 unsafe impl Sync for AtomicInt {}
 
-#[deprecated="renamed to AtomicUsize"]
+#[unstable(feature = "core")]
+#[deprecated(since = "1.0.0",
+             reason = "renamed to AtomicUsize")]
 #[allow(missing_docs)]
 pub struct AtomicUint {
     v: UnsafeCell<uint>,
@@ -1052,11 +1056,15 @@ pub struct AtomicUint {
 
 unsafe impl Sync for AtomicUint {}
 
-#[deprecated="use ATOMIC_ISIZE_INIT instead"]
+#[unstable(feature = "core")]
+#[deprecated(since = "1.0.0",
+             reason = "use ATOMIC_ISIZE_INIT instead")]
 #[allow(missing_docs, deprecated)]
 pub const ATOMIC_INT_INIT: AtomicInt =
         AtomicInt { v: UnsafeCell { value: 0 } };
-#[deprecated="use ATOMIC_USIZE_INIT instead"]
+#[unstable(feature = "core")]
+#[deprecated(since = "1.0.0",
+             reason = "use ATOMIC_USIZE_INIT instead")]
 #[allow(missing_docs, deprecated)]
 pub const ATOMIC_UINT_INIT: AtomicUint =
         AtomicUint { v: UnsafeCell { value: 0, } };
diff --git a/src/libcore/borrow.rs b/src/libcore/borrow.rs
index 63614aaa463..be144b052c7 100644
--- a/src/libcore/borrow.rs
+++ b/src/libcore/borrow.rs
@@ -42,7 +42,8 @@
 //! is desired, `to_mut` will obtain a mutable references to an owned
 //! value, cloning if necessary.
 
-#![unstable = "recently added as part of collections reform"]
+#![unstable(feature = "core",
+            reason = "recently added as part of collections reform")]
 
 use clone::Clone;
 use cmp::{Eq, Ord, Ordering, PartialEq, PartialOrd};
@@ -141,7 +142,7 @@ pub enum Cow<'a, T, B: ?Sized + 'a> where B: ToOwned<T> {
     Owned(T)
 }
 
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl<'a, T, B: ?Sized> Clone for Cow<'a, T, B> where B: ToOwned<T> {
     fn clone(&self) -> Cow<'a, T, B> {
         match *self {
@@ -195,7 +196,7 @@ impl<'a, T, B: ?Sized> Cow<'a, T, B> where B: ToOwned<T> {
     }
 }
 
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl<'a, T, B: ?Sized> Deref for Cow<'a, T, B> where B: ToOwned<T>  {
     type Target = B;
 
@@ -207,10 +208,10 @@ impl<'a, T, B: ?Sized> Deref for Cow<'a, T, B> where B: ToOwned<T>  {
     }
 }
 
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl<'a, T, B: ?Sized> Eq for Cow<'a, T, B> where B: Eq + ToOwned<T> {}
 
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl<'a, T, B: ?Sized> Ord for Cow<'a, T, B> where B: Ord + ToOwned<T> {
     #[inline]
     fn cmp(&self, other: &Cow<'a, T, B>) -> Ordering {
@@ -218,7 +219,7 @@ impl<'a, T, B: ?Sized> Ord for Cow<'a, T, B> where B: Ord + ToOwned<T> {
     }
 }
 
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl<'a, 'b, T, U, B: ?Sized, C: ?Sized> PartialEq<Cow<'b, U, C>> for Cow<'a, T, B> where
     B: PartialEq<C> + ToOwned<T>,
     C: ToOwned<U>,
@@ -229,7 +230,7 @@ impl<'a, 'b, T, U, B: ?Sized, C: ?Sized> PartialEq<Cow<'b, U, C>> for Cow<'a, T,
     }
 }
 
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl<'a, T, B: ?Sized> PartialOrd for Cow<'a, T, B> where B: PartialOrd + ToOwned<T> {
     #[inline]
     fn partial_cmp(&self, other: &Cow<'a, T, B>) -> Option<Ordering> {
@@ -237,7 +238,7 @@ impl<'a, T, B: ?Sized> PartialOrd for Cow<'a, T, B> where B: PartialOrd + ToOwne
     }
 }
 
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl<'a, T, B: ?Sized> fmt::Debug for Cow<'a, T, B> where
     B: fmt::Debug + ToOwned<T>,
     T: fmt::Debug,
@@ -250,7 +251,7 @@ impl<'a, T, B: ?Sized> fmt::Debug for Cow<'a, T, B> where
     }
 }
 
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl<'a, T, B: ?Sized> fmt::Display for Cow<'a, T, B> where
     B: fmt::Display + ToOwned<T>,
     T: fmt::Display,
diff --git a/src/libcore/cell.rs b/src/libcore/cell.rs
index 916c5f50d22..02cc4038a69 100644
--- a/src/libcore/cell.rs
+++ b/src/libcore/cell.rs
@@ -139,7 +139,7 @@
 //! ```
 //!
 
-#![stable]
+#![stable(feature = "rust1", since = "1.0.0")]
 
 use clone::Clone;
 use cmp::PartialEq;
@@ -152,7 +152,7 @@ use option::Option::{None, Some};
 /// A mutable memory location that admits only `Copy` data.
 ///
 /// See the [module-level documentation](../index.html) for more.
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 pub struct Cell<T> {
     value: UnsafeCell<T>,
 }
@@ -167,7 +167,7 @@ impl<T:Copy> Cell<T> {
     ///
     /// let c = Cell::new(5);
     /// ```
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     pub fn new(value: T) -> Cell<T> {
         Cell {
             value: UnsafeCell::new(value),
@@ -186,7 +186,7 @@ impl<T:Copy> Cell<T> {
     /// let five = c.get();
     /// ```
     #[inline]
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     pub fn get(&self) -> T {
         unsafe{ *self.value.get() }
     }
@@ -203,7 +203,7 @@ impl<T:Copy> Cell<T> {
     /// c.set(10);
     /// ```
     #[inline]
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     pub fn set(&self, value: T) {
         unsafe {
             *self.value.get() = value;
@@ -226,31 +226,31 @@ impl<T:Copy> Cell<T> {
     /// let uc = unsafe { c.as_unsafe_cell() };
     /// ```
     #[inline]
-    #[unstable]
+    #[unstable(feature = "core")]
     pub unsafe fn as_unsafe_cell<'a>(&'a self) -> &'a UnsafeCell<T> {
         &self.value
     }
 }
 
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 unsafe impl<T> Send for Cell<T> where T: Send {}
 
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl<T:Copy> Clone for Cell<T> {
     fn clone(&self) -> Cell<T> {
         Cell::new(self.get())
     }
 }
 
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl<T:Default + Copy> Default for Cell<T> {
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     fn default() -> Cell<T> {
         Cell::new(Default::default())
     }
 }
 
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl<T:PartialEq + Copy> PartialEq for Cell<T> {
     fn eq(&self, other: &Cell<T>) -> bool {
         self.get() == other.get()
@@ -260,7 +260,7 @@ impl<T:PartialEq + Copy> PartialEq for Cell<T> {
 /// A mutable memory location with dynamically checked borrow rules
 ///
 /// See the [module-level documentation](../index.html) for more.
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 pub struct RefCell<T> {
     value: UnsafeCell<T>,
     borrow: Cell<BorrowFlag>,
@@ -282,7 +282,7 @@ impl<T> RefCell<T> {
     ///
     /// let c = RefCell::new(5);
     /// ```
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     pub fn new(value: T) -> RefCell<T> {
         RefCell {
             value: UnsafeCell::new(value),
@@ -301,7 +301,7 @@ impl<T> RefCell<T> {
     ///
     /// let five = c.into_inner();
     /// ```
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     pub fn into_inner(self) -> T {
         // Since this function takes `self` (the `RefCell`) by value, the
         // compiler statically verifies that it is not currently borrowed.
@@ -316,7 +316,7 @@ impl<T> RefCell<T> {
     /// immutable borrows can be taken out at the same time.
     ///
     /// Returns `None` if the value is currently mutably borrowed.
-    #[unstable = "may be renamed or removed"]
+    #[unstable(feature = "core", reason = "may be renamed or removed")]
     pub fn try_borrow<'a>(&'a self) -> Option<Ref<'a, T>> {
         match BorrowRef::new(&self.borrow) {
             Some(b) => Some(Ref { _value: unsafe { &*self.value.get() }, _borrow: b }),
@@ -359,7 +359,7 @@ impl<T> RefCell<T> {
     ///
     /// assert!(result.is_err());
     /// ```
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     pub fn borrow<'a>(&'a self) -> Ref<'a, T> {
         match self.try_borrow() {
             Some(ptr) => ptr,
@@ -373,7 +373,7 @@ impl<T> RefCell<T> {
     /// cannot be borrowed while this borrow is active.
     ///
     /// Returns `None` if the value is currently borrowed.
-    #[unstable = "may be renamed or removed"]
+    #[unstable(feature = "core", reason = "may be renamed or removed")]
     pub fn try_borrow_mut<'a>(&'a self) -> Option<RefMut<'a, T>> {
         match BorrowRefMut::new(&self.borrow) {
             Some(b) => Some(RefMut { _value: unsafe { &mut *self.value.get() }, _borrow: b }),
@@ -415,7 +415,7 @@ impl<T> RefCell<T> {
     ///
     /// assert!(result.is_err());
     /// ```
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     pub fn borrow_mut<'a>(&'a self) -> RefMut<'a, T> {
         match self.try_borrow_mut() {
             Some(ptr) => ptr,
@@ -429,31 +429,31 @@ impl<T> RefCell<T> {
     ///
     /// This function is `unsafe` because `UnsafeCell`'s field is public.
     #[inline]
-    #[unstable]
+    #[unstable(feature = "core")]
     pub unsafe fn as_unsafe_cell<'a>(&'a self) -> &'a UnsafeCell<T> {
         &self.value
     }
 }
 
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 unsafe impl<T> Send for RefCell<T> where T: Send {}
 
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl<T: Clone> Clone for RefCell<T> {
     fn clone(&self) -> RefCell<T> {
         RefCell::new(self.borrow().clone())
     }
 }
 
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl<T:Default> Default for RefCell<T> {
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     fn default() -> RefCell<T> {
         RefCell::new(Default::default())
     }
 }
 
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl<T: PartialEq> PartialEq for RefCell<T> {
     fn eq(&self, other: &RefCell<T>) -> bool {
         *self.borrow() == *other.borrow()
@@ -496,10 +496,11 @@ impl<'b> Clone for BorrowRef<'b> {
     }
 }
 
+/// Wraps a borrowed reference to a value in a `RefCell` box.
 /// A wrapper type for an immutably borrowed value from a `RefCell<T>`.
 ///
 /// See the [module-level documentation](../index.html) for more.
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 pub struct Ref<'b, T:'b> {
     // FIXME #12808: strange name to try to avoid interfering with
     // field accesses of the contained type via Deref
@@ -507,7 +508,7 @@ pub struct Ref<'b, T:'b> {
     _borrow: BorrowRef<'b>,
 }
 
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl<'b, T> Deref for Ref<'b, T> {
     type Target = T;
 
@@ -523,7 +524,8 @@ impl<'b, T> Deref for Ref<'b, T> {
 ///
 /// A `Clone` implementation would interfere with the widespread
 /// use of `r.borrow().clone()` to clone the contents of a `RefCell`.
-#[unstable = "likely to be moved to a method, pending language changes"]
+#[unstable(feature = "core",
+           reason = "likely to be moved to a method, pending language changes")]
 pub fn clone_ref<'b, T:Clone>(orig: &Ref<'b, T>) -> Ref<'b, T> {
     Ref {
         _value: orig._value,
@@ -559,7 +561,7 @@ impl<'b> BorrowRefMut<'b> {
 /// A wrapper type for a mutably borrowed value from a `RefCell<T>`.
 ///
 /// See the [module-level documentation](../index.html) for more.
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 pub struct RefMut<'b, T:'b> {
     // FIXME #12808: strange name to try to avoid interfering with
     // field accesses of the contained type via Deref
@@ -567,7 +569,7 @@ pub struct RefMut<'b, T:'b> {
     _borrow: BorrowRefMut<'b>,
 }
 
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl<'b, T> Deref for RefMut<'b, T> {
     type Target = T;
 
@@ -577,7 +579,7 @@ impl<'b, T> Deref for RefMut<'b, T> {
     }
 }
 
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl<'b, T> DerefMut for RefMut<'b, T> {
     #[inline]
     fn deref_mut<'a>(&'a mut self) -> &'a mut T {
@@ -619,13 +621,13 @@ impl<'b, T> DerefMut for RefMut<'b, T> {
 /// **NOTE:** `UnsafeCell<T>`'s fields are public to allow static initializers. It is not
 /// recommended to access its fields directly, `get` should be used instead.
 #[lang="unsafe"]
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 pub struct UnsafeCell<T> {
     /// Wrapped value
     ///
     /// This field should not be accessed directly, it is made public for static
     /// initializers.
-    #[unstable]
+    #[unstable(feature = "core")]
     pub value: T,
 }
 
@@ -643,7 +645,7 @@ impl<T> UnsafeCell<T> {
     ///
     /// let uc = UnsafeCell::new(5);
     /// ```
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     pub fn new(value: T) -> UnsafeCell<T> {
         UnsafeCell { value: value }
     }
@@ -660,7 +662,7 @@ impl<T> UnsafeCell<T> {
     /// let five = uc.get();
     /// ```
     #[inline]
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     pub fn get(&self) -> *mut T { &self.value as *const T as *mut T }
 
     /// Unwraps the value
@@ -680,6 +682,6 @@ impl<T> UnsafeCell<T> {
     /// let five = unsafe { uc.into_inner() };
     /// ```
     #[inline]
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     pub unsafe fn into_inner(self) -> T { self.value }
 }
diff --git a/src/libcore/char.rs b/src/libcore/char.rs
index c17f7cdccba..22bfd47893c 100644
--- a/src/libcore/char.rs
+++ b/src/libcore/char.rs
@@ -64,12 +64,12 @@ static MAX_THREE_B: u32 =  0x10000u32;
 */
 
 /// The highest valid code point
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 pub const MAX: char = '\u{10ffff}';
 
 /// Converts from `u32` to a `char`
 #[inline]
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 pub fn from_u32(i: u32) -> Option<char> {
     // catch out-of-bounds and surrogates
     if (i > MAX as u32) || (i >= 0xD800 && i <= 0xDFFF) {
@@ -92,7 +92,7 @@ pub fn from_u32(i: u32) -> Option<char> {
 /// Panics if given an `radix` > 36.
 ///
 #[inline]
-#[unstable = "pending integer conventions"]
+#[unstable(feature = "core", reason = "pending integer conventions")]
 pub fn from_digit(num: uint, radix: uint) -> Option<char> {
     if radix > 36 {
         panic!("from_digit: radix is too high (maximum 36)");
@@ -111,7 +111,7 @@ pub fn from_digit(num: uint, radix: uint) -> Option<char> {
 }
 
 /// Basic `char` manipulations.
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 pub trait CharExt {
     /// Checks if a `char` parses as a numeric digit in the given radix.
     ///
@@ -126,7 +126,8 @@ pub trait CharExt {
     /// # Panics
     ///
     /// Panics if given a radix > 36.
-    #[unstable = "pending integer conventions"]
+    #[unstable(feature = "core",
+               reason = "pending integer conventions")]
     fn is_digit(self, radix: uint) -> bool;
 
     /// Converts a character to the corresponding digit.
@@ -140,7 +141,8 @@ pub trait CharExt {
     /// # Panics
     ///
     /// Panics if given a radix outside the range [0..36].
-    #[unstable = "pending integer conventions"]
+    #[unstable(feature = "core",
+               reason = "pending integer conventions")]
     fn to_digit(self, radix: uint) -> Option<uint>;
 
     /// Returns an iterator that yields the hexadecimal Unicode escape
@@ -149,7 +151,7 @@ pub trait CharExt {
     /// All characters are escaped with Rust syntax of the form `\\u{NNNN}`
     /// where `NNNN` is the shortest hexadecimal representation of the code
     /// point.
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     fn escape_unicode(self) -> EscapeUnicode;
 
     /// Returns an iterator that yields the 'default' ASCII and
@@ -164,17 +166,17 @@ pub trait CharExt {
     ///   escaped.
     /// * Any other chars in the range [0x20,0x7e] are not escaped.
     /// * Any other chars are given hex Unicode escapes; see `escape_unicode`.
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     fn escape_default(self) -> EscapeDefault;
 
     /// Returns the amount of bytes this character would need if encoded in
     /// UTF-8.
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     fn len_utf8(self) -> uint;
 
     /// Returns the amount of bytes this character would need if encoded in
     /// UTF-16.
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     fn len_utf16(self) -> uint;
 
     /// Encodes this character as UTF-8 into the provided byte buffer,
@@ -182,7 +184,7 @@ pub trait CharExt {
     ///
     /// If the buffer is not large enough, nothing will be written into it
     /// and a `None` will be returned.
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     fn encode_utf8(self, dst: &mut [u8]) -> Option<uint>;
 
     /// Encodes this character as UTF-16 into the provided `u16` buffer,
@@ -190,18 +192,20 @@ pub trait CharExt {
     ///
     /// If the buffer is not large enough, nothing will be written into it
     /// and a `None` will be returned.
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     fn encode_utf16(self, dst: &mut [u16]) -> Option<uint>;
 }
 
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl CharExt for char {
-    #[unstable = "pending integer conventions"]
+    #[unstable(feature = "core",
+               reason = "pending integer conventions")]
     fn is_digit(self, radix: uint) -> bool {
         self.to_digit(radix).is_some()
     }
 
-    #[unstable = "pending integer conventions"]
+    #[unstable(feature = "core",
+               reason = "pending integer conventions")]
     fn to_digit(self, radix: uint) -> Option<uint> {
         if radix > 36 {
             panic!("to_digit: radix is too high (maximum 36)");
@@ -216,12 +220,12 @@ impl CharExt for char {
         else { None }
     }
 
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     fn escape_unicode(self) -> EscapeUnicode {
         EscapeUnicode { c: self, state: EscapeUnicodeState::Backslash }
     }
 
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     fn escape_default(self) -> EscapeDefault {
         let init_state = match self {
             '\t' => EscapeDefaultState::Backslash('t'),
@@ -237,7 +241,7 @@ impl CharExt for char {
     }
 
     #[inline]
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     fn len_utf8(self) -> uint {
         let code = self as u32;
         match () {
@@ -249,20 +253,22 @@ impl CharExt for char {
     }
 
     #[inline]
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     fn len_utf16(self) -> uint {
         let ch = self as u32;
         if (ch & 0xFFFF_u32) == ch { 1 } else { 2 }
     }
 
     #[inline]
-    #[unstable = "pending decision about Iterator/Writer/Reader"]
+    #[unstable(feature = "core",
+               reason = "pending decision about Iterator/Writer/Reader")]
     fn encode_utf8(self, dst: &mut [u8]) -> Option<uint> {
         encode_utf8_raw(self as u32, dst)
     }
 
     #[inline]
-    #[unstable = "pending decision about Iterator/Writer/Reader"]
+    #[unstable(feature = "core",
+               reason = "pending decision about Iterator/Writer/Reader")]
     fn encode_utf16(self, dst: &mut [u16]) -> Option<uint> {
         encode_utf16_raw(self as u32, dst)
     }
@@ -274,7 +280,7 @@ impl CharExt for char {
 /// If the buffer is not large enough, nothing will be written into it
 /// and a `None` will be returned.
 #[inline]
-#[unstable]
+#[unstable(feature = "core")]
 pub fn encode_utf8_raw(code: u32, dst: &mut [u8]) -> Option<uint> {
     // Marked #[inline] to allow llvm optimizing it away
     if code < MAX_ONE_B && dst.len() >= 1 {
@@ -306,7 +312,7 @@ pub fn encode_utf8_raw(code: u32, dst: &mut [u8]) -> Option<uint> {
 /// If the buffer is not large enough, nothing will be written into it
 /// and a `None` will be returned.
 #[inline]
-#[unstable]
+#[unstable(feature = "core")]
 pub fn encode_utf16_raw(mut ch: u32, dst: &mut [u16]) -> Option<uint> {
     // Marked #[inline] to allow llvm optimizing it away
     if (ch & 0xFFFF_u32) == ch  && dst.len() >= 1 {
@@ -327,14 +333,14 @@ pub fn encode_utf16_raw(mut ch: u32, dst: &mut [u16]) -> Option<uint> {
 /// An iterator over the characters that represent a `char`, as escaped by
 /// Rust's unicode escaping rules.
 #[derive(Clone)]
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 pub struct EscapeUnicode {
     c: char,
     state: EscapeUnicodeState
 }
 
 #[derive(Clone)]
-#[unstable]
+#[unstable(feature = "core")]
 enum EscapeUnicodeState {
     Backslash,
     Type,
@@ -344,7 +350,7 @@ enum EscapeUnicodeState {
     Done,
 }
 
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl Iterator for EscapeUnicode {
     type Item = char;
 
@@ -390,13 +396,13 @@ impl Iterator for EscapeUnicode {
 /// An iterator over the characters that represent a `char`, escaped
 /// for maximum portability.
 #[derive(Clone)]
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 pub struct EscapeDefault {
     state: EscapeDefaultState
 }
 
 #[derive(Clone)]
-#[unstable]
+#[unstable(feature = "core")]
 enum EscapeDefaultState {
     Backslash(char),
     Char(char),
@@ -404,7 +410,7 @@ enum EscapeDefaultState {
     Unicode(EscapeUnicode),
 }
 
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl Iterator for EscapeDefault {
     type Item = char;
 
diff --git a/src/libcore/clone.rs b/src/libcore/clone.rs
index ffa6d085543..28c306fc009 100644
--- a/src/libcore/clone.rs
+++ b/src/libcore/clone.rs
@@ -19,15 +19,15 @@
 //! explicitly, by convention implementing the `Clone` trait and calling
 //! the `clone` method.
 
-#![stable]
+#![stable(feature = "rust1", since = "1.0.0")]
 
 use marker::Sized;
 
 /// A common trait for cloning an object.
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 pub trait Clone : Sized {
     /// Returns a copy of the value.
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     fn clone(&self) -> Self;
 
     /// Perform copy-assignment from `source`.
@@ -36,13 +36,14 @@ pub trait Clone : Sized {
     /// but can be overridden to reuse the resources of `a` to avoid unnecessary
     /// allocations.
     #[inline(always)]
-    #[unstable = "this function is rarely used"]
+    #[unstable(feature = "core",
+               reason = "this function is rarely used")]
     fn clone_from(&mut self, source: &Self) {
         *self = source.clone()
     }
 }
 
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl<'a, T: ?Sized> Clone for &'a T {
     /// Return a shallow copy of the reference.
     #[inline]
@@ -51,7 +52,7 @@ impl<'a, T: ?Sized> Clone for &'a T {
 
 macro_rules! clone_impl {
     ($t:ty) => {
-        #[stable]
+        #[stable(feature = "rust1", since = "1.0.0")]
         impl Clone for $t {
             /// Return a deep copy of the value.
             #[inline]
@@ -81,7 +82,8 @@ clone_impl! { char }
 
 macro_rules! extern_fn_clone {
     ($($A:ident),*) => (
-        #[unstable = "this may not be sufficient for fns with region parameters"]
+        #[unstable(feature = "core",
+                   reason = "this may not be sufficient for fns with region parameters")]
         impl<$($A,)* ReturnType> Clone for extern "Rust" fn($($A),*) -> ReturnType {
             /// Return a copy of a function pointer
             #[inline]
diff --git a/src/libcore/cmp.rs b/src/libcore/cmp.rs
index 6cda9d0e653..2ecbd55fcb1 100644
--- a/src/libcore/cmp.rs
+++ b/src/libcore/cmp.rs
@@ -39,7 +39,7 @@
 //! assert!(SketchyNum {num: 25} != SketchyNum {num: 57});
 //! ```
 
-#![stable]
+#![stable(feature = "rust1", since = "1.0.0")]
 
 use self::Ordering::*;
 
@@ -68,16 +68,16 @@ use option::Option::{self, Some, None};
 /// the rule that `eq` is a strict inverse of `ne`; that is, `!(a == b)` if and
 /// only if `a != b`.
 #[lang="eq"]
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 #[old_orphan_check]
 pub trait PartialEq<Rhs: ?Sized = Self> {
     /// This method tests for `self` and `other` values to be equal, and is used by `==`.
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     fn eq(&self, other: &Rhs) -> bool;
 
     /// This method tests for `!=`.
     #[inline]
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     fn ne(&self, other: &Rhs) -> bool { !self.eq(other) }
 }
 
@@ -90,7 +90,7 @@ pub trait PartialEq<Rhs: ?Sized = Self> {
 /// - reflexive: `a == a`;
 /// - symmetric: `a == b` implies `b == a`; and
 /// - transitive: `a == b` and `b == c` implies `a == c`.
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 pub trait Eq: PartialEq<Self> {
     // FIXME #13101: this method is used solely by #[deriving] to
     // assert that every component of a type implements #[deriving]
@@ -106,16 +106,16 @@ pub trait Eq: PartialEq<Self> {
 
 /// An ordering is, e.g, a result of a comparison between two values.
 #[derive(Clone, Copy, PartialEq, Show)]
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 pub enum Ordering {
     /// An ordering where a compared value is less [than another].
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     Less = -1,
     /// An ordering where a compared value is equal [to another].
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     Equal = 0,
     /// An ordering where a compared value is greater [than another].
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     Greater = 1,
 }
 
@@ -141,7 +141,7 @@ impl Ordering {
     /// assert!(data == b);
     /// ```
     #[inline]
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     pub fn reverse(self) -> Ordering {
         unsafe {
             // this compiles really nicely (to a single instruction);
@@ -164,7 +164,7 @@ impl Ordering {
 ///   true; and
 /// - transitive, `a < b` and `b < c` implies `a < c`. The same must hold for
 ///   both `==` and `>`.
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 pub trait Ord: Eq + PartialOrd<Self> {
     /// This method returns an ordering between `self` and `other` values.
     ///
@@ -178,26 +178,26 @@ pub trait Ord: Eq + PartialOrd<Self> {
     /// assert_eq!(10.cmp(&5),  Greater);  // because 10 > 5
     /// assert_eq!( 5.cmp(&5),  Equal);    // because 5 == 5
     /// ```
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     fn cmp(&self, other: &Self) -> Ordering;
 }
 
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl Eq for Ordering {}
 
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl Ord for Ordering {
     #[inline]
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     fn cmp(&self, other: &Ordering) -> Ordering {
         (*self as int).cmp(&(*other as int))
     }
 }
 
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl PartialOrd for Ordering {
     #[inline]
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     fn partial_cmp(&self, other: &Ordering) -> Option<Ordering> {
         (*self as int).partial_cmp(&(*other as int))
     }
@@ -224,16 +224,16 @@ impl PartialOrd for Ordering {
 /// `NaN < 0 == false` and `NaN >= 0 == false` (cf. IEEE 754-2008 section
 /// 5.11).
 #[lang="ord"]
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 pub trait PartialOrd<Rhs: ?Sized = Self>: PartialEq<Rhs> {
     /// This method returns an ordering between `self` and `other` values
     /// if one exists.
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     fn partial_cmp(&self, other: &Rhs) -> Option<Ordering>;
 
     /// This method tests less than (for `self` and `other`) and is used by the `<` operator.
     #[inline]
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     fn lt(&self, other: &Rhs) -> bool {
         match self.partial_cmp(other) {
             Some(Less) => true,
@@ -243,7 +243,7 @@ pub trait PartialOrd<Rhs: ?Sized = Self>: PartialEq<Rhs> {
 
     /// This method tests less than or equal to (`<=`).
     #[inline]
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     fn le(&self, other: &Rhs) -> bool {
         match self.partial_cmp(other) {
             Some(Less) | Some(Equal) => true,
@@ -253,7 +253,7 @@ pub trait PartialOrd<Rhs: ?Sized = Self>: PartialEq<Rhs> {
 
     /// This method tests greater than (`>`).
     #[inline]
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     fn gt(&self, other: &Rhs) -> bool {
         match self.partial_cmp(other) {
             Some(Greater) => true,
@@ -263,7 +263,7 @@ pub trait PartialOrd<Rhs: ?Sized = Self>: PartialEq<Rhs> {
 
     /// This method tests greater than or equal to (`>=`).
     #[inline]
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     fn ge(&self, other: &Rhs) -> bool {
         match self.partial_cmp(other) {
             Some(Greater) | Some(Equal) => true,
@@ -274,14 +274,14 @@ pub trait PartialOrd<Rhs: ?Sized = Self>: PartialEq<Rhs> {
 
 /// Compare and return the minimum of two values.
 #[inline]
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 pub fn min<T: Ord>(v1: T, v2: T) -> T {
     if v1 < v2 { v1 } else { v2 }
 }
 
 /// Compare and return the maximum of two values.
 #[inline]
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 pub fn max<T: Ord>(v1: T, v2: T) -> T {
     if v1 > v2 { v1 } else { v2 }
 }
@@ -290,7 +290,7 @@ pub fn max<T: Ord>(v1: T, v2: T) -> T {
 ///
 /// Returns the first argument if the comparison determines them to be equal.
 #[inline]
-#[unstable]
+#[unstable(feature = "core")]
 pub fn partial_min<T: PartialOrd>(v1: T, v2: T) -> Option<T> {
     match v1.partial_cmp(&v2) {
         Some(Less) | Some(Equal) => Some(v1),
@@ -303,7 +303,7 @@ pub fn partial_min<T: PartialOrd>(v1: T, v2: T) -> Option<T> {
 ///
 /// Returns the first argument if the comparison determines them to be equal.
 #[inline]
-#[unstable]
+#[unstable(feature = "core")]
 pub fn partial_max<T: PartialOrd>(v1: T, v2: T) -> Option<T> {
     match v1.partial_cmp(&v2) {
         Some(Less) => Some(v2),
@@ -322,7 +322,7 @@ mod impls {
 
     macro_rules! partial_eq_impl {
         ($($t:ty)*) => ($(
-            #[stable]
+            #[stable(feature = "rust1", since = "1.0.0")]
             impl PartialEq for $t {
                 #[inline]
                 fn eq(&self, other: &$t) -> bool { (*self) == (*other) }
@@ -332,7 +332,7 @@ mod impls {
         )*)
     }
 
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     impl PartialEq for () {
         #[inline]
         fn eq(&self, _other: &()) -> bool { true }
@@ -346,7 +346,7 @@ mod impls {
 
     macro_rules! eq_impl {
         ($($t:ty)*) => ($(
-            #[stable]
+            #[stable(feature = "rust1", since = "1.0.0")]
             impl Eq for $t {}
         )*)
     }
@@ -355,7 +355,7 @@ mod impls {
 
     macro_rules! partial_ord_impl {
         ($($t:ty)*) => ($(
-            #[stable]
+            #[stable(feature = "rust1", since = "1.0.0")]
             impl PartialOrd for $t {
                 #[inline]
                 fn partial_cmp(&self, other: &$t) -> Option<Ordering> {
@@ -378,7 +378,7 @@ mod impls {
         )*)
     }
 
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     impl PartialOrd for () {
         #[inline]
         fn partial_cmp(&self, _: &()) -> Option<Ordering> {
@@ -386,7 +386,7 @@ mod impls {
         }
     }
 
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     impl PartialOrd for bool {
         #[inline]
         fn partial_cmp(&self, other: &bool) -> Option<Ordering> {
@@ -398,7 +398,7 @@ mod impls {
 
     macro_rules! ord_impl {
         ($($t:ty)*) => ($(
-            #[stable]
+            #[stable(feature = "rust1", since = "1.0.0")]
             impl Ord for $t {
                 #[inline]
                 fn cmp(&self, other: &$t) -> Ordering {
@@ -410,13 +410,13 @@ mod impls {
         )*)
     }
 
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     impl Ord for () {
         #[inline]
         fn cmp(&self, _other: &()) -> Ordering { Equal }
     }
 
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     impl Ord for bool {
         #[inline]
         fn cmp(&self, other: &bool) -> Ordering {
@@ -428,14 +428,14 @@ mod impls {
 
     // & pointers
 
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     impl<'a, 'b, A: ?Sized, B: ?Sized> PartialEq<&'b B> for &'a A where A: PartialEq<B> {
         #[inline]
         fn eq(&self, other: & &'b B) -> bool { PartialEq::eq(*self, *other) }
         #[inline]
         fn ne(&self, other: & &'b B) -> bool { PartialEq::ne(*self, *other) }
     }
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     impl<'a, 'b, A: ?Sized, B: ?Sized> PartialOrd<&'b B> for &'a A where A: PartialOrd<B> {
         #[inline]
         fn partial_cmp(&self, other: &&'b B) -> Option<Ordering> {
@@ -450,24 +450,24 @@ mod impls {
         #[inline]
         fn gt(&self, other: & &'b B) -> bool { PartialOrd::gt(*self, *other) }
     }
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     impl<'a, A: ?Sized> Ord for &'a A where A: Ord {
         #[inline]
         fn cmp(&self, other: & &'a A) -> Ordering { Ord::cmp(*self, *other) }
     }
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     impl<'a, A: ?Sized> Eq for &'a A where A: Eq {}
 
     // &mut pointers
 
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     impl<'a, 'b, A: ?Sized, B: ?Sized> PartialEq<&'b mut B> for &'a mut A where A: PartialEq<B> {
         #[inline]
         fn eq(&self, other: &&'b mut B) -> bool { PartialEq::eq(*self, *other) }
         #[inline]
         fn ne(&self, other: &&'b mut B) -> bool { PartialEq::ne(*self, *other) }
     }
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     impl<'a, 'b, A: ?Sized, B: ?Sized> PartialOrd<&'b mut B> for &'a mut A where A: PartialOrd<B> {
         #[inline]
         fn partial_cmp(&self, other: &&'b mut B) -> Option<Ordering> {
@@ -482,15 +482,15 @@ mod impls {
         #[inline]
         fn gt(&self, other: &&'b mut B) -> bool { PartialOrd::gt(*self, *other) }
     }
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     impl<'a, A: ?Sized> Ord for &'a mut A where A: Ord {
         #[inline]
         fn cmp(&self, other: &&'a mut A) -> Ordering { Ord::cmp(*self, *other) }
     }
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     impl<'a, A: ?Sized> Eq for &'a mut A where A: Eq {}
 
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     impl<'a, 'b, A: ?Sized, B: ?Sized> PartialEq<&'b mut B> for &'a A where A: PartialEq<B> {
         #[inline]
         fn eq(&self, other: &&'b mut B) -> bool { PartialEq::eq(*self, *other) }
@@ -498,7 +498,7 @@ mod impls {
         fn ne(&self, other: &&'b mut B) -> bool { PartialEq::ne(*self, *other) }
     }
 
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     impl<'a, 'b, A: ?Sized, B: ?Sized> PartialEq<&'b B> for &'a mut A where A: PartialEq<B> {
         #[inline]
         fn eq(&self, other: &&'b B) -> bool { PartialEq::eq(*self, *other) }
diff --git a/src/libcore/default.rs b/src/libcore/default.rs
index 3b1e5e23150..d79b613f589 100644
--- a/src/libcore/default.rs
+++ b/src/libcore/default.rs
@@ -81,7 +81,7 @@
 //! }
 //! ```
 
-#![stable]
+#![stable(feature = "rust1", since = "1.0.0")]
 
 /// A trait that types which have a useful default value should implement.
 ///
@@ -97,7 +97,7 @@
 ///     bar: f32,
 /// }
 /// ```
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 pub trait Default {
     /// Returns the "default value" for a type.
     ///
@@ -131,16 +131,16 @@ pub trait Default {
     ///     fn default() -> Kind { Kind::A }
     /// }
     /// ```
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     fn default() -> Self;
 }
 
 macro_rules! default_impl {
     ($t:ty, $v:expr) => {
-        #[stable]
+        #[stable(feature = "rust1", since = "1.0.0")]
         impl Default for $t {
             #[inline]
-            #[stable]
+            #[stable(feature = "rust1", since = "1.0.0")]
             fn default() -> $t { $v }
         }
     }
diff --git a/src/libcore/error.rs b/src/libcore/error.rs
index 7bb11fb5d92..71d5e88cccf 100644
--- a/src/libcore/error.rs
+++ b/src/libcore/error.rs
@@ -79,13 +79,14 @@
 //! }
 //! ```
 
-#![stable]
+#![stable(feature = "rust1", since = "1.0.0")]
 
 use prelude::*;
 use fmt::Display;
 
 /// Base functionality for all errors in Rust.
-#[unstable = "the exact API of this trait may change"]
+#[unstable(feature = "core",
+           reason = "the exact API of this trait may change")]
 pub trait Error: Display {
     /// A short description of the error; usually a static string.
     fn description(&self) -> &str;
@@ -95,14 +96,15 @@ pub trait Error: Display {
 }
 
 /// A trait for types that can be converted from a given error type `E`.
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 pub trait FromError<E> {
     /// Perform the conversion.
+    #[stable(feature = "rust1", since = "1.0.0")]
     fn from_error(err: E) -> Self;
 }
 
 // Any type is convertable from itself
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl<E> FromError<E> for E {
     fn from_error(err: E) -> E {
         err
diff --git a/src/libcore/finally.rs b/src/libcore/finally.rs
index ed3612bded0..0f444ef186f 100644
--- a/src/libcore/finally.rs
+++ b/src/libcore/finally.rs
@@ -30,10 +30,12 @@
 //! })
 //! ```
 
-#![deprecated = "It is unclear if this module is more robust than implementing \
-                 Drop on a custom type, and this module is being removed with no \
-                 replacement. Use a custom Drop implementation to regain existing \
-                 functionality."]
+#![unstable(feature = "core")]
+#![deprecated(since = "1.0.0",
+              reason = "It is unclear if this module is more robust than implementing \
+                        Drop on a custom type, and this module is being removed with no \
+                        replacement. Use a custom Drop implementation to regain existing \
+                        functionality.")]
 #![allow(deprecated)]
 
 use ops::{Drop, FnMut, FnOnce};
diff --git a/src/libcore/fmt/mod.rs b/src/libcore/fmt/mod.rs
index 3c07e2e85d1..06428ad2f39 100644
--- a/src/libcore/fmt/mod.rs
+++ b/src/libcore/fmt/mod.rs
@@ -11,7 +11,7 @@
 //! Utilities for formatting and printing strings
 
 #![allow(unused_variables)]
-#![stable]
+#![stable(feature = "rust1", since = "1.0.0")]
 
 use any;
 use cell::{Cell, RefCell, Ref, RefMut};
@@ -39,7 +39,8 @@ mod num;
 mod float;
 pub mod rt;
 
-#[unstable = "core and I/O reconciliation may alter this definition"]
+#[unstable(feature = "core",
+           reason = "core and I/O reconciliation may alter this definition")]
 /// The type returned by formatter methods.
 pub type Result = result::Result<(), Error>;
 
@@ -48,7 +49,8 @@ pub type Result = result::Result<(), Error>;
 /// This type does not support transmission of an error other than that an error
 /// occurred. Any extra information must be arranged to be transmitted through
 /// some other means.
-#[unstable = "core and I/O reconciliation may alter this definition"]
+#[unstable(feature = "core",
+           reason = "core and I/O reconciliation may alter this definition")]
 #[derive(Copy, Show)]
 pub struct Error;
 
@@ -61,7 +63,8 @@ pub struct Error;
 /// This trait should generally not be implemented by consumers of the standard
 /// library. The `write!` macro accepts an instance of `io::Writer`, and the
 /// `io::Writer` trait is favored over implementing this trait.
-#[unstable = "waiting for core and I/O reconciliation"]
+#[unstable(feature = "core",
+           reason = "waiting for core and I/O reconciliation")]
 pub trait Writer {
     /// Writes a slice of bytes into this writer, returning whether the write
     /// succeeded.
@@ -104,7 +107,8 @@ pub trait Writer {
 /// A struct to represent both where to emit formatting strings to and how they
 /// should be formatted. A mutable version of this is passed to all formatting
 /// traits.
-#[unstable = "name may change and implemented traits are also unstable"]
+#[unstable(feature = "core",
+           reason = "name may change and implemented traits are also unstable")]
 pub struct Formatter<'a> {
     flags: uint,
     fill: char,
@@ -126,7 +130,8 @@ enum Void {}
 /// family of functions. It contains a function to format the given value. At
 /// compile time it is ensured that the function and the value have the correct
 /// types, and then this struct is used to canonicalize arguments to one type.
-#[unstable = "implementation detail of the `format_args!` macro"]
+#[unstable(feature = "core",
+           reason = "implementation detail of the `format_args!` macro")]
 #[derive(Copy)]
 pub struct Argument<'a> {
     value: &'a Void,
@@ -165,7 +170,8 @@ impl<'a> Arguments<'a> {
     /// When using the format_args!() macro, this function is used to generate the
     /// Arguments structure.
     #[doc(hidden)] #[inline]
-    #[unstable = "implementation detail of the `format_args!` macro"]
+    #[unstable(feature = "core",
+               reason = "implementation detail of the `format_args!` macro")]
     pub fn new(pieces: &'a [&'a str],
                args: &'a [Argument<'a>]) -> Arguments<'a> {
         Arguments {
@@ -182,7 +188,8 @@ impl<'a> Arguments<'a> {
     /// created with `argumentuint`. However, failing to do so doesn't cause
     /// unsafety, but will ignore invalid .
     #[doc(hidden)] #[inline]
-    #[unstable = "implementation detail of the `format_args!` macro"]
+    #[unstable(feature = "core",
+               reason = "implementation detail of the `format_args!` macro")]
     pub fn with_placeholders(pieces: &'a [&'a str],
                              fmt: &'a [rt::Argument],
                              args: &'a [Argument<'a>]) -> Arguments<'a> {
@@ -203,7 +210,7 @@ impl<'a> Arguments<'a> {
 /// and pass it to a function or closure, passed as the first argument. The
 /// macro validates the format string at compile-time so usage of the `write`
 /// and `format` functions can be safely performed.
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 #[derive(Copy)]
 pub struct Arguments<'a> {
     // Format string pieces to print.
@@ -217,14 +224,14 @@ pub struct Arguments<'a> {
     args: &'a [Argument<'a>],
 }
 
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl<'a> Debug for Arguments<'a> {
     fn fmt(&self, fmt: &mut Formatter) -> Result {
         Display::fmt(self, fmt)
     }
 }
 
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl<'a> Display for Arguments<'a> {
     fn fmt(&self, fmt: &mut Formatter) -> Result {
         write(fmt.buf, *self)
@@ -233,7 +240,9 @@ impl<'a> Display for Arguments<'a> {
 
 /// Format trait for the `:?` format. Useful for debugging, all types
 /// should implement this.
-#[deprecated = "renamed to Debug"]
+#[unstable(feature = "core",
+           reason = "I/O and core have yet to be reconciled")]
+#[deprecated(since = "1.0.0", reason = "renamed to Debug")]
 #[cfg(not(stage0))]
 pub trait Show {
     /// Formats the value using the given formatter.
@@ -242,7 +251,8 @@ pub trait Show {
 
 /// Format trait for the `:?` format. Useful for debugging, all types
 /// should implement this.
-#[unstable = "I/O and core have yet to be reconciled"]
+#[unstable(feature = "core",
+           reason = "I/O and core have yet to be reconciled")]
 #[rustc_on_unimplemented = "`{Self}` cannot be formatted using `:?`; if it is defined in your \
                             crate, add `#[derive(Debug)]` or manually implement it"]
 #[lang = "debug_trait"]
@@ -259,7 +269,8 @@ impl<T: Show + ?Sized> Debug for T {
 
 /// When a value can be semantically expressed as a String, this trait may be
 /// used. It corresponds to the default format, `{}`.
-#[deprecated = "renamed to Display"]
+#[unstable(feature = "core")]
+#[deprecated(since = "1.0.0", reason = "renamed to Display")]
 #[cfg(not(stage0))]
 pub trait String {
     /// Formats the value using the given formatter.
@@ -268,7 +279,8 @@ pub trait String {
 
 /// When a value can be semantically expressed as a String, this trait may be
 /// used. It corresponds to the default format, `{}`.
-#[unstable = "I/O and core have yet to be reconciled"]
+#[unstable(feature = "core",
+           reason = "I/O and core have yet to be reconciled")]
 #[rustc_on_unimplemented = "`{Self}` cannot be formatted with the default formatter; try using \
                             `:?` instead if you are using a format string"]
 pub trait Display {
@@ -283,49 +295,56 @@ impl<T: String + ?Sized> Display for T {
 }
 
 /// Format trait for the `o` character
-#[unstable = "I/O and core have yet to be reconciled"]
+#[unstable(feature = "core",
+           reason = "I/O and core have yet to be reconciled")]
 pub trait Octal {
     /// Formats the value using the given formatter.
     fn fmt(&self, &mut Formatter) -> Result;
 }
 
 /// Format trait for the `b` character
-#[unstable = "I/O and core have yet to be reconciled"]
+#[unstable(feature = "core",
+           reason = "I/O and core have yet to be reconciled")]
 pub trait Binary {
     /// Formats the value using the given formatter.
     fn fmt(&self, &mut Formatter) -> Result;
 }
 
 /// Format trait for the `x` character
-#[unstable = "I/O and core have yet to be reconciled"]
+#[unstable(feature = "core",
+           reason = "I/O and core have yet to be reconciled")]
 pub trait LowerHex {
     /// Formats the value using the given formatter.
     fn fmt(&self, &mut Formatter) -> Result;
 }
 
 /// Format trait for the `X` character
-#[unstable = "I/O and core have yet to be reconciled"]
+#[unstable(feature = "core",
+           reason = "I/O and core have yet to be reconciled")]
 pub trait UpperHex {
     /// Formats the value using the given formatter.
     fn fmt(&self, &mut Formatter) -> Result;
 }
 
 /// Format trait for the `p` character
-#[unstable = "I/O and core have yet to be reconciled"]
+#[unstable(feature = "core",
+           reason = "I/O and core have yet to be reconciled")]
 pub trait Pointer {
     /// Formats the value using the given formatter.
     fn fmt(&self, &mut Formatter) -> Result;
 }
 
 /// Format trait for the `e` character
-#[unstable = "I/O and core have yet to be reconciled"]
+#[unstable(feature = "core",
+           reason = "I/O and core have yet to be reconciled")]
 pub trait LowerExp {
     /// Formats the value using the given formatter.
     fn fmt(&self, &mut Formatter) -> Result;
 }
 
 /// Format trait for the `E` character
-#[unstable = "I/O and core have yet to be reconciled"]
+#[unstable(feature = "core",
+           reason = "I/O and core have yet to be reconciled")]
 pub trait UpperExp {
     /// Formats the value using the given formatter.
     fn fmt(&self, &mut Formatter) -> Result;
@@ -339,8 +358,9 @@ pub trait UpperExp {
 ///
 ///   * output - the buffer to write output to
 ///   * args - the precompiled arguments generated by `format_args!`
-#[unstable = "libcore and I/O have yet to be reconciled, and this is an \
-                  implementation detail which should not otherwise be exported"]
+#[unstable(feature = "core",
+           reason = "libcore and I/O have yet to be reconciled, and this is an \
+                     implementation detail which should not otherwise be exported")]
 pub fn write(output: &mut Writer, args: Arguments) -> Result {
     let mut formatter = Formatter {
         flags: 0,
@@ -436,7 +456,8 @@ impl<'a> Formatter<'a> {
     ///
     /// This function will correctly account for the flags provided as well as
     /// the minimum width. It will not take precision into account.
-    #[unstable = "definition may change slightly over time"]
+    #[unstable(feature = "core",
+               reason = "definition may change slightly over time")]
     pub fn pad_integral(&mut self,
                         is_positive: bool,
                         prefix: &str,
@@ -512,7 +533,8 @@ impl<'a> Formatter<'a> {
     ///               is longer than this length
     ///
     /// Notably this function ignored the `flag` parameters
-    #[unstable = "definition may change slightly over time"]
+    #[unstable(feature = "core",
+               reason = "definition may change slightly over time")]
     pub fn pad(&mut self, s: &str) -> Result {
         // Make sure there's a fast path up front
         if self.width.is_none() && self.precision.is_none() {
@@ -589,39 +611,42 @@ impl<'a> Formatter<'a> {
 
     /// Writes some data to the underlying buffer contained within this
     /// formatter.
-    #[unstable = "reconciling core and I/O may alter this definition"]
+    #[unstable(feature = "core",
+               reason = "reconciling core and I/O may alter this definition")]
     pub fn write_str(&mut self, data: &str) -> Result {
         self.buf.write_str(data)
     }
 
     /// Writes some formatted information into this instance
-    #[unstable = "reconciling core and I/O may alter this definition"]
+    #[unstable(feature = "core",
+               reason = "reconciling core and I/O may alter this definition")]
     pub fn write_fmt(&mut self, fmt: Arguments) -> Result {
         write(self.buf, fmt)
     }
 
     /// Flags for formatting (packed version of rt::Flag)
-    #[unstable = "return type may change and method was just created"]
+    #[unstable(feature = "core",
+               reason = "return type may change and method was just created")]
     pub fn flags(&self) -> uint { self.flags }
 
     /// Character used as 'fill' whenever there is alignment
-    #[unstable = "method was just created"]
+    #[unstable(feature = "core", reason = "method was just created")]
     pub fn fill(&self) -> char { self.fill }
 
     /// Flag indicating what form of alignment was requested
-    #[unstable = "method was just created"]
+    #[unstable(feature = "core", reason = "method was just created")]
     pub fn align(&self) -> rt::Alignment { self.align }
 
     /// Optionally specified integer width that the output should be
-    #[unstable = "method was just created"]
+    #[unstable(feature = "core", reason = "method was just created")]
     pub fn width(&self) -> Option<uint> { self.width }
 
     /// Optionally specified precision for numeric types
-    #[unstable = "method was just created"]
+    #[unstable(feature = "core", reason = "method was just created")]
     pub fn precision(&self) -> Option<uint> { self.precision }
 }
 
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl Display for Error {
     fn fmt(&self, f: &mut Formatter) -> Result {
         Display::fmt("an error occurred when formatting an argument", f)
@@ -631,7 +656,8 @@ impl Display for Error {
 /// This is a function which calls are emitted to by the compiler itself to
 /// create the Argument structures that are passed into the `format` function.
 #[doc(hidden)] #[inline]
-#[unstable = "implementation detail of the `format_args!` macro"]
+#[unstable(feature = "core",
+           reason = "implementation detail of the `format_args!` macro")]
 pub fn argument<'a, T>(f: fn(&T, &mut Formatter) -> Result,
                        t: &'a T) -> Argument<'a> {
     Argument::new(t, f)
@@ -640,7 +666,8 @@ pub fn argument<'a, T>(f: fn(&T, &mut Formatter) -> Result,
 /// When the compiler determines that the type of an argument *must* be a uint
 /// (such as for width and precision), then it invokes this method.
 #[doc(hidden)] #[inline]
-#[unstable = "implementation detail of the `format_args!` macro"]
+#[unstable(feature = "core",
+           reason = "implementation detail of the `format_args!` macro")]
 pub fn argumentuint<'a>(s: &'a uint) -> Argument<'a> {
     Argument::from_uint(s)
 }
@@ -650,11 +677,11 @@ pub fn argumentuint<'a>(s: &'a uint) -> Argument<'a> {
 macro_rules! fmt_refs {
     ($($tr:ident),*) => {
         $(
-        #[stable]
+        #[stable(feature = "rust1", since = "1.0.0")]
         impl<'a, T: ?Sized + $tr> $tr for &'a T {
             fn fmt(&self, f: &mut Formatter) -> Result { $tr::fmt(&**self, f) }
         }
-        #[stable]
+        #[stable(feature = "rust1", since = "1.0.0")]
         impl<'a, T: ?Sized + $tr> $tr for &'a mut T {
             fn fmt(&self, f: &mut Formatter) -> Result { $tr::fmt(&**self, f) }
         }
@@ -664,21 +691,21 @@ macro_rules! fmt_refs {
 
 fmt_refs! { Debug, Display, Octal, Binary, LowerHex, UpperHex, LowerExp, UpperExp }
 
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl Debug for bool {
     fn fmt(&self, f: &mut Formatter) -> Result {
         Display::fmt(self, f)
     }
 }
 
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl Display for bool {
     fn fmt(&self, f: &mut Formatter) -> Result {
         Display::fmt(if *self { "true" } else { "false" }, f)
     }
 }
 
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl Debug for str {
     fn fmt(&self, f: &mut Formatter) -> Result {
         try!(write!(f, "\""));
@@ -689,14 +716,14 @@ impl Debug for str {
     }
 }
 
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl Display for str {
     fn fmt(&self, f: &mut Formatter) -> Result {
         f.pad(self)
     }
 }
 
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl Debug for char {
     fn fmt(&self, f: &mut Formatter) -> Result {
         use char::CharExt;
@@ -708,7 +735,7 @@ impl Debug for char {
     }
 }
 
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl Display for char {
     fn fmt(&self, f: &mut Formatter) -> Result {
         let mut utf8 = [0u8; 4];
@@ -718,7 +745,7 @@ impl Display for char {
     }
 }
 
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl<T> Pointer for *const T {
     fn fmt(&self, f: &mut Formatter) -> Result {
         f.flags |= 1 << (rt::FlagAlternate as uint);
@@ -728,21 +755,21 @@ impl<T> Pointer for *const T {
     }
 }
 
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl<T> Pointer for *mut T {
     fn fmt(&self, f: &mut Formatter) -> Result {
         Pointer::fmt(&(*self as *const T), f)
     }
 }
 
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl<'a, T> Pointer for &'a T {
     fn fmt(&self, f: &mut Formatter) -> Result {
         Pointer::fmt(&(*self as *const T), f)
     }
 }
 
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl<'a, T> Pointer for &'a mut T {
     fn fmt(&self, f: &mut Formatter) -> Result {
         Pointer::fmt(&(&**self as *const T), f)
@@ -751,14 +778,14 @@ impl<'a, T> Pointer for &'a mut T {
 
 macro_rules! floating { ($ty:ident) => {
 
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     impl Debug for $ty {
         fn fmt(&self, fmt: &mut Formatter) -> Result {
             Display::fmt(self, fmt)
         }
     }
 
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     impl Display for $ty {
         fn fmt(&self, fmt: &mut Formatter) -> Result {
             use num::Float;
@@ -780,7 +807,7 @@ macro_rules! floating { ($ty:ident) => {
         }
     }
 
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     impl LowerExp for $ty {
         fn fmt(&self, fmt: &mut Formatter) -> Result {
             use num::Float;
@@ -802,7 +829,7 @@ macro_rules! floating { ($ty:ident) => {
         }
     }
 
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     impl UpperExp for $ty {
         fn fmt(&self, fmt: &mut Formatter) -> Result {
             use num::Float;
@@ -829,11 +856,11 @@ floating! { f64 }
 
 // Implementation of Display/Debug for various core types
 
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl<T> Debug for *const T {
     fn fmt(&self, f: &mut Formatter) -> Result { Pointer::fmt(self, f) }
 }
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl<T> Debug for *mut T {
     fn fmt(&self, f: &mut Formatter) -> Result { Pointer::fmt(self, f) }
 }
@@ -845,7 +872,7 @@ macro_rules! peel {
 macro_rules! tuple {
     () => ();
     ( $($name:ident,)+ ) => (
-        #[stable]
+        #[stable(feature = "rust1", since = "1.0.0")]
         impl<$($name:Debug),*> Debug for ($($name,)*) {
             #[allow(non_snake_case, unused_assignments)]
             fn fmt(&self, f: &mut Formatter) -> Result {
@@ -871,12 +898,12 @@ macro_rules! tuple {
 
 tuple! { T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, }
 
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl<'a> Debug for &'a (any::Any+'a) {
     fn fmt(&self, f: &mut Formatter) -> Result { f.pad("&Any") }
 }
 
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl<T: Debug> Debug for [T] {
     fn fmt(&self, f: &mut Formatter) -> Result {
         if f.flags & (1 << (rt::FlagAlternate as uint)) == 0 {
@@ -898,21 +925,21 @@ impl<T: Debug> Debug for [T] {
     }
 }
 
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl Debug for () {
     fn fmt(&self, f: &mut Formatter) -> Result {
         f.pad("()")
     }
 }
 
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl<T: Copy + Debug> Debug for Cell<T> {
     fn fmt(&self, f: &mut Formatter) -> Result {
         write!(f, "Cell {{ value: {:?} }}", self.get())
     }
 }
 
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl<T: Debug> Debug for RefCell<T> {
     fn fmt(&self, f: &mut Formatter) -> Result {
         match self.try_borrow() {
@@ -922,14 +949,14 @@ impl<T: Debug> Debug for RefCell<T> {
     }
 }
 
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl<'b, T: Debug> Debug for Ref<'b, T> {
     fn fmt(&self, f: &mut Formatter) -> Result {
         Debug::fmt(&**self, f)
     }
 }
 
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl<'b, T: Debug> Debug for RefMut<'b, T> {
     fn fmt(&self, f: &mut Formatter) -> Result {
         Debug::fmt(&*(self.deref()), f)
diff --git a/src/libcore/fmt/num.rs b/src/libcore/fmt/num.rs
index a659a9988bb..1222126b5e0 100644
--- a/src/libcore/fmt/num.rs
+++ b/src/libcore/fmt/num.rs
@@ -111,7 +111,8 @@ radix! { UpperHex, 16, "0x", x @  0 ...  9 => b'0' + x,
 
 /// A radix with in the range of `2..36`.
 #[derive(Clone, Copy, PartialEq)]
-#[unstable = "may be renamed or move to a different module"]
+#[unstable(feature = "core",
+           reason = "may be renamed or move to a different module")]
 pub struct Radix {
     base: u8,
 }
@@ -135,7 +136,8 @@ impl GenericRadix for Radix {
 }
 
 /// A helper type for formatting radixes.
-#[unstable = "may be renamed or move to a different module"]
+#[unstable(feature = "core",
+           reason = "may be renamed or move to a different module")]
 #[derive(Copy)]
 pub struct RadixFmt<T, R>(T, R);
 
@@ -147,20 +149,21 @@ pub struct RadixFmt<T, R>(T, R);
 /// use std::fmt::radix;
 /// assert_eq!(format!("{}", radix(55, 36)), "1j".to_string());
 /// ```
-#[unstable = "may be renamed or move to a different module"]
+#[unstable(feature = "core",
+           reason = "may be renamed or move to a different module")]
 pub fn radix<T>(x: T, base: u8) -> RadixFmt<T, Radix> {
     RadixFmt(x, Radix::new(base))
 }
 
 macro_rules! radix_fmt {
     ($T:ty as $U:ty, $fmt:ident, $S:expr) => {
-        #[stable]
+        #[stable(feature = "rust1", since = "1.0.0")]
         impl fmt::Debug for RadixFmt<$T, Radix> {
             fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
                 fmt::Display::fmt(self, f)
             }
         }
-        #[stable]
+        #[stable(feature = "rust1", since = "1.0.0")]
         impl fmt::Display for RadixFmt<$T, Radix> {
             fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
                 match *self { RadixFmt(ref x, radix) => radix.$fmt(*x as $U, f) }
@@ -170,7 +173,7 @@ macro_rules! radix_fmt {
 }
 macro_rules! int_base {
     ($Trait:ident for $T:ident as $U:ident -> $Radix:ident) => {
-        #[stable]
+        #[stable(feature = "rust1", since = "1.0.0")]
         impl fmt::$Trait for $T {
             fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
                 $Radix.fmt_int(*self as $U, f)
@@ -181,7 +184,7 @@ macro_rules! int_base {
 
 macro_rules! show {
     ($T:ident with $S:expr) => {
-        #[stable]
+        #[stable(feature = "rust1", since = "1.0.0")]
         impl fmt::Debug for $T {
             fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
                 fmt::Display::fmt(self, f)
diff --git a/src/libcore/fmt/rt.rs b/src/libcore/fmt/rt.rs
index bea32219155..0b2c1efbc5d 100644
--- a/src/libcore/fmt/rt.rs
+++ b/src/libcore/fmt/rt.rs
@@ -14,7 +14,8 @@
 //! These definitions are similar to their `ct` equivalents, but differ in that
 //! these can be statically allocated and are slightly optimized for the runtime
 
-#![unstable = "implementation detail of the `format_args!` macro"]
+#![unstable(feature = "core",
+            reason = "implementation detail of the `format_args!` macro")]
 
 pub use self::Alignment::*;
 pub use self::Count::*;
diff --git a/src/libcore/hash/mod.rs b/src/libcore/hash/mod.rs
index 742e6239017..5a4d2fffade 100644
--- a/src/libcore/hash/mod.rs
+++ b/src/libcore/hash/mod.rs
@@ -56,7 +56,8 @@
 //! assert_eq!(hash::<_, SipHasher>(&person1), hash::<_, SipHasher>(&person2));
 //! ```
 
-#![unstable = "module was recently redesigned"]
+#![unstable(feature = "hash",
+            reason = "module was recently redesigned")]
 
 use prelude::*;
 
@@ -95,7 +96,8 @@ pub trait Hasher {
 
 /// A common bound on the `Hasher` parameter to `Hash` implementations in order
 /// to generically hash an aggregate.
-#[experimental = "this trait will likely be replaced by io::Writer"]
+#[unstable(feature = "hash",
+           reason = "this trait will likely be replaced by io::Writer")]
 #[allow(missing_docs)]
 pub trait Writer {
     fn write(&mut self, bytes: &[u8]);
diff --git a/src/libcore/hash/sip.rs b/src/libcore/hash/sip.rs
index 8840eaf5fbc..bef196d4824 100644
--- a/src/libcore/hash/sip.rs
+++ b/src/libcore/hash/sip.rs
@@ -112,7 +112,8 @@ impl SipHasher {
     }
 
     /// Returns the computed hash.
-    #[deprecated = "renamed to finish"]
+    #[unstable(feature = "hash")]
+    #[deprecated(since = "1.0.0", reason = "renamed to finish")]
     pub fn result(&self) -> u64 { self.finish() }
 }
 
diff --git a/src/libcore/intrinsics.rs b/src/libcore/intrinsics.rs
index dd488a74216..dd6b1e7b4e8 100644
--- a/src/libcore/intrinsics.rs
+++ b/src/libcore/intrinsics.rs
@@ -39,7 +39,7 @@
 //!   guaranteed to happen in order. This is the standard mode for working
 //!   with atomic types and is equivalent to Java's `volatile`.
 
-#![unstable]
+#![unstable(feature = "core")]
 #![allow(missing_docs)]
 
 use marker::Sized;
@@ -221,7 +221,7 @@ extern "rust-intrinsic" {
     ///
     /// `forget` is unsafe because the caller is responsible for
     /// ensuring the argument is deallocated already.
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     pub fn forget<T>(_: T) -> ();
 
     /// Unsafely transforms a value of one type into a value of another type.
@@ -237,7 +237,7 @@ extern "rust-intrinsic" {
     /// let v: &[u8] = unsafe { mem::transmute("L") };
     /// assert!(v == [76u8]);
     /// ```
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     pub fn transmute<T,U>(e: T) -> U;
 
     /// Gives the address for the return value of the enclosing function.
@@ -297,7 +297,7 @@ extern "rust-intrinsic" {
     ///     }
     /// }
     /// ```
-    #[unstable]
+    #[unstable(feature = "core")]
     pub fn copy_nonoverlapping_memory<T>(dst: *mut T, src: *const T, count: uint);
 
     /// Copies `count * size_of<T>` bytes from `src` to `dst`. The source
@@ -327,12 +327,13 @@ extern "rust-intrinsic" {
     /// }
     /// ```
     ///
-    #[unstable]
+    #[unstable(feature = "core")]
     pub fn copy_memory<T>(dst: *mut T, src: *const T, count: uint);
 
     /// Invokes memset on the specified pointer, setting `count * size_of::<T>()`
     /// bytes of memory starting at `dst` to `c`.
-    #[unstable = "uncertain about naming and semantics"]
+    #[unstable(feature = "core",
+               reason = "uncertain about naming and semantics")]
     pub fn set_memory<T>(dst: *mut T, val: u8, count: uint);
 
     /// Equivalent to the appropriate `llvm.memcpy.p0i8.0i8.*` intrinsic, with
diff --git a/src/libcore/iter.rs b/src/libcore/iter.rs
index 4910c03de5c..74d8a7ae1d6 100644
--- a/src/libcore/iter.rs
+++ b/src/libcore/iter.rs
@@ -54,7 +54,7 @@
 //!
 //! This `for` loop syntax can be applied to any iterator over any type.
 
-#![stable]
+#![stable(feature = "rust1", since = "1.0.0")]
 
 use self::MinMaxResult::*;
 
@@ -81,15 +81,15 @@ use usize;
 /// it wishes, either by returning `None` infinitely, or by doing something
 /// else.
 #[lang="iterator"]
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 #[rustc_on_unimplemented = "`{Self}` is not an iterator; maybe try calling `.iter()` or a similar \
                             method"]
 pub trait Iterator {
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     type Item;
 
     /// Advance the iterator and return the next value. Return `None` when the end is reached.
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     fn next(&mut self) -> Option<Self::Item>;
 
     /// Returns a lower and upper bound on the remaining length of the iterator.
@@ -97,7 +97,7 @@ pub trait Iterator {
     /// An upper bound of `None` means either there is no known upper bound, or the upper bound
     /// does not fit within a `usize`.
     #[inline]
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     fn size_hint(&self) -> (usize, Option<usize>) { (0, None) }
 }
 
@@ -116,7 +116,7 @@ impl<'a, T> Iterator for &'a mut (Iterator<Item=T> + 'a) {
 }
 
 /// Conversion from an `Iterator`
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 #[rustc_on_unimplemented="a collection of type `{Self}` cannot be \
                           built from an iterator over elements of type `{A}`"]
 pub trait FromIterator<A> {
@@ -125,15 +125,15 @@ pub trait FromIterator<A> {
 }
 
 /// A type growable from an `Iterator` implementation
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 pub trait Extend<A> {
     /// Extend a container with the elements yielded by an arbitrary iterator
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     fn extend<T: Iterator<Item=A>>(&mut self, iterator: T);
 }
 
 /// An extension trait providing numerous methods applicable to all iterators.
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 pub trait IteratorExt: Iterator + Sized {
     /// Counts the number of elements in this iterator.
     ///
@@ -144,7 +144,7 @@ pub trait IteratorExt: Iterator + Sized {
     /// assert_eq!(a.iter().count(), 5);
     /// ```
     #[inline]
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     fn count(self) -> usize {
         self.fold(0, |cnt, _x| cnt + 1)
     }
@@ -159,7 +159,7 @@ pub trait IteratorExt: Iterator + Sized {
     /// assert!(a.iter().last().unwrap() == &5);
     /// ```
     #[inline]
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     fn last(mut self) -> Option<Self::Item> {
         let mut last = None;
         for x in self { last = Some(x); }
@@ -178,7 +178,7 @@ pub trait IteratorExt: Iterator + Sized {
     /// assert!(it.nth(2) == None);
     /// ```
     #[inline]
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     fn nth(&mut self, mut n: usize) -> Option<Self::Item> {
         for x in *self {
             if n == 0 { return Some(x) }
@@ -202,7 +202,7 @@ pub trait IteratorExt: Iterator + Sized {
     /// assert!(it.next().is_none());
     /// ```
     #[inline]
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     fn chain<U>(self, other: U) -> Chain<Self, U> where
         U: Iterator<Item=Self::Item>,
     {
@@ -224,7 +224,7 @@ pub trait IteratorExt: Iterator + Sized {
     /// assert!(it.next().is_none());
     /// ```
     #[inline]
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     fn zip<B, U>(self, other: U) -> Zip<Self, U> where
         U: Iterator<Item=B>,
     {
@@ -244,7 +244,7 @@ pub trait IteratorExt: Iterator + Sized {
     /// assert!(it.next().is_none());
     /// ```
     #[inline]
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     fn map<B, F>(self, f: F) -> Map<Self::Item, B, Self, F> where
         F: FnMut(Self::Item) -> B,
     {
@@ -264,7 +264,7 @@ pub trait IteratorExt: Iterator + Sized {
     /// assert!(it.next().is_none());
     /// ```
     #[inline]
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     fn filter<P>(self, predicate: P) -> Filter<Self::Item, Self, P> where
         P: FnMut(&Self::Item) -> bool,
     {
@@ -284,7 +284,7 @@ pub trait IteratorExt: Iterator + Sized {
     /// assert!(it.next().is_none());
     /// ```
     #[inline]
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     fn filter_map<B, F>(self, f: F) -> FilterMap<Self::Item, B, Self, F> where
         F: FnMut(Self::Item) -> Option<B>,
     {
@@ -304,7 +304,7 @@ pub trait IteratorExt: Iterator + Sized {
     /// assert!(it.next().is_none());
     /// ```
     #[inline]
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     fn enumerate(self) -> Enumerate<Self> {
         Enumerate{iter: self, count: 0}
     }
@@ -327,7 +327,7 @@ pub trait IteratorExt: Iterator + Sized {
     /// assert!(it.next().is_none());
     /// ```
     #[inline]
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     fn peekable(self) -> Peekable<Self::Item, Self> {
         Peekable{iter: self, peeked: None}
     }
@@ -347,7 +347,7 @@ pub trait IteratorExt: Iterator + Sized {
     /// assert!(it.next().is_none());
     /// ```
     #[inline]
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     fn skip_while<P>(self, predicate: P) -> SkipWhile<Self::Item, Self, P> where
         P: FnMut(&Self::Item) -> bool,
     {
@@ -368,7 +368,7 @@ pub trait IteratorExt: Iterator + Sized {
     /// assert!(it.next().is_none());
     /// ```
     #[inline]
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     fn take_while<P>(self, predicate: P) -> TakeWhile<Self::Item, Self, P> where
         P: FnMut(&Self::Item) -> bool,
     {
@@ -388,7 +388,7 @@ pub trait IteratorExt: Iterator + Sized {
     /// assert!(it.next().is_none());
     /// ```
     #[inline]
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     fn skip(self, n: usize) -> Skip<Self> {
         Skip{iter: self, n: n}
     }
@@ -407,7 +407,7 @@ pub trait IteratorExt: Iterator + Sized {
     /// assert!(it.next().is_none());
     /// ```
     #[inline]
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     fn take(self, n: usize) -> Take<Self> {
         Take{iter: self, n: n}
     }
@@ -433,7 +433,7 @@ pub trait IteratorExt: Iterator + Sized {
     /// assert!(it.next().is_none());
     /// ```
     #[inline]
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     fn scan<St, B, F>(
         self,
         initial_state: St,
@@ -459,7 +459,7 @@ pub trait IteratorExt: Iterator + Sized {
     /// }
     /// ```
     #[inline]
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     fn flat_map<B, U, F>(self, f: F) -> FlatMap<Self::Item, B, Self, U, F> where
         U: Iterator<Item=B>,
         F: FnMut(Self::Item) -> U,
@@ -495,7 +495,7 @@ pub trait IteratorExt: Iterator + Sized {
     /// assert_eq!(process(x.into_iter()), 1006);
     /// ```
     #[inline]
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     fn fuse(self) -> Fuse<Self> {
         Fuse{iter: self, done: false}
     }
@@ -519,7 +519,7 @@ pub trait IteratorExt: Iterator + Sized {
     /// println!("{}", sum);
     /// ```
     #[inline]
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     fn inspect<F>(self, f: F) -> Inspect<Self::Item, Self, F> where
         F: FnMut(&Self::Item),
     {
@@ -540,7 +540,7 @@ pub trait IteratorExt: Iterator + Sized {
     /// assert!(partial_sum == 10);
     /// assert!(it.next() == Some(5));
     /// ```
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     fn by_ref<'r>(&'r mut self) -> ByRef<'r, Self> {
         ByRef{iter: self}
     }
@@ -556,7 +556,7 @@ pub trait IteratorExt: Iterator + Sized {
     /// assert_eq!(a, b);
     /// ```
     #[inline]
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     fn collect<B: FromIterator<Self::Item>>(self) -> B {
         FromIterator::from_iter(self)
     }
@@ -572,7 +572,8 @@ pub trait IteratorExt: Iterator + Sized {
     /// assert_eq!(even, vec![2, 4]);
     /// assert_eq!(odd, vec![1, 3]);
     /// ```
-    #[unstable = "recently added as part of collections reform"]
+    #[unstable(feature = "core",
+               reason = "recently added as part of collections reform")]
     fn partition<B, F>(mut self, mut f: F) -> (B, B) where
         B: Default + Extend<Self::Item>,
         F: FnMut(&Self::Item) -> bool
@@ -601,7 +602,7 @@ pub trait IteratorExt: Iterator + Sized {
     /// assert!(a.iter().fold(0, |a, &b| a + b) == 15);
     /// ```
     #[inline]
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     fn fold<B, F>(mut self, init: B, mut f: F) -> B where
         F: FnMut(B, Self::Item) -> B,
     {
@@ -622,7 +623,7 @@ pub trait IteratorExt: Iterator + Sized {
     /// assert!(!a.iter().all(|x| *x > 2));
     /// ```
     #[inline]
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     fn all<F>(mut self, mut f: F) -> bool where F: FnMut(Self::Item) -> bool {
         for x in self { if !f(x) { return false; } }
         true
@@ -642,7 +643,7 @@ pub trait IteratorExt: Iterator + Sized {
     ///
     /// ```
     #[inline]
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     fn any<F>(&mut self, mut f: F) -> bool where F: FnMut(Self::Item) -> bool {
         for x in *self { if f(x) { return true; } }
         false
@@ -660,7 +661,7 @@ pub trait IteratorExt: Iterator + Sized {
     /// assert_eq!(it.find(|&x| *x == 3).unwrap(), &3);
     /// assert_eq!(it.as_slice(), [4, 5]);
     #[inline]
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     fn find<P>(&mut self, mut predicate: P) -> Option<Self::Item> where
         P: FnMut(&Self::Item) -> bool,
     {
@@ -682,7 +683,7 @@ pub trait IteratorExt: Iterator + Sized {
     /// assert_eq!(it.position(|x| *x == 3).unwrap(), 2);
     /// assert_eq!(it.as_slice(), [4, 5]);
     #[inline]
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     fn position<P>(&mut self, mut predicate: P) -> Option<usize> where
         P: FnMut(Self::Item) -> bool,
     {
@@ -710,7 +711,7 @@ pub trait IteratorExt: Iterator + Sized {
     /// assert_eq!(it.rposition(|x| *x == 2).unwrap(), 2);
     /// assert_eq!(it.as_slice(), [1, 2]);
     #[inline]
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     fn rposition<P>(&mut self, mut predicate: P) -> Option<usize> where
         P: FnMut(Self::Item) -> bool,
         Self: ExactSizeIterator + DoubleEndedIterator
@@ -733,7 +734,7 @@ pub trait IteratorExt: Iterator + Sized {
     /// assert!(a.iter().max().unwrap() == &5);
     /// ```
     #[inline]
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     fn max(self) -> Option<Self::Item> where Self::Item: Ord
     {
         self.fold(None, |max, x| {
@@ -753,7 +754,7 @@ pub trait IteratorExt: Iterator + Sized {
     /// assert!(a.iter().min().unwrap() == &1);
     /// ```
     #[inline]
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     fn min(self) -> Option<Self::Item> where Self::Item: Ord
     {
         self.fold(None, |min, x| {
@@ -794,7 +795,7 @@ pub trait IteratorExt: Iterator + Sized {
     /// let a = [1, 1, 1, 1];
     /// assert!(a.iter().min_max() == MinMax(&1, &1));
     /// ```
-    #[unstable = "return type may change"]
+    #[unstable(feature = "core", reason = "return type may change")]
     fn min_max(mut self) -> MinMaxResult<Self::Item> where Self::Item: Ord
     {
         let (mut min, mut max) = match self.next() {
@@ -851,7 +852,8 @@ pub trait IteratorExt: Iterator + Sized {
     /// assert_eq!(*a.iter().max_by(|x| x.abs()).unwrap(), -10);
     /// ```
     #[inline]
-    #[unstable = "may want to produce an Ordering directly; see #15311"]
+    #[unstable(feature = "core",
+               reason = "may want to produce an Ordering directly; see #15311")]
     fn max_by<B: Ord, F>(self, mut f: F) -> Option<Self::Item> where
         F: FnMut(&Self::Item) -> B,
     {
@@ -880,7 +882,8 @@ pub trait IteratorExt: Iterator + Sized {
     /// assert_eq!(*a.iter().min_by(|x| x.abs()).unwrap(), 0);
     /// ```
     #[inline]
-    #[unstable = "may want to produce an Ordering directly; see #15311"]
+    #[unstable(feature = "core",
+               reason = "may want to produce an Ordering directly; see #15311")]
     fn min_by<B: Ord, F>(self, mut f: F) -> Option<Self::Item> where
         F: FnMut(&Self::Item) -> B,
     {
@@ -910,7 +913,7 @@ pub trait IteratorExt: Iterator + Sized {
     /// Note: Random access with flipped indices still only applies to the first
     /// `std::usize::MAX` elements of the original iterator.
     #[inline]
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     fn rev(self) -> Rev<Self> {
         Rev{iter: self}
     }
@@ -928,7 +931,7 @@ pub trait IteratorExt: Iterator + Sized {
     /// assert_eq!([1, 3], left);
     /// assert_eq!([2, 4], right);
     /// ```
-    #[unstable = "recent addition"]
+    #[unstable(feature = "core", reason = "recent addition")]
     fn unzip<A, B, FromA, FromB>(mut self) -> (FromA, FromB) where
         FromA: Default + Extend<A>,
         FromB: Default + Extend<B>,
@@ -961,7 +964,7 @@ pub trait IteratorExt: Iterator + Sized {
 
     /// Creates an iterator that clones the elements it yields. Useful for converting an
     /// Iterator<&T> to an Iterator<T>.
-    #[unstable = "recent addition"]
+    #[unstable(feature = "core", reason = "recent addition")]
     fn cloned<T, D>(self) -> Cloned<Self> where
         Self: Iterator<Item=D>,
         D: Deref<Target=T>,
@@ -981,14 +984,15 @@ pub trait IteratorExt: Iterator + Sized {
     /// assert_eq!(it.next().unwrap(), &2);
     /// assert_eq!(it.next().unwrap(), &1);
     /// ```
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     #[inline]
     fn cycle(self) -> Cycle<Self> where Self: Clone {
         Cycle{orig: self.clone(), iter: self}
     }
 
     /// Use an iterator to reverse a container in place.
-    #[unstable = "uncertain about placement or widespread use"]
+    #[unstable(feature = "core",
+               reason = "uncertain about placement or widespread use")]
     fn reverse_in_place<'a, T: 'a>(&mut self) where
         Self: Iterator<Item=&'a mut T> + DoubleEndedIterator
     {
@@ -1001,17 +1005,17 @@ pub trait IteratorExt: Iterator + Sized {
     }
 }
 
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl<I> IteratorExt for I where I: Iterator {}
 
 /// A range iterator able to yield elements from both ends
 ///
 /// A `DoubleEndedIterator` can be thought of as a deque in that `next()` and `next_back()` exhaust
 /// elements from the *same* range, and do not work independently of each other.
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 pub trait DoubleEndedIterator: Iterator {
     /// Yield an element from the end of the range, returning `None` if the range is empty.
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     fn next_back(&mut self) -> Option<Self::Item>;
 }
 
@@ -1021,7 +1025,8 @@ pub trait DoubleEndedIterator: Iterator {
 /// Calling `next()` or `next_back()` on a `RandomAccessIterator`
 /// reduces the indexable range accordingly. That is, `it.idx(1)` will become `it.idx(0)`
 /// after `it.next()` is called.
-#[unstable = "not widely used, may be better decomposed into Index and ExactSizeIterator"]
+#[unstable(feature = "core",
+           reason = "not widely used, may be better decomposed into Index and ExactSizeIterator")]
 pub trait RandomAccessIterator: Iterator {
     /// Return the number of indexable elements. At most `std::usize::MAX`
     /// elements are indexable, even if the iterator represents a longer range.
@@ -1038,7 +1043,7 @@ pub trait RandomAccessIterator: Iterator {
 ///
 /// `Iterator::size_hint` *must* return the exact size of the iterator.
 /// Note that the size must fit in `usize`.
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 pub trait ExactSizeIterator: Iterator {
     #[inline]
     /// Return the exact length of the iterator.
@@ -1055,32 +1060,32 @@ pub trait ExactSizeIterator: Iterator {
 
 // All adaptors that preserve the size of the wrapped iterator are fine
 // Adaptors that may overflow in `size_hint` are not, i.e. `Chain`.
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl<I> ExactSizeIterator for Enumerate<I> where I: ExactSizeIterator {}
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl<A, I, F> ExactSizeIterator for Inspect<A, I, F> where
     I: ExactSizeIterator<Item=A>,
     F: FnMut(&A),
 {}
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl<I> ExactSizeIterator for Rev<I> where I: ExactSizeIterator + DoubleEndedIterator {}
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl<A, B, I, F> ExactSizeIterator for Map<A, B, I, F> where
     I: ExactSizeIterator<Item=A>,
     F: FnMut(A) -> B,
 {}
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl<A, B> ExactSizeIterator for Zip<A, B> where A: ExactSizeIterator, B: ExactSizeIterator {}
 
 /// An double-ended iterator with the direction inverted
 #[derive(Clone)]
 #[must_use = "iterator adaptors are lazy and do nothing unless consumed"]
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 pub struct Rev<T> {
     iter: T
 }
 
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl<I> Iterator for Rev<I> where I: DoubleEndedIterator {
     type Item = <I as Iterator>::Item;
 
@@ -1090,13 +1095,13 @@ impl<I> Iterator for Rev<I> where I: DoubleEndedIterator {
     fn size_hint(&self) -> (usize, Option<usize>) { self.iter.size_hint() }
 }
 
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl<I> DoubleEndedIterator for Rev<I> where I: DoubleEndedIterator {
     #[inline]
     fn next_back(&mut self) -> Option<<I as Iterator>::Item> { self.iter.next() }
 }
 
-#[unstable = "trait is experimental"]
+#[unstable(feature = "core", reason = "trait is experimental")]
 impl<I> RandomAccessIterator for Rev<I> where I: DoubleEndedIterator + RandomAccessIterator {
     #[inline]
     fn indexable(&self) -> usize { self.iter.indexable() }
@@ -1109,12 +1114,12 @@ impl<I> RandomAccessIterator for Rev<I> where I: DoubleEndedIterator + RandomAcc
 
 /// A mutable reference to an iterator
 #[must_use = "iterator adaptors are lazy and do nothing unless consumed"]
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 pub struct ByRef<'a, I:'a> {
     iter: &'a mut I,
 }
 
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl<'a, I> Iterator for ByRef<'a, I> where I: 'a + Iterator {
     type Item = <I as Iterator>::Item;
 
@@ -1124,17 +1129,18 @@ impl<'a, I> Iterator for ByRef<'a, I> where I: 'a + Iterator {
     fn size_hint(&self) -> (usize, Option<usize>) { self.iter.size_hint() }
 }
 
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl<'a, I> DoubleEndedIterator for ByRef<'a, I> where I: 'a + DoubleEndedIterator {
     #[inline]
     fn next_back(&mut self) -> Option<<I as Iterator>::Item> { self.iter.next_back() }
 }
 
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl<'a, I> ExactSizeIterator for ByRef<'a, I> where I: 'a + ExactSizeIterator {}
 
 /// A trait for iterators over elements which can be added together
-#[unstable = "needs to be re-evaluated as part of numerics reform"]
+#[unstable(feature = "core",
+           reason = "needs to be re-evaluated as part of numerics reform")]
 pub trait AdditiveIterator<A> {
     /// Iterates over the entire iterator, summing up all the elements
     ///
@@ -1152,7 +1158,7 @@ pub trait AdditiveIterator<A> {
 
 macro_rules! impl_additive {
     ($A:ty, $init:expr) => {
-        #[unstable = "trait is experimental"]
+        #[unstable(feature = "core", reason = "trait is experimental")]
         impl<T: Iterator<Item=$A>> AdditiveIterator<$A> for T {
             #[inline]
             fn sum(self) -> $A {
@@ -1175,7 +1181,8 @@ impl_additive! { f32,  0.0 }
 impl_additive! { f64,  0.0 }
 
 /// A trait for iterators over elements which can be multiplied together.
-#[unstable = "needs to be re-evaluated as part of numerics reform"]
+#[unstable(feature = "core",
+           reason = "needs to be re-evaluated as part of numerics reform")]
 pub trait MultiplicativeIterator<A> {
     /// Iterates over the entire iterator, multiplying all the elements
     ///
@@ -1196,7 +1203,7 @@ pub trait MultiplicativeIterator<A> {
 
 macro_rules! impl_multiplicative {
     ($A:ty, $init:expr) => {
-        #[unstable = "trait is experimental"]
+        #[unstable(feature = "core", reason = "trait is experimental")]
         impl<T: Iterator<Item=$A>> MultiplicativeIterator<$A> for T {
             #[inline]
             fn product(self) -> $A {
@@ -1220,7 +1227,8 @@ impl_multiplicative! { f64,  1.0 }
 
 /// `MinMaxResult` is an enum returned by `min_max`. See `IteratorOrdExt::min_max` for more detail.
 #[derive(Clone, PartialEq, Show)]
-#[unstable = "unclear whether such a fine-grained result is widely useful"]
+#[unstable(feature = "core",
+           reason = "unclear whether such a fine-grained result is widely useful")]
 pub enum MinMaxResult<T> {
     /// Empty iterator
     NoElements,
@@ -1252,7 +1260,7 @@ impl<T: Clone> MinMaxResult<T> {
     /// let r = MinMax(1, 2);
     /// assert_eq!(r.into_option(), Some((1, 2)));
     /// ```
-    #[unstable = "type is unstable"]
+    #[unstable(feature = "core", reason = "type is unstable")]
     pub fn into_option(self) -> Option<(T,T)> {
         match self {
             NoElements => None,
@@ -1263,14 +1271,14 @@ impl<T: Clone> MinMaxResult<T> {
 }
 
 /// An iterator that clones the elements of an underlying iterator
-#[unstable = "recent addition"]
+#[unstable(feature = "core", reason = "recent addition")]
 #[must_use = "iterator adaptors are lazy and do nothing unless consumed"]
 #[derive(Clone)]
 pub struct Cloned<I> {
     it: I,
 }
 
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl<T, D, I> Iterator for Cloned<I> where
     T: Clone,
     D: Deref<Target=T>,
@@ -1287,7 +1295,7 @@ impl<T, D, I> Iterator for Cloned<I> where
     }
 }
 
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl<T, D, I> DoubleEndedIterator for Cloned<I> where
     T: Clone,
     D: Deref<Target=T>,
@@ -1298,7 +1306,7 @@ impl<T, D, I> DoubleEndedIterator for Cloned<I> where
     }
 }
 
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl<T, D, I> ExactSizeIterator for Cloned<I> where
     T: Clone,
     D: Deref<Target=T>,
@@ -1308,13 +1316,13 @@ impl<T, D, I> ExactSizeIterator for Cloned<I> where
 /// An iterator that repeats endlessly
 #[derive(Clone, Copy)]
 #[must_use = "iterator adaptors are lazy and do nothing unless consumed"]
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 pub struct Cycle<I> {
     orig: I,
     iter: I,
 }
 
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl<I> Iterator for Cycle<I> where I: Clone + Iterator {
     type Item = <I as Iterator>::Item;
 
@@ -1337,7 +1345,7 @@ impl<I> Iterator for Cycle<I> where I: Clone + Iterator {
     }
 }
 
-#[unstable = "trait is experimental"]
+#[unstable(feature = "core", reason = "trait is experimental")]
 impl<I> RandomAccessIterator for Cycle<I> where
     I: Clone + RandomAccessIterator,
 {
@@ -1367,14 +1375,14 @@ impl<I> RandomAccessIterator for Cycle<I> where
 /// An iterator that strings two iterators together
 #[derive(Clone)]
 #[must_use = "iterator adaptors are lazy and do nothing unless consumed"]
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 pub struct Chain<A, B> {
     a: A,
     b: B,
     flag: bool,
 }
 
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl<T, A, B> Iterator for Chain<A, B> where A: Iterator<Item=T>, B: Iterator<Item=T> {
     type Item = T;
 
@@ -1408,7 +1416,7 @@ impl<T, A, B> Iterator for Chain<A, B> where A: Iterator<Item=T>, B: Iterator<It
     }
 }
 
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl<T, A, B> DoubleEndedIterator for Chain<A, B> where
     A: DoubleEndedIterator<Item=T>,
     B: DoubleEndedIterator<Item=T>,
@@ -1422,7 +1430,7 @@ impl<T, A, B> DoubleEndedIterator for Chain<A, B> where
     }
 }
 
-#[unstable = "trait is experimental"]
+#[unstable(feature = "core", reason = "trait is experimental")]
 impl<T, A, B> RandomAccessIterator for Chain<A, B> where
     A: RandomAccessIterator<Item=T>,
     B: RandomAccessIterator<Item=T>,
@@ -1447,13 +1455,13 @@ impl<T, A, B> RandomAccessIterator for Chain<A, B> where
 /// An iterator that iterates two other iterators simultaneously
 #[derive(Clone)]
 #[must_use = "iterator adaptors are lazy and do nothing unless consumed"]
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 pub struct Zip<A, B> {
     a: A,
     b: B
 }
 
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl<T, U, A, B> Iterator for Zip<A, B> where
     A: Iterator<Item = T>,
     B: Iterator<Item = U>,
@@ -1489,7 +1497,7 @@ impl<T, U, A, B> Iterator for Zip<A, B> where
     }
 }
 
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl<T, U, A, B> DoubleEndedIterator for Zip<A, B> where
     A: DoubleEndedIterator + ExactSizeIterator<Item=T>,
     B: DoubleEndedIterator + ExactSizeIterator<Item=U>,
@@ -1514,7 +1522,7 @@ impl<T, U, A, B> DoubleEndedIterator for Zip<A, B> where
     }
 }
 
-#[unstable = "trait is experimental"]
+#[unstable(feature = "core", reason = "trait is experimental")]
 impl<T, U, A, B> RandomAccessIterator for Zip<A, B> where
     A: RandomAccessIterator<Item=T>,
     B: RandomAccessIterator<Item=U>,
@@ -1538,14 +1546,14 @@ impl<T, U, A, B> RandomAccessIterator for Zip<A, B> where
 
 /// An iterator that maps the values of `iter` with `f`
 #[must_use = "iterator adaptors are lazy and do nothing unless consumed"]
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 pub struct Map<A, B, I: Iterator<Item=A>, F: FnMut(A) -> B> {
     iter: I,
     f: F,
 }
 
 // FIXME(#19839) Remove in favor of `#[derive(Clone)]`
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl<A, B, I, F> Clone for Map<A, B, I, F> where
     I: Clone + Iterator<Item=A>,
     F: Clone + FnMut(A) -> B,
@@ -1568,7 +1576,7 @@ impl<A, B, I, F> Map<A, B, I, F> where I: Iterator<Item=A>, F: FnMut(A) -> B {
     }
 }
 
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl<A, B, I, F> Iterator for Map<A, B, I, F> where I: Iterator<Item=A>, F: FnMut(A) -> B {
     type Item = B;
 
@@ -1584,7 +1592,7 @@ impl<A, B, I, F> Iterator for Map<A, B, I, F> where I: Iterator<Item=A>, F: FnMu
     }
 }
 
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl<A, B, I, F> DoubleEndedIterator for Map<A, B, I, F> where
     I: DoubleEndedIterator<Item=A>,
     F: FnMut(A) -> B,
@@ -1596,7 +1604,7 @@ impl<A, B, I, F> DoubleEndedIterator for Map<A, B, I, F> where
     }
 }
 
-#[unstable = "trait is experimental"]
+#[unstable(feature = "core", reason = "trait is experimental")]
 impl<A, B, I, F> RandomAccessIterator for Map<A, B, I, F> where
     I: RandomAccessIterator<Item=A>,
     F: FnMut(A) -> B,
@@ -1615,14 +1623,14 @@ impl<A, B, I, F> RandomAccessIterator for Map<A, B, I, F> where
 
 /// An iterator that filters the elements of `iter` with `predicate`
 #[must_use = "iterator adaptors are lazy and do nothing unless consumed"]
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 pub struct Filter<A, I, P> where I: Iterator<Item=A>, P: FnMut(&A) -> bool {
     iter: I,
     predicate: P,
 }
 
 // FIXME(#19839) Remove in favor of `#[derive(Clone)]`
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl<A, I, P> Clone for Filter<A, I, P> where
     I: Clone + Iterator<Item=A>,
     P: Clone + FnMut(&A) -> bool,
@@ -1635,7 +1643,7 @@ impl<A, I, P> Clone for Filter<A, I, P> where
     }
 }
 
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl<A, I, P> Iterator for Filter<A, I, P> where I: Iterator<Item=A>, P: FnMut(&A) -> bool {
     type Item = A;
 
@@ -1658,7 +1666,7 @@ impl<A, I, P> Iterator for Filter<A, I, P> where I: Iterator<Item=A>, P: FnMut(&
     }
 }
 
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl<A, I, P> DoubleEndedIterator for Filter<A, I, P> where
     I: DoubleEndedIterator<Item=A>,
     P: FnMut(&A) -> bool,
@@ -1676,14 +1684,14 @@ impl<A, I, P> DoubleEndedIterator for Filter<A, I, P> where
 
 /// An iterator that uses `f` to both filter and map elements from `iter`
 #[must_use = "iterator adaptors are lazy and do nothing unless consumed"]
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 pub struct FilterMap<A, B, I, F> where I: Iterator<Item=A>, F: FnMut(A) -> Option<B> {
     iter: I,
     f: F,
 }
 
 // FIXME(#19839) Remove in favor of `#[derive(Clone)]`
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl<A, B, I, F> Clone for FilterMap<A, B, I, F> where
     I: Clone + Iterator<Item=A>,
     F: Clone + FnMut(A) -> Option<B>,
@@ -1696,7 +1704,7 @@ impl<A, B, I, F> Clone for FilterMap<A, B, I, F> where
     }
 }
 
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl<A, B, I, F> Iterator for FilterMap<A, B, I, F> where
     I: Iterator<Item=A>,
     F: FnMut(A) -> Option<B>,
@@ -1721,7 +1729,7 @@ impl<A, B, I, F> Iterator for FilterMap<A, B, I, F> where
     }
 }
 
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl<A, B, I, F> DoubleEndedIterator for FilterMap<A, B, I, F> where
     I: DoubleEndedIterator<Item=A>,
     F: FnMut(A) -> Option<B>,
@@ -1741,13 +1749,13 @@ impl<A, B, I, F> DoubleEndedIterator for FilterMap<A, B, I, F> where
 /// An iterator that yields the current count and the element during iteration
 #[derive(Clone)]
 #[must_use = "iterator adaptors are lazy and do nothing unless consumed"]
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 pub struct Enumerate<I> {
     iter: I,
     count: usize
 }
 
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl<I> Iterator for Enumerate<I> where I: Iterator {
     type Item = (usize, <I as Iterator>::Item);
 
@@ -1769,7 +1777,7 @@ impl<I> Iterator for Enumerate<I> where I: Iterator {
     }
 }
 
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl<I> DoubleEndedIterator for Enumerate<I> where
     I: ExactSizeIterator + DoubleEndedIterator
 {
@@ -1785,7 +1793,7 @@ impl<I> DoubleEndedIterator for Enumerate<I> where
     }
 }
 
-#[unstable = "trait is experimental"]
+#[unstable(feature = "core", reason = "trait is experimental")]
 impl<I> RandomAccessIterator for Enumerate<I> where I: RandomAccessIterator {
     #[inline]
     fn indexable(&self) -> usize {
@@ -1803,14 +1811,14 @@ impl<I> RandomAccessIterator for Enumerate<I> where I: RandomAccessIterator {
 
 /// An iterator with a `peek()` that returns an optional reference to the next element.
 #[must_use = "iterator adaptors are lazy and do nothing unless consumed"]
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 #[derive(Copy)]
 pub struct Peekable<T, I> where I: Iterator<Item=T> {
     iter: I,
     peeked: Option<T>,
 }
 
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl<T, I> Iterator for Peekable<T, I> where I: Iterator<Item=T> {
     type Item = T;
 
@@ -1836,10 +1844,10 @@ impl<T, I> Iterator for Peekable<T, I> where I: Iterator<Item=T> {
     }
 }
 
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl<T, I> ExactSizeIterator for Peekable<T, I> where I: ExactSizeIterator<Item = T> {}
 
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl<T, I> Peekable<T, I> where I: Iterator<Item=T> {
     /// Return a reference to the next element of the iterator with out advancing it,
     /// or None if the iterator is exhausted.
@@ -1863,7 +1871,7 @@ impl<T, I> Peekable<T, I> where I: Iterator<Item=T> {
 
 /// An iterator that rejects elements while `predicate` is true
 #[must_use = "iterator adaptors are lazy and do nothing unless consumed"]
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 pub struct SkipWhile<A, I, P> where I: Iterator<Item=A>, P: FnMut(&A) -> bool {
     iter: I,
     flag: bool,
@@ -1871,7 +1879,7 @@ pub struct SkipWhile<A, I, P> where I: Iterator<Item=A>, P: FnMut(&A) -> bool {
 }
 
 // FIXME(#19839) Remove in favor of `#[derive(Clone)]`
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl<A, I, P> Clone for SkipWhile<A, I, P> where
     I: Clone + Iterator<Item=A>,
     P: Clone + FnMut(&A) -> bool,
@@ -1885,7 +1893,7 @@ impl<A, I, P> Clone for SkipWhile<A, I, P> where
     }
 }
 
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl<A, I, P> Iterator for SkipWhile<A, I, P> where I: Iterator<Item=A>, P: FnMut(&A) -> bool {
     type Item = A;
 
@@ -1909,7 +1917,7 @@ impl<A, I, P> Iterator for SkipWhile<A, I, P> where I: Iterator<Item=A>, P: FnMu
 
 /// An iterator that only accepts elements while `predicate` is true
 #[must_use = "iterator adaptors are lazy and do nothing unless consumed"]
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 pub struct TakeWhile<A, I, P> where I: Iterator<Item=A>, P: FnMut(&A) -> bool {
     iter: I,
     flag: bool,
@@ -1917,7 +1925,7 @@ pub struct TakeWhile<A, I, P> where I: Iterator<Item=A>, P: FnMut(&A) -> bool {
 }
 
 // FIXME(#19839) Remove in favor of `#[derive(Clone)]`
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl<A, I, P> Clone for TakeWhile<A, I, P> where
     I: Clone + Iterator<Item=A>,
     P: Clone + FnMut(&A) -> bool,
@@ -1931,7 +1939,7 @@ impl<A, I, P> Clone for TakeWhile<A, I, P> where
     }
 }
 
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl<A, I, P> Iterator for TakeWhile<A, I, P> where I: Iterator<Item=A>, P: FnMut(&A) -> bool {
     type Item = A;
 
@@ -1964,13 +1972,13 @@ impl<A, I, P> Iterator for TakeWhile<A, I, P> where I: Iterator<Item=A>, P: FnMu
 /// An iterator that skips over `n` elements of `iter`.
 #[derive(Clone)]
 #[must_use = "iterator adaptors are lazy and do nothing unless consumed"]
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 pub struct Skip<I> {
     iter: I,
     n: usize
 }
 
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl<I> Iterator for Skip<I> where I: Iterator {
     type Item = <I as Iterator>::Item;
 
@@ -2014,7 +2022,7 @@ impl<I> Iterator for Skip<I> where I: Iterator {
     }
 }
 
-#[unstable = "trait is experimental"]
+#[unstable(feature = "core", reason = "trait is experimental")]
 impl<I> RandomAccessIterator for Skip<I> where I: RandomAccessIterator{
     #[inline]
     fn indexable(&self) -> usize {
@@ -2031,19 +2039,19 @@ impl<I> RandomAccessIterator for Skip<I> where I: RandomAccessIterator{
     }
 }
 
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl<I> ExactSizeIterator for Skip<I> where I: ExactSizeIterator {}
 
 /// An iterator that only iterates over the first `n` iterations of `iter`.
 #[derive(Clone)]
 #[must_use = "iterator adaptors are lazy and do nothing unless consumed"]
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 pub struct Take<I> {
     iter: I,
     n: usize
 }
 
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl<I> Iterator for Take<I> where I: Iterator{
     type Item = <I as Iterator>::Item;
 
@@ -2072,7 +2080,7 @@ impl<I> Iterator for Take<I> where I: Iterator{
     }
 }
 
-#[unstable = "trait is experimental"]
+#[unstable(feature = "core", reason = "trait is experimental")]
 impl<I> RandomAccessIterator for Take<I> where I: RandomAccessIterator{
     #[inline]
     fn indexable(&self) -> usize {
@@ -2089,13 +2097,13 @@ impl<I> RandomAccessIterator for Take<I> where I: RandomAccessIterator{
     }
 }
 
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl<I> ExactSizeIterator for Take<I> where I: ExactSizeIterator {}
 
 
 /// An iterator to maintain state while iterating another iterator
 #[must_use = "iterator adaptors are lazy and do nothing unless consumed"]
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 pub struct Scan<A, B, I, St, F> where I: Iterator, F: FnMut(&mut St, A) -> Option<B> {
     iter: I,
     f: F,
@@ -2105,7 +2113,7 @@ pub struct Scan<A, B, I, St, F> where I: Iterator, F: FnMut(&mut St, A) -> Optio
 }
 
 // FIXME(#19839) Remove in favor of `#[derive(Clone)]`
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl<A, B, I, St, F> Clone for Scan<A, B, I, St, F> where
     I: Clone + Iterator<Item=A>,
     St: Clone,
@@ -2120,7 +2128,7 @@ impl<A, B, I, St, F> Clone for Scan<A, B, I, St, F> where
     }
 }
 
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl<A, B, I, St, F> Iterator for Scan<A, B, I, St, F> where
     I: Iterator<Item=A>,
     F: FnMut(&mut St, A) -> Option<B>,
@@ -2143,7 +2151,7 @@ impl<A, B, I, St, F> Iterator for Scan<A, B, I, St, F> where
 /// and yields the elements of the produced iterators
 ///
 #[must_use = "iterator adaptors are lazy and do nothing unless consumed"]
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 pub struct FlatMap<A, B, I, U, F> where
     I: Iterator<Item=A>,
     U: Iterator<Item=B>,
@@ -2156,7 +2164,7 @@ pub struct FlatMap<A, B, I, U, F> where
 }
 
 // FIXME(#19839) Remove in favor of `#[derive(Clone)]`
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl<A, B, I, U, F> Clone for FlatMap<A, B, I, U, F> where
     I: Clone + Iterator<Item=A>,
     U: Clone + Iterator<Item=B>,
@@ -2172,7 +2180,7 @@ impl<A, B, I, U, F> Clone for FlatMap<A, B, I, U, F> where
     }
 }
 
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl<A, B, I, U, F> Iterator for FlatMap<A, B, I, U, F> where
     I: Iterator<Item=A>,
     U: Iterator<Item=B>,
@@ -2207,7 +2215,7 @@ impl<A, B, I, U, F> Iterator for FlatMap<A, B, I, U, F> where
     }
 }
 
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl<A, B, I, U, F> DoubleEndedIterator for FlatMap<A, B, I, U, F> where
     I: DoubleEndedIterator<Item=A>,
     U: DoubleEndedIterator<Item=B>,
@@ -2234,13 +2242,13 @@ impl<A, B, I, U, F> DoubleEndedIterator for FlatMap<A, B, I, U, F> where
 /// yields `None` once.
 #[derive(Clone)]
 #[must_use = "iterator adaptors are lazy and do nothing unless consumed"]
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 pub struct Fuse<I> {
     iter: I,
     done: bool
 }
 
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl<I> Iterator for Fuse<I> where I: Iterator {
     type Item = <I as Iterator>::Item;
 
@@ -2269,7 +2277,7 @@ impl<I> Iterator for Fuse<I> where I: Iterator {
     }
 }
 
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl<I> DoubleEndedIterator for Fuse<I> where I: DoubleEndedIterator {
     #[inline]
     fn next_back(&mut self) -> Option<<I as Iterator>::Item> {
@@ -2288,7 +2296,7 @@ impl<I> DoubleEndedIterator for Fuse<I> where I: DoubleEndedIterator {
 }
 
 // Allow RandomAccessIterators to be fused without affecting random-access behavior
-#[unstable = "trait is experimental"]
+#[unstable(feature = "core", reason = "trait is experimental")]
 impl<I> RandomAccessIterator for Fuse<I> where I: RandomAccessIterator {
     #[inline]
     fn indexable(&self) -> usize {
@@ -2301,14 +2309,14 @@ impl<I> RandomAccessIterator for Fuse<I> where I: RandomAccessIterator {
     }
 }
 
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl<I> ExactSizeIterator for Fuse<I> where I: ExactSizeIterator {}
 
 impl<I> Fuse<I> {
     /// Resets the fuse such that the next call to .next() or .next_back() will
     /// call the underlying iterator again even if it previously returned None.
     #[inline]
-    #[unstable = "seems marginal"]
+    #[unstable(feature = "core", reason = "seems marginal")]
     pub fn reset_fuse(&mut self) {
         self.done = false
     }
@@ -2317,14 +2325,14 @@ impl<I> Fuse<I> {
 /// An iterator that calls a function with a reference to each
 /// element before yielding it.
 #[must_use = "iterator adaptors are lazy and do nothing unless consumed"]
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 pub struct Inspect<A, I, F> where I: Iterator<Item=A>, F: FnMut(&A) {
     iter: I,
     f: F,
 }
 
 // FIXME(#19839) Remove in favor of `#[derive(Clone)]`
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl<A, I, F> Clone for Inspect<A, I, F> where
     I: Clone + Iterator<Item=A>,
     F: Clone + FnMut(&A),
@@ -2349,7 +2357,7 @@ impl<A, I, F> Inspect<A, I, F> where I: Iterator<Item=A>, F: FnMut(&A) {
     }
 }
 
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl<A, I, F> Iterator for Inspect<A, I, F> where I: Iterator<Item=A>, F: FnMut(&A) {
     type Item = A;
 
@@ -2365,7 +2373,7 @@ impl<A, I, F> Iterator for Inspect<A, I, F> where I: Iterator<Item=A>, F: FnMut(
     }
 }
 
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl<A, I, F> DoubleEndedIterator for Inspect<A, I, F> where
     I: DoubleEndedIterator<Item=A>,
     F: FnMut(&A),
@@ -2377,7 +2385,7 @@ impl<A, I, F> DoubleEndedIterator for Inspect<A, I, F> where
     }
 }
 
-#[unstable = "trait is experimental"]
+#[unstable(feature = "core", reason = "trait is experimental")]
 impl<A, I, F> RandomAccessIterator for Inspect<A, I, F> where
     I: RandomAccessIterator<Item=A>,
     F: FnMut(&A),
@@ -2426,7 +2434,7 @@ impl<A, I, F> RandomAccessIterator for Inspect<A, I, F> where
 ///     println!("{}", i);
 /// }
 /// ```
-#[unstable]
+#[unstable(feature = "core")]
 pub struct Unfold<A, St, F> where F: FnMut(&mut St) -> Option<A> {
     f: F,
     /// Internal state that will be passed to the closure on the next iteration
@@ -2434,7 +2442,7 @@ pub struct Unfold<A, St, F> where F: FnMut(&mut St) -> Option<A> {
 }
 
 // FIXME(#19839) Remove in favor of `#[derive(Clone)]`
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl<A, St, F> Clone for Unfold<A, St, F> where
     F: Clone + FnMut(&mut St) -> Option<A>,
     St: Clone,
@@ -2447,7 +2455,7 @@ impl<A, St, F> Clone for Unfold<A, St, F> where
     }
 }
 
-#[unstable]
+#[unstable(feature = "core")]
 impl<A, St, F> Unfold<A, St, F> where F: FnMut(&mut St) -> Option<A> {
     /// Creates a new iterator with the specified closure as the "iterator
     /// function" and an initial state to eventually pass to the closure
@@ -2460,7 +2468,7 @@ impl<A, St, F> Unfold<A, St, F> where F: FnMut(&mut St) -> Option<A> {
     }
 }
 
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl<A, St, F> Iterator for Unfold<A, St, F> where F: FnMut(&mut St) -> Option<A> {
     type Item = A;
 
@@ -2479,7 +2487,8 @@ impl<A, St, F> Iterator for Unfold<A, St, F> where F: FnMut(&mut St) -> Option<A
 /// An infinite iterator starting at `start` and advancing by `step` with each
 /// iteration
 #[derive(Clone, Copy)]
-#[unstable = "may be renamed or replaced by range notation adapaters"]
+#[unstable(feature = "core",
+           reason = "may be renamed or replaced by range notation adapaters")]
 pub struct Counter<A> {
     /// The current state the counter is at (next value to be yielded)
     state: A,
@@ -2489,12 +2498,13 @@ pub struct Counter<A> {
 
 /// Creates a new counter with the specified start/step
 #[inline]
-#[unstable = "may be renamed or replaced by range notation adapaters"]
+#[unstable(feature = "core",
+           reason = "may be renamed or replaced by range notation adapaters")]
 pub fn count<A>(start: A, step: A) -> Counter<A> {
     Counter{state: start, step: step}
 }
 
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl<A: Add<Output=A> + Clone> Iterator for Counter<A> {
     type Item = A;
 
@@ -2513,7 +2523,8 @@ impl<A: Add<Output=A> + Clone> Iterator for Counter<A> {
 
 /// An iterator over the range [start, stop)
 #[derive(Clone, Copy)]
-#[unstable = "will be replaced by range notation"]
+#[unstable(feature = "core",
+           reason = "will be replaced by range notation")]
 pub struct Range<A> {
     state: A,
     stop: A,
@@ -2534,7 +2545,8 @@ pub struct Range<A> {
 /// }
 /// ```
 #[inline]
-#[unstable = "will be replaced by range notation"]
+#[unstable(feature = "core",
+           reason = "will be replaced by range notation")]
 pub fn range<A: Int>(start: A, stop: A) -> Range<A> {
     Range {
         state: start,
@@ -2544,7 +2556,8 @@ pub fn range<A: Int>(start: A, stop: A) -> Range<A> {
 }
 
 // FIXME: #10414: Unfortunate type bound
-#[unstable = "will be replaced by range notation"]
+#[unstable(feature = "core",
+           reason = "will be replaced by range notation")]
 impl<A: Int + ToPrimitive> Iterator for Range<A> {
     type Item = A;
 
@@ -2594,7 +2607,8 @@ impl<A: Int + ToPrimitive> Iterator for Range<A> {
 
 /// `Int` is required to ensure the range will be the same regardless of
 /// the direction it is consumed.
-#[unstable = "will be replaced by range notation"]
+#[unstable(feature = "core",
+           reason = "will be replaced by range notation")]
 impl<A: Int + ToPrimitive> DoubleEndedIterator for Range<A> {
     #[inline]
     fn next_back(&mut self) -> Option<A> {
@@ -2609,7 +2623,8 @@ impl<A: Int + ToPrimitive> DoubleEndedIterator for Range<A> {
 
 /// An iterator over the range [start, stop]
 #[derive(Clone)]
-#[unstable = "likely to be replaced by range notation and adapters"]
+#[unstable(feature = "core",
+           reason = "likely to be replaced by range notation and adapters")]
 pub struct RangeInclusive<A> {
     range: Range<A>,
     done: bool,
@@ -2617,7 +2632,8 @@ pub struct RangeInclusive<A> {
 
 /// Return an iterator over the range [start, stop]
 #[inline]
-#[unstable = "likely to be replaced by range notation and adapters"]
+#[unstable(feature = "core",
+           reason = "likely to be replaced by range notation and adapters")]
 pub fn range_inclusive<A: Int>(start: A, stop: A) -> RangeInclusive<A> {
     RangeInclusive {
         range: range(start, stop),
@@ -2625,7 +2641,8 @@ pub fn range_inclusive<A: Int>(start: A, stop: A) -> RangeInclusive<A> {
     }
 }
 
-#[unstable = "likely to be replaced by range notation and adapters"]
+#[unstable(feature = "core",
+           reason = "likely to be replaced by range notation and adapters")]
 impl<A: Int + ToPrimitive> Iterator for RangeInclusive<A> {
     type Item = A;
 
@@ -2660,7 +2677,8 @@ impl<A: Int + ToPrimitive> Iterator for RangeInclusive<A> {
     }
 }
 
-#[unstable = "likely to be replaced by range notation and adapters"]
+#[unstable(feature = "core",
+           reason = "likely to be replaced by range notation and adapters")]
 impl<A: Int + ToPrimitive> DoubleEndedIterator for RangeInclusive<A> {
     #[inline]
     fn next_back(&mut self) -> Option<A> {
@@ -2679,7 +2697,8 @@ impl<A: Int + ToPrimitive> DoubleEndedIterator for RangeInclusive<A> {
 
 /// An iterator over the range [start, stop) by `step`. It handles overflow by stopping.
 #[derive(Clone)]
-#[unstable = "likely to be replaced by range notation and adapters"]
+#[unstable(feature = "core",
+           reason = "likely to be replaced by range notation and adapters")]
 pub struct RangeStep<A> {
     state: A,
     stop: A,
@@ -2689,13 +2708,15 @@ pub struct RangeStep<A> {
 
 /// Return an iterator over the range [start, stop) by `step`. It handles overflow by stopping.
 #[inline]
-#[unstable = "likely to be replaced by range notation and adapters"]
+#[unstable(feature = "core",
+           reason = "likely to be replaced by range notation and adapters")]
 pub fn range_step<A: Int>(start: A, stop: A, step: A) -> RangeStep<A> {
     let rev = step < Int::zero();
     RangeStep{state: start, stop: stop, step: step, rev: rev}
 }
 
-#[unstable = "likely to be replaced by range notation and adapters"]
+#[unstable(feature = "core",
+           reason = "likely to be replaced by range notation and adapters")]
 impl<A: Int> Iterator for RangeStep<A> {
     type Item = A;
 
@@ -2716,7 +2737,8 @@ impl<A: Int> Iterator for RangeStep<A> {
 
 /// An iterator over the range [start, stop] by `step`. It handles overflow by stopping.
 #[derive(Clone)]
-#[unstable = "likely to be replaced by range notation and adapters"]
+#[unstable(feature = "core",
+           reason = "likely to be replaced by range notation and adapters")]
 pub struct RangeStepInclusive<A> {
     state: A,
     stop: A,
@@ -2727,7 +2749,8 @@ pub struct RangeStepInclusive<A> {
 
 /// Return an iterator over the range [start, stop] by `step`. It handles overflow by stopping.
 #[inline]
-#[unstable = "likely to be replaced by range notation and adapters"]
+#[unstable(feature = "core",
+           reason = "likely to be replaced by range notation and adapters")]
 pub fn range_step_inclusive<A: Int>(start: A, stop: A, step: A) -> RangeStepInclusive<A> {
     let rev = step < Int::zero();
     RangeStepInclusive {
@@ -2739,7 +2762,8 @@ pub fn range_step_inclusive<A: Int>(start: A, stop: A, step: A) -> RangeStepIncl
     }
 }
 
-#[unstable = "likely to be replaced by range notation and adapters"]
+#[unstable(feature = "core",
+           reason = "likely to be replaced by range notation and adapters")]
 impl<A: Int> Iterator for RangeStepInclusive<A> {
     type Item = A;
 
@@ -2761,7 +2785,7 @@ impl<A: Int> Iterator for RangeStepInclusive<A> {
 
 macro_rules! range_impl {
     ($($t:ty)*) => ($(
-        #[stable]
+        #[stable(feature = "rust1", since = "1.0.0")]
         impl Iterator for ::ops::Range<$t> {
             type Item = $t;
 
@@ -2784,14 +2808,14 @@ macro_rules! range_impl {
             }
         }
 
-        #[stable]
+        #[stable(feature = "rust1", since = "1.0.0")]
         impl ExactSizeIterator for ::ops::Range<$t> {}
     )*)
 }
 
 macro_rules! range_impl_no_hint {
     ($($t:ty)*) => ($(
-        #[stable]
+        #[stable(feature = "rust1", since = "1.0.0")]
         impl Iterator for ::ops::Range<$t> {
             type Item = $t;
 
@@ -2811,7 +2835,7 @@ macro_rules! range_impl_no_hint {
 
 macro_rules! range_other_impls {
     ($($t:ty)*) => ($(
-        #[stable]
+        #[stable(feature = "rust1", since = "1.0.0")]
         impl DoubleEndedIterator for ::ops::Range<$t> {
             #[inline]
             fn next_back(&mut self) -> Option<$t> {
@@ -2824,7 +2848,7 @@ macro_rules! range_other_impls {
             }
         }
 
-        #[stable]
+        #[stable(feature = "rust1", since = "1.0.0")]
         impl Iterator for ::ops::RangeFrom<$t> {
             type Item = $t;
 
@@ -2849,12 +2873,12 @@ range_other_impls!(usize u8 u16 u32 u64 isize i8 i16 i32 i64);
 
 /// An iterator that repeats an element endlessly
 #[derive(Clone)]
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 pub struct Repeat<A> {
     element: A
 }
 
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl<A: Clone> Iterator for Repeat<A> {
     type Item = A;
 
@@ -2864,13 +2888,13 @@ impl<A: Clone> Iterator for Repeat<A> {
     fn size_hint(&self) -> (usize, Option<usize>) { (usize::MAX, None) }
 }
 
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl<A: Clone> DoubleEndedIterator for Repeat<A> {
     #[inline]
     fn next_back(&mut self) -> Option<A> { self.idx(0) }
 }
 
-#[unstable = "trait is experimental"]
+#[unstable(feature = "core", reason = "trait is experimental")]
 impl<A: Clone> RandomAccessIterator for Repeat<A> {
     #[inline]
     fn indexable(&self) -> usize { usize::MAX }
@@ -2882,12 +2906,12 @@ type IterateState<T, F> = (F, Option<T>, bool);
 
 /// An iterator that repeatedly applies a given function, starting
 /// from a given seed value.
-#[unstable]
+#[unstable(feature = "core")]
 pub type Iterate<T, F> = Unfold<T, IterateState<T, F>, fn(&mut IterateState<T, F>) -> Option<T>>;
 
 /// Create a new iterator that produces an infinite sequence of
 /// repeated applications of the given function `f`.
-#[unstable]
+#[unstable(feature = "core")]
 pub fn iterate<T, F>(seed: T, f: F) -> Iterate<T, F> where
     T: Clone,
     F: FnMut(T) -> T,
@@ -2918,7 +2942,7 @@ pub fn iterate<T, F>(seed: T, f: F) -> Iterate<T, F> where
 
 /// Create a new iterator that endlessly repeats the element `elt`.
 #[inline]
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 pub fn repeat<T: Clone>(elt: T) -> Repeat<T> {
     Repeat{element: elt}
 }
@@ -2930,7 +2954,7 @@ pub fn repeat<T: Clone>(elt: T) -> Repeat<T> {
 ///
 /// If two sequences are equal up until the point where one ends,
 /// the shorter sequence compares less.
-#[unstable = "needs review and revision"]
+#[unstable(feature = "core", reason = "needs review and revision")]
 pub mod order {
     use cmp;
     use cmp::{Eq, Ord, PartialOrd, PartialEq};
diff --git a/src/libcore/lib.rs b/src/libcore/lib.rs
index 1e271f972b1..d4ca5e3f8dc 100644
--- a/src/libcore/lib.rs
+++ b/src/libcore/lib.rs
@@ -48,7 +48,8 @@
 // separate crate, libcoretest, to avoid bizarre issues.
 
 #![crate_name = "core"]
-#![unstable]
+#![unstable(feature = "core")]
+#![feature(staged_api)]
 #![staged_api]
 #![crate_type = "rlib"]
 #![doc(html_logo_url = "http://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
diff --git a/src/libcore/macros.rs b/src/libcore/macros.rs
index d44eaae820f..943365d8454 100644
--- a/src/libcore/macros.rs
+++ b/src/libcore/macros.rs
@@ -52,7 +52,7 @@ macro_rules! panic {
 /// assert!(a + b == 30, "a = {}, b = {}", a, b);
 /// ```
 #[macro_export]
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 macro_rules! assert {
     ($cond:expr) => (
         if !$cond {
@@ -79,7 +79,7 @@ macro_rules! assert {
 /// assert_eq!(a, b);
 /// ```
 #[macro_export]
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 macro_rules! assert_eq {
     ($left:expr , $right:expr) => ({
         match (&($left), &($right)) {
@@ -123,7 +123,7 @@ macro_rules! assert_eq {
 /// debug_assert!(a + b == 30, "a = {}, b = {}", a, b);
 /// ```
 #[macro_export]
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 macro_rules! debug_assert {
     ($($arg:tt)*) => (if cfg!(not(ndebug)) { assert!($($arg)*); })
 }
@@ -185,7 +185,7 @@ macro_rules! write {
 /// Equivalent to the `write!` macro, except that a newline is appended after
 /// the message is written.
 #[macro_export]
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 macro_rules! writeln {
     ($dst:expr, $fmt:expr) => (
         write!($dst, concat!($fmt, "\n"))
@@ -235,7 +235,8 @@ macro_rules! writeln {
 /// }
 /// ```
 #[macro_export]
-#[unstable = "relationship with panic is unclear"]
+#[unstable(feature = "core",
+           reason = "relationship with panic is unclear")]
 macro_rules! unreachable {
     () => ({
         panic!("internal error: entered unreachable code")
@@ -251,7 +252,8 @@ macro_rules! unreachable {
 /// A standardised placeholder for marking unfinished code. It panics with the
 /// message `"not yet implemented"` when executed.
 #[macro_export]
-#[unstable = "relationship with panic is unclear"]
+#[unstable(feature = "core",
+           reason = "relationship with panic is unclear")]
 macro_rules! unimplemented {
     () => (panic!("not yet implemented"))
 }
diff --git a/src/libcore/marker.rs b/src/libcore/marker.rs
index 688f0484401..1fc3e34af5e 100644
--- a/src/libcore/marker.rs
+++ b/src/libcore/marker.rs
@@ -23,12 +23,13 @@
 //! implemented using unsafe code. In that case, you may want to embed
 //! some of the marker types below into your type.
 
-#![stable]
+#![stable(feature = "rust1", since = "1.0.0")]
 
 use clone::Clone;
 
 /// Types able to be transferred across thread boundaries.
-#[unstable = "will be overhauled with new lifetime rules; see RFC 458"]
+#[unstable(feature = "core",
+           reason = "will be overhauled with new lifetime rules; see RFC 458")]
 #[lang="send"]
 #[rustc_on_unimplemented = "`{Self}` cannot be sent between threads safely"]
 pub unsafe trait Send: 'static {
@@ -36,7 +37,7 @@ pub unsafe trait Send: 'static {
 }
 
 /// Types with a constant size known at compile-time.
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 #[lang="sized"]
 #[rustc_on_unimplemented = "`{Self}` does not have a constant size known at compile-time"]
 pub trait Sized {
@@ -142,7 +143,7 @@ pub trait Sized {
 /// to consider though: if you think your type may _not_ be able to implement `Copy` in the future,
 /// then it might be prudent to not implement `Copy`. This is because removing `Copy` is a breaking
 /// change: that second example would fail to compile if we made `Foo` non-`Copy`.
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 #[lang="copy"]
 pub trait Copy {
     // Empty.
@@ -193,7 +194,8 @@ pub trait Copy {
 /// around the value(s) which can be mutated when behind a `&`
 /// reference; not doing this is undefined behaviour (for example,
 /// `transmute`-ing from `&T` to `&mut T` is illegal).
-#[unstable = "will be overhauled with new lifetime rules; see RFC 458"]
+#[unstable(feature = "core",
+           reason = "will be overhauled with new lifetime rules; see RFC 458")]
 #[lang="sync"]
 #[rustc_on_unimplemented = "`{Self}` cannot be shared between threads safely"]
 pub unsafe trait Sync {
@@ -238,7 +240,8 @@ pub unsafe trait Sync {
 /// `S<T>` is a subtype of `S<U>` if `T` is a subtype of `U`
 /// (for example, `S<&'static int>` is a subtype of `S<&'a int>`
 /// for some lifetime `'a`, but not the other way around).
-#[unstable = "likely to change with new variance strategy"]
+#[unstable(feature = "core",
+           reason = "likely to change with new variance strategy")]
 #[lang="covariant_type"]
 #[derive(PartialEq, Eq, PartialOrd, Ord)]
 pub struct CovariantType<T: ?Sized>;
@@ -287,7 +290,8 @@ impl<T: ?Sized> Clone for CovariantType<T> {
 /// subtype of `S<U>` if `U` is a subtype of `T`; given that the
 /// function requires arguments of type `T`, it must also accept
 /// arguments of type `U`, hence such a conversion is safe.
-#[unstable = "likely to change with new variance strategy"]
+#[unstable(feature = "core",
+           reason = "likely to change with new variance strategy")]
 #[lang="contravariant_type"]
 #[derive(PartialEq, Eq, PartialOrd, Ord)]
 pub struct ContravariantType<T: ?Sized>;
@@ -317,14 +321,17 @@ impl<T: ?Sized> Clone for ContravariantType<T> {
 /// The type system would infer that `value` is only read here and
 /// never written, but in fact `Cell` uses unsafe code to achieve
 /// interior mutability.
-#[unstable = "likely to change with new variance strategy"]
+#[unstable(feature = "core",
+           reason = "likely to change with new variance strategy")]
 #[lang="invariant_type"]
 #[derive(PartialEq, Eq, PartialOrd, Ord)]
 pub struct InvariantType<T: ?Sized>;
 
-#[unstable = "likely to change with new variance strategy"]
+#[unstable(feature = "core",
+           reason = "likely to change with new variance strategy")]
 impl<T: ?Sized> Copy for InvariantType<T> {}
-#[unstable = "likely to change with new variance strategy"]
+#[unstable(feature = "core",
+           reason = "likely to change with new variance strategy")]
 impl<T: ?Sized> Clone for InvariantType<T> {
     fn clone(&self) -> InvariantType<T> { *self }
 }
@@ -345,7 +352,8 @@ impl<T: ?Sized> Clone for InvariantType<T> {
 ///
 /// For more information about variance, refer to this Wikipedia
 /// article <http://en.wikipedia.org/wiki/Variance_%28computer_science%29>.
-#[unstable = "likely to change with new variance strategy"]
+#[unstable(feature = "core",
+           reason = "likely to change with new variance strategy")]
 #[lang="covariant_lifetime"]
 #[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
 pub struct CovariantLifetime<'a>;
@@ -362,7 +370,8 @@ pub struct CovariantLifetime<'a>;
 ///
 /// For more information about variance, refer to this Wikipedia
 /// article <http://en.wikipedia.org/wiki/Variance_%28computer_science%29>.
-#[unstable = "likely to change with new variance strategy"]
+#[unstable(feature = "core",
+           reason = "likely to change with new variance strategy")]
 #[lang="contravariant_lifetime"]
 #[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
 pub struct ContravariantLifetime<'a>;
@@ -374,7 +383,8 @@ pub struct ContravariantLifetime<'a>;
 /// pointer that is actually a pointer into memory with lifetime `'a`,
 /// and this pointer is itself stored in an inherently mutable
 /// location (such as a `Cell`).
-#[unstable = "likely to change with new variance strategy"]
+#[unstable(feature = "core",
+           reason = "likely to change with new variance strategy")]
 #[lang="invariant_lifetime"]
 #[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
 pub struct InvariantLifetime<'a>;
@@ -382,7 +392,8 @@ pub struct InvariantLifetime<'a>;
 /// A type which is considered "not POD", meaning that it is not
 /// implicitly copyable. This is typically embedded in other types to
 /// ensure that they are never copied, even if they lack a destructor.
-#[unstable = "likely to change with new variance strategy"]
+#[unstable(feature = "core",
+           reason = "likely to change with new variance strategy")]
 #[lang="no_copy_bound"]
 #[derive(Clone, PartialEq, Eq, PartialOrd, Ord)]
 #[allow(missing_copy_implementations)]
@@ -390,7 +401,8 @@ pub struct NoCopy;
 
 /// A type which is considered managed by the GC. This is typically
 /// embedded in other types.
-#[unstable = "likely to change with new variance strategy"]
+#[unstable(feature = "core",
+           reason = "likely to change with new variance strategy")]
 #[lang="managed_bound"]
 #[derive(Clone, PartialEq, Eq, PartialOrd, Ord)]
 #[allow(missing_copy_implementations)]
diff --git a/src/libcore/mem.rs b/src/libcore/mem.rs
index 608a78325b3..0d26c8e7914 100644
--- a/src/libcore/mem.rs
+++ b/src/libcore/mem.rs
@@ -13,13 +13,13 @@
 //! This module contains functions for querying the size and alignment of
 //! types, initializing and manipulating memory.
 
-#![stable]
+#![stable(feature = "rust1", since = "1.0.0")]
 
 use marker::Sized;
 use intrinsics;
 use ptr;
 
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 pub use intrinsics::transmute;
 
 /// Moves a thing into the void.
@@ -29,7 +29,7 @@ pub use intrinsics::transmute;
 ///
 /// This function is the unsafe version of the `drop` function because it does
 /// not run any destructors.
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 pub use intrinsics::forget;
 
 /// Returns the size of a type in bytes.
@@ -42,7 +42,7 @@ pub use intrinsics::forget;
 /// assert_eq!(4, mem::size_of::<i32>());
 /// ```
 #[inline]
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 pub fn size_of<T>() -> uint {
     unsafe { intrinsics::size_of::<T>() }
 }
@@ -57,7 +57,7 @@ pub fn size_of<T>() -> uint {
 /// assert_eq!(4, mem::size_of_val(&5i32));
 /// ```
 #[inline]
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 pub fn size_of_val<T>(_val: &T) -> uint {
     size_of::<T>()
 }
@@ -74,7 +74,7 @@ pub fn size_of_val<T>(_val: &T) -> uint {
 /// assert_eq!(4, mem::min_align_of::<i32>());
 /// ```
 #[inline]
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 pub fn min_align_of<T>() -> uint {
     unsafe { intrinsics::min_align_of::<T>() }
 }
@@ -89,7 +89,7 @@ pub fn min_align_of<T>() -> uint {
 /// assert_eq!(4, mem::min_align_of_val(&5i32));
 /// ```
 #[inline]
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 pub fn min_align_of_val<T>(_val: &T) -> uint {
     min_align_of::<T>()
 }
@@ -107,7 +107,7 @@ pub fn min_align_of_val<T>(_val: &T) -> uint {
 /// assert_eq!(4, mem::align_of::<i32>());
 /// ```
 #[inline]
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 pub fn align_of<T>() -> uint {
     // We use the preferred alignment as the default alignment for a type. This
     // appears to be what clang migrated towards as well:
@@ -129,7 +129,7 @@ pub fn align_of<T>() -> uint {
 /// assert_eq!(4, mem::align_of_val(&5i32));
 /// ```
 #[inline]
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 pub fn align_of_val<T>(_val: &T) -> uint {
     align_of::<T>()
 }
@@ -153,7 +153,7 @@ pub fn align_of_val<T>(_val: &T) -> uint {
 /// let x: int = unsafe { mem::zeroed() };
 /// ```
 #[inline]
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 pub unsafe fn zeroed<T>() -> T {
     intrinsics::init()
 }
@@ -174,7 +174,7 @@ pub unsafe fn zeroed<T>() -> T {
 /// let x: int = unsafe { mem::uninitialized() };
 /// ```
 #[inline]
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 pub unsafe fn uninitialized<T>() -> T {
     intrinsics::uninit()
 }
@@ -196,7 +196,7 @@ pub unsafe fn uninitialized<T>() -> T {
 /// assert_eq!(5, *y);
 /// ```
 #[inline]
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 pub fn swap<T>(x: &mut T, y: &mut T) {
     unsafe {
         // Give ourselves some scratch space to work with
@@ -261,7 +261,7 @@ pub fn swap<T>(x: &mut T, y: &mut T) {
 /// }
 /// ```
 #[inline]
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 pub fn replace<T>(dest: &mut T, mut src: T) -> T {
     swap(dest, &mut src);
     src
@@ -288,7 +288,7 @@ pub fn replace<T>(dest: &mut T, mut src: T) -> T {
 /// println!("{}", *borrow);
 /// ```
 #[inline]
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 pub fn drop<T>(_x: T) { }
 
 /// Interprets `src` as `&U`, and then reads `src` without moving the contained value.
@@ -311,15 +311,16 @@ pub fn drop<T>(_x: T) { }
 /// assert_eq!(1, one);
 /// ```
 #[inline]
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 pub unsafe fn transmute_copy<T, U>(src: &T) -> U {
     ptr::read(src as *const T as *const U)
 }
 
 /// Transforms lifetime of the second pointer to match the first.
 #[inline]
-#[unstable = "this function may be removed in the future due to its \
-              questionable utility"]
+#[unstable(feature = "core",
+           reason = "this function may be removed in the future due to its \
+                     questionable utility")]
 pub unsafe fn copy_lifetime<'a, S: ?Sized, T: ?Sized + 'a>(_ptr: &'a S,
                                                         ptr: &T) -> &'a T {
     transmute(ptr)
@@ -327,8 +328,9 @@ pub unsafe fn copy_lifetime<'a, S: ?Sized, T: ?Sized + 'a>(_ptr: &'a S,
 
 /// Transforms lifetime of the second mutable pointer to match the first.
 #[inline]
-#[unstable = "this function may be removed in the future due to its \
-              questionable utility"]
+#[unstable(feature = "core",
+           reason = "this function may be removed in the future due to its \
+                     questionable utility")]
 pub unsafe fn copy_mut_lifetime<'a, S: ?Sized, T: ?Sized + 'a>(_ptr: &'a mut S,
                                                             ptr: &mut T)
                                                             -> &'a mut T {
diff --git a/src/libcore/nonzero.rs b/src/libcore/nonzero.rs
index 1231e1ab894..495c7c2bc2e 100644
--- a/src/libcore/nonzero.rs
+++ b/src/libcore/nonzero.rs
@@ -32,7 +32,7 @@ unsafe impl Zeroable for u64 {}
 /// NULL or 0 that might allow certain optimizations.
 #[lang="non_zero"]
 #[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Show, Hash)]
-#[unstable]
+#[unstable(feature = "core")]
 pub struct NonZero<T: Zeroable>(T);
 
 impl<T: Zeroable> NonZero<T> {
@@ -52,4 +52,4 @@ impl<T: Zeroable> Deref for NonZero<T> {
         let NonZero(ref inner) = *self;
         inner
     }
-}
\ No newline at end of file
+}
diff --git a/src/libcore/num/f32.rs b/src/libcore/num/f32.rs
index 2186101bc2f..83d070feb8a 100644
--- a/src/libcore/num/f32.rs
+++ b/src/libcore/num/f32.rs
@@ -14,7 +14,7 @@
 // FIXME: MIN_VALUE and MAX_VALUE literals are parsed as -inf and inf #14353
 #![allow(overflowing_literals)]
 
-#![stable]
+#![stable(feature = "rust1", since = "1.0.0")]
 
 use intrinsics;
 use mem;
@@ -22,46 +22,47 @@ use num::Float;
 use num::FpCategory as Fp;
 use option::Option;
 
-#[unstable = "pending integer conventions"]
+#[unstable(feature = "core", reason = "pending integer conventions")]
 pub const RADIX: uint = 2;
 
-#[unstable = "pending integer conventions"]
+#[unstable(feature = "core", reason = "pending integer conventions")]
 pub const MANTISSA_DIGITS: uint = 24;
-#[unstable = "pending integer conventions"]
+#[unstable(feature = "core", reason = "pending integer conventions")]
 pub const DIGITS: uint = 6;
 
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 pub const EPSILON: f32 = 1.19209290e-07_f32;
 
 /// Smallest finite f32 value
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 pub const MIN_VALUE: f32 = -3.40282347e+38_f32;
 /// Smallest positive, normalized f32 value
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 pub const MIN_POS_VALUE: f32 = 1.17549435e-38_f32;
 /// Largest finite f32 value
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 pub const MAX_VALUE: f32 = 3.40282347e+38_f32;
 
-#[unstable = "pending integer conventions"]
+#[unstable(feature = "core", reason = "pending integer conventions")]
 pub const MIN_EXP: int = -125;
-#[unstable = "pending integer conventions"]
+#[unstable(feature = "core", reason = "pending integer conventions")]
 pub const MAX_EXP: int = 128;
 
-#[unstable = "pending integer conventions"]
+#[unstable(feature = "core", reason = "pending integer conventions")]
 pub const MIN_10_EXP: int = -37;
-#[unstable = "pending integer conventions"]
+#[unstable(feature = "core", reason = "pending integer conventions")]
 pub const MAX_10_EXP: int = 38;
 
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 pub const NAN: f32 = 0.0_f32/0.0_f32;
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 pub const INFINITY: f32 = 1.0_f32/0.0_f32;
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 pub const NEG_INFINITY: f32 = -1.0_f32/0.0_f32;
 
 /// Various useful constants.
-#[unstable = "naming scheme needs to be revisited"]
+#[unstable(feature = "core",
+           reason = "naming scheme needs to be revisited")]
 pub mod consts {
     // FIXME: replace with mathematical constants from cmath.
 
@@ -117,7 +118,7 @@ pub mod consts {
     pub const LN_10: f32 = 2.30258509299404568401799145468436421_f32;
 }
 
-#[unstable = "trait is unstable"]
+#[unstable(feature = "core", reason = "trait is unstable")]
 impl Float for f32 {
     #[inline]
     fn nan() -> f32 { NAN }
@@ -177,43 +178,53 @@ impl Float for f32 {
     }
 
     #[inline]
-    #[deprecated]
+    #[unstable(feature = "core")]
+    #[deprecated(since = "1.0.0")]
     fn mantissa_digits(_: Option<f32>) -> uint { MANTISSA_DIGITS }
 
     #[inline]
-    #[deprecated]
+    #[unstable(feature = "core")]
+    #[deprecated(since = "1.0.0")]
     fn digits(_: Option<f32>) -> uint { DIGITS }
 
     #[inline]
-    #[deprecated]
+    #[unstable(feature = "core")]
+    #[deprecated(since = "1.0.0")]
     fn epsilon() -> f32 { EPSILON }
 
     #[inline]
-    #[deprecated]
+    #[unstable(feature = "core")]
+    #[deprecated(since = "1.0.0")]
     fn min_exp(_: Option<f32>) -> int { MIN_EXP }
 
     #[inline]
-    #[deprecated]
+    #[unstable(feature = "core")]
+    #[deprecated(since = "1.0.0")]
     fn max_exp(_: Option<f32>) -> int { MAX_EXP }
 
     #[inline]
-    #[deprecated]
+    #[unstable(feature = "core")]
+    #[deprecated(since = "1.0.0")]
     fn min_10_exp(_: Option<f32>) -> int { MIN_10_EXP }
 
     #[inline]
-    #[deprecated]
+    #[unstable(feature = "core")]
+    #[deprecated(since = "1.0.0")]
     fn max_10_exp(_: Option<f32>) -> int { MAX_10_EXP }
 
     #[inline]
-    #[deprecated]
+    #[unstable(feature = "core")]
+    #[deprecated(since = "1.0.0")]
     fn min_value() -> f32 { MIN_VALUE }
 
     #[inline]
-    #[deprecated]
+    #[unstable(feature = "core")]
+    #[deprecated(since = "1.0.0")]
     fn min_pos_value(_: Option<f32>) -> f32 { MIN_POS_VALUE }
 
     #[inline]
-    #[deprecated]
+    #[unstable(feature = "core")]
+    #[deprecated(since = "1.0.0")]
     fn max_value() -> f32 { MAX_VALUE }
 
     /// Returns the mantissa, exponent and sign as integers.
diff --git a/src/libcore/num/f64.rs b/src/libcore/num/f64.rs
index a7f0266b095..ce011b3c2ee 100644
--- a/src/libcore/num/f64.rs
+++ b/src/libcore/num/f64.rs
@@ -14,7 +14,7 @@
 // FIXME: MIN_VALUE and MAX_VALUE literals are parsed as -inf and inf #14353
 #![allow(overflowing_literals)]
 
-#![stable]
+#![stable(feature = "rust1", since = "1.0.0")]
 
 use intrinsics;
 use mem;
@@ -26,45 +26,46 @@ use option::Option;
 // constants are implemented in favour of referencing the respective
 // members of `Bounded` and `Float`.
 
-#[unstable = "pending integer conventions"]
+#[unstable(feature = "core", reason = "pending integer conventions")]
 pub const RADIX: uint = 2;
 
 pub const MANTISSA_DIGITS: uint = 53;
-#[unstable = "pending integer conventions"]
+#[unstable(feature = "core", reason = "pending integer conventions")]
 pub const DIGITS: uint = 15;
 
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 pub const EPSILON: f64 = 2.2204460492503131e-16_f64;
 
 /// Smallest finite f64 value
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 pub const MIN_VALUE: f64 = -1.7976931348623157e+308_f64;
 /// Smallest positive, normalized f64 value
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 pub const MIN_POS_VALUE: f64 = 2.2250738585072014e-308_f64;
 /// Largest finite f64 value
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 pub const MAX_VALUE: f64 = 1.7976931348623157e+308_f64;
 
-#[unstable = "pending integer conventions"]
+#[unstable(feature = "core", reason = "pending integer conventions")]
 pub const MIN_EXP: int = -1021;
-#[unstable = "pending integer conventions"]
+#[unstable(feature = "core", reason = "pending integer conventions")]
 pub const MAX_EXP: int = 1024;
 
-#[unstable = "pending integer conventions"]
+#[unstable(feature = "core", reason = "pending integer conventions")]
 pub const MIN_10_EXP: int = -307;
-#[unstable = "pending integer conventions"]
+#[unstable(feature = "core", reason = "pending integer conventions")]
 pub const MAX_10_EXP: int = 308;
 
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 pub const NAN: f64 = 0.0_f64/0.0_f64;
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 pub const INFINITY: f64 = 1.0_f64/0.0_f64;
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 pub const NEG_INFINITY: f64 = -1.0_f64/0.0_f64;
 
 /// Various useful constants.
-#[unstable = "naming scheme needs to be revisited"]
+#[unstable(feature = "core",
+           reason = "naming scheme needs to be revisited")]
 pub mod consts {
     // FIXME: replace with mathematical constants from cmath.
 
@@ -124,7 +125,7 @@ pub mod consts {
     pub const LN_10: f64 = 2.30258509299404568401799145468436421_f64;
 }
 
-#[unstable = "trait is unstable"]
+#[unstable(feature = "core", reason = "trait is unstable")]
 impl Float for f64 {
     #[inline]
     fn nan() -> f64 { NAN }
@@ -184,43 +185,53 @@ impl Float for f64 {
     }
 
     #[inline]
-    #[deprecated]
+    #[unstable(feature = "core")]
+    #[deprecated(since = "1.0.0")]
     fn mantissa_digits(_: Option<f64>) -> uint { MANTISSA_DIGITS }
 
     #[inline]
-    #[deprecated]
+    #[unstable(feature = "core")]
+    #[deprecated(since = "1.0.0")]
     fn digits(_: Option<f64>) -> uint { DIGITS }
 
     #[inline]
-    #[deprecated]
+    #[unstable(feature = "core")]
+    #[deprecated(since = "1.0.0")]
     fn epsilon() -> f64 { EPSILON }
 
     #[inline]
-    #[deprecated]
+    #[unstable(feature = "core")]
+    #[deprecated(since = "1.0.0")]
     fn min_exp(_: Option<f64>) -> int { MIN_EXP }
 
     #[inline]
-    #[deprecated]
+    #[unstable(feature = "core")]
+    #[deprecated(since = "1.0.0")]
     fn max_exp(_: Option<f64>) -> int { MAX_EXP }
 
     #[inline]
-    #[deprecated]
+    #[unstable(feature = "core")]
+    #[deprecated(since = "1.0.0")]
     fn min_10_exp(_: Option<f64>) -> int { MIN_10_EXP }
 
     #[inline]
-    #[deprecated]
+    #[unstable(feature = "core")]
+    #[deprecated(since = "1.0.0")]
     fn max_10_exp(_: Option<f64>) -> int { MAX_10_EXP }
 
     #[inline]
-    #[deprecated]
+    #[unstable(feature = "core")]
+    #[deprecated(since = "1.0.0")]
     fn min_value() -> f64 { MIN_VALUE }
 
     #[inline]
-    #[deprecated]
+    #[unstable(feature = "core")]
+    #[deprecated(since = "1.0.0")]
     fn min_pos_value(_: Option<f64>) -> f64 { MIN_POS_VALUE }
 
     #[inline]
-    #[deprecated]
+    #[unstable(feature = "core")]
+    #[deprecated(since = "1.0.0")]
     fn max_value() -> f64 { MAX_VALUE }
 
     /// Returns the mantissa, exponent and sign as integers.
diff --git a/src/libcore/num/i16.rs b/src/libcore/num/i16.rs
index eb2a4c3835d..5ea60d0d96d 100644
--- a/src/libcore/num/i16.rs
+++ b/src/libcore/num/i16.rs
@@ -10,7 +10,7 @@
 
 //! Operations and constants for signed 16-bits integers (`i16` type)
 
-#![stable]
+#![stable(feature = "rust1", since = "1.0.0")]
 #![doc(primitive = "i16")]
 
 int_module! { i16, 16 }
diff --git a/src/libcore/num/i32.rs b/src/libcore/num/i32.rs
index 849fa205756..7d9faa998c1 100644
--- a/src/libcore/num/i32.rs
+++ b/src/libcore/num/i32.rs
@@ -10,7 +10,7 @@
 
 //! Operations and constants for signed 32-bits integers (`i32` type)
 
-#![stable]
+#![stable(feature = "rust1", since = "1.0.0")]
 #![doc(primitive = "i32")]
 
 int_module! { i32, 32 }
diff --git a/src/libcore/num/i64.rs b/src/libcore/num/i64.rs
index b6cba728e44..5a70911387b 100644
--- a/src/libcore/num/i64.rs
+++ b/src/libcore/num/i64.rs
@@ -10,7 +10,7 @@
 
 //! Operations and constants for signed 64-bits integers (`i64` type)
 
-#![stable]
+#![stable(feature = "rust1", since = "1.0.0")]
 #![doc(primitive = "i64")]
 
 int_module! { i64, 64 }
diff --git a/src/libcore/num/i8.rs b/src/libcore/num/i8.rs
index fd0759898ea..1d7d78ffa6c 100644
--- a/src/libcore/num/i8.rs
+++ b/src/libcore/num/i8.rs
@@ -10,7 +10,7 @@
 
 //! Operations and constants for signed 8-bits integers (`i8` type)
 
-#![stable]
+#![stable(feature = "rust1", since = "1.0.0")]
 #![doc(primitive = "i8")]
 
 int_module! { i8, 8 }
diff --git a/src/libcore/num/int.rs b/src/libcore/num/int.rs
index 83011db35ce..2132b9516ab 100644
--- a/src/libcore/num/int.rs
+++ b/src/libcore/num/int.rs
@@ -14,7 +14,8 @@
 //! alpha cycle along with the development of clearer conventions
 //! around integer types.
 
-#![deprecated = "replaced by isize"]
+#![unstable(feature = "core")]
+#![deprecated(since = "1.0.0", reason = "replaced by isize")]
 
 #[cfg(target_pointer_width = "32")] int_module! { int, 32 }
 #[cfg(target_pointer_width = "64")] int_module! { int, 64 }
diff --git a/src/libcore/num/int_macros.rs b/src/libcore/num/int_macros.rs
index 61cd8cbf7c1..954c8a08e64 100644
--- a/src/libcore/num/int_macros.rs
+++ b/src/libcore/num/int_macros.rs
@@ -14,21 +14,21 @@ macro_rules! int_module { ($T:ty, $bits:expr) => (
 
 // FIXME(#11621): Should be deprecated once CTFE is implemented in favour of
 // calling the `mem::size_of` function.
-#[unstable]
+#[unstable(feature = "core")]
 pub const BITS : uint = $bits;
 // FIXME(#11621): Should be deprecated once CTFE is implemented in favour of
 // calling the `mem::size_of` function.
-#[unstable]
+#[unstable(feature = "core")]
 pub const BYTES : uint = ($bits / 8);
 
 // FIXME(#11621): Should be deprecated once CTFE is implemented in favour of
 // calling the `Bounded::min_value` function.
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 pub const MIN: $T = (-1 as $T) << (BITS - 1);
 // FIXME(#9837): Compute MIN like this so the high bits that shouldn't exist are 0.
 // FIXME(#11621): Should be deprecated once CTFE is implemented in favour of
 // calling the `Bounded::max_value` function.
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 pub const MAX: $T = !MIN;
 
 ) }
diff --git a/src/libcore/num/isize.rs b/src/libcore/num/isize.rs
index e4711c92c59..0fd0d90b125 100644
--- a/src/libcore/num/isize.rs
+++ b/src/libcore/num/isize.rs
@@ -14,7 +14,7 @@
 //! new type will gradually take place over the alpha cycle along with
 //! the development of clearer conventions around integer types.
 
-#![stable]
+#![stable(feature = "rust1", since = "1.0.0")]
 #![doc(primitive = "isize")]
 
 #[cfg(target_pointer_width = "32")]
diff --git a/src/libcore/num/mod.rs b/src/libcore/num/mod.rs
index 910c9e6c670..9e460492b64 100644
--- a/src/libcore/num/mod.rs
+++ b/src/libcore/num/mod.rs
@@ -12,7 +12,7 @@
 
 //! Numeric traits and functions for the built-in numeric types.
 
-#![stable]
+#![stable(feature = "rust1", since = "1.0.0")]
 #![allow(missing_docs)]
 
 use char::CharExt;
@@ -30,7 +30,7 @@ use option::Option::{Some, None};
 use str::{FromStr, StrExt};
 
 /// A built-in signed or unsigned integer.
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 pub trait Int
     : Copy + Clone
     + NumCast
@@ -50,22 +50,26 @@ pub trait Int
 {
     /// Returns the `0` value of this integer type.
     // FIXME (#5527): Should be an associated constant
-    #[unstable = "unsure about its place in the world"]
+    #[unstable(feature = "core",
+               reason = "unsure about its place in the world")]
     fn zero() -> Self;
 
     /// Returns the `1` value of this integer type.
     // FIXME (#5527): Should be an associated constant
-    #[unstable = "unsure about its place in the world"]
+    #[unstable(feature = "core",
+               reason = "unsure about its place in the world")]
     fn one() -> Self;
 
     /// Returns the smallest value that can be represented by this integer type.
     // FIXME (#5527): Should be and associated constant
-    #[unstable = "unsure about its place in the world"]
+    #[unstable(feature = "core",
+               reason = "unsure about its place in the world")]
     fn min_value() -> Self;
 
     /// Returns the largest value that can be represented by this integer type.
     // FIXME (#5527): Should be and associated constant
-    #[unstable = "unsure about its place in the world"]
+    #[unstable(feature = "core",
+               reason = "unsure about its place in the world")]
     fn max_value() -> Self;
 
     /// Returns the number of ones in the binary representation of `self`.
@@ -79,7 +83,8 @@ pub trait Int
     ///
     /// assert_eq!(n.count_ones(), 3);
     /// ```
-    #[unstable = "pending integer conventions"]
+    #[unstable(feature = "core",
+               reason = "pending integer conventions")]
     fn count_ones(self) -> uint;
 
     /// Returns the number of zeros in the binary representation of `self`.
@@ -93,7 +98,8 @@ pub trait Int
     ///
     /// assert_eq!(n.count_zeros(), 5);
     /// ```
-    #[unstable = "pending integer conventions"]
+    #[unstable(feature = "core",
+               reason = "pending integer conventions")]
     #[inline]
     fn count_zeros(self) -> uint {
         (!self).count_ones()
@@ -111,7 +117,8 @@ pub trait Int
     ///
     /// assert_eq!(n.leading_zeros(), 10);
     /// ```
-    #[unstable = "pending integer conventions"]
+    #[unstable(feature = "core",
+               reason = "pending integer conventions")]
     fn leading_zeros(self) -> uint;
 
     /// Returns the number of trailing zeros in the binary representation
@@ -126,7 +133,8 @@ pub trait Int
     ///
     /// assert_eq!(n.trailing_zeros(), 3);
     /// ```
-    #[unstable = "pending integer conventions"]
+    #[unstable(feature = "core",
+               reason = "pending integer conventions")]
     fn trailing_zeros(self) -> uint;
 
     /// Shifts the bits to the left by a specified amount amount, `n`, wrapping
@@ -142,7 +150,8 @@ pub trait Int
     ///
     /// assert_eq!(n.rotate_left(12), m);
     /// ```
-    #[unstable = "pending integer conventions"]
+    #[unstable(feature = "core",
+               reason = "pending integer conventions")]
     fn rotate_left(self, n: uint) -> Self;
 
     /// Shifts the bits to the right by a specified amount amount, `n`, wrapping
@@ -158,7 +167,8 @@ pub trait Int
     ///
     /// assert_eq!(n.rotate_right(12), m);
     /// ```
-    #[unstable = "pending integer conventions"]
+    #[unstable(feature = "core",
+               reason = "pending integer conventions")]
     fn rotate_right(self, n: uint) -> Self;
 
     /// Reverses the byte order of the integer.
@@ -173,7 +183,7 @@ pub trait Int
     ///
     /// assert_eq!(n.swap_bytes(), m);
     /// ```
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     fn swap_bytes(self) -> Self;
 
     /// Convert an integer from big endian to the target's endianness.
@@ -193,7 +203,7 @@ pub trait Int
     ///     assert_eq!(Int::from_be(n), n.swap_bytes())
     /// }
     /// ```
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     #[inline]
     fn from_be(x: Self) -> Self {
         if cfg!(target_endian = "big") { x } else { x.swap_bytes() }
@@ -216,7 +226,7 @@ pub trait Int
     ///     assert_eq!(Int::from_le(n), n.swap_bytes())
     /// }
     /// ```
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     #[inline]
     fn from_le(x: Self) -> Self {
         if cfg!(target_endian = "little") { x } else { x.swap_bytes() }
@@ -239,7 +249,7 @@ pub trait Int
     ///     assert_eq!(n.to_be(), n.swap_bytes())
     /// }
     /// ```
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     #[inline]
     fn to_be(self) -> Self { // or not to be?
         if cfg!(target_endian = "big") { self } else { self.swap_bytes() }
@@ -262,7 +272,7 @@ pub trait Int
     ///     assert_eq!(n.to_le(), n.swap_bytes())
     /// }
     /// ```
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     #[inline]
     fn to_le(self) -> Self {
         if cfg!(target_endian = "little") { self } else { self.swap_bytes() }
@@ -279,7 +289,7 @@ pub trait Int
     /// assert_eq!(5u16.checked_add(65530), Some(65535));
     /// assert_eq!(6u16.checked_add(65530), None);
     /// ```
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     fn checked_add(self, other: Self) -> Option<Self>;
 
     /// Checked integer subtraction. Computes `self - other`, returning `None`
@@ -293,7 +303,7 @@ pub trait Int
     /// assert_eq!((-127i8).checked_sub(1), Some(-128));
     /// assert_eq!((-128i8).checked_sub(1), None);
     /// ```
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     fn checked_sub(self, other: Self) -> Option<Self>;
 
     /// Checked integer multiplication. Computes `self * other`, returning
@@ -307,7 +317,7 @@ pub trait Int
     /// assert_eq!(5u8.checked_mul(51), Some(255));
     /// assert_eq!(5u8.checked_mul(52), None);
     /// ```
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     fn checked_mul(self, other: Self) -> Option<Self>;
 
     /// Checked integer division. Computes `self / other`, returning `None` if
@@ -322,12 +332,12 @@ pub trait Int
     /// assert_eq!((-128i8).checked_div(-1), None);
     /// assert_eq!((1i8).checked_div(0), None);
     /// ```
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     fn checked_div(self, other: Self) -> Option<Self>;
 
     /// Saturating integer addition. Computes `self + other`, saturating at
     /// the numeric bounds instead of overflowing.
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     #[inline]
     fn saturating_add(self, other: Self) -> Self {
         match self.checked_add(other) {
@@ -339,7 +349,7 @@ pub trait Int
 
     /// Saturating integer subtraction. Computes `self - other`, saturating at
     /// the numeric bounds instead of overflowing.
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     #[inline]
     fn saturating_sub(self, other: Self) -> Self {
         match self.checked_sub(other) {
@@ -358,7 +368,8 @@ pub trait Int
     ///
     /// assert_eq!(2.pow(4), 16);
     /// ```
-    #[unstable = "pending integer conventions"]
+    #[unstable(feature = "core",
+               reason = "pending integer conventions")]
     #[inline]
     fn pow(self, mut exp: uint) -> Self {
         let mut base = self;
@@ -390,7 +401,7 @@ macro_rules! uint_impl {
      $add_with_overflow:path,
      $sub_with_overflow:path,
      $mul_with_overflow:path) => {
-        #[stable]
+        #[stable(feature = "rust1", since = "1.0.0")]
         impl Int for $T {
             #[inline]
             fn zero() -> $T { 0 }
@@ -521,7 +532,7 @@ macro_rules! int_impl {
      $add_with_overflow:path,
      $sub_with_overflow:path,
      $mul_with_overflow:path) => {
-        #[stable]
+        #[stable(feature = "rust1", since = "1.0.0")]
         impl Int for $T {
             #[inline]
             fn zero() -> $T { 0 }
@@ -614,14 +625,14 @@ int_impl! { int = i64, u64, 64,
     intrinsics::i64_mul_with_overflow }
 
 /// A built-in two's complement integer.
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 pub trait SignedInt
     : Int
     + Neg<Output=Self>
 {
     /// Computes the absolute value of `self`. `Int::min_value()` will be
     /// returned if the number is `Int::min_value()`.
-    #[unstable = "overflow in debug builds?"]
+    #[unstable(feature = "core", reason = "overflow in debug builds?")]
     fn abs(self) -> Self;
 
     /// Returns a number representing sign of `self`.
@@ -629,23 +640,23 @@ pub trait SignedInt
     /// - `0` if the number is zero
     /// - `1` if the number is positive
     /// - `-1` if the number is negative
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     fn signum(self) -> Self;
 
     /// Returns `true` if `self` is positive and `false` if the number
     /// is zero or negative.
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     fn is_positive(self) -> bool;
 
     /// Returns `true` if `self` is negative and `false` if the number
     /// is zero or positive.
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     fn is_negative(self) -> bool;
 }
 
 macro_rules! signed_int_impl {
     ($T:ty) => {
-        #[stable]
+        #[stable(feature = "rust1", since = "1.0.0")]
         impl SignedInt for $T {
             #[inline]
             fn abs(self) -> $T {
@@ -677,10 +688,10 @@ signed_int_impl! { i64 }
 signed_int_impl! { int }
 
 /// A built-in unsigned integer.
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 pub trait UnsignedInt: Int {
     /// Returns `true` iff `self == 2^k` for some `k`.
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     #[inline]
     fn is_power_of_two(self) -> bool {
         (self - Int::one()) & self == Int::zero() && !(self == Int::zero())
@@ -688,7 +699,7 @@ pub trait UnsignedInt: Int {
 
     /// Returns the smallest power of two greater than or equal to `self`.
     /// Unspecified behavior on overflow.
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     #[inline]
     fn next_power_of_two(self) -> Self {
         let bits = size_of::<Self>() * 8;
@@ -699,7 +710,7 @@ pub trait UnsignedInt: Int {
     /// Returns the smallest power of two greater than or equal to `n`. If the
     /// next power of two is greater than the type's maximum value, `None` is
     /// returned, otherwise the power of two is wrapped in `Some`.
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     fn checked_next_power_of_two(self) -> Option<Self> {
         let npot = self.next_power_of_two();
         if npot >= self {
@@ -710,23 +721,23 @@ pub trait UnsignedInt: Int {
     }
 }
 
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl UnsignedInt for uint {}
 
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl UnsignedInt for u8 {}
 
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl UnsignedInt for u16 {}
 
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl UnsignedInt for u32 {}
 
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl UnsignedInt for u64 {}
 
 /// A generic trait for converting a value to a number.
-#[unstable = "trait is likely to be removed"]
+#[unstable(feature = "core", reason = "trait is likely to be removed")]
 pub trait ToPrimitive {
     /// Converts the value of `self` to an `int`.
     #[inline]
@@ -991,7 +1002,7 @@ impl_to_primitive_float! { f32 }
 impl_to_primitive_float! { f64 }
 
 /// A generic trait for converting a number to a value.
-#[unstable = "trait is likely to be removed"]
+#[unstable(feature = "core", reason = "trait is likely to be removed")]
 pub trait FromPrimitive : ::marker::Sized {
     /// Convert an `int` to return an optional value of this type. If the
     /// value cannot be represented by this value, the `None` is returned.
@@ -1073,73 +1084,73 @@ pub trait FromPrimitive : ::marker::Sized {
 }
 
 /// A utility function that just calls `FromPrimitive::from_int`.
-#[unstable = "likely to be removed"]
+#[unstable(feature = "core", reason = "likely to be removed")]
 pub fn from_int<A: FromPrimitive>(n: int) -> Option<A> {
     FromPrimitive::from_int(n)
 }
 
 /// A utility function that just calls `FromPrimitive::from_i8`.
-#[unstable = "likely to be removed"]
+#[unstable(feature = "core", reason = "likely to be removed")]
 pub fn from_i8<A: FromPrimitive>(n: i8) -> Option<A> {
     FromPrimitive::from_i8(n)
 }
 
 /// A utility function that just calls `FromPrimitive::from_i16`.
-#[unstable = "likely to be removed"]
+#[unstable(feature = "core", reason = "likely to be removed")]
 pub fn from_i16<A: FromPrimitive>(n: i16) -> Option<A> {
     FromPrimitive::from_i16(n)
 }
 
 /// A utility function that just calls `FromPrimitive::from_i32`.
-#[unstable = "likely to be removed"]
+#[unstable(feature = "core", reason = "likely to be removed")]
 pub fn from_i32<A: FromPrimitive>(n: i32) -> Option<A> {
     FromPrimitive::from_i32(n)
 }
 
 /// A utility function that just calls `FromPrimitive::from_i64`.
-#[unstable = "likely to be removed"]
+#[unstable(feature = "core", reason = "likely to be removed")]
 pub fn from_i64<A: FromPrimitive>(n: i64) -> Option<A> {
     FromPrimitive::from_i64(n)
 }
 
 /// A utility function that just calls `FromPrimitive::from_uint`.
-#[unstable = "likely to be removed"]
+#[unstable(feature = "core", reason = "likely to be removed")]
 pub fn from_uint<A: FromPrimitive>(n: uint) -> Option<A> {
     FromPrimitive::from_uint(n)
 }
 
 /// A utility function that just calls `FromPrimitive::from_u8`.
-#[unstable = "likely to be removed"]
+#[unstable(feature = "core", reason = "likely to be removed")]
 pub fn from_u8<A: FromPrimitive>(n: u8) -> Option<A> {
     FromPrimitive::from_u8(n)
 }
 
 /// A utility function that just calls `FromPrimitive::from_u16`.
-#[unstable = "likely to be removed"]
+#[unstable(feature = "core", reason = "likely to be removed")]
 pub fn from_u16<A: FromPrimitive>(n: u16) -> Option<A> {
     FromPrimitive::from_u16(n)
 }
 
 /// A utility function that just calls `FromPrimitive::from_u32`.
-#[unstable = "likely to be removed"]
+#[unstable(feature = "core", reason = "likely to be removed")]
 pub fn from_u32<A: FromPrimitive>(n: u32) -> Option<A> {
     FromPrimitive::from_u32(n)
 }
 
 /// A utility function that just calls `FromPrimitive::from_u64`.
-#[unstable = "likely to be removed"]
+#[unstable(feature = "core", reason = "likely to be removed")]
 pub fn from_u64<A: FromPrimitive>(n: u64) -> Option<A> {
     FromPrimitive::from_u64(n)
 }
 
 /// A utility function that just calls `FromPrimitive::from_f32`.
-#[unstable = "likely to be removed"]
+#[unstable(feature = "core", reason = "likely to be removed")]
 pub fn from_f32<A: FromPrimitive>(n: f32) -> Option<A> {
     FromPrimitive::from_f32(n)
 }
 
 /// A utility function that just calls `FromPrimitive::from_f64`.
-#[unstable = "likely to be removed"]
+#[unstable(feature = "core", reason = "likely to be removed")]
 pub fn from_f64<A: FromPrimitive>(n: f64) -> Option<A> {
     FromPrimitive::from_f64(n)
 }
@@ -1190,13 +1201,13 @@ impl_from_primitive! { f64, to_f64 }
 /// ```
 ///
 #[inline]
-#[unstable = "likely to be removed"]
+#[unstable(feature = "core", reason = "likely to be removed")]
 pub fn cast<T: NumCast,U: NumCast>(n: T) -> Option<U> {
     NumCast::from(n)
 }
 
 /// An interface for casting between machine scalars.
-#[unstable = "trait is likely to be removed"]
+#[unstable(feature = "core", reason = "trait is likely to be removed")]
 pub trait NumCast: ToPrimitive {
     /// Creates a number from another value that can be converted into a primitive via the
     /// `ToPrimitive` trait.
@@ -1231,7 +1242,7 @@ impl_num_cast! { f64,   to_f64 }
 
 /// Used for representing the classification of floating point numbers
 #[derive(Copy, PartialEq, Show)]
-#[unstable = "may be renamed"]
+#[unstable(feature = "core", reason = "may be renamed")]
 pub enum FpCategory {
     /// "Not a Number", often obtained by dividing by zero
     Nan,
@@ -1251,7 +1262,8 @@ pub enum FpCategory {
 //
 // FIXME(#8888): Several of these functions have a parameter named
 //               `unused_self`. Removing it requires #8888 to be fixed.
-#[unstable = "distribution of methods between core/std is unclear"]
+#[unstable(feature = "core",
+           reason = "distribution of methods between core/std is unclear")]
 pub trait Float
     : Copy + Clone
     + NumCast
@@ -1280,34 +1292,56 @@ pub trait Float
     // FIXME (#5527): These should be associated constants
 
     /// Returns the number of binary digits of mantissa that this type supports.
-    #[deprecated = "use `std::f32::MANTISSA_DIGITS` or `std::f64::MANTISSA_DIGITS` as appropriate"]
+    #[unstable(feature = "core")]
+    #[deprecated(since = "1.0.0",
+                 reason = "use `std::f32::MANTISSA_DIGITS` or \
+                           `std::f64::MANTISSA_DIGITS` as appropriate")]
     fn mantissa_digits(unused_self: Option<Self>) -> uint;
     /// Returns the number of base-10 digits of precision that this type supports.
-    #[deprecated = "use `std::f32::DIGITS` or `std::f64::DIGITS` as appropriate"]
+    #[unstable(feature = "core")]
+    #[deprecated(since = "1.0.0",
+                 reason = "use `std::f32::DIGITS` or `std::f64::DIGITS` as appropriate")]
     fn digits(unused_self: Option<Self>) -> uint;
     /// Returns the difference between 1.0 and the smallest representable number larger than 1.0.
-    #[deprecated = "use `std::f32::EPSILON` or `std::f64::EPSILON` as appropriate"]
+    #[unstable(feature = "core")]
+    #[deprecated(since = "1.0.0",
+                 reason = "use `std::f32::EPSILON` or `std::f64::EPSILON` as appropriate")]
     fn epsilon() -> Self;
     /// Returns the minimum binary exponent that this type can represent.
-    #[deprecated = "use `std::f32::MIN_EXP` or `std::f64::MIN_EXP` as appropriate"]
+    #[unstable(feature = "core")]
+    #[deprecated(since = "1.0.0",
+                 reason = "use `std::f32::MIN_EXP` or `std::f64::MIN_EXP` as appropriate")]
     fn min_exp(unused_self: Option<Self>) -> int;
     /// Returns the maximum binary exponent that this type can represent.
-    #[deprecated = "use `std::f32::MAX_EXP` or `std::f64::MAX_EXP` as appropriate"]
+    #[unstable(feature = "core")]
+    #[deprecated(since = "1.0.0",
+                 reason = "use `std::f32::MAX_EXP` or `std::f64::MAX_EXP` as appropriate")]
     fn max_exp(unused_self: Option<Self>) -> int;
     /// Returns the minimum base-10 exponent that this type can represent.
-    #[deprecated = "use `std::f32::MIN_10_EXP` or `std::f64::MIN_10_EXP` as appropriate"]
+    #[unstable(feature = "core")]
+    #[deprecated(since = "1.0.0",
+                 reason = "use `std::f32::MIN_10_EXP` or `std::f64::MIN_10_EXP` as appropriate")]
     fn min_10_exp(unused_self: Option<Self>) -> int;
     /// Returns the maximum base-10 exponent that this type can represent.
-    #[deprecated = "use `std::f32::MAX_10_EXP` or `std::f64::MAX_10_EXP` as appropriate"]
+    #[unstable(feature = "core")]
+    #[deprecated(since = "1.0.0",
+                 reason = "use `std::f32::MAX_10_EXP` or `std::f64::MAX_10_EXP` as appropriate")]
     fn max_10_exp(unused_self: Option<Self>) -> int;
     /// Returns the smallest finite value that this type can represent.
-    #[deprecated = "use `std::f32::MIN_VALUE` or `std::f64::MIN_VALUE` as appropriate"]
+    #[unstable(feature = "core")]
+    #[deprecated(since = "1.0.0",
+                 reason = "use `std::f32::MIN_VALUE` or `std::f64::MIN_VALUE` as appropriate")]
     fn min_value() -> Self;
     /// Returns the smallest normalized positive number that this type can represent.
-    #[deprecated = "use `std::f32::MIN_POS_VALUE` or `std::f64::MIN_POS_VALUE` as appropriate"]
+    #[unstable(feature = "core")]
+    #[deprecated(since = "1.0.0",
+                 reason = "use `std::f32::MIN_POS_VALUE` or \
+                           `std::f64::MIN_POS_VALUE` as appropriate")]
     fn min_pos_value(unused_self: Option<Self>) -> Self;
     /// Returns the largest finite value that this type can represent.
-    #[deprecated = "use `std::f32::MAX_VALUE` or `std::f64::MAX_VALUE` as appropriate"]
+    #[unstable(feature = "core")]
+    #[deprecated(since = "1.0.0",
+                 reason = "use `std::f32::MAX_VALUE` or `std::f64::MAX_VALUE` as appropriate")]
     fn max_value() -> Self;
 
     /// Returns true if this value is NaN and false otherwise.
@@ -1394,20 +1428,21 @@ pub trait Float
 }
 
 /// A generic trait for converting a string with a radix (base) to a value
-#[unstable = "might need to return Result"]
+#[unstable(feature = "core", reason = "might need to return Result")]
 pub trait FromStrRadix {
     fn from_str_radix(str: &str, radix: uint) -> Option<Self>;
 }
 
 /// A utility function that just calls FromStrRadix::from_str_radix.
-#[unstable = "might need to return Result"]
+#[unstable(feature = "core", reason = "might need to return Result")]
 pub fn from_str_radix<T: FromStrRadix>(str: &str, radix: uint) -> Option<T> {
     FromStrRadix::from_str_radix(str, radix)
 }
 
 macro_rules! from_str_radix_float_impl {
     ($T:ty) => {
-        #[unstable = "might need to return Result"]
+        #[unstable(feature = "core",
+                   reason = "might need to return Result")]
         impl FromStr for $T {
             /// Convert a string in base 10 to a float.
             /// Accepts an optional decimal exponent.
@@ -1440,7 +1475,8 @@ macro_rules! from_str_radix_float_impl {
             }
         }
 
-        #[unstable = "might need to return Result"]
+        #[unstable(feature = "core",
+                   reason = "might need to return Result")]
         impl FromStrRadix for $T {
             /// Convert a string in a given base to a float.
             ///
@@ -1604,7 +1640,8 @@ from_str_radix_float_impl! { f64 }
 
 macro_rules! from_str_radix_int_impl {
     ($T:ty) => {
-        #[unstable = "might need to return Result"]
+        #[unstable(feature = "core",
+                   reason = "might need to return Result")]
         impl FromStr for $T {
             #[inline]
             fn from_str(src: &str) -> Option<$T> {
@@ -1612,7 +1649,8 @@ macro_rules! from_str_radix_int_impl {
             }
         }
 
-        #[unstable = "might need to return Result"]
+        #[unstable(feature = "core",
+                   reason = "might need to return Result")]
         impl FromStrRadix for $T {
             fn from_str_radix(src: &str, radix: uint) -> Option<$T> {
                 assert!(radix >= 2 && radix <= 36,
diff --git a/src/libcore/num/u16.rs b/src/libcore/num/u16.rs
index 730a24a963a..21635799a77 100644
--- a/src/libcore/num/u16.rs
+++ b/src/libcore/num/u16.rs
@@ -10,7 +10,7 @@
 
 //! Operations and constants for unsigned 16-bits integers (`u16` type)
 
-#![stable]
+#![stable(feature = "rust1", since = "1.0.0")]
 #![doc(primitive = "u16")]
 
 uint_module! { u16, i16, 16 }
diff --git a/src/libcore/num/u32.rs b/src/libcore/num/u32.rs
index f308122af43..7d520770503 100644
--- a/src/libcore/num/u32.rs
+++ b/src/libcore/num/u32.rs
@@ -10,7 +10,7 @@
 
 //! Operations and constants for unsigned 32-bits integers (`u32` type)
 
-#![stable]
+#![stable(feature = "rust1", since = "1.0.0")]
 #![doc(primitive = "u32")]
 
 uint_module! { u32, i32, 32 }
diff --git a/src/libcore/num/u64.rs b/src/libcore/num/u64.rs
index a55868eb746..f10822077dc 100644
--- a/src/libcore/num/u64.rs
+++ b/src/libcore/num/u64.rs
@@ -10,7 +10,7 @@
 
 //! Operations and constants for unsigned 64-bits integer (`u64` type)
 
-#![stable]
+#![stable(feature = "rust1", since = "1.0.0")]
 #![doc(primitive = "u64")]
 
 uint_module! { u64, i64, 64 }
diff --git a/src/libcore/num/u8.rs b/src/libcore/num/u8.rs
index 8643f8ad650..3d6922b07b1 100644
--- a/src/libcore/num/u8.rs
+++ b/src/libcore/num/u8.rs
@@ -10,7 +10,7 @@
 
 //! Operations and constants for unsigned 8-bits integers (`u8` type)
 
-#![stable]
+#![stable(feature = "rust1", since = "1.0.0")]
 #![doc(primitive = "u8")]
 
 uint_module! { u8, i8, 8 }
diff --git a/src/libcore/num/uint.rs b/src/libcore/num/uint.rs
index 7931890ca5e..f66a0eed971 100644
--- a/src/libcore/num/uint.rs
+++ b/src/libcore/num/uint.rs
@@ -14,6 +14,7 @@
 //! alpha cycle along with the development of clearer conventions
 //! around integer types.
 
-#![deprecated = "replaced by usize"]
+#![unstable(feature = "core")]
+#![deprecated(since = "1.0.0", reason = "replaced by usize")]
 
 uint_module! { uint, int, ::int::BITS }
diff --git a/src/libcore/num/uint_macros.rs b/src/libcore/num/uint_macros.rs
index 535765840a0..06502be54aa 100644
--- a/src/libcore/num/uint_macros.rs
+++ b/src/libcore/num/uint_macros.rs
@@ -12,14 +12,14 @@
 
 macro_rules! uint_module { ($T:ty, $T_SIGNED:ty, $bits:expr) => (
 
-#[unstable]
+#[unstable(feature = "core")]
 pub const BITS : uint = $bits;
-#[unstable]
+#[unstable(feature = "core")]
 pub const BYTES : uint = ($bits / 8);
 
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 pub const MIN: $T = 0 as $T;
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 pub const MAX: $T = 0 as $T - 1 as $T;
 
 ) }
diff --git a/src/libcore/num/usize.rs b/src/libcore/num/usize.rs
index 5eebcd51a77..602ef4fe45e 100644
--- a/src/libcore/num/usize.rs
+++ b/src/libcore/num/usize.rs
@@ -14,7 +14,7 @@
 //! new type will gradually take place over the alpha cycle along with
 //! the development of clearer conventions around integer types.
 
-#![stable]
+#![stable(feature = "rust1", since = "1.0.0")]
 #![doc(primitive = "usize")]
 
 uint_module! { usize, isize, ::isize::BITS }
diff --git a/src/libcore/ops.rs b/src/libcore/ops.rs
index 130db7d8ce6..bbb964508b4 100644
--- a/src/libcore/ops.rs
+++ b/src/libcore/ops.rs
@@ -65,7 +65,7 @@
 //! See the documentation for each trait for a minimum implementation that prints
 //! something to the screen.
 
-#![stable]
+#![stable(feature = "rust1", since = "1.0.0")]
 
 use marker::Sized;
 use fmt;
@@ -92,10 +92,10 @@ use fmt;
 /// }
 /// ```
 #[lang="drop"]
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 pub trait Drop {
     /// The `drop` method, called when the value goes out of scope.
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     fn drop(&mut self);
 }
 
@@ -103,7 +103,8 @@ pub trait Drop {
 // based on "op T" where T is expected to be `Copy`able
 macro_rules! forward_ref_unop {
     (impl $imp:ident, $method:ident for $t:ty) => {
-        #[unstable = "recently added, waiting for dust to settle"]
+        #[unstable(feature = "core",
+                   reason = "recently added, waiting for dust to settle")]
         impl<'a> $imp for &'a $t {
             type Output = <$t as $imp>::Output;
 
@@ -119,7 +120,8 @@ macro_rules! forward_ref_unop {
 // based on "T op U" where T and U are expected to be `Copy`able
 macro_rules! forward_ref_binop {
     (impl $imp:ident, $method:ident for $t:ty, $u:ty) => {
-        #[unstable = "recently added, waiting for dust to settle"]
+        #[unstable(feature = "core",
+                   reason = "recently added, waiting for dust to settle")]
         impl<'a> $imp<$u> for &'a $t {
             type Output = <$t as $imp<$u>>::Output;
 
@@ -129,7 +131,8 @@ macro_rules! forward_ref_binop {
             }
         }
 
-        #[unstable = "recently added, waiting for dust to settle"]
+        #[unstable(feature = "core",
+                   reason = "recently added, waiting for dust to settle")]
         impl<'a> $imp<&'a $u> for $t {
             type Output = <$t as $imp<$u>>::Output;
 
@@ -139,7 +142,8 @@ macro_rules! forward_ref_binop {
             }
         }
 
-        #[unstable = "recently added, waiting for dust to settle"]
+        #[unstable(feature = "core",
+                   reason = "recently added, waiting for dust to settle")]
         impl<'a, 'b> $imp<&'a $u> for &'b $t {
             type Output = <$t as $imp<$u>>::Output;
 
@@ -178,19 +182,19 @@ macro_rules! forward_ref_binop {
 /// }
 /// ```
 #[lang="add"]
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 pub trait Add<RHS=Self> {
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     type Output;
 
     /// The method for the `+` operator
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     fn add(self, rhs: RHS) -> Self::Output;
 }
 
 macro_rules! add_impl {
     ($($t:ty)*) => ($(
-        #[stable]
+        #[stable(feature = "rust1", since = "1.0.0")]
         impl Add for $t {
             type Output = $t;
 
@@ -231,19 +235,19 @@ add_impl! { uint u8 u16 u32 u64 int i8 i16 i32 i64 f32 f64 }
 /// }
 /// ```
 #[lang="sub"]
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 pub trait Sub<RHS=Self> {
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     type Output;
 
     /// The method for the `-` operator
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     fn sub(self, rhs: RHS) -> Self::Output;
 }
 
 macro_rules! sub_impl {
     ($($t:ty)*) => ($(
-        #[stable]
+        #[stable(feature = "rust1", since = "1.0.0")]
         impl Sub for $t {
             type Output = $t;
 
@@ -284,19 +288,19 @@ sub_impl! { uint u8 u16 u32 u64 int i8 i16 i32 i64 f32 f64 }
 /// }
 /// ```
 #[lang="mul"]
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 pub trait Mul<RHS=Self> {
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     type Output;
 
     /// The method for the `*` operator
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     fn mul(self, rhs: RHS) -> Self::Output;
 }
 
 macro_rules! mul_impl {
     ($($t:ty)*) => ($(
-        #[stable]
+        #[stable(feature = "rust1", since = "1.0.0")]
         impl Mul for $t {
             type Output = $t;
 
@@ -337,19 +341,19 @@ mul_impl! { uint u8 u16 u32 u64 int i8 i16 i32 i64 f32 f64 }
 /// }
 /// ```
 #[lang="div"]
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 pub trait Div<RHS=Self> {
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     type Output;
 
     /// The method for the `/` operator
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     fn div(self, rhs: RHS) -> Self::Output;
 }
 
 macro_rules! div_impl {
     ($($t:ty)*) => ($(
-        #[stable]
+        #[stable(feature = "rust1", since = "1.0.0")]
         impl Div for $t {
             type Output = $t;
 
@@ -390,19 +394,19 @@ div_impl! { uint u8 u16 u32 u64 int i8 i16 i32 i64 f32 f64 }
 /// }
 /// ```
 #[lang="rem"]
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 pub trait Rem<RHS=Self> {
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     type Output = Self;
 
     /// The method for the `%` operator
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     fn rem(self, rhs: RHS) -> Self::Output;
 }
 
 macro_rules! rem_impl {
     ($($t:ty)*) => ($(
-        #[stable]
+        #[stable(feature = "rust1", since = "1.0.0")]
         impl Rem for $t {
             type Output = $t;
 
@@ -416,7 +420,7 @@ macro_rules! rem_impl {
 
 macro_rules! rem_float_impl {
     ($t:ty, $fmod:ident) => {
-        #[stable]
+        #[stable(feature = "rust1", since = "1.0.0")]
         impl Rem for $t {
             type Output = $t;
 
@@ -462,25 +466,25 @@ rem_float_impl! { f64, fmod }
 /// }
 /// ```
 #[lang="neg"]
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 pub trait Neg {
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     type Output;
 
     /// The method for the unary `-` operator
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     fn neg(self) -> Self::Output;
 }
 
 macro_rules! neg_impl {
     ($($t:ty)*) => ($(
-        #[stable]
+        #[stable(feature = "rust1", since = "1.0.0")]
         impl Neg for $t {
-            #[stable]
+            #[stable(feature = "rust1", since = "1.0.0")]
             type Output = $t;
 
             #[inline]
-            #[stable]
+            #[stable(feature = "rust1", since = "1.0.0")]
             fn neg(self) -> $t { -self }
         }
 
@@ -490,7 +494,7 @@ macro_rules! neg_impl {
 
 macro_rules! neg_uint_impl {
     ($t:ty, $t_signed:ty) => {
-        #[stable]
+        #[stable(feature = "rust1", since = "1.0.0")]
         impl Neg for $t {
             type Output = $t;
 
@@ -538,19 +542,19 @@ neg_uint_impl! { u64, i64 }
 /// }
 /// ```
 #[lang="not"]
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 pub trait Not {
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     type Output;
 
     /// The method for the unary `!` operator
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     fn not(self) -> Self::Output;
 }
 
 macro_rules! not_impl {
     ($($t:ty)*) => ($(
-        #[stable]
+        #[stable(feature = "rust1", since = "1.0.0")]
         impl Not for $t {
             type Output = $t;
 
@@ -591,19 +595,19 @@ not_impl! { bool uint u8 u16 u32 u64 int i8 i16 i32 i64 }
 /// }
 /// ```
 #[lang="bitand"]
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 pub trait BitAnd<RHS=Self> {
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     type Output;
 
     /// The method for the `&` operator
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     fn bitand(self, rhs: RHS) -> Self::Output;
 }
 
 macro_rules! bitand_impl {
     ($($t:ty)*) => ($(
-        #[stable]
+        #[stable(feature = "rust1", since = "1.0.0")]
         impl BitAnd for $t {
             type Output = $t;
 
@@ -644,19 +648,19 @@ bitand_impl! { bool uint u8 u16 u32 u64 int i8 i16 i32 i64 }
 /// }
 /// ```
 #[lang="bitor"]
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 pub trait BitOr<RHS=Self> {
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     type Output;
 
     /// The method for the `|` operator
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     fn bitor(self, rhs: RHS) -> Self::Output;
 }
 
 macro_rules! bitor_impl {
     ($($t:ty)*) => ($(
-        #[stable]
+        #[stable(feature = "rust1", since = "1.0.0")]
         impl BitOr for $t {
             type Output = $t;
 
@@ -697,19 +701,19 @@ bitor_impl! { bool uint u8 u16 u32 u64 int i8 i16 i32 i64 }
 /// }
 /// ```
 #[lang="bitxor"]
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 pub trait BitXor<RHS=Self> {
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     type Output;
 
     /// The method for the `^` operator
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     fn bitxor(self, rhs: RHS) -> Self::Output;
 }
 
 macro_rules! bitxor_impl {
     ($($t:ty)*) => ($(
-        #[stable]
+        #[stable(feature = "rust1", since = "1.0.0")]
         impl BitXor for $t {
             type Output = $t;
 
@@ -750,19 +754,19 @@ bitxor_impl! { bool uint u8 u16 u32 u64 int i8 i16 i32 i64 }
 /// }
 /// ```
 #[lang="shl"]
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 pub trait Shl<RHS> {
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     type Output;
 
     /// The method for the `<<` operator
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     fn shl(self, rhs: RHS) -> Self::Output;
 }
 
 macro_rules! shl_impl {
     ($t:ty, $f:ty) => (
-        #[stable]
+        #[stable(feature = "rust1", since = "1.0.0")]
         impl Shl<$f> for $t {
             type Output = $t;
 
@@ -821,13 +825,13 @@ shl_impl_all! { u8 u16 u32 u64 usize i8 i16 i32 i64 isize }
 /// }
 /// ```
 #[lang="shr"]
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 pub trait Shr<RHS> {
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     type Output;
 
     /// The method for the `>>` operator
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     fn shr(self, rhs: RHS) -> Self::Output;
 }
 
@@ -894,12 +898,12 @@ shr_impl_all! { u8 u16 u32 u64 usize i8 i16 i32 i64 isize }
 /// ```
 #[lang="index"]
 #[rustc_on_unimplemented = "the type `{Self}` cannot be indexed by `{Index}`"]
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 pub trait Index<Index: ?Sized> {
     type Output: ?Sized;
 
     /// The method for the indexing (`Foo[Bar]`) operation
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     fn index<'a>(&'a self, index: &Index) -> &'a Self::Output;
 }
 
@@ -933,22 +937,22 @@ pub trait Index<Index: ?Sized> {
 /// ```
 #[lang="index_mut"]
 #[rustc_on_unimplemented = "the type `{Self}` cannot be mutably indexed by `{Index}`"]
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 pub trait IndexMut<Index: ?Sized> {
     type Output: ?Sized;
 
     /// The method for the indexing (`Foo[Bar]`) operation
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     fn index_mut<'a>(&'a mut self, index: &Index) -> &'a mut Self::Output;
 }
 
 /// An unbounded range.
 #[derive(Copy, Clone, PartialEq, Eq)]
 #[lang="full_range"]
-#[unstable = "may be renamed to RangeFull"]
+#[unstable(feature = "core", reason  = "may be renamed to RangeFull")]
 pub struct FullRange;
 
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl fmt::Debug for FullRange {
     fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
         fmt::Debug::fmt("..", fmt)
@@ -958,7 +962,7 @@ impl fmt::Debug for FullRange {
 /// A (half-open) range which is bounded at both ends.
 #[derive(Copy, Clone, PartialEq, Eq)]
 #[lang="range"]
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 pub struct Range<Idx> {
     /// The lower bound of the range (inclusive).
     pub start: Idx,
@@ -966,7 +970,7 @@ pub struct Range<Idx> {
     pub end: Idx,
 }
 
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl<Idx: fmt::Debug> fmt::Debug for Range<Idx> {
     fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
         write!(fmt, "{:?}..{:?}", self.start, self.end)
@@ -976,7 +980,7 @@ impl<Idx: fmt::Debug> fmt::Debug for Range<Idx> {
 /// A range which is only bounded below.
 #[derive(Copy, Clone, PartialEq, Eq)]
 #[lang="range_from"]
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 pub struct RangeFrom<Idx> {
     /// The lower bound of the range (inclusive).
     pub start: Idx,
@@ -984,7 +988,7 @@ pub struct RangeFrom<Idx> {
 
 
 
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl<Idx: fmt::Debug> fmt::Debug for RangeFrom<Idx> {
     fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
         write!(fmt, "{:?}..", self.start)
@@ -994,13 +998,13 @@ impl<Idx: fmt::Debug> fmt::Debug for RangeFrom<Idx> {
 /// A range which is only bounded above.
 #[derive(Copy, Clone, PartialEq, Eq)]
 #[lang="range_to"]
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 pub struct RangeTo<Idx> {
     /// The upper bound of the range (exclusive).
     pub end: Idx,
 }
 
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl<Idx: fmt::Debug> fmt::Debug for RangeTo<Idx> {
     fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
         write!(fmt, "..{:?}", self.end)
@@ -1037,24 +1041,24 @@ impl<Idx: fmt::Debug> fmt::Debug for RangeTo<Idx> {
 /// }
 /// ```
 #[lang="deref"]
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 pub trait Deref {
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     type Target: ?Sized;
 
     /// The method called to dereference a value
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     fn deref<'a>(&'a self) -> &'a Self::Target;
 }
 
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl<'a, T: ?Sized> Deref for &'a T {
     type Target = T;
 
     fn deref(&self) -> &T { *self }
 }
 
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl<'a, T: ?Sized> Deref for &'a mut T {
     type Target = T;
 
@@ -1097,42 +1101,49 @@ impl<'a, T: ?Sized> Deref for &'a mut T {
 /// }
 /// ```
 #[lang="deref_mut"]
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 pub trait DerefMut: Deref {
     /// The method called to mutably dereference a value
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     fn deref_mut<'a>(&'a mut self) -> &'a mut Self::Target;
 }
 
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl<'a, T: ?Sized> DerefMut for &'a mut T {
     fn deref_mut(&mut self) -> &mut T { *self }
 }
 
 /// A version of the call operator that takes an immutable receiver.
 #[lang="fn"]
-#[unstable = "uncertain about variadic generics, input versus associated types"]
-pub trait Fn<Args,Result> {
+#[unstable(feature = "core",
+           reason = "uncertain about variadic generics, input versus associated types")]
+#[cfg(stage0)]
+pub trait Fn<Args,Output> {
     /// This is called when the call operator is used.
-    extern "rust-call" fn call(&self, args: Args) -> Result;
+    extern "rust-call" fn call(&self, args: Args) -> Output;
 }
 
 /// A version of the call operator that takes a mutable receiver.
 #[lang="fn_mut"]
-#[unstable = "uncertain about variadic generics, input versus associated types"]
-pub trait FnMut<Args,Result> {
+#[unstable(feature = "core",
+           reason = "uncertain about variadic generics, input versus associated types")]
+#[cfg(stage0)]
+pub trait FnMut<Args,Output> {
     /// This is called when the call operator is used.
-    extern "rust-call" fn call_mut(&mut self, args: Args) -> Result;
+    extern "rust-call" fn call_mut(&mut self, args: Args) -> Output;
 }
 
 /// A version of the call operator that takes a by-value receiver.
 #[lang="fn_once"]
-#[unstable = "uncertain about variadic generics, input versus associated types"]
-pub trait FnOnce<Args,Result> {
+#[unstable(feature = "core",
+           reason = "uncertain about variadic generics, input versus associated types")]
+#[cfg(stage0)]
+pub trait FnOnce<Args,Output> {
     /// This is called when the call operator is used.
-    extern "rust-call" fn call_once(self, args: Args) -> Result;
+    extern "rust-call" fn call_once(self, args: Args) -> Output;
 }
 
+#[cfg(stage0)]
 impl<F: ?Sized, A, R> FnMut<A, R> for F
     where F : Fn<A, R>
 {
@@ -1141,6 +1152,7 @@ impl<F: ?Sized, A, R> FnMut<A, R> for F
     }
 }
 
+#[cfg(stage0)]
 impl<F,A,R> FnOnce<A,R> for F
     where F : FnMut<A,R>
 {
@@ -1148,3 +1160,61 @@ impl<F,A,R> FnOnce<A,R> for F
         self.call_mut(args)
     }
 }
+
+/// A version of the call operator that takes an immutable receiver.
+#[lang="fn"]
+#[unstable(feature = "core",
+           reason = "uncertain about variadic generics, input versus associated types")]
+#[cfg(not(stage0))]
+pub trait Fn<Args> {
+    type Output;
+
+    /// This is called when the call operator is used.
+    extern "rust-call" fn call(&self, args: Args) -> Self::Output;
+}
+
+/// A version of the call operator that takes a mutable receiver.
+#[lang="fn_mut"]
+#[unstable(feature = "core",
+           reason = "uncertain about variadic generics, input versus associated types")]
+#[cfg(not(stage0))]
+pub trait FnMut<Args> {
+    type Output;
+
+    /// This is called when the call operator is used.
+    extern "rust-call" fn call_mut(&mut self, args: Args) -> Self::Output;
+}
+
+/// A version of the call operator that takes a by-value receiver.
+#[lang="fn_once"]
+#[unstable(feature = "core",
+           reason = "uncertain about variadic generics, input versus associated types")]
+#[cfg(not(stage0))]
+pub trait FnOnce<Args> {
+    type Output;
+
+    /// This is called when the call operator is used.
+    extern "rust-call" fn call_once(self, args: Args) -> Self::Output;
+}
+
+#[cfg(not(stage0))]
+impl<F: ?Sized, A> FnMut<A> for F
+    where F : Fn<A>
+{
+    type Output = <F as Fn<A>>::Output;
+
+    extern "rust-call" fn call_mut(&mut self, args: A) -> <F as Fn<A>>::Output {
+        self.call(args)
+    }
+}
+
+#[cfg(not(stage0))]
+impl<F,A> FnOnce<A> for F
+    where F : FnMut<A>
+{
+    type Output = <F as FnMut<A>>::Output;
+
+    extern "rust-call" fn call_once(mut self, args: A) -> <F as FnMut<A>>::Output {
+        self.call_mut(args)
+    }
+}
diff --git a/src/libcore/option.rs b/src/libcore/option.rs
index 3ee2aa678e9..c7266aa4f1a 100644
--- a/src/libcore/option.rs
+++ b/src/libcore/option.rs
@@ -141,7 +141,7 @@
 //! }
 //! ```
 
-#![stable]
+#![stable(feature = "rust1", since = "1.0.0")]
 
 use self::Option::*;
 
@@ -164,13 +164,13 @@ use slice;
 
 /// The `Option` type.
 #[derive(Clone, Copy, PartialEq, PartialOrd, Eq, Ord, Show, Hash)]
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 pub enum Option<T> {
     /// No value
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     None,
     /// Some value `T`
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     Some(T)
 }
 
@@ -195,7 +195,7 @@ impl<T> Option<T> {
     /// assert_eq!(x.is_some(), false);
     /// ```
     #[inline]
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     pub fn is_some(&self) -> bool {
         match *self {
             Some(_) => true,
@@ -215,7 +215,7 @@ impl<T> Option<T> {
     /// assert_eq!(x.is_none(), true);
     /// ```
     #[inline]
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     pub fn is_none(&self) -> bool {
         !self.is_some()
     }
@@ -241,7 +241,7 @@ impl<T> Option<T> {
     /// println!("still can print num_as_str: {:?}", num_as_str);
     /// ```
     #[inline]
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     pub fn as_ref<'r>(&'r self) -> Option<&'r T> {
         match *self {
             Some(ref x) => Some(x),
@@ -262,7 +262,7 @@ impl<T> Option<T> {
     /// assert_eq!(x, Some(42));
     /// ```
     #[inline]
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     pub fn as_mut<'r>(&'r mut self) -> Option<&'r mut T> {
         match *self {
             Some(ref mut x) => Some(x),
@@ -285,7 +285,8 @@ impl<T> Option<T> {
     /// assert_eq!(x, Some("Dirt"));
     /// ```
     #[inline]
-    #[unstable = "waiting for mut conventions"]
+    #[unstable(feature = "core",
+               reason = "waiting for mut conventions")]
     pub fn as_mut_slice<'r>(&'r mut self) -> &'r mut [T] {
         match *self {
             Some(ref mut x) => {
@@ -322,7 +323,7 @@ impl<T> Option<T> {
     /// x.expect("the world is ending"); // panics with `world is ending`
     /// ```
     #[inline]
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     pub fn expect(self, msg: &str) -> T {
         match self {
             Some(val) => val,
@@ -354,7 +355,7 @@ impl<T> Option<T> {
     /// assert_eq!(x.unwrap(), "air"); // fails
     /// ```
     #[inline]
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     pub fn unwrap(self) -> T {
         match self {
             Some(val) => val,
@@ -371,7 +372,7 @@ impl<T> Option<T> {
     /// assert_eq!(None.unwrap_or("bike"), "bike");
     /// ```
     #[inline]
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     pub fn unwrap_or(self, def: T) -> T {
         match self {
             Some(x) => x,
@@ -389,7 +390,7 @@ impl<T> Option<T> {
     /// assert_eq!(None.unwrap_or_else(|| 2 * k), 20);
     /// ```
     #[inline]
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     pub fn unwrap_or_else<F: FnOnce() -> T>(self, f: F) -> T {
         match self {
             Some(x) => x,
@@ -413,7 +414,7 @@ impl<T> Option<T> {
     /// let num_as_int: Option<uint> = num_as_str.map(|n| n.len());
     /// ```
     #[inline]
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     pub fn map<U, F: FnOnce(T) -> U>(self, f: F) -> Option<U> {
         match self {
             Some(x) => Some(f(x)),
@@ -433,7 +434,7 @@ impl<T> Option<T> {
     /// assert_eq!(x.map_or(42, |v| v.len()), 42);
     /// ```
     #[inline]
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     pub fn map_or<U, F: FnOnce(T) -> U>(self, def: U, f: F) -> U {
         match self {
             Some(t) => f(t),
@@ -455,7 +456,7 @@ impl<T> Option<T> {
     /// assert_eq!(x.map_or_else(|| 2 * k, |v| v.len()), 42);
     /// ```
     #[inline]
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     pub fn map_or_else<U, D: FnOnce() -> U, F: FnOnce(T) -> U>(self, def: D, f: F) -> U {
         match self {
             Some(t) => f(t),
@@ -476,7 +477,7 @@ impl<T> Option<T> {
     /// assert_eq!(x.ok_or(0), Err(0));
     /// ```
     #[inline]
-    #[unstable]
+    #[unstable(feature = "core")]
     pub fn ok_or<E>(self, err: E) -> Result<T, E> {
         match self {
             Some(v) => Ok(v),
@@ -497,7 +498,7 @@ impl<T> Option<T> {
     /// assert_eq!(x.ok_or_else(|| 0), Err(0));
     /// ```
     #[inline]
-    #[unstable]
+    #[unstable(feature = "core")]
     pub fn ok_or_else<E, F: FnOnce() -> E>(self, err: F) -> Result<T, E> {
         match self {
             Some(v) => Ok(v),
@@ -521,7 +522,7 @@ impl<T> Option<T> {
     /// assert_eq!(x.iter().next(), None);
     /// ```
     #[inline]
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     pub fn iter(&self) -> Iter<T> {
         Iter { inner: Item { opt: self.as_ref() } }
     }
@@ -542,7 +543,8 @@ impl<T> Option<T> {
     /// assert_eq!(x.iter_mut().next(), None);
     /// ```
     #[inline]
-    #[unstable = "waiting for iterator conventions"]
+    #[unstable(feature = "core",
+               reason = "waiting for iterator conventions")]
     pub fn iter_mut(&mut self) -> IterMut<T> {
         IterMut { inner: Item { opt: self.as_mut() } }
     }
@@ -561,7 +563,7 @@ impl<T> Option<T> {
     /// assert!(v.is_empty());
     /// ```
     #[inline]
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     pub fn into_iter(self) -> IntoIter<T> {
         IntoIter { inner: Item { opt: self } }
     }
@@ -592,7 +594,7 @@ impl<T> Option<T> {
     /// assert_eq!(x.and(y), None);
     /// ```
     #[inline]
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     pub fn and<U>(self, optb: Option<U>) -> Option<U> {
         match self {
             Some(_) => optb,
@@ -615,7 +617,7 @@ impl<T> Option<T> {
     /// assert_eq!(None.and_then(sq).and_then(sq), None);
     /// ```
     #[inline]
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     pub fn and_then<U, F: FnOnce(T) -> Option<U>>(self, f: F) -> Option<U> {
         match self {
             Some(x) => f(x),
@@ -645,7 +647,7 @@ impl<T> Option<T> {
     /// assert_eq!(x.or(y), None);
     /// ```
     #[inline]
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     pub fn or(self, optb: Option<T>) -> Option<T> {
         match self {
             Some(_) => self,
@@ -667,7 +669,7 @@ impl<T> Option<T> {
     /// assert_eq!(None.or_else(nobody), None);
     /// ```
     #[inline]
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     pub fn or_else<F: FnOnce() -> Option<T>>(self, f: F) -> Option<T> {
         match self {
             Some(_) => self,
@@ -693,7 +695,7 @@ impl<T> Option<T> {
     /// assert_eq!(x, None);
     /// ```
     #[inline]
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     pub fn take(&mut self) -> Option<T> {
         mem::replace(self, None)
     }
@@ -702,7 +704,8 @@ impl<T> Option<T> {
 impl<'a, T: Clone, D: Deref<Target=T>> Option<D> {
     /// Maps an Option<D> to an Option<T> by dereffing and cloning the contents of the Option.
     /// Useful for converting an Option<&T> to an Option<T>.
-    #[unstable = "recently added as part of collections reform"]
+    #[unstable(feature = "core",
+               reason = "recently added as part of collections reform")]
     pub fn cloned(self) -> Option<T> {
         self.map(|t| t.deref().clone())
     }
@@ -732,7 +735,7 @@ impl<T: Default> Option<T> {
     /// assert_eq!(0, bad_year);
     /// ```
     #[inline]
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     pub fn unwrap_or_default(self) -> T {
         match self {
             Some(x) => x,
@@ -745,7 +748,8 @@ impl<T: Default> Option<T> {
 // Trait implementations
 /////////////////////////////////////////////////////////////////////////////
 
-#[unstable = "waiting on the stability of the trait itself"]
+#[unstable(feature = "core",
+           reason = "waiting on the stability of the trait itself")]
 impl<T> AsSlice<T> for Option<T> {
     /// Convert from `Option<T>` to `&[T]` (without copying)
     #[inline]
@@ -760,10 +764,10 @@ impl<T> AsSlice<T> for Option<T> {
     }
 }
 
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl<T> Default for Option<T> {
     #[inline]
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     fn default() -> Option<T> { None }
 }
 
@@ -803,10 +807,10 @@ impl<A> DoubleEndedIterator for Item<A> {
 impl<A> ExactSizeIterator for Item<A> {}
 
 /// An iterator over a reference of the contained item in an Option.
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 pub struct Iter<'a, A: 'a> { inner: Item<&'a A> }
 
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl<'a, A> Iterator for Iter<'a, A> {
     type Item = &'a A;
 
@@ -816,16 +820,16 @@ impl<'a, A> Iterator for Iter<'a, A> {
     fn size_hint(&self) -> (uint, Option<uint>) { self.inner.size_hint() }
 }
 
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl<'a, A> DoubleEndedIterator for Iter<'a, A> {
     #[inline]
     fn next_back(&mut self) -> Option<&'a A> { self.inner.next_back() }
 }
 
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl<'a, A> ExactSizeIterator for Iter<'a, A> {}
 
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl<'a, A> Clone for Iter<'a, A> {
     fn clone(&self) -> Iter<'a, A> {
         Iter { inner: self.inner.clone() }
@@ -833,10 +837,10 @@ impl<'a, A> Clone for Iter<'a, A> {
 }
 
 /// An iterator over a mutable reference of the contained item in an Option.
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 pub struct IterMut<'a, A: 'a> { inner: Item<&'a mut A> }
 
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl<'a, A> Iterator for IterMut<'a, A> {
     type Item = &'a mut A;
 
@@ -846,20 +850,20 @@ impl<'a, A> Iterator for IterMut<'a, A> {
     fn size_hint(&self) -> (uint, Option<uint>) { self.inner.size_hint() }
 }
 
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl<'a, A> DoubleEndedIterator for IterMut<'a, A> {
     #[inline]
     fn next_back(&mut self) -> Option<&'a mut A> { self.inner.next_back() }
 }
 
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl<'a, A> ExactSizeIterator for IterMut<'a, A> {}
 
 /// An iterator over the item contained inside an Option.
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 pub struct IntoIter<A> { inner: Item<A> }
 
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl<A> Iterator for IntoIter<A> {
     type Item = A;
 
@@ -869,20 +873,20 @@ impl<A> Iterator for IntoIter<A> {
     fn size_hint(&self) -> (uint, Option<uint>) { self.inner.size_hint() }
 }
 
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl<A> DoubleEndedIterator for IntoIter<A> {
     #[inline]
     fn next_back(&mut self) -> Option<A> { self.inner.next_back() }
 }
 
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl<A> ExactSizeIterator for IntoIter<A> {}
 
 /////////////////////////////////////////////////////////////////////////////
 // FromIterator
 /////////////////////////////////////////////////////////////////////////////
 
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl<A, V: FromIterator<A>> FromIterator<Option<A>> for Option<V> {
     /// Takes each element in the `Iterator`: if it is `None`, no further
     /// elements are taken, and the `None` is returned. Should no `None` occur, a
@@ -902,7 +906,7 @@ impl<A, V: FromIterator<A>> FromIterator<Option<A>> for Option<V> {
     /// assert!(res == Some(vec!(2, 3)));
     /// ```
     #[inline]
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     fn from_iter<I: Iterator<Item=Option<A>>>(iter: I) -> Option<V> {
         // FIXME(#11084): This could be replaced with Iterator::scan when this
         // performance bug is closed.
diff --git a/src/libcore/ptr.rs b/src/libcore/ptr.rs
index 0b89467d63b..9c18cd0f6d9 100644
--- a/src/libcore/ptr.rs
+++ b/src/libcore/ptr.rs
@@ -86,7 +86,7 @@
 //! but C APIs hand out a lot of pointers generally, so are a common source
 //! of unsafe pointers in Rust.
 
-#![stable]
+#![stable(feature = "rust1", since = "1.0.0")]
 
 use mem;
 use clone::Clone;
@@ -99,13 +99,14 @@ use cmp::Ordering::{self, Less, Equal, Greater};
 
 // FIXME #19649: intrinsic docs don't render, so these have no docs :(
 
-#[unstable]
+#[unstable(feature = "core")]
 pub use intrinsics::copy_nonoverlapping_memory;
 
-#[unstable]
+#[unstable(feature = "core")]
 pub use intrinsics::copy_memory;
 
-#[unstable = "uncertain about naming and semantics"]
+#[unstable(feature = "core",
+           reason = "uncertain about naming and semantics")]
 pub use intrinsics::set_memory;
 
 
@@ -120,7 +121,7 @@ pub use intrinsics::set_memory;
 /// assert!(p.is_null());
 /// ```
 #[inline]
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 pub fn null<T>() -> *const T { 0 as *const T }
 
 /// Creates a null mutable raw pointer.
@@ -134,7 +135,7 @@ pub fn null<T>() -> *const T { 0 as *const T }
 /// assert!(p.is_null());
 /// ```
 #[inline]
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 pub fn null_mut<T>() -> *mut T { 0 as *mut T }
 
 /// Zeroes out `count * size_of::<T>` bytes of memory at `dst`. `count` may be
@@ -145,7 +146,8 @@ pub fn null_mut<T>() -> *mut T { 0 as *mut T }
 /// Beyond accepting a raw pointer, this is unsafe because it will not drop the
 /// contents of `dst`, and may be used to create invalid instances of `T`.
 #[inline]
-#[unstable = "may play a larger role in std::ptr future extensions"]
+#[unstable(feature = "core",
+           reason = "may play a larger role in std::ptr future extensions")]
 pub unsafe fn zero_memory<T>(dst: *mut T, count: uint) {
     set_memory(dst, 0, count);
 }
@@ -158,7 +160,7 @@ pub unsafe fn zero_memory<T>(dst: *mut T, count: uint) {
 ///
 /// This is only unsafe because it accepts a raw pointer.
 #[inline]
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 pub unsafe fn swap<T>(x: *mut T, y: *mut T) {
     // Give ourselves some scratch space to work with
     let mut tmp: T = mem::uninitialized();
@@ -182,7 +184,7 @@ pub unsafe fn swap<T>(x: *mut T, y: *mut T) {
 /// This is only unsafe because it accepts a raw pointer.
 /// Otherwise, this operation is identical to `mem::replace`.
 #[inline]
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 pub unsafe fn replace<T>(dest: *mut T, mut src: T) -> T {
     mem::swap(mem::transmute(dest), &mut src); // cannot overlap
     src
@@ -200,7 +202,7 @@ pub unsafe fn replace<T>(dest: *mut T, mut src: T) -> T {
 /// `zero_memory`, or `copy_memory`). Note that `*src = foo` counts as a use
 /// because it will attempt to drop the value previously at `*src`.
 #[inline(always)]
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 pub unsafe fn read<T>(src: *const T) -> T {
     let mut tmp: T = mem::uninitialized();
     copy_nonoverlapping_memory(&mut tmp, src, 1);
@@ -213,7 +215,8 @@ pub unsafe fn read<T>(src: *const T) -> T {
 ///
 /// This is unsafe for the same reasons that `read` is unsafe.
 #[inline(always)]
-#[unstable = "may play a larger role in std::ptr future extensions"]
+#[unstable(feature = "core",
+           reason = "may play a larger role in std::ptr future extensions")]
 pub unsafe fn read_and_zero<T>(dest: *mut T) -> T {
     // Copy the data out from `dest`:
     let tmp = read(&*dest);
@@ -236,18 +239,18 @@ pub unsafe fn read_and_zero<T>(dest: *mut T) -> T {
 /// This is appropriate for initializing uninitialized memory, or overwriting
 /// memory that has previously been `read` from.
 #[inline]
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 pub unsafe fn write<T>(dst: *mut T, src: T) {
     intrinsics::move_val_init(&mut *dst, src)
 }
 
 /// Methods on raw pointers
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 pub trait PtrExt: Sized {
     type Target;
 
     /// Returns true if the pointer is null.
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     fn is_null(self) -> bool;
 
     /// Returns `None` if the pointer is null, or else returns a reference to
@@ -259,8 +262,9 @@ pub trait PtrExt: Sized {
     /// null-safety, it is important to note that this is still an unsafe
     /// operation because the returned value could be pointing to invalid
     /// memory.
-    #[unstable = "Option is not clearly the right return type, and we may want \
-                  to tie the return lifetime to a borrow of the raw pointer"]
+    #[unstable(feature = "core",
+               reason = "Option is not clearly the right return type, and we may want \
+                         to tie the return lifetime to a borrow of the raw pointer")]
     unsafe fn as_ref<'a>(&self) -> Option<&'a Self::Target>;
 
     /// Calculates the offset from a pointer. `count` is in units of T; e.g. a
@@ -271,12 +275,12 @@ pub trait PtrExt: Sized {
     /// The offset must be in-bounds of the object, or one-byte-past-the-end.
     /// Otherwise `offset` invokes Undefined Behaviour, regardless of whether
     /// the pointer is used.
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     unsafe fn offset(self, count: int) -> Self;
 }
 
 /// Methods on mutable raw pointers
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 pub trait MutPtrExt {
     type Target;
 
@@ -287,28 +291,30 @@ pub trait MutPtrExt {
     ///
     /// As with `as_ref`, this is unsafe because it cannot verify the validity
     /// of the returned pointer.
-    #[unstable = "Option is not clearly the right return type, and we may want \
-                  to tie the return lifetime to a borrow of the raw pointer"]
+    #[unstable(feature = "core",
+               reason = "Option is not clearly the right return type, and we may want \
+                         to tie the return lifetime to a borrow of the raw pointer")]
     unsafe fn as_mut<'a>(&self) -> Option<&'a mut Self::Target>;
 }
 
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl<T> PtrExt for *const T {
     type Target = T;
 
     #[inline]
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     fn is_null(self) -> bool { self as uint == 0 }
 
     #[inline]
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     unsafe fn offset(self, count: int) -> *const T {
         intrinsics::offset(self, count)
     }
 
     #[inline]
-    #[unstable = "return value does not necessarily convey all possible \
-                  information"]
+    #[unstable(feature = "core",
+               reason = "return value does not necessarily convey all possible \
+                         information")]
     unsafe fn as_ref<'a>(&self) -> Option<&'a T> {
         if self.is_null() {
             None
@@ -318,23 +324,24 @@ impl<T> PtrExt for *const T {
     }
 }
 
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl<T> PtrExt for *mut T {
     type Target = T;
 
     #[inline]
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     fn is_null(self) -> bool { self as uint == 0 }
 
     #[inline]
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     unsafe fn offset(self, count: int) -> *mut T {
         intrinsics::offset(self, count) as *mut T
     }
 
     #[inline]
-    #[unstable = "return value does not necessarily convey all possible \
-                  information"]
+    #[unstable(feature = "core",
+               reason = "return value does not necessarily convey all possible \
+                         information")]
     unsafe fn as_ref<'a>(&self) -> Option<&'a T> {
         if self.is_null() {
             None
@@ -344,13 +351,14 @@ impl<T> PtrExt for *mut T {
     }
 }
 
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl<T> MutPtrExt for *mut T {
     type Target = T;
 
     #[inline]
-    #[unstable = "return value does not necessarily convey all possible \
-                  information"]
+    #[unstable(feature = "core",
+               reason = "return value does not necessarily convey all possible \
+                         information")]
     unsafe fn as_mut<'a>(&self) -> Option<&'a mut T> {
         if self.is_null() {
             None
@@ -361,7 +369,7 @@ impl<T> MutPtrExt for *mut T {
 }
 
 // Equality for pointers
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl<T> PartialEq for *const T {
     #[inline]
     fn eq(&self, other: &*const T) -> bool {
@@ -371,10 +379,10 @@ impl<T> PartialEq for *const T {
     fn ne(&self, other: &*const T) -> bool { !self.eq(other) }
 }
 
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl<T> Eq for *const T {}
 
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl<T> PartialEq for *mut T {
     #[inline]
     fn eq(&self, other: &*mut T) -> bool {
@@ -384,10 +392,10 @@ impl<T> PartialEq for *mut T {
     fn ne(&self, other: &*mut T) -> bool { !self.eq(other) }
 }
 
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl<T> Eq for *mut T {}
 
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl<T> Clone for *const T {
     #[inline]
     fn clone(&self) -> *const T {
@@ -395,7 +403,7 @@ impl<T> Clone for *const T {
     }
 }
 
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl<T> Clone for *mut T {
     #[inline]
     fn clone(&self) -> *mut T {
@@ -408,7 +416,7 @@ mod externfnpointers {
     use mem;
     use cmp::PartialEq;
 
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     impl<_R> PartialEq for extern "C" fn() -> _R {
         #[inline]
         fn eq(&self, other: &extern "C" fn() -> _R) -> bool {
@@ -419,7 +427,7 @@ mod externfnpointers {
     }
     macro_rules! fnptreq {
         ($($p:ident),*) => {
-            #[stable]
+            #[stable(feature = "rust1", since = "1.0.0")]
             impl<_R,$($p),*> PartialEq for extern "C" fn($($p),*) -> _R {
                 #[inline]
                 fn eq(&self, other: &extern "C" fn($($p),*) -> _R) -> bool {
@@ -439,7 +447,7 @@ mod externfnpointers {
 }
 
 // Comparison for pointers
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl<T> Ord for *const T {
     #[inline]
     fn cmp(&self, other: &*const T) -> Ordering {
@@ -453,7 +461,7 @@ impl<T> Ord for *const T {
     }
 }
 
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl<T> PartialOrd for *const T {
     #[inline]
     fn partial_cmp(&self, other: &*const T) -> Option<Ordering> {
@@ -473,7 +481,7 @@ impl<T> PartialOrd for *const T {
     fn ge(&self, other: &*const T) -> bool { *self >= *other }
 }
 
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl<T> Ord for *mut T {
     #[inline]
     fn cmp(&self, other: &*mut T) -> Ordering {
@@ -487,7 +495,7 @@ impl<T> Ord for *mut T {
     }
 }
 
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl<T> PartialOrd for *mut T {
     #[inline]
     fn partial_cmp(&self, other: &*mut T) -> Option<Ordering> {
@@ -513,32 +521,34 @@ impl<T> PartialOrd for *mut T {
 /// raw `*mut T` (which conveys no particular ownership semantics).
 /// Useful for building abstractions like `Vec<T>` or `Box<T>`, which
 /// internally use raw pointers to manage the memory that they own.
-#[unstable = "recently added to this module"]
+#[unstable(feature = "core", reason = "recently added to this module")]
 pub struct Unique<T>(pub *mut T);
 
 /// `Unique` pointers are `Send` if `T` is `Send` because the data they
 /// reference is unaliased. Note that this aliasing invariant is
 /// unenforced by the type system; the abstraction using the
 /// `Unique` must enforce it.
-#[unstable = "recently added to this module"]
+#[unstable(feature = "core", reason = "recently added to this module")]
 unsafe impl<T:Send> Send for Unique<T> { }
 
 /// `Unique` pointers are `Sync` if `T` is `Sync` because the data they
 /// reference is unaliased. Note that this aliasing invariant is
 /// unenforced by the type system; the abstraction using the
 /// `Unique` must enforce it.
-#[unstable = "recently added to this module"]
+#[unstable(feature = "core", reason = "recently added to this module")]
 unsafe impl<T:Sync> Sync for Unique<T> { }
 
 impl<T> Unique<T> {
     /// Returns a null Unique.
-    #[unstable = "recently added to this module"]
+    #[unstable(feature = "core",
+               reason = "recently added to this module")]
     pub fn null() -> Unique<T> {
         Unique(null_mut())
     }
 
     /// Return an (unsafe) pointer into the memory owned by `self`.
-    #[unstable = "recently added to this module"]
+    #[unstable(feature = "core",
+               reason = "recently added to this module")]
     pub unsafe fn offset(self, offset: int) -> *mut T {
         self.0.offset(offset)
     }
diff --git a/src/libcore/raw.rs b/src/libcore/raw.rs
index 13a387c7cb0..3fd244b46e3 100644
--- a/src/libcore/raw.rs
+++ b/src/libcore/raw.rs
@@ -9,7 +9,7 @@
 // except according to those terms.
 
 #![allow(missing_docs)]
-#![unstable]
+#![unstable(feature = "core")]
 
 //! Contains struct definitions for the layout of compiler built-in types.
 //!
diff --git a/src/libcore/result.rs b/src/libcore/result.rs
index 28463c0f04c..ade257165c6 100644
--- a/src/libcore/result.rs
+++ b/src/libcore/result.rs
@@ -224,7 +224,7 @@
 //!
 //! `try!` is imported by the prelude, and is available everywhere.
 
-#![stable]
+#![stable(feature = "rust1", since = "1.0.0")]
 
 use self::Result::{Ok, Err};
 
@@ -241,14 +241,14 @@ use slice;
 /// See the [`std::result`](index.html) module documentation for details.
 #[derive(Clone, Copy, PartialEq, PartialOrd, Eq, Ord, Show, Hash)]
 #[must_use]
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 pub enum Result<T, E> {
     /// Contains the success value
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     Ok(T),
 
     /// Contains the error value
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     Err(E)
 }
 
@@ -256,7 +256,7 @@ pub enum Result<T, E> {
 // Type implementation
 /////////////////////////////////////////////////////////////////////////////
 
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl<T, E> Result<T, E> {
     /////////////////////////////////////////////////////////////////////////
     // Querying the contained values
@@ -274,7 +274,7 @@ impl<T, E> Result<T, E> {
     /// assert_eq!(x.is_ok(), false);
     /// ```
     #[inline]
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     pub fn is_ok(&self) -> bool {
         match *self {
             Ok(_) => true,
@@ -294,7 +294,7 @@ impl<T, E> Result<T, E> {
     /// assert_eq!(x.is_err(), true);
     /// ```
     #[inline]
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     pub fn is_err(&self) -> bool {
         !self.is_ok()
     }
@@ -318,7 +318,7 @@ impl<T, E> Result<T, E> {
     /// assert_eq!(x.ok(), None);
     /// ```
     #[inline]
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     pub fn ok(self) -> Option<T> {
         match self {
             Ok(x)  => Some(x),
@@ -341,7 +341,7 @@ impl<T, E> Result<T, E> {
     /// assert_eq!(x.err(), Some("Nothing here"));
     /// ```
     #[inline]
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     pub fn err(self) -> Option<E> {
         match self {
             Ok(_)  => None,
@@ -366,7 +366,7 @@ impl<T, E> Result<T, E> {
     /// assert_eq!(x.as_ref(), Err(&"Error"));
     /// ```
     #[inline]
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     pub fn as_ref(&self) -> Result<&T, &E> {
         match *self {
             Ok(ref x) => Ok(x),
@@ -393,7 +393,7 @@ impl<T, E> Result<T, E> {
     /// assert_eq!(x.unwrap_err(), 0);
     /// ```
     #[inline]
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     pub fn as_mut(&mut self) -> Result<&mut T, &mut E> {
         match *self {
             Ok(ref mut x) => Ok(x),
@@ -417,7 +417,8 @@ impl<T, E> Result<T, E> {
     /// assert!(x.as_mut_slice().is_empty());
     /// ```
     #[inline]
-    #[unstable = "waiting for mut conventions"]
+    #[unstable(feature = "core",
+               reason = "waiting for mut conventions")]
     pub fn as_mut_slice(&mut self) -> &mut [T] {
         match *self {
             Ok(ref mut x) => slice::mut_ref_slice(x),
@@ -463,7 +464,7 @@ impl<T, E> Result<T, E> {
     /// assert!(sum == 10);
     /// ```
     #[inline]
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     pub fn map<U, F: FnOnce(T) -> U>(self, op: F) -> Result<U,E> {
         match self {
             Ok(t) => Ok(op(t)),
@@ -489,7 +490,7 @@ impl<T, E> Result<T, E> {
     /// assert_eq!(x.map_err(stringify), Err("error code: 13".to_string()));
     /// ```
     #[inline]
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     pub fn map_err<F, O: FnOnce(E) -> F>(self, op: O) -> Result<T,F> {
         match self {
             Ok(t) => Ok(t),
@@ -513,7 +514,7 @@ impl<T, E> Result<T, E> {
     /// assert_eq!(x.iter().next(), None);
     /// ```
     #[inline]
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     pub fn iter(&self) -> Iter<T> {
         Iter { inner: self.as_ref().ok() }
     }
@@ -534,7 +535,7 @@ impl<T, E> Result<T, E> {
     /// assert_eq!(x.iter_mut().next(), None);
     /// ```
     #[inline]
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     pub fn iter_mut(&mut self) -> IterMut<T> {
         IterMut { inner: self.as_mut().ok() }
     }
@@ -553,7 +554,7 @@ impl<T, E> Result<T, E> {
     /// assert_eq!(v, vec![]);
     /// ```
     #[inline]
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     pub fn into_iter(self) -> IntoIter<T> {
         IntoIter { inner: self.ok() }
     }
@@ -584,7 +585,7 @@ impl<T, E> Result<T, E> {
     /// assert_eq!(x.and(y), Ok("different result type"));
     /// ```
     #[inline]
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     pub fn and<U>(self, res: Result<U, E>) -> Result<U, E> {
         match self {
             Ok(_) => res,
@@ -608,7 +609,7 @@ impl<T, E> Result<T, E> {
     /// assert_eq!(Err(3).and_then(sq).and_then(sq), Err(3));
     /// ```
     #[inline]
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     pub fn and_then<U, F: FnOnce(T) -> Result<U, E>>(self, op: F) -> Result<U, E> {
         match self {
             Ok(t) => op(t),
@@ -638,7 +639,7 @@ impl<T, E> Result<T, E> {
     /// assert_eq!(x.or(y), Ok(2));
     /// ```
     #[inline]
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     pub fn or(self, res: Result<T, E>) -> Result<T, E> {
         match self {
             Ok(_) => self,
@@ -662,7 +663,7 @@ impl<T, E> Result<T, E> {
     /// assert_eq!(Err(3).or_else(err).or_else(err), Err(3));
     /// ```
     #[inline]
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     pub fn or_else<F, O: FnOnce(E) -> Result<T, F>>(self, op: O) -> Result<T, F> {
         match self {
             Ok(t) => Ok(t),
@@ -684,7 +685,7 @@ impl<T, E> Result<T, E> {
     /// assert_eq!(x.unwrap_or(optb), optb);
     /// ```
     #[inline]
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     pub fn unwrap_or(self, optb: T) -> T {
         match self {
             Ok(t) => t,
@@ -704,7 +705,7 @@ impl<T, E> Result<T, E> {
     /// assert_eq!(Err("foo").unwrap_or_else(count), 3);
     /// ```
     #[inline]
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     pub fn unwrap_or_else<F: FnOnce(E) -> T>(self, op: F) -> T {
         match self {
             Ok(t) => t,
@@ -713,7 +714,7 @@ impl<T, E> Result<T, E> {
     }
 }
 
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl<T, E: Debug> Result<T, E> {
     /// Unwraps a result, yielding the content of an `Ok`.
     ///
@@ -734,7 +735,7 @@ impl<T, E: Debug> Result<T, E> {
     /// x.unwrap(); // panics with `emergency failure`
     /// ```
     #[inline]
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     pub fn unwrap(self) -> T {
         match self {
             Ok(t) => t,
@@ -744,7 +745,7 @@ impl<T, E: Debug> Result<T, E> {
     }
 }
 
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl<T: Debug, E> Result<T, E> {
     /// Unwraps a result, yielding the content of an `Err`.
     ///
@@ -765,7 +766,7 @@ impl<T: Debug, E> Result<T, E> {
     /// assert_eq!(x.unwrap_err(), "emergency failure");
     /// ```
     #[inline]
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     pub fn unwrap_err(self) -> E {
         match self {
             Ok(t) =>
@@ -782,7 +783,7 @@ impl<T: Debug, E> Result<T, E> {
 impl<T, E> AsSlice<T> for Result<T, E> {
     /// Convert from `Result<T, E>` to `&[T]` (without copying)
     #[inline]
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     fn as_slice<'a>(&'a self) -> &'a [T] {
         match *self {
             Ok(ref x) => slice::ref_slice(x),
@@ -800,10 +801,10 @@ impl<T, E> AsSlice<T> for Result<T, E> {
 /////////////////////////////////////////////////////////////////////////////
 
 /// An iterator over a reference to the `Ok` variant of a `Result`.
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 pub struct Iter<'a, T: 'a> { inner: Option<&'a T> }
 
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl<'a, T> Iterator for Iter<'a, T> {
     type Item = &'a T;
 
@@ -816,13 +817,13 @@ impl<'a, T> Iterator for Iter<'a, T> {
     }
 }
 
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl<'a, T> DoubleEndedIterator for Iter<'a, T> {
     #[inline]
     fn next_back(&mut self) -> Option<&'a T> { self.inner.take() }
 }
 
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl<'a, T> ExactSizeIterator for Iter<'a, T> {}
 
 impl<'a, T> Clone for Iter<'a, T> {
@@ -830,10 +831,10 @@ impl<'a, T> Clone for Iter<'a, T> {
 }
 
 /// An iterator over a mutable reference to the `Ok` variant of a `Result`.
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 pub struct IterMut<'a, T: 'a> { inner: Option<&'a mut T> }
 
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl<'a, T> Iterator for IterMut<'a, T> {
     type Item = &'a mut T;
 
@@ -846,20 +847,20 @@ impl<'a, T> Iterator for IterMut<'a, T> {
     }
 }
 
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl<'a, T> DoubleEndedIterator for IterMut<'a, T> {
     #[inline]
     fn next_back(&mut self) -> Option<&'a mut T> { self.inner.take() }
 }
 
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl<'a, T> ExactSizeIterator for IterMut<'a, T> {}
 
 /// An iterator over the value in a `Ok` variant of a `Result`.
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 pub struct IntoIter<T> { inner: Option<T> }
 
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl<T> Iterator for IntoIter<T> {
     type Item = T;
 
@@ -872,20 +873,20 @@ impl<T> Iterator for IntoIter<T> {
     }
 }
 
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl<T> DoubleEndedIterator for IntoIter<T> {
     #[inline]
     fn next_back(&mut self) -> Option<T> { self.inner.take() }
 }
 
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl<T> ExactSizeIterator for IntoIter<T> {}
 
 /////////////////////////////////////////////////////////////////////////////
 // FromIterator
 /////////////////////////////////////////////////////////////////////////////
 
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl<A, E, V: FromIterator<A>> FromIterator<Result<A, E>> for Result<V, E> {
     /// Takes each element in the `Iterator`: if it is an `Err`, no further
     /// elements are taken, and the `Err` is returned. Should no `Err` occur, a
@@ -949,7 +950,7 @@ impl<A, E, V: FromIterator<A>> FromIterator<Result<A, E>> for Result<V, E> {
 /// If an `Err` is encountered, it is immediately returned.
 /// Otherwise, the folded value is returned.
 #[inline]
-#[unstable]
+#[unstable(feature = "core")]
 pub fn fold<T,
             V,
             E,
diff --git a/src/libcore/simd.rs b/src/libcore/simd.rs
index b73910d7c06..4a1c123668f 100644
--- a/src/libcore/simd.rs
+++ b/src/libcore/simd.rs
@@ -19,7 +19,6 @@
 //! provided beyond this module.
 //!
 //! ```rust
-//! #[allow(unstable)];
 //!
 //! fn main() {
 //!     use std::simd::f32x4;
@@ -37,7 +36,7 @@
 #![allow(non_camel_case_types)]
 #![allow(missing_docs)]
 
-#[unstable]
+#[unstable(feature = "core")]
 #[simd]
 #[derive(Copy, Show)]
 #[repr(C)]
@@ -46,26 +45,26 @@ pub struct i8x16(pub i8, pub i8, pub i8, pub i8,
                  pub i8, pub i8, pub i8, pub i8,
                  pub i8, pub i8, pub i8, pub i8);
 
-#[unstable]
+#[unstable(feature = "core")]
 #[simd]
 #[derive(Copy, Show)]
 #[repr(C)]
 pub struct i16x8(pub i16, pub i16, pub i16, pub i16,
                  pub i16, pub i16, pub i16, pub i16);
 
-#[unstable]
+#[unstable(feature = "core")]
 #[simd]
 #[derive(Copy, Show)]
 #[repr(C)]
 pub struct i32x4(pub i32, pub i32, pub i32, pub i32);
 
-#[unstable]
+#[unstable(feature = "core")]
 #[simd]
 #[derive(Copy, Show)]
 #[repr(C)]
 pub struct i64x2(pub i64, pub i64);
 
-#[unstable]
+#[unstable(feature = "core")]
 #[simd]
 #[derive(Copy, Show)]
 #[repr(C)]
@@ -74,32 +73,32 @@ pub struct u8x16(pub u8, pub u8, pub u8, pub u8,
                  pub u8, pub u8, pub u8, pub u8,
                  pub u8, pub u8, pub u8, pub u8);
 
-#[unstable]
+#[unstable(feature = "core")]
 #[simd]
 #[derive(Copy, Show)]
 #[repr(C)]
 pub struct u16x8(pub u16, pub u16, pub u16, pub u16,
                  pub u16, pub u16, pub u16, pub u16);
 
-#[unstable]
+#[unstable(feature = "core")]
 #[simd]
 #[derive(Copy, Show)]
 #[repr(C)]
 pub struct u32x4(pub u32, pub u32, pub u32, pub u32);
 
-#[unstable]
+#[unstable(feature = "core")]
 #[simd]
 #[derive(Copy, Show)]
 #[repr(C)]
 pub struct u64x2(pub u64, pub u64);
 
-#[unstable]
+#[unstable(feature = "core")]
 #[simd]
 #[derive(Copy, Show)]
 #[repr(C)]
 pub struct f32x4(pub f32, pub f32, pub f32, pub f32);
 
-#[unstable]
+#[unstable(feature = "core")]
 #[simd]
 #[derive(Copy, Show)]
 #[repr(C)]
diff --git a/src/libcore/slice.rs b/src/libcore/slice.rs
index f08978db8fe..a113a34ef35 100644
--- a/src/libcore/slice.rs
+++ b/src/libcore/slice.rs
@@ -12,7 +12,7 @@
 //!
 //! For more details `std::slice`.
 
-#![stable]
+#![stable(feature = "rust1", since = "1.0.0")]
 #![doc(primitive = "slice")]
 
 // How this module is organized.
@@ -125,7 +125,7 @@ pub trait SliceExt {
     fn clone_from_slice(&mut self, &[Self::Item]) -> uint where Self::Item: Clone;
 }
 
-#[unstable]
+#[unstable(feature = "core")]
 impl<T> SliceExt for [T] {
     type Item = T;
 
@@ -230,7 +230,7 @@ impl<T> SliceExt for [T] {
         self.repr().data
     }
 
-    #[unstable]
+    #[unstable(feature = "core")]
     fn binary_search_by<F>(&self, mut f: F) -> Result<uint, uint> where
         F: FnMut(&T) -> Ordering
     {
@@ -410,12 +410,12 @@ impl<T> SliceExt for [T] {
         m >= n && needle == &self[m-n..]
     }
 
-    #[unstable]
+    #[unstable(feature = "core")]
     fn binary_search(&self, x: &T) -> Result<uint, uint> where T: Ord {
         self.binary_search_by(|p| p.cmp(x))
     }
 
-    #[unstable]
+    #[unstable(feature = "core")]
     fn next_permutation(&mut self) -> bool where T: Ord {
         // These cases only have 1 permutation each, so we can't do anything.
         if self.len() < 2 { return false; }
@@ -446,7 +446,7 @@ impl<T> SliceExt for [T] {
         true
     }
 
-    #[unstable]
+    #[unstable(feature = "core")]
     fn prev_permutation(&mut self) -> bool where T: Ord {
         // These cases only have 1 permutation each, so we can't do anything.
         if self.len() < 2 { return false; }
@@ -489,7 +489,7 @@ impl<T> SliceExt for [T] {
     }
 }
 
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl<T> ops::Index<uint> for [T] {
     type Output = T;
 
@@ -500,7 +500,7 @@ impl<T> ops::Index<uint> for [T] {
     }
 }
 
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl<T> ops::IndexMut<uint> for [T] {
     type Output = T;
 
@@ -511,7 +511,7 @@ impl<T> ops::IndexMut<uint> for [T] {
     }
 }
 
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl<T> ops::Index<ops::Range<uint>> for [T] {
     type Output = [T];
     #[inline]
@@ -526,7 +526,7 @@ impl<T> ops::Index<ops::Range<uint>> for [T] {
         }
     }
 }
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl<T> ops::Index<ops::RangeTo<uint>> for [T] {
     type Output = [T];
     #[inline]
@@ -534,7 +534,7 @@ impl<T> ops::Index<ops::RangeTo<uint>> for [T] {
         self.index(&ops::Range{ start: 0, end: index.end })
     }
 }
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl<T> ops::Index<ops::RangeFrom<uint>> for [T] {
     type Output = [T];
     #[inline]
@@ -542,7 +542,7 @@ impl<T> ops::Index<ops::RangeFrom<uint>> for [T] {
         self.index(&ops::Range{ start: index.start, end: self.len() })
     }
 }
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl<T> ops::Index<ops::FullRange> for [T] {
     type Output = [T];
     #[inline]
@@ -551,7 +551,7 @@ impl<T> ops::Index<ops::FullRange> for [T] {
     }
 }
 
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl<T> ops::IndexMut<ops::Range<uint>> for [T] {
     type Output = [T];
     #[inline]
@@ -566,7 +566,7 @@ impl<T> ops::IndexMut<ops::Range<uint>> for [T] {
         }
     }
 }
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl<T> ops::IndexMut<ops::RangeTo<uint>> for [T] {
     type Output = [T];
     #[inline]
@@ -574,7 +574,7 @@ impl<T> ops::IndexMut<ops::RangeTo<uint>> for [T] {
         self.index_mut(&ops::Range{ start: 0, end: index.end })
     }
 }
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl<T> ops::IndexMut<ops::RangeFrom<uint>> for [T] {
     type Output = [T];
     #[inline]
@@ -583,7 +583,7 @@ impl<T> ops::IndexMut<ops::RangeFrom<uint>> for [T] {
         self.index_mut(&ops::Range{ start: index.start, end: len })
     }
 }
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl<T> ops::IndexMut<ops::FullRange> for [T] {
     type Output = [T];
     #[inline]
@@ -598,33 +598,34 @@ impl<T> ops::IndexMut<ops::FullRange> for [T] {
 ////////////////////////////////////////////////////////////////////////////////
 
 /// Data that is viewable as a slice.
-#[unstable = "will be replaced by slice syntax"]
+#[unstable(feature = "core",
+           reason = "will be replaced by slice syntax")]
 pub trait AsSlice<T> {
     /// Work with `self` as a slice.
     fn as_slice<'a>(&'a self) -> &'a [T];
 }
 
-#[unstable = "trait is experimental"]
+#[unstable(feature = "core", reason = "trait is experimental")]
 impl<T> AsSlice<T> for [T] {
     #[inline(always)]
     fn as_slice<'a>(&'a self) -> &'a [T] { self }
 }
 
-#[unstable = "trait is experimental"]
+#[unstable(feature = "core", reason = "trait is experimental")]
 impl<'a, T, U: ?Sized + AsSlice<T>> AsSlice<T> for &'a U {
     #[inline(always)]
     fn as_slice(&self) -> &[T] { AsSlice::as_slice(*self) }
 }
 
-#[unstable = "trait is experimental"]
+#[unstable(feature = "core", reason = "trait is experimental")]
 impl<'a, T, U: ?Sized + AsSlice<T>> AsSlice<T> for &'a mut U {
     #[inline(always)]
     fn as_slice(&self) -> &[T] { AsSlice::as_slice(*self) }
 }
 
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl<'a, T> Default for &'a [T] {
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     fn default() -> &'a [T] { &[] }
 }
 
@@ -635,7 +636,7 @@ impl<'a, T> Default for &'a [T] {
 // The shared definition of the `Iter` and `IterMut` iterators
 macro_rules! iterator {
     (struct $name:ident -> $ptr:ty, $elem:ty) => {
-        #[stable]
+        #[stable(feature = "rust1", since = "1.0.0")]
         impl<'a, T> Iterator for $name<'a, T> {
             type Item = $elem;
 
@@ -673,7 +674,7 @@ macro_rules! iterator {
             }
         }
 
-        #[stable]
+        #[stable(feature = "rust1", since = "1.0.0")]
         impl<'a, T> DoubleEndedIterator for $name<'a, T> {
             #[inline]
             fn next_back(&mut self) -> Option<$elem> {
@@ -715,14 +716,14 @@ macro_rules! make_slice {
 }
 
 /// Immutable slice iterator
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 pub struct Iter<'a, T: 'a> {
     ptr: *const T,
     end: *const T,
     marker: marker::ContravariantLifetime<'a>
 }
 
-#[unstable]
+#[unstable(feature = "core")]
 impl<'a, T> ops::Index<ops::Range<uint>> for Iter<'a, T> {
     type Output = [T];
     #[inline]
@@ -731,7 +732,7 @@ impl<'a, T> ops::Index<ops::Range<uint>> for Iter<'a, T> {
     }
 }
 
-#[unstable]
+#[unstable(feature = "core")]
 impl<'a, T> ops::Index<ops::RangeTo<uint>> for Iter<'a, T> {
     type Output = [T];
     #[inline]
@@ -740,7 +741,7 @@ impl<'a, T> ops::Index<ops::RangeTo<uint>> for Iter<'a, T> {
     }
 }
 
-#[unstable]
+#[unstable(feature = "core")]
 impl<'a, T> ops::Index<ops::RangeFrom<uint>> for Iter<'a, T> {
     type Output = [T];
     #[inline]
@@ -749,7 +750,7 @@ impl<'a, T> ops::Index<ops::RangeFrom<uint>> for Iter<'a, T> {
     }
 }
 
-#[unstable]
+#[unstable(feature = "core")]
 impl<'a, T> ops::Index<ops::FullRange> for Iter<'a, T> {
     type Output = [T];
     #[inline]
@@ -763,7 +764,7 @@ impl<'a, T> Iter<'a, T> {
     ///
     /// This has the same lifetime as the original slice, and so the
     /// iterator can continue to be used while this exists.
-    #[unstable]
+    #[unstable(feature = "core")]
     pub fn as_slice(&self) -> &'a [T] {
         make_slice!(T => &'a [T]: self.ptr, self.end)
     }
@@ -773,15 +774,15 @@ impl<'a,T> Copy for Iter<'a,T> {}
 
 iterator!{struct Iter -> *const T, &'a T}
 
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl<'a, T> ExactSizeIterator for Iter<'a, T> {}
 
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl<'a, T> Clone for Iter<'a, T> {
     fn clone(&self) -> Iter<'a, T> { *self }
 }
 
-#[unstable = "trait is experimental"]
+#[unstable(feature = "core", reason = "trait is experimental")]
 impl<'a, T> RandomAccessIterator for Iter<'a, T> {
     #[inline]
     fn indexable(&self) -> uint {
@@ -807,7 +808,7 @@ impl<'a, T> RandomAccessIterator for Iter<'a, T> {
 }
 
 /// Mutable slice iterator.
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 pub struct IterMut<'a, T: 'a> {
     ptr: *mut T,
     end: *mut T,
@@ -815,7 +816,7 @@ pub struct IterMut<'a, T: 'a> {
 }
 
 
-#[unstable]
+#[unstable(feature = "core")]
 impl<'a, T> ops::Index<ops::Range<uint>> for IterMut<'a, T> {
     type Output = [T];
     #[inline]
@@ -823,7 +824,7 @@ impl<'a, T> ops::Index<ops::Range<uint>> for IterMut<'a, T> {
         self.index(&ops::FullRange).index(index)
     }
 }
-#[unstable]
+#[unstable(feature = "core")]
 impl<'a, T> ops::Index<ops::RangeTo<uint>> for IterMut<'a, T> {
     type Output = [T];
     #[inline]
@@ -831,7 +832,7 @@ impl<'a, T> ops::Index<ops::RangeTo<uint>> for IterMut<'a, T> {
         self.index(&ops::FullRange).index(index)
     }
 }
-#[unstable]
+#[unstable(feature = "core")]
 impl<'a, T> ops::Index<ops::RangeFrom<uint>> for IterMut<'a, T> {
     type Output = [T];
     #[inline]
@@ -839,7 +840,7 @@ impl<'a, T> ops::Index<ops::RangeFrom<uint>> for IterMut<'a, T> {
         self.index(&ops::FullRange).index(index)
     }
 }
-#[unstable]
+#[unstable(feature = "core")]
 impl<'a, T> ops::Index<ops::FullRange> for IterMut<'a, T> {
     type Output = [T];
     #[inline]
@@ -848,7 +849,7 @@ impl<'a, T> ops::Index<ops::FullRange> for IterMut<'a, T> {
     }
 }
 
-#[unstable]
+#[unstable(feature = "core")]
 impl<'a, T> ops::IndexMut<ops::Range<uint>> for IterMut<'a, T> {
     type Output = [T];
     #[inline]
@@ -856,7 +857,7 @@ impl<'a, T> ops::IndexMut<ops::Range<uint>> for IterMut<'a, T> {
         self.index_mut(&ops::FullRange).index_mut(index)
     }
 }
-#[unstable]
+#[unstable(feature = "core")]
 impl<'a, T> ops::IndexMut<ops::RangeTo<uint>> for IterMut<'a, T> {
     type Output = [T];
     #[inline]
@@ -864,7 +865,7 @@ impl<'a, T> ops::IndexMut<ops::RangeTo<uint>> for IterMut<'a, T> {
         self.index_mut(&ops::FullRange).index_mut(index)
     }
 }
-#[unstable]
+#[unstable(feature = "core")]
 impl<'a, T> ops::IndexMut<ops::RangeFrom<uint>> for IterMut<'a, T> {
     type Output = [T];
     #[inline]
@@ -872,7 +873,7 @@ impl<'a, T> ops::IndexMut<ops::RangeFrom<uint>> for IterMut<'a, T> {
         self.index_mut(&ops::FullRange).index_mut(index)
     }
 }
-#[unstable]
+#[unstable(feature = "core")]
 impl<'a, T> ops::IndexMut<ops::FullRange> for IterMut<'a, T> {
     type Output = [T];
     #[inline]
@@ -889,7 +890,7 @@ impl<'a, T> IterMut<'a, T> {
     /// to consume the iterator. Consider using the `Slice` and
     /// `SliceMut` implementations for obtaining slices with more
     /// restricted lifetimes that do not consume the iterator.
-    #[unstable]
+    #[unstable(feature = "core")]
     pub fn into_slice(self) -> &'a mut [T] {
         make_slice!(T => &'a mut [T]: self.ptr, self.end)
     }
@@ -897,7 +898,7 @@ impl<'a, T> IterMut<'a, T> {
 
 iterator!{struct IterMut -> *mut T, &'a mut T}
 
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl<'a, T> ExactSizeIterator for IterMut<'a, T> {}
 
 /// An internal abstraction over the splitting iterators, so that
@@ -910,7 +911,7 @@ trait SplitIter: DoubleEndedIterator {
 
 /// An iterator over subslices separated by elements that match a predicate
 /// function.
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 pub struct Split<'a, T:'a, P> where P: FnMut(&T) -> bool {
     v: &'a [T],
     pred: P,
@@ -918,7 +919,7 @@ pub struct Split<'a, T:'a, P> where P: FnMut(&T) -> bool {
 }
 
 // FIXME(#19839) Remove in favor of `#[derive(Clone)]`
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl<'a, T, P> Clone for Split<'a, T, P> where P: Clone + FnMut(&T) -> bool {
     fn clone(&self) -> Split<'a, T, P> {
         Split {
@@ -929,7 +930,7 @@ impl<'a, T, P> Clone for Split<'a, T, P> where P: Clone + FnMut(&T) -> bool {
     }
 }
 
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl<'a, T, P> Iterator for Split<'a, T, P> where P: FnMut(&T) -> bool {
     type Item = &'a [T];
 
@@ -957,7 +958,7 @@ impl<'a, T, P> Iterator for Split<'a, T, P> where P: FnMut(&T) -> bool {
     }
 }
 
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl<'a, T, P> DoubleEndedIterator for Split<'a, T, P> where P: FnMut(&T) -> bool {
     #[inline]
     fn next_back(&mut self) -> Option<&'a [T]> {
@@ -983,7 +984,7 @@ impl<'a, T, P> SplitIter for Split<'a, T, P> where P: FnMut(&T) -> bool {
 
 /// An iterator over the subslices of the vector which are separated
 /// by elements that match `pred`.
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 pub struct SplitMut<'a, T:'a, P> where P: FnMut(&T) -> bool {
     v: &'a mut [T],
     pred: P,
@@ -1002,7 +1003,7 @@ impl<'a, T, P> SplitIter for SplitMut<'a, T, P> where P: FnMut(&T) -> bool {
     }
 }
 
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl<'a, T, P> Iterator for SplitMut<'a, T, P> where P: FnMut(&T) -> bool {
     type Item = &'a mut [T];
 
@@ -1037,7 +1038,7 @@ impl<'a, T, P> Iterator for SplitMut<'a, T, P> where P: FnMut(&T) -> bool {
     }
 }
 
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl<'a, T, P> DoubleEndedIterator for SplitMut<'a, T, P> where
     P: FnMut(&T) -> bool,
 {
@@ -1092,7 +1093,7 @@ impl<T, I: SplitIter<Item=T>> Iterator for GenericSplitN<I> {
 
 /// An iterator over subslices separated by elements that match a predicate
 /// function, limited to a given number of splits.
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 pub struct SplitN<'a, T: 'a, P> where P: FnMut(&T) -> bool {
     inner: GenericSplitN<Split<'a, T, P>>
 }
@@ -1100,14 +1101,14 @@ pub struct SplitN<'a, T: 'a, P> where P: FnMut(&T) -> bool {
 /// An iterator over subslices separated by elements that match a
 /// predicate function, limited to a given number of splits, starting
 /// from the end of the slice.
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 pub struct RSplitN<'a, T: 'a, P> where P: FnMut(&T) -> bool {
     inner: GenericSplitN<Split<'a, T, P>>
 }
 
 /// An iterator over subslices separated by elements that match a predicate
 /// function, limited to a given number of splits.
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 pub struct SplitNMut<'a, T: 'a, P> where P: FnMut(&T) -> bool {
     inner: GenericSplitN<SplitMut<'a, T, P>>
 }
@@ -1115,14 +1116,14 @@ pub struct SplitNMut<'a, T: 'a, P> where P: FnMut(&T) -> bool {
 /// An iterator over subslices separated by elements that match a
 /// predicate function, limited to a given number of splits, starting
 /// from the end of the slice.
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 pub struct RSplitNMut<'a, T: 'a, P> where P: FnMut(&T) -> bool {
     inner: GenericSplitN<SplitMut<'a, T, P>>
 }
 
 macro_rules! forward_iterator {
     ($name:ident: $elem:ident, $iter_of:ty) => {
-        #[stable]
+        #[stable(feature = "rust1", since = "1.0.0")]
         impl<'a, $elem, P> Iterator for $name<'a, $elem, P> where
             P: FnMut(&T) -> bool
         {
@@ -1148,13 +1149,13 @@ forward_iterator! { RSplitNMut: T, &'a mut [T] }
 
 /// An iterator over overlapping subslices of length `size`.
 #[derive(Clone)]
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 pub struct Windows<'a, T:'a> {
     v: &'a [T],
     size: uint
 }
 
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl<'a, T> Iterator for Windows<'a, T> {
     type Item = &'a [T];
 
@@ -1186,13 +1187,13 @@ impl<'a, T> Iterator for Windows<'a, T> {
 /// When the slice len is not evenly divided by the chunk size, the last slice
 /// of the iteration will be the remainder.
 #[derive(Clone)]
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 pub struct Chunks<'a, T:'a> {
     v: &'a [T],
     size: uint
 }
 
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl<'a, T> Iterator for Chunks<'a, T> {
     type Item = &'a [T];
 
@@ -1221,7 +1222,7 @@ impl<'a, T> Iterator for Chunks<'a, T> {
     }
 }
 
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl<'a, T> DoubleEndedIterator for Chunks<'a, T> {
     #[inline]
     fn next_back(&mut self) -> Option<&'a [T]> {
@@ -1237,10 +1238,10 @@ impl<'a, T> DoubleEndedIterator for Chunks<'a, T> {
     }
 }
 
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl<'a, T> ExactSizeIterator for Chunks<'a, T> {}
 
-#[unstable = "trait is experimental"]
+#[unstable(feature = "core", reason = "trait is experimental")]
 impl<'a, T> RandomAccessIterator for Chunks<'a, T> {
     #[inline]
     fn indexable(&self) -> uint {
@@ -1264,13 +1265,13 @@ impl<'a, T> RandomAccessIterator for Chunks<'a, T> {
 /// An iterator over a slice in (non-overlapping) mutable chunks (`size`
 /// elements at a time). When the slice len is not evenly divided by the chunk
 /// size, the last slice of the iteration will be the remainder.
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 pub struct ChunksMut<'a, T:'a> {
     v: &'a mut [T],
     chunk_size: uint
 }
 
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl<'a, T> Iterator for ChunksMut<'a, T> {
     type Item = &'a mut [T];
 
@@ -1300,7 +1301,7 @@ impl<'a, T> Iterator for ChunksMut<'a, T> {
     }
 }
 
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl<'a, T> DoubleEndedIterator for ChunksMut<'a, T> {
     #[inline]
     fn next_back(&mut self) -> Option<&'a mut [T]> {
@@ -1318,7 +1319,7 @@ impl<'a, T> DoubleEndedIterator for ChunksMut<'a, T> {
     }
 }
 
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl<'a, T> ExactSizeIterator for ChunksMut<'a, T> {}
 
 //
@@ -1326,7 +1327,7 @@ impl<'a, T> ExactSizeIterator for ChunksMut<'a, T> {}
 //
 
 /// Converts a pointer to A into a slice of length 1 (without copying).
-#[unstable]
+#[unstable(feature = "core")]
 pub fn ref_slice<'a, A>(s: &'a A) -> &'a [A] {
     unsafe {
         transmute(RawSlice { data: s, len: 1 })
@@ -1334,7 +1335,7 @@ pub fn ref_slice<'a, A>(s: &'a A) -> &'a [A] {
 }
 
 /// Converts a pointer to A into a slice of length 1 (without copying).
-#[unstable]
+#[unstable(feature = "core")]
 pub fn mut_ref_slice<'a, A>(s: &'a mut A) -> &'a mut [A] {
     unsafe {
         let ptr: *const A = transmute(s);
@@ -1368,7 +1369,8 @@ pub fn mut_ref_slice<'a, A>(s: &'a mut A) -> &'a mut [A] {
 /// }
 /// ```
 #[inline]
-#[unstable = "should be renamed to from_raw_parts"]
+#[unstable(feature = "core",
+           reason = "should be renamed to from_raw_parts")]
 pub unsafe fn from_raw_buf<'a, T>(p: &'a *const T, len: uint) -> &'a [T] {
     transmute(RawSlice { data: *p, len: len })
 }
@@ -1380,7 +1382,8 @@ pub unsafe fn from_raw_buf<'a, T>(p: &'a *const T, len: uint) -> &'a [T] {
 /// not being able to provide a non-aliasing guarantee of the returned mutable
 /// slice.
 #[inline]
-#[unstable = "should be renamed to from_raw_parts_mut"]
+#[unstable(feature = "core",
+           reason = "should be renamed to from_raw_parts_mut")]
 pub unsafe fn from_raw_mut_buf<'a, T>(p: &'a *mut T, len: uint) -> &'a mut [T] {
     transmute(RawSlice { data: *p, len: len })
 }
@@ -1390,7 +1393,7 @@ pub unsafe fn from_raw_mut_buf<'a, T>(p: &'a *mut T, len: uint) -> &'a mut [T] {
 //
 
 /// Operations on `[u8]`.
-#[unstable = "needs review"]
+#[unstable(feature = "core", reason = "needs review")]
 pub mod bytes {
     use ptr;
     use slice::SliceExt;
@@ -1403,7 +1406,6 @@ pub mod bytes {
 
     impl MutableByteVector for [u8] {
         #[inline]
-        #[allow(unstable)]
         fn set_memory(&mut self, value: u8) {
             unsafe { ptr::set_memory(self.as_mut_ptr(), value, self.len()) };
         }
@@ -1432,7 +1434,7 @@ pub mod bytes {
 // Boilerplate traits
 //
 
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl<A, B> PartialEq<[B]> for [A] where A: PartialEq<B> {
     fn eq(&self, other: &[B]) -> bool {
         self.len() == other.len() &&
@@ -1444,17 +1446,17 @@ impl<A, B> PartialEq<[B]> for [A] where A: PartialEq<B> {
     }
 }
 
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl<T: Eq> Eq for [T] {}
 
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl<T: Ord> Ord for [T] {
     fn cmp(&self, other: &[T]) -> Ordering {
         order::cmp(self.iter(), other.iter())
     }
 }
 
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl<T: PartialOrd> PartialOrd for [T] {
     #[inline]
     fn partial_cmp(&self, other: &[T]) -> Option<Ordering> {
@@ -1479,7 +1481,7 @@ impl<T: PartialOrd> PartialOrd for [T] {
 }
 
 /// Extension methods for slices containing integers.
-#[unstable]
+#[unstable(feature = "core")]
 pub trait IntSliceExt<U, S> {
     /// Converts the slice to an immutable slice of unsigned integers with the same width.
     fn as_unsigned<'a>(&'a self) -> &'a [U];
@@ -1494,7 +1496,7 @@ pub trait IntSliceExt<U, S> {
 
 macro_rules! impl_int_slice {
     ($u:ty, $s:ty, $t:ty) => {
-        #[unstable]
+        #[unstable(feature = "core")]
         impl IntSliceExt<$u, $s> for [$t] {
             #[inline]
             fn as_unsigned(&self) -> &[$u] { unsafe { transmute(self) } }
diff --git a/src/libcore/str/mod.rs b/src/libcore/str/mod.rs
index b0227c749cc..101d349c351 100644
--- a/src/libcore/str/mod.rs
+++ b/src/libcore/str/mod.rs
@@ -47,7 +47,7 @@ macro_rules! delegate_iter {
         }
     };
     ($te:ty : $ti:ty) => {
-        #[stable]
+        #[stable(feature = "rust1", since = "1.0.0")]
         impl<'a> Iterator for $ti {
             type Item = $te;
 
@@ -60,7 +60,7 @@ macro_rules! delegate_iter {
                 self.0.size_hint()
             }
         }
-        #[stable]
+        #[stable(feature = "rust1", since = "1.0.0")]
         impl<'a> DoubleEndedIterator for $ti {
             #[inline]
             fn next_back(&mut self) -> Option<$te> {
@@ -69,7 +69,7 @@ macro_rules! delegate_iter {
         }
     };
     (pattern $te:ty : $ti:ty) => {
-        #[stable]
+        #[stable(feature = "rust1", since = "1.0.0")]
         impl<'a, P: CharEq> Iterator for $ti {
             type Item = $te;
 
@@ -82,7 +82,7 @@ macro_rules! delegate_iter {
                 self.0.size_hint()
             }
         }
-        #[stable]
+        #[stable(feature = "rust1", since = "1.0.0")]
         impl<'a, P: CharEq> DoubleEndedIterator for $ti {
             #[inline]
             fn next_back(&mut self) -> Option<$te> {
@@ -91,7 +91,7 @@ macro_rules! delegate_iter {
         }
     };
     (pattern forward $te:ty : $ti:ty) => {
-        #[stable]
+        #[stable(feature = "rust1", since = "1.0.0")]
         impl<'a, P: CharEq> Iterator for $ti {
             type Item = $te;
 
@@ -110,7 +110,8 @@ macro_rules! delegate_iter {
 /// A trait to abstract the idea of creating a new instance of a type from a
 /// string.
 // FIXME(#17307): there should be an `E` associated type for a `Result` return
-#[unstable = "will return a Result once associated types are working"]
+#[unstable(feature = "core",
+           reason = "will return a Result once associated types are working")]
 pub trait FromStr {
     /// Parses a string `s` to return an optional value of this type. If the
     /// string is ill-formatted, the None is returned.
@@ -145,7 +146,8 @@ Section: Creating a string
 
 /// Errors which can occur when attempting to interpret a byte slice as a `str`.
 #[derive(Copy, Eq, PartialEq, Clone, Show)]
-#[unstable = "error enumeration recently added and definitions may be refined"]
+#[unstable(feature = "core",
+           reason = "error enumeration recently added and definitions may be refined")]
 pub enum Utf8Error {
     /// An invalid byte was detected at the byte offset given.
     ///
@@ -169,7 +171,7 @@ pub enum Utf8Error {
 ///
 /// Returns `Err` if the slice is not utf-8 with a description as to why the
 /// provided slice is not utf-8.
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 pub fn from_utf8(v: &[u8]) -> Result<&str, Utf8Error> {
     try!(run_utf8_validation_iterator(&mut v.iter()));
     Ok(unsafe { from_utf8_unchecked(v) })
@@ -177,7 +179,7 @@ pub fn from_utf8(v: &[u8]) -> Result<&str, Utf8Error> {
 
 /// Converts a slice of bytes to a string slice without checking
 /// that the string contains valid UTF-8.
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 pub unsafe fn from_utf8_unchecked<'a>(v: &'a [u8]) -> &'a str {
     mem::transmute(v)
 }
@@ -195,7 +197,9 @@ pub unsafe fn from_utf8_unchecked<'a>(v: &'a [u8]) -> &'a str {
 /// # Panics
 ///
 /// This function will panic if the string pointed to by `s` is not valid UTF-8.
-#[deprecated = "use std::ffi::c_str_to_bytes + str::from_utf8"]
+#[unstable(feature = "core")]
+#[deprecated(since = "1.0.0",
+             reason = "use std::ffi::c_str_to_bytes + str::from_utf8")]
 pub unsafe fn from_c_str(s: *const i8) -> &'static str {
     let s = s as *const u8;
     let mut len = 0;
@@ -207,7 +211,8 @@ pub unsafe fn from_c_str(s: *const i8) -> &'static str {
 }
 
 /// Something that can be used to compare against a character
-#[unstable = "definition may change as pattern-related methods are stabilized"]
+#[unstable(feature = "core",
+           reason = "definition may change as pattern-related methods are stabilized")]
 pub trait CharEq {
     /// Determine if the splitter should split at the given character
     fn matches(&mut self, char) -> bool;
@@ -244,7 +249,7 @@ impl<'a> CharEq for &'a [char] {
     }
 }
 
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl Error for Utf8Error {
     fn description(&self) -> &str {
         match *self {
@@ -254,7 +259,7 @@ impl Error for Utf8Error {
     }
 }
 
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl fmt::Display for Utf8Error {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         match *self {
@@ -276,7 +281,7 @@ Section: Iterators
 ///
 /// Created with the method `.chars()`.
 #[derive(Clone, Copy)]
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 pub struct Chars<'a> {
     iter: slice::Iter<'a, u8>
 }
@@ -307,7 +312,7 @@ fn unwrap_or_0(opt: Option<&u8>) -> u8 {
 
 /// Reads the next code point out of a byte iterator (assuming a
 /// UTF-8-like encoding).
-#[unstable]
+#[unstable(feature = "core")]
 pub fn next_code_point(bytes: &mut slice::Iter<u8>) -> Option<u32> {
     // Decode UTF-8
     let x = match bytes.next() {
@@ -339,7 +344,7 @@ pub fn next_code_point(bytes: &mut slice::Iter<u8>) -> Option<u32> {
     Some(ch)
 }
 
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl<'a> Iterator for Chars<'a> {
     type Item = char;
 
@@ -360,7 +365,7 @@ impl<'a> Iterator for Chars<'a> {
     }
 }
 
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl<'a> DoubleEndedIterator for Chars<'a> {
     #[inline]
     fn next_back(&mut self) -> Option<char> {
@@ -397,13 +402,13 @@ impl<'a> DoubleEndedIterator for Chars<'a> {
 /// External iterator for a string's characters and their byte offsets.
 /// Use with the `std::iter` module.
 #[derive(Clone)]
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 pub struct CharIndices<'a> {
     front_offset: uint,
     iter: Chars<'a>,
 }
 
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl<'a> Iterator for CharIndices<'a> {
     type Item = (uint, char);
 
@@ -427,7 +432,7 @@ impl<'a> Iterator for CharIndices<'a> {
     }
 }
 
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl<'a> DoubleEndedIterator for CharIndices<'a> {
     #[inline]
     fn next_back(&mut self) -> Option<(uint, char)> {
@@ -446,7 +451,7 @@ impl<'a> DoubleEndedIterator for CharIndices<'a> {
 /// Use with the `std::iter` module.
 ///
 /// Created with `StrExt::bytes`
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 #[derive(Clone)]
 pub struct Bytes<'a>(Map<&'a u8, u8, slice::Iter<'a, u8>, BytesDeref>);
 delegate_iter!{exact u8 : Bytes<'a>}
@@ -456,6 +461,7 @@ delegate_iter!{exact u8 : Bytes<'a>}
 #[derive(Copy, Clone)]
 struct BytesDeref;
 
+#[cfg(stage0)]
 impl<'a> Fn(&'a u8) -> u8 for BytesDeref {
     #[inline]
     extern "rust-call" fn call(&self, (ptr,): (&'a u8,)) -> u8 {
@@ -463,6 +469,16 @@ impl<'a> Fn(&'a u8) -> u8 for BytesDeref {
     }
 }
 
+#[cfg(not(stage0))]
+impl<'a> Fn<(&'a u8,)> for BytesDeref {
+    type Output = u8;
+
+    #[inline]
+    extern "rust-call" fn call(&self, (ptr,): (&'a u8,)) -> u8 {
+        *ptr
+    }
+}
+
 /// An iterator over the substrings of a string, separated by `sep`.
 #[derive(Clone)]
 struct CharSplits<'a, Sep> {
@@ -486,13 +502,13 @@ struct CharSplitsN<'a, Sep> {
 }
 
 /// An iterator over the lines of a string, separated by `\n`.
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 pub struct Lines<'a> {
     inner: CharSplits<'a, char>,
 }
 
 /// An iterator over the lines of a string, separated by either `\n` or (`\r\n`).
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 pub struct LinesAny<'a> {
     inner: Map<&'a str, &'a str, Lines<'a>, fn(&str) -> &str>,
 }
@@ -509,7 +525,7 @@ impl<'a, Sep> CharSplits<'a, Sep> {
     }
 }
 
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl<'a, Sep: CharEq> Iterator for CharSplits<'a, Sep> {
     type Item = &'a str;
 
@@ -544,7 +560,7 @@ impl<'a, Sep: CharEq> Iterator for CharSplits<'a, Sep> {
     }
 }
 
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl<'a, Sep: CharEq> DoubleEndedIterator for CharSplits<'a, Sep> {
     #[inline]
     fn next_back(&mut self) -> Option<&'a str> {
@@ -586,7 +602,7 @@ impl<'a, Sep: CharEq> DoubleEndedIterator for CharSplits<'a, Sep> {
     }
 }
 
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl<'a, Sep: CharEq> Iterator for CharSplitsN<'a, Sep> {
     type Item = &'a str;
 
@@ -892,7 +908,7 @@ impl Searcher {
 /// An iterator over the start and end indices of the matches of a
 /// substring within a larger string
 #[derive(Clone)]
-#[unstable = "type may be removed"]
+#[unstable(feature = "core", reason = "type may be removed")]
 pub struct MatchIndices<'a> {
     // constants
     haystack: &'a str,
@@ -903,14 +919,14 @@ pub struct MatchIndices<'a> {
 /// An iterator over the substrings of a string separated by a given
 /// search string
 #[derive(Clone)]
-#[unstable = "type may be removed"]
+#[unstable(feature = "core", reason = "type may be removed")]
 pub struct SplitStr<'a> {
     it: MatchIndices<'a>,
     last_end: uint,
     finished: bool
 }
 
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl<'a> Iterator for MatchIndices<'a> {
     type Item = (uint, uint);
 
@@ -927,7 +943,7 @@ impl<'a> Iterator for MatchIndices<'a> {
     }
 }
 
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl<'a> Iterator for SplitStr<'a> {
     type Item = &'a str;
 
@@ -1087,7 +1103,8 @@ static UTF8_CHAR_WIDTH: [u8; 256] = [
 /// the next `char` in a string.  This can be used as a data structure
 /// for iterating over the UTF-8 bytes of a string.
 #[derive(Copy)]
-#[unstable = "naming is uncertain with container conventions"]
+#[unstable(feature = "core",
+           reason = "naming is uncertain with container conventions")]
 pub struct CharRange {
     /// Current `char`
     pub ch: char,
@@ -1113,7 +1130,7 @@ mod traits {
     use ops;
     use str::{StrExt, eq_slice};
 
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     impl Ord for str {
         #[inline]
         fn cmp(&self, other: &str) -> Ordering {
@@ -1129,7 +1146,7 @@ mod traits {
         }
     }
 
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     impl PartialEq for str {
         #[inline]
         fn eq(&self, other: &str) -> bool {
@@ -1139,10 +1156,10 @@ mod traits {
         fn ne(&self, other: &str) -> bool { !(*self).eq(other) }
     }
 
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     impl Eq for str {}
 
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     impl PartialOrd for str {
         #[inline]
         fn partial_cmp(&self, other: &str) -> Option<Ordering> {
@@ -1176,7 +1193,7 @@ mod traits {
     /// // byte 100 is outside the string
     /// // &s[3 .. 100];
     /// ```
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     impl ops::Index<ops::Range<uint>> for str {
         type Output = str;
         #[inline]
@@ -1199,7 +1216,7 @@ mod traits {
     ///
     /// Panics when `end` does not point to a valid character, or is
     /// out of bounds.
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     impl ops::Index<ops::RangeTo<uint>> for str {
         type Output = str;
         #[inline]
@@ -1219,7 +1236,7 @@ mod traits {
     ///
     /// Panics when `begin` does not point to a valid character, or is
     /// out of bounds.
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     impl ops::Index<ops::RangeFrom<uint>> for str {
         type Output = str;
         #[inline]
@@ -1233,7 +1250,7 @@ mod traits {
         }
     }
 
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     impl ops::Index<ops::FullRange> for str {
         type Output = str;
         #[inline]
@@ -1244,9 +1261,10 @@ mod traits {
 }
 
 /// Any string that can be represented as a slice
-#[unstable = "Instead of taking this bound generically, this trait will be \
-              replaced with one of slicing syntax (&foo[]), deref coercions, or \
-              a more generic conversion trait"]
+#[unstable(feature = "core",
+           reason = "Instead of taking this bound generically, this trait will be \
+                     replaced with one of slicing syntax (&foo[]), deref coercions, or \
+                     a more generic conversion trait")]
 pub trait Str {
     /// Work with `self` as a slice.
     fn as_slice<'a>(&'a self) -> &'a str;
@@ -1264,25 +1282,26 @@ impl<'a, S: ?Sized> Str for &'a S where S: Str {
 
 /// Return type of `StrExt::split`
 #[derive(Clone)]
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 pub struct Split<'a, P>(CharSplits<'a, P>);
 delegate_iter!{pattern &'a str : Split<'a, P>}
 
 /// Return type of `StrExt::split_terminator`
 #[derive(Clone)]
-#[unstable = "might get removed in favour of a constructor method on Split"]
+#[unstable(feature = "core",
+           reason = "might get removed in favour of a constructor method on Split")]
 pub struct SplitTerminator<'a, P>(CharSplits<'a, P>);
 delegate_iter!{pattern &'a str : SplitTerminator<'a, P>}
 
 /// Return type of `StrExt::splitn`
 #[derive(Clone)]
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 pub struct SplitN<'a, P>(CharSplitsN<'a, P>);
 delegate_iter!{pattern forward &'a str : SplitN<'a, P>}
 
 /// Return type of `StrExt::rsplitn`
 #[derive(Clone)]
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 pub struct RSplitN<'a, P>(CharSplitsN<'a, P>);
 delegate_iter!{pattern forward &'a str : RSplitN<'a, P>}
 
@@ -1648,7 +1667,7 @@ impl StrExt for str {
 /// Pluck a code point out of a UTF-8-like byte slice and return the
 /// index of the next code point.
 #[inline]
-#[unstable]
+#[unstable(feature = "core")]
 pub fn char_range_at_raw(bytes: &[u8], i: uint) -> (u32, usize) {
     if bytes[i] < 128u8 {
         return (bytes[i] as u32, i + 1);
@@ -1671,13 +1690,13 @@ pub fn char_range_at_raw(bytes: &[u8], i: uint) -> (u32, usize) {
     multibyte_char_range_at(bytes, i)
 }
 
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl<'a> Default for &'a str {
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     fn default() -> &'a str { "" }
 }
 
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl<'a> Iterator for Lines<'a> {
     type Item = &'a str;
 
@@ -1687,13 +1706,13 @@ impl<'a> Iterator for Lines<'a> {
     fn size_hint(&self) -> (uint, Option<uint>) { self.inner.size_hint() }
 }
 
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl<'a> DoubleEndedIterator for Lines<'a> {
     #[inline]
     fn next_back(&mut self) -> Option<&'a str> { self.inner.next_back() }
 }
 
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl<'a> Iterator for LinesAny<'a> {
     type Item = &'a str;
 
@@ -1703,7 +1722,7 @@ impl<'a> Iterator for LinesAny<'a> {
     fn size_hint(&self) -> (uint, Option<uint>) { self.inner.size_hint() }
 }
 
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl<'a> DoubleEndedIterator for LinesAny<'a> {
     #[inline]
     fn next_back(&mut self) -> Option<&'a str> { self.inner.next_back() }
diff --git a/src/libcore/tuple.rs b/src/libcore/tuple.rs
index 5baeae236b3..64c2964eb7c 100644
--- a/src/libcore/tuple.rs
+++ b/src/libcore/tuple.rs
@@ -33,7 +33,7 @@
 //! * `Ord`
 //! * `Default`
 
-#![stable]
+#![stable(feature = "rust1", since = "1.0.0")]
 
 use clone::Clone;
 use cmp::*;
@@ -55,14 +55,14 @@ macro_rules! tuple_impls {
         }
     )+) => {
         $(
-            #[stable]
+            #[stable(feature = "rust1", since = "1.0.0")]
             impl<$($T:Clone),+> Clone for ($($T,)+) {
                 fn clone(&self) -> ($($T,)+) {
                     ($(e!(self.$idx.clone()),)+)
                 }
             }
 
-            #[stable]
+            #[stable(feature = "rust1", since = "1.0.0")]
             impl<$($T:PartialEq),+> PartialEq for ($($T,)+) {
                 #[inline]
                 fn eq(&self, other: &($($T,)+)) -> bool {
@@ -74,10 +74,10 @@ macro_rules! tuple_impls {
                 }
             }
 
-            #[stable]
+            #[stable(feature = "rust1", since = "1.0.0")]
             impl<$($T:Eq),+> Eq for ($($T,)+) {}
 
-            #[stable]
+            #[stable(feature = "rust1", since = "1.0.0")]
             impl<$($T:PartialOrd + PartialEq),+> PartialOrd for ($($T,)+) {
                 #[inline]
                 fn partial_cmp(&self, other: &($($T,)+)) -> Option<Ordering> {
@@ -101,7 +101,7 @@ macro_rules! tuple_impls {
                 }
             }
 
-            #[stable]
+            #[stable(feature = "rust1", since = "1.0.0")]
             impl<$($T:Ord),+> Ord for ($($T,)+) {
                 #[inline]
                 fn cmp(&self, other: &($($T,)+)) -> Ordering {
@@ -109,9 +109,9 @@ macro_rules! tuple_impls {
                 }
             }
 
-            #[stable]
+            #[stable(feature = "rust1", since = "1.0.0")]
             impl<$($T:Default),+> Default for ($($T,)+) {
-                #[stable]
+                #[stable(feature = "rust1", since = "1.0.0")]
                 #[inline]
                 fn default() -> ($($T,)+) {
                     ($({ let x: $T = Default::default(); x},)+)
diff --git a/src/libcoretest/cell.rs b/src/libcoretest/cell.rs
index a808593ffbd..8bd2ed95ed5 100644
--- a/src/libcoretest/cell.rs
+++ b/src/libcoretest/cell.rs
@@ -114,7 +114,6 @@ fn discard_doesnt_unborrow() {
 }
 
 #[test]
-#[allow(unstable)]
 fn clone_ref_updates_flag() {
     let x = RefCell::new(0i);
     {
diff --git a/src/libcoretest/lib.rs b/src/libcoretest/lib.rs
index 0c7b72612fa..0d371dbe153 100644
--- a/src/libcoretest/lib.rs
+++ b/src/libcoretest/lib.rs
@@ -12,7 +12,6 @@
 #![feature(unboxed_closures)]
 #![feature(box_syntax)]
 #![allow(unknown_features)] #![feature(int_uint)]
-#![allow(unstable)]
 
 extern crate core;
 extern crate test;
diff --git a/src/libflate/lib.rs b/src/libflate/lib.rs
index f0a2ab3d1d6..5f3a68a9e34 100644
--- a/src/libflate/lib.rs
+++ b/src/libflate/lib.rs
@@ -15,15 +15,18 @@
 //! [mz]: https://code.google.com/p/miniz/
 
 #![crate_name = "flate"]
-#![unstable]
+#![unstable(feature = "rustc_private")]
+#![feature(staged_api)]
 #![staged_api]
 #![allow(unknown_features)] #![feature(int_uint)]
-#![allow(unstable)]
 #![crate_type = "rlib"]
 #![crate_type = "dylib"]
 #![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",
        html_root_url = "http://doc.rust-lang.org/nightly/")]
+#![feature(hash)]
+#![feature(core)]
+#![feature(libc)]
 
 #[cfg(test)] #[macro_use] extern crate log;
 
diff --git a/src/libfmt_macros/lib.rs b/src/libfmt_macros/lib.rs
index 0ff15327441..d76e4b2ed95 100644
--- a/src/libfmt_macros/lib.rs
+++ b/src/libfmt_macros/lib.rs
@@ -15,7 +15,8 @@
 //! generated instead.
 
 #![crate_name = "fmt_macros"]
-#![unstable]
+#![unstable(feature = "rustc_private")]
+#![feature(staged_api)]
 #![staged_api]
 #![crate_type = "rlib"]
 #![crate_type = "dylib"]
@@ -26,7 +27,9 @@
 
 #![feature(slicing_syntax)]
 #![allow(unknown_features)] #![feature(int_uint)]
-#![allow(unstable)]
+#![feature(collections)]
+#![feature(core)]
+#![feature(unicode)]
 
 pub use self::Piece::*;
 pub use self::Position::*;
diff --git a/src/libgetopts/lib.rs b/src/libgetopts/lib.rs
index 70f2429282b..4774262246a 100644
--- a/src/libgetopts/lib.rs
+++ b/src/libgetopts/lib.rs
@@ -78,7 +78,9 @@
 //! ```
 
 #![crate_name = "getopts"]
-#![unstable = "use the crates.io `getopts` library instead"]
+#![unstable(feature = "rustc_private",
+            reason = "use the crates.io `getopts` library instead")]
+#![feature(staged_api)]
 #![staged_api]
 #![crate_type = "rlib"]
 #![crate_type = "dylib"]
@@ -88,8 +90,10 @@
        html_playground_url = "http://play.rust-lang.org/")]
 #![feature(slicing_syntax)]
 #![allow(unknown_features)] #![feature(int_uint)]
-#![allow(unstable)]
 #![deny(missing_docs)]
+#![feature(collections)]
+#![feature(core)]
+#![cfg_attr(test, feature(rustc_private))]
 
 #[cfg(test)] #[macro_use] extern crate log;
 
@@ -538,7 +542,9 @@ pub fn opt(short_name: &str,
 
 impl Fail {
     /// Convert a `Fail` enum into an error string.
-    #[deprecated="use `fmt::String` (`{}` format specifier)"]
+    #[unstable(feature = "rustc_private")]
+    #[deprecated(since = "1.0.0",
+                 reason = "use `fmt::String` (`{}` format specifier)")]
     pub fn to_err_msg(self) -> String {
         self.to_string()
     }
diff --git a/src/libgraphviz/lib.rs b/src/libgraphviz/lib.rs
index ebe2487215a..171b4ec2097 100644
--- a/src/libgraphviz/lib.rs
+++ b/src/libgraphviz/lib.rs
@@ -265,7 +265,8 @@
 //! * [DOT language](http://www.graphviz.org/doc/info/lang.html)
 
 #![crate_name = "graphviz"]
-#![unstable]
+#![unstable(feature = "rustc_private")]
+#![feature(staged_api)]
 #![staged_api]
 #![crate_type = "rlib"]
 #![crate_type = "dylib"]
@@ -274,7 +275,10 @@
        html_root_url = "http://doc.rust-lang.org/nightly/")]
 #![feature(slicing_syntax)]
 #![allow(unknown_features)] #![feature(int_uint)]
-#![allow(unstable)]
+#![feature(collections)]
+#![feature(core)]
+#![feature(io)]
+#![feature(path)]
 
 use self::LabelText::*;
 
diff --git a/src/libgraphviz/maybe_owned_vec.rs b/src/libgraphviz/maybe_owned_vec.rs
index 4e6437a5e76..71f11783593 100644
--- a/src/libgraphviz/maybe_owned_vec.rs
+++ b/src/libgraphviz/maybe_owned_vec.rs
@@ -8,7 +8,8 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#![deprecated = "use std::vec::CowVec"]
+#![unstable(feature = "rustc_private")]
+#![deprecated(since = "1.0.0", reason = "use std::vec::CowVec")]
 
 pub use self::MaybeOwnedVector::*;
 
diff --git a/src/liblibc/lib.rs b/src/liblibc/lib.rs
index a07fd61cd8c..548782216bb 100644
--- a/src/liblibc/lib.rs
+++ b/src/liblibc/lib.rs
@@ -10,15 +10,18 @@
 
 #![crate_name = "libc"]
 #![crate_type = "rlib"]
-#![cfg_attr(not(feature = "cargo-build"), unstable)]
+#![cfg_attr(not(feature = "cargo-build"),
+            unstable(feature = "libc"))]
+#![cfg_attr(not(feature = "cargo-build"), feature(staged_api))]
 #![cfg_attr(not(feature = "cargo-build"), staged_api)]
+#![cfg_attr(not(feature = "cargo-build"), feature(core))]
 #![allow(unknown_features)] #![feature(int_uint)]
-#![allow(unstable)]
 #![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",
        html_root_url = "http://doc.rust-lang.org/nightly/",
        html_playground_url = "http://play.rust-lang.org/")]
+#![cfg_attr(test, feature(test))]
 
 //! Bindings for the C standard library and other platform libraries
 //!
@@ -73,7 +76,6 @@
 //! one from Berkeley after the lawsuits died down and the CSRG dissolved.
 
 #![allow(bad_style, raw_pointer_derive)]
-
 #[cfg(feature = "cargo-build")] extern crate "std" as core;
 #[cfg(not(feature = "cargo-build"))] extern crate core;
 
diff --git a/src/liblog/lib.rs b/src/liblog/lib.rs
index 6712f153c09..dfec2c18816 100644
--- a/src/liblog/lib.rs
+++ b/src/liblog/lib.rs
@@ -156,7 +156,9 @@
 //! if logging is disabled, none of the components of the log will be executed.
 
 #![crate_name = "log"]
-#![unstable = "use the crates.io `log` library instead"]
+#![unstable(feature = "rustc_private",
+            reason = "use the crates.io `log` library instead")]
+#![feature(staged_api)]
 #![staged_api]
 #![crate_type = "rlib"]
 #![crate_type = "dylib"]
@@ -169,8 +171,13 @@
 #![feature(slicing_syntax)]
 #![feature(box_syntax)]
 #![allow(unknown_features)] #![feature(int_uint)]
-#![allow(unstable)]
 #![deny(missing_docs)]
+#![feature(collections)]
+#![feature(core)]
+#![feature(io)]
+#![feature(os)]
+#![feature(rustc_private)]
+#![feature(std_misc)]
 
 use std::cell::RefCell;
 use std::fmt;
diff --git a/src/librand/distributions/mod.rs b/src/librand/distributions/mod.rs
index e248de10df4..25c205b2bf2 100644
--- a/src/librand/distributions/mod.rs
+++ b/src/librand/distributions/mod.rs
@@ -17,7 +17,7 @@
 //! internally. The `IndependentSample` trait is for generating values
 //! that do not need to record state.
 
-#![unstable]
+#![unstable(feature = "rand")]
 
 use core::prelude::*;
 use core::num::{Float, Int};
diff --git a/src/librand/lib.rs b/src/librand/lib.rs
index 853eb41d011..76258151850 100644
--- a/src/librand/lib.rs
+++ b/src/librand/lib.rs
@@ -23,10 +23,11 @@
        html_root_url = "http://doc.rust-lang.org/nightly/",
        html_playground_url = "http://play.rust-lang.org/")]
 #![allow(unknown_features)] #![feature(int_uint)]
-#![allow(unstable)]
 #![no_std]
-#![unstable]
+#![unstable(feature = "rand")]
+#![feature(staged_api)]
 #![staged_api]
+#![feature(core)]
 
 #[macro_use]
 extern crate core;
diff --git a/src/librand/reseeding.rs b/src/librand/reseeding.rs
index 63de49ac5cd..10c71cff5be 100644
--- a/src/librand/reseeding.rs
+++ b/src/librand/reseeding.rs
@@ -141,9 +141,9 @@ impl<R: Rng + Default> Reseeder<R> for ReseedWithDefault {
         *rng = Default::default();
     }
 }
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl Default for ReseedWithDefault {
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     fn default() -> ReseedWithDefault { ReseedWithDefault }
 }
 
diff --git a/src/librbml/lib.rs b/src/librbml/lib.rs
index 37a17a27369..2500cb86463 100644
--- a/src/librbml/lib.rs
+++ b/src/librbml/lib.rs
@@ -16,7 +16,8 @@
 //!     http://www.matroska.org/technical/specs/rfc/index.html
 
 #![crate_name = "rbml"]
-#![unstable]
+#![unstable(feature = "rustc_private")]
+#![feature(staged_api)]
 #![staged_api]
 #![crate_type = "rlib"]
 #![crate_type = "dylib"]
@@ -27,7 +28,10 @@
 #![allow(unknown_features)]
 #![feature(slicing_syntax)]
 #![allow(unknown_features)] #![feature(int_uint)]
-#![allow(unstable)]
+#![feature(collections)]
+#![feature(core)]
+#![feature(io)]
+#![feature(rustc_private)]
 
 extern crate serialize;
 #[macro_use] extern crate log;
@@ -853,7 +857,10 @@ pub mod writer {
 
     // Set to true to generate more debugging in EBML code.
     // Totally lame approach.
+    #[cfg(not(ndebug))]
     static DEBUG: bool = true;
+    #[cfg(ndebug)]
+    static DEBUG: bool = false;
 
     impl<'a, W: Writer + Seek> Encoder<'a, W> {
         // used internally to emit things like the vector length and so on
diff --git a/src/librustc/lib.rs b/src/librustc/lib.rs
index b961200f335..580e55f78a9 100644
--- a/src/librustc/lib.rs
+++ b/src/librustc/lib.rs
@@ -15,7 +15,8 @@
 //! This API is completely unstable and subject to change.
 
 #![crate_name = "rustc"]
-#![unstable]
+#![unstable(feature = "rustc_private")]
+#![feature(staged_api)]
 #![staged_api]
 #![crate_type = "dylib"]
 #![crate_type = "rlib"]
@@ -29,7 +30,17 @@
 #![feature(box_syntax)]
 #![allow(unknown_features)] #![feature(int_uint)]
 #![feature(rustc_diagnostic_macros)]
-#![allow(unstable)]
+#![feature(collections)]
+#![feature(core)]
+#![feature(io)]
+#![feature(libc)]
+#![feature(os)]
+#![feature(path)]
+#![feature(rustc_private)]
+#![feature(std_misc)]
+#![feature(unicode)]
+#![feature(hash)]
+#![cfg_attr(test, feature(test))]
 
 extern crate arena;
 extern crate flate;
diff --git a/src/librustc/lint/builtin.rs b/src/librustc/lint/builtin.rs
index 34ed5b0cd57..f13814527cd 100644
--- a/src/librustc/lint/builtin.rs
+++ b/src/librustc/lint/builtin.rs
@@ -46,7 +46,7 @@ use std::{i8, i16, i32, i64, u8, u16, u32, u64, f32, f64};
 use syntax::{abi, ast, ast_map};
 use syntax::ast_util::is_shift_binop;
 use syntax::attr::{self, AttrMetaMethods};
-use syntax::codemap::{self, Span, DUMMY_SP};
+use syntax::codemap::{self, Span};
 use syntax::parse::token;
 use syntax::ast::{TyIs, TyUs, TyI8, TyU8, TyI16, TyU16, TyI32, TyU32, TyI64, TyU64};
 use syntax::ast_util;
@@ -662,9 +662,6 @@ impl LintPass for UnusedAttributes {
             // FIXME: #14407 these are only looked at on-demand so we can't
             // guarantee they'll have already been checked
             "deprecated",
-            "experimental",
-            "frozen",
-            "locked",
             "must_use",
             "stable",
             "unstable",
@@ -1696,37 +1693,16 @@ declare_lint! {
     "detects use of #[deprecated] items"
 }
 
-declare_lint! {
-    UNSTABLE,
-    Warn,
-    "detects use of #[unstable] items (incl. items with no stability attribute)"
-}
-
-/// Checks for use of items with `#[deprecated]`, `#[unstable]` and
-/// `#[unstable]` attributes, or no stability attribute.
+/// Checks for use of items with `#[deprecated]` attributes
 #[derive(Copy)]
-pub struct Stability { this_crate_staged: bool }
+pub struct Stability;
 
 impl Stability {
-    pub fn new() -> Stability { Stability { this_crate_staged: false } }
-
-    fn lint(&self, cx: &Context, id: ast::DefId, span: Span) {
-
-        let ref stability = stability::lookup(cx.tcx, id);
-        let cross_crate = !ast_util::is_local(id);
-        let staged = (!cross_crate && self.this_crate_staged)
-            || (cross_crate && stability::is_staged_api(cx.tcx, id));
+    fn lint(&self, cx: &Context, _id: ast::DefId, span: Span, stability: &Option<attr::Stability>) {
 
-        if !staged { return }
-
-        // stability attributes are promises made across crates; only
-        // check DEPRECATED for crate-local usage.
+        // deprecated attributes apply in-crate and cross-crate
         let (lint, label) = match *stability {
-            // no stability attributes == Unstable
-            None if cross_crate => (UNSTABLE, "unmarked"),
-            Some(attr::Stability { level: attr::Unstable, .. }) if cross_crate =>
-                (UNSTABLE, "unstable"),
-            Some(attr::Stability { level: attr::Deprecated, .. }) =>
+            Some(attr::Stability { deprecated_since: Some(_), .. }) =>
                 (DEPRECATED, "deprecated"),
             _ => return
         };
@@ -1736,7 +1712,7 @@ impl Stability {
         fn output(cx: &Context, span: Span, stability: &Option<attr::Stability>,
                   lint: &'static Lint, label: &'static str) {
             let msg = match *stability {
-                Some(attr::Stability { text: Some(ref s), .. }) => {
+                Some(attr::Stability { reason: Some(ref s), .. }) => {
                     format!("use of {} item: {}", label, *s)
                 }
                 _ => format!("use of {} item", label)
@@ -1745,111 +1721,21 @@ impl Stability {
             cx.span_lint(lint, span, &msg[]);
         }
     }
-
-
-    fn is_internal(&self, cx: &Context, span: Span) -> bool {
-        cx.tcx.sess.codemap().span_is_internal(span)
-    }
-
 }
 
 impl LintPass for Stability {
     fn get_lints(&self) -> LintArray {
-        lint_array!(DEPRECATED, UNSTABLE)
-    }
-
-    fn check_crate(&mut self, _: &Context, c: &ast::Crate) {
-        // Just mark the #[staged_api] attribute used, though nothing else is done
-        // with it during this pass over the source.
-        for attr in c.attrs.iter() {
-            if attr.name().get() == "staged_api" {
-                match attr.node.value.node {
-                    ast::MetaWord(_) => {
-                        attr::mark_used(attr);
-                        self.this_crate_staged = true;
-                    }
-                    _ => (/*pass*/)
-                }
-            }
-        }
-    }
-
-    fn check_expr(&mut self, cx: &Context, e: &ast::Expr) {
-        if self.is_internal(cx, e.span) { return; }
-
-        let mut span = e.span;
-
-        let id = match e.node {
-            ast::ExprPath(..) | ast::ExprQPath(..) | ast::ExprStruct(..) => {
-                match cx.tcx.def_map.borrow().get(&e.id) {
-                    Some(&def) => def.def_id(),
-                    None => return
-                }
-            }
-            ast::ExprMethodCall(i, _, _) => {
-                span = i.span;
-                let method_call = ty::MethodCall::expr(e.id);
-                match cx.tcx.method_map.borrow().get(&method_call) {
-                    Some(method) => {
-                        match method.origin {
-                            ty::MethodStatic(def_id) => {
-                                def_id
-                            }
-                            ty::MethodStaticClosure(def_id) => {
-                                def_id
-                            }
-                            ty::MethodTypeParam(ty::MethodParam {
-                                ref trait_ref,
-                                method_num: index,
-                                ..
-                            }) |
-                            ty::MethodTraitObject(ty::MethodObject {
-                                ref trait_ref,
-                                method_num: index,
-                                ..
-                            }) => {
-                                ty::trait_item(cx.tcx, trait_ref.def_id, index).def_id()
-                            }
-                        }
-                    }
-                    None => return
-                }
-            }
-            _ => return
-        };
-
-        self.lint(cx, id, span);
+        lint_array!(DEPRECATED)
     }
 
     fn check_item(&mut self, cx: &Context, item: &ast::Item) {
-        if self.is_internal(cx, item.span) { return }
-
-        match item.node {
-            ast::ItemExternCrate(_) => {
-                // compiler-generated `extern crate` items have a dummy span.
-                if item.span == DUMMY_SP { return }
+        stability::check_item(cx.tcx, item,
+                              &mut |id, sp, stab| self.lint(cx, id, sp, stab));
+    }
 
-                let cnum = match cx.tcx.sess.cstore.find_extern_mod_stmt_cnum(item.id) {
-                    Some(cnum) => cnum,
-                    None => return,
-                };
-                let id = ast::DefId { krate: cnum, node: ast::CRATE_NODE_ID };
-                self.lint(cx, id, item.span);
-            }
-            ast::ItemTrait(_, _, ref supertraits, _) => {
-                for t in supertraits.iter() {
-                    if let ast::TraitTyParamBound(ref t, _) = *t {
-                        let id = ty::trait_ref_to_def_id(cx.tcx, &t.trait_ref);
-                        self.lint(cx, id, t.trait_ref.path.span);
-                    }
-                }
-            }
-            ast::ItemImpl(_, _, _, Some(ref t), _, _) => {
-                let id = ty::trait_ref_to_def_id(cx.tcx, t);
-                self.lint(cx, id, t.path.span);
-            }
-            _ => (/* pass */)
-        }
+    fn check_expr(&mut self, cx: &Context, e: &ast::Expr) {
+        stability::check_expr(cx.tcx, e,
+                              &mut |id, sp, stab| self.lint(cx, id, sp, stab));
     }
 }
 
@@ -2096,9 +1982,9 @@ declare_lint! {
 }
 
 declare_lint! {
-    pub UNKNOWN_FEATURES,
+    pub UNUSED_FEATURES,
     Deny,
-    "unknown features found in crate-level #[feature] directives"
+    "unused or unknown features found in crate-level #[feature] directives"
 }
 
 declare_lint! {
@@ -2142,7 +2028,7 @@ impl LintPass for HardwiredLints {
             DEAD_CODE,
             UNREACHABLE_CODE,
             WARNINGS,
-            UNKNOWN_FEATURES,
+            UNUSED_FEATURES,
             UNKNOWN_CRATE_TYPES,
             VARIANT_SIZE_DIFFERENCES,
             FAT_PTR_TRANSMUTES
diff --git a/src/librustc/lint/context.rs b/src/librustc/lint/context.rs
index d871461dd8a..3a103e42101 100644
--- a/src/librustc/lint/context.rs
+++ b/src/librustc/lint/context.rs
@@ -211,6 +211,7 @@ impl LintStore {
                      UnusedAllocation,
                      MissingCopyImplementations,
                      UnstableFeatures,
+                     Stability,
                      UnconditionalRecursion,
         );
 
@@ -218,7 +219,6 @@ impl LintStore {
                               TypeLimits,
                               RawPointerDerive,
                               MissingDoc,
-                              Stability,
                               MissingDebugImplementations,
         );
 
@@ -236,6 +236,7 @@ impl LintStore {
         // Insert temporary renamings for a one-time deprecation
         self.register_renamed("raw_pointer_deriving", "raw_pointer_derive");
 
+        self.register_renamed("unknown_features", "unused_features");
     }
 
     #[allow(unused_variables)]
@@ -295,15 +296,6 @@ impl LintStore {
             },
             None => unreachable!()
         }
-        match self.by_name.get("unstable") {
-            Some(&Id(lint_id)) => if self.get_level_source(lint_id).0 != Forbid {
-                self.set_level(lint_id, (lvl, ReleaseChannel))
-            },
-            Some(&Renamed(_, lint_id)) => if self.get_level_source(lint_id).0 != Forbid {
-                self.set_level(lint_id, (lvl, ReleaseChannel))
-            },
-            None => unreachable!()
-        }
     }
 }
 
@@ -809,6 +801,5 @@ pub fn check_crate(tcx: &ty::ctxt,
         }
     }
 
-    tcx.sess.abort_if_errors();
     *tcx.node_lint_levels.borrow_mut() = cx.node_levels.into_inner();
 }
diff --git a/src/librustc/middle/astencode.rs b/src/librustc/middle/astencode.rs
index 091ef9d52eb..af41844b2df 100644
--- a/src/librustc/middle/astencode.rs
+++ b/src/librustc/middle/astencode.rs
@@ -904,8 +904,8 @@ impl<'a, 'tcx> rbml_writer_helpers<'tcx> for Encoder<'a> {
                             try!(this.emit_struct_field("method_num", 0, |this| {
                                 this.emit_uint(o.method_num)
                             }));
-                            try!(this.emit_struct_field("real_index", 0, |this| {
-                                this.emit_uint(o.real_index)
+                            try!(this.emit_struct_field("vtable_index", 0, |this| {
+                                this.emit_uint(o.vtable_index)
                             }));
                             Ok(())
                         })
@@ -1492,8 +1492,8 @@ impl<'a, 'tcx> rbml_decoder_decoder_helpers<'tcx> for reader::Decoder<'a> {
                                             this.read_uint()
                                         }).unwrap()
                                     },
-                                    real_index: {
-                                        this.read_struct_field("real_index", 3, |this| {
+                                    vtable_index: {
+                                        this.read_struct_field("vtable_index", 3, |this| {
                                             this.read_uint()
                                         }).unwrap()
                                     },
diff --git a/src/librustc/middle/infer/mod.rs b/src/librustc/middle/infer/mod.rs
index 8fd44f144e1..eaec4fac0a3 100644
--- a/src/librustc/middle/infer/mod.rs
+++ b/src/librustc/middle/infer/mod.rs
@@ -79,16 +79,13 @@ pub struct InferCtxt<'a, 'tcx: 'a> {
     type_variables: RefCell<type_variable::TypeVariableTable<'tcx>>,
 
     // Map from integral variable to the kind of integer it represents
-    int_unification_table:
-        RefCell<UnificationTable<ty::IntVid, Option<IntVarValue>>>,
+    int_unification_table: RefCell<UnificationTable<ty::IntVid>>,
 
     // Map from floating variable to the kind of float it represents
-    float_unification_table:
-        RefCell<UnificationTable<ty::FloatVid, Option<ast::FloatTy>>>,
+    float_unification_table: RefCell<UnificationTable<ty::FloatVid>>,
 
     // For region variables.
-    region_vars:
-        RegionVarBindings<'a, 'tcx>,
+    region_vars: RegionVarBindings<'a, 'tcx>,
 }
 
 /// A map returned by `skolemize_late_bound_regions()` indicating the skolemized
diff --git a/src/librustc/middle/infer/type_variable.rs b/src/librustc/middle/infer/type_variable.rs
index 3f3e4c50e70..4bbc5035799 100644
--- a/src/librustc/middle/infer/type_variable.rs
+++ b/src/librustc/middle/infer/type_variable.rs
@@ -19,7 +19,7 @@ use std::u32;
 use util::snapshot_vec as sv;
 
 pub struct TypeVariableTable<'tcx> {
-    values: sv::SnapshotVec<TypeVariableData<'tcx>,UndoEntry,Delegate>,
+    values: sv::SnapshotVec<Delegate<'tcx>>,
 }
 
 struct TypeVariableData<'tcx> {
@@ -42,7 +42,7 @@ enum UndoEntry {
     Relate(ty::TyVid, ty::TyVid),
 }
 
-struct Delegate;
+struct Delegate<'tcx>;
 
 type Relation = (RelationDir, ty::TyVid);
 
@@ -195,9 +195,12 @@ impl<'tcx> TypeVariableTable<'tcx> {
     }
 }
 
-impl<'tcx> sv::SnapshotVecDelegate<TypeVariableData<'tcx>,UndoEntry> for Delegate {
+impl<'tcx> sv::SnapshotVecDelegate for Delegate<'tcx> {
+    type Value = TypeVariableData<'tcx>;
+    type Undo = UndoEntry;
+
     fn reverse(&mut self,
-               values: &mut Vec<TypeVariableData>,
+               values: &mut Vec<TypeVariableData<'tcx>>,
                action: UndoEntry) {
         match action {
             SpecifyVar(vid, relations) => {
diff --git a/src/librustc/middle/infer/unify.rs b/src/librustc/middle/infer/unify.rs
index ed11cafdca9..e15eb9c0576 100644
--- a/src/librustc/middle/infer/unify.rs
+++ b/src/librustc/middle/infer/unify.rs
@@ -19,7 +19,6 @@ use middle::infer::InferCtxt;
 use std::cell::RefCell;
 use std::fmt::Debug;
 use syntax::ast;
-use util::ppaux::Repr;
 use util::snapshot_vec as sv;
 
 /// This trait is implemented by any type that can serve as a type
@@ -32,7 +31,9 @@ use util::snapshot_vec as sv;
 /// (possibly not yet known) sort of integer.
 ///
 /// Implementations of this trait are at the end of this file.
-pub trait UnifyKey<'tcx, V> : Clone + Debug + PartialEq + Repr<'tcx> {
+pub trait UnifyKey : Clone + Debug + PartialEq {
+    type Value : UnifyValue;
+
     fn index(&self) -> uint;
 
     fn from_index(u: uint) -> Self;
@@ -40,7 +41,7 @@ pub trait UnifyKey<'tcx, V> : Clone + Debug + PartialEq + Repr<'tcx> {
     // Given an inference context, returns the unification table
     // appropriate to this key type.
     fn unification_table<'v>(infcx: &'v InferCtxt)
-                             -> &'v RefCell<UnificationTable<Self,V>>;
+                             -> &'v RefCell<UnificationTable<Self>>;
 
     fn tag(k: Option<Self>) -> &'static str;
 }
@@ -51,7 +52,7 @@ pub trait UnifyKey<'tcx, V> : Clone + Debug + PartialEq + Repr<'tcx> {
 /// whose value is not yet set).
 ///
 /// Implementations of this trait are at the end of this file.
-pub trait UnifyValue<'tcx> : Clone + Repr<'tcx> + PartialEq {
+pub trait UnifyValue : Clone + PartialEq + Debug {
 }
 
 /// Value of a unification key. We implement Tarjan's union-find
@@ -62,21 +63,21 @@ pub trait UnifyValue<'tcx> : Clone + Repr<'tcx> + PartialEq {
 /// to keep the DAG relatively balanced, which helps keep the running
 /// time of the algorithm under control. For more information, see
 /// <http://en.wikipedia.org/wiki/Disjoint-set_data_structure>.
-#[derive(PartialEq,Clone)]
-pub enum VarValue<K,V> {
+#[derive(PartialEq,Clone,Show)]
+pub enum VarValue<K:UnifyKey> {
     Redirect(K),
-    Root(V, uint),
+    Root(K::Value, uint),
 }
 
 /// Table of unification keys and their values.
-pub struct UnificationTable<K,V> {
+pub struct UnificationTable<K:UnifyKey> {
     /// Indicates the current value of each key.
-    values: sv::SnapshotVec<VarValue<K,V>,(),Delegate>,
+    values: sv::SnapshotVec<Delegate<K>>,
 }
 
 /// At any time, users may snapshot a unification table.  The changes
 /// made during the snapshot may either be *committed* or *rolled back*.
-pub struct Snapshot<K> {
+pub struct Snapshot<K:UnifyKey> {
     // Link snapshot to the key type `K` of the table.
     marker: marker::CovariantType<K>,
     snapshot: sv::Snapshot,
@@ -84,22 +85,22 @@ pub struct Snapshot<K> {
 
 /// Internal type used to represent the result of a `get()` operation.
 /// Conveys the current root and value of the key.
-pub struct Node<K,V> {
+pub struct Node<K:UnifyKey> {
     pub key: K,
-    pub value: V,
+    pub value: K::Value,
     pub rank: uint,
 }
 
 #[derive(Copy)]
-pub struct Delegate;
+pub struct Delegate<K>;
 
 // We can't use V:LatticeValue, much as I would like to,
 // because frequently the pattern is that V=Option<U> for some
 // other type parameter U, and we have no way to say
 // Option<U>:LatticeValue.
 
-impl<'tcx, V:PartialEq+Clone+Repr<'tcx>, K:UnifyKey<'tcx, V>> UnificationTable<K,V> {
-    pub fn new() -> UnificationTable<K,V> {
+impl<K:UnifyKey> UnificationTable<K> {
+    pub fn new() -> UnificationTable<K> {
         UnificationTable {
             values: sv::SnapshotVec::new(Delegate),
         }
@@ -126,7 +127,7 @@ impl<'tcx, V:PartialEq+Clone+Repr<'tcx>, K:UnifyKey<'tcx, V>> UnificationTable<K
         self.values.commit(snapshot.snapshot);
     }
 
-    pub fn new_key(&mut self, value: V) -> K {
+    pub fn new_key(&mut self, value: K::Value) -> K {
         let index = self.values.push(Root(value, 0));
         let k = UnifyKey::from_index(index);
         debug!("{}: created new key: {:?}",
@@ -137,12 +138,12 @@ impl<'tcx, V:PartialEq+Clone+Repr<'tcx>, K:UnifyKey<'tcx, V>> UnificationTable<K
 
     /// Find the root node for `vid`. This uses the standard union-find algorithm with path
     /// compression: http://en.wikipedia.org/wiki/Disjoint-set_data_structure
-    pub fn get(&mut self, tcx: &ty::ctxt, vid: K) -> Node<K,V> {
+    pub fn get(&mut self, tcx: &ty::ctxt, vid: K) -> Node<K> {
         let index = vid.index();
         let value = (*self.values.get(index)).clone();
         match value {
             Redirect(redirect) => {
-                let node: Node<K,V> = self.get(tcx, redirect.clone());
+                let node: Node<K> = self.get(tcx, redirect.clone());
                 if node.key != redirect {
                     // Path compression
                     self.values.set(index, Redirect(node.key.clone()));
@@ -164,16 +165,15 @@ impl<'tcx, V:PartialEq+Clone+Repr<'tcx>, K:UnifyKey<'tcx, V>> UnificationTable<K
 
     /// Sets the value for `vid` to `new_value`. `vid` MUST be a root node! Also, we must be in the
     /// middle of a snapshot.
-    pub fn set(&mut self,
-               tcx: &ty::ctxt<'tcx>,
-               key: K,
-               new_value: VarValue<K,V>)
+    pub fn set<'tcx>(&mut self,
+                     _tcx: &ty::ctxt<'tcx>,
+                     key: K,
+                     new_value: VarValue<K>)
     {
         assert!(self.is_root(&key));
 
-        debug!("Updating variable {} to {}",
-               key.repr(tcx),
-               new_value.repr(tcx));
+        debug!("Updating variable {:?} to {:?}",
+               key, new_value);
 
         self.values.set(key.index(), new_value);
     }
@@ -181,16 +181,16 @@ impl<'tcx, V:PartialEq+Clone+Repr<'tcx>, K:UnifyKey<'tcx, V>> UnificationTable<K
     /// Either redirects node_a to node_b or vice versa, depending on the relative rank. Returns
     /// the new root and rank. You should then update the value of the new root to something
     /// suitable.
-    pub fn unify(&mut self,
-                 tcx: &ty::ctxt<'tcx>,
-                 node_a: &Node<K,V>,
-                 node_b: &Node<K,V>)
-                 -> (K, uint)
+    pub fn unify<'tcx>(&mut self,
+                       tcx: &ty::ctxt<'tcx>,
+                       node_a: &Node<K>,
+                       node_b: &Node<K>)
+                       -> (K, uint)
     {
-        debug!("unify(node_a(id={}, rank={}), node_b(id={}, rank={}))",
-               node_a.key.repr(tcx),
+        debug!("unify(node_a(id={:?}, rank={:?}), node_b(id={:?}, rank={:?}))",
+               node_a.key,
                node_a.rank,
-               node_b.key.repr(tcx),
+               node_b.key,
                node_b.rank);
 
         if node_a.rank > node_b.rank {
@@ -212,8 +212,11 @@ impl<'tcx, V:PartialEq+Clone+Repr<'tcx>, K:UnifyKey<'tcx, V>> UnificationTable<K
     }
 }
 
-impl<K,V> sv::SnapshotVecDelegate<VarValue<K,V>,()> for Delegate {
-    fn reverse(&mut self, _: &mut Vec<VarValue<K,V>>, _: ()) {
+impl<K> sv::SnapshotVecDelegate for Delegate<K> {
+    type Value = VarValue<K>;
+    type Undo = ();
+
+    fn reverse(&mut self, _: &mut Vec<VarValue<K>>, _: ()) {
         panic!("Nothing to reverse");
     }
 }
@@ -224,7 +227,7 @@ impl<K,V> sv::SnapshotVecDelegate<VarValue<K,V>,()> for Delegate {
 
 /// Indicates a type that does not have any kind of subtyping
 /// relationship.
-pub trait SimplyUnifiable<'tcx> : Clone + PartialEq + Repr<'tcx> {
+pub trait SimplyUnifiable<'tcx> : Clone + PartialEq + Debug {
     fn to_type(&self, tcx: &ty::ctxt<'tcx>) -> Ty<'tcx>;
     fn to_type_err(expected_found<Self>) -> ty::type_err<'tcx>;
 }
@@ -242,8 +245,11 @@ pub fn err<'tcx, V:SimplyUnifiable<'tcx>>(a_is_expected: bool,
     }
 }
 
-pub trait InferCtxtMethodsForSimplyUnifiableTypes<'tcx, V:SimplyUnifiable<'tcx>,
-                                                  K:UnifyKey<'tcx, Option<V>>> {
+pub trait InferCtxtMethodsForSimplyUnifiableTypes<'tcx,K,V>
+    where K : UnifyKey<Value=Option<V>>,
+          V : SimplyUnifiable<'tcx>,
+          Option<V> : UnifyValue,
+{
     fn simple_vars(&self,
                    a_is_expected: bool,
                    a_id: K,
@@ -257,8 +263,10 @@ pub trait InferCtxtMethodsForSimplyUnifiableTypes<'tcx, V:SimplyUnifiable<'tcx>,
     fn probe_var(&self, a_id: K) -> Option<Ty<'tcx>>;
 }
 
-impl<'a,'tcx,V:SimplyUnifiable<'tcx>,K:UnifyKey<'tcx, Option<V>>>
-    InferCtxtMethodsForSimplyUnifiableTypes<'tcx, V, K> for InferCtxt<'a, 'tcx>
+impl<'a,'tcx,V,K> InferCtxtMethodsForSimplyUnifiableTypes<'tcx,K,V> for InferCtxt<'a,'tcx>
+    where K : UnifyKey<Value=Option<V>>,
+          V : SimplyUnifiable<'tcx>,
+          Option<V> : UnifyValue,
 {
     /// Unifies two simple keys. Because simple keys do not have any subtyping relationships, if
     /// both keys have already been associated with a value, then those two values must be the
@@ -271,8 +279,8 @@ impl<'a,'tcx,V:SimplyUnifiable<'tcx>,K:UnifyKey<'tcx, Option<V>>>
     {
         let tcx = self.tcx;
         let table = UnifyKey::unification_table(self);
-        let node_a = table.borrow_mut().get(tcx, a_id);
-        let node_b = table.borrow_mut().get(tcx, b_id);
+        let node_a: Node<K> = table.borrow_mut().get(tcx, a_id);
+        let node_b: Node<K> = table.borrow_mut().get(tcx, b_id);
         let a_id = node_a.key.clone();
         let b_id = node_b.key.clone();
 
@@ -346,14 +354,14 @@ impl<'a,'tcx,V:SimplyUnifiable<'tcx>,K:UnifyKey<'tcx, Option<V>>>
 
 // Integral type keys
 
-impl<'tcx> UnifyKey<'tcx, Option<IntVarValue>> for ty::IntVid {
+impl UnifyKey for ty::IntVid {
+    type Value = Option<IntVarValue>;
+
     fn index(&self) -> uint { self.index as uint }
 
     fn from_index(i: uint) -> ty::IntVid { ty::IntVid { index: i as u32 } }
 
-    fn unification_table<'v>(infcx: &'v InferCtxt)
-        -> &'v RefCell<UnificationTable<ty::IntVid, Option<IntVarValue>>>
-    {
+    fn unification_table<'v>(infcx: &'v InferCtxt) -> &'v RefCell<UnificationTable<ty::IntVid>> {
         return &infcx.int_unification_table;
     }
 
@@ -375,18 +383,18 @@ impl<'tcx> SimplyUnifiable<'tcx> for IntVarValue {
     }
 }
 
-impl<'tcx> UnifyValue<'tcx> for Option<IntVarValue> { }
+impl UnifyValue for Option<IntVarValue> { }
 
 // Floating point type keys
 
-impl<'tcx> UnifyKey<'tcx, Option<ast::FloatTy>> for ty::FloatVid {
+impl UnifyKey for ty::FloatVid {
+    type Value = Option<ast::FloatTy>;
+
     fn index(&self) -> uint { self.index as uint }
 
     fn from_index(i: uint) -> ty::FloatVid { ty::FloatVid { index: i as u32 } }
 
-    fn unification_table<'v>(infcx: &'v InferCtxt)
-        -> &'v RefCell<UnificationTable<ty::FloatVid, Option<ast::FloatTy>>>
-    {
+    fn unification_table<'v>(infcx: &'v InferCtxt) -> &'v RefCell<UnificationTable<ty::FloatVid>> {
         return &infcx.float_unification_table;
     }
 
@@ -395,7 +403,7 @@ impl<'tcx> UnifyKey<'tcx, Option<ast::FloatTy>> for ty::FloatVid {
     }
 }
 
-impl<'tcx> UnifyValue<'tcx> for Option<ast::FloatTy> {
+impl UnifyValue for Option<ast::FloatTy> {
 }
 
 impl<'tcx> SimplyUnifiable<'tcx> for ast::FloatTy {
@@ -407,12 +415,3 @@ impl<'tcx> SimplyUnifiable<'tcx> for ast::FloatTy {
         ty::terr_float_mismatch(err)
     }
 }
-
-impl<'tcx, K:Repr<'tcx>, V:Repr<'tcx>> Repr<'tcx> for VarValue<K,V> {
-    fn repr(&self, tcx: &ty::ctxt<'tcx>) -> String {
-        match *self {
-            Redirect(ref k) => format!("Redirect({})", k.repr(tcx)),
-            Root(ref v, r) => format!("Root({}, {})", v.repr(tcx), r)
-        }
-    }
-}
diff --git a/src/librustc/middle/stability.rs b/src/librustc/middle/stability.rs
index 1a00e175e0f..7b5af0ab1aa 100644
--- a/src/librustc/middle/stability.rs
+++ b/src/librustc/middle/stability.rs
@@ -11,24 +11,30 @@
 //! A pass that annotates every item and method with its stability level,
 //! propagating default levels lexically from parent to children ast nodes.
 
+use session::Session;
+use lint;
 use middle::ty;
 use metadata::csearch;
-use syntax::codemap::Span;
+use syntax::parse::token::InternedString;
+use syntax::codemap::{Span, DUMMY_SP};
 use syntax::{attr, visit};
 use syntax::ast;
 use syntax::ast::{Attribute, Block, Crate, DefId, FnDecl, NodeId, Variant};
 use syntax::ast::{Item, RequiredMethod, ProvidedMethod, TraitItem};
 use syntax::ast::{TypeMethod, Method, Generics, StructField, TypeTraitItem};
 use syntax::ast_util::is_local;
-use syntax::attr::Stability;
+use syntax::attr::{Stability, AttrMetaMethods};
 use syntax::visit::{FnKind, FkMethod, Visitor};
-use util::nodemap::{NodeMap, DefIdMap};
+use syntax::feature_gate::emit_feature_warn;
+use util::nodemap::{NodeMap, DefIdMap, FnvHashSet, FnvHashMap};
 use util::ppaux::Repr;
 
 use std::mem::replace;
 
 /// A stability index, giving the stability level for items and methods.
 pub struct Index {
+    // Indicates whether this crate has #![feature(staged_api)]
+    staged_api: bool,
     // stability for crate-local items; unmarked stability == no entry
     local: NodeMap<Stability>,
     // cache for extern-crate items; unmarked stability == entry with None
@@ -36,23 +42,24 @@ pub struct Index {
 }
 
 // A private tree-walker for producing an Index.
-struct Annotator {
+struct Annotator<'a> {
+    sess: &'a Session,
     index: Index,
     parent: Option<Stability>
 }
 
-impl Annotator {
+impl<'a> Annotator<'a> {
     // Determine the stability for a node based on its attributes and inherited
     // stability. The stability is recorded in the index and used as the parent.
     fn annotate<F>(&mut self, id: NodeId, use_parent: bool,
-                   attrs: &Vec<Attribute>, f: F) where
+                   attrs: &Vec<Attribute>, item_sp: Span, f: F) where
         F: FnOnce(&mut Annotator),
     {
-        match attr::find_stability(attrs.as_slice()) {
+        match attr::find_stability(self.sess.diagnostic(), attrs.as_slice(), item_sp) {
             Some(stab) => {
                 self.index.local.insert(id, stab.clone());
 
-                // Don't inherit #[stable]
+                // Don't inherit #[stable(feature = "rust1", since = "1.0.0")]
                 if stab.level != attr::Stable {
                     let parent = replace(&mut self.parent, Some(stab));
                     f(self);
@@ -71,7 +78,7 @@ impl Annotator {
     }
 }
 
-impl<'v> Visitor<'v> for Annotator {
+impl<'a, 'v> Visitor<'v> for Annotator<'a> {
     fn visit_item(&mut self, i: &Item) {
         // FIXME (#18969): the following is a hack around the fact
         // that we cannot currently annotate the stability of
@@ -86,72 +93,276 @@ impl<'v> Visitor<'v> for Annotator {
             _ => true,
         };
 
-        self.annotate(i.id, use_parent, &i.attrs, |v| visit::walk_item(v, i));
+        self.annotate(i.id, use_parent, &i.attrs, i.span, |v| visit::walk_item(v, i));
 
         if let ast::ItemStruct(ref sd, _) = i.node {
             sd.ctor_id.map(|id| {
-                self.annotate(id, true, &i.attrs, |_| {})
+                self.annotate(id, true, &i.attrs, i.span, |_| {})
             });
         }
     }
 
     fn visit_fn(&mut self, fk: FnKind<'v>, _: &'v FnDecl,
-                _: &'v Block, _: Span, _: NodeId) {
+                _: &'v Block, sp: Span, _: NodeId) {
         if let FkMethod(_, _, meth) = fk {
             // Methods are not already annotated, so we annotate it
-            self.annotate(meth.id, true, &meth.attrs, |_| {});
+            self.annotate(meth.id, true, &meth.attrs, sp, |_| {});
         }
         // Items defined in a function body have no reason to have
         // a stability attribute, so we don't recurse.
     }
 
     fn visit_trait_item(&mut self, t: &TraitItem) {
-        let (id, attrs) = match *t {
-            RequiredMethod(TypeMethod {id, ref attrs, ..}) => (id, attrs),
+        let (id, attrs, sp) = match *t {
+            RequiredMethod(TypeMethod {id, ref attrs, span, ..}) => (id, attrs, span),
 
             // work around lack of pattern matching for @ types
             ProvidedMethod(ref method) => {
                 match **method {
-                    Method {ref attrs, id, ..} => (id, attrs),
+                    Method {ref attrs, id, span, ..} => (id, attrs, span),
                 }
             }
 
-            TypeTraitItem(ref typedef) => (typedef.ty_param.id, &typedef.attrs),
+            TypeTraitItem(ref typedef) => (typedef.ty_param.id, &typedef.attrs,
+                                           typedef.ty_param.span),
         };
-        self.annotate(id, true, attrs, |v| visit::walk_trait_item(v, t));
+        self.annotate(id, true, attrs, sp, |v| visit::walk_trait_item(v, t));
     }
 
     fn visit_variant(&mut self, var: &Variant, g: &'v Generics) {
-        self.annotate(var.node.id, true, &var.node.attrs,
+        self.annotate(var.node.id, true, &var.node.attrs, var.span,
                       |v| visit::walk_variant(v, var, g))
     }
 
     fn visit_struct_field(&mut self, s: &StructField) {
-        self.annotate(s.node.id, true, &s.node.attrs,
+        self.annotate(s.node.id, true, &s.node.attrs, s.span,
                       |v| visit::walk_struct_field(v, s));
     }
 
     fn visit_foreign_item(&mut self, i: &ast::ForeignItem) {
-        self.annotate(i.id, true, &i.attrs, |_| {});
+        self.annotate(i.id, true, &i.attrs, i.span, |_| {});
     }
 }
 
 impl Index {
     /// Construct the stability index for a crate being compiled.
-    pub fn build(krate: &Crate) -> Index {
+    pub fn build(sess: &Session, krate: &Crate) -> Index {
+        let mut staged_api = false;
+        for attr in krate.attrs.iter() {
+            if attr.name().get() == "staged_api" {
+                match attr.node.value.node {
+                    ast::MetaWord(_) => {
+                        attr::mark_used(attr);
+                        staged_api = true;
+                    }
+                    _ => (/*pass*/)
+                }
+            }
+        }
+        let index = Index {
+            staged_api: staged_api,
+            local: NodeMap(),
+            extern_cache: DefIdMap()
+        };
+        if !staged_api {
+            return index;
+        }
         let mut annotator = Annotator {
-            index: Index {
-                local: NodeMap(),
-                extern_cache: DefIdMap()
-            },
+            sess: sess,
+            index: index,
             parent: None
         };
-        annotator.annotate(ast::CRATE_NODE_ID, true, &krate.attrs,
+        annotator.annotate(ast::CRATE_NODE_ID, true, &krate.attrs, krate.span,
                            |v| visit::walk_crate(v, krate));
         annotator.index
     }
 }
 
+/// Cross-references the feature names of unstable APIs with enabled
+/// features and possibly prints errors. Returns a list of all
+/// features used.
+pub fn check_unstable_api_usage(tcx: &ty::ctxt) -> FnvHashSet<InternedString> {
+    let ref active_lib_features = tcx.sess.features.borrow().lib_features;
+
+    // Put the active features into a map for quick lookup
+    let active_features = active_lib_features.iter().map(|&(ref s, _)| s.clone()).collect();
+
+    let mut checker = Checker {
+        tcx: tcx,
+        active_features: active_features,
+        used_features: FnvHashSet()
+    };
+
+    let krate = tcx.map.krate();
+    visit::walk_crate(&mut checker, krate);
+
+    let used_features = checker.used_features;
+    return used_features;
+}
+
+struct Checker<'a, 'tcx: 'a> {
+    tcx: &'a ty::ctxt<'tcx>,
+    active_features: FnvHashSet<InternedString>,
+    used_features: FnvHashSet<InternedString>
+}
+
+impl<'a, 'tcx> Checker<'a, 'tcx> {
+    fn check(&mut self, id: ast::DefId, span: Span, stab: &Option<Stability>) {
+        // Only the cross-crate scenario matters when checking unstable APIs
+        let cross_crate = !is_local(id);
+        if !cross_crate { return }
+
+        match *stab {
+            Some(Stability { level: attr::Unstable, ref feature, ref reason, .. }) => {
+                self.used_features.insert(feature.clone());
+
+                if !self.active_features.contains(feature) {
+                    let msg = match *reason {
+                        Some(ref r) => format!("use of unstable library feature '{}': {}",
+                                               feature.get(), r.get()),
+                        None => format!("use of unstable library feature '{}'", feature.get())
+                    };
+
+                    emit_feature_warn(&self.tcx.sess.parse_sess.span_diagnostic,
+                                      feature.get(), span, &msg[]);
+                }
+            }
+            Some(..) => {
+                // Stable APIs are always ok to call and deprecated APIs are
+                // handled by a lint.
+            }
+            None => {
+                // This is an 'unmarked' API, which should not exist
+                // in the standard library.
+                self.tcx.sess.span_err(span, "use of unmarked library feature");
+                self.tcx.sess.span_note(span, "this is either a bug in the library you are \
+                                               using or a bug in the compiler - there is \
+                                               no way to use this feature");
+            }
+        }
+    }
+}
+
+impl<'a, 'v, 'tcx> Visitor<'v> for Checker<'a, 'tcx> {
+    fn visit_item(&mut self, item: &ast::Item) {
+        check_item(self.tcx, item,
+                   &mut |id, sp, stab| self.check(id, sp, stab));
+        visit::walk_item(self, item);
+    }
+
+    fn visit_expr(&mut self, ex: &ast::Expr) {
+        check_expr(self.tcx, ex,
+                   &mut |id, sp, stab| self.check(id, sp, stab));
+        visit::walk_expr(self, ex);
+    }
+}
+
+/// Helper for discovering nodes to check for stability
+pub fn check_item(tcx: &ty::ctxt, item: &ast::Item,
+                  cb: &mut FnMut(ast::DefId, Span, &Option<Stability>)) {
+    match item.node {
+        ast::ItemExternCrate(_) => {
+            // compiler-generated `extern crate` items have a dummy span.
+            if item.span == DUMMY_SP { return }
+
+            let cnum = match tcx.sess.cstore.find_extern_mod_stmt_cnum(item.id) {
+                Some(cnum) => cnum,
+                None => return,
+            };
+            let id = ast::DefId { krate: cnum, node: ast::CRATE_NODE_ID };
+            maybe_do_stability_check(tcx, id, item.span, cb);
+        }
+        ast::ItemTrait(_, _, ref supertraits, _) => {
+            for t in supertraits.iter() {
+                if let ast::TraitTyParamBound(ref t, _) = *t {
+                    let id = ty::trait_ref_to_def_id(tcx, &t.trait_ref);
+                    maybe_do_stability_check(tcx, id, t.trait_ref.path.span, cb);
+                }
+            }
+        }
+        ast::ItemImpl(_, _, _, Some(ref t), _, _) => {
+            let id = ty::trait_ref_to_def_id(tcx, t);
+            maybe_do_stability_check(tcx, id, t.path.span, cb);
+        }
+        _ => (/* pass */)
+    }
+}
+
+/// Helper for discovering nodes to check for stability
+pub fn check_expr(tcx: &ty::ctxt, e: &ast::Expr,
+                  cb: &mut FnMut(ast::DefId, Span, &Option<Stability>)) {
+    if is_internal(tcx, e.span) { return; }
+
+    let mut span = e.span;
+
+    let id = match e.node {
+        ast::ExprPath(..) | ast::ExprQPath(..) | ast::ExprStruct(..) => {
+            match tcx.def_map.borrow().get(&e.id) {
+                Some(&def) => def.def_id(),
+                None => return
+            }
+        }
+        ast::ExprMethodCall(i, _, _) => {
+            span = i.span;
+            let method_call = ty::MethodCall::expr(e.id);
+            match tcx.method_map.borrow().get(&method_call) {
+                Some(method) => {
+                    match method.origin {
+                        ty::MethodStatic(def_id) => {
+                            def_id
+                        }
+                        ty::MethodStaticClosure(def_id) => {
+                            def_id
+                        }
+                        ty::MethodTypeParam(ty::MethodParam {
+                            ref trait_ref,
+                            method_num: index,
+                            ..
+                        }) |
+                        ty::MethodTraitObject(ty::MethodObject {
+                            ref trait_ref,
+                            method_num: index,
+                            ..
+                        }) => {
+                            ty::trait_item(tcx, trait_ref.def_id, index).def_id()
+                        }
+                    }
+                }
+                None => return
+            }
+        }
+        _ => return
+    };
+
+    maybe_do_stability_check(tcx, id, span, cb);
+}
+
+fn maybe_do_stability_check(tcx: &ty::ctxt, id: ast::DefId, span: Span,
+                            cb: &mut FnMut(ast::DefId, Span, &Option<Stability>)) {
+    if !is_staged_api(tcx, id) { return  }
+    let ref stability = lookup(tcx, id);
+    cb(id, span, stability);
+}
+
+fn is_internal(tcx: &ty::ctxt, span: Span) -> bool {
+    tcx.sess.codemap().span_is_internal(span)
+}
+
+fn is_staged_api(tcx: &ty::ctxt, id: DefId) -> bool {
+    match ty::trait_item_of_item(tcx, id) {
+        Some(ty::MethodTraitItemId(trait_method_id))
+            if trait_method_id != id => {
+                is_staged_api(tcx, trait_method_id)
+            }
+        _ if is_local(id) => {
+            tcx.stability.borrow().staged_api
+        }
+        _ => {
+            csearch::is_staged_api(&tcx.sess.cstore, id)
+        }
+    }
+}
+
 /// Lookup the stability for a node, loading external crate
 /// metadata as necessary.
 pub fn lookup(tcx: &ty::ctxt, id: DefId) -> Option<Stability> {
@@ -190,18 +401,23 @@ pub fn lookup(tcx: &ty::ctxt, id: DefId) -> Option<Stability> {
     })
 }
 
-pub fn is_staged_api(tcx: &ty::ctxt, id: DefId) -> bool {
-    match ty::trait_item_of_item(tcx, id) {
-        Some(ty::MethodTraitItemId(trait_method_id))
-            if trait_method_id != id => {
-                is_staged_api(tcx, trait_method_id)
-            }
-        _ if is_local(id) => {
-            // Unused case
-            unreachable!()
-        }
-        _ => {
-            csearch::is_staged_api(&tcx.sess.cstore, id)
-        }
+/// Given the list of enabled features that were not language features (i.e. that
+/// were expected to be library features), and the list of features used from
+/// libraries, identify activated features that don't exist and error about them.
+pub fn check_unused_features(sess: &Session,
+                             used_lib_features: &FnvHashSet<InternedString>) {
+    let ref lib_features = sess.features.borrow().lib_features;
+    let mut active_lib_features: FnvHashMap<InternedString, Span>
+        = lib_features.clone().into_iter().collect();
+
+    for used_feature in used_lib_features.iter() {
+        active_lib_features.remove(used_feature);
+    }
+
+    for (_, &span) in active_lib_features.iter() {
+        sess.add_lint(lint::builtin::UNUSED_FEATURES,
+                      ast::CRATE_NODE_ID,
+                      span,
+                      "unused or unknown feature".to_string());
     }
 }
diff --git a/src/librustc/middle/traits/error_reporting.rs b/src/librustc/middle/traits/error_reporting.rs
index 7ccb5e6e711..5e7168b6735 100644
--- a/src/librustc/middle/traits/error_reporting.rs
+++ b/src/librustc/middle/traits/error_reporting.rs
@@ -408,7 +408,7 @@ fn note_obligation_cause_code<'a, 'tcx>(infcx: &InferCtxt<'a, 'tcx>,
         }
         ObligationCauseCode::CompareImplMethodObligation => {
             span_note!(tcx.sess, cause_span,
-                      "the requirement `{}` appears on the impl method\
+                      "the requirement `{}` appears on the impl method \
                       but not on the corresponding trait method",
                       predicate.user_string(infcx.tcx));
         }
diff --git a/src/librustc/middle/traits/fulfill.rs b/src/librustc/middle/traits/fulfill.rs
index d08857c9613..ed058280483 100644
--- a/src/librustc/middle/traits/fulfill.rs
+++ b/src/librustc/middle/traits/fulfill.rs
@@ -394,7 +394,7 @@ fn process_predicate<'a,'tcx>(selcx: &mut SelectionContext<'a,'tcx>,
         ty::Predicate::Projection(ref data) => {
             let project_obligation = obligation.with(data.clone());
             let result = project::poly_project_and_unify_type(selcx, &project_obligation);
-            debug!("poly_project_and_unify_type({}) = {}",
+            debug!("process_predicate: poly_project_and_unify_type({}) returned {}",
                    project_obligation.repr(tcx),
                    result.repr(tcx));
             match result {
diff --git a/src/librustc/middle/traits/mod.rs b/src/librustc/middle/traits/mod.rs
index 8d3888fcfdb..82a4a60cebb 100644
--- a/src/librustc/middle/traits/mod.rs
+++ b/src/librustc/middle/traits/mod.rs
@@ -18,7 +18,7 @@ pub use self::ObligationCauseCode::*;
 use middle::mem_categorization::Typer;
 use middle::subst;
 use middle::ty::{self, Ty};
-use middle::infer::InferCtxt;
+use middle::infer::{self, InferCtxt};
 use std::slice::Iter;
 use std::rc::Rc;
 use syntax::ast;
@@ -392,6 +392,65 @@ pub fn type_known_to_meet_builtin_bound<'a,'tcx>(infcx: &InferCtxt<'a,'tcx>,
     }
 }
 
+pub fn normalize_param_env_or_error<'a,'tcx>(unnormalized_env: ty::ParameterEnvironment<'a,'tcx>,
+                                             cause: ObligationCause<'tcx>)
+                                             -> ty::ParameterEnvironment<'a,'tcx>
+{
+    match normalize_param_env(&unnormalized_env, cause) {
+        Ok(p) => p,
+        Err(errors) => {
+            // I'm not wild about reporting errors here; I'd prefer to
+            // have the errors get reported at a defined place (e.g.,
+            // during typeck). Instead I have all parameter
+            // environments, in effect, going through this function
+            // and hence potentially reporting errors. This ensurse of
+            // course that we never forget to normalize (the
+            // alternative seemed like it would involve a lot of
+            // manual invocations of this fn -- and then we'd have to
+            // deal with the errors at each of those sites).
+            //
+            // In any case, in practice, typeck constructs all the
+            // parameter environments once for every fn as it goes,
+            // and errors will get reported then; so after typeck we
+            // can be sure that no errors should occur.
+            let infcx = infer::new_infer_ctxt(unnormalized_env.tcx);
+            report_fulfillment_errors(&infcx, &errors);
+
+            // Normalized failed? use what they gave us, it's better than nothing.
+            unnormalized_env
+        }
+    }
+}
+
+pub fn normalize_param_env<'a,'tcx>(param_env: &ty::ParameterEnvironment<'a,'tcx>,
+                                    cause: ObligationCause<'tcx>)
+                                    -> Result<ty::ParameterEnvironment<'a,'tcx>,
+                                              Vec<FulfillmentError<'tcx>>>
+{
+    let tcx = param_env.tcx;
+
+    debug!("normalize_param_env(param_env={})",
+           param_env.repr(tcx));
+
+    let predicates: Vec<ty::Predicate<'tcx>> = {
+        let infcx = infer::new_infer_ctxt(tcx);
+        let mut selcx = &mut SelectionContext::new(&infcx, param_env);
+        let mut fulfill_cx = FulfillmentContext::new();
+        let Normalized { value: predicates, obligations } =
+            project::normalize(selcx, cause, &param_env.caller_bounds);
+        for obligation in obligations.into_iter() {
+            fulfill_cx.register_predicate_obligation(selcx.infcx(), obligation);
+        }
+        try!(fulfill_cx.select_all_or_error(selcx.infcx(), param_env));
+        predicates.iter().map(|p| infcx.resolve_type_vars_if_possible(p)).collect()
+    };
+
+    debug!("normalize_param_env: predicates={}",
+           predicates.repr(tcx));
+
+    Ok(param_env.with_caller_bounds(predicates))
+}
+
 impl<'tcx,O> Obligation<'tcx,O> {
     pub fn new(cause: ObligationCause<'tcx>,
                trait_ref: O)
diff --git a/src/librustc/middle/traits/object_safety.rs b/src/librustc/middle/traits/object_safety.rs
index c0399112c33..56c1419502f 100644
--- a/src/librustc/middle/traits/object_safety.rs
+++ b/src/librustc/middle/traits/object_safety.rs
@@ -122,17 +122,15 @@ fn trait_has_sized_self<'tcx>(tcx: &ty::ctxt<'tcx>,
                               trait_def_id: ast::DefId)
                               -> bool
 {
-    let trait_def = ty::lookup_trait_def(tcx, trait_def_id);
-    let param_env = ty::construct_parameter_environment(tcx,
-                                                        &trait_def.generics,
-                                                        ast::DUMMY_NODE_ID);
-    let predicates = param_env.caller_bounds.predicates.as_slice().to_vec();
     let sized_def_id = match tcx.lang_items.sized_trait() {
         Some(def_id) => def_id,
         None => { return false; /* No Sized trait, can't require it! */ }
     };
 
     // Search for a predicate like `Self : Sized` amongst the trait bounds.
+    let trait_def = ty::lookup_trait_def(tcx, trait_def_id);
+    let free_substs = ty::construct_free_substs(tcx, &trait_def.generics, ast::DUMMY_NODE_ID);
+    let predicates = trait_def.generics.to_bounds(tcx, &free_substs).predicates.into_vec();
     elaborate_predicates(tcx, predicates)
         .any(|predicate| {
             match predicate {
diff --git a/src/librustc/middle/traits/project.rs b/src/librustc/middle/traits/project.rs
index ffb38091a87..d1dd086a5a3 100644
--- a/src/librustc/middle/traits/project.rs
+++ b/src/librustc/middle/traits/project.rs
@@ -18,13 +18,17 @@ use super::PredicateObligation;
 use super::SelectionContext;
 use super::SelectionError;
 use super::VtableImplData;
+use super::util;
 
 use middle::infer;
-use middle::subst::Subst;
+use middle::subst::{Subst, Substs};
 use middle::ty::{self, AsPredicate, ReferencesError, RegionEscape,
                  HasProjectionTypes, ToPolyTraitRef, Ty};
 use middle::ty_fold::{self, TypeFoldable, TypeFolder};
 use std::rc::Rc;
+use syntax::ast;
+use syntax::parse::token;
+use util::common::FN_OUTPUT_NAME;
 use util::ppaux::Repr;
 
 pub type PolyProjectionObligation<'tcx> =
@@ -53,6 +57,8 @@ pub struct MismatchedProjectionTypes<'tcx> {
 enum ProjectionTyCandidate<'tcx> {
     ParamEnv(ty::PolyProjectionPredicate<'tcx>),
     Impl(VtableImplData<'tcx, PredicateObligation<'tcx>>),
+    Closure(ast::DefId, Substs<'tcx>),
+    FnPointer(Ty<'tcx>),
 }
 
 struct ProjectionTyCandidateSet<'tcx> {
@@ -60,12 +66,17 @@ struct ProjectionTyCandidateSet<'tcx> {
     ambiguous: bool
 }
 
+/// Evaluates constraints of the form:
+///
+///     for<...> <T as Trait>::U == V
+///
+/// If successful, this may result in additional obligations.
 pub fn poly_project_and_unify_type<'cx,'tcx>(
     selcx: &mut SelectionContext<'cx,'tcx>,
     obligation: &PolyProjectionObligation<'tcx>)
     -> Result<Option<Vec<PredicateObligation<'tcx>>>, MismatchedProjectionTypes<'tcx>>
 {
-    debug!("poly_project(obligation={})",
+    debug!("poly_project_and_unify_type(obligation={})",
            obligation.repr(selcx.tcx()));
 
     let infcx = selcx.infcx();
@@ -102,14 +113,17 @@ pub fn poly_project_and_unify_type<'cx,'tcx>(
     }
 }
 
-/// Compute result of projecting an associated type and unify it with
-/// `obligation.predicate.ty` (if we can).
+/// Evaluates constraints of the form:
+///
+///     <T as Trait>::U == V
+///
+/// If successful, this may result in additional obligations.
 fn project_and_unify_type<'cx,'tcx>(
     selcx: &mut SelectionContext<'cx,'tcx>,
     obligation: &ProjectionObligation<'tcx>)
     -> Result<Option<Vec<PredicateObligation<'tcx>>>, MismatchedProjectionTypes<'tcx>>
 {
-    debug!("project_and_unify(obligation={})",
+    debug!("project_and_unify_type(obligation={})",
            obligation.repr(selcx.tcx()));
 
     let Normalized { value: normalized_ty, obligations } =
@@ -133,6 +147,10 @@ fn project_and_unify_type<'cx,'tcx>(
     }
 }
 
+/// Normalizes any associated type projections in `value`, replacing
+/// them with a fully resolved type where possible. The return value
+/// combines the normalized result and any additional obligations that
+/// were incurred as result.
 pub fn normalize<'a,'b,'tcx,T>(selcx: &'a mut SelectionContext<'b,'tcx>,
                                cause: ObligationCause<'tcx>,
                                value: &T)
@@ -142,6 +160,7 @@ pub fn normalize<'a,'b,'tcx,T>(selcx: &'a mut SelectionContext<'b,'tcx>,
     normalize_with_depth(selcx, cause, 0, value)
 }
 
+/// As `normalize`, but with a custom depth.
 pub fn normalize_with_depth<'a,'b,'tcx,T>(selcx: &'a mut SelectionContext<'b,'tcx>,
                                           cause: ObligationCause<'tcx>,
                                           depth: uint,
@@ -251,6 +270,12 @@ impl<'tcx,T> Normalized<'tcx,T> {
     }
 }
 
+/// The guts of `normalize`: normalize a specific projection like `<T
+/// as Trait>::Item`. The result is always a type (and possibly
+/// additional obligations). If ambiguity arises, which implies that
+/// there are unresolved type variables in the projection, we will
+/// substitute a fresh type variable `$X` and generate a new
+/// obligation `<T as Trait>::Item == $X` for later.
 pub fn normalize_projection_type<'a,'b,'tcx>(
     selcx: &'a mut SelectionContext<'b,'tcx>,
     projection_ty: ty::ProjectionTy<'tcx>,
@@ -277,6 +302,10 @@ pub fn normalize_projection_type<'a,'b,'tcx>(
         })
 }
 
+/// The guts of `normalize`: normalize a specific projection like `<T
+/// as Trait>::Item`. The result is always a type (and possibly
+/// additional obligations). Returns `None` in the case of ambiguity,
+/// which indicates that there are unbound type variables.
 fn opt_normalize_projection_type<'a,'b,'tcx>(
     selcx: &'a mut SelectionContext<'b,'tcx>,
     projection_ty: ty::ProjectionTy<'tcx>,
@@ -440,8 +469,7 @@ fn assemble_candidates_from_param_env<'cx,'tcx>(
     obligation_trait_ref: &Rc<ty::TraitRef<'tcx>>,
     candidate_set: &mut ProjectionTyCandidateSet<'tcx>)
 {
-    let env_predicates = selcx.param_env().caller_bounds.predicates.clone();
-    let env_predicates = env_predicates.iter().cloned().collect();
+    let env_predicates = selcx.param_env().caller_bounds.clone();
     assemble_candidates_from_predicates(selcx, obligation, obligation_trait_ref,
                                         candidate_set, env_predicates);
 }
@@ -464,20 +492,22 @@ fn assemble_candidates_from_predicates<'cx,'tcx>(
 
                 let is_match = same_name && infcx.probe(|_| {
                     let origin = infer::Misc(obligation.cause.span);
-                    let obligation_poly_trait_ref =
-                        obligation_trait_ref.to_poly_trait_ref();
                     let data_poly_trait_ref =
                         data.to_poly_trait_ref();
+                    let obligation_poly_trait_ref =
+                        obligation_trait_ref.to_poly_trait_ref();
                     infcx.sub_poly_trait_refs(false,
                                               origin,
-                                              obligation_poly_trait_ref,
-                                              data_poly_trait_ref).is_ok()
+                                              data_poly_trait_ref,
+                                              obligation_poly_trait_ref).is_ok()
                 });
 
-                if is_match {
-                    debug!("assemble_candidates_from_predicates: candidate {}",
-                           data.repr(selcx.tcx()));
+                debug!("assemble_candidates_from_predicates: candidate {} is_match {} same_name {}",
+                       data.repr(selcx.tcx()),
+                       is_match,
+                       same_name);
 
+                if is_match {
                     candidate_set.vec.push(
                         ProjectionTyCandidate::ParamEnv(data.clone()));
                 }
@@ -551,6 +581,14 @@ fn assemble_candidates_from_impls<'cx,'tcx>(
                 selcx, obligation, obligation_trait_ref, candidate_set,
                 data.object_ty);
         }
+        super::VtableClosure(closure_def_id, substs) => {
+            candidate_set.vec.push(
+                ProjectionTyCandidate::Closure(closure_def_id, substs));
+        }
+        super::VtableFnPointer(fn_type) => {
+            candidate_set.vec.push(
+                ProjectionTyCandidate::FnPointer(fn_type));
+        }
         super::VtableParam(..) => {
             // This case tell us nothing about the value of an
             // associated type. Consider:
@@ -578,9 +616,7 @@ fn assemble_candidates_from_impls<'cx,'tcx>(
             // projection. And the projection where clause is handled
             // in `assemble_candidates_from_param_env`.
         }
-        super::VtableBuiltin(..) |
-        super::VtableClosure(..) |
-        super::VtableFnPointer(..) => {
+        super::VtableBuiltin(..) => {
             // These traits have no associated types.
             selcx.tcx().sess.span_bug(
                 obligation.cause.span,
@@ -606,67 +642,150 @@ fn confirm_candidate<'cx,'tcx>(
 
     match candidate {
         ProjectionTyCandidate::ParamEnv(poly_projection) => {
-            let projection =
-                infcx.replace_late_bound_regions_with_fresh_var(
-                    obligation.cause.span,
-                    infer::LateBoundRegionConversionTime::HigherRankedType,
-                    &poly_projection).0;
-
-            assert_eq!(projection.projection_ty.item_name,
-                       obligation.predicate.item_name);
-
-            let origin = infer::RelateOutputImplTypes(obligation.cause.span);
-            match infcx.sub_trait_refs(false,
-                                       origin,
-                                       obligation.predicate.trait_ref.clone(),
-                                       projection.projection_ty.trait_ref.clone()) {
-                Ok(()) => { }
-                Err(e) => {
-                    selcx.tcx().sess.span_bug(
-                        obligation.cause.span,
-                        format!("Failed to unify `{}` and `{}` in projection: {}",
-                                obligation.repr(selcx.tcx()),
-                                projection.repr(selcx.tcx()),
-                                ty::type_err_to_str(selcx.tcx(), &e)).as_slice());
-                }
-            }
-
-            (projection.ty, vec!())
+            confirm_param_env_candidate(selcx, obligation, poly_projection)
         }
 
         ProjectionTyCandidate::Impl(impl_vtable) => {
-            // there don't seem to be nicer accessors to these:
-            let impl_items_map = selcx.tcx().impl_items.borrow();
-            let impl_or_trait_items_map = selcx.tcx().impl_or_trait_items.borrow();
-
-            let impl_items = &impl_items_map[impl_vtable.impl_def_id];
-            let mut impl_ty = None;
-            for impl_item in impl_items.iter() {
-                let assoc_type = match impl_or_trait_items_map[impl_item.def_id()] {
-                    ty::TypeTraitItem(ref assoc_type) => assoc_type.clone(),
-                    ty::MethodTraitItem(..) => { continue; }
-                };
-
-                if assoc_type.name != obligation.predicate.item_name {
-                    continue;
-                }
+            confirm_impl_candidate(selcx, obligation, impl_vtable)
+        }
 
-                let impl_poly_ty = ty::lookup_item_type(selcx.tcx(), assoc_type.def_id);
-                impl_ty = Some(impl_poly_ty.ty.subst(selcx.tcx(), &impl_vtable.substs));
-                break;
-            }
+        ProjectionTyCandidate::Closure(def_id, substs) => {
+            confirm_closure_candidate(selcx, obligation, def_id, &substs)
+        }
 
-            match impl_ty {
-                Some(ty) => (ty, impl_vtable.nested.into_vec()),
-                None => {
-                    // This means that the impl is missing a
-                    // definition for the associated type. This error
-                    // ought to be reported by the type checker method
-                    // `check_impl_items_against_trait`, so here we
-                    // just return ty_err.
-                    (selcx.tcx().types.err, vec!())
-                }
-            }
+        ProjectionTyCandidate::FnPointer(fn_type) => {
+            confirm_fn_pointer_candidate(selcx, obligation, fn_type)
+        }
+    }
+}
+
+fn confirm_fn_pointer_candidate<'cx,'tcx>(
+    selcx: &mut SelectionContext<'cx,'tcx>,
+    obligation: &ProjectionTyObligation<'tcx>,
+    fn_type: Ty<'tcx>)
+    -> (Ty<'tcx>, Vec<PredicateObligation<'tcx>>)
+{
+    let fn_type = selcx.infcx().shallow_resolve(fn_type);
+    let sig = ty::ty_fn_sig(fn_type);
+    confirm_callable_candidate(selcx, obligation, sig, util::TupleArgumentsFlag::Yes)
+}
+
+fn confirm_closure_candidate<'cx,'tcx>(
+    selcx: &mut SelectionContext<'cx,'tcx>,
+    obligation: &ProjectionTyObligation<'tcx>,
+    closure_def_id: ast::DefId,
+    substs: &Substs<'tcx>)
+    -> (Ty<'tcx>, Vec<PredicateObligation<'tcx>>)
+{
+    let closure_typer = selcx.closure_typer();
+    let closure_type = closure_typer.closure_type(closure_def_id, substs);
+    confirm_callable_candidate(selcx, obligation, &closure_type.sig, util::TupleArgumentsFlag::No)
+}
+
+fn confirm_callable_candidate<'cx,'tcx>(
+    selcx: &mut SelectionContext<'cx,'tcx>,
+    obligation: &ProjectionTyObligation<'tcx>,
+    fn_sig: &ty::PolyFnSig<'tcx>,
+    flag: util::TupleArgumentsFlag)
+    -> (Ty<'tcx>, Vec<PredicateObligation<'tcx>>)
+{
+    let tcx = selcx.tcx();
+
+    debug!("confirm_closure_candidate({},{})",
+           obligation.repr(tcx),
+           fn_sig.repr(tcx));
+
+    // Note: we unwrap the binder here but re-create it below (1)
+    let ty::Binder((trait_ref, ret_type)) =
+        util::closure_trait_ref_and_return_type(tcx,
+                                                obligation.predicate.trait_ref.def_id,
+                                                obligation.predicate.trait_ref.self_ty(),
+                                                fn_sig,
+                                                flag);
+
+    let predicate = ty::Binder(ty::ProjectionPredicate { // (1) recreate binder here
+        projection_ty: ty::ProjectionTy {
+            trait_ref: trait_ref,
+            item_name: token::intern(FN_OUTPUT_NAME),
+        },
+        ty: ret_type
+    });
+
+    confirm_param_env_candidate(selcx, obligation, predicate)
+}
+
+fn confirm_param_env_candidate<'cx,'tcx>(
+    selcx: &mut SelectionContext<'cx,'tcx>,
+    obligation: &ProjectionTyObligation<'tcx>,
+    poly_projection: ty::PolyProjectionPredicate<'tcx>)
+    -> (Ty<'tcx>, Vec<PredicateObligation<'tcx>>)
+{
+    let infcx = selcx.infcx();
+
+    let projection =
+        infcx.replace_late_bound_regions_with_fresh_var(
+            obligation.cause.span,
+            infer::LateBoundRegionConversionTime::HigherRankedType,
+            &poly_projection).0;
+
+    assert_eq!(projection.projection_ty.item_name,
+               obligation.predicate.item_name);
+
+    let origin = infer::RelateOutputImplTypes(obligation.cause.span);
+    match infcx.sub_trait_refs(false,
+                               origin,
+                               obligation.predicate.trait_ref.clone(),
+                               projection.projection_ty.trait_ref.clone()) {
+        Ok(()) => { }
+        Err(e) => {
+            selcx.tcx().sess.span_bug(
+                obligation.cause.span,
+                format!("Failed to unify `{}` and `{}` in projection: {}",
+                        obligation.repr(selcx.tcx()),
+                        projection.repr(selcx.tcx()),
+                        ty::type_err_to_str(selcx.tcx(), &e)).as_slice());
+        }
+    }
+
+    (projection.ty, vec!())
+}
+
+fn confirm_impl_candidate<'cx,'tcx>(
+    selcx: &mut SelectionContext<'cx,'tcx>,
+    obligation: &ProjectionTyObligation<'tcx>,
+    impl_vtable: VtableImplData<'tcx, PredicateObligation<'tcx>>)
+    -> (Ty<'tcx>, Vec<PredicateObligation<'tcx>>)
+{
+    // there don't seem to be nicer accessors to these:
+    let impl_items_map = selcx.tcx().impl_items.borrow();
+    let impl_or_trait_items_map = selcx.tcx().impl_or_trait_items.borrow();
+
+    let impl_items = &impl_items_map[impl_vtable.impl_def_id];
+    let mut impl_ty = None;
+    for impl_item in impl_items.iter() {
+        let assoc_type = match impl_or_trait_items_map[impl_item.def_id()] {
+            ty::TypeTraitItem(ref assoc_type) => assoc_type.clone(),
+            ty::MethodTraitItem(..) => { continue; }
+        };
+
+        if assoc_type.name != obligation.predicate.item_name {
+            continue;
+        }
+
+        let impl_poly_ty = ty::lookup_item_type(selcx.tcx(), assoc_type.def_id);
+        impl_ty = Some(impl_poly_ty.ty.subst(selcx.tcx(), &impl_vtable.substs));
+        break;
+    }
+
+    match impl_ty {
+        Some(ty) => (ty, impl_vtable.nested.into_vec()),
+        None => {
+            // This means that the impl is missing a
+            // definition for the associated type. This error
+            // ought to be reported by the type checker method
+            // `check_impl_items_against_trait`, so here we
+            // just return ty_err.
+            (selcx.tcx().types.err, vec!())
         }
     }
 }
@@ -688,7 +807,11 @@ impl<'tcx> Repr<'tcx> for ProjectionTyCandidate<'tcx> {
             ProjectionTyCandidate::ParamEnv(ref data) =>
                 format!("ParamEnv({})", data.repr(tcx)),
             ProjectionTyCandidate::Impl(ref data) =>
-                format!("Impl({})", data.repr(tcx))
+                format!("Impl({})", data.repr(tcx)),
+            ProjectionTyCandidate::Closure(ref a, ref b) =>
+                format!("Closure(({},{}))", a.repr(tcx), b.repr(tcx)),
+            ProjectionTyCandidate::FnPointer(a) =>
+                format!("FnPointer(({}))", a.repr(tcx)),
         }
     }
 }
diff --git a/src/librustc/middle/traits/select.rs b/src/librustc/middle/traits/select.rs
index b2e8bbe059f..4d5f3d925b0 100644
--- a/src/librustc/middle/traits/select.rs
+++ b/src/librustc/middle/traits/select.rs
@@ -214,6 +214,10 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
         self.closure_typer.param_env()
     }
 
+    pub fn closure_typer(&self) -> &'cx (ty::ClosureTyper<'tcx>+'cx) {
+        self.closure_typer
+    }
+
     ///////////////////////////////////////////////////////////////////////////
     // Selection
     //
@@ -526,9 +530,13 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
 
         // If no match, compute result and insert into cache.
         let candidate = self.candidate_from_obligation_no_cache(stack);
-        debug!("CACHE MISS: cache_fresh_trait_pred={}, candidate={}",
-               cache_fresh_trait_pred.repr(self.tcx()), candidate.repr(self.tcx()));
-        self.insert_candidate_cache(cache_fresh_trait_pred, candidate.clone());
+
+        if self.should_update_candidate_cache(&cache_fresh_trait_pred, &candidate) {
+            debug!("CACHE MISS: cache_fresh_trait_pred={}, candidate={}",
+                   cache_fresh_trait_pred.repr(self.tcx()), candidate.repr(self.tcx()));
+            self.insert_candidate_cache(cache_fresh_trait_pred, candidate.clone());
+        }
+
         candidate
     }
 
@@ -705,6 +713,47 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
         hashmap.insert(cache_fresh_trait_pred.0.trait_ref.clone(), candidate);
     }
 
+    fn should_update_candidate_cache(&mut self,
+                                     cache_fresh_trait_pred: &ty::PolyTraitPredicate<'tcx>,
+                                     candidate: &SelectionResult<'tcx, SelectionCandidate<'tcx>>)
+                                     -> bool
+    {
+        // In general, it's a good idea to cache results, even
+        // ambigious ones, to save us some trouble later. But we have
+        // to be careful not to cache results that could be
+        // invalidated later by advances in inference. Normally, this
+        // is not an issue, because any inference variables whose
+        // types are not yet bound are "freshened" in the cache key,
+        // which means that if we later get the same request once that
+        // type variable IS bound, we'll have a different cache key.
+        // For example, if we have `Vec<_#0t> : Foo`, and `_#0t` is
+        // not yet known, we may cache the result as `None`. But if
+        // later `_#0t` is bound to `Bar`, then when we freshen we'll
+        // have `Vec<Bar> : Foo` as the cache key.
+        //
+        // HOWEVER, it CAN happen that we get an ambiguity result in
+        // one particular case around closures where the cache key
+        // would not change. That is when the precise types of the
+        // upvars that a closure references have not yet been figured
+        // out (i.e., because it is not yet known if they are captured
+        // by ref, and if by ref, what kind of ref). In these cases,
+        // when matching a builtin bound, we will yield back an
+        // ambiguous result. But the *cache key* is just the closure type,
+        // it doesn't capture the state of the upvar computation.
+        //
+        // To avoid this trap, just don't cache ambiguous results if
+        // the self-type contains no inference byproducts (that really
+        // shouldn't happen in other circumstances anyway, given
+        // coherence).
+
+        match *candidate {
+            Ok(Some(_)) | Err(_) => true,
+            Ok(None) => {
+                cache_fresh_trait_pred.0.input_types().iter().any(|&t| ty::type_has_ty_infer(t))
+            }
+        }
+    }
+
     fn assemble_candidates<'o>(&mut self,
                                stack: &TraitObligationStack<'o, 'tcx>)
                                -> Result<SelectionCandidateSet<'tcx>, SelectionError<'tcx>>
@@ -788,6 +837,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
                 // FIXME(#20297) -- being strict about this can cause
                 // inference failures with BorrowFrom, which is
                 // unfortunate. Can we do better here?
+                debug!("assemble_candidates_for_projected_tys: ambiguous self-type");
                 candidates.ambiguous = true;
                 return;
             }
@@ -905,7 +955,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
                stack.obligation.repr(self.tcx()));
 
         let caller_trait_refs: Vec<_> =
-            self.param_env().caller_bounds.predicates.iter()
+            self.param_env().caller_bounds.iter()
             .filter_map(|o| o.to_opt_poly_trait_ref())
             .collect();
 
@@ -962,6 +1012,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
         let (closure_def_id, substs) = match self_ty.sty {
             ty::ty_closure(id, _, ref substs) => (id, substs.clone()),
             ty::ty_infer(ty::TyVar(_)) => {
+                debug!("assemble_unboxed_closure_candidates: ambiguous self-type");
                 candidates.ambiguous = true;
                 return Ok(());
             }
@@ -1000,6 +1051,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
         let self_ty = self.infcx.shallow_resolve(obligation.self_ty());
         match self_ty.sty {
             ty::ty_infer(ty::TyVar(_)) => {
+                debug!("assemble_fn_pointer_candidates: ambiguous self-type");
                 candidates.ambiguous = true; // could wind up being a fn() type
             }
 
@@ -1270,7 +1322,10 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
                 Ok(())
             }
             Ok(ParameterBuiltin) => { Ok(()) }
-            Ok(AmbiguousBuiltin) => { Ok(candidates.ambiguous = true) }
+            Ok(AmbiguousBuiltin) => {
+                debug!("assemble_builtin_bound_candidates: ambiguous builtin");
+                Ok(candidates.ambiguous = true)
+            }
             Err(e) => { Err(e) }
         }
     }
@@ -1476,6 +1531,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
                         Ok(If(upvars.iter().map(|c| c.ty).collect()))
                     }
                     None => {
+                        debug!("assemble_builtin_bound_candidates: no upvar types available yet");
                         Ok(AmbiguousBuiltin)
                     }
                 }
@@ -1512,6 +1568,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
                 // Unbound type variable. Might or might not have
                 // applicable impls and so forth, depending on what
                 // those type variables wind up being bound to.
+                debug!("assemble_builtin_bound_candidates: ambiguous builtin");
                 Ok(AmbiguousBuiltin)
             }
 
@@ -1860,33 +1917,14 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
                obligation.repr(self.tcx()));
 
         let self_ty = self.infcx.shallow_resolve(obligation.self_ty());
-        let sig = match self_ty.sty {
-            ty::ty_bare_fn(_, &ty::BareFnTy {
-                unsafety: ast::Unsafety::Normal,
-                abi: abi::Rust,
-                ref sig
-            }) => {
-                sig
-            }
-            _ => {
-                self.tcx().sess.span_bug(
-                    obligation.cause.span,
-                    &format!("Fn pointer candidate for inappropriate self type: {}",
-                            self_ty.repr(self.tcx()))[]);
-            }
-        };
-
-        let arguments_tuple = ty::mk_tup(self.tcx(), sig.0.inputs.to_vec());
-        let output_type = sig.0.output.unwrap();
-        let substs =
-            Substs::new_trait(
-                vec![arguments_tuple, output_type],
-                vec![],
-                self_ty);
-        let trait_ref = ty::Binder(Rc::new(ty::TraitRef {
-            def_id: obligation.predicate.def_id(),
-            substs: self.tcx().mk_substs(substs),
-        }));
+        let sig = ty::ty_fn_sig(self_ty);
+        let ty::Binder((trait_ref, _)) =
+            util::closure_trait_ref_and_return_type(self.tcx(),
+                                                    obligation.predicate.def_id(),
+                                                    self_ty,
+                                                    sig,
+                                                    util::TupleArgumentsFlag::Yes);
+        let trait_ref = ty::Binder(trait_ref);
 
         try!(self.confirm_poly_trait_refs(obligation.cause.clone(),
                                           obligation.predicate.to_poly_trait_ref(),
@@ -1905,23 +1943,9 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
                closure_def_id.repr(self.tcx()),
                substs.repr(self.tcx()));
 
-        let closure_type = self.closure_typer.closure_type(closure_def_id, substs);
-
-        debug!("confirm_closure_candidate: closure_def_id={} closure_type={}",
-               closure_def_id.repr(self.tcx()),
-               closure_type.repr(self.tcx()));
-
-        let closure_sig = &closure_type.sig;
-        let arguments_tuple = closure_sig.0.inputs[0];
-        let trait_substs =
-            Substs::new_trait(
-                vec![arguments_tuple, closure_sig.0.output.unwrap()],
-                vec![],
-                obligation.self_ty());
-        let trait_ref = ty::Binder(Rc::new(ty::TraitRef {
-            def_id: obligation.predicate.def_id(),
-            substs: self.tcx().mk_substs(trait_substs),
-        }));
+        let trait_ref = self.closure_trait_ref(obligation,
+                                               closure_def_id,
+                                               substs);
 
         debug!("confirm_closure_candidate(closure_def_id={}, trait_ref={})",
                closure_def_id.repr(self.tcx()),
@@ -2104,16 +2128,10 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
                                     where_clause_trait_ref: ty::PolyTraitRef<'tcx>)
                                     -> Result<Vec<PredicateObligation<'tcx>>,()>
     {
-        let where_clause_trait_ref =
-            project::normalize_with_depth(self,
-                                          obligation.cause.clone(),
-                                          obligation.recursion_depth+1,
-                                          &where_clause_trait_ref);
-
         let () =
-            try!(self.match_poly_trait_ref(obligation, where_clause_trait_ref.value.clone()));
+            try!(self.match_poly_trait_ref(obligation, where_clause_trait_ref));
 
-        Ok(where_clause_trait_ref.obligations)
+        Ok(Vec::new())
     }
 
     /// Returns `Ok` if `poly_trait_ref` being true implies that the
@@ -2233,6 +2251,29 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
         }
     }
 
+    fn closure_trait_ref(&self,
+                         obligation: &TraitObligation<'tcx>,
+                         closure_def_id: ast::DefId,
+                         substs: &Substs<'tcx>)
+                         -> ty::PolyTraitRef<'tcx>
+    {
+        let closure_type = self.closure_typer.closure_type(closure_def_id, substs);
+        let ty::Binder((trait_ref, _)) =
+            util::closure_trait_ref_and_return_type(self.tcx(),
+                                                    obligation.predicate.def_id(),
+                                                    obligation.predicate.0.self_ty(), // (1)
+                                                    &closure_type.sig,
+                                                    util::TupleArgumentsFlag::No);
+
+        // (1) Feels icky to skip the binder here, but OTOH we know
+        // that the self-type is an unboxed closure type and hence is
+        // in fact unparameterized (or at least does not reference any
+        // regions bound in the obligation). Still probably some
+        // refactoring could make this nicer.
+
+        ty::Binder(trait_ref)
+    }
+
     fn impl_obligations(&mut self,
                         cause: ObligationCause<'tcx>,
                         recursion_depth: uint,
diff --git a/src/librustc/middle/traits/util.rs b/src/librustc/middle/traits/util.rs
index beb28260834..edeca83d569 100644
--- a/src/librustc/middle/traits/util.rs
+++ b/src/librustc/middle/traits/util.rs
@@ -329,28 +329,67 @@ pub fn upcast<'tcx>(tcx: &ty::ctxt<'tcx>,
 pub fn get_vtable_index_of_object_method<'tcx>(tcx: &ty::ctxt<'tcx>,
                                                object_trait_ref: ty::PolyTraitRef<'tcx>,
                                                trait_def_id: ast::DefId,
-                                               method_index_in_trait: uint) -> uint {
+                                               method_offset_in_trait: uint) -> uint {
     // We need to figure the "real index" of the method in a
     // listing of all the methods of an object. We do this by
     // iterating down the supertraits of the object's trait until
     // we find the trait the method came from, counting up the
     // methods from them.
     let mut method_count = 0;
-    ty::each_bound_trait_and_supertraits(tcx, &[object_trait_ref], |bound_ref| {
+
+    for bound_ref in transitive_bounds(tcx, &[object_trait_ref]) {
         if bound_ref.def_id() == trait_def_id {
-            false
-        } else {
-            let trait_items = ty::trait_items(tcx, bound_ref.def_id());
-            for trait_item in trait_items.iter() {
-                match *trait_item {
-                    ty::MethodTraitItem(_) => method_count += 1,
-                    ty::TypeTraitItem(_) => {}
-                }
+            break;
+        }
+
+        let trait_items = ty::trait_items(tcx, bound_ref.def_id());
+        for trait_item in trait_items.iter() {
+            match *trait_item {
+                ty::MethodTraitItem(_) => method_count += 1,
+                ty::TypeTraitItem(_) => {}
             }
-            true
         }
+    }
+
+    // count number of methods preceding the one we are selecting and
+    // add them to the total offset; skip over associated types.
+    let trait_items = ty::trait_items(tcx, trait_def_id);
+    for trait_item in trait_items.iter().take(method_offset_in_trait) {
+        match *trait_item {
+            ty::MethodTraitItem(_) => method_count += 1,
+            ty::TypeTraitItem(_) => {}
+        }
+    }
+
+    // the item at the offset we were given really ought to be a method
+    assert!(match trait_items[method_offset_in_trait] {
+        ty::MethodTraitItem(_) => true,
+        ty::TypeTraitItem(_) => false
+    });
+
+    method_count
+}
+
+pub enum TupleArgumentsFlag { Yes, No }
+
+pub fn closure_trait_ref_and_return_type<'tcx>(
+    tcx: &ty::ctxt<'tcx>,
+    fn_trait_def_id: ast::DefId,
+    self_ty: Ty<'tcx>,
+    sig: &ty::PolyFnSig<'tcx>,
+    tuple_arguments: TupleArgumentsFlag)
+    -> ty::Binder<(Rc<ty::TraitRef<'tcx>>, Ty<'tcx>)>
+{
+    let arguments_tuple = match tuple_arguments {
+        TupleArgumentsFlag::No => sig.0.inputs[0],
+        TupleArgumentsFlag::Yes => ty::mk_tup(tcx, sig.0.inputs.to_vec()),
+    };
+    let trait_substs = Substs::new_trait(vec![arguments_tuple], vec![], self_ty);
+    let trait_ref = Rc::new(ty::TraitRef {
+        def_id: fn_trait_def_id,
+        substs: tcx.mk_substs(trait_substs),
     });
-    method_count + method_index_in_trait
+    ty::Binder((trait_ref, sig.0.output.unwrap()))
 }
 
 impl<'tcx,O:Repr<'tcx>> Repr<'tcx> for super::Obligation<'tcx, O> {
diff --git a/src/librustc/middle/ty.rs b/src/librustc/middle/ty.rs
index 86cf030c828..062ddd23d9d 100644
--- a/src/librustc/middle/ty.rs
+++ b/src/librustc/middle/ty.rs
@@ -452,7 +452,10 @@ pub struct MethodParam<'tcx> {
     // never contains bound regions; those regions should have been
     // instantiated with fresh variables at this point.
     pub trait_ref: Rc<ty::TraitRef<'tcx>>,
-    // index of uint in the list of methods for the trait
+
+    // index of uint in the list of trait items. Note that this is NOT
+    // the index into the vtable, because the list of trait items
+    // includes associated types.
     pub method_num: uint,
 
     /// The impl for the trait from which the method comes. This
@@ -471,14 +474,14 @@ pub struct MethodObject<'tcx> {
     // the actual base trait id of the object
     pub object_trait_id: ast::DefId,
 
-    // index of the method to be invoked amongst the trait's methods
+    // index of the method to be invoked amongst the trait's items
     pub method_num: uint,
 
     // index into the actual runtime vtable.
     // the vtable is formed by concatenating together the method lists of
-    // the base object trait and all supertraits;  this is the index into
+    // the base object trait and all supertraits; this is the index into
     // that vtable
-    pub real_index: uint,
+    pub vtable_index: uint,
 }
 
 #[derive(Clone)]
@@ -2084,11 +2087,7 @@ impl<'tcx> TraitRef<'tcx> {
 pub struct ParameterEnvironment<'a, 'tcx:'a> {
     pub tcx: &'a ctxt<'tcx>,
 
-    /// A substitution that can be applied to move from
-    /// the "outer" view of a type or method to the "inner" view.
-    /// In general, this means converting from bound parameters to
-    /// free parameters. Since we currently represent bound/free type
-    /// parameters in the same way, this only has an effect on regions.
+    /// See `construct_free_substs` for details.
     pub free_substs: Substs<'tcx>,
 
     /// Each type parameter has an implicit region bound that
@@ -2100,7 +2099,7 @@ pub struct ParameterEnvironment<'a, 'tcx:'a> {
     /// Obligations that the caller must satisfy. This is basically
     /// the set of bounds on the in-scope type parameters, translated
     /// into Obligations.
-    pub caller_bounds: ty::GenericBounds<'tcx>,
+    pub caller_bounds: Vec<ty::Predicate<'tcx>>,
 
     /// Caches the results of trait selection. This cache is used
     /// for things that have to do with the parameters in scope.
@@ -2108,6 +2107,19 @@ pub struct ParameterEnvironment<'a, 'tcx:'a> {
 }
 
 impl<'a, 'tcx> ParameterEnvironment<'a, 'tcx> {
+    pub fn with_caller_bounds(&self,
+                              caller_bounds: Vec<ty::Predicate<'tcx>>)
+                              -> ParameterEnvironment<'a,'tcx>
+    {
+        ParameterEnvironment {
+            tcx: self.tcx,
+            free_substs: self.free_substs.clone(),
+            implicit_region_bound: self.implicit_region_bound,
+            caller_bounds: caller_bounds,
+            selection_cache: traits::SelectionCache::new(),
+        }
+    }
+
     pub fn for_item(cx: &'a ctxt<'tcx>, id: NodeId) -> ParameterEnvironment<'a, 'tcx> {
         match cx.map.find(id) {
             Some(ast_map::NodeImplItem(ref impl_item)) => {
@@ -2119,6 +2131,7 @@ impl<'a, 'tcx> ParameterEnvironment<'a, 'tcx> {
                                 let method_generics = &method_ty.generics;
                                 construct_parameter_environment(
                                     cx,
+                                    method.span,
                                     method_generics,
                                     method.pe_body().id)
                             }
@@ -2153,6 +2166,7 @@ impl<'a, 'tcx> ParameterEnvironment<'a, 'tcx> {
                                 let method_generics = &method_ty.generics;
                                 construct_parameter_environment(
                                     cx,
+                                    method.span,
                                     method_generics,
                                     method.pe_body().id)
                             }
@@ -2179,6 +2193,7 @@ impl<'a, 'tcx> ParameterEnvironment<'a, 'tcx> {
                         let fn_pty = ty::lookup_item_type(cx, fn_def_id);
 
                         construct_parameter_environment(cx,
+                                                        item.span,
                                                         &fn_pty.generics,
                                                         body.id)
                     }
@@ -2189,7 +2204,7 @@ impl<'a, 'tcx> ParameterEnvironment<'a, 'tcx> {
                     ast::ItemStatic(..) => {
                         let def_id = ast_util::local_def(id);
                         let pty = ty::lookup_item_type(cx, def_id);
-                        construct_parameter_environment(cx, &pty.generics, id)
+                        construct_parameter_environment(cx, item.span, &pty.generics, id)
                     }
                     _ => {
                         cx.sess.span_bug(item.span,
@@ -6258,23 +6273,22 @@ impl Variance {
 pub fn empty_parameter_environment<'a,'tcx>(cx: &'a ctxt<'tcx>) -> ParameterEnvironment<'a,'tcx> {
     ty::ParameterEnvironment { tcx: cx,
                                free_substs: Substs::empty(),
-                               caller_bounds: GenericBounds::empty(),
+                               caller_bounds: Vec::new(),
                                implicit_region_bound: ty::ReEmpty,
                                selection_cache: traits::SelectionCache::new(), }
 }
 
-/// See `ParameterEnvironment` struct def'n for details
-pub fn construct_parameter_environment<'a,'tcx>(
+/// Constructs and returns a substitution that can be applied to move from
+/// the "outer" view of a type or method to the "inner" view.
+/// In general, this means converting from bound parameters to
+/// free parameters. Since we currently represent bound/free type
+/// parameters in the same way, this only has an effect on regions.
+pub fn construct_free_substs<'a,'tcx>(
     tcx: &'a ctxt<'tcx>,
     generics: &ty::Generics<'tcx>,
     free_id: ast::NodeId)
-    -> ParameterEnvironment<'a, 'tcx>
+    -> Substs<'tcx>
 {
-
-    //
-    // Construct the free substs.
-    //
-
     // map T => T
     let mut types = VecPerParamSpace::empty();
     push_types_from_defs(tcx, &mut types, generics.types.as_slice());
@@ -6283,11 +6297,45 @@ pub fn construct_parameter_environment<'a,'tcx>(
     let mut regions = VecPerParamSpace::empty();
     push_region_params(&mut regions, free_id, generics.regions.as_slice());
 
-    let free_substs = Substs {
+    return Substs {
         types: types,
         regions: subst::NonerasedRegions(regions)
     };
 
+    fn push_region_params(regions: &mut VecPerParamSpace<ty::Region>,
+                          free_id: ast::NodeId,
+                          region_params: &[RegionParameterDef])
+    {
+        for r in region_params.iter() {
+            regions.push(r.space, ty::free_region_from_def(free_id, r));
+        }
+    }
+
+    fn push_types_from_defs<'tcx>(tcx: &ty::ctxt<'tcx>,
+                                  types: &mut VecPerParamSpace<Ty<'tcx>>,
+                                  defs: &[TypeParameterDef<'tcx>]) {
+        for def in defs.iter() {
+            debug!("construct_parameter_environment(): push_types_from_defs: def={:?}",
+                   def.repr(tcx));
+            let ty = ty::mk_param_from_def(tcx, def);
+            types.push(def.space, ty);
+       }
+    }
+}
+
+/// See `ParameterEnvironment` struct def'n for details
+pub fn construct_parameter_environment<'a,'tcx>(
+    tcx: &'a ctxt<'tcx>,
+    span: Span,
+    generics: &ty::Generics<'tcx>,
+    free_id: ast::NodeId)
+    -> ParameterEnvironment<'a, 'tcx>
+{
+    //
+    // Construct the free substs.
+    //
+
+    let free_substs = construct_free_substs(tcx, generics, free_id);
     let free_id_scope = region::CodeExtent::from_node_id(free_id);
 
     //
@@ -6296,6 +6344,7 @@ pub fn construct_parameter_environment<'a,'tcx>(
 
     let bounds = generics.to_bounds(tcx, &free_substs);
     let bounds = liberate_late_bound_regions(tcx, free_id_scope, &ty::Binder(bounds));
+    let predicates = bounds.predicates.into_vec();
 
     //
     // Compute region bounds. For now, these relations are stored in a
@@ -6303,45 +6352,42 @@ pub fn construct_parameter_environment<'a,'tcx>(
     // crazy about this scheme, but it's convenient, at least.
     //
 
-    record_region_bounds(tcx, &bounds);
+    record_region_bounds(tcx, &*predicates);
 
-    debug!("construct_parameter_environment: free_id={:?} free_subst={:?} bounds={:?}",
+    debug!("construct_parameter_environment: free_id={:?} free_subst={:?} predicates={:?}",
            free_id,
            free_substs.repr(tcx),
-           bounds.repr(tcx));
+           predicates.repr(tcx));
+
+    //
+    // Finally, we have to normalize the bounds in the environment, in
+    // case they contain any associated type projections. This process
+    // can yield errors if the put in illegal associated types, like
+    // `<i32 as Foo>::Bar` where `i32` does not implement `Foo`. We
+    // report these errors right here; this doesn't actually feel
+    // right to me, because constructing the environment feels like a
+    // kind of a "idempotent" action, but I'm not sure where would be
+    // a better place. In practice, we construct environments for
+    // every fn once during type checking, and we'll abort if there
+    // are any errors at that point, so after type checking you can be
+    // sure that this will succeed without errors anyway.
+    //
 
-    return ty::ParameterEnvironment {
+    let unnormalized_env = ty::ParameterEnvironment {
         tcx: tcx,
         free_substs: free_substs,
         implicit_region_bound: ty::ReScope(free_id_scope),
-        caller_bounds: bounds,
+        caller_bounds: predicates,
         selection_cache: traits::SelectionCache::new(),
     };
 
-    fn push_region_params(regions: &mut VecPerParamSpace<ty::Region>,
-                          free_id: ast::NodeId,
-                          region_params: &[RegionParameterDef])
-    {
-        for r in region_params.iter() {
-            regions.push(r.space, ty::free_region_from_def(free_id, r));
-        }
-    }
-
-    fn push_types_from_defs<'tcx>(tcx: &ty::ctxt<'tcx>,
-                                  types: &mut VecPerParamSpace<Ty<'tcx>>,
-                                  defs: &[TypeParameterDef<'tcx>]) {
-        for def in defs.iter() {
-            debug!("construct_parameter_environment(): push_types_from_defs: def={:?}",
-                   def.repr(tcx));
-            let ty = ty::mk_param_from_def(tcx, def);
-            types.push(def.space, ty);
-       }
-    }
+    let cause = traits::ObligationCause::misc(span, free_id);
+    return traits::normalize_param_env_or_error(unnormalized_env, cause);
 
-    fn record_region_bounds<'tcx>(tcx: &ty::ctxt<'tcx>, bounds: &GenericBounds<'tcx>) {
-        debug!("record_region_bounds(bounds={:?})", bounds.repr(tcx));
+    fn record_region_bounds<'tcx>(tcx: &ty::ctxt<'tcx>, predicates: &[ty::Predicate<'tcx>]) {
+        debug!("record_region_bounds(predicates={:?})", predicates.repr(tcx));
 
-        for predicate in bounds.predicates.iter() {
+        for predicate in predicates.iter() {
             match *predicate {
                 Predicate::Projection(..) |
                 Predicate::Trait(..) |
diff --git a/src/librustc/middle/ty_fold.rs b/src/librustc/middle/ty_fold.rs
index 86552705963..69d32c3f5fc 100644
--- a/src/librustc/middle/ty_fold.rs
+++ b/src/librustc/middle/ty_fold.rs
@@ -71,7 +71,7 @@ pub trait TypeFolder<'tcx> : Sized {
     fn exit_region_binder(&mut self) { }
 
     fn fold_binder<T>(&mut self, t: &ty::Binder<T>) -> ty::Binder<T>
-        where T : TypeFoldable<'tcx> + Repr<'tcx>
+        where T : TypeFoldable<'tcx> + Repr<'tcx> + Clone
     {
         // FIXME(#20526) this should replace `enter_region_binder`/`exit_region_binder`.
         super_fold_binder(self, t)
@@ -186,7 +186,7 @@ impl<'tcx, T: TypeFoldable<'tcx>> TypeFoldable<'tcx> for Vec<T> {
     }
 }
 
-impl<'tcx, T:TypeFoldable<'tcx>+Repr<'tcx>> TypeFoldable<'tcx> for ty::Binder<T> {
+impl<'tcx, T:TypeFoldable<'tcx>+Repr<'tcx>+Clone> TypeFoldable<'tcx> for ty::Binder<T> {
     fn fold_with<F: TypeFolder<'tcx>>(&self, folder: &mut F) -> ty::Binder<T> {
         folder.fold_binder(self)
     }
@@ -319,7 +319,7 @@ impl<'tcx> TypeFoldable<'tcx> for ty::MethodOrigin<'tcx> {
                     trait_ref: object.trait_ref.fold_with(folder),
                     object_trait_id: object.object_trait_id,
                     method_num: object.method_num,
-                    real_index: object.real_index
+                    vtable_index: object.vtable_index,
                 })
             }
         }
diff --git a/src/librustc/session/mod.rs b/src/librustc/session/mod.rs
index f90a60c9754..e62f3145e5a 100644
--- a/src/librustc/session/mod.rs
+++ b/src/librustc/session/mod.rs
@@ -305,9 +305,19 @@ pub fn build_session(sopts: config::Options,
                      local_crate_source_file: Option<Path>,
                      registry: diagnostics::registry::Registry)
                      -> Session {
+    // FIXME: This is not general enough to make the warning lint completely override
+    // normal diagnostic warnings, since the warning lint can also be denied and changed
+    // later via the source code.
+    let can_print_warnings = sopts.lint_opts
+        .iter()
+        .filter(|&&(ref key, _)| *key == "warnings")
+        .map(|&(_, ref level)| *level != lint::Allow)
+        .last()
+        .unwrap_or(true);
+
     let codemap = codemap::CodeMap::new();
     let diagnostic_handler =
-        diagnostic::default_handler(sopts.color, Some(registry));
+        diagnostic::default_handler(sopts.color, Some(registry), can_print_warnings);
     let span_diagnostic_handler =
         diagnostic::mk_span_handler(diagnostic_handler, codemap);
 
diff --git a/src/librustc/util/common.rs b/src/librustc/util/common.rs
index 8915d55e206..bdb6ea22f8b 100644
--- a/src/librustc/util/common.rs
+++ b/src/librustc/util/common.rs
@@ -22,6 +22,9 @@ use syntax::ast;
 use syntax::visit;
 use syntax::visit::Visitor;
 
+// The name of the associated type for `Fn` return types
+pub const FN_OUTPUT_NAME: &'static str = "Output";
+
 // Useful type to use with `Result<>` indicate that an error has already
 // been reported to the user, so no need to continue checking.
 #[derive(Clone, Copy, Show)]
diff --git a/src/librustc/util/ppaux.rs b/src/librustc/util/ppaux.rs
index 5601898136c..1be99a8e569 100644
--- a/src/librustc/util/ppaux.rs
+++ b/src/librustc/util/ppaux.rs
@@ -298,17 +298,9 @@ pub fn ty_to_string<'tcx>(cx: &ctxt<'tcx>, typ: &ty::TyS<'tcx>) -> String {
 
     fn closure_to_string<'tcx>(cx: &ctxt<'tcx>, cty: &ty::ClosureTy<'tcx>) -> String {
         let mut s = String::new();
-
-        match cty.unsafety {
-            ast::Unsafety::Normal => {}
-            ast::Unsafety::Unsafe => {
-                s.push_str(cty.unsafety.to_string().as_slice());
-                s.push(' ');
-            }
-        };
-
-        push_sig_to_string(cx, &mut s, '|', '|', &cty.sig);
-
+        s.push_str("[closure");
+        push_sig_to_string(cx, &mut s, '(', ')', &cty.sig);
+        s.push(']');
         s
     }
 
@@ -399,18 +391,10 @@ pub fn ty_to_string<'tcx>(cx: &ctxt<'tcx>, typ: &ty::TyS<'tcx>) -> String {
         ty_enum(did, substs) | ty_struct(did, substs) => {
             let base = ty::item_path_str(cx, did);
             let generics = ty::lookup_item_type(cx, did).generics;
-            parameterized(cx, base.as_slice(), substs, &generics, did)
+            parameterized(cx, base.as_slice(), substs, &generics, did, &[])
         }
-        ty_trait(box ty::TyTrait {
-            ref principal, ref bounds
-        }) => {
-            let principal = principal.user_string(cx);
-            let bound_str = bounds.user_string(cx);
-            let bound_sep = if bound_str.is_empty() { "" } else { " + " };
-            format!("{}{}{}",
-                    principal,
-                    bound_sep,
-                    bound_str)
+        ty_trait(ref data) => {
+            data.user_string(cx)
         }
         ty::ty_projection(ref data) => {
             format!("<{} as {}>::{}",
@@ -420,14 +404,15 @@ pub fn ty_to_string<'tcx>(cx: &ctxt<'tcx>, typ: &ty::TyS<'tcx>) -> String {
         }
         ty_str => "str".to_string(),
         ty_closure(ref did, _, substs) => {
-            cx.closures.borrow().get(did).map(|cl| {
+            let closures = cx.closures.borrow();
+            closures.get(did).map(|cl| {
                 closure_to_string(cx, &cl.closure_type.subst(cx, substs))
             }).unwrap_or_else(|| {
                 if did.krate == ast::LOCAL_CRATE {
                     let span = cx.map.span(did.node);
-                    format!("closure[{}]", span.repr(cx))
+                    format!("[closure {}]", span.repr(cx))
                 } else {
-                    format!("closure")
+                    format!("[closure]")
                 }
             })
         }
@@ -458,7 +443,8 @@ pub fn parameterized<'tcx>(cx: &ctxt<'tcx>,
                            base: &str,
                            substs: &subst::Substs<'tcx>,
                            generics: &ty::Generics<'tcx>,
-                           did: ast::DefId)
+                           did: ast::DefId,
+                           projections: &[ty::ProjectionPredicate<'tcx>])
                            -> String
 {
     if cx.sess.verbose() {
@@ -511,7 +497,20 @@ pub fn parameterized<'tcx>(cx: &ctxt<'tcx>,
         strs.push(ty_to_string(cx, *t))
     }
 
-    if cx.lang_items.fn_trait_kind(did).is_some() {
+    for projection in projections.iter() {
+        strs.push(format!("{}={}",
+                          projection.projection_ty.item_name.user_string(cx),
+                          projection.ty.user_string(cx)));
+    }
+
+    if cx.lang_items.fn_trait_kind(did).is_some() && projections.len() == 1 {
+        let projection_ty = projections[0].ty;
+        let tail =
+            if ty::type_is_nil(projection_ty) {
+                format!("")
+            } else {
+                format!(" -> {}", projection_ty.user_string(cx))
+            };
         format!("{}({}){}",
                 base,
                 if strs[0].starts_with("(") && strs[0].ends_with(",)") {
@@ -521,7 +520,7 @@ pub fn parameterized<'tcx>(cx: &ctxt<'tcx>,
                 } else {
                     &strs[0][]
                 },
-                if &*strs[1] == "()" { String::new() } else { format!(" -> {}", strs[1]) })
+                tail)
     } else if strs.len() > 0 {
         format!("{}<{}>", base, strs.connect(", "))
     } else {
@@ -623,6 +622,65 @@ impl<'tcx> Repr<'tcx> for def::Def {
     }
 }
 
+/// This curious type is here to help pretty-print trait objects. In
+/// a trait object, the projections are stored separately from the
+/// main trait bound, but in fact we want to package them together
+/// when printing out; they also have separate binders, but we want
+/// them to share a binder when we print them out. (And the binder
+/// pretty-printing logic is kind of clever and we don't want to
+/// reproduce it.) So we just repackage up the structure somewhat.
+///
+/// Right now there is only one trait in an object that can have
+/// projection bounds, so we just stuff them altogether. But in
+/// reality we should eventually sort things out better.
+type TraitAndProjections<'tcx> =
+    (Rc<ty::TraitRef<'tcx>>, Vec<ty::ProjectionPredicate<'tcx>>);
+
+impl<'tcx> UserString<'tcx> for TraitAndProjections<'tcx> {
+    fn user_string(&self, tcx: &ctxt<'tcx>) -> String {
+        let &(ref trait_ref, ref projection_bounds) = self;
+        let base = ty::item_path_str(tcx, trait_ref.def_id);
+        let trait_def = ty::lookup_trait_def(tcx, trait_ref.def_id);
+        parameterized(tcx,
+                      base.as_slice(),
+                      trait_ref.substs,
+                      &trait_def.generics,
+                      trait_ref.def_id,
+                      &projection_bounds[])
+    }
+}
+
+impl<'tcx> UserString<'tcx> for ty::TyTrait<'tcx> {
+    fn user_string(&self, tcx: &ctxt<'tcx>) -> String {
+        let &ty::TyTrait { ref principal, ref bounds } = self;
+
+        let mut components = vec![];
+
+        let tap: ty::Binder<TraitAndProjections<'tcx>> =
+            ty::Binder((principal.0.clone(),
+                        bounds.projection_bounds.iter().map(|x| x.0.clone()).collect()));
+
+        // Generate the main trait ref, including associated types.
+        components.push(tap.user_string(tcx));
+
+        // Builtin bounds.
+        for bound in bounds.builtin_bounds.iter() {
+            components.push(bound.user_string(tcx));
+        }
+
+        // Region, if not obviously implied by builtin bounds.
+        if bounds.region_bound != ty::ReStatic ||
+            !bounds.builtin_bounds.contains(&ty::BoundSend)
+        { // Region bound is implied by builtin bounds:
+            components.push(bounds.region_bound.user_string(tcx));
+        }
+
+        components.retain(|s| !s.is_empty());
+
+        components.connect(" + ")
+    }
+}
+
 impl<'tcx> Repr<'tcx> for ty::TypeParameterDef<'tcx> {
     fn repr(&self, tcx: &ctxt<'tcx>) -> String {
         format!("TypeParameterDef({:?}, {}, {:?}/{})",
@@ -701,12 +759,6 @@ impl<'tcx> Repr<'tcx> for ty::BuiltinBounds {
     }
 }
 
-impl<'tcx> Repr<'tcx> for ty::ExistentialBounds<'tcx> {
-    fn repr(&self, tcx: &ctxt<'tcx>) -> String {
-        self.user_string(tcx)
-    }
-}
-
 impl<'tcx> Repr<'tcx> for ty::ParamBounds<'tcx> {
     fn repr(&self, tcx: &ctxt<'tcx>) -> String {
         let mut res = Vec::new();
@@ -727,7 +779,8 @@ impl<'tcx> Repr<'tcx> for ty::TraitRef<'tcx> {
         let trait_def = ty::lookup_trait_def(tcx, self.def_id);
         format!("TraitRef({}, {})",
                 self.substs.self_ty().repr(tcx),
-                parameterized(tcx, base.as_slice(), self.substs, &trait_def.generics, self.def_id))
+                parameterized(tcx, base.as_slice(), self.substs,
+                              &trait_def.generics, self.def_id, &[]))
     }
 }
 
@@ -1062,7 +1115,7 @@ impl<'tcx> Repr<'tcx> for ty::MethodObject<'tcx> {
         format!("MethodObject({},{},{})",
                 self.trait_ref.repr(tcx),
                 self.method_num,
-                self.real_index)
+                self.vtable_index)
     }
 }
 
@@ -1110,14 +1163,8 @@ impl<'tcx> UserString<'tcx> for ty::ParamBounds<'tcx> {
     }
 }
 
-impl<'tcx> UserString<'tcx> for ty::ExistentialBounds<'tcx> {
-    fn user_string(&self, tcx: &ctxt<'tcx>) -> String {
-        if self.builtin_bounds.contains(&ty::BoundSend) &&
-            self.region_bound == ty::ReStatic
-        { // Region bound is implied by builtin bounds:
-            return self.builtin_bounds.repr(tcx);
-        }
-
+impl<'tcx> Repr<'tcx> for ty::ExistentialBounds<'tcx> {
+    fn repr(&self, tcx: &ctxt<'tcx>) -> String {
         let mut res = Vec::new();
 
         let region_str = self.region_bound.user_string(tcx);
@@ -1129,6 +1176,10 @@ impl<'tcx> UserString<'tcx> for ty::ExistentialBounds<'tcx> {
             res.push(bound.user_string(tcx));
         }
 
+        for projection_bound in self.projection_bounds.iter() {
+            res.push(projection_bound.user_string(tcx));
+        }
+
         res.connect("+")
     }
 }
@@ -1184,7 +1235,7 @@ impl<'tcx> UserString<'tcx> for ty::TraitRef<'tcx> {
         let path_str = ty::item_path_str(tcx, self.def_id);
         let trait_def = ty::lookup_trait_def(tcx, self.def_id);
         parameterized(tcx, path_str.as_slice(), self.substs,
-                      &trait_def.generics, self.def_id)
+                      &trait_def.generics, self.def_id, &[])
     }
 }
 
diff --git a/src/librustc/util/snapshot_vec.rs b/src/librustc/util/snapshot_vec.rs
index 8fc95529bc0..151173b3a40 100644
--- a/src/librustc/util/snapshot_vec.rs
+++ b/src/librustc/util/snapshot_vec.rs
@@ -22,8 +22,7 @@ use self::UndoLog::*;
 
 use std::mem;
 
-#[derive(PartialEq)]
-pub enum UndoLog<T,U> {
+pub enum UndoLog<D:SnapshotVecDelegate> {
     /// Indicates where a snapshot started.
     OpenSnapshot,
 
@@ -34,15 +33,15 @@ pub enum UndoLog<T,U> {
     NewElem(uint),
 
     /// Variable with given index was changed *from* the given value.
-    SetElem(uint, T),
+    SetElem(uint, D::Value),
 
     /// Extensible set of actions
-    Other(U)
+    Other(D::Undo)
 }
 
-pub struct SnapshotVec<T,U,D> {
-    values: Vec<T>,
-    undo_log: Vec<UndoLog<T,U>>,
+pub struct SnapshotVec<D:SnapshotVecDelegate> {
+    values: Vec<D::Value>,
+    undo_log: Vec<UndoLog<D>>,
     delegate: D
 }
 
@@ -53,12 +52,15 @@ pub struct Snapshot {
     length: uint,
 }
 
-pub trait SnapshotVecDelegate<T,U> {
-    fn reverse(&mut self, values: &mut Vec<T>, action: U);
+pub trait SnapshotVecDelegate {
+    type Value;
+    type Undo;
+
+    fn reverse(&mut self, values: &mut Vec<Self::Value>, action: Self::Undo);
 }
 
-impl<T,U,D:SnapshotVecDelegate<T,U>> SnapshotVec<T,U,D> {
-    pub fn new(delegate: D) -> SnapshotVec<T,U,D> {
+impl<D:SnapshotVecDelegate> SnapshotVec<D> {
+    pub fn new(delegate: D) -> SnapshotVec<D> {
         SnapshotVec {
             values: Vec::new(),
             undo_log: Vec::new(),
@@ -70,13 +72,13 @@ impl<T,U,D:SnapshotVecDelegate<T,U>> SnapshotVec<T,U,D> {
         !self.undo_log.is_empty()
     }
 
-    pub fn record(&mut self, action: U) {
+    pub fn record(&mut self, action: D::Undo) {
         if self.in_snapshot() {
             self.undo_log.push(Other(action));
         }
     }
 
-    pub fn push(&mut self, elem: T) -> uint {
+    pub fn push(&mut self, elem: D::Value) -> uint {
         let len = self.values.len();
         self.values.push(elem);
 
@@ -87,20 +89,20 @@ impl<T,U,D:SnapshotVecDelegate<T,U>> SnapshotVec<T,U,D> {
         len
     }
 
-    pub fn get<'a>(&'a self, index: uint) -> &'a T {
+    pub fn get<'a>(&'a self, index: uint) -> &'a D::Value {
         &self.values[index]
     }
 
     /// Returns a mutable pointer into the vec; whatever changes you make here cannot be undone
     /// automatically, so you should be sure call `record()` with some sort of suitable undo
     /// action.
-    pub fn get_mut<'a>(&'a mut self, index: uint) -> &'a mut T {
+    pub fn get_mut<'a>(&'a mut self, index: uint) -> &'a mut D::Value {
         &mut self.values[index]
     }
 
     /// Updates the element at the given index. The old value will saved (and perhaps restored) if
     /// a snapshot is active.
-    pub fn set(&mut self, index: uint, new_elem: T) {
+    pub fn set(&mut self, index: uint, new_elem: D::Value) {
         let old_elem = mem::replace(&mut self.values[index], new_elem);
         if self.in_snapshot() {
             self.undo_log.push(SetElem(index, old_elem));
@@ -115,7 +117,7 @@ impl<T,U,D:SnapshotVecDelegate<T,U>> SnapshotVec<T,U,D> {
 
     pub fn actions_since_snapshot(&self,
                                   snapshot: &Snapshot)
-                                  -> &[UndoLog<T,U>] {
+                                  -> &[UndoLog<D>] {
         &self.undo_log[snapshot.length..]
     }
 
diff --git a/src/librustc_back/lib.rs b/src/librustc_back/lib.rs
index d778b916b67..13dec65d13e 100644
--- a/src/librustc_back/lib.rs
+++ b/src/librustc_back/lib.rs
@@ -22,7 +22,8 @@
 //! build speedups.
 
 #![crate_name = "rustc_back"]
-#![unstable]
+#![unstable(feature = "rustc_private")]
+#![feature(staged_api)]
 #![staged_api]
 #![crate_type = "dylib"]
 #![crate_type = "rlib"]
@@ -32,7 +33,13 @@
 #![allow(unknown_features)]
 #![feature(slicing_syntax, box_syntax)]
 #![allow(unknown_features)] #![feature(int_uint)]
-#![allow(unstable)]
+#![feature(collections)]
+#![feature(core)]
+#![feature(hash)]
+#![feature(io)]
+#![feature(os)]
+#![feature(path)]
+#![feature(rustc_private)]
 
 extern crate syntax;
 extern crate serialize;
diff --git a/src/librustc_back/target/mod.rs b/src/librustc_back/target/mod.rs
index 36d83da725e..a63e8237b4b 100644
--- a/src/librustc_back/target/mod.rs
+++ b/src/librustc_back/target/mod.rs
@@ -223,7 +223,7 @@ impl Target {
         // this is 1. ugly, 2. error prone.
 
 
-        let handler = diagnostic::default_handler(diagnostic::Auto, None);
+        let handler = diagnostic::default_handler(diagnostic::Auto, None, true);
 
         let get_req_field = |&: name: &str| {
             match obj.find(name)
diff --git a/src/librustc_bitflags/lib.rs b/src/librustc_bitflags/lib.rs
index c47a525552d..e0f5b5c387f 100644
--- a/src/librustc_bitflags/lib.rs
+++ b/src/librustc_bitflags/lib.rs
@@ -9,10 +9,12 @@
 // except according to those terms.
 
 #![crate_name = "rustc_bitflags"]
-#![unstable]
+#![allow(unknown_features)]
+#![feature(staged_api)]
 #![staged_api]
 #![crate_type = "rlib"]
 #![no_std]
+#![unstable(feature = "rustc_private")]
 
 //! A typesafe bitmask flag generator.
 
diff --git a/src/librustc_borrowck/lib.rs b/src/librustc_borrowck/lib.rs
index 4dd9b3ad2ef..d525c22f0ab 100644
--- a/src/librustc_borrowck/lib.rs
+++ b/src/librustc_borrowck/lib.rs
@@ -9,7 +9,8 @@
 // except according to those terms.
 
 #![crate_name = "rustc_borrowck"]
-#![unstable]
+#![unstable(feature = "rustc_private")]
+#![feature(staged_api)]
 #![staged_api]
 #![crate_type = "dylib"]
 #![crate_type = "rlib"]
@@ -23,7 +24,10 @@
 #![feature(rustc_diagnostic_macros)]
 #![allow(unknown_features)] #![feature(int_uint)]
 #![allow(non_camel_case_types)]
-#![allow(unstable)]
+#![feature(collections)]
+#![feature(core)]
+#![feature(rustc_private)]
+#![feature(hash)]
 
 #[macro_use] extern crate log;
 #[macro_use] extern crate syntax;
diff --git a/src/librustc_driver/driver.rs b/src/librustc_driver/driver.rs
index 25b90041505..6e76519ce23 100644
--- a/src/librustc_driver/driver.rs
+++ b/src/librustc_driver/driver.rs
@@ -390,16 +390,10 @@ pub fn phase_2_configure_and_expand(sess: &Session,
     // baz! should not use this definition unless foo is enabled.
 
     time(time_passes, "gated macro checking", (), |_| {
-        let (features, unknown_features) =
+        let features =
             syntax::feature_gate::check_crate_macros(sess.codemap(),
                                                      &sess.parse_sess.span_diagnostic,
                                                      &krate);
-        for uf in unknown_features.iter() {
-            sess.add_lint(lint::builtin::UNKNOWN_FEATURES,
-                          ast::CRATE_NODE_ID,
-                          *uf,
-                          "unknown feature".to_string());
-        }
 
         // these need to be set "early" so that expansion sees `quote` if enabled.
         *sess.features.borrow_mut() = features;
@@ -492,9 +486,11 @@ pub fn phase_2_configure_and_expand(sess: &Session,
 
     // Needs to go *after* expansion to be able to check the results of macro expansion.
     time(time_passes, "complete gated feature checking", (), |_| {
-        syntax::feature_gate::check_crate(sess.codemap(),
+        let features =
+            syntax::feature_gate::check_crate(sess.codemap(),
                                           &sess.parse_sess.span_diagnostic,
                                           &krate);
+        *sess.features.borrow_mut() = features;
         sess.abort_if_errors();
     });
 
@@ -599,7 +595,7 @@ pub fn phase_3_run_analysis_passes<'tcx>(sess: Session,
          middle::check_loop::check_crate(&sess, krate));
 
     let stability_index = time(time_passes, "stability index", (), |_|
-                               stability::Index::build(krate));
+                               stability::Index::build(&sess, krate));
 
     time(time_passes, "static item recursion checking", (), |_|
          middle::check_static_recursion::check_crate(&sess, krate, &def_map, &ast_map));
@@ -668,9 +664,20 @@ pub fn phase_3_run_analysis_passes<'tcx>(sess: Session,
                                   &reachable_map)
     });
 
+    let ref lib_features_used =
+        time(time_passes, "stability checking", (), |_|
+             stability::check_unstable_api_usage(&ty_cx));
+
+    time(time_passes, "unused feature checking", (), |_|
+         stability::check_unused_features(
+             &ty_cx.sess, lib_features_used));
+
     time(time_passes, "lint checking", (), |_|
          lint::check_crate(&ty_cx, &exported_items));
 
+    // The above three passes generate errors w/o aborting
+    ty_cx.sess.abort_if_errors();
+
     ty::CrateAnalysis {
         export_map: export_map,
         ty_cx: ty_cx,
diff --git a/src/librustc_driver/lib.rs b/src/librustc_driver/lib.rs
index fdda8e737a9..727638c29c3 100644
--- a/src/librustc_driver/lib.rs
+++ b/src/librustc_driver/lib.rs
@@ -15,7 +15,8 @@
 //! This API is completely unstable and subject to change.
 
 #![crate_name = "rustc_driver"]
-#![unstable]
+#![unstable(feature = "rustc_private")]
+#![feature(staged_api)]
 #![staged_api]
 #![crate_type = "dylib"]
 #![crate_type = "rlib"]
@@ -29,7 +30,15 @@
 #![feature(box_syntax)]
 #![feature(rustc_diagnostic_macros)]
 #![allow(unknown_features)] #![feature(int_uint)]
-#![allow(unstable)]
+#![feature(collections)]
+#![feature(core)]
+#![feature(io)]
+#![feature(libc)]
+#![feature(os)]
+#![feature(path)]
+#![feature(rustc_private)]
+#![feature(std_misc)]
+#![feature(unicode)]
 
 extern crate arena;
 extern crate flate;
diff --git a/src/librustc_driver/test.rs b/src/librustc_driver/test.rs
index 67b15ce8a87..52d7415a523 100644
--- a/src/librustc_driver/test.rs
+++ b/src/librustc_driver/test.rs
@@ -103,7 +103,7 @@ fn test_env<F>(source_string: &str,
     let codemap =
         CodeMap::new();
     let diagnostic_handler =
-        diagnostic::mk_handler(emitter);
+        diagnostic::mk_handler(true, emitter);
     let span_diagnostic_handler =
         diagnostic::mk_span_handler(diagnostic_handler, codemap);
 
@@ -125,7 +125,7 @@ fn test_env<F>(source_string: &str,
         resolve::resolve_crate(&sess, &ast_map, &lang_items, krate, resolve::MakeGlobMap::No);
     let named_region_map = resolve_lifetime::krate(&sess, krate, &def_map);
     let region_map = region::resolve_crate(&sess, krate);
-    let stability_index = stability::Index::build(krate);
+    let stability_index = stability::Index::build(&sess, krate);
     let tcx = ty::mk_ctxt(sess,
                           &arenas,
                           def_map,
diff --git a/src/librustc_llvm/lib.rs b/src/librustc_llvm/lib.rs
index 8c651cf839b..17191356d3f 100644
--- a/src/librustc_llvm/lib.rs
+++ b/src/librustc_llvm/lib.rs
@@ -14,7 +14,8 @@
 #![allow(dead_code)]
 
 #![crate_name = "rustc_llvm"]
-#![unstable]
+#![unstable(feature = "rustc_private")]
+#![feature(staged_api)]
 #![staged_api]
 #![crate_type = "dylib"]
 #![crate_type = "rlib"]
@@ -26,7 +27,12 @@
 #![feature(link_args)]
 #![feature(box_syntax)]
 #![allow(unknown_features)] #![feature(int_uint)]
-#![allow(unstable)]
+#![feature(collections)]
+#![feature(core)]
+#![feature(libc)]
+#![feature(path)]
+#![feature(std_misc)]
+#![feature(hash)]
 
 extern crate libc;
 #[macro_use] #[no_link] extern crate rustc_bitflags;
diff --git a/src/librustc_privacy/lib.rs b/src/librustc_privacy/lib.rs
index b89853fb5cc..dbac2358047 100644
--- a/src/librustc_privacy/lib.rs
+++ b/src/librustc_privacy/lib.rs
@@ -9,7 +9,8 @@
 // except according to those terms.
 
 #![crate_name = "rustc_privacy"]
-#![unstable]
+#![unstable(feature = "rustc_private")]
+#![feature(staged_api)]
 #![staged_api]
 #![crate_type = "dylib"]
 #![crate_type = "rlib"]
@@ -19,7 +20,9 @@
 
 #![feature(rustc_diagnostic_macros)]
 #![allow(unknown_features)] #![feature(int_uint)]
-#![allow(unstable)]
+#![feature(collections)]
+#![feature(core)]
+#![feature(rustc_private)]
 
 #[macro_use] extern crate log;
 #[macro_use] extern crate syntax;
diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs
index 084675cfe06..1d9c701a16c 100644
--- a/src/librustc_resolve/lib.rs
+++ b/src/librustc_resolve/lib.rs
@@ -9,7 +9,8 @@
 // except according to those terms.
 
 #![crate_name = "rustc_resolve"]
-#![unstable]
+#![unstable(feature = "rustc_private")]
+#![feature(staged_api)]
 #![staged_api]
 #![crate_type = "dylib"]
 #![crate_type = "rlib"]
@@ -20,7 +21,12 @@
 #![feature(slicing_syntax)]
 #![feature(rustc_diagnostic_macros)]
 #![allow(unknown_features)] #![feature(int_uint)]
-#![allow(unstable)]
+#![feature(alloc)]
+#![feature(collections)]
+#![feature(core)]
+#![feature(rustc_private)]
+#![feature(std_misc)]
+#![feature(hash)]
 
 #[macro_use] extern crate log;
 #[macro_use] extern crate syntax;
diff --git a/src/librustc_trans/back/write.rs b/src/librustc_trans/back/write.rs
index 370ea0c7b14..15b9d6237ed 100644
--- a/src/librustc_trans/back/write.rs
+++ b/src/librustc_trans/back/write.rs
@@ -911,7 +911,7 @@ fn run_work_multithreaded(sess: &Session,
         futures.push(rx);
 
         thread::Builder::new().name(format!("codegen-{}", i)).spawn(move |:| {
-            let diag_handler = mk_handler(box diag_emitter);
+            let diag_handler = mk_handler(true, box diag_emitter);
 
             // Must construct cgcx inside the proc because it has non-Send
             // fields.
diff --git a/src/librustc_trans/lib.rs b/src/librustc_trans/lib.rs
index c3e88e65b2f..bb026e237df 100644
--- a/src/librustc_trans/lib.rs
+++ b/src/librustc_trans/lib.rs
@@ -15,7 +15,8 @@
 //! This API is completely unstable and subject to change.
 
 #![crate_name = "rustc_trans"]
-#![unstable]
+#![unstable(feature = "rustc_private")]
+#![feature(staged_api)]
 #![staged_api]
 #![crate_type = "dylib"]
 #![crate_type = "rlib"]
@@ -29,7 +30,17 @@
 #![feature(box_syntax)]
 #![feature(rustc_diagnostic_macros)]
 #![allow(unknown_features)] #![feature(int_uint)]
-#![allow(unstable)]
+#![feature(alloc)]
+#![feature(collections)]
+#![feature(core)]
+#![feature(io)]
+#![feature(libc)]
+#![feature(os)]
+#![feature(path)]
+#![feature(rustc_private)]
+#![feature(std_misc)]
+#![feature(unicode)]
+#![feature(hash)]
 
 extern crate arena;
 extern crate flate;
diff --git a/src/librustc_trans/trans/meth.rs b/src/librustc_trans/trans/meth.rs
index 187b73b1b09..c4240fa9eba 100644
--- a/src/librustc_trans/trans/meth.rs
+++ b/src/librustc_trans/trans/meth.rs
@@ -13,7 +13,7 @@ use back::abi;
 use back::link;
 use llvm::{self, ValueRef, get_param};
 use metadata::csearch;
-use middle::subst::{Subst, Substs};
+use middle::subst::Substs;
 use middle::subst::VecPerParamSpace;
 use middle::subst;
 use middle::traits;
@@ -29,6 +29,7 @@ use trans::expr::{SaveIn, Ignore};
 use trans::expr;
 use trans::glue;
 use trans::machine;
+use trans::monomorphize;
 use trans::type_::Type;
 use trans::type_of::*;
 use middle::ty::{self, Ty};
@@ -162,7 +163,7 @@ pub fn trans_method_callee<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
             };
             trans_trait_callee(bcx,
                                monomorphize_type(bcx, method_ty),
-                               mt.real_index,
+                               mt.vtable_index,
                                self_expr,
                                arg_cleanup_scope)
         }
@@ -439,7 +440,7 @@ fn combine_impl_and_methods_tps<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
 /// extract the self data and vtable out of the pair.
 fn trans_trait_callee<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
                                   method_ty: Ty<'tcx>,
-                                  n_method: uint,
+                                  vtable_index: uint,
                                   self_expr: &ast::Expr,
                                   arg_cleanup_scope: cleanup::ScopeId)
                                   -> Callee<'blk, 'tcx> {
@@ -469,28 +470,28 @@ fn trans_trait_callee<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
         self_datum.val
     };
 
-    trans_trait_callee_from_llval(bcx, method_ty, n_method, llval)
+    trans_trait_callee_from_llval(bcx, method_ty, vtable_index, llval)
 }
 
 /// Same as `trans_trait_callee()` above, except that it is given a by-ref pointer to the object
 /// pair.
 pub fn trans_trait_callee_from_llval<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
                                                  callee_ty: Ty<'tcx>,
-                                                 n_method: uint,
+                                                 vtable_index: uint,
                                                  llpair: ValueRef)
                                                  -> Callee<'blk, 'tcx> {
     let _icx = push_ctxt("meth::trans_trait_callee");
     let ccx = bcx.ccx();
 
     // Load the data pointer from the object.
-    debug!("(translating trait callee) loading second index from pair");
+    debug!("trans_trait_callee_from_llval(callee_ty={}, vtable_index={}, llpair={})",
+           callee_ty.repr(ccx.tcx()),
+           vtable_index,
+           bcx.val_to_string(llpair));
     let llboxptr = GEPi(bcx, llpair, &[0u, abi::FAT_PTR_ADDR]);
     let llbox = Load(bcx, llboxptr);
     let llself = PointerCast(bcx, llbox, Type::i8p(ccx));
 
-    // Load the function from the vtable and cast it to the expected type.
-    debug!("(translating trait callee) loading method");
-
     // Replace the self type (&Self or Box<Self>) with an opaque pointer.
     let llcallee_ty = match callee_ty.sty {
         ty::ty_bare_fn(_, ref f) if f.abi == Rust || f.abi == RustCall => {
@@ -500,10 +501,7 @@ pub fn trans_trait_callee_from_llval<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
                     output: f.sig.0.output,
                     variadic: f.sig.0.variadic,
                 });
-            type_of_rust_fn(ccx,
-                            Some(Type::i8p(ccx)),
-                            &fake_sig,
-                            f.abi)
+            type_of_rust_fn(ccx, Some(Type::i8p(ccx)), &fake_sig, f.abi)
         }
         _ => {
             ccx.sess().bug("meth::trans_trait_callee given non-bare-rust-fn");
@@ -514,7 +512,7 @@ pub fn trans_trait_callee_from_llval<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
                                     GEPi(bcx, llpair,
                                          &[0u, abi::FAT_PTR_EXTRA]),
                                     Type::vtable(ccx).ptr_to().ptr_to()));
-    let mptr = Load(bcx, GEPi(bcx, llvtable, &[0u, n_method + VTABLE_OFFSET]));
+    let mptr = Load(bcx, GEPi(bcx, llvtable, &[0u, vtable_index + VTABLE_OFFSET]));
     let mptr = PointerCast(bcx, mptr, llcallee_ty.ptr_to());
 
     return Callee {
@@ -558,7 +556,7 @@ pub fn trans_object_shim<'a, 'tcx>(
     let _icx = push_ctxt("trans_object_shim");
     let tcx = ccx.tcx();
 
-    debug!("trans_object_shim(object_ty={}, trait_id={}, n_method={})",
+    debug!("trans_object_shim(object_ty={}, trait_id={}, method_offset_in_trait={})",
            object_ty.repr(tcx),
            trait_id.repr(tcx),
            method_offset_in_trait);
@@ -587,7 +585,7 @@ pub fn trans_object_shim<'a, 'tcx>(
             tcx.sess.bug("can't create a method shim for an associated type")
         }
     };
-    let fty = method_ty.fty.subst(tcx, &object_substs);
+    let fty = monomorphize::apply_param_substs(tcx, &object_substs, &method_ty.fty);
     let fty = tcx.mk_bare_fn(fty);
     debug!("trans_object_shim: fty={}", fty.repr(tcx));
 
diff --git a/src/librustc_trans/trans/type_of.rs b/src/librustc_trans/trans/type_of.rs
index 61dbb551435..6b6ca600a88 100644
--- a/src/librustc_trans/trans/type_of.rs
+++ b/src/librustc_trans/trans/type_of.rs
@@ -103,6 +103,10 @@ pub fn type_of_rust_fn<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
                                  abi: abi::Abi)
                                  -> Type
 {
+    debug!("type_of_rust_fn(sig={},abi={:?})",
+           sig.repr(cx.tcx()),
+           abi);
+
     let sig = ty::erase_late_bound_regions(cx.tcx(), sig);
     assert!(!sig.variadic); // rust fns are never variadic
 
diff --git a/src/librustc_typeck/astconv.rs b/src/librustc_typeck/astconv.rs
index 921ed505fa3..6e8dd6b0ae7 100644
--- a/src/librustc_typeck/astconv.rs
+++ b/src/librustc_typeck/astconv.rs
@@ -57,7 +57,7 @@ use middle::ty::{self, RegionEscape, ToPolyTraitRef, Ty};
 use rscope::{self, UnelidableRscope, RegionScope, SpecificRscope,
              ShiftedRscope, BindingRscope};
 use TypeAndSubsts;
-use util::common::ErrorReported;
+use util::common::{ErrorReported, FN_OUTPUT_NAME};
 use util::nodemap::DefIdMap;
 use util::ppaux::{self, Repr, UserString};
 
@@ -268,7 +268,7 @@ pub fn ast_path_substs_for_ty<'tcx>(
         ast::ParenthesizedParameters(ref data) => {
             span_err!(tcx.sess, path.span, E0214,
                 "parenthesized parameters may only be used with a trait");
-            (Vec::new(), convert_parenthesized_parameters(this, data), Vec::new())
+            convert_parenthesized_parameters(this, data)
         }
     };
 
@@ -479,7 +479,9 @@ fn convert_ty_with_lifetime_elision<'tcx>(this: &AstConv<'tcx>,
 
 fn convert_parenthesized_parameters<'tcx>(this: &AstConv<'tcx>,
                                           data: &ast::ParenthesizedParameterData)
-                                          -> Vec<Ty<'tcx>>
+                                          -> (Vec<ty::Region>,
+                                              Vec<Ty<'tcx>>,
+                                              Vec<ConvertedBinding<'tcx>>)
 {
     let binding_rscope = BindingRscope::new();
     let inputs = data.inputs.iter()
@@ -492,15 +494,26 @@ fn convert_parenthesized_parameters<'tcx>(this: &AstConv<'tcx>,
 
     let input_ty = ty::mk_tup(this.tcx(), inputs);
 
-    let output = match data.output {
-        Some(ref output_ty) => convert_ty_with_lifetime_elision(this,
-                                                                implied_output_region,
-                                                                params_lifetimes,
-                                                                &**output_ty),
-        None => ty::mk_nil(this.tcx()),
+    let (output, output_span) = match data.output {
+        Some(ref output_ty) => {
+            (convert_ty_with_lifetime_elision(this,
+                                              implied_output_region,
+                                              params_lifetimes,
+                                              &**output_ty),
+             output_ty.span)
+        }
+        None => {
+            (ty::mk_nil(this.tcx()), data.span)
+        }
+    };
+
+    let output_binding = ConvertedBinding {
+        item_name: token::intern(FN_OUTPUT_NAME),
+        ty: output,
+        span: output_span
     };
 
-    vec![input_ty, output]
+    (vec![], vec![input_ty], vec![output_binding])
 }
 
 pub fn instantiate_poly_trait_ref<'tcx>(
@@ -630,7 +643,7 @@ fn ast_path_to_trait_ref<'a,'tcx>(
                             the crate attributes to enable");
             }
 
-            (Vec::new(), convert_parenthesized_parameters(this, data), Vec::new())
+            convert_parenthesized_parameters(this, data)
         }
     };
 
diff --git a/src/librustc_typeck/check/closure.rs b/src/librustc_typeck/check/closure.rs
index 2d7a7634472..bdae34e7878 100644
--- a/src/librustc_typeck/check/closure.rs
+++ b/src/librustc_typeck/check/closure.rs
@@ -34,7 +34,7 @@ pub fn check_expr_closure<'a,'tcx>(fcx: &FnCtxt<'a,'tcx>,
            expected.repr(fcx.tcx()));
 
     let expected_sig_and_kind = expected.to_option(fcx).and_then(|ty| {
-        deduce_closure_expectations_from_expected_type(fcx, ty)
+        deduce_expectations_from_expected_type(fcx, ty)
     });
 
     match opt_kind {
@@ -137,20 +137,21 @@ fn check_closure<'a,'tcx>(fcx: &FnCtxt<'a,'tcx>,
     fcx.inh.closures.borrow_mut().insert(expr_def_id, closure);
 }
 
-fn deduce_closure_expectations_from_expected_type<'a,'tcx>(
+fn deduce_expectations_from_expected_type<'a,'tcx>(
     fcx: &FnCtxt<'a,'tcx>,
     expected_ty: Ty<'tcx>)
     -> Option<(ty::FnSig<'tcx>,ty::ClosureKind)>
 {
     match expected_ty.sty {
         ty::ty_trait(ref object_type) => {
-            let trait_ref =
-                object_type.principal_trait_ref_with_self_ty(fcx.tcx(),
-                                                             fcx.tcx().types.err);
-            deduce_closure_expectations_from_trait_ref(fcx, &trait_ref)
+            let proj_bounds = object_type.projection_bounds_with_self_ty(fcx.tcx(),
+                                                                         fcx.tcx().types.err);
+            proj_bounds.iter()
+                       .filter_map(|pb| deduce_expectations_from_projection(fcx, pb))
+                       .next()
         }
         ty::ty_infer(ty::TyVar(vid)) => {
-            deduce_closure_expectations_from_obligations(fcx, vid)
+            deduce_expectations_from_obligations(fcx, vid)
         }
         _ => {
             None
@@ -158,15 +159,51 @@ fn deduce_closure_expectations_from_expected_type<'a,'tcx>(
     }
 }
 
-fn deduce_closure_expectations_from_trait_ref<'a,'tcx>(
+fn deduce_expectations_from_obligations<'a,'tcx>(
     fcx: &FnCtxt<'a,'tcx>,
-    trait_ref: &ty::PolyTraitRef<'tcx>)
+    expected_vid: ty::TyVid)
+    -> Option<(ty::FnSig<'tcx>, ty::ClosureKind)>
+{
+    let fulfillment_cx = fcx.inh.fulfillment_cx.borrow();
+    // Here `expected_ty` is known to be a type inference variable.
+
+    fulfillment_cx.pending_obligations()
+                  .iter()
+                  .filter_map(|obligation| {
+                      match obligation.predicate {
+                          ty::Predicate::Projection(ref proj_predicate) => {
+                              let trait_ref = proj_predicate.to_poly_trait_ref();
+                              let self_ty = fcx.infcx().shallow_resolve(trait_ref.self_ty());
+                              match self_ty.sty {
+                                  ty::ty_infer(ty::TyVar(v)) if expected_vid == v => {
+                                      deduce_expectations_from_projection(fcx, proj_predicate)
+                                  }
+                                  _ => {
+                                      None
+                                  }
+                              }
+                          }
+                          _ => {
+                              None
+                          }
+                      }
+                  })
+                  .next()
+}
+
+/// Given a projection like "<F as Fn(X)>::Result == Y", we can deduce
+/// everything we need to know about a closure.
+fn deduce_expectations_from_projection<'a,'tcx>(
+    fcx: &FnCtxt<'a,'tcx>,
+    projection: &ty::PolyProjectionPredicate<'tcx>)
     -> Option<(ty::FnSig<'tcx>, ty::ClosureKind)>
 {
     let tcx = fcx.tcx();
 
-    debug!("deduce_closure_expectations_from_object_type({})",
-           trait_ref.repr(tcx));
+    debug!("deduce_expectations_from_projection({})",
+           projection.repr(tcx));
+
+    let trait_ref = projection.to_poly_trait_ref();
 
     let kind = match tcx.lang_items.fn_trait_kind(trait_ref.def_id()) {
         Some(k) => k,
@@ -185,7 +222,7 @@ fn deduce_closure_expectations_from_trait_ref<'a,'tcx>(
     };
     debug!("input_tys {}", input_tys.repr(tcx));
 
-    let ret_param_ty = *trait_ref.substs().types.get(subst::TypeSpace, 1);
+    let ret_param_ty = projection.0.ty;
     let ret_param_ty = fcx.infcx().resolve_type_vars_if_possible(&ret_param_ty);
     debug!("ret_param_ty {}", ret_param_ty.repr(tcx));
 
@@ -199,30 +236,3 @@ fn deduce_closure_expectations_from_trait_ref<'a,'tcx>(
     return Some((fn_sig, kind));
 }
 
-fn deduce_closure_expectations_from_obligations<'a,'tcx>(
-    fcx: &FnCtxt<'a,'tcx>,
-    expected_vid: ty::TyVid)
-    -> Option<(ty::FnSig<'tcx>, ty::ClosureKind)>
-{
-    // Here `expected_ty` is known to be a type inference variable.
-    for obligation in fcx.inh.fulfillment_cx.borrow().pending_obligations().iter() {
-        match obligation.predicate {
-            ty::Predicate::Trait(ref trait_predicate) => {
-                let trait_ref = trait_predicate.to_poly_trait_ref();
-                let self_ty = fcx.infcx().shallow_resolve(trait_ref.self_ty());
-                match self_ty.sty {
-                    ty::ty_infer(ty::TyVar(v)) if expected_vid == v => { }
-                    _ => { continue; }
-                }
-
-                match deduce_closure_expectations_from_trait_ref(fcx, &trait_ref) {
-                    Some(e) => { return Some(e); }
-                    None => { }
-                }
-            }
-            _ => { }
-        }
-    }
-
-    None
-}
diff --git a/src/librustc_typeck/check/compare_method.rs b/src/librustc_typeck/check/compare_method.rs
index e3e5d67869f..31b14ea3f3d 100644
--- a/src/librustc_typeck/check/compare_method.rs
+++ b/src/librustc_typeck/check/compare_method.rs
@@ -215,14 +215,8 @@ pub fn compare_impl_method<'tcx>(tcx: &ty::ctxt<'tcx>,
     debug!("compare_impl_method: impl_bounds={}",
            impl_bounds.repr(tcx));
 
-    // // Normalize the associated types in the impl_bounds.
-    // let traits::Normalized { value: impl_bounds, .. } =
-    //     traits::normalize(&mut selcx, normalize_cause.clone(), &impl_bounds);
-
     // Normalize the associated types in the trait_bounds.
     let trait_bounds = trait_m.generics.to_bounds(tcx, &trait_to_skol_substs);
-    // let traits::Normalized { value: trait_bounds, .. } =
-    //     traits::normalize(&mut selcx, normalize_cause, &trait_bounds);
 
     // Obtain the predicate split predicate sets for each.
     let trait_pred = trait_bounds.predicates.split();
@@ -242,19 +236,18 @@ pub fn compare_impl_method<'tcx>(tcx: &ty::ctxt<'tcx>,
     );
 
     // Construct trait parameter environment and then shift it into the skolemized viewpoint.
-    let mut trait_param_env = impl_param_env.clone();
     // The key step here is to update the caller_bounds's predicates to be
     // the new hybrid bounds we computed.
-    trait_param_env.caller_bounds.predicates = hybrid_preds;
+    let normalize_cause = traits::ObligationCause::misc(impl_m_span, impl_m_body_id);
+    let trait_param_env = impl_param_env.with_caller_bounds(hybrid_preds.into_vec());
+    let trait_param_env = traits::normalize_param_env_or_error(trait_param_env,
+                                                               normalize_cause.clone());
 
     debug!("compare_impl_method: trait_bounds={}",
         trait_param_env.caller_bounds.repr(tcx));
 
     let mut selcx = traits::SelectionContext::new(&infcx, &trait_param_env);
 
-    let normalize_cause =
-        traits::ObligationCause::misc(impl_m_span, impl_m_body_id);
-
     for predicate in impl_pred.fns.into_iter() {
         let traits::Normalized { value: predicate, .. } =
             traits::normalize(&mut selcx, normalize_cause.clone(), &predicate);
diff --git a/src/librustc_typeck/check/demand.rs b/src/librustc_typeck/check/demand.rs
index a51e89c1669..8188835718c 100644
--- a/src/librustc_typeck/check/demand.rs
+++ b/src/librustc_typeck/check/demand.rs
@@ -60,7 +60,8 @@ pub fn coerce<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, sp: Span,
     debug!("demand::coerce(expected = {}, expr_ty = {})",
            expected.repr(fcx.ccx.tcx),
            expr_ty.repr(fcx.ccx.tcx));
-    let expected = fcx.infcx().resolve_type_vars_if_possible(&expected);
+    let expr_ty = fcx.resolve_type_vars_if_possible(expr_ty);
+    let expected = fcx.resolve_type_vars_if_possible(expected);
     match fcx.mk_assignty(expr, expr_ty, expected) {
       Ok(()) => { /* ok */ }
       Err(ref err) => {
diff --git a/src/librustc_typeck/check/method/confirm.rs b/src/librustc_typeck/check/method/confirm.rs
index 4aa0a211221..67b055ac946 100644
--- a/src/librustc_typeck/check/method/confirm.rs
+++ b/src/librustc_typeck/check/method/confirm.rs
@@ -206,7 +206,7 @@ impl<'a,'tcx> ConfirmContext<'a,'tcx> {
                 (impl_polytype.substs, MethodStatic(pick.method_ty.def_id))
             }
 
-            probe::ObjectPick(trait_def_id, method_num, real_index) => {
+            probe::ObjectPick(trait_def_id, method_num, vtable_index) => {
                 self.extract_trait_ref(self_ty, |this, object_ty, data| {
                     // The object data has no entry for the Self
                     // Type. For the purposes of this method call, we
@@ -233,7 +233,7 @@ impl<'a,'tcx> ConfirmContext<'a,'tcx> {
                         trait_ref: upcast_trait_ref,
                         object_trait_id: trait_def_id,
                         method_num: method_num,
-                        real_index: real_index,
+                        vtable_index: vtable_index,
                     });
                     (substs, origin)
                 })
diff --git a/src/librustc_typeck/check/method/probe.rs b/src/librustc_typeck/check/method/probe.rs
index 4c5a8144cbd..6a3554314e2 100644
--- a/src/librustc_typeck/check/method/probe.rs
+++ b/src/librustc_typeck/check/method/probe.rs
@@ -59,7 +59,7 @@ struct Candidate<'tcx> {
 
 enum CandidateKind<'tcx> {
     InherentImplCandidate(/* Impl */ ast::DefId, subst::Substs<'tcx>),
-    ObjectCandidate(/* Trait */ ast::DefId, /* method_num */ uint, /* real_index */ uint),
+    ObjectCandidate(/* Trait */ ast::DefId, /* method_num */ uint, /* vtable index */ uint),
     ExtensionImplCandidate(/* Impl */ ast::DefId, Rc<ty::TraitRef<'tcx>>,
                            subst::Substs<'tcx>, MethodIndex),
     ClosureCandidate(/* Trait */ ast::DefId, MethodIndex),
@@ -318,7 +318,7 @@ impl<'a,'tcx> ProbeContext<'a,'tcx> {
         // itself. Hence, a `&self` method will wind up with an
         // argument type like `&Trait`.
         let trait_ref = data.principal_trait_ref_with_self_ty(self.tcx(), self_ty);
-        self.elaborate_bounds(&[trait_ref.clone()], false, |this, new_trait_ref, m, method_num| {
+        self.elaborate_bounds(&[trait_ref.clone()], |this, new_trait_ref, m, method_num| {
             let new_trait_ref = this.erase_late_bound_regions(&new_trait_ref);
 
             let vtable_index =
@@ -343,7 +343,7 @@ impl<'a,'tcx> ProbeContext<'a,'tcx> {
         // FIXME -- Do we want to commit to this behavior for param bounds?
 
         let bounds: Vec<_> =
-            self.fcx.inh.param_env.caller_bounds.predicates
+            self.fcx.inh.param_env.caller_bounds
             .iter()
             .filter_map(|predicate| {
                 match *predicate {
@@ -365,7 +365,7 @@ impl<'a,'tcx> ProbeContext<'a,'tcx> {
             })
             .collect();
 
-        self.elaborate_bounds(bounds.as_slice(), true, |this, poly_trait_ref, m, method_num| {
+        self.elaborate_bounds(bounds.as_slice(), |this, poly_trait_ref, m, method_num| {
             let trait_ref =
                 this.erase_late_bound_regions(&poly_trait_ref);
 
@@ -405,7 +405,6 @@ impl<'a,'tcx> ProbeContext<'a,'tcx> {
     fn elaborate_bounds<F>(
         &mut self,
         bounds: &[ty::PolyTraitRef<'tcx>],
-        num_includes_types: bool,
         mut mk_cand: F,
     ) where
         F: for<'b> FnMut(
@@ -427,8 +426,7 @@ impl<'a,'tcx> ProbeContext<'a,'tcx> {
 
             let (pos, method) = match trait_method(tcx,
                                                    bound_trait_ref.def_id(),
-                                                   self.method_name,
-                                                   num_includes_types) {
+                                                   self.method_name) {
                 Some(v) => v,
                 None => { continue; }
             };
@@ -697,8 +695,7 @@ impl<'a,'tcx> ProbeContext<'a,'tcx> {
         debug!("assemble_where_clause_candidates(trait_def_id={})",
                trait_def_id.repr(self.tcx()));
 
-        let caller_predicates =
-            self.fcx.inh.param_env.caller_bounds.predicates.as_slice().to_vec();
+        let caller_predicates = self.fcx.inh.param_env.caller_bounds.clone();
         for poly_bound in traits::elaborate_predicates(self.tcx(), caller_predicates)
                           .filter_map(|p| p.to_opt_poly_trait_ref())
                           .filter(|b| b.def_id() == trait_def_id)
@@ -1140,19 +1137,13 @@ fn impl_method<'tcx>(tcx: &ty::ctxt<'tcx>,
 /// index (or `None`, if no such method).
 fn trait_method<'tcx>(tcx: &ty::ctxt<'tcx>,
                       trait_def_id: ast::DefId,
-                      method_name: ast::Name,
-                      num_includes_types: bool)
+                      method_name: ast::Name)
                       -> Option<(uint, Rc<ty::Method<'tcx>>)>
 {
     let trait_items = ty::trait_items(tcx, trait_def_id);
     debug!("trait_method; items: {:?}", trait_items);
     trait_items
         .iter()
-        .filter(|item|
-            num_includes_types || match *item {
-                &ty::MethodTraitItem(_) => true,
-                &ty::TypeTraitItem(_) => false
-            })
         .enumerate()
         .find(|&(_, ref item)| item.name() == method_name)
         .and_then(|(idx, item)| item.as_opt_method().map(|m| (idx, m)))
diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs
index 65560040f47..fe3d9157be4 100644
--- a/src/librustc_typeck/check/mod.rs
+++ b/src/librustc_typeck/check/mod.rs
@@ -467,7 +467,8 @@ fn check_bare_fn<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
                            body: &ast::Block,
                            id: ast::NodeId,
                            raw_fty: Ty<'tcx>,
-                           param_env: ty::ParameterEnvironment<'a, 'tcx>) {
+                           param_env: ty::ParameterEnvironment<'a, 'tcx>)
+{
     match raw_fty.sty {
         ty::ty_bare_fn(_, ref fn_ty) => {
             let inh = Inherited::new(ccx.tcx, param_env);
@@ -1242,6 +1243,36 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         self.ccx.tcx.sess.err_count() - self.err_count_on_creation
     }
 
+    /// Resolves type variables in `ty` if possible. Unlike the infcx
+    /// version, this version will also select obligations if it seems
+    /// useful, in an effort to get more type information.
+    fn resolve_type_vars_if_possible(&self, mut ty: Ty<'tcx>) -> Ty<'tcx> {
+        // No ty::infer()? Nothing needs doing.
+        if !ty::type_has_ty_infer(ty) {
+            return ty;
+        }
+
+        // If `ty` is a type variable, see whether we already know what it is.
+        ty = self.infcx().resolve_type_vars_if_possible(&ty);
+        if !ty::type_has_ty_infer(ty) {
+            return ty;
+        }
+
+        // If not, try resolving any new fcx obligations that have cropped up.
+        vtable::select_new_fcx_obligations(self);
+        ty = self.infcx().resolve_type_vars_if_possible(&ty);
+        if !ty::type_has_ty_infer(ty) {
+            return ty;
+        }
+
+        // If not, try resolving *all* pending obligations as much as
+        // possible. This can help substantially when there are
+        // indirect dependencies that don't seem worth tracking
+        // precisely.
+        vtable::select_fcx_obligations_where_possible(self);
+        self.infcx().resolve_type_vars_if_possible(&ty)
+    }
+
     /// Resolves all type variables in `t` and then, if any were left
     /// unresolved, substitutes an error type. This is used after the
     /// main checking when doing a second pass before writeback. The
@@ -2333,9 +2364,9 @@ fn check_argument_types<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
         let check_blocks = *check_blocks;
         debug!("check_blocks={}", check_blocks);
 
-        // More awful hacks: before we check the blocks, try to do
-        // an "opportunistic" vtable resolution of any trait
-        // bounds on the call.
+        // More awful hacks: before we check argument types, try to do
+        // an "opportunistic" vtable resolution of any trait bounds on
+        // the call. This helps coercions.
         if check_blocks {
             vtable::select_new_fcx_obligations(fcx);
         }
@@ -2875,7 +2906,7 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>,
             // Shift is a special case: rhs must be uint, no matter what lhs is
             check_expr(fcx, &**rhs);
             let rhs_ty = fcx.expr_ty(&**rhs);
-            let rhs_ty = fcx.infcx().resolve_type_vars_if_possible(&rhs_ty);
+            let rhs_ty = structurally_resolved_type(fcx, rhs.span, rhs_ty);
             if ty::type_is_integral(rhs_ty) {
                 fcx.write_ty(expr.id, lhs_t);
             } else {
@@ -5127,21 +5158,12 @@ pub fn instantiate_path<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
 
 // Resolves `typ` by a single level if `typ` is a type variable.  If no
 // resolution is possible, then an error is reported.
-pub fn structurally_resolved_type<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, sp: Span,
-                                            mut ty: Ty<'tcx>) -> Ty<'tcx> {
-    // If `ty` is a type variable, see whether we already know what it is.
-    ty = fcx.infcx().shallow_resolve(ty);
-
-    // If not, try resolve pending fcx obligations. Those can shed light.
-    //
-    // FIXME(#18391) -- This current strategy can lead to bad performance in
-    // extreme cases.  We probably ought to smarter in general about
-    // only resolving when we need help and only resolving obligations
-    // will actually help.
-    if ty::type_is_ty_var(ty) {
-        vtable::select_fcx_obligations_where_possible(fcx);
-        ty = fcx.infcx().shallow_resolve(ty);
-    }
+pub fn structurally_resolved_type<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
+                                            sp: Span,
+                                            ty: Ty<'tcx>)
+                                            -> Ty<'tcx>
+{
+    let mut ty = fcx.resolve_type_vars_if_possible(ty);
 
     // If not, error.
     if ty::type_is_ty_var(ty) {
diff --git a/src/librustc_typeck/check/regionck.rs b/src/librustc_typeck/check/regionck.rs
index f2a3d660925..b039f3ab8e4 100644
--- a/src/librustc_typeck/check/regionck.rs
+++ b/src/librustc_typeck/check/regionck.rs
@@ -1482,7 +1482,7 @@ fn generic_must_outlive<'a, 'tcx>(rcx: &Rcx<'a, 'tcx>,
     let mut param_bounds =
         ty::required_region_bounds(rcx.tcx(),
                                    generic.to_ty(rcx.tcx()),
-                                   param_env.caller_bounds.predicates.as_slice().to_vec());
+                                   param_env.caller_bounds.clone());
 
     // In the case of a projection T::Foo, we may be able to extract bounds from the trait def:
     match *generic {
diff --git a/src/librustc_typeck/check/wf.rs b/src/librustc_typeck/check/wf.rs
index 60284433ffe..db226295cd9 100644
--- a/src/librustc_typeck/check/wf.rs
+++ b/src/librustc_typeck/check/wf.rs
@@ -127,6 +127,7 @@ impl<'ccx, 'tcx> CheckTypeWellFormedVisitor<'ccx, 'tcx> {
         reject_non_type_param_bounds(ccx.tcx, item.span, &type_scheme.generics);
         let param_env =
             ty::construct_parameter_environment(ccx.tcx,
+                                                item.span,
                                                 &type_scheme.generics,
                                                 item.id);
         let inh = Inherited::new(ccx.tcx, param_env);
diff --git a/src/librustc_typeck/lib.rs b/src/librustc_typeck/lib.rs
index 78007f3552e..31c9f996126 100644
--- a/src/librustc_typeck/lib.rs
+++ b/src/librustc_typeck/lib.rs
@@ -64,7 +64,8 @@ This API is completely unstable and subject to change.
 */
 
 #![crate_name = "rustc_typeck"]
-#![unstable]
+#![unstable(feature = "rustc_private")]
+#![feature(staged_api)]
 #![staged_api]
 #![crate_type = "dylib"]
 #![crate_type = "rlib"]
@@ -79,7 +80,10 @@ This API is completely unstable and subject to change.
 #![feature(rustc_diagnostic_macros)]
 #![allow(unknown_features)] #![feature(int_uint)]
 #![allow(non_camel_case_types)]
-#![allow(unstable)]
+#![feature(collections)]
+#![feature(core)]
+#![feature(rustc_private)]
+#![feature(std_misc)]
 
 #[macro_use] extern crate log;
 #[macro_use] extern crate syntax;
diff --git a/src/librustc_typeck/variance.rs b/src/librustc_typeck/variance.rs
index ed8a50110e5..63ad47ff31f 100644
--- a/src/librustc_typeck/variance.rs
+++ b/src/librustc_typeck/variance.rs
@@ -818,6 +818,12 @@ impl<'a, 'tcx> ConstraintContext<'a, 'tcx> {
                     trait_def.generics.regions.get_slice(subst::TypeSpace),
                     trait_ref.substs(),
                     variance);
+
+                let projections = data.projection_bounds_with_self_ty(self.tcx(),
+                                                                      self.tcx().types.err);
+                for projection in projections.iter() {
+                    self.add_constraints_from_ty(generics, projection.0.ty, self.invariant);
+                }
             }
 
             ty::ty_param(ref data) => {
diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs
index 4276e079e29..d2080419469 100644
--- a/src/librustdoc/clean/mod.rs
+++ b/src/librustdoc/clean/mod.rs
@@ -32,6 +32,7 @@ use syntax::ast_util;
 use syntax::ast_util::PostExpansionMethod;
 use syntax::attr;
 use syntax::attr::{AttributeMethods, AttrMetaMethods};
+use syntax::codemap;
 use syntax::codemap::{DUMMY_SP, Pos, Spanned};
 use syntax::parse::token::{self, InternedString, special_idents};
 use syntax::ptr::P;
@@ -446,11 +447,13 @@ impl attr::AttrMetaMethods for Attribute {
         }
     }
     fn meta_item_list<'a>(&'a self) -> Option<&'a [P<ast::MetaItem>]> { None }
+    fn span(&self) -> codemap::Span { unimplemented!() }
 }
 impl<'a> attr::AttrMetaMethods for &'a Attribute {
     fn name(&self) -> InternedString { (**self).name() }
     fn value_str(&self) -> Option<InternedString> { (**self).value_str() }
     fn meta_item_list(&self) -> Option<&[P<ast::MetaItem>]> { None }
+    fn span(&self) -> codemap::Span { unimplemented!() }
 }
 
 #[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Show)]
@@ -533,7 +536,7 @@ fn external_path_params(cx: &DocContext, trait_did: Option<ast::DefId>,
     match (trait_did, cx.tcx_opt()) {
         // Attempt to sugar an external path like Fn<(A, B,), C> to Fn(A, B) -> C
         (Some(did), Some(ref tcx)) if tcx.lang_items.fn_trait_kind(did).is_some() => {
-            assert_eq!(types.len(), 2);
+            assert_eq!(types.len(), 1);
             let inputs = match types[0].sty {
                 sty::ty_tup(ref tys) => tys.iter().map(|t| t.clean(cx)).collect(),
                 _ => {
@@ -544,10 +547,12 @@ fn external_path_params(cx: &DocContext, trait_did: Option<ast::DefId>,
                     }
                 }
             };
-            let output = match types[1].sty {
-                sty::ty_tup(ref v) if v.is_empty() => None, // -> ()
-                _ => Some(types[1].clean(cx))
-            };
+            let output = None;
+            // FIXME(#20299) return type comes from a projection now
+            // match types[1].sty {
+            //     sty::ty_tup(ref v) if v.is_empty() => None, // -> ()
+            //     _ => Some(types[1].clean(cx))
+            // };
             PathParameters::Parenthesized {
                 inputs: inputs,
                 output: output
@@ -2473,15 +2478,20 @@ impl Clean<Item> for doctree::Macro {
 #[derive(Clone, RustcEncodable, RustcDecodable, Show)]
 pub struct Stability {
     pub level: attr::StabilityLevel,
-    pub text: String
+    pub feature: String,
+    pub since: String,
+    pub reason: String
 }
 
 impl Clean<Stability> for attr::Stability {
     fn clean(&self, _: &DocContext) -> Stability {
         Stability {
             level: self.level,
-            text: self.text.as_ref().map_or("".to_string(),
-                                            |interned| interned.get().to_string()),
+            feature: self.feature.get().to_string(),
+            since: self.since.as_ref().map_or("".to_string(),
+                                              |interned| interned.get().to_string()),
+            reason: self.reason.as_ref().map_or("".to_string(),
+                                                |interned| interned.get().to_string()),
         }
     }
 }
diff --git a/src/librustdoc/core.rs b/src/librustdoc/core.rs
index 90a0a0f843e..fc3d6f5912f 100644
--- a/src/librustdoc/core.rs
+++ b/src/librustdoc/core.rs
@@ -108,7 +108,7 @@ pub fn run_core(search_paths: SearchPaths, cfgs: Vec<String>, externs: Externs,
     };
 
     let codemap = codemap::CodeMap::new();
-    let diagnostic_handler = diagnostic::default_handler(diagnostic::Auto, None);
+    let diagnostic_handler = diagnostic::default_handler(diagnostic::Auto, None, true);
     let span_diagnostic_handler =
         diagnostic::mk_span_handler(diagnostic_handler, codemap);
 
diff --git a/src/librustdoc/html/format.rs b/src/librustdoc/html/format.rs
index b713032bc05..b6db3222f30 100644
--- a/src/librustdoc/html/format.rs
+++ b/src/librustdoc/html/format.rs
@@ -714,7 +714,7 @@ impl<'a> fmt::Display for Stability<'a> {
             Some(ref stability) => {
                 write!(f, "<a class='stability {lvl}' title='{reason}'>{lvl}</a>",
                        lvl = stability.level,
-                       reason = stability.text)
+                       reason = stability.reason)
             }
             None => Ok(())
         }
@@ -728,8 +728,8 @@ impl<'a> fmt::Display for ConciseStability<'a> {
             Some(ref stability) => {
                 write!(f, "<a class='stability {lvl}' title='{lvl}{colon}{reason}'></a>",
                        lvl = stability.level,
-                       colon = if stability.text.len() > 0 { ": " } else { "" },
-                       reason = stability.text)
+                       colon = if stability.reason.len() > 0 { ": " } else { "" },
+                       reason = stability.reason)
             }
             None => {
                 write!(f, "<a class='stability Unmarked' title='No stability level'></a>")
@@ -765,12 +765,6 @@ impl fmt::Display for ModuleSummary {
             try!(write!(f, "<span class='summary Unstable' \
                             style='width: {:.4}%; display: inline-block'>&nbsp</span>",
                         (100 * cnt.unstable) as f64/tot as f64));
-            try!(write!(f, "<span class='summary Experimental' \
-                            style='width: {:.4}%; display: inline-block'>&nbsp</span>",
-                        (100 * cnt.experimental) as f64/tot as f64));
-            try!(write!(f, "<span class='summary Deprecated' \
-                            style='width: {:.4}%; display: inline-block'>&nbsp</span>",
-                        (100 * cnt.deprecated) as f64/tot as f64));
             try!(write!(f, "<span class='summary Unmarked' \
                             style='width: {:.4}%; display: inline-block'>&nbsp</span>",
                         (100 * cnt.unmarked) as f64/tot as f64));
@@ -786,13 +780,11 @@ impl fmt::Display for ModuleSummary {
         let mut context = Vec::new();
 
         let tot = self.counts.total();
-        let (stable, unstable, experimental, deprecated, unmarked) = if tot == 0 {
-            (0, 0, 0, 0, 0)
+        let (stable, unstable, unmarked) = if tot == 0 {
+            (0, 0, 0)
         } else {
             ((100 * self.counts.stable)/tot,
              (100 * self.counts.unstable)/tot,
-             (100 * self.counts.experimental)/tot,
-             (100 * self.counts.deprecated)/tot,
              (100 * self.counts.unmarked)/tot)
         };
 
@@ -804,13 +796,11 @@ its children (percentages total for {name}):
 <blockquote>
 <a class='stability Stable'></a> stable ({}%),<br/>
 <a class='stability Unstable'></a> unstable ({}%),<br/>
-<a class='stability Experimental'></a> experimental ({}%),<br/>
-<a class='stability Deprecated'></a> deprecated ({}%),<br/>
 <a class='stability Unmarked'></a> unmarked ({}%)
 </blockquote>
 The counts do not include methods or trait
 implementations that are visible only through a re-exported type.",
-stable, unstable, experimental, deprecated, unmarked,
+stable, unstable, unmarked,
 name=self.name));
         try!(write!(f, "<table>"));
         try!(fmt_inner(f, &mut context, self));
diff --git a/src/librustdoc/lib.rs b/src/librustdoc/lib.rs
index 18b62f5ebd2..75812a2803c 100644
--- a/src/librustdoc/lib.rs
+++ b/src/librustdoc/lib.rs
@@ -9,7 +9,8 @@
 // except according to those terms.
 
 #![crate_name = "rustdoc"]
-#![unstable]
+#![unstable(feature = "rustdoc")]
+#![feature(staged_api)]
 #![staged_api]
 #![crate_type = "dylib"]
 #![crate_type = "rlib"]
@@ -20,7 +21,17 @@
 #![feature(slicing_syntax)]
 #![feature(box_syntax)]
 #![allow(unknown_features)] #![feature(int_uint)]
-#![allow(unstable)]
+#![feature(collections)]
+#![feature(core)]
+#![feature(io)]
+#![feature(libc)]
+#![feature(os)]
+#![feature(path)]
+#![feature(rustc_private)]
+#![feature(std_misc)]
+#![feature(test)]
+#![feature(unicode)]
+#![feature(hash)]
 
 extern crate arena;
 extern crate getopts;
diff --git a/src/librustdoc/stability_summary.rs b/src/librustdoc/stability_summary.rs
index 943bc6ec996..f1d9aef7f7c 100644
--- a/src/librustdoc/stability_summary.rs
+++ b/src/librustdoc/stability_summary.rs
@@ -16,7 +16,7 @@
 use std::cmp::Ordering;
 use std::ops::Add;
 
-use syntax::attr::{Deprecated, Experimental, Unstable, Stable, Frozen, Locked};
+use syntax::attr::{Unstable, Stable};
 use syntax::ast::Public;
 
 use clean::{Crate, Item, ModuleItem, Module, EnumItem, Enum};
@@ -29,12 +29,8 @@ use html::render::cache;
 /// The counts for each stability level.
 #[derive(Copy)]
 pub struct Counts {
-    pub deprecated: uint,
-    pub experimental: uint,
     pub unstable: uint,
     pub stable: uint,
-    pub frozen: uint,
-    pub locked: uint,
 
     /// No stability level, inherited or otherwise.
     pub unmarked: uint,
@@ -45,12 +41,8 @@ impl Add for Counts {
 
     fn add(self, other: Counts) -> Counts {
         Counts {
-            deprecated:   self.deprecated   + other.deprecated,
-            experimental: self.experimental + other.experimental,
             unstable:     self.unstable     + other.unstable,
             stable:       self.stable       + other.stable,
-            frozen:       self.frozen       + other.frozen,
-            locked:       self.locked       + other.locked,
             unmarked:     self.unmarked     + other.unmarked,
         }
     }
@@ -59,19 +51,14 @@ impl Add for Counts {
 impl Counts {
     fn zero() -> Counts {
         Counts {
-            deprecated:   0,
-            experimental: 0,
             unstable:     0,
             stable:       0,
-            frozen:       0,
-            locked:       0,
             unmarked:     0,
         }
     }
 
     pub fn total(&self) -> uint {
-        self.deprecated + self.experimental + self.unstable + self.stable +
-            self.frozen + self.locked + self.unmarked
+        self.unstable + self.stable + self.unmarked
     }
 }
 
@@ -106,14 +93,10 @@ fn visible(item: &Item) -> bool {
 
 fn count_stability(stab: Option<&Stability>) -> Counts {
     match stab {
-        None             => Counts { unmarked: 1,     .. Counts::zero() },
+        None            => Counts { unmarked: 1,     .. Counts::zero() },
         Some(ref stab) => match stab.level {
-            Deprecated   => Counts { deprecated: 1,   .. Counts::zero() },
-            Experimental => Counts { experimental: 1, .. Counts::zero() },
-            Unstable     => Counts { unstable: 1,     .. Counts::zero() },
-            Stable       => Counts { stable: 1,       .. Counts::zero() },
-            Frozen       => Counts { frozen: 1,       .. Counts::zero() },
-            Locked       => Counts { locked: 1,       .. Counts::zero() },
+            Unstable    => Counts { unstable: 1,     .. Counts::zero() },
+            Stable      => Counts { stable: 1,       .. Counts::zero() },
         }
     }
 }
diff --git a/src/librustdoc/test.rs b/src/librustdoc/test.rs
index 0919377395b..2f692fe99cd 100644
--- a/src/librustdoc/test.rs
+++ b/src/librustdoc/test.rs
@@ -58,7 +58,7 @@ pub fn run(input: &str,
     };
 
     let codemap = CodeMap::new();
-    let diagnostic_handler = diagnostic::default_handler(diagnostic::Auto, None);
+    let diagnostic_handler = diagnostic::default_handler(diagnostic::Auto, None, true);
     let span_diagnostic_handler =
     diagnostic::mk_span_handler(diagnostic_handler, codemap);
 
@@ -164,7 +164,7 @@ fn runtest(test: &str, cratename: &str, libs: SearchPaths,
 
     // Compile the code
     let codemap = CodeMap::new();
-    let diagnostic_handler = diagnostic::mk_handler(box emitter);
+    let diagnostic_handler = diagnostic::mk_handler(true, box emitter);
     let span_diagnostic_handler =
         diagnostic::mk_span_handler(diagnostic_handler, codemap);
 
diff --git a/src/libserialize/lib.rs b/src/libserialize/lib.rs
index 45dc297330b..d51bb3af627 100644
--- a/src/libserialize/lib.rs
+++ b/src/libserialize/lib.rs
@@ -15,7 +15,9 @@ Core encoding and decoding interfaces.
 */
 
 #![crate_name = "serialize"]
-#![unstable = "deprecated in favor of rustc-serialize on crates.io"]
+#![unstable(feature = "rustc_private",
+            reason = "deprecated in favor of rustc-serialize on crates.io")]
+#![feature(staged_api)]
 #![staged_api]
 #![crate_type = "rlib"]
 #![crate_type = "dylib"]
@@ -28,7 +30,14 @@ Core encoding and decoding interfaces.
 #![feature(old_impl_check)]
 #![feature(slicing_syntax)]
 #![allow(unknown_features)] #![feature(int_uint)]
-#![allow(unstable)]
+#![feature(collections)]
+#![feature(core)]
+#![feature(io)]
+#![feature(path)]
+#![feature(rustc_private)]
+#![feature(std_misc)]
+#![feature(unicode)]
+#![cfg_attr(test, feature(test))]
 
 // test harness access
 #[cfg(test)] extern crate test;
diff --git a/src/libstd/ascii.rs b/src/libstd/ascii.rs
index 77c2315194b..9aa38e711e7 100644
--- a/src/libstd/ascii.rs
+++ b/src/libstd/ascii.rs
@@ -12,7 +12,8 @@
 
 //! Operations on ASCII strings and characters
 
-#![unstable = "unsure about placement and naming"]
+#![unstable(feature = "std_misc",
+            reason = "unsure about placement and naming")]
 
 use iter::IteratorExt;
 use ops::FnMut;
@@ -22,7 +23,8 @@ use string::String;
 use vec::Vec;
 
 /// Extension methods for ASCII-subset only operations on owned strings
-#[unstable = "would prefer to do this in a more general way"]
+#[unstable(feature = "std_misc",
+           reason = "would prefer to do this in a more general way")]
 pub trait OwnedAsciiExt {
     /// Convert the string to ASCII upper case:
     /// ASCII letters 'a' to 'z' are mapped to 'A' to 'Z',
@@ -36,7 +38,8 @@ pub trait OwnedAsciiExt {
 }
 
 /// Extension methods for ASCII-subset only operations on string slices
-#[unstable = "would prefer to do this in a more general way"]
+#[unstable(feature = "std_misc",
+           reason = "would prefer to do this in a more general way")]
 pub trait AsciiExt<T = Self> {
     /// Check if within the ASCII range.
     fn is_ascii(&self) -> bool;
@@ -57,7 +60,8 @@ pub trait AsciiExt<T = Self> {
     fn eq_ignore_ascii_case(&self, other: &Self) -> bool;
 }
 
-#[unstable = "would prefer to do this in a more general way"]
+#[unstable(feature = "std_misc",
+           reason = "would prefer to do this in a more general way")]
 impl AsciiExt<String> for str {
     #[inline]
     fn is_ascii(&self) -> bool {
@@ -82,7 +86,8 @@ impl AsciiExt<String> for str {
     }
 }
 
-#[unstable = "would prefer to do this in a more general way"]
+#[unstable(feature = "std_misc",
+           reason = "would prefer to do this in a more general way")]
 impl OwnedAsciiExt for String {
     #[inline]
     fn into_ascii_uppercase(self) -> String {
@@ -97,7 +102,8 @@ impl OwnedAsciiExt for String {
     }
 }
 
-#[unstable = "would prefer to do this in a more general way"]
+#[unstable(feature = "std_misc",
+           reason = "would prefer to do this in a more general way")]
 impl AsciiExt<Vec<u8>> for [u8] {
     #[inline]
     fn is_ascii(&self) -> bool {
@@ -123,7 +129,8 @@ impl AsciiExt<Vec<u8>> for [u8] {
     }
 }
 
-#[unstable = "would prefer to do this in a more general way"]
+#[unstable(feature = "std_misc",
+           reason = "would prefer to do this in a more general way")]
 impl OwnedAsciiExt for Vec<u8> {
     #[inline]
     fn into_ascii_uppercase(mut self) -> Vec<u8> {
@@ -142,7 +149,8 @@ impl OwnedAsciiExt for Vec<u8> {
     }
 }
 
-#[unstable = "would prefer to do this in a more general way"]
+#[unstable(feature = "std_misc",
+           reason = "would prefer to do this in a more general way")]
 impl AsciiExt for u8 {
     #[inline]
     fn is_ascii(&self) -> bool {
@@ -165,7 +173,8 @@ impl AsciiExt for u8 {
     }
 }
 
-#[unstable = "would prefer to do this in a more general way"]
+#[unstable(feature = "std_misc",
+           reason = "would prefer to do this in a more general way")]
 impl AsciiExt for char {
     #[inline]
     fn is_ascii(&self) -> bool {
@@ -207,7 +216,8 @@ impl AsciiExt for char {
 /// - Any other chars in the range [0x20,0x7e] are not escaped.
 /// - Any other chars are given hex escapes.
 /// - Unicode escapes are never generated by this function.
-#[unstable = "needs to be updated to use an iterator"]
+#[unstable(feature = "std_misc",
+           reason = "needs to be updated to use an iterator")]
 pub fn escape_default<F>(c: u8, mut f: F) where
     F: FnMut(u8),
 {
diff --git a/src/libstd/bool.rs b/src/libstd/bool.rs
index bbaab5ee3db..0d8b233a169 100644
--- a/src/libstd/bool.rs
+++ b/src/libstd/bool.rs
@@ -11,5 +11,5 @@
 //! The boolean type
 
 #![doc(primitive = "bool")]
-#![stable]
+#![stable(feature = "rust1", since = "1.0.0")]
 
diff --git a/src/libstd/collections/hash/map.rs b/src/libstd/collections/hash/map.rs
index 342d00a23c8..ae295c3e8e4 100644
--- a/src/libstd/collections/hash/map.rs
+++ b/src/libstd/collections/hash/map.rs
@@ -296,7 +296,7 @@ fn test_resize_policy() {
 /// }
 /// ```
 #[derive(Clone)]
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 pub struct HashMap<K, V, S = RandomState> {
     // All hashes are keyed on these values, to prevent hash collision attacks.
     hash_state: S,
@@ -499,7 +499,7 @@ impl<K: Hash<Hasher> + Eq, V> HashMap<K, V, RandomState> {
     /// let mut map: HashMap<&str, int> = HashMap::new();
     /// ```
     #[inline]
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     pub fn new() -> HashMap<K, V, RandomState> {
         Default::default()
     }
@@ -513,7 +513,7 @@ impl<K: Hash<Hasher> + Eq, V> HashMap<K, V, RandomState> {
     /// let mut map: HashMap<&str, int> = HashMap::with_capacity(10);
     /// ```
     #[inline]
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     pub fn with_capacity(capacity: uint) -> HashMap<K, V, RandomState> {
         HashMap::with_capacity_and_hash_state(capacity, Default::default())
     }
@@ -539,7 +539,7 @@ impl<K, V, S, H> HashMap<K, V, S>
     /// map.insert(1i, 2u);
     /// ```
     #[inline]
-    #[unstable = "hasher stuff is unclear"]
+    #[unstable(feature = "std_misc", reason = "hasher stuff is unclear")]
     pub fn with_hash_state(hash_state: S) -> HashMap<K, V, S> {
         HashMap {
             hash_state:    hash_state,
@@ -567,7 +567,7 @@ impl<K, V, S, H> HashMap<K, V, S>
     /// map.insert(1i, 2u);
     /// ```
     #[inline]
-    #[unstable = "hasher stuff is unclear"]
+    #[unstable(feature = "std_misc", reason = "hasher stuff is unclear")]
     pub fn with_capacity_and_hash_state(capacity: uint, hash_state: S)
                                         -> HashMap<K, V, S> {
         let resize_policy = DefaultResizePolicy::new();
@@ -591,7 +591,7 @@ impl<K, V, S, H> HashMap<K, V, S>
     /// assert!(map.capacity() >= 100);
     /// ```
     #[inline]
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     pub fn capacity(&self) -> uint {
         self.resize_policy.usable_capacity(self.table.capacity())
     }
@@ -611,7 +611,7 @@ impl<K, V, S, H> HashMap<K, V, S>
     /// let mut map: HashMap<&str, int> = HashMap::new();
     /// map.reserve(10);
     /// ```
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     pub fn reserve(&mut self, additional: uint) {
         let new_size = self.len().checked_add(additional).expect("capacity overflow");
         let min_cap = self.resize_policy.min_capacity(new_size);
@@ -723,7 +723,7 @@ impl<K, V, S, H> HashMap<K, V, S>
     /// map.shrink_to_fit();
     /// assert!(map.capacity() >= 2);
     /// ```
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     pub fn shrink_to_fit(&mut self) {
         let min_capacity = self.resize_policy.min_capacity(self.len());
         let min_capacity = max(min_capacity.next_power_of_two(), INITIAL_CAPACITY);
@@ -817,7 +817,7 @@ impl<K, V, S, H> HashMap<K, V, S>
     ///     println!("{}", key);
     /// }
     /// ```
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     pub fn keys<'a>(&'a self) -> Keys<'a, K, V> {
         fn first<A, B>((a, _): (A, B)) -> A { a }
         let first: fn((&'a K,&'a V)) -> &'a K = first; // coerce to fn ptr
@@ -842,7 +842,7 @@ impl<K, V, S, H> HashMap<K, V, S>
     ///     println!("{}", val);
     /// }
     /// ```
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     pub fn values<'a>(&'a self) -> Values<'a, K, V> {
         fn second<A, B>((_, b): (A, B)) -> B { b }
         let second: fn((&'a K,&'a V)) -> &'a V = second; // coerce to fn ptr
@@ -867,7 +867,7 @@ impl<K, V, S, H> HashMap<K, V, S>
     ///     println!("key: {} val: {}", key, val);
     /// }
     /// ```
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     pub fn iter(&self) -> Iter<K, V> {
         Iter { inner: self.table.iter() }
     }
@@ -895,7 +895,7 @@ impl<K, V, S, H> HashMap<K, V, S>
     ///     println!("key: {} val: {}", key, val);
     /// }
     /// ```
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     pub fn iter_mut(&mut self) -> IterMut<K, V> {
         IterMut { inner: self.table.iter_mut() }
     }
@@ -917,7 +917,7 @@ impl<K, V, S, H> HashMap<K, V, S>
     /// // Not possible with .iter()
     /// let vec: Vec<(&str, int)> = map.into_iter().collect();
     /// ```
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     pub fn into_iter(self) -> IntoIter<K, V> {
         fn last_two<A, B, C>((_, b, c): (A, B, C)) -> (B, C) { (b, c) }
         let last_two: fn((SafeHash, K, V)) -> (K, V) = last_two;
@@ -928,7 +928,8 @@ impl<K, V, S, H> HashMap<K, V, S>
     }
 
     /// Gets the given key's corresponding entry in the map for in-place manipulation.
-    #[unstable = "precise API still being fleshed out"]
+    #[unstable(feature = "std_misc",
+               reason = "precise API still being fleshed out")]
     pub fn entry<'a>(&'a mut self, key: K) -> Entry<'a, K, V>
     {
         // Gotta resize now.
@@ -950,7 +951,7 @@ impl<K, V, S, H> HashMap<K, V, S>
     /// a.insert(1u, "a");
     /// assert_eq!(a.len(), 1);
     /// ```
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     pub fn len(&self) -> uint { self.table.size() }
 
     /// Returns true if the map contains no elements.
@@ -966,7 +967,7 @@ impl<K, V, S, H> HashMap<K, V, S>
     /// assert!(!a.is_empty());
     /// ```
     #[inline]
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     pub fn is_empty(&self) -> bool { self.len() == 0 }
 
     /// Clears the map, returning all key-value pairs as an iterator. Keeps the
@@ -989,7 +990,8 @@ impl<K, V, S, H> HashMap<K, V, S>
     /// assert!(a.is_empty());
     /// ```
     #[inline]
-    #[unstable = "matches collection reform specification, waiting for dust to settle"]
+    #[unstable(feature = "std_misc",
+               reason = "matches collection reform specification, waiting for dust to settle")]
     pub fn drain(&mut self) -> Drain<K, V> {
         fn last_two<A, B, C>((_, b, c): (A, B, C)) -> (B, C) { (b, c) }
         let last_two: fn((SafeHash, K, V)) -> (K, V) = last_two; // coerce to fn pointer
@@ -1012,7 +1014,7 @@ impl<K, V, S, H> HashMap<K, V, S>
     /// a.clear();
     /// assert!(a.is_empty());
     /// ```
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     #[inline]
     pub fn clear(&mut self) {
         self.drain();
@@ -1034,7 +1036,7 @@ impl<K, V, S, H> HashMap<K, V, S>
     /// assert_eq!(map.get(&1), Some(&"a"));
     /// assert_eq!(map.get(&2), None);
     /// ```
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     pub fn get<Q: ?Sized>(&self, k: &Q) -> Option<&V>
         where Q: Hash<H> + Eq + BorrowFrom<K>
     {
@@ -1057,7 +1059,7 @@ impl<K, V, S, H> HashMap<K, V, S>
     /// assert_eq!(map.contains_key(&1), true);
     /// assert_eq!(map.contains_key(&2), false);
     /// ```
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     pub fn contains_key<Q: ?Sized>(&self, k: &Q) -> bool
         where Q: Hash<H> + Eq + BorrowFrom<K>
     {
@@ -1083,7 +1085,7 @@ impl<K, V, S, H> HashMap<K, V, S>
     /// }
     /// assert_eq!(map[1], "b");
     /// ```
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     pub fn get_mut<Q: ?Sized>(&mut self, k: &Q) -> Option<&mut V>
         where Q: Hash<H> + Eq + BorrowFrom<K>
     {
@@ -1106,7 +1108,7 @@ impl<K, V, S, H> HashMap<K, V, S>
     /// assert_eq!(map.insert(37, "c"), Some("b"));
     /// assert_eq!(map[37], "c");
     /// ```
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     pub fn insert(&mut self, k: K, v: V) -> Option<V> {
         let hash = self.make_hash(&k);
         self.reserve(1);
@@ -1135,7 +1137,7 @@ impl<K, V, S, H> HashMap<K, V, S>
     /// assert_eq!(map.remove(&1), Some("a"));
     /// assert_eq!(map.remove(&1), None);
     /// ```
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     pub fn remove<Q: ?Sized>(&mut self, k: &Q) -> Option<V>
         where Q: Hash<H> + Eq + BorrowFrom<K>
     {
@@ -1208,14 +1210,14 @@ impl<K, V, S, H> PartialEq for HashMap<K, V, S>
     }
 }
 
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl<K, V, S, H> Eq for HashMap<K, V, S>
     where K: Eq + Hash<H>, V: Eq,
           S: HashState<Hasher=H>,
           H: hash::Hasher<Output=u64>
 {}
 
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl<K, V, S, H> Debug for HashMap<K, V, S>
     where K: Eq + Hash<H> + Debug, V: Debug,
           S: HashState<Hasher=H>,
@@ -1233,7 +1235,7 @@ impl<K, V, S, H> Debug for HashMap<K, V, S>
     }
 }
 
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl<K, V, S, H> Default for HashMap<K, V, S>
     where K: Eq + Hash<H>,
           S: HashState<Hasher=H> + Default,
@@ -1244,7 +1246,7 @@ impl<K, V, S, H> Default for HashMap<K, V, S>
     }
 }
 
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl<K, Q: ?Sized, V, S, H> Index<Q> for HashMap<K, V, S>
     where K: Eq + Hash<H>,
           Q: Eq + Hash<H> + BorrowFrom<K>,
@@ -1259,7 +1261,7 @@ impl<K, Q: ?Sized, V, S, H> Index<Q> for HashMap<K, V, S>
     }
 }
 
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl<K, V, S, H, Q: ?Sized> IndexMut<Q> for HashMap<K, V, S>
     where K: Eq + Hash<H>,
           Q: Eq + Hash<H> + BorrowFrom<K>,
@@ -1275,7 +1277,7 @@ impl<K, V, S, H, Q: ?Sized> IndexMut<Q> for HashMap<K, V, S>
 }
 
 /// HashMap iterator.
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 pub struct Iter<'a, K: 'a, V: 'a> {
     inner: table::Iter<'a, K, V>
 }
@@ -1290,13 +1292,13 @@ impl<'a, K, V> Clone for Iter<'a, K, V> {
 }
 
 /// HashMap mutable values iterator.
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 pub struct IterMut<'a, K: 'a, V: 'a> {
     inner: table::IterMut<'a, K, V>
 }
 
 /// HashMap move iterator.
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 pub struct IntoIter<K, V> {
     inner: iter::Map<
         (SafeHash, K, V),
@@ -1307,7 +1309,7 @@ pub struct IntoIter<K, V> {
 }
 
 /// HashMap keys iterator.
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 pub struct Keys<'a, K: 'a, V: 'a> {
     inner: Map<(&'a K, &'a V), &'a K, Iter<'a, K, V>, fn((&'a K, &'a V)) -> &'a K>
 }
@@ -1322,7 +1324,7 @@ impl<'a, K, V> Clone for Keys<'a, K, V> {
 }
 
 /// HashMap values iterator.
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 pub struct Values<'a, K: 'a, V: 'a> {
     inner: Map<(&'a K, &'a V), &'a V, Iter<'a, K, V>, fn((&'a K, &'a V)) -> &'a V>
 }
@@ -1337,7 +1339,8 @@ impl<'a, K, V> Clone for Values<'a, K, V> {
 }
 
 /// HashMap drain iterator.
-#[unstable = "matches collection reform specification, waiting for dust to settle"]
+#[unstable(feature = "std_misc",
+           reason = "matches collection reform specification, waiting for dust to settle")]
 pub struct Drain<'a, K: 'a, V: 'a> {
     inner: iter::Map<
         (SafeHash, K, V),
@@ -1348,13 +1351,15 @@ pub struct Drain<'a, K: 'a, V: 'a> {
 }
 
 /// A view into a single occupied location in a HashMap.
-#[unstable = "precise API still being fleshed out"]
+#[unstable(feature = "std_misc",
+           reason = "precise API still being fleshed out")]
 pub struct OccupiedEntry<'a, K: 'a, V: 'a> {
     elem: FullBucket<K, V, &'a mut RawTable<K, V>>,
 }
 
 /// A view into a single empty location in a HashMap.
-#[unstable = "precise API still being fleshed out"]
+#[unstable(feature = "std_misc",
+           reason = "precise API still being fleshed out")]
 pub struct VacantEntry<'a, K: 'a, V: 'a> {
     hash: SafeHash,
     key: K,
@@ -1362,7 +1367,8 @@ pub struct VacantEntry<'a, K: 'a, V: 'a> {
 }
 
 /// A view into a single location in a map, which may be vacant or occupied.
-#[unstable = "precise API still being fleshed out"]
+#[unstable(feature = "std_misc",
+           reason = "precise API still being fleshed out")]
 pub enum Entry<'a, K: 'a, V: 'a> {
     /// An occupied Entry.
     Occupied(OccupiedEntry<'a, K, V>),
@@ -1379,79 +1385,80 @@ enum VacantEntryState<K, V, M> {
     NoElem(EmptyBucket<K, V, M>),
 }
 
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl<'a, K, V> Iterator for Iter<'a, K, V> {
     type Item = (&'a K, &'a V);
 
     #[inline] fn next(&mut self) -> Option<(&'a K, &'a V)> { self.inner.next() }
     #[inline] fn size_hint(&self) -> (usize, Option<usize>) { self.inner.size_hint() }
 }
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl<'a, K, V> ExactSizeIterator for Iter<'a, K, V> {
     #[inline] fn len(&self) -> usize { self.inner.len() }
 }
 
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl<'a, K, V> Iterator for IterMut<'a, K, V> {
     type Item = (&'a K, &'a mut V);
 
     #[inline] fn next(&mut self) -> Option<(&'a K, &'a mut V)> { self.inner.next() }
     #[inline] fn size_hint(&self) -> (usize, Option<usize>) { self.inner.size_hint() }
 }
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl<'a, K, V> ExactSizeIterator for IterMut<'a, K, V> {
     #[inline] fn len(&self) -> usize { self.inner.len() }
 }
 
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl<K, V> Iterator for IntoIter<K, V> {
     type Item = (K, V);
 
     #[inline] fn next(&mut self) -> Option<(K, V)> { self.inner.next() }
     #[inline] fn size_hint(&self) -> (usize, Option<usize>) { self.inner.size_hint() }
 }
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl<K, V> ExactSizeIterator for IntoIter<K, V> {
     #[inline] fn len(&self) -> usize { self.inner.len() }
 }
 
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl<'a, K, V> Iterator for Keys<'a, K, V> {
     type Item = &'a K;
 
     #[inline] fn next(&mut self) -> Option<(&'a K)> { self.inner.next() }
     #[inline] fn size_hint(&self) -> (usize, Option<usize>) { self.inner.size_hint() }
 }
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl<'a, K, V> ExactSizeIterator for Keys<'a, K, V> {
     #[inline] fn len(&self) -> usize { self.inner.len() }
 }
 
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl<'a, K, V> Iterator for Values<'a, K, V> {
     type Item = &'a V;
 
     #[inline] fn next(&mut self) -> Option<(&'a V)> { self.inner.next() }
     #[inline] fn size_hint(&self) -> (usize, Option<usize>) { self.inner.size_hint() }
 }
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl<'a, K, V> ExactSizeIterator for Values<'a, K, V> {
     #[inline] fn len(&self) -> usize { self.inner.len() }
 }
 
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl<'a, K, V> Iterator for Drain<'a, K, V> {
     type Item = (K, V);
 
     #[inline] fn next(&mut self) -> Option<(K, V)> { self.inner.next() }
     #[inline] fn size_hint(&self) -> (usize, Option<usize>) { self.inner.size_hint() }
 }
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl<'a, K, V> ExactSizeIterator for Drain<'a, K, V> {
     #[inline] fn len(&self) -> usize { self.inner.len() }
 }
 
-#[unstable = "matches collection reform v2 specification, waiting for dust to settle"]
+#[unstable(feature = "std_misc",
+           reason = "matches collection reform v2 specification, waiting for dust to settle")]
 impl<'a, K, V> Entry<'a, K, V> {
     /// Returns a mutable reference to the entry if occupied, or the VacantEntry if vacant.
     pub fn get(self) -> Result<&'a mut V, VacantEntry<'a, K, V>> {
@@ -1462,7 +1469,8 @@ impl<'a, K, V> Entry<'a, K, V> {
     }
 }
 
-#[unstable = "matches collection reform v2 specification, waiting for dust to settle"]
+#[unstable(feature = "std_misc",
+           reason = "matches collection reform v2 specification, waiting for dust to settle")]
 impl<'a, K, V> OccupiedEntry<'a, K, V> {
     /// Gets a reference to the value in the entry.
     pub fn get(&self) -> &V {
@@ -1493,7 +1501,8 @@ impl<'a, K, V> OccupiedEntry<'a, K, V> {
     }
 }
 
-#[unstable = "matches collection reform v2 specification, waiting for dust to settle"]
+#[unstable(feature = "std_misc",
+           reason = "matches collection reform v2 specification, waiting for dust to settle")]
 impl<'a, K: 'a, V: 'a> VacantEntry<'a, K, V> {
     /// Sets the value of the entry with the VacantEntry's key,
     /// and returns a mutable reference to it
@@ -1509,7 +1518,7 @@ impl<'a, K: 'a, V: 'a> VacantEntry<'a, K, V> {
     }
 }
 
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl<K, V, S, H> FromIterator<(K, V)> for HashMap<K, V, S>
     where K: Eq + Hash<H>,
           S: HashState<Hasher=H> + Default,
@@ -1524,7 +1533,7 @@ impl<K, V, S, H> FromIterator<(K, V)> for HashMap<K, V, S>
     }
 }
 
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl<K, V, S, H> Extend<(K, V)> for HashMap<K, V, S>
     where K: Eq + Hash<H>,
           S: HashState<Hasher=H>,
@@ -1545,13 +1554,15 @@ impl<K, V, S, H> Extend<(K, V)> for HashMap<K, V, S>
 /// instances are unlikely to produce the same result for the same values.
 #[derive(Clone)]
 #[allow(missing_copy_implementations)]
-#[unstable = "hashing an hash maps may be altered"]
+#[unstable(feature = "std_misc",
+           reason = "hashing an hash maps may be altered")]
 pub struct RandomState {
     k0: u64,
     k1: u64,
 }
 
-#[unstable = "hashing an hash maps may be altered"]
+#[unstable(feature = "std_misc",
+           reason = "hashing an hash maps may be altered")]
 impl RandomState {
     /// Construct a new `RandomState` that is initialized with random keys.
     #[inline]
@@ -1561,7 +1572,8 @@ impl RandomState {
     }
 }
 
-#[unstable = "hashing an hash maps may be altered"]
+#[unstable(feature = "std_misc",
+           reason = "hashing an hash maps may be altered")]
 impl HashState for RandomState {
     type Hasher = Hasher;
     fn hasher(&self) -> Hasher {
@@ -1569,7 +1581,8 @@ impl HashState for RandomState {
     }
 }
 
-#[unstable = "hashing an hash maps may be altered"]
+#[unstable(feature = "std_misc",
+           reason = "hashing an hash maps may be altered")]
 impl Default for RandomState {
     #[inline]
     fn default() -> RandomState {
diff --git a/src/libstd/collections/hash/set.rs b/src/libstd/collections/hash/set.rs
index 29e247d96d2..84f01f70c3e 100644
--- a/src/libstd/collections/hash/set.rs
+++ b/src/libstd/collections/hash/set.rs
@@ -90,7 +90,7 @@ use super::state::HashState;
 /// }
 /// ```
 #[derive(Clone)]
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 pub struct HashSet<T, S = RandomState> {
     map: HashMap<T, (), S>
 }
@@ -105,7 +105,7 @@ impl<T: Hash<Hasher> + Eq> HashSet<T, RandomState> {
     /// let mut set: HashSet<int> = HashSet::new();
     /// ```
     #[inline]
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     pub fn new() -> HashSet<T, RandomState> {
         HashSet::with_capacity(INITIAL_CAPACITY)
     }
@@ -120,7 +120,7 @@ impl<T: Hash<Hasher> + Eq> HashSet<T, RandomState> {
     /// let mut set: HashSet<int> = HashSet::with_capacity(10);
     /// ```
     #[inline]
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     pub fn with_capacity(capacity: uint) -> HashSet<T, RandomState> {
         HashSet { map: HashMap::with_capacity(capacity) }
     }
@@ -147,7 +147,7 @@ impl<T, S, H> HashSet<T, S>
     /// set.insert(2u);
     /// ```
     #[inline]
-    #[unstable = "hasher stuff is unclear"]
+    #[unstable(feature = "std_misc", reason = "hasher stuff is unclear")]
     pub fn with_hash_state(hash_state: S) -> HashSet<T, S> {
         HashSet::with_capacity_and_hash_state(INITIAL_CAPACITY, hash_state)
     }
@@ -171,7 +171,7 @@ impl<T, S, H> HashSet<T, S>
     /// set.insert(1i);
     /// ```
     #[inline]
-    #[unstable = "hasher stuff is unclear"]
+    #[unstable(feature = "std_misc", reason = "hasher stuff is unclear")]
     pub fn with_capacity_and_hash_state(capacity: uint, hash_state: S)
                                         -> HashSet<T, S> {
         HashSet {
@@ -189,7 +189,7 @@ impl<T, S, H> HashSet<T, S>
     /// assert!(set.capacity() >= 100);
     /// ```
     #[inline]
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     pub fn capacity(&self) -> uint {
         self.map.capacity()
     }
@@ -209,7 +209,7 @@ impl<T, S, H> HashSet<T, S>
     /// let mut set: HashSet<int> = HashSet::new();
     /// set.reserve(10);
     /// ```
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     pub fn reserve(&mut self, additional: uint) {
         self.map.reserve(additional)
     }
@@ -230,7 +230,7 @@ impl<T, S, H> HashSet<T, S>
     /// set.shrink_to_fit();
     /// assert!(set.capacity() >= 2);
     /// ```
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     pub fn shrink_to_fit(&mut self) {
         self.map.shrink_to_fit()
     }
@@ -251,7 +251,7 @@ impl<T, S, H> HashSet<T, S>
     ///     println!("{}", x);
     /// }
     /// ```
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     pub fn iter(&self) -> Iter<T> {
         Iter { iter: self.map.keys() }
     }
@@ -276,7 +276,7 @@ impl<T, S, H> HashSet<T, S>
     ///     println!("{}", x);
     /// }
     /// ```
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     pub fn into_iter(self) -> IntoIter<T> {
         fn first<A, B>((a, _): (A, B)) -> A { a }
         let first: fn((T, ())) -> T = first;
@@ -306,7 +306,7 @@ impl<T, S, H> HashSet<T, S>
     /// let diff: HashSet<int> = b.difference(&a).map(|&x| x).collect();
     /// assert_eq!(diff, [4i].iter().map(|&x| x).collect());
     /// ```
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     pub fn difference<'a>(&'a self, other: &'a HashSet<T, S>) -> Difference<'a, T, S> {
         Difference {
             iter: self.iter(),
@@ -334,7 +334,7 @@ impl<T, S, H> HashSet<T, S>
     /// assert_eq!(diff1, diff2);
     /// assert_eq!(diff1, [1i, 4].iter().map(|&x| x).collect());
     /// ```
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     pub fn symmetric_difference<'a>(&'a self, other: &'a HashSet<T, S>)
         -> SymmetricDifference<'a, T, S> {
         SymmetricDifference { iter: self.difference(other).chain(other.difference(self)) }
@@ -357,7 +357,7 @@ impl<T, S, H> HashSet<T, S>
     /// let diff: HashSet<int> = a.intersection(&b).map(|&x| x).collect();
     /// assert_eq!(diff, [2i, 3].iter().map(|&x| x).collect());
     /// ```
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     pub fn intersection<'a>(&'a self, other: &'a HashSet<T, S>) -> Intersection<'a, T, S> {
         Intersection {
             iter: self.iter(),
@@ -382,7 +382,7 @@ impl<T, S, H> HashSet<T, S>
     /// let diff: HashSet<int> = a.union(&b).map(|&x| x).collect();
     /// assert_eq!(diff, [1i, 2, 3, 4].iter().map(|&x| x).collect());
     /// ```
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     pub fn union<'a>(&'a self, other: &'a HashSet<T, S>) -> Union<'a, T, S> {
         Union { iter: self.iter().chain(other.difference(self)) }
     }
@@ -399,7 +399,7 @@ impl<T, S, H> HashSet<T, S>
     /// v.insert(1u);
     /// assert_eq!(v.len(), 1);
     /// ```
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     pub fn len(&self) -> uint { self.map.len() }
 
     /// Returns true if the set contains no elements
@@ -414,12 +414,13 @@ impl<T, S, H> HashSet<T, S>
     /// v.insert(1u);
     /// assert!(!v.is_empty());
     /// ```
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     pub fn is_empty(&self) -> bool { self.map.len() == 0 }
 
     /// Clears the set, returning all elements in an iterator.
     #[inline]
-    #[unstable = "matches collection reform specification, waiting for dust to settle"]
+    #[unstable(feature = "std_misc",
+               reason = "matches collection reform specification, waiting for dust to settle")]
     pub fn drain(&mut self) -> Drain<T> {
         fn first<A, B>((a, _): (A, B)) -> A { a }
         let first: fn((T, ())) -> T = first; // coerce to fn pointer
@@ -439,7 +440,7 @@ impl<T, S, H> HashSet<T, S>
     /// v.clear();
     /// assert!(v.is_empty());
     /// ```
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     pub fn clear(&mut self) { self.map.clear() }
 
     /// Returns `true` if the set contains a value.
@@ -457,7 +458,7 @@ impl<T, S, H> HashSet<T, S>
     /// assert_eq!(set.contains(&1), true);
     /// assert_eq!(set.contains(&4), false);
     /// ```
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     pub fn contains<Q: ?Sized>(&self, value: &Q) -> bool
         where Q: BorrowFrom<T> + Hash<H> + Eq
     {
@@ -481,7 +482,7 @@ impl<T, S, H> HashSet<T, S>
     /// b.insert(1);
     /// assert_eq!(a.is_disjoint(&b), false);
     /// ```
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     pub fn is_disjoint(&self, other: &HashSet<T, S>) -> bool {
         self.iter().all(|v| !other.contains(v))
     }
@@ -502,7 +503,7 @@ impl<T, S, H> HashSet<T, S>
     /// set.insert(4);
     /// assert_eq!(set.is_subset(&sup), false);
     /// ```
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     pub fn is_subset(&self, other: &HashSet<T, S>) -> bool {
         self.iter().all(|v| other.contains(v))
     }
@@ -527,7 +528,7 @@ impl<T, S, H> HashSet<T, S>
     /// assert_eq!(set.is_superset(&sub), true);
     /// ```
     #[inline]
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     pub fn is_superset(&self, other: &HashSet<T, S>) -> bool {
         other.is_subset(self)
     }
@@ -546,7 +547,7 @@ impl<T, S, H> HashSet<T, S>
     /// assert_eq!(set.insert(2), false);
     /// assert_eq!(set.len(), 1);
     /// ```
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     pub fn insert(&mut self, value: T) -> bool { self.map.insert(value, ()).is_none() }
 
     /// Removes a value from the set. Returns `true` if the value was
@@ -567,7 +568,7 @@ impl<T, S, H> HashSet<T, S>
     /// assert_eq!(set.remove(&2), true);
     /// assert_eq!(set.remove(&2), false);
     /// ```
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     pub fn remove<Q: ?Sized>(&mut self, value: &Q) -> bool
         where Q: BorrowFrom<T> + Hash<H> + Eq
     {
@@ -575,7 +576,7 @@ impl<T, S, H> HashSet<T, S>
     }
 }
 
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl<T, S, H> PartialEq for HashSet<T, S>
     where T: Eq + Hash<H>,
           S: HashState<Hasher=H>,
@@ -588,14 +589,14 @@ impl<T, S, H> PartialEq for HashSet<T, S>
     }
 }
 
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl<T, S, H> Eq for HashSet<T, S>
     where T: Eq + Hash<H>,
           S: HashState<Hasher=H>,
           H: hash::Hasher<Output=u64>
 {}
 
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl<T, S, H> fmt::Debug for HashSet<T, S>
     where T: Eq + Hash<H> + fmt::Debug,
           S: HashState<Hasher=H>,
@@ -613,7 +614,7 @@ impl<T, S, H> fmt::Debug for HashSet<T, S>
     }
 }
 
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl<T, S, H> FromIterator<T> for HashSet<T, S>
     where T: Eq + Hash<H>,
           S: HashState<Hasher=H> + Default,
@@ -627,7 +628,7 @@ impl<T, S, H> FromIterator<T> for HashSet<T, S>
     }
 }
 
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl<T, S, H> Extend<T> for HashSet<T, S>
     where T: Eq + Hash<H>,
           S: HashState<Hasher=H>,
@@ -640,19 +641,19 @@ impl<T, S, H> Extend<T> for HashSet<T, S>
     }
 }
 
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl<T, S, H> Default for HashSet<T, S>
     where T: Eq + Hash<H>,
           S: HashState<Hasher=H> + Default,
           H: hash::Hasher<Output=u64>
 {
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     fn default() -> HashSet<T, S> {
         HashSet::with_hash_state(Default::default())
     }
 }
 
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl<'a, 'b, T, S, H> BitOr<&'b HashSet<T, S>> for &'a HashSet<T, S>
     where T: Eq + Hash<H> + Clone,
           S: HashState<Hasher=H> + Default,
@@ -685,7 +686,7 @@ impl<'a, 'b, T, S, H> BitOr<&'b HashSet<T, S>> for &'a HashSet<T, S>
     }
 }
 
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl<'a, 'b, T, S, H> BitAnd<&'b HashSet<T, S>> for &'a HashSet<T, S>
     where T: Eq + Hash<H> + Clone,
           S: HashState<Hasher=H> + Default,
@@ -718,7 +719,7 @@ impl<'a, 'b, T, S, H> BitAnd<&'b HashSet<T, S>> for &'a HashSet<T, S>
     }
 }
 
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl<'a, 'b, T, S, H> BitXor<&'b HashSet<T, S>> for &'a HashSet<T, S>
     where T: Eq + Hash<H> + Clone,
           S: HashState<Hasher=H> + Default,
@@ -751,7 +752,7 @@ impl<'a, 'b, T, S, H> BitXor<&'b HashSet<T, S>> for &'a HashSet<T, S>
     }
 }
 
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl<'a, 'b, T, S, H> Sub<&'b HashSet<T, S>> for &'a HashSet<T, S>
     where T: Eq + Hash<H> + Clone,
           S: HashState<Hasher=H> + Default,
@@ -785,25 +786,25 @@ impl<'a, 'b, T, S, H> Sub<&'b HashSet<T, S>> for &'a HashSet<T, S>
 }
 
 /// HashSet iterator
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 pub struct Iter<'a, K: 'a> {
     iter: Keys<'a, K, ()>
 }
 
 /// HashSet move iterator
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 pub struct IntoIter<K> {
     iter: Map<(K, ()), K, map::IntoIter<K, ()>, fn((K, ())) -> K>
 }
 
 /// HashSet drain iterator
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 pub struct Drain<'a, K: 'a> {
     iter: Map<(K, ()), K, map::Drain<'a, K, ()>, fn((K, ())) -> K>,
 }
 
 /// Intersection iterator
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 pub struct Intersection<'a, T: 'a, S: 'a> {
     // iterator of the first set
     iter: Iter<'a, T>,
@@ -812,7 +813,7 @@ pub struct Intersection<'a, T: 'a, S: 'a> {
 }
 
 /// Difference iterator
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 pub struct Difference<'a, T: 'a, S: 'a> {
     // iterator of the first set
     iter: Iter<'a, T>,
@@ -821,54 +822,54 @@ pub struct Difference<'a, T: 'a, S: 'a> {
 }
 
 /// Symmetric difference iterator.
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 pub struct SymmetricDifference<'a, T: 'a, S: 'a> {
     iter: Chain<Difference<'a, T, S>, Difference<'a, T, S>>
 }
 
 /// Set union iterator.
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 pub struct Union<'a, T: 'a, S: 'a> {
     iter: Chain<Iter<'a, T>, Difference<'a, T, S>>
 }
 
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl<'a, K> Iterator for Iter<'a, K> {
     type Item = &'a K;
 
     fn next(&mut self) -> Option<&'a K> { self.iter.next() }
     fn size_hint(&self) -> (usize, Option<usize>) { self.iter.size_hint() }
 }
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl<'a, K> ExactSizeIterator for Iter<'a, K> {
     fn len(&self) -> usize { self.iter.len() }
 }
 
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl<K> Iterator for IntoIter<K> {
     type Item = K;
 
     fn next(&mut self) -> Option<K> { self.iter.next() }
     fn size_hint(&self) -> (usize, Option<usize>) { self.iter.size_hint() }
 }
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl<K> ExactSizeIterator for IntoIter<K> {
     fn len(&self) -> usize { self.iter.len() }
 }
 
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl<'a, K> Iterator for Drain<'a, K> {
     type Item = K;
 
     fn next(&mut self) -> Option<K> { self.iter.next() }
     fn size_hint(&self) -> (usize, Option<usize>) { self.iter.size_hint() }
 }
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl<'a, K> ExactSizeIterator for Drain<'a, K> {
     fn len(&self) -> usize { self.iter.len() }
 }
 
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl<'a, T, S, H> Iterator for Intersection<'a, T, S>
     where T: Eq + Hash<H>,
           S: HashState<Hasher=H>,
@@ -893,7 +894,7 @@ impl<'a, T, S, H> Iterator for Intersection<'a, T, S>
     }
 }
 
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl<'a, T, S, H> Iterator for Difference<'a, T, S>
     where T: Eq + Hash<H>,
           S: HashState<Hasher=H>,
@@ -918,7 +919,7 @@ impl<'a, T, S, H> Iterator for Difference<'a, T, S>
     }
 }
 
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl<'a, T, S, H> Iterator for SymmetricDifference<'a, T, S>
     where T: Eq + Hash<H>,
           S: HashState<Hasher=H>,
@@ -930,7 +931,7 @@ impl<'a, T, S, H> Iterator for SymmetricDifference<'a, T, S>
     fn size_hint(&self) -> (usize, Option<usize>) { self.iter.size_hint() }
 }
 
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl<'a, T, S, H> Iterator for Union<'a, T, S>
     where T: Eq + Hash<H>,
           S: HashState<Hasher=H>,
diff --git a/src/libstd/collections/hash/table.rs b/src/libstd/collections/hash/table.rs
index d810460a7d4..9e6a45d8bf0 100644
--- a/src/libstd/collections/hash/table.rs
+++ b/src/libstd/collections/hash/table.rs
@@ -629,7 +629,6 @@ impl<K, V> RawTable<K, V> {
 
     /// Creates a new raw table from a given capacity. All buckets are
     /// initially empty.
-    #[allow(unstable)]
     pub fn new(capacity: uint) -> RawTable<K, V> {
         unsafe {
             let ret = RawTable::new_uninitialized(capacity);
diff --git a/src/libstd/collections/mod.rs b/src/libstd/collections/mod.rs
index 21bea5dcdcb..0c55850b32a 100644
--- a/src/libstd/collections/mod.rs
+++ b/src/libstd/collections/mod.rs
@@ -359,7 +359,7 @@
 //! }
 //! ```
 
-#![stable]
+#![stable(feature = "rust1", since = "1.0.0")]
 
 pub use core_collections::Bound;
 pub use core_collections::{BinaryHeap, Bitv, BitvSet, BTreeMap, BTreeSet};
@@ -373,13 +373,13 @@ pub use self::hash_set::HashSet;
 
 mod hash;
 
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 pub mod hash_map {
     //! A hashmap
     pub use super::hash::map::*;
 }
 
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 pub mod hash_set {
     //! A hashset
     pub use super::hash::set::*;
@@ -387,7 +387,7 @@ pub mod hash_set {
 
 /// Experimental support for providing custom hash algorithms to a HashMap and
 /// HashSet.
-#[unstable = "module was recently added"]
+#[unstable(feature = "std_misc", reason = "module was recently added")]
 pub mod hash_state {
     pub use super::hash::state::*;
 }
diff --git a/src/libstd/dynamic_lib.rs b/src/libstd/dynamic_lib.rs
index db1239ae5b5..f35f63143ef 100644
--- a/src/libstd/dynamic_lib.rs
+++ b/src/libstd/dynamic_lib.rs
@@ -12,7 +12,7 @@
 //!
 //! A simple wrapper over the platform's dynamic library facilities
 
-#![unstable]
+#![unstable(feature = "std_misc")]
 #![allow(missing_docs)]
 
 use prelude::v1::*;
diff --git a/src/libstd/failure.rs b/src/libstd/failure.rs
index fdf522baf5c..c184d3f4661 100644
--- a/src/libstd/failure.rs
+++ b/src/libstd/failure.rs
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#![unstable]
+#![unstable(feature = "std_misc")]
 
 use prelude::v1::*;
 
diff --git a/src/libstd/ffi/c_str.rs b/src/libstd/ffi/c_str.rs
index 7d0e42e8e49..fdd7aa216d3 100644
--- a/src/libstd/ffi/c_str.rs
+++ b/src/libstd/ffi/c_str.rs
@@ -119,7 +119,7 @@ impl Deref for CString {
     }
 }
 
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl fmt::Debug for CString {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         String::from_utf8_lossy(self.as_bytes()).fmt(f)
diff --git a/src/libstd/ffi/mod.rs b/src/libstd/ffi/mod.rs
index 95ad6178bab..69ada28a4b4 100644
--- a/src/libstd/ffi/mod.rs
+++ b/src/libstd/ffi/mod.rs
@@ -10,8 +10,9 @@
 
 //! Utilities related to FFI bindings.
 
-#![unstable = "module just underwent fairly large reorganization and the dust \
-               still needs to settle"]
+#![unstable(feature = "std_misc",
+            reason = "module just underwent fairly large reorganization and the dust \
+                      still needs to settle")]
 
 pub use self::c_str::CString;
 pub use self::c_str::c_str_to_bytes;
diff --git a/src/libstd/ffi/os_str.rs b/src/libstd/ffi/os_str.rs
index 9c5cf62f853..8fdc5547e46 100644
--- a/src/libstd/ffi/os_str.rs
+++ b/src/libstd/ffi/os_str.rs
@@ -29,7 +29,8 @@
 //! for conversion to/from various other string types. Eventually these types
 //! will offer a full-fledged string API.
 
-#![unstable = "recently added as part of path/io reform"]
+#![unstable(feature = "os",
+            reason = "recently added as part of path/io reform")]
 
 use core::prelude::*;
 
diff --git a/src/libstd/fmt.rs b/src/libstd/fmt.rs
index 5965a0ceffb..4ab43e875cd 100644
--- a/src/libstd/fmt.rs
+++ b/src/libstd/fmt.rs
@@ -401,7 +401,7 @@
 //! them with the same character. For example, the `{` character is escaped with
 //! `{{` and the `}` character is escaped with `}}`.
 
-#![unstable]
+#![unstable(feature = "std_misc")]
 
 use string;
 
@@ -431,8 +431,9 @@ pub use core::fmt::{argument, argumentuint};
 /// let s = fmt::format(format_args!("Hello, {}!", "world"));
 /// assert_eq!(s, "Hello, world!".to_string());
 /// ```
-#[unstable = "this is an implementation detail of format! and should not \
-                  be called directly"]
+#[unstable(feature = "std_misc",
+           reason = "this is an implementation detail of format! and should not \
+                     be called directly")]
 pub fn format(args: Arguments) -> string::String {
     let mut output = string::String::new();
     let _ = write!(&mut output, "{}", args);
diff --git a/src/libstd/lib.rs b/src/libstd/lib.rs
index 119e7c50196..3a745389e1e 100644
--- a/src/libstd/lib.rs
+++ b/src/libstd/lib.rs
@@ -96,7 +96,8 @@
 //! and `format!`, also available to all Rust code.
 
 #![crate_name = "std"]
-#![stable]
+#![stable(feature = "rust1", since = "1.0.0")]
+#![feature(staged_api)]
 #![staged_api]
 #![crate_type = "rlib"]
 #![crate_type = "dylib"]
@@ -114,7 +115,14 @@
 #![feature(optin_builtin_traits)]
 #![feature(int_uint)]
 #![feature(int_uint)]
-#![allow(unstable)]
+#![feature(core)]
+#![feature(libc)]
+#![feature(alloc)]
+#![feature(unicode)]
+#![feature(collections)]
+#![feature(rand)]
+#![feature(hash)]
+#![cfg_attr(test, feature(test))]
 
 // Don't link to std. We are std.
 #![no_std]
@@ -177,7 +185,7 @@ pub use alloc::rc;
 pub use core_collections::slice;
 pub use core_collections::str;
 pub use core_collections::string;
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 pub use core_collections::vec;
 
 pub use unicode::char;
diff --git a/src/libstd/macros.rs b/src/libstd/macros.rs
index 9f0276c744b..9c3285a9d08 100644
--- a/src/libstd/macros.rs
+++ b/src/libstd/macros.rs
@@ -14,7 +14,7 @@
 //! library. Each macro is available for use when linking against the standard
 //! library.
 
-#![unstable]
+#![unstable(feature = "std_misc")]
 
 /// The entry point for panic of Rust tasks.
 ///
@@ -36,7 +36,7 @@
 /// panic!("this is a {} {message}", "fancy", message = "message");
 /// ```
 #[macro_export]
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 macro_rules! panic {
     () => ({
         panic!("explicit panic")
@@ -71,7 +71,7 @@ macro_rules! panic {
 /// format!("x = {}, y = {y}", 10i, y = 30i);
 /// ```
 #[macro_export]
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 macro_rules! format {
     ($($arg:tt)*) => ($crate::fmt::format(format_args!($($arg)*)))
 }
@@ -79,7 +79,7 @@ macro_rules! format {
 /// Equivalent to the `println!` macro except that a newline is not printed at
 /// the end of the message.
 #[macro_export]
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 macro_rules! print {
     ($($arg:tt)*) => ($crate::old_io::stdio::print_args(format_args!($($arg)*)))
 }
@@ -97,7 +97,7 @@ macro_rules! print {
 /// println!("format {} arguments", "some");
 /// ```
 #[macro_export]
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 macro_rules! println {
     ($($arg:tt)*) => ($crate::old_io::stdio::println_args(format_args!($($arg)*)))
 }
@@ -106,7 +106,7 @@ macro_rules! println {
 /// error if the value of the expression is `Err`. For more information, see
 /// `std::io`.
 #[macro_export]
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 macro_rules! try {
     ($expr:expr) => (match $expr {
         $crate::result::Result::Ok(val) => val,
@@ -148,7 +148,7 @@ macro_rules! try {
 ///
 /// For more information about select, see the `std::sync::mpsc::Select` structure.
 #[macro_export]
-#[unstable]
+#[unstable(feature = "std_misc")]
 macro_rules! select {
     (
         $($name:pat = $rx:ident.$meth:ident() => $code:expr),+
diff --git a/src/libstd/num/f32.rs b/src/libstd/num/f32.rs
index adbce893887..9b5b0e62a3c 100644
--- a/src/libstd/num/f32.rs
+++ b/src/libstd/num/f32.rs
@@ -10,7 +10,7 @@
 
 //! Operations and constants for 32-bits floats (`f32` type)
 
-#![stable]
+#![stable(feature = "rust1", since = "1.0.0")]
 #![allow(missing_docs)]
 #![allow(unsigned_negation)]
 #![doc(primitive = "f32")]
@@ -73,7 +73,7 @@ mod cmath {
     }
 }
 
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl Float for f32 {
     #[inline]
     fn nan() -> f32 { num::Float::nan() }
@@ -366,7 +366,7 @@ impl Float for f32 {
 ///
 /// * num - The float value
 #[inline]
-#[unstable = "may be removed or relocated"]
+#[unstable(feature = "std_misc", reason = "may be removed or relocated")]
 pub fn to_string(num: f32) -> String {
     let (r, _) = strconv::float_to_str_common(
         num, 10u, true, SignNeg, DigAll, ExpNone, false);
@@ -379,7 +379,7 @@ pub fn to_string(num: f32) -> String {
 ///
 /// * num - The float value
 #[inline]
-#[unstable = "may be removed or relocated"]
+#[unstable(feature = "std_misc", reason = "may be removed or relocated")]
 pub fn to_str_hex(num: f32) -> String {
     let (r, _) = strconv::float_to_str_common(
         num, 16u, true, SignNeg, DigAll, ExpNone, false);
@@ -394,7 +394,7 @@ pub fn to_str_hex(num: f32) -> String {
 /// * num - The float value
 /// * radix - The base to use
 #[inline]
-#[unstable = "may be removed or relocated"]
+#[unstable(feature = "std_misc", reason = "may be removed or relocated")]
 pub fn to_str_radix_special(num: f32, rdx: uint) -> (String, bool) {
     strconv::float_to_str_common(num, rdx, true, SignNeg, DigAll, ExpNone, false)
 }
@@ -407,7 +407,7 @@ pub fn to_str_radix_special(num: f32, rdx: uint) -> (String, bool) {
 /// * num - The float value
 /// * digits - The number of significant digits
 #[inline]
-#[unstable = "may be removed or relocated"]
+#[unstable(feature = "std_misc", reason = "may be removed or relocated")]
 pub fn to_str_exact(num: f32, dig: uint) -> String {
     let (r, _) = strconv::float_to_str_common(
         num, 10u, true, SignNeg, DigExact(dig), ExpNone, false);
@@ -422,7 +422,7 @@ pub fn to_str_exact(num: f32, dig: uint) -> String {
 /// * num - The float value
 /// * digits - The number of significant digits
 #[inline]
-#[unstable = "may be removed or relocated"]
+#[unstable(feature = "std_misc", reason = "may be removed or relocated")]
 pub fn to_str_digits(num: f32, dig: uint) -> String {
     let (r, _) = strconv::float_to_str_common(
         num, 10u, true, SignNeg, DigMax(dig), ExpNone, false);
@@ -438,7 +438,7 @@ pub fn to_str_digits(num: f32, dig: uint) -> String {
 /// * digits - The number of digits after the decimal point
 /// * upper - Use `E` instead of `e` for the exponent sign
 #[inline]
-#[unstable = "may be removed or relocated"]
+#[unstable(feature = "std_misc", reason = "may be removed or relocated")]
 pub fn to_str_exp_exact(num: f32, dig: uint, upper: bool) -> String {
     let (r, _) = strconv::float_to_str_common(
         num, 10u, true, SignNeg, DigExact(dig), ExpDec, upper);
@@ -454,7 +454,7 @@ pub fn to_str_exp_exact(num: f32, dig: uint, upper: bool) -> String {
 /// * digits - The number of digits after the decimal point
 /// * upper - Use `E` instead of `e` for the exponent sign
 #[inline]
-#[unstable = "may be removed or relocated"]
+#[unstable(feature = "std_misc", reason = "may be removed or relocated")]
 pub fn to_str_exp_digits(num: f32, dig: uint, upper: bool) -> String {
     let (r, _) = strconv::float_to_str_common(
         num, 10u, true, SignNeg, DigMax(dig), ExpDec, upper);
diff --git a/src/libstd/num/f64.rs b/src/libstd/num/f64.rs
index baff14125ee..1c955832529 100644
--- a/src/libstd/num/f64.rs
+++ b/src/libstd/num/f64.rs
@@ -10,7 +10,7 @@
 
 //! Operations and constants for 64-bits floats (`f64` type)
 
-#![stable]
+#![stable(feature = "rust1", since = "1.0.0")]
 #![allow(missing_docs)]
 #![doc(primitive = "f64")]
 
@@ -81,7 +81,7 @@ mod cmath {
     }
 }
 
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl Float for f64 {
     // inlined methods from `num::Float`
     #[inline]
@@ -375,7 +375,7 @@ impl Float for f64 {
 ///
 /// * num - The float value
 #[inline]
-#[unstable = "may be removed or relocated"]
+#[unstable(feature = "std_misc", reason = "may be removed or relocated")]
 pub fn to_string(num: f64) -> String {
     let (r, _) = strconv::float_to_str_common(
         num, 10u, true, SignNeg, DigAll, ExpNone, false);
@@ -388,7 +388,7 @@ pub fn to_string(num: f64) -> String {
 ///
 /// * num - The float value
 #[inline]
-#[unstable = "may be removed or relocated"]
+#[unstable(feature = "std_misc", reason = "may be removed or relocated")]
 pub fn to_str_hex(num: f64) -> String {
     let (r, _) = strconv::float_to_str_common(
         num, 16u, true, SignNeg, DigAll, ExpNone, false);
@@ -403,7 +403,7 @@ pub fn to_str_hex(num: f64) -> String {
 /// * num - The float value
 /// * radix - The base to use
 #[inline]
-#[unstable = "may be removed or relocated"]
+#[unstable(feature = "std_misc", reason = "may be removed or relocated")]
 pub fn to_str_radix_special(num: f64, rdx: uint) -> (String, bool) {
     strconv::float_to_str_common(num, rdx, true, SignNeg, DigAll, ExpNone, false)
 }
@@ -416,7 +416,7 @@ pub fn to_str_radix_special(num: f64, rdx: uint) -> (String, bool) {
 /// * num - The float value
 /// * digits - The number of significant digits
 #[inline]
-#[unstable = "may be removed or relocated"]
+#[unstable(feature = "std_misc", reason = "may be removed or relocated")]
 pub fn to_str_exact(num: f64, dig: uint) -> String {
     let (r, _) = strconv::float_to_str_common(
         num, 10u, true, SignNeg, DigExact(dig), ExpNone, false);
@@ -431,7 +431,7 @@ pub fn to_str_exact(num: f64, dig: uint) -> String {
 /// * num - The float value
 /// * digits - The number of significant digits
 #[inline]
-#[unstable = "may be removed or relocated"]
+#[unstable(feature = "std_misc", reason = "may be removed or relocated")]
 pub fn to_str_digits(num: f64, dig: uint) -> String {
     let (r, _) = strconv::float_to_str_common(
         num, 10u, true, SignNeg, DigMax(dig), ExpNone, false);
@@ -447,7 +447,7 @@ pub fn to_str_digits(num: f64, dig: uint) -> String {
 /// * digits - The number of digits after the decimal point
 /// * upper - Use `E` instead of `e` for the exponent sign
 #[inline]
-#[unstable = "may be removed or relocated"]
+#[unstable(feature = "std_misc", reason = "may be removed or relocated")]
 pub fn to_str_exp_exact(num: f64, dig: uint, upper: bool) -> String {
     let (r, _) = strconv::float_to_str_common(
         num, 10u, true, SignNeg, DigExact(dig), ExpDec, upper);
@@ -463,7 +463,7 @@ pub fn to_str_exp_exact(num: f64, dig: uint, upper: bool) -> String {
 /// * digits - The number of digits after the decimal point
 /// * upper - Use `E` instead of `e` for the exponent sign
 #[inline]
-#[unstable = "may be removed or relocated"]
+#[unstable(feature = "std_misc", reason = "may be removed or relocated")]
 pub fn to_str_exp_digits(num: f64, dig: uint, upper: bool) -> String {
     let (r, _) = strconv::float_to_str_common(
         num, 10u, true, SignNeg, DigMax(dig), ExpDec, upper);
diff --git a/src/libstd/num/float_macros.rs b/src/libstd/num/float_macros.rs
index ec168eaaa9d..2b730cd6f9a 100644
--- a/src/libstd/num/float_macros.rs
+++ b/src/libstd/num/float_macros.rs
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#![unstable]
+#![unstable(feature = "std_misc")]
 #![doc(hidden)]
 
 macro_rules! assert_approx_eq {
diff --git a/src/libstd/num/i16.rs b/src/libstd/num/i16.rs
index 367147b84be..498f19b9b83 100644
--- a/src/libstd/num/i16.rs
+++ b/src/libstd/num/i16.rs
@@ -10,7 +10,7 @@
 
 //! Operations and constants for signed 16-bits integers (`i16` type)
 
-#![stable]
+#![stable(feature = "rust1", since = "1.0.0")]
 #![doc(primitive = "i16")]
 
 pub use core::i16::{BITS, BYTES, MIN, MAX};
diff --git a/src/libstd/num/i32.rs b/src/libstd/num/i32.rs
index 19fb40c9644..aea1e92117b 100644
--- a/src/libstd/num/i32.rs
+++ b/src/libstd/num/i32.rs
@@ -10,7 +10,7 @@
 
 //! Operations and constants for signed 32-bits integers (`i32` type)
 
-#![stable]
+#![stable(feature = "rust1", since = "1.0.0")]
 #![doc(primitive = "i32")]
 
 pub use core::i32::{BITS, BYTES, MIN, MAX};
diff --git a/src/libstd/num/i64.rs b/src/libstd/num/i64.rs
index 2379b03c64f..43794345fe7 100644
--- a/src/libstd/num/i64.rs
+++ b/src/libstd/num/i64.rs
@@ -10,7 +10,7 @@
 
 //! Operations and constants for signed 64-bits integers (`i64` type)
 
-#![stable]
+#![stable(feature = "rust1", since = "1.0.0")]
 #![doc(primitive = "i64")]
 
 pub use core::i64::{BITS, BYTES, MIN, MAX};
diff --git a/src/libstd/num/i8.rs b/src/libstd/num/i8.rs
index a09ceefc6a0..1b03bf6f4f0 100644
--- a/src/libstd/num/i8.rs
+++ b/src/libstd/num/i8.rs
@@ -10,7 +10,7 @@
 
 //! Operations and constants for signed 8-bits integers (`i8` type)
 
-#![stable]
+#![stable(feature = "rust1", since = "1.0.0")]
 #![doc(primitive = "i8")]
 
 pub use core::i8::{BITS, BYTES, MIN, MAX};
diff --git a/src/libstd/num/int.rs b/src/libstd/num/int.rs
index 69439f85115..669952eee39 100644
--- a/src/libstd/num/int.rs
+++ b/src/libstd/num/int.rs
@@ -14,7 +14,8 @@
 //! alpha cycle along with the development of clearer conventions
 //! around integer types.
 
-#![deprecated = "replaced by isize"]
+#![unstable(feature = "std_misc")]
+#![deprecated(since = "1.0.0", reason = "replaced by isize")]
 
 pub use core::int::{BITS, BYTES, MIN, MAX};
 
diff --git a/src/libstd/num/int_macros.rs b/src/libstd/num/int_macros.rs
index 5bc54152874..af1976d5750 100644
--- a/src/libstd/num/int_macros.rs
+++ b/src/libstd/num/int_macros.rs
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#![unstable]
+#![unstable(feature = "std_misc")]
 #![doc(hidden)]
 
 macro_rules! int_module { ($T:ty) => (
diff --git a/src/libstd/num/isize.rs b/src/libstd/num/isize.rs
index 22395a1c0ff..7fb2cd81aba 100644
--- a/src/libstd/num/isize.rs
+++ b/src/libstd/num/isize.rs
@@ -14,7 +14,7 @@
 //! new type will gradually take place over the alpha cycle along with
 //! the development of clearer conventions around integer types.
 
-#![stable]
+#![stable(feature = "rust1", since = "1.0.0")]
 #![doc(primitive = "isize")]
 
 pub use core::isize::{BITS, BYTES, MIN, MAX};
diff --git a/src/libstd/num/mod.rs b/src/libstd/num/mod.rs
index 9ced1a7e130..dad8b70ceac 100644
--- a/src/libstd/num/mod.rs
+++ b/src/libstd/num/mod.rs
@@ -13,7 +13,7 @@
 //! These are implemented for the primitive numeric types in `std::{u8, u16,
 //! u32, u64, uint, i8, i16, i32, i64, int, f32, f64}`.
 
-#![stable]
+#![stable(feature = "rust1", since = "1.0.0")]
 #![allow(missing_docs)]
 
 #[cfg(test)] use fmt::Debug;
@@ -33,11 +33,11 @@ pub use core::num::{FpCategory};
 
 use option::Option;
 
-#[unstable = "may be removed or relocated"]
+#[unstable(feature = "std_misc", reason = "may be removed or relocated")]
 pub mod strconv;
 
 /// Mathematical operations on primitive floating point numbers.
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 pub trait Float
     : Copy + Clone
     + NumCast
@@ -52,172 +52,200 @@ pub trait Float
 {
     // inlined methods from `num::Float`
     /// Returns the NaN value.
-    #[unstable = "unsure about its place in the world"]
+    #[unstable(feature = "std_misc",
+               reason = "unsure about its place in the world")]
     fn nan() -> Self;
     /// Returns the infinite value.
-    #[unstable = "unsure about its place in the world"]
+    #[unstable(feature = "std_misc",
+               reason = "unsure about its place in the world")]
     fn infinity() -> Self;
     /// Returns the negative infinite value.
-    #[unstable = "unsure about its place in the world"]
+    #[unstable(feature = "std_misc",
+               reason = "unsure about its place in the world")]
     fn neg_infinity() -> Self;
     /// Returns the `0` value.
-    #[unstable = "unsure about its place in the world"]
+    #[unstable(feature = "std_misc",
+               reason = "unsure about its place in the world")]
     fn zero() -> Self;
     /// Returns -0.0.
-    #[unstable = "unsure about its place in the world"]
+    #[unstable(feature = "std_misc",
+               reason = "unsure about its place in the world")]
     fn neg_zero() -> Self;
     /// Returns the `1` value.
-    #[unstable = "unsure about its place in the world"]
+    #[unstable(feature = "std_misc",
+               reason = "unsure about its place in the world")]
     fn one() -> Self;
 
     // FIXME (#5527): These should be associated constants
 
     /// Returns the number of binary digits of mantissa that this type supports.
-    #[deprecated = "use `std::f32::MANTISSA_DIGITS` or `std::f64::MANTISSA_DIGITS` as appropriate"]
+    #[unstable(feature = "std_misc")]
+    #[deprecated(since = "1.0.0",
+                 reason = "use `std::f32::MANTISSA_DIGITS` or \
+                           `std::f64::MANTISSA_DIGITS` as appropriate")]
     fn mantissa_digits(unused_self: Option<Self>) -> uint;
     /// Returns the number of base-10 digits of precision that this type supports.
-    #[deprecated = "use `std::f32::DIGITS` or `std::f64::DIGITS` as appropriate"]
+    #[unstable(feature = "std_misc")]
+    #[deprecated(since = "1.0.0",
+                 reason = "use `std::f32::DIGITS` or `std::f64::DIGITS` as appropriate")]
     fn digits(unused_self: Option<Self>) -> uint;
     /// Returns the difference between 1.0 and the smallest representable number larger than 1.0.
-    #[deprecated = "use `std::f32::EPSILON` or `std::f64::EPSILON` as appropriate"]
+    #[unstable(feature = "std_misc")]
+    #[deprecated(since = "1.0.0",
+                 reason = "use `std::f32::EPSILON` or `std::f64::EPSILON` as appropriate")]
     fn epsilon() -> Self;
     /// Returns the minimum binary exponent that this type can represent.
-    #[deprecated = "use `std::f32::MIN_EXP` or `std::f64::MIN_EXP` as appropriate"]
+    #[unstable(feature = "std_misc")]
+    #[deprecated(since = "1.0.0",
+                 reason = "use `std::f32::MIN_EXP` or `std::f64::MIN_EXP` as appropriate")]
     fn min_exp(unused_self: Option<Self>) -> int;
     /// Returns the maximum binary exponent that this type can represent.
-    #[deprecated = "use `std::f32::MAX_EXP` or `std::f64::MAX_EXP` as appropriate"]
+    #[unstable(feature = "std_misc")]
+    #[deprecated(since = "1.0.0",
+                 reason = "use `std::f32::MAX_EXP` or `std::f64::MAX_EXP` as appropriate")]
     fn max_exp(unused_self: Option<Self>) -> int;
     /// Returns the minimum base-10 exponent that this type can represent.
-    #[deprecated = "use `std::f32::MIN_10_EXP` or `std::f64::MIN_10_EXP` as appropriate"]
+    #[unstable(feature = "std_misc")]
+    #[deprecated(since = "1.0.0",
+                 reason = "use `std::f32::MIN_10_EXP` or `std::f64::MIN_10_EXP` as appropriate")]
     fn min_10_exp(unused_self: Option<Self>) -> int;
     /// Returns the maximum base-10 exponent that this type can represent.
-    #[deprecated = "use `std::f32::MAX_10_EXP` or `std::f64::MAX_10_EXP` as appropriate"]
+    #[unstable(feature = "std_misc")]
+    #[deprecated(since = "1.0.0",
+                 reason = "use `std::f32::MAX_10_EXP` or `std::f64::MAX_10_EXP` as appropriate")]
     fn max_10_exp(unused_self: Option<Self>) -> int;
 
     /// Returns the smallest finite value that this type can represent.
-    #[unstable = "unsure about its place in the world"]
+    #[unstable(feature = "std_misc",
+               reason = "unsure about its place in the world")]
     fn min_value() -> Self;
     /// Returns the smallest normalized positive number that this type can represent.
-    #[unstable = "unsure about its place in the world"]
+    #[unstable(feature = "std_misc",
+               reason = "unsure about its place in the world")]
     fn min_pos_value(unused_self: Option<Self>) -> Self;
     /// Returns the largest finite value that this type can represent.
-    #[unstable = "unsure about its place in the world"]
+    #[unstable(feature = "std_misc",
+               reason = "unsure about its place in the world")]
     fn max_value() -> Self;
 
     /// Returns true if this value is NaN and false otherwise.
-    #[unstable = "position is undecided"]
+    #[unstable(feature = "std_misc", reason = "position is undecided")]
     fn is_nan(self) -> bool;
     /// Returns true if this value is positive infinity or negative infinity and
     /// false otherwise.
-    #[unstable = "position is undecided"]
+    #[unstable(feature = "std_misc", reason = "position is undecided")]
     fn is_infinite(self) -> bool;
     /// Returns true if this number is neither infinite nor NaN.
-    #[unstable = "position is undecided"]
+    #[unstable(feature = "std_misc", reason = "position is undecided")]
     fn is_finite(self) -> bool;
     /// Returns true if this number is neither zero, infinite, denormal, or NaN.
-    #[unstable = "position is undecided"]
+    #[unstable(feature = "std_misc", reason = "position is undecided")]
     fn is_normal(self) -> bool;
     /// Returns the category that this number falls into.
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     fn classify(self) -> FpCategory;
 
     /// Returns the mantissa, exponent and sign as integers, respectively.
-    #[unstable = "signature is undecided"]
+    #[unstable(feature = "std_misc", reason = "signature is undecided")]
     fn integer_decode(self) -> (u64, i16, i8);
 
     /// Return the largest integer less than or equal to a number.
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     fn floor(self) -> Self;
     /// Return the smallest integer greater than or equal to a number.
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     fn ceil(self) -> Self;
     /// Return the nearest integer to a number. Round half-way cases away from
     /// `0.0`.
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     fn round(self) -> Self;
     /// Return the integer part of a number.
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     fn trunc(self) -> Self;
     /// Return the fractional part of a number.
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     fn fract(self) -> Self;
 
     /// Computes the absolute value of `self`. Returns `Float::nan()` if the
     /// number is `Float::nan()`.
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     fn abs(self) -> Self;
     /// Returns a number that represents the sign of `self`.
     ///
     /// - `1.0` if the number is positive, `+0.0` or `Float::infinity()`
     /// - `-1.0` if the number is negative, `-0.0` or `Float::neg_infinity()`
     /// - `Float::nan()` if the number is `Float::nan()`
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     fn signum(self) -> Self;
     /// Returns `true` if `self` is positive, including `+0.0` and
     /// `Float::infinity()`.
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     fn is_positive(self) -> bool;
     /// Returns `true` if `self` is negative, including `-0.0` and
     /// `Float::neg_infinity()`.
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     fn is_negative(self) -> bool;
 
     /// Fused multiply-add. Computes `(self * a) + b` with only one rounding
     /// error. This produces a more accurate result with better performance than
     /// a separate multiplication operation followed by an add.
-    #[unstable = "unsure about its place in the world"]
+    #[unstable(feature = "std_misc",
+               reason = "unsure about its place in the world")]
     fn mul_add(self, a: Self, b: Self) -> Self;
     /// Take the reciprocal (inverse) of a number, `1/x`.
-    #[unstable = "unsure about its place in the world"]
+    #[unstable(feature = "std_misc",
+               reason = "unsure about its place in the world")]
     fn recip(self) -> Self;
 
     /// Raise a number to an integer power.
     ///
     /// Using this function is generally faster than using `powf`
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     fn powi(self, n: i32) -> Self;
     /// Raise a number to a floating point power.
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     fn powf(self, n: Self) -> Self;
 
     /// Take the square root of a number.
     ///
     /// Returns NaN if `self` is a negative number.
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     fn sqrt(self) -> Self;
     /// Take the reciprocal (inverse) square root of a number, `1/sqrt(x)`.
-    #[unstable = "unsure about its place in the world"]
+    #[unstable(feature = "std_misc",
+               reason = "unsure about its place in the world")]
     fn rsqrt(self) -> Self;
 
     /// Returns `e^(self)`, (the exponential function).
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     fn exp(self) -> Self;
     /// Returns 2 raised to the power of the number, `2^(self)`.
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     fn exp2(self) -> Self;
     /// Returns the natural logarithm of the number.
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     fn ln(self) -> Self;
     /// Returns the logarithm of the number with respect to an arbitrary base.
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     fn log(self, base: Self) -> Self;
     /// Returns the base 2 logarithm of the number.
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     fn log2(self) -> Self;
     /// Returns the base 10 logarithm of the number.
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     fn log10(self) -> Self;
 
     /// Convert radians to degrees.
-    #[unstable = "desirability is unclear"]
+    #[unstable(feature = "std_misc", reason = "desirability is unclear")]
     fn to_degrees(self) -> Self;
     /// Convert degrees to radians.
-    #[unstable = "desirability is unclear"]
+    #[unstable(feature = "std_misc", reason = "desirability is unclear")]
     fn to_radians(self) -> Self;
 
     /// Constructs a floating point number created by multiplying `x` by 2
     /// raised to the power of `exp`.
-    #[unstable = "pending integer conventions"]
+    #[unstable(feature = "std_misc",
+               reason = "pending integer conventions")]
     fn ldexp(x: Self, exp: int) -> Self;
     /// Breaks the number into a normalized fraction and a base-2 exponent,
     /// satisfying:
@@ -225,94 +253,97 @@ pub trait Float
     ///  * `self = x * pow(2, exp)`
     ///
     ///  * `0.5 <= abs(x) < 1.0`
-    #[unstable = "pending integer conventions"]
+    #[unstable(feature = "std_misc",
+               reason = "pending integer conventions")]
     fn frexp(self) -> (Self, int);
 
     /// Returns the next representable floating-point value in the direction of
     /// `other`.
-    #[unstable = "unsure about its place in the world"]
+    #[unstable(feature = "std_misc",
+               reason = "unsure about its place in the world")]
     fn next_after(self, other: Self) -> Self;
 
     /// Returns the maximum of the two numbers.
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     fn max(self, other: Self) -> Self;
     /// Returns the minimum of the two numbers.
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     fn min(self, other: Self) -> Self;
 
     /// The positive difference of two numbers. Returns `0.0` if the number is
     /// less than or equal to `other`, otherwise the difference between`self`
     /// and `other` is returned.
-    #[unstable = "may be renamed"]
+    #[unstable(feature = "std_misc", reason = "may be renamed")]
     fn abs_sub(self, other: Self) -> Self;
 
     /// Take the cubic root of a number.
-    #[unstable = "may be renamed"]
+    #[unstable(feature = "std_misc", reason = "may be renamed")]
     fn cbrt(self) -> Self;
     /// Calculate the length of the hypotenuse of a right-angle triangle given
     /// legs of length `x` and `y`.
-    #[unstable = "unsure about its place in the world"]
+    #[unstable(feature = "std_misc",
+               reason = "unsure about its place in the world")]
     fn hypot(self, other: Self) -> Self;
 
     /// Computes the sine of a number (in radians).
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     fn sin(self) -> Self;
     /// Computes the cosine of a number (in radians).
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     fn cos(self) -> Self;
     /// Computes the tangent of a number (in radians).
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     fn tan(self) -> Self;
 
     /// Computes the arcsine of a number. Return value is in radians in
     /// the range [-pi/2, pi/2] or NaN if the number is outside the range
     /// [-1, 1].
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     fn asin(self) -> Self;
     /// Computes the arccosine of a number. Return value is in radians in
     /// the range [0, pi] or NaN if the number is outside the range
     /// [-1, 1].
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     fn acos(self) -> Self;
     /// Computes the arctangent of a number. Return value is in radians in the
     /// range [-pi/2, pi/2];
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     fn atan(self) -> Self;
     /// Computes the four quadrant arctangent of a number, `y`, and another
     /// number `x`. Return value is in radians in the range [-pi, pi].
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     fn atan2(self, other: Self) -> Self;
     /// Simultaneously computes the sine and cosine of the number, `x`. Returns
     /// `(sin(x), cos(x))`.
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     fn sin_cos(self) -> (Self, Self);
 
     /// Returns the exponential of the number, minus 1, in a way that is
     /// accurate even if the number is close to zero.
-    #[unstable = "may be renamed"]
+    #[unstable(feature = "std_misc", reason = "may be renamed")]
     fn exp_m1(self) -> Self;
     /// Returns the natural logarithm of the number plus 1 (`ln(1+n)`) more
     /// accurately than if the operations were performed separately.
-    #[unstable = "may be renamed"]
+    #[unstable(feature = "std_misc", reason = "may be renamed")]
     fn ln_1p(self) -> Self;
 
     /// Hyperbolic sine function.
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     fn sinh(self) -> Self;
     /// Hyperbolic cosine function.
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     fn cosh(self) -> Self;
     /// Hyperbolic tangent function.
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     fn tanh(self) -> Self;
     /// Inverse hyperbolic sine function.
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     fn asinh(self) -> Self;
     /// Inverse hyperbolic cosine function.
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     fn acosh(self) -> Self;
     /// Inverse hyperbolic tangent function.
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     fn atanh(self) -> Self;
 }
 
diff --git a/src/libstd/num/u16.rs b/src/libstd/num/u16.rs
index 7cb6a8ffe07..3fda77fb69c 100644
--- a/src/libstd/num/u16.rs
+++ b/src/libstd/num/u16.rs
@@ -10,7 +10,7 @@
 
 //! Operations and constants for unsigned 16-bits integers (`u16` type)
 
-#![stable]
+#![stable(feature = "rust1", since = "1.0.0")]
 #![doc(primitive = "u16")]
 
 pub use core::u16::{BITS, BYTES, MIN, MAX};
diff --git a/src/libstd/num/u32.rs b/src/libstd/num/u32.rs
index 43b01ddb16b..8610f0c0147 100644
--- a/src/libstd/num/u32.rs
+++ b/src/libstd/num/u32.rs
@@ -10,7 +10,7 @@
 
 //! Operations and constants for unsigned 32-bits integers (`u32` type)
 
-#![stable]
+#![stable(feature = "rust1", since = "1.0.0")]
 #![doc(primitive = "u32")]
 
 pub use core::u32::{BITS, BYTES, MIN, MAX};
diff --git a/src/libstd/num/u64.rs b/src/libstd/num/u64.rs
index 79e7f237051..3587b069656 100644
--- a/src/libstd/num/u64.rs
+++ b/src/libstd/num/u64.rs
@@ -10,7 +10,7 @@
 
 //! Operations and constants for unsigned 64-bits integer (`u64` type)
 
-#![stable]
+#![stable(feature = "rust1", since = "1.0.0")]
 #![doc(primitive = "u64")]
 
 pub use core::u64::{BITS, BYTES, MIN, MAX};
diff --git a/src/libstd/num/u8.rs b/src/libstd/num/u8.rs
index 3da2fabe3f2..6a285e8299c 100644
--- a/src/libstd/num/u8.rs
+++ b/src/libstd/num/u8.rs
@@ -10,7 +10,7 @@
 
 //! Operations and constants for unsigned 8-bits integers (`u8` type)
 
-#![stable]
+#![stable(feature = "rust1", since = "1.0.0")]
 #![doc(primitive = "u8")]
 
 pub use core::u8::{BITS, BYTES, MIN, MAX};
diff --git a/src/libstd/num/uint.rs b/src/libstd/num/uint.rs
index 0e12eff205f..c7b491381f3 100644
--- a/src/libstd/num/uint.rs
+++ b/src/libstd/num/uint.rs
@@ -14,7 +14,8 @@
 //! alpha cycle along with the development of clearer conventions
 //! around integer types.
 
-#![deprecated = "replaced by usize"]
+#![unstable(feature = "std_misc")]
+#![deprecated(since = "1.0.0", reason = "replaced by usize")]
 
 pub use core::uint::{BITS, BYTES, MIN, MAX};
 
diff --git a/src/libstd/num/uint_macros.rs b/src/libstd/num/uint_macros.rs
index f480a3b420f..82c55d7b5b8 100644
--- a/src/libstd/num/uint_macros.rs
+++ b/src/libstd/num/uint_macros.rs
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#![unstable]
+#![unstable(feature = "std_misc")]
 #![doc(hidden)]
 #![allow(unsigned_negation)]
 
diff --git a/src/libstd/num/usize.rs b/src/libstd/num/usize.rs
index 74dd38e13c5..19964c306a7 100644
--- a/src/libstd/num/usize.rs
+++ b/src/libstd/num/usize.rs
@@ -14,7 +14,7 @@
 //! new type will gradually take place over the alpha cycle along with
 //! the development of clearer conventions around integer types.
 
-#![stable]
+#![stable(feature = "rust1", since = "1.0.0")]
 #![doc(primitive = "usize")]
 
 pub use core::usize::{BITS, BYTES, MIN, MAX};
diff --git a/src/libstd/old_io/buffered.rs b/src/libstd/old_io/buffered.rs
index 768cec129a9..1590598c0b8 100644
--- a/src/libstd/old_io/buffered.rs
+++ b/src/libstd/old_io/buffered.rs
@@ -52,7 +52,7 @@ pub struct BufferedReader<R> {
     cap: uint,
 }
 
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl<R> fmt::Debug for BufferedReader<R> where R: fmt::Debug {
     fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
         write!(fmt, "BufferedReader {{ reader: {:?}, buffer: {}/{} }}",
@@ -151,7 +151,7 @@ pub struct BufferedWriter<W> {
     pos: uint
 }
 
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl<W> fmt::Debug for BufferedWriter<W> where W: fmt::Debug {
     fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
         write!(fmt, "BufferedWriter {{ writer: {:?}, buffer: {}/{} }}",
@@ -251,7 +251,7 @@ pub struct LineBufferedWriter<W> {
     inner: BufferedWriter<W>,
 }
 
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl<W> fmt::Debug for LineBufferedWriter<W> where W: fmt::Debug {
     fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
         write!(fmt, "LineBufferedWriter {{ writer: {:?}, buffer: {}/{} }}",
@@ -342,7 +342,7 @@ pub struct BufferedStream<S> {
     inner: BufferedReader<InternalBufferedWriter<S>>
 }
 
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl<S> fmt::Debug for BufferedStream<S> where S: fmt::Debug {
     fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
         let reader = &self.inner;
diff --git a/src/libstd/old_io/comm_adapters.rs b/src/libstd/old_io/comm_adapters.rs
index a1f2efdb28a..feb2ef6f4f3 100644
--- a/src/libstd/old_io/comm_adapters.rs
+++ b/src/libstd/old_io/comm_adapters.rs
@@ -134,7 +134,7 @@ impl ChanWriter {
     }
 }
 
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl Clone for ChanWriter {
     fn clone(&self) -> ChanWriter {
         ChanWriter { tx: self.tx.clone() }
diff --git a/src/libstd/old_io/mem.rs b/src/libstd/old_io/mem.rs
index be965d9cf2d..254daf3202a 100644
--- a/src/libstd/old_io/mem.rs
+++ b/src/libstd/old_io/mem.rs
@@ -62,7 +62,9 @@ impl Writer for Vec<u8> {
 ///
 /// assert_eq!(w.into_inner(), vec!(0, 1, 2));
 /// ```
-#[deprecated = "use the Vec<u8> Writer implementation directly"]
+#[unstable(feature = "io")]
+#[deprecated(since = "1.0.0",
+             reason = "use the Vec<u8> Writer implementation directly")]
 #[derive(Clone)]
 pub struct MemWriter {
     buf: Vec<u8>,
diff --git a/src/libstd/old_io/mod.rs b/src/libstd/old_io/mod.rs
index 3d1c8a0b86c..6c5ce129a33 100644
--- a/src/libstd/old_io/mod.rs
+++ b/src/libstd/old_io/mod.rs
@@ -237,7 +237,7 @@
 //! concerned with error handling; instead its caller is responsible for
 //! responding to errors that may occur while attempting to read the numbers.
 
-#![unstable]
+#![unstable(feature = "io")]
 #![deny(unused_must_use)]
 
 pub use self::SeekStyle::*;
@@ -357,7 +357,7 @@ impl IoError {
     }
 }
 
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl fmt::Display for IoError {
     fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
         match *self {
@@ -1000,7 +1000,8 @@ pub trait Writer {
     fn write_all(&mut self, buf: &[u8]) -> IoResult<()>;
 
     /// Deprecated, this method was renamed to `write_all`
-    #[deprecated = "renamed to `write_all`"]
+    #[unstable(feature = "io")]
+    #[deprecated(since = "1.0.0", reason = "renamed to `write_all`")]
     fn write(&mut self, buf: &[u8]) -> IoResult<()> { self.write_all(buf) }
 
     /// Flush this output stream, ensuring that all intermediately buffered
@@ -1711,7 +1712,6 @@ pub enum FileType {
 /// # Examples
 ///
 /// ```no_run
-/// # #![allow(unstable)]
 ///
 /// use std::old_io::fs::PathExtensions;
 ///
@@ -1752,7 +1752,7 @@ pub struct FileStat {
     ///
     /// Usage of this field is discouraged, but if access is desired then the
     /// fields are located here.
-    #[unstable]
+    #[unstable(feature = "io")]
     pub unstable: UnstableFileStat,
 }
 
@@ -1760,7 +1760,7 @@ pub struct FileStat {
 /// returned from a `stat` syscall which is not contained in the `FileStat`
 /// structure. This information is not necessarily platform independent, and may
 /// have different meanings or no meaning at all on some platforms.
-#[unstable]
+#[unstable(feature = "io")]
 #[derive(Copy, Hash)]
 pub struct UnstableFileStat {
     /// The ID of the device containing the file.
@@ -1824,14 +1824,14 @@ bitflags! {
 }
 
 
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl Default for FilePermission {
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     #[inline]
     fn default() -> FilePermission { FilePermission::empty() }
 }
 
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl fmt::Display for FilePermission {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         write!(f, "{:04o}", self.bits)
diff --git a/src/libstd/old_io/net/ip.rs b/src/libstd/old_io/net/ip.rs
index 26eb068b151..e60b455aecd 100644
--- a/src/libstd/old_io/net/ip.rs
+++ b/src/libstd/old_io/net/ip.rs
@@ -38,7 +38,7 @@ pub enum IpAddr {
     Ipv6Addr(u16, u16, u16, u16, u16, u16, u16, u16)
 }
 
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl fmt::Display for IpAddr {
     fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
         match *self {
@@ -70,7 +70,7 @@ pub struct SocketAddr {
     pub port: Port,
 }
 
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl fmt::Display for SocketAddr {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         match self.ip {
diff --git a/src/libstd/old_io/net/pipe.rs b/src/libstd/old_io/net/pipe.rs
index 760e778fd7c..71b77adcd96 100644
--- a/src/libstd/old_io/net/pipe.rs
+++ b/src/libstd/old_io/net/pipe.rs
@@ -68,7 +68,8 @@ impl UnixStream {
     ///
     /// If a `timeout` with zero or negative duration is specified then
     /// the function returns `Err`, with the error kind set to `TimedOut`.
-    #[unstable = "the timeout argument is likely to change types"]
+    #[unstable(feature = "io",
+               reason = "the timeout argument is likely to change types")]
     pub fn connect_timeout<P>(path: P, timeout: Duration)
                               -> IoResult<UnixStream>
                               where P: BytesContainer {
@@ -107,7 +108,8 @@ impl UnixStream {
     /// Sets the read/write timeout for this socket.
     ///
     /// For more information, see `TcpStream::set_timeout`
-    #[unstable = "the timeout argument may change in type and value"]
+    #[unstable(feature = "io",
+               reason = "the timeout argument may change in type and value")]
     pub fn set_timeout(&mut self, timeout_ms: Option<u64>) {
         self.inner.set_timeout(timeout_ms)
     }
@@ -115,7 +117,8 @@ impl UnixStream {
     /// Sets the read timeout for this socket.
     ///
     /// For more information, see `TcpStream::set_timeout`
-    #[unstable = "the timeout argument may change in type and value"]
+    #[unstable(feature = "io",
+               reason = "the timeout argument may change in type and value")]
     pub fn set_read_timeout(&mut self, timeout_ms: Option<u64>) {
         self.inner.set_read_timeout(timeout_ms)
     }
@@ -123,7 +126,8 @@ impl UnixStream {
     /// Sets the write timeout for this socket.
     ///
     /// For more information, see `TcpStream::set_timeout`
-    #[unstable = "the timeout argument may change in type and value"]
+    #[unstable(feature = "io",
+               reason = "the timeout argument may change in type and value")]
     pub fn set_write_timeout(&mut self, timeout_ms: Option<u64>) {
         self.inner.set_write_timeout(timeout_ms)
     }
@@ -217,8 +221,9 @@ impl UnixAcceptor {
     /// When using this method, it is likely necessary to reset the timeout as
     /// appropriate, the timeout specified is specific to this object, not
     /// specific to the next request.
-    #[unstable = "the name and arguments to this function are likely \
-                      to change"]
+    #[unstable(feature = "io",
+               reason = "the name and arguments to this function are likely \
+                         to change")]
     pub fn set_timeout(&mut self, timeout_ms: Option<u64>) {
         self.inner.set_timeout(timeout_ms)
     }
@@ -227,7 +232,7 @@ impl UnixAcceptor {
     ///
     /// This function has the same semantics as `TcpAcceptor::close_accept`, and
     /// more information can be found in that documentation.
-    #[unstable]
+    #[unstable(feature = "io")]
     pub fn close_accept(&mut self) -> IoResult<()> {
         self.inner.close_accept()
     }
diff --git a/src/libstd/old_io/net/tcp.rs b/src/libstd/old_io/net/tcp.rs
index f01f6e1a87c..1e76bb3ab0d 100644
--- a/src/libstd/old_io/net/tcp.rs
+++ b/src/libstd/old_io/net/tcp.rs
@@ -85,7 +85,8 @@ impl TcpStream {
     ///
     /// If a `timeout` with zero or negative duration is specified then
     /// the function returns `Err`, with the error kind set to `TimedOut`.
-    #[unstable = "the timeout argument may eventually change types"]
+    #[unstable(feature = "io",
+               reason = "the timeout argument may eventually change types")]
     pub fn connect_timeout<A: ToSocketAddr>(addr: A,
                                             timeout: Duration) -> IoResult<TcpStream> {
         if timeout <= Duration::milliseconds(0) {
@@ -109,7 +110,7 @@ impl TcpStream {
     }
 
     /// Sets the nodelay flag on this connection to the boolean specified
-    #[unstable]
+    #[unstable(feature = "io")]
     pub fn set_nodelay(&mut self, nodelay: bool) -> IoResult<()> {
         self.inner.set_nodelay(nodelay)
     }
@@ -119,7 +120,7 @@ impl TcpStream {
     /// If the value specified is `None`, then the keepalive flag is cleared on
     /// this connection. Otherwise, the keepalive timeout will be set to the
     /// specified time, in seconds.
-    #[unstable]
+    #[unstable(feature = "io")]
     pub fn set_keepalive(&mut self, delay_in_seconds: Option<uint>) -> IoResult<()> {
         self.inner.set_keepalive(delay_in_seconds)
     }
@@ -187,7 +188,8 @@ impl TcpStream {
     ///
     /// For clarification on the semantics of interrupting a read and a write,
     /// take a look at `set_read_timeout` and `set_write_timeout`.
-    #[unstable = "the timeout argument may change in type and value"]
+    #[unstable(feature = "io",
+               reason = "the timeout argument may change in type and value")]
     pub fn set_timeout(&mut self, timeout_ms: Option<u64>) {
         self.inner.set_timeout(timeout_ms)
     }
@@ -204,7 +206,8 @@ impl TcpStream {
     /// action is taken. Otherwise, the read operation will be scheduled to
     /// promptly return. If a timeout error is returned, then no data was read
     /// during the timeout period.
-    #[unstable = "the timeout argument may change in type and value"]
+    #[unstable(feature = "io",
+               reason = "the timeout argument may change in type and value")]
     pub fn set_read_timeout(&mut self, timeout_ms: Option<u64>) {
         self.inner.set_read_timeout(timeout_ms)
     }
@@ -231,7 +234,8 @@ impl TcpStream {
     /// does not know how many bytes were written as part of the timeout
     /// operation. It may be the case that bytes continue to be written in an
     /// asynchronous fashion after the call to write returns.
-    #[unstable = "the timeout argument may change in type and value"]
+    #[unstable(feature = "io",
+               reason = "the timeout argument may change in type and value")]
     pub fn set_write_timeout(&mut self, timeout_ms: Option<u64>) {
         self.inner.set_write_timeout(timeout_ms)
     }
@@ -372,7 +376,6 @@ impl TcpAcceptor {
     /// # Example
     ///
     /// ```no_run
-    /// # #![allow(unstable)]
     /// use std::old_io::TcpListener;
     /// use std::old_io::{Listener, Acceptor, TimedOut};
     ///
@@ -395,8 +398,9 @@ impl TcpAcceptor {
     /// a.set_timeout(None);
     /// let socket = a.accept();
     /// ```
-    #[unstable = "the type of the argument and name of this function are \
-                      subject to change"]
+    #[unstable(feature = "io",
+               reason = "the type of the argument and name of this function are \
+                         subject to change")]
     pub fn set_timeout(&mut self, ms: Option<u64>) { self.inner.set_timeout(ms); }
 
     /// Closes the accepting capabilities of this acceptor.
@@ -416,7 +420,6 @@ impl TcpAcceptor {
     /// # Example
     ///
     /// ```
-    /// # #![allow(unstable)]
     /// use std::old_io::{TcpListener, Listener, Acceptor, EndOfFile};
     /// use std::thread::Thread;
     ///
@@ -442,7 +445,7 @@ impl TcpAcceptor {
     /// // Signal our accept loop to exit
     /// assert!(a.close_accept().is_ok());
     /// ```
-    #[unstable]
+    #[unstable(feature = "io")]
     pub fn close_accept(&mut self) -> IoResult<()> {
         self.inner.close_accept()
     }
@@ -480,7 +483,6 @@ impl sys_common::AsInner<TcpAcceptorImp> for TcpAcceptor {
 }
 
 #[cfg(test)]
-#[allow(unstable)]
 mod test {
     use prelude::v1::*;
 
diff --git a/src/libstd/old_io/net/udp.rs b/src/libstd/old_io/net/udp.rs
index d7fc760951e..9055a089eec 100644
--- a/src/libstd/old_io/net/udp.rs
+++ b/src/libstd/old_io/net/udp.rs
@@ -92,13 +92,13 @@ impl UdpSocket {
     }
 
     /// Joins a multicast IP address (becomes a member of it)
-    #[unstable]
+    #[unstable(feature = "io")]
     pub fn join_multicast(&mut self, multi: IpAddr) -> IoResult<()> {
         self.inner.join_multicast(multi)
     }
 
     /// Leaves a multicast IP address (drops membership from it)
-    #[unstable]
+    #[unstable(feature = "io")]
     pub fn leave_multicast(&mut self, multi: IpAddr) -> IoResult<()> {
         self.inner.leave_multicast(multi)
     }
@@ -106,25 +106,25 @@ impl UdpSocket {
     /// Set the multicast loop flag to the specified value
     ///
     /// This lets multicast packets loop back to local sockets (if enabled)
-    #[unstable]
+    #[unstable(feature = "io")]
     pub fn set_multicast_loop(&mut self, on: bool) -> IoResult<()> {
         self.inner.set_multicast_loop(on)
     }
 
     /// Sets the multicast TTL
-    #[unstable]
+    #[unstable(feature = "io")]
     pub fn set_multicast_ttl(&mut self, ttl: int) -> IoResult<()> {
         self.inner.multicast_time_to_live(ttl)
     }
 
     /// Sets this socket's TTL
-    #[unstable]
+    #[unstable(feature = "io")]
     pub fn set_ttl(&mut self, ttl: int) -> IoResult<()> {
         self.inner.time_to_live(ttl)
     }
 
     /// Sets the broadcast flag on or off
-    #[unstable]
+    #[unstable(feature = "io")]
     pub fn set_broadcast(&mut self, broadcast: bool) -> IoResult<()> {
         self.inner.set_broadcast(broadcast)
     }
@@ -132,7 +132,8 @@ impl UdpSocket {
     /// Sets the read/write timeout for this socket.
     ///
     /// For more information, see `TcpStream::set_timeout`
-    #[unstable = "the timeout argument may change in type and value"]
+    #[unstable(feature = "io",
+               reason = "the timeout argument may change in type and value")]
     pub fn set_timeout(&mut self, timeout_ms: Option<u64>) {
         self.inner.set_timeout(timeout_ms)
     }
@@ -140,7 +141,8 @@ impl UdpSocket {
     /// Sets the read timeout for this socket.
     ///
     /// For more information, see `TcpStream::set_timeout`
-    #[unstable = "the timeout argument may change in type and value"]
+    #[unstable(feature = "io",
+               reason = "the timeout argument may change in type and value")]
     pub fn set_read_timeout(&mut self, timeout_ms: Option<u64>) {
         self.inner.set_read_timeout(timeout_ms)
     }
@@ -148,7 +150,8 @@ impl UdpSocket {
     /// Sets the write timeout for this socket.
     ///
     /// For more information, see `TcpStream::set_timeout`
-    #[unstable = "the timeout argument may change in type and value"]
+    #[unstable(feature = "io",
+               reason = "the timeout argument may change in type and value")]
     pub fn set_write_timeout(&mut self, timeout_ms: Option<u64>) {
         self.inner.set_write_timeout(timeout_ms)
     }
@@ -176,7 +179,6 @@ impl sys_common::AsInner<UdpSocketImp> for UdpSocket {
 }
 
 #[cfg(test)]
-#[allow(unstable)]
 mod test {
     use prelude::v1::*;
 
diff --git a/src/libstd/old_io/process.rs b/src/libstd/old_io/process.rs
index 280d2a8add5..78910882467 100644
--- a/src/libstd/old_io/process.rs
+++ b/src/libstd/old_io/process.rs
@@ -10,7 +10,6 @@
 
 //! Bindings for executing child processes
 
-#![allow(unstable)]
 #![allow(non_upper_case_globals)]
 
 pub use self::StdioContainer::*;
@@ -502,7 +501,7 @@ pub enum ProcessExit {
     ExitSignal(int),
 }
 
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl fmt::Display for ProcessExit {
     /// Format a ProcessExit enum, to nicely present the information.
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
@@ -653,7 +652,6 @@ impl Process {
     /// # Example
     ///
     /// ```no_run
-    /// # #![allow(unstable)]
     /// use std::old_io::{Command, IoResult};
     /// use std::old_io::process::ProcessExit;
     ///
@@ -681,7 +679,8 @@ impl Process {
     ///     p.wait()
     /// }
     /// ```
-    #[unstable = "the type of the timeout is likely to change"]
+    #[unstable(feature = "io",
+               reason = "the type of the timeout is likely to change")]
     pub fn set_timeout(&mut self, timeout_ms: Option<u64>) {
         self.deadline = timeout_ms.map(|i| i + sys::timer::now()).unwrap_or(0);
     }
diff --git a/src/libstd/os.rs b/src/libstd/os.rs
index 6dde65854d7..979a61d20d5 100644
--- a/src/libstd/os.rs
+++ b/src/libstd/os.rs
@@ -24,7 +24,7 @@
 //! which OS the user is on -- they should be given the opportunity to write
 //! OS-ignorant code by default.
 
-#![unstable]
+#![unstable(feature = "os")]
 
 #![allow(missing_docs)]
 #![allow(non_snake_case)]
@@ -902,7 +902,7 @@ pub enum MapError {
     ErrMapViewOfFile(uint)
 }
 
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl fmt::Display for MapError {
     fn fmt(&self, out: &mut fmt::Formatter) -> fmt::Result {
         let str = match *self {
diff --git a/src/libstd/path/mod.rs b/src/libstd/path/mod.rs
index 1b09fb92737..b42353e964c 100644
--- a/src/libstd/path/mod.rs
+++ b/src/libstd/path/mod.rs
@@ -59,7 +59,7 @@
 //! println!("path exists: {}", path.exists());
 //! ```
 
-#![unstable]
+#![unstable(feature = "path")]
 
 use core::marker::Sized;
 use ffi::CString;
@@ -823,14 +823,14 @@ pub struct Display<'a, P:'a> {
     filename: bool
 }
 
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl<'a, P: GenericPath> fmt::Debug for Display<'a, P> {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         fmt::Debug::fmt(&self.as_cow(), f)
     }
 }
 
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl<'a, P: GenericPath> fmt::Display for Display<'a, P> {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         self.as_cow().fmt(f)
diff --git a/src/libstd/path/posix.rs b/src/libstd/path/posix.rs
index 202d81f5696..39138e14803 100644
--- a/src/libstd/path/posix.rs
+++ b/src/libstd/path/posix.rs
@@ -57,7 +57,7 @@ pub fn is_sep(c: char) -> bool {
     c == SEP
 }
 
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl fmt::Debug for Path {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         fmt::Debug::fmt(&self.display(), f)
diff --git a/src/libstd/path/windows.rs b/src/libstd/path/windows.rs
index 9f5ed177918..34faa65af75 100644
--- a/src/libstd/path/windows.rs
+++ b/src/libstd/path/windows.rs
@@ -85,7 +85,7 @@ pub struct Path {
     sepidx: Option<uint> // index of the final separator in the non-prefix portion of repr
 }
 
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl fmt::Debug for Path {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         fmt::Debug::fmt(&self.display(), f)
diff --git a/src/libstd/prelude/mod.rs b/src/libstd/prelude/mod.rs
index 0496944dbaf..09fa10dacf9 100644
--- a/src/libstd/prelude/mod.rs
+++ b/src/libstd/prelude/mod.rs
@@ -35,7 +35,6 @@
 //! pervasive that it would be obnoxious to import for every use, particularly
 //! those that define methods on primitive types.
 
-#![stable]
+#![stable(feature = "rust1", since = "1.0.0")]
 
-#[stable]
 pub mod v1;
diff --git a/src/libstd/prelude/v1.rs b/src/libstd/prelude/v1.rs
index aa4db7b6b70..51c9f9de83c 100644
--- a/src/libstd/prelude/v1.rs
+++ b/src/libstd/prelude/v1.rs
@@ -10,35 +10,54 @@
 
 //! The first version of the prelude of the standard library.
 
-#![stable]
+#![stable(feature = "rust1", since = "1.0.0")]
 
 // Reexported core operators
-#[stable] #[doc(no_inline)] pub use marker::{Copy, Send, Sized, Sync};
-#[stable] #[doc(no_inline)] pub use ops::{Drop, Fn, FnMut, FnOnce};
+#[stable(feature = "rust1", since = "1.0.0")]
+#[doc(no_inline)] pub use marker::{Copy, Send, Sized, Sync};
+#[stable(feature = "rust1", since = "1.0.0")]
+#[doc(no_inline)] pub use ops::{Drop, Fn, FnMut, FnOnce};
 
 // TEMPORARY
-#[unstable] #[doc(no_inline)] pub use ops::FullRange;
+#[unstable(feature = "std_misc")]
+#[doc(no_inline)] pub use ops::FullRange;
 
 // Reexported functions
-#[stable] #[doc(no_inline)] pub use mem::drop;
+#[stable(feature = "rust1", since = "1.0.0")]
+#[doc(no_inline)] pub use mem::drop;
 
 // Reexported types and traits
 
-#[stable] #[doc(no_inline)] pub use boxed::Box;
-#[stable] #[doc(no_inline)] pub use char::CharExt;
-#[stable] #[doc(no_inline)] pub use clone::Clone;
-#[stable] #[doc(no_inline)] pub use cmp::{PartialEq, PartialOrd, Eq, Ord};
-#[stable] #[doc(no_inline)] pub use iter::DoubleEndedIterator;
-#[stable] #[doc(no_inline)] pub use iter::ExactSizeIterator;
-#[stable] #[doc(no_inline)] pub use iter::{Iterator, IteratorExt, Extend};
-#[stable] #[doc(no_inline)] pub use option::Option::{self, Some, None};
-#[stable] #[doc(no_inline)] pub use ptr::{PtrExt, MutPtrExt};
-#[stable] #[doc(no_inline)] pub use result::Result::{self, Ok, Err};
-#[stable] #[doc(no_inline)] pub use slice::AsSlice;
-#[stable] #[doc(no_inline)] pub use slice::{SliceExt, SliceConcatExt};
-#[stable] #[doc(no_inline)] pub use str::{Str, StrExt};
-#[stable] #[doc(no_inline)] pub use string::{String, ToString};
-#[stable] #[doc(no_inline)] pub use vec::Vec;
+#[stable(feature = "rust1", since = "1.0.0")]
+#[doc(no_inline)] pub use boxed::Box;
+#[stable(feature = "rust1", since = "1.0.0")]
+#[doc(no_inline)] pub use char::CharExt;
+#[stable(feature = "rust1", since = "1.0.0")]
+#[doc(no_inline)] pub use clone::Clone;
+#[stable(feature = "rust1", since = "1.0.0")]
+#[doc(no_inline)] pub use cmp::{PartialEq, PartialOrd, Eq, Ord};
+#[stable(feature = "rust1", since = "1.0.0")]
+#[doc(no_inline)] pub use iter::DoubleEndedIterator;
+#[stable(feature = "rust1", since = "1.0.0")]
+#[doc(no_inline)] pub use iter::ExactSizeIterator;
+#[stable(feature = "rust1", since = "1.0.0")]
+#[doc(no_inline)] pub use iter::{Iterator, IteratorExt, Extend};
+#[stable(feature = "rust1", since = "1.0.0")]
+#[doc(no_inline)] pub use option::Option::{self, Some, None};
+#[stable(feature = "rust1", since = "1.0.0")]
+#[doc(no_inline)] pub use ptr::{PtrExt, MutPtrExt};
+#[stable(feature = "rust1", since = "1.0.0")]
+#[doc(no_inline)] pub use result::Result::{self, Ok, Err};
+#[stable(feature = "rust1", since = "1.0.0")]
+#[doc(no_inline)] pub use slice::AsSlice;
+#[stable(feature = "rust1", since = "1.0.0")]
+#[doc(no_inline)] pub use slice::{SliceExt, SliceConcatExt};
+#[stable(feature = "rust1", since = "1.0.0")]
+#[doc(no_inline)] pub use str::{Str, StrExt};
+#[stable(feature = "rust1", since = "1.0.0")]
+#[doc(no_inline)] pub use string::{String, ToString};
+#[stable(feature = "rust1", since = "1.0.0")]
+#[doc(no_inline)] pub use vec::Vec;
 
 // NB: remove when path reform lands
 #[doc(no_inline)] pub use path::{Path, GenericPath};
diff --git a/src/libstd/rand/mod.rs b/src/libstd/rand/mod.rs
index 01111462eaa..0a6dc386edf 100644
--- a/src/libstd/rand/mod.rs
+++ b/src/libstd/rand/mod.rs
@@ -219,7 +219,7 @@
 //! }
 //! ```
 
-#![unstable]
+#![unstable(feature = "rand")]
 
 use cell::RefCell;
 use clone::Clone;
diff --git a/src/libstd/rt/mod.rs b/src/libstd/rt/mod.rs
index e3e4e132b81..7e19f1cac2c 100644
--- a/src/libstd/rt/mod.rs
+++ b/src/libstd/rt/mod.rs
@@ -16,7 +16,7 @@
 //! and should be considered as private implementation details for the
 //! time being.
 
-#![unstable]
+#![unstable(feature = "std_misc")]
 
 // FIXME: this should not be here.
 #![allow(missing_docs)]
diff --git a/src/libstd/rt/unwind.rs b/src/libstd/rt/unwind.rs
index b313a5312bc..18298f1c7f4 100644
--- a/src/libstd/rt/unwind.rs
+++ b/src/libstd/rt/unwind.rs
@@ -582,7 +582,7 @@ fn begin_unwind_inner(msg: Box<Any + Send>, file_line: &(&'static str, uint)) ->
 /// Only a limited number of callbacks can be registered, and this function
 /// returns whether the callback was successfully registered or not. It is not
 /// currently possible to unregister a callback once it has been registered.
-#[unstable]
+#[unstable(feature = "std_misc")]
 pub unsafe fn register(f: Callback) -> bool {
     match CALLBACK_CNT.fetch_add(1, Ordering::SeqCst) {
         // The invocation code has knowledge of this window where the count has
diff --git a/src/libstd/rtdeps.rs b/src/libstd/rtdeps.rs
index f4fbd378899..06b68162487 100644
--- a/src/libstd/rtdeps.rs
+++ b/src/libstd/rtdeps.rs
@@ -12,7 +12,7 @@
 //! the standard library This varies per-platform, but these libraries are
 //! necessary for running libstd.
 
-#![unstable]
+#![unstable(feature = "std_misc")]
 
 // All platforms need to link to rustrt
 #[cfg(not(test))]
diff --git a/src/libstd/sync/barrier.rs b/src/libstd/sync/barrier.rs
index 70939879400..40710d627c0 100644
--- a/src/libstd/sync/barrier.rs
+++ b/src/libstd/sync/barrier.rs
@@ -29,7 +29,7 @@ use sync::{Mutex, Condvar};
 ///     });
 /// }
 /// ```
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 pub struct Barrier {
     lock: Mutex<BarrierState>,
     cvar: Condvar,
@@ -54,7 +54,7 @@ impl Barrier {
     ///
     /// A barrier will block `n`-1 threads which call `wait` and then wake up
     /// all threads at once when the `n`th thread calls `wait`.
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     pub fn new(n: uint) -> Barrier {
         Barrier {
             lock: Mutex::new(BarrierState {
@@ -75,7 +75,7 @@ impl Barrier {
     /// returns `true` from `is_leader` when returning from this function, and
     /// all other threads will receive a result that will return `false` from
     /// `is_leader`
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     pub fn wait(&self) -> BarrierWaitResult {
         let mut lock = self.lock.lock().unwrap();
         let local_gen = lock.generation_id;
@@ -102,7 +102,7 @@ impl BarrierWaitResult {
     ///
     /// Only one thread will have `true` returned from their result, all other
     /// threads will have `false` returned.
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     pub fn is_leader(&self) -> bool { self.0 }
 }
 
diff --git a/src/libstd/sync/condvar.rs b/src/libstd/sync/condvar.rs
index d2d5335078e..a7a5b084582 100644
--- a/src/libstd/sync/condvar.rs
+++ b/src/libstd/sync/condvar.rs
@@ -58,7 +58,7 @@ use sync::{mutex, MutexGuard};
 ///     started = cvar.wait(started).unwrap();
 /// }
 /// ```
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 pub struct Condvar { inner: Box<StaticCondvar> }
 
 unsafe impl Send for Condvar {}
@@ -76,7 +76,8 @@ unsafe impl Sync for Condvar {}
 ///
 /// static CVAR: StaticCondvar = CONDVAR_INIT;
 /// ```
-#[unstable = "may be merged with Condvar in the future"]
+#[unstable(feature = "std_misc",
+           reason = "may be merged with Condvar in the future")]
 pub struct StaticCondvar {
     inner: sys::Condvar,
     mutex: AtomicUsize,
@@ -86,7 +87,8 @@ unsafe impl Send for StaticCondvar {}
 unsafe impl Sync for StaticCondvar {}
 
 /// Constant initializer for a statically allocated condition variable.
-#[unstable = "may be merged with Condvar in the future"]
+#[unstable(feature = "std_misc",
+           reason = "may be merged with Condvar in the future")]
 pub const CONDVAR_INIT: StaticCondvar = StaticCondvar {
     inner: sys::CONDVAR_INIT,
     mutex: ATOMIC_USIZE_INIT,
@@ -95,7 +97,7 @@ pub const CONDVAR_INIT: StaticCondvar = StaticCondvar {
 impl Condvar {
     /// Creates a new condition variable which is ready to be waited on and
     /// notified.
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     pub fn new() -> Condvar {
         Condvar {
             inner: box StaticCondvar {
@@ -131,7 +133,7 @@ impl Condvar {
     /// over time. Each condition variable is dynamically bound to exactly one
     /// mutex to ensure defined behavior across platforms. If this functionality
     /// is not desired, then unsafe primitives in `sys` are provided.
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     pub fn wait<'a, T>(&self, guard: MutexGuard<'a, T>)
                        -> LockResult<MutexGuard<'a, T>> {
         unsafe {
@@ -154,7 +156,7 @@ impl Condvar {
     ///
     /// Like `wait`, the lock specified will be re-acquired when this function
     /// returns, regardless of whether the timeout elapsed or not.
-    #[unstable]
+    #[unstable(feature = "std_misc")]
     pub fn wait_timeout<'a, T>(&self, guard: MutexGuard<'a, T>, dur: Duration)
                            -> LockResult<(MutexGuard<'a, T>, bool)> {
         unsafe {
@@ -169,7 +171,7 @@ impl Condvar {
     /// The semantics of this function are equivalent to `wait_timeout` except
     /// that the implementation will repeatedly wait while the duration has not
     /// passed and the provided function returns `false`.
-    #[unstable]
+    #[unstable(feature = "std_misc")]
     pub fn wait_timeout_with<'a, T, F>(&self,
                                        guard: MutexGuard<'a, T>,
                                        dur: Duration,
@@ -189,7 +191,7 @@ impl Condvar {
     /// `notify_one` are not buffered in any way.
     ///
     /// To wake up all threads, see `notify_all()`.
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     pub fn notify_one(&self) { unsafe { self.inner.inner.notify_one() } }
 
     /// Wake up all blocked threads on this condvar.
@@ -199,11 +201,11 @@ impl Condvar {
     /// way.
     ///
     /// To wake up only one thread, see `notify_one()`.
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     pub fn notify_all(&self) { unsafe { self.inner.inner.notify_all() } }
 }
 
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl Drop for Condvar {
     fn drop(&mut self) {
         unsafe { self.inner.inner.destroy() }
@@ -215,7 +217,8 @@ impl StaticCondvar {
     /// notification.
     ///
     /// See `Condvar::wait`.
-    #[unstable = "may be merged with Condvar in the future"]
+    #[unstable(feature = "std_misc",
+               reason = "may be merged with Condvar in the future")]
     pub fn wait<'a, T>(&'static self, guard: MutexGuard<'a, T>)
                        -> LockResult<MutexGuard<'a, T>> {
         let poisoned = unsafe {
@@ -235,7 +238,8 @@ impl StaticCondvar {
     /// specified duration.
     ///
     /// See `Condvar::wait_timeout`.
-    #[unstable = "may be merged with Condvar in the future"]
+    #[unstable(feature = "std_misc",
+               reason = "may be merged with Condvar in the future")]
     pub fn wait_timeout<'a, T>(&'static self, guard: MutexGuard<'a, T>, dur: Duration)
                                -> LockResult<(MutexGuard<'a, T>, bool)> {
         let (poisoned, success) = unsafe {
@@ -258,7 +262,8 @@ impl StaticCondvar {
     /// passed and the function returns `false`.
     ///
     /// See `Condvar::wait_timeout_with`.
-    #[unstable = "may be merged with Condvar in the future"]
+    #[unstable(feature = "std_misc",
+               reason = "may be merged with Condvar in the future")]
     pub fn wait_timeout_with<'a, T, F>(&'static self,
                                        guard: MutexGuard<'a, T>,
                                        dur: Duration,
@@ -298,13 +303,15 @@ impl StaticCondvar {
     /// Wake up one blocked thread on this condvar.
     ///
     /// See `Condvar::notify_one`.
-    #[unstable = "may be merged with Condvar in the future"]
+    #[unstable(feature = "std_misc",
+               reason = "may be merged with Condvar in the future")]
     pub fn notify_one(&'static self) { unsafe { self.inner.notify_one() } }
 
     /// Wake up all blocked threads on this condvar.
     ///
     /// See `Condvar::notify_all`.
-    #[unstable = "may be merged with Condvar in the future"]
+    #[unstable(feature = "std_misc",
+               reason = "may be merged with Condvar in the future")]
     pub fn notify_all(&'static self) { unsafe { self.inner.notify_all() } }
 
     /// Deallocate all resources associated with this static condvar.
@@ -313,7 +320,8 @@ impl StaticCondvar {
     /// active users of the condvar, and this also doesn't prevent any future
     /// users of the condvar. This method is required to be called to not leak
     /// memory on all platforms.
-    #[unstable = "may be merged with Condvar in the future"]
+    #[unstable(feature = "std_misc",
+               reason = "may be merged with Condvar in the future")]
     pub unsafe fn destroy(&'static self) {
         self.inner.destroy()
     }
diff --git a/src/libstd/sync/future.rs b/src/libstd/sync/future.rs
index 36bbc5ff5b4..a79fb684f47 100644
--- a/src/libstd/sync/future.rs
+++ b/src/libstd/sync/future.rs
@@ -27,9 +27,10 @@
 //! ```
 
 #![allow(missing_docs)]
-#![unstable = "futures as-is have yet to be deeply reevaluated with recent \
-               core changes to Rust's synchronization story, and will likely \
-               become stable in the future but are unstable until that time"]
+#![unstable(feature = "std_misc",
+            reason = "futures as-is have yet to be deeply reevaluated with recent \
+                      core changes to Rust's synchronization story, and will likely \
+                      become stable in the future but are unstable until that time")]
 
 use core::prelude::*;
 use core::mem::replace;
diff --git a/src/libstd/sync/mod.rs b/src/libstd/sync/mod.rs
index 6fff6765bd3..f3b721438d8 100644
--- a/src/libstd/sync/mod.rs
+++ b/src/libstd/sync/mod.rs
@@ -15,7 +15,7 @@
 //! and/or blocking at all, but rather provide the necessary tools to build
 //! other types of concurrent primitives.
 
-#![stable]
+#![stable(feature = "rust1", since = "1.0.0")]
 
 pub use alloc::arc::{Arc, Weak};
 pub use core::atomic;
diff --git a/src/libstd/sync/mpsc/mod.rs b/src/libstd/sync/mpsc/mod.rs
index 6140e3fd36c..322c6137984 100644
--- a/src/libstd/sync/mpsc/mod.rs
+++ b/src/libstd/sync/mpsc/mod.rs
@@ -163,7 +163,7 @@
 //! }
 //! ```
 
-#![stable]
+#![stable(feature = "rust1", since = "1.0.0")]
 
 // A description of how Rust's channel implementation works
 //
@@ -338,7 +338,7 @@ mod spsc_queue;
 
 /// The receiving-half of Rust's channel type. This half can only be owned by
 /// one task
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 pub struct Receiver<T> {
     inner: UnsafeCell<Flavor<T>>,
 }
@@ -350,14 +350,14 @@ unsafe impl<T:Send> Send for Receiver<T> { }
 /// An iterator over messages on a receiver, this iterator will block
 /// whenever `next` is called, waiting for a new message, and `None` will be
 /// returned when the corresponding channel has hung up.
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 pub struct Iter<'a, T:'a> {
     rx: &'a Receiver<T>
 }
 
 /// The sending-half of Rust's asynchronous channel type. This half can only be
 /// owned by one task, but it can be cloned to send to other tasks.
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 pub struct Sender<T> {
     inner: UnsafeCell<Flavor<T>>,
 }
@@ -368,7 +368,7 @@ unsafe impl<T:Send> Send for Sender<T> { }
 
 /// The sending-half of Rust's synchronous channel type. This half can only be
 /// owned by one task, but it can be cloned to send to other tasks.
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 pub struct SyncSender<T> {
     inner: Arc<UnsafeCell<sync::Packet<T>>>,
 }
@@ -383,7 +383,7 @@ impl<T> !Sync for SyncSender<T> {}
 /// disconnected, implying that the data could never be received. The error
 /// contains the data being sent as a payload so it can be recovered.
 #[derive(PartialEq, Eq)]
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 pub struct SendError<T>(pub T);
 
 /// An error returned from the `recv` function on a `Receiver`.
@@ -391,29 +391,29 @@ pub struct SendError<T>(pub T);
 /// The `recv` operation can only fail if the sending half of a channel is
 /// disconnected, implying that no further messages will ever be received.
 #[derive(PartialEq, Eq, Clone, Copy, Show)]
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 pub struct RecvError;
 
 /// This enumeration is the list of the possible reasons that try_recv could not
 /// return data when called.
 #[derive(PartialEq, Clone, Copy, Show)]
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 pub enum TryRecvError {
     /// This channel is currently empty, but the sender(s) have not yet
     /// disconnected, so data may yet become available.
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     Empty,
 
     /// This channel's sending half has become disconnected, and there will
     /// never be any more data received on this channel
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     Disconnected,
 }
 
 /// This enumeration is the list of the possible error outcomes for the
 /// `SyncSender::try_send` method.
 #[derive(PartialEq, Clone)]
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 pub enum TrySendError<T> {
     /// The data could not be sent on the channel because it would require that
     /// the callee block to send the data.
@@ -421,12 +421,12 @@ pub enum TrySendError<T> {
     /// If this is a buffered channel, then the buffer is full at this time. If
     /// this is not a buffered channel, then there is no receiver available to
     /// acquire the data.
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     Full(T),
 
     /// This channel's receiving half has disconnected, so the data could not be
     /// sent. The data is returned back to the callee in this case.
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     Disconnected(T),
 }
 
@@ -484,7 +484,7 @@ impl<T> UnsafeFlavor<T> for Receiver<T> {
 /// // Let's see what that answer was
 /// println!("{:?}", rx.recv().unwrap());
 /// ```
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 pub fn channel<T: Send>() -> (Sender<T>, Receiver<T>) {
     let a = Arc::new(UnsafeCell::new(oneshot::Packet::new()));
     (Sender::new(Flavor::Oneshot(a.clone())), Receiver::new(Flavor::Oneshot(a)))
@@ -524,7 +524,7 @@ pub fn channel<T: Send>() -> (Sender<T>, Receiver<T>) {
 /// assert_eq!(rx.recv().unwrap(), 1i);
 /// assert_eq!(rx.recv().unwrap(), 2i);
 /// ```
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 pub fn sync_channel<T: Send>(bound: uint) -> (SyncSender<T>, Receiver<T>) {
     let a = Arc::new(UnsafeCell::new(sync::Packet::new(bound)));
     (SyncSender::new(a.clone()), Receiver::new(Flavor::Sync(a)))
@@ -568,7 +568,7 @@ impl<T: Send> Sender<T> {
     /// drop(rx);
     /// assert_eq!(tx.send(1i).err().unwrap().0, 1);
     /// ```
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     pub fn send(&self, t: T) -> Result<(), SendError<T>> {
         let (new_inner, ret) = match *unsafe { self.inner() } {
             Flavor::Oneshot(ref p) => {
@@ -615,7 +615,7 @@ impl<T: Send> Sender<T> {
     }
 }
 
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl<T: Send> Clone for Sender<T> {
     fn clone(&self) -> Sender<T> {
         let (packet, sleeper, guard) = match *unsafe { self.inner() } {
@@ -661,7 +661,7 @@ impl<T: Send> Clone for Sender<T> {
 }
 
 #[unsafe_destructor]
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl<T: Send> Drop for Sender<T> {
     fn drop(&mut self) {
         match *unsafe { self.inner_mut() } {
@@ -696,7 +696,7 @@ impl<T: Send> SyncSender<T> {
     /// This function will never panic, but it may return `Err` if the
     /// `Receiver` has disconnected and is no longer able to receive
     /// information.
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     pub fn send(&self, t: T) -> Result<(), SendError<T>> {
         unsafe { (*self.inner.get()).send(t).map_err(SendError) }
     }
@@ -710,13 +710,13 @@ impl<T: Send> SyncSender<T> {
     ///
     /// See `SyncSender::send` for notes about guarantees of whether the
     /// receiver has received the data or not if this function is successful.
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     pub fn try_send(&self, t: T) -> Result<(), TrySendError<T>> {
         unsafe { (*self.inner.get()).try_send(t) }
     }
 }
 
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl<T: Send> Clone for SyncSender<T> {
     fn clone(&self) -> SyncSender<T> {
         unsafe { (*self.inner.get()).clone_chan(); }
@@ -725,7 +725,7 @@ impl<T: Send> Clone for SyncSender<T> {
 }
 
 #[unsafe_destructor]
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl<T: Send> Drop for SyncSender<T> {
     fn drop(&mut self) {
         unsafe { (*self.inner.get()).drop_chan(); }
@@ -749,7 +749,7 @@ impl<T: Send> Receiver<T> {
     ///
     /// This is useful for a flavor of "optimistic check" before deciding to
     /// block on a receiver.
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     pub fn try_recv(&self) -> Result<T, TryRecvError> {
         loop {
             let new_port = match *unsafe { self.inner() } {
@@ -810,7 +810,7 @@ impl<T: Send> Receiver<T> {
     /// If the corresponding `Sender` has disconnected, or it disconnects while
     /// this call is blocking, this call will wake up and return `Err` to
     /// indicate that no more messages can ever be received on this channel.
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     pub fn recv(&self) -> Result<T, RecvError> {
         loop {
             let new_port = match *unsafe { self.inner() } {
@@ -849,7 +849,7 @@ impl<T: Send> Receiver<T> {
 
     /// Returns an iterator that will block waiting for messages, but never
     /// `panic!`. It will return `None` when the channel has hung up.
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     pub fn iter(&self) -> Iter<T> {
         Iter { rx: self }
     }
@@ -941,7 +941,7 @@ impl<T: Send> select::Packet for Receiver<T> {
     }
 }
 
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl<'a, T: Send> Iterator for Iter<'a, T> {
     type Item = T;
 
@@ -949,7 +949,7 @@ impl<'a, T: Send> Iterator for Iter<'a, T> {
 }
 
 #[unsafe_destructor]
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl<T: Send> Drop for Receiver<T> {
     fn drop(&mut self) {
         match *unsafe { self.inner_mut() } {
@@ -961,21 +961,21 @@ impl<T: Send> Drop for Receiver<T> {
     }
 }
 
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl<T> fmt::Debug for SendError<T> {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         "SendError(..)".fmt(f)
     }
 }
 
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl<T> fmt::Display for SendError<T> {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         "sending on a closed channel".fmt(f)
     }
 }
 
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl<T> fmt::Debug for TrySendError<T> {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         match *self {
@@ -985,7 +985,7 @@ impl<T> fmt::Debug for TrySendError<T> {
     }
 }
 
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl<T> fmt::Display for TrySendError<T> {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         match *self {
@@ -999,14 +999,14 @@ impl<T> fmt::Display for TrySendError<T> {
     }
 }
 
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl fmt::Display for RecvError {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         "receiving on a closed channel".fmt(f)
     }
 }
 
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl fmt::Display for TryRecvError {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         match *self {
diff --git a/src/libstd/sync/mpsc/mpsc_queue.rs b/src/libstd/sync/mpsc/mpsc_queue.rs
index ea81ed30a9c..c222c313ba6 100644
--- a/src/libstd/sync/mpsc/mpsc_queue.rs
+++ b/src/libstd/sync/mpsc/mpsc_queue.rs
@@ -35,7 +35,7 @@
 //! method, and see the method for more information about it. Due to this
 //! caveat, this queue may not be appropriate for all use-cases.
 
-#![unstable]
+#![unstable(feature = "std_misc")]
 
 // http://www.1024cores.net/home/lock-free-algorithms
 //                         /queues/non-intrusive-mpsc-node-based-queue
@@ -139,7 +139,7 @@ impl<T: Send> Queue<T> {
 }
 
 #[unsafe_destructor]
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl<T: Send> Drop for Queue<T> {
     fn drop(&mut self) {
         unsafe {
diff --git a/src/libstd/sync/mpsc/select.rs b/src/libstd/sync/mpsc/select.rs
index f5bacbb8ce2..e97c82a5b1b 100644
--- a/src/libstd/sync/mpsc/select.rs
+++ b/src/libstd/sync/mpsc/select.rs
@@ -46,12 +46,13 @@
 //! ```
 
 #![allow(dead_code)]
-#![unstable = "This implementation, while likely sufficient, is unsafe and \
-                   likely to be error prone. At some point in the future this \
-                   module will likely be replaced, and it is currently \
-                   unknown how much API breakage that will cause. The ability \
-                   to select over a number of channels will remain forever, \
-                   but no guarantees beyond this are being made"]
+#![unstable(feature = "std_misc",
+            reason = "This implementation, while likely sufficient, is unsafe and \
+                      likely to be error prone. At some point in the future this \
+                      module will likely be replaced, and it is currently \
+                      unknown how much API breakage that will cause. The ability \
+                      to select over a number of channels will remain forever, \
+                      but no guarantees beyond this are being made")]
 
 
 use core::prelude::*;
diff --git a/src/libstd/sync/mpsc/spsc_queue.rs b/src/libstd/sync/mpsc/spsc_queue.rs
index 8cd88cedf6b..c1983fcab19 100644
--- a/src/libstd/sync/mpsc/spsc_queue.rs
+++ b/src/libstd/sync/mpsc/spsc_queue.rs
@@ -33,7 +33,7 @@
 //! concurrently between two tasks. This data structure is safe to use and
 //! enforces the semantics that there is one pusher and one popper.
 
-#![unstable]
+#![unstable(feature = "std_misc")]
 
 use core::prelude::*;
 
diff --git a/src/libstd/sync/mutex.rs b/src/libstd/sync/mutex.rs
index 6ddfe3e075b..f7fdd60eb8c 100644
--- a/src/libstd/sync/mutex.rs
+++ b/src/libstd/sync/mutex.rs
@@ -109,7 +109,7 @@ use sys_common::mutex as sys;
 ///
 /// *guard += 1;
 /// ```
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 pub struct Mutex<T> {
     // Note that this static mutex is in a *box*, not inlined into the struct
     // itself. Once a native mutex has been used once, its address can never
@@ -145,7 +145,8 @@ unsafe impl<T:Send> Sync for Mutex<T> { }
 /// }
 /// // lock is unlocked here.
 /// ```
-#[unstable = "may be merged with Mutex in the future"]
+#[unstable(feature = "std_misc",
+           reason = "may be merged with Mutex in the future")]
 pub struct StaticMutex {
     lock: sys::Mutex,
     poison: poison::Flag,
@@ -159,7 +160,7 @@ unsafe impl Sync for StaticMutex {}
 /// The data protected by the mutex can be access through this guard via its
 /// Deref and DerefMut implementations
 #[must_use]
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 pub struct MutexGuard<'a, T: 'a> {
     // funny underscores due to how Deref/DerefMut currently work (they
     // disregard field privacy).
@@ -172,7 +173,8 @@ impl<'a, T> !marker::Send for MutexGuard<'a, T> {}
 
 /// Static initialization of a mutex. This constant can be used to initialize
 /// other mutex constants.
-#[unstable = "may be merged with Mutex in the future"]
+#[unstable(feature = "std_misc",
+           reason = "may be merged with Mutex in the future")]
 pub const MUTEX_INIT: StaticMutex = StaticMutex {
     lock: sys::MUTEX_INIT,
     poison: poison::FLAG_INIT,
@@ -180,7 +182,7 @@ pub const MUTEX_INIT: StaticMutex = StaticMutex {
 
 impl<T: Send> Mutex<T> {
     /// Creates a new mutex in an unlocked state ready for use.
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     pub fn new(t: T) -> Mutex<T> {
         Mutex {
             inner: box MUTEX_INIT,
@@ -199,7 +201,7 @@ impl<T: Send> Mutex<T> {
     ///
     /// If another user of this mutex panicked while holding the mutex, then
     /// this call will return an error once the mutex is acquired.
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     pub fn lock(&self) -> LockResult<MutexGuard<T>> {
         unsafe { self.inner.lock.lock() }
         MutexGuard::new(&*self.inner, &self.data)
@@ -218,7 +220,7 @@ impl<T: Send> Mutex<T> {
     /// If another user of this mutex panicked while holding the mutex, then
     /// this call will return failure if the mutex would otherwise be
     /// acquired.
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     pub fn try_lock(&self) -> TryLockResult<MutexGuard<T>> {
         if unsafe { self.inner.lock.try_lock() } {
             Ok(try!(MutexGuard::new(&*self.inner, &self.data)))
@@ -229,7 +231,7 @@ impl<T: Send> Mutex<T> {
 }
 
 #[unsafe_destructor]
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl<T: Send> Drop for Mutex<T> {
     fn drop(&mut self) {
         // This is actually safe b/c we know that there is no further usage of
@@ -246,7 +248,8 @@ static DUMMY: Dummy = Dummy(UnsafeCell { value: () });
 impl StaticMutex {
     /// Acquires this lock, see `Mutex::lock`
     #[inline]
-    #[unstable = "may be merged with Mutex in the future"]
+    #[unstable(feature = "std_misc",
+               reason = "may be merged with Mutex in the future")]
     pub fn lock(&'static self) -> LockResult<MutexGuard<()>> {
         unsafe { self.lock.lock() }
         MutexGuard::new(self, &DUMMY.0)
@@ -254,7 +257,8 @@ impl StaticMutex {
 
     /// Attempts to grab this lock, see `Mutex::try_lock`
     #[inline]
-    #[unstable = "may be merged with Mutex in the future"]
+    #[unstable(feature = "std_misc",
+               reason = "may be merged with Mutex in the future")]
     pub fn try_lock(&'static self) -> TryLockResult<MutexGuard<()>> {
         if unsafe { self.lock.try_lock() } {
             Ok(try!(MutexGuard::new(self, &DUMMY.0)))
@@ -273,7 +277,8 @@ impl StaticMutex {
     /// *all* platforms. It may be the case that some platforms do not leak
     /// memory if this method is not called, but this is not guaranteed to be
     /// true on all platforms.
-    #[unstable = "may be merged with Mutex in the future"]
+    #[unstable(feature = "std_misc",
+               reason = "may be merged with Mutex in the future")]
     pub unsafe fn destroy(&'static self) {
         self.lock.destroy()
     }
@@ -293,7 +298,7 @@ impl<'mutex, T> MutexGuard<'mutex, T> {
     }
 }
 
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl<'mutex, T> Deref for MutexGuard<'mutex, T> {
     type Target = T;
 
@@ -301,7 +306,7 @@ impl<'mutex, T> Deref for MutexGuard<'mutex, T> {
         unsafe { &*self.__data.get() }
     }
 }
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl<'mutex, T> DerefMut for MutexGuard<'mutex, T> {
     fn deref_mut<'a>(&'a mut self) -> &'a mut T {
         unsafe { &mut *self.__data.get() }
@@ -309,7 +314,7 @@ impl<'mutex, T> DerefMut for MutexGuard<'mutex, T> {
 }
 
 #[unsafe_destructor]
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl<'a, T> Drop for MutexGuard<'a, T> {
     #[inline]
     fn drop(&mut self) {
diff --git a/src/libstd/sync/once.rs b/src/libstd/sync/once.rs
index 6231a91833d..1c489540581 100644
--- a/src/libstd/sync/once.rs
+++ b/src/libstd/sync/once.rs
@@ -36,7 +36,7 @@ use sync::{StaticMutex, MUTEX_INIT};
 ///     // run initialization here
 /// });
 /// ```
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 pub struct Once {
     mutex: StaticMutex,
     cnt: AtomicIsize,
@@ -46,7 +46,7 @@ pub struct Once {
 unsafe impl Sync for Once {}
 
 /// Initialization value for static `Once` values.
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 pub const ONCE_INIT: Once = Once {
     mutex: MUTEX_INIT,
     cnt: ATOMIC_ISIZE_INIT,
@@ -63,7 +63,7 @@ impl Once {
     ///
     /// When this function returns, it is guaranteed that some initialization
     /// has run and completed (it may not be the closure specified).
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     pub fn call_once<F>(&'static self, f: F) where F: FnOnce() {
         // Optimize common path: load is much cheaper than fetch_add.
         if self.cnt.load(Ordering::SeqCst) < 0 {
diff --git a/src/libstd/sync/poison.rs b/src/libstd/sync/poison.rs
index d7fcee3ae2e..18680b96592 100644
--- a/src/libstd/sync/poison.rs
+++ b/src/libstd/sync/poison.rs
@@ -53,22 +53,22 @@ pub struct Guard {
 /// is held. The precise semantics for when a lock is poisoned is documented on
 /// each lock, but once a lock is poisoned then all future acquisitions will
 /// return this error.
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 pub struct PoisonError<T> {
     guard: T,
 }
 
 /// An enumeration of possible errors which can occur while calling the
 /// `try_lock` method.
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 pub enum TryLockError<T> {
     /// The lock could not be acquired because another task failed while holding
     /// the lock.
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     Poisoned(PoisonError<T>),
     /// The lock could not be acquired at this time because the operation would
     /// otherwise block.
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     WouldBlock,
 }
 
@@ -79,7 +79,7 @@ pub enum TryLockError<T> {
 /// that the primitive was poisoned. Note that the `Err` variant *also* carries
 /// the associated guard, and it can be acquired through the `into_inner`
 /// method.
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 pub type LockResult<Guard> = Result<Guard, PoisonError<Guard>>;
 
 /// A type alias for the result of a nonblocking locking method.
@@ -87,17 +87,17 @@ pub type LockResult<Guard> = Result<Guard, PoisonError<Guard>>;
 /// For more information, see `LockResult`. A `TryLockResult` doesn't
 /// necessarily hold the associated guard in the `Err` type as the lock may not
 /// have been acquired for other reasons.
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 pub type TryLockResult<Guard> = Result<Guard, TryLockError<Guard>>;
 
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl<T> fmt::Debug for PoisonError<T> {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         "PoisonError { inner: .. }".fmt(f)
     }
 }
 
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl<T> fmt::Display for PoisonError<T> {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         self.description().fmt(f)
@@ -113,22 +113,23 @@ impl<T> Error for PoisonError<T> {
 impl<T> PoisonError<T> {
     /// Consumes this error indicating that a lock is poisoned, returning the
     /// underlying guard to allow access regardless.
-    #[deprecated="renamed to into_inner"]
+    #[unstable(feature = "std_misc")]
+    #[deprecated(since = "1.0.0", reason = "renamed to into_inner")]
     pub fn into_guard(self) -> T { self.guard }
 
     /// Consumes this error indicating that a lock is poisoned, returning the
     /// underlying guard to allow access regardless.
-    #[unstable]
+    #[unstable(feature = "std_misc")]
     pub fn into_inner(self) -> T { self.guard }
 
     /// Reaches into this error indicating that a lock is poisoned, returning a
     /// reference to the underlying guard to allow access regardless.
-    #[unstable]
+    #[unstable(feature = "std_misc")]
     pub fn get_ref(&self) -> &T { &self.guard }
 
     /// Reaches into this error indicating that a lock is poisoned, returning a
     /// mutable reference to the underlying guard to allow access regardless.
-    #[unstable]
+    #[unstable(feature = "std_misc")]
     pub fn get_mut(&mut self) -> &mut T { &mut self.guard }
 }
 
@@ -138,7 +139,7 @@ impl<T> FromError<PoisonError<T>> for TryLockError<T> {
     }
 }
 
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl<T> fmt::Debug for TryLockError<T> {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         match *self {
@@ -148,7 +149,7 @@ impl<T> fmt::Debug for TryLockError<T> {
     }
 }
 
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl<T> fmt::Display for TryLockError<T> {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         self.description().fmt(f)
diff --git a/src/libstd/sync/rwlock.rs b/src/libstd/sync/rwlock.rs
index 8cc2cac33ec..12befbf72e3 100644
--- a/src/libstd/sync/rwlock.rs
+++ b/src/libstd/sync/rwlock.rs
@@ -58,7 +58,7 @@ use sys_common::rwlock as sys;
 ///     assert_eq!(*w, 6);
 /// } // write lock is dropped here
 /// ```
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 pub struct RwLock<T> {
     inner: Box<StaticRwLock>,
     data: UnsafeCell<T>,
@@ -90,7 +90,8 @@ unsafe impl<T> Sync for RwLock<T> {}
 /// }
 /// unsafe { LOCK.destroy() } // free all resources
 /// ```
-#[unstable = "may be merged with RwLock in the future"]
+#[unstable(feature = "std_misc",
+           reason = "may be merged with RwLock in the future")]
 pub struct StaticRwLock {
     lock: sys::RWLock,
     poison: poison::Flag,
@@ -100,7 +101,8 @@ unsafe impl Send for StaticRwLock {}
 unsafe impl Sync for StaticRwLock {}
 
 /// Constant initialization for a statically-initialized rwlock.
-#[unstable = "may be merged with RwLock in the future"]
+#[unstable(feature = "std_misc",
+           reason = "may be merged with RwLock in the future")]
 pub const RW_LOCK_INIT: StaticRwLock = StaticRwLock {
     lock: sys::RWLOCK_INIT,
     poison: poison::FLAG_INIT,
@@ -109,7 +111,7 @@ pub const RW_LOCK_INIT: StaticRwLock = StaticRwLock {
 /// RAII structure used to release the shared read access of a lock when
 /// dropped.
 #[must_use]
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 pub struct RwLockReadGuard<'a, T: 'a> {
     __lock: &'a StaticRwLock,
     __data: &'a UnsafeCell<T>,
@@ -120,7 +122,7 @@ impl<'a, T> !marker::Send for RwLockReadGuard<'a, T> {}
 /// RAII structure used to release the exclusive write access of a lock when
 /// dropped.
 #[must_use]
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 pub struct RwLockWriteGuard<'a, T: 'a> {
     __lock: &'a StaticRwLock,
     __data: &'a UnsafeCell<T>,
@@ -139,7 +141,7 @@ impl<T: Send + Sync> RwLock<T> {
     ///
     /// let lock = RwLock::new(5);
     /// ```
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     pub fn new(t: T) -> RwLock<T> {
         RwLock { inner: box RW_LOCK_INIT, data: UnsafeCell::new(t) }
     }
@@ -162,7 +164,7 @@ impl<T: Send + Sync> RwLock<T> {
     /// is poisoned whenever a writer panics while holding an exclusive lock.
     /// The failure will occur immediately after the lock has been acquired.
     #[inline]
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     pub fn read(&self) -> LockResult<RwLockReadGuard<T>> {
         unsafe { self.inner.lock.read() }
         RwLockReadGuard::new(&*self.inner, &self.data)
@@ -184,7 +186,7 @@ impl<T: Send + Sync> RwLock<T> {
     /// error will only be returned if the lock would have otherwise been
     /// acquired.
     #[inline]
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     pub fn try_read(&self) -> TryLockResult<RwLockReadGuard<T>> {
         if unsafe { self.inner.lock.try_read() } {
             Ok(try!(RwLockReadGuard::new(&*self.inner, &self.data)))
@@ -208,7 +210,7 @@ impl<T: Send + Sync> RwLock<T> {
     /// is poisoned whenever a writer panics while holding an exclusive lock.
     /// An error will be returned when the lock is acquired.
     #[inline]
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     pub fn write(&self) -> LockResult<RwLockWriteGuard<T>> {
         unsafe { self.inner.lock.write() }
         RwLockWriteGuard::new(&*self.inner, &self.data)
@@ -227,7 +229,7 @@ impl<T: Send + Sync> RwLock<T> {
     /// error will only be returned if the lock would have otherwise been
     /// acquired.
     #[inline]
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     pub fn try_write(&self) -> TryLockResult<RwLockWriteGuard<T>> {
         if unsafe { self.inner.lock.try_read() } {
             Ok(try!(RwLockWriteGuard::new(&*self.inner, &self.data)))
@@ -238,7 +240,7 @@ impl<T: Send + Sync> RwLock<T> {
 }
 
 #[unsafe_destructor]
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl<T> Drop for RwLock<T> {
     fn drop(&mut self) {
         unsafe { self.inner.lock.destroy() }
@@ -255,7 +257,8 @@ impl StaticRwLock {
     ///
     /// See `RwLock::read`.
     #[inline]
-    #[unstable = "may be merged with RwLock in the future"]
+    #[unstable(feature = "std_misc",
+               reason = "may be merged with RwLock in the future")]
     pub fn read(&'static self) -> LockResult<RwLockReadGuard<'static, ()>> {
         unsafe { self.lock.read() }
         RwLockReadGuard::new(self, &DUMMY.0)
@@ -265,7 +268,8 @@ impl StaticRwLock {
     ///
     /// See `RwLock::try_read`.
     #[inline]
-    #[unstable = "may be merged with RwLock in the future"]
+    #[unstable(feature = "std_misc",
+               reason = "may be merged with RwLock in the future")]
     pub fn try_read(&'static self)
                     -> TryLockResult<RwLockReadGuard<'static, ()>> {
         if unsafe { self.lock.try_read() } {
@@ -280,7 +284,8 @@ impl StaticRwLock {
     ///
     /// See `RwLock::write`.
     #[inline]
-    #[unstable = "may be merged with RwLock in the future"]
+    #[unstable(feature = "std_misc",
+               reason = "may be merged with RwLock in the future")]
     pub fn write(&'static self) -> LockResult<RwLockWriteGuard<'static, ()>> {
         unsafe { self.lock.write() }
         RwLockWriteGuard::new(self, &DUMMY.0)
@@ -290,7 +295,8 @@ impl StaticRwLock {
     ///
     /// See `RwLock::try_write`.
     #[inline]
-    #[unstable = "may be merged with RwLock in the future"]
+    #[unstable(feature = "std_misc",
+               reason = "may be merged with RwLock in the future")]
     pub fn try_write(&'static self)
                      -> TryLockResult<RwLockWriteGuard<'static, ()>> {
         if unsafe { self.lock.try_write() } {
@@ -306,7 +312,8 @@ impl StaticRwLock {
     /// active users of the lock, and this also doesn't prevent any future users
     /// of this lock. This method is required to be called to not leak memory on
     /// all platforms.
-    #[unstable = "may be merged with RwLock in the future"]
+    #[unstable(feature = "std_misc",
+               reason = "may be merged with RwLock in the future")]
     pub unsafe fn destroy(&'static self) {
         self.lock.destroy()
     }
@@ -338,19 +345,19 @@ impl<'rwlock, T> RwLockWriteGuard<'rwlock, T> {
     }
 }
 
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl<'rwlock, T> Deref for RwLockReadGuard<'rwlock, T> {
     type Target = T;
 
     fn deref(&self) -> &T { unsafe { &*self.__data.get() } }
 }
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl<'rwlock, T> Deref for RwLockWriteGuard<'rwlock, T> {
     type Target = T;
 
     fn deref(&self) -> &T { unsafe { &*self.__data.get() } }
 }
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl<'rwlock, T> DerefMut for RwLockWriteGuard<'rwlock, T> {
     fn deref_mut(&mut self) -> &mut T {
         unsafe { &mut *self.__data.get() }
@@ -358,7 +365,7 @@ impl<'rwlock, T> DerefMut for RwLockWriteGuard<'rwlock, T> {
 }
 
 #[unsafe_destructor]
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl<'a, T> Drop for RwLockReadGuard<'a, T> {
     fn drop(&mut self) {
         unsafe { self.__lock.lock.read_unlock(); }
@@ -366,7 +373,7 @@ impl<'a, T> Drop for RwLockReadGuard<'a, T> {
 }
 
 #[unsafe_destructor]
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl<'a, T> Drop for RwLockWriteGuard<'a, T> {
     fn drop(&mut self) {
         self.__lock.poison.done(&self.__poison);
diff --git a/src/libstd/sync/semaphore.rs b/src/libstd/sync/semaphore.rs
index 8d44084671a..0304b898884 100644
--- a/src/libstd/sync/semaphore.rs
+++ b/src/libstd/sync/semaphore.rs
@@ -8,8 +8,9 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#![unstable = "the interaction between semaphores and the acquisition/release \
-               of resources is currently unclear"]
+#![unstable(feature = "std_misc",
+            reason = "the interaction between semaphores and the acquisition/release \
+                      of resources is currently unclear")]
 
 use ops::Drop;
 use sync::{Mutex, Condvar};
@@ -99,7 +100,7 @@ impl Semaphore {
 }
 
 #[unsafe_destructor]
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl<'a> Drop for SemaphoreGuard<'a> {
     fn drop(&mut self) {
         self.sem.release();
diff --git a/src/libstd/sync/task_pool.rs b/src/libstd/sync/task_pool.rs
index 278528bdb38..3fac998d3e7 100644
--- a/src/libstd/sync/task_pool.rs
+++ b/src/libstd/sync/task_pool.rs
@@ -10,10 +10,11 @@
 
 //! Abstraction of a thread pool for basic parallelism.
 
-#![unstable = "the semantics of a failing task and whether a thread is \
-               re-attached to a thread pool are somewhat unclear, and the \
-               utility of this type in `std::sync` is questionable with \
-               respect to the jobs of other primitives"]
+#![unstable(feature = "std_misc",
+            reason = "the semantics of a failing task and whether a thread is \
+                      re-attached to a thread pool are somewhat unclear, and the \
+                      utility of this type in `std::sync` is questionable with \
+                      respect to the jobs of other primitives")]
 
 use core::prelude::*;
 
diff --git a/src/libstd/sys/unix/ext.rs b/src/libstd/sys/unix/ext.rs
index 37c47d593e0..4a82b2807e7 100644
--- a/src/libstd/sys/unix/ext.rs
+++ b/src/libstd/sys/unix/ext.rs
@@ -29,7 +29,7 @@
 //! }
 //! ```
 
-#![unstable]
+#![unstable(feature = "std_misc")]
 
 use vec::Vec;
 use sys::os_str::Buf;
diff --git a/src/libstd/sys/windows/ext.rs b/src/libstd/sys/windows/ext.rs
index 8e87f8cba36..a3bbf5c5fe7 100644
--- a/src/libstd/sys/windows/ext.rs
+++ b/src/libstd/sys/windows/ext.rs
@@ -14,7 +14,7 @@
 //! descriptors, and sockets, but its functionality will grow over
 //! time.
 
-#![unstable]
+#![unstable(feature = "std_misc")]
 
 pub use sys_common::wtf8::{Wtf8Buf, EncodeWide};
 
diff --git a/src/libstd/thread.rs b/src/libstd/thread.rs
index 4d932b3e777..c19ec8ea25c 100644
--- a/src/libstd/thread.rs
+++ b/src/libstd/thread.rs
@@ -144,7 +144,7 @@
 //!
 //! * It can be implemented highly efficiently on many platforms.
 
-#![stable]
+#![stable(feature = "rust1", since = "1.0.0")]
 
 use any::Any;
 use boxed::Box;
@@ -166,7 +166,7 @@ use sys_common::{stack, thread_info};
 
 /// Thread configuration. Provides detailed control over the properties
 /// and behavior of new threads.
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 pub struct Builder {
     // A name for the thread-to-be, for identification in panic messages
     name: Option<String>,
@@ -181,7 +181,7 @@ pub struct Builder {
 impl Builder {
     /// Generate the base configuration for spawning a thread, from which
     /// configuration methods can be chained.
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     pub fn new() -> Builder {
         Builder {
             name: None,
@@ -193,28 +193,30 @@ impl Builder {
 
     /// Name the thread-to-be. Currently the name is used for identification
     /// only in panic messages.
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     pub fn name(mut self, name: String) -> Builder {
         self.name = Some(name);
         self
     }
 
     /// Set the size of the stack for the new thread.
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     pub fn stack_size(mut self, size: uint) -> Builder {
         self.stack_size = Some(size);
         self
     }
 
     /// Redirect thread-local stdout.
-    #[unstable = "Will likely go away after proc removal"]
+    #[unstable(feature = "std_misc",
+               reason = "Will likely go away after proc removal")]
     pub fn stdout(mut self, stdout: Box<Writer + Send>) -> Builder {
         self.stdout = Some(stdout);
         self
     }
 
     /// Redirect thread-local stderr.
-    #[unstable = "Will likely go away after proc removal"]
+    #[unstable(feature = "std_misc",
+               reason = "Will likely go away after proc removal")]
     pub fn stderr(mut self, stderr: Box<Writer + Send>) -> Builder {
         self.stderr = Some(stderr);
         self
@@ -223,7 +225,8 @@ impl Builder {
     /// Spawn a new detached thread, and return a handle to it.
     ///
     /// See `Thead::spawn` and the module doc for more details.
-    #[unstable = "may change with specifics of new Send semantics"]
+    #[unstable(feature = "std_misc",
+               reason = "may change with specifics of new Send semantics")]
     pub fn spawn<F>(self, f: F) -> Thread where F: FnOnce(), F: Send + 'static {
         let (native, thread) = self.spawn_inner(Thunk::new(f), Thunk::with_arg(|_| {}));
         unsafe { imp::detach(native) };
@@ -234,7 +237,8 @@ impl Builder {
     /// scope, and return a `JoinGuard`.
     ///
     /// See `Thead::scoped` and the module doc for more details.
-    #[unstable = "may change with specifics of new Send semantics"]
+    #[unstable(feature = "std_misc",
+               reason = "may change with specifics of new Send semantics")]
     pub fn scoped<'a, T, F>(self, f: F) -> JoinGuard<'a, T> where
         T: Send + 'a, F: FnOnce() -> T, F: Send + 'a
     {
@@ -326,7 +330,7 @@ struct Inner {
 unsafe impl Sync for Inner {}
 
 #[derive(Clone)]
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 /// A handle to a thread.
 pub struct Thread {
     inner: Arc<Inner>,
@@ -350,7 +354,8 @@ impl Thread {
     /// main thread; the whole process is terminated when the main thread
     /// finishes.) The thread handle can be used for low-level
     /// synchronization. See the module documentation for additional details.
-    #[unstable = "may change with specifics of new Send semantics"]
+    #[unstable(feature = "std_misc",
+               reason = "may change with specifics of new Send semantics")]
     pub fn spawn<F>(f: F) -> Thread where F: FnOnce(), F: Send + 'static {
         Builder::new().spawn(f)
     }
@@ -363,7 +368,8 @@ impl Thread {
     /// current thread's stack (hence the "scoped" name), it cannot be detached;
     /// it *must* be joined before the relevant stack frame is popped. See the
     /// module documentation for additional details.
-    #[unstable = "may change with specifics of new Send semantics"]
+    #[unstable(feature = "std_misc",
+               reason = "may change with specifics of new Send semantics")]
     pub fn scoped<'a, T, F>(f: F) -> JoinGuard<'a, T> where
         T: Send + 'a, F: FnOnce() -> T, F: Send + 'a
     {
@@ -371,20 +377,20 @@ impl Thread {
     }
 
     /// Gets a handle to the thread that invokes it.
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     pub fn current() -> Thread {
         thread_info::current_thread()
     }
 
     /// Cooperatively give up a timeslice to the OS scheduler.
-    #[unstable = "name may change"]
+    #[unstable(feature = "std_misc", reason = "name may change")]
     pub fn yield_now() {
         unsafe { imp::yield_now() }
     }
 
     /// Determines whether the current thread is unwinding because of panic.
     #[inline]
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     pub fn panicking() -> bool {
         unwind::panicking()
     }
@@ -398,7 +404,7 @@ impl Thread {
     // future, this will be implemented in a more efficient way, perhaps along the lines of
     //   http://cr.openjdk.java.net/~stefank/6989984.1/raw_files/new/src/os/linux/vm/os_linux.cpp
     // or futuxes, and in either case may allow spurious wakeups.
-    #[unstable = "recently introduced"]
+    #[unstable(feature = "std_misc", reason = "recently introduced")]
     pub fn park() {
         let thread = Thread::current();
         let mut guard = thread.inner.lock.lock().unwrap();
@@ -411,7 +417,7 @@ impl Thread {
     /// Atomically makes the handle's token available if it is not already.
     ///
     /// See the module doc for more detail.
-    #[unstable = "recently introduced"]
+    #[unstable(feature = "std_misc", reason = "recently introduced")]
     pub fn unpark(&self) {
         let mut guard = self.inner.lock.lock().unwrap();
         if !*guard {
@@ -421,7 +427,7 @@ impl Thread {
     }
 
     /// Get the thread's name.
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     pub fn name(&self) -> Option<&str> {
         self.inner.name.as_ref().map(|s| s.as_slice())
     }
@@ -435,7 +441,7 @@ impl thread_info::NewThread for Thread {
 /// Indicates the manner in which a thread exited.
 ///
 /// A thread that completes without panicking is considered to exit successfully.
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 pub type Result<T> = ::result::Result<T, Box<Any + Send>>;
 
 struct Packet<T>(Arc<UnsafeCell<Option<Result<T>>>>);
@@ -447,7 +453,8 @@ unsafe impl<T> Sync for Packet<T> {}
 ///
 /// The type `T` is the return type for the thread's main function.
 #[must_use]
-#[unstable = "may change with specifics of new Send semantics"]
+#[unstable(feature = "std_misc",
+           reason = "may change with specifics of new Send semantics")]
 pub struct JoinGuard<'a, T: 'a> {
     native: imp::rust_thread,
     thread: Thread,
@@ -455,12 +462,12 @@ pub struct JoinGuard<'a, T: 'a> {
     packet: Packet<T>,
 }
 
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 unsafe impl<'a, T: Send + 'a> Sync for JoinGuard<'a, T> {}
 
 impl<'a, T: Send + 'a> JoinGuard<'a, T> {
     /// Extract a handle to the thread this guard will join on.
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     pub fn thread(&self) -> &Thread {
         &self.thread
     }
@@ -470,7 +477,7 @@ impl<'a, T: Send + 'a> JoinGuard<'a, T> {
     ///
     /// If the child thread panics, `Err` is returned with the parameter given
     /// to `panic`.
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     pub fn join(mut self) -> Result<T> {
         assert!(!self.joined);
         unsafe { imp::join(self.native) };
@@ -483,7 +490,8 @@ impl<'a, T: Send + 'a> JoinGuard<'a, T> {
 
 impl<T: Send> JoinGuard<'static, T> {
     /// Detaches the child thread, allowing it to outlive its parent.
-    #[unstable = "unsure whether this API imposes limitations elsewhere"]
+    #[unstable(feature = "std_misc",
+               reason = "unsure whether this API imposes limitations elsewhere")]
     pub fn detach(mut self) {
         unsafe { imp::detach(self.native) };
         self.joined = true; // avoid joining in the destructor
@@ -491,7 +499,7 @@ impl<T: Send> JoinGuard<'static, T> {
 }
 
 #[unsafe_destructor]
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl<'a, T: Send + 'a> Drop for JoinGuard<'a, T> {
     fn drop(&mut self) {
         if !self.joined {
diff --git a/src/libstd/thread_local/mod.rs b/src/libstd/thread_local/mod.rs
index f7a2f8e10e9..2a9bf452329 100644
--- a/src/libstd/thread_local/mod.rs
+++ b/src/libstd/thread_local/mod.rs
@@ -34,7 +34,7 @@
 //! will want to make use of some form of **interior mutability** through the
 //! `Cell` or `RefCell` types.
 
-#![stable]
+#![stable(feature = "rust1", since = "1.0.0")]
 
 use prelude::v1::*;
 
@@ -93,7 +93,7 @@ pub mod __impl {
 ///     assert_eq!(*f.borrow(), 2);
 /// });
 /// ```
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 pub struct Key<T> {
     // The key itself may be tagged with #[thread_local], and this `Key` is
     // stored as a `static`, and it's not valid for a static to reference the
@@ -113,7 +113,7 @@ pub struct Key<T> {
 
 /// Declare a new thread local storage key of type `std::thread_local::Key`.
 #[macro_export]
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 macro_rules! thread_local {
     (static $name:ident: $t:ty = $init:expr) => (
         static $name: ::std::thread_local::Key<$t> = {
@@ -218,7 +218,8 @@ macro_rules! __thread_local_inner {
 }
 
 /// Indicator of the state of a thread local storage key.
-#[unstable = "state querying was recently added"]
+#[unstable(feature = "std_misc",
+           reason = "state querying was recently added")]
 #[derive(Eq, PartialEq, Copy)]
 pub enum State {
     /// All keys are in this state whenever a thread starts. Keys will
@@ -258,7 +259,7 @@ impl<T: 'static> Key<T> {
     /// This function will `panic!()` if the key currently has its
     /// destructor running, and it **may** panic if the destructor has
     /// previously been run for this thread.
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     pub fn with<F, R>(&'static self, f: F) -> R
                       where F: FnOnce(&T) -> R {
         let slot = (self.inner)();
@@ -301,7 +302,8 @@ impl<T: 'static> Key<T> {
     /// initialization does not panic. Keys in the `Valid` state are guaranteed
     /// to be able to be accessed. Keys in the `Destroyed` state will panic on
     /// any call to `with`.
-    #[unstable = "state querying was recently added"]
+    #[unstable(feature = "std_misc",
+               reason = "state querying was recently added")]
     pub fn state(&'static self) -> State {
         unsafe {
             match (self.inner)().get() {
@@ -317,7 +319,9 @@ impl<T: 'static> Key<T> {
     }
 
     /// Deprecated
-    #[deprecated = "function renamed to state() and returns more info"]
+    #[unstable(feature = "std_misc")]
+    #[deprecated(since = "1.0.0",
+                 reason = "function renamed to state() and returns more info")]
     pub fn destroyed(&'static self) -> bool { self.state() == State::Destroyed }
 }
 
diff --git a/src/libstd/thread_local/scoped.rs b/src/libstd/thread_local/scoped.rs
index 1fb5652bc0c..1a20612d60a 100644
--- a/src/libstd/thread_local/scoped.rs
+++ b/src/libstd/thread_local/scoped.rs
@@ -38,8 +38,9 @@
 //! });
 //! ```
 
-#![unstable = "scoped TLS has yet to have wide enough use to fully consider \
-               stabilizing its interface"]
+#![unstable(feature = "std_misc",
+            reason = "scoped TLS has yet to have wide enough use to fully consider \
+                      stabilizing its interface")]
 
 use prelude::v1::*;
 
diff --git a/src/libstd/thunk.rs b/src/libstd/thunk.rs
index 1830a4df54a..2e53d0ceecb 100644
--- a/src/libstd/thunk.rs
+++ b/src/libstd/thunk.rs
@@ -10,6 +10,7 @@
 
 // Because this module is temporary...
 #![allow(missing_docs)]
+#![unstable(feature = "std_misc")]
 
 use alloc::boxed::Box;
 use core::marker::Send;
diff --git a/src/libstd/time/duration.rs b/src/libstd/time/duration.rs
index 2d56a8bcddf..fdd9cbdccf5 100644
--- a/src/libstd/time/duration.rs
+++ b/src/libstd/time/duration.rs
@@ -10,7 +10,7 @@
 
 //! Temporal quantification
 
-#![unstable]
+#![unstable(feature = "std_misc")]
 
 use {fmt, i64};
 use ops::{Add, Sub, Mul, Div, Neg, FnOnce};
@@ -334,7 +334,7 @@ impl Div<i32> for Duration {
     }
 }
 
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl fmt::Display for Duration {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         // technically speaking, negative duration is not valid ISO 8601,
diff --git a/src/libstd/tuple.rs b/src/libstd/tuple.rs
index e76dcef226d..2a911557765 100644
--- a/src/libstd/tuple.rs
+++ b/src/libstd/tuple.rs
@@ -57,4 +57,4 @@
 //! ```
 
 #![doc(primitive = "tuple")]
-#![stable]
+#![stable(feature = "rust1", since = "1.0.0")]
diff --git a/src/libstd/unit.rs b/src/libstd/unit.rs
index 012b175b031..2c3ddcd9d49 100644
--- a/src/libstd/unit.rs
+++ b/src/libstd/unit.rs
@@ -9,7 +9,7 @@
 // except according to those terms.
 
 #![doc(primitive = "unit")]
-#![stable]
+#![stable(feature = "rust1", since = "1.0.0")]
 
 //! The `()` type, sometimes called "unit" or "nil".
 //!
diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs
index 4f6cd8ad356..4dada5bc81e 100644
--- a/src/libsyntax/ast.rs
+++ b/src/libsyntax/ast.rs
@@ -347,6 +347,9 @@ impl AngleBracketedParameterData {
 /// A path like `Foo(A,B) -> C`
 #[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Show)]
 pub struct ParenthesizedParameterData {
+    /// Overall span
+    pub span: Span,
+
     /// `(A,B)`
     pub inputs: Vec<P<Ty>>,
 
diff --git a/src/libsyntax/attr.rs b/src/libsyntax/attr.rs
index 59471488af9..061600d9420 100644
--- a/src/libsyntax/attr.rs
+++ b/src/libsyntax/attr.rs
@@ -21,7 +21,7 @@ use codemap::{Span, Spanned, spanned, dummy_spanned};
 use codemap::BytePos;
 use diagnostic::SpanHandler;
 use parse::lexer::comments::{doc_comment_style, strip_doc_comment_decoration};
-use parse::token::InternedString;
+use parse::token::{InternedString, intern_and_get_ident};
 use parse::token;
 use ptr::P;
 
@@ -56,6 +56,8 @@ pub trait AttrMetaMethods {
     fn value_str(&self) -> Option<InternedString>;
     /// Gets a list of inner meta items from a list MetaItem type.
     fn meta_item_list<'a>(&'a self) -> Option<&'a [P<MetaItem>]>;
+
+    fn span(&self) -> Span;
 }
 
 impl AttrMetaMethods for Attribute {
@@ -73,6 +75,7 @@ impl AttrMetaMethods for Attribute {
     fn meta_item_list<'a>(&'a self) -> Option<&'a [P<MetaItem>]> {
         self.node.value.meta_item_list()
     }
+    fn span(&self) -> Span { self.meta().span }
 }
 
 impl AttrMetaMethods for MetaItem {
@@ -102,6 +105,7 @@ impl AttrMetaMethods for MetaItem {
             _ => None
         }
     }
+    fn span(&self) -> Span { self.span }
 }
 
 // Annoying, but required to get test_cfg to work
@@ -111,6 +115,7 @@ impl AttrMetaMethods for P<MetaItem> {
     fn meta_item_list<'a>(&'a self) -> Option<&'a [P<MetaItem>]> {
         (**self).meta_item_list()
     }
+    fn span(&self) -> Span { (**self).span() }
 }
 
 
@@ -340,22 +345,23 @@ pub fn cfg_matches(diagnostic: &SpanHandler, cfgs: &[P<MetaItem>], cfg: &ast::Me
     }
 }
 
-/// Represents the #[deprecated="foo"] and friends attributes.
+/// Represents the #[deprecated] and friends attributes.
 #[derive(RustcEncodable,RustcDecodable,Clone,Show)]
 pub struct Stability {
     pub level: StabilityLevel,
-    pub text: Option<InternedString>
+    pub feature: InternedString,
+    pub since: Option<InternedString>,
+    pub deprecated_since: Option<InternedString>,
+    // The reason for the current stability level. If deprecated, the
+    // reason for deprecation.
+    pub reason: Option<InternedString>,
 }
 
 /// The available stability levels.
 #[derive(RustcEncodable,RustcDecodable,PartialEq,PartialOrd,Clone,Show,Copy)]
 pub enum StabilityLevel {
-    Deprecated,
-    Experimental,
     Unstable,
     Stable,
-    Frozen,
-    Locked
 }
 
 impl fmt::Display for StabilityLevel {
@@ -364,36 +370,128 @@ impl fmt::Display for StabilityLevel {
     }
 }
 
-pub fn find_stability_generic<'a,
+fn find_stability_generic<'a,
                               AM: AttrMetaMethods,
                               I: Iterator<Item=&'a AM>>
-                             (mut attrs: I)
-                             -> Option<(Stability, &'a AM)> {
-    for attr in attrs {
-        let level = match attr.name().get() {
-            "deprecated" => Deprecated,
-            "experimental" => Experimental,
-            "unstable" => Unstable,
-            "stable" => Stable,
-            "frozen" => Frozen,
-            "locked" => Locked,
-            _ => continue // not a stability level
+                             (diagnostic: &SpanHandler, mut attrs: I, item_sp: Span)
+                             -> (Option<Stability>, Vec<&'a AM>) {
+
+    let mut stab: Option<Stability> = None;
+    let mut deprecated: Option<(InternedString, Option<InternedString>)> = None;
+    let mut used_attrs: Vec<&'a AM> = vec![];
+
+    'outer: for attr in attrs {
+        let tag = attr.name();
+        let tag = tag.get();
+        if tag != "deprecated" && tag != "unstable" && tag != "stable" {
+            continue // not a stability level
+        }
+
+        used_attrs.push(attr);
+
+        let (feature, since, reason) = match attr.meta_item_list() {
+            Some(metas) => {
+                let mut feature = None;
+                let mut since = None;
+                let mut reason = None;
+                for meta in metas.iter() {
+                    if meta.name().get() == "feature" {
+                        match meta.value_str() {
+                            Some(v) => feature = Some(v),
+                            None => {
+                                diagnostic.span_err(meta.span, "incorrect meta item");
+                                continue 'outer;
+                            }
+                        }
+                    }
+                    if meta.name().get() == "since" {
+                        match meta.value_str() {
+                            Some(v) => since = Some(v),
+                            None => {
+                                diagnostic.span_err(meta.span, "incorrect meta item");
+                                continue 'outer;
+                            }
+                        }
+                    }
+                    if meta.name().get() == "reason" {
+                        match meta.value_str() {
+                            Some(v) => reason = Some(v),
+                            None => {
+                                diagnostic.span_err(meta.span, "incorrect meta item");
+                                continue 'outer;
+                            }
+                        }
+                    }
+                }
+                (feature, since, reason)
+            }
+            None => {
+                diagnostic.span_err(attr.span(), "incorrect stability attribute type");
+                continue
+            }
         };
 
-        return Some((Stability {
-            level: level,
-                text: attr.value_str()
-            }, attr));
+        // Deprecated tags don't require feature names
+        if feature == None && tag != "deprecated" {
+            diagnostic.span_err(attr.span(), "missing 'feature'");
+        }
+
+        // Unstable tags don't require a version
+        if since == None && tag != "unstable" {
+            diagnostic.span_err(attr.span(), "missing 'since'");
+        }
+
+        if tag == "unstable" || tag == "stable" {
+            if stab.is_some() {
+                diagnostic.span_err(item_sp, "multiple stability levels");
+            }
+
+            let level = match tag {
+                "unstable" => Unstable,
+                "stable" => Stable,
+                _ => unreachable!()
+            };
+
+            stab = Some(Stability {
+                level: level,
+                feature: feature.unwrap_or(intern_and_get_ident("bogus")),
+                since: since,
+                deprecated_since: None,
+                reason: reason
+            });
+        } else { // "deprecated"
+            if deprecated.is_some() {
+                diagnostic.span_err(item_sp, "multiple deprecated attributes");
+            }
+
+            deprecated = Some((since.unwrap_or(intern_and_get_ident("bogus")), reason));
+        }
     }
-    None
+
+    // Merge the deprecation info into the stability info
+    if deprecated.is_some() {
+        match stab {
+            Some(ref mut s) => {
+                let (since, reason) = deprecated.unwrap();
+                s.deprecated_since = Some(since);
+                s.reason = reason;
+            }
+            None => {
+                diagnostic.span_err(item_sp, "deprecated attribute must be paired with \
+                                              either stable or unstable attribute");
+            }
+        }
+    }
+
+    (stab, used_attrs)
 }
 
 /// Find the first stability attribute. `None` if none exists.
-pub fn find_stability(attrs: &[Attribute]) -> Option<Stability> {
-    find_stability_generic(attrs.iter()).map(|(s, attr)| {
-        mark_used(attr);
-        s
-    })
+pub fn find_stability(diagnostic: &SpanHandler, attrs: &[Attribute],
+                      item_sp: Span) -> Option<Stability> {
+    let (s, used) = find_stability_generic(diagnostic, attrs.iter(), item_sp);
+    for used in used.into_iter() { mark_used(used) }
+    return s;
 }
 
 pub fn require_unique_names(diagnostic: &SpanHandler, metas: &[P<MetaItem>]) {
diff --git a/src/libsyntax/diagnostic.rs b/src/libsyntax/diagnostic.rs
index 5b79cb7b5dd..f3e66897316 100644
--- a/src/libsyntax/diagnostic.rs
+++ b/src/libsyntax/diagnostic.rs
@@ -143,6 +143,7 @@ impl SpanHandler {
 pub struct Handler {
     err_count: Cell<usize>,
     emit: RefCell<Box<Emitter + Send>>,
+    pub can_emit_warnings: bool
 }
 
 impl Handler {
@@ -195,6 +196,7 @@ impl Handler {
                 cmsp: Option<(&codemap::CodeMap, Span)>,
                 msg: &str,
                 lvl: Level) {
+        if lvl == Warning && !self.can_emit_warnings { return }
         self.emit.borrow_mut().emit(cmsp, msg, None, lvl);
     }
     pub fn emit_with_code(&self,
@@ -202,10 +204,12 @@ impl Handler {
                           msg: &str,
                           code: &str,
                           lvl: Level) {
+        if lvl == Warning && !self.can_emit_warnings { return }
         self.emit.borrow_mut().emit(cmsp, msg, Some(code), lvl);
     }
     pub fn custom_emit(&self, cm: &codemap::CodeMap,
                        sp: RenderSpan, msg: &str, lvl: Level) {
+        if lvl == Warning && !self.can_emit_warnings { return }
         self.emit.borrow_mut().custom_emit(cm, sp, msg, lvl);
     }
 }
@@ -218,14 +222,16 @@ pub fn mk_span_handler(handler: Handler, cm: codemap::CodeMap) -> SpanHandler {
 }
 
 pub fn default_handler(color_config: ColorConfig,
-                       registry: Option<diagnostics::registry::Registry>) -> Handler {
-    mk_handler(box EmitterWriter::stderr(color_config, registry))
+                       registry: Option<diagnostics::registry::Registry>,
+                       can_emit_warnings: bool) -> Handler {
+    mk_handler(can_emit_warnings, box EmitterWriter::stderr(color_config, registry))
 }
 
-pub fn mk_handler(e: Box<Emitter + Send>) -> Handler {
+pub fn mk_handler(can_emit_warnings: bool, e: Box<Emitter + Send>) -> Handler {
     Handler {
         err_count: Cell::new(0),
         emit: RefCell::new(e),
+        can_emit_warnings: can_emit_warnings
     }
 }
 
diff --git a/src/libsyntax/ext/base.rs b/src/libsyntax/ext/base.rs
index ef8010927dc..dd89153d497 100644
--- a/src/libsyntax/ext/base.rs
+++ b/src/libsyntax/ext/base.rs
@@ -570,7 +570,9 @@ impl<'a> ExtCtxt<'a> {
         }
     }
 
-    #[deprecated = "Replaced with `expander().fold_expr()`"]
+    #[unstable(feature = "rustc_private")]
+    #[deprecated(since = "1.0.0",
+                 reason = "Replaced with `expander().fold_expr()`")]
     pub fn expand_expr(&mut self, e: P<ast::Expr>) -> P<ast::Expr> {
         self.expander().fold_expr(e)
     }
diff --git a/src/libsyntax/ext/tt/macro_parser.rs b/src/libsyntax/ext/tt/macro_parser.rs
index d115f2ed620..9d5be3fff61 100644
--- a/src/libsyntax/ext/tt/macro_parser.rs
+++ b/src/libsyntax/ext/tt/macro_parser.rs
@@ -83,7 +83,7 @@ use self::TokenTreeOrTokenTreeVec::*;
 use ast;
 use ast::{TokenTree, Ident};
 use ast::{TtDelimited, TtSequence, TtToken};
-use codemap::{BytePos, mk_sp};
+use codemap::{BytePos, mk_sp, Span};
 use codemap;
 use parse::lexer::*; //resolve bug?
 use parse::ParseSess;
@@ -483,11 +483,11 @@ pub fn parse(sess: &ParseSess,
 
                 let mut ei = bb_eis.pop().unwrap();
                 match ei.top_elts.get_tt(ei.idx) {
-                  TtToken(_, MatchNt(_, name, _, _)) => {
+                  TtToken(span, MatchNt(_, name, _, _)) => {
                     let name_string = token::get_ident(name);
                     let match_cur = ei.match_cur;
                     (&mut ei.matches[match_cur]).push(Rc::new(MatchedNonterminal(
-                        parse_nt(&mut rust_parser, name_string.get()))));
+                        parse_nt(&mut rust_parser, span, name_string.get()))));
                     ei.idx += 1us;
                     ei.match_cur += 1;
                   }
@@ -505,7 +505,7 @@ pub fn parse(sess: &ParseSess,
     }
 }
 
-pub fn parse_nt(p: &mut Parser, name: &str) -> Nonterminal {
+pub fn parse_nt(p: &mut Parser, sp: Span, name: &str) -> Nonterminal {
     match name {
         "tt" => {
             p.quote_depth += 1us; //but in theory, non-quoted tts might be useful
@@ -541,7 +541,11 @@ pub fn parse_nt(p: &mut Parser, name: &str) -> Nonterminal {
       }
       "meta" => token::NtMeta(p.parse_meta_item()),
       _ => {
-          p.fatal(&format!("unsupported builtin nonterminal parser: {}", name)[])
+          p.span_fatal_help(sp,
+                            &format!("invalid fragment specifier `{}`", name)[],
+                            "valid fragment specifiers are `ident`, `block`, \
+                             `stmt`, `expr`, `pat`, `ty`, `path`, `meta`, `tt` \
+                             and `item`")
       }
     }
 }
diff --git a/src/libsyntax/ext/tt/macro_rules.rs b/src/libsyntax/ext/tt/macro_rules.rs
index 8350e0222ef..666281ac6b6 100644
--- a/src/libsyntax/ext/tt/macro_rules.rs
+++ b/src/libsyntax/ext/tt/macro_rules.rs
@@ -457,7 +457,7 @@ fn is_in_follow(_: &ExtCtxt, tok: &Token, frag: &str) -> Result<bool, String> {
                 // harmless
                 Ok(true)
             },
-            _ => Err(format!("unrecognized builtin nonterminal `{}`", frag))
+            _ => Err(format!("invalid fragment specifier `{}`", frag))
         }
     }
 }
diff --git a/src/libsyntax/feature_gate.rs b/src/libsyntax/feature_gate.rs
index 762a1dcbfc3..6e797844c18 100644
--- a/src/libsyntax/feature_gate.rs
+++ b/src/libsyntax/feature_gate.rs
@@ -17,6 +17,10 @@
 //!
 //! Features are enabled in programs via the crate-level attributes of
 //! `#![feature(...)]` with a comma-separated list of features.
+//!
+//! For the purpose of future feature-tracking, once code for detection of feature
+//! gate usage is added, *do not remove it again* even once the feature
+//! becomes stable.
 use self::Status::*;
 
 use abi::RustIntrinsic;
@@ -28,82 +32,90 @@ use codemap::{CodeMap, Span};
 use diagnostic::SpanHandler;
 use visit;
 use visit::Visitor;
-use parse::token;
+use parse::token::{self, InternedString};
 
 use std::slice;
 use std::ascii::AsciiExt;
 
-
-// if you change this list without updating src/doc/reference.md, @cmr will be sad
-static KNOWN_FEATURES: &'static [(&'static str, Status)] = &[
-    ("globs", Accepted),
-    ("macro_rules", Accepted),
-    ("struct_variant", Accepted),
-    ("asm", Active),
-    ("managed_boxes", Removed),
-    ("non_ascii_idents", Active),
-    ("thread_local", Active),
-    ("link_args", Active),
-    ("phase", Removed),
-    ("plugin_registrar", Active),
-    ("log_syntax", Active),
-    ("trace_macros", Active),
-    ("concat_idents", Active),
-    ("unsafe_destructor", Active),
-    ("intrinsics", Active),
-    ("lang_items", Active),
-
-    ("simd", Active),
-    ("default_type_params", Accepted),
-    ("quote", Active),
-    ("link_llvm_intrinsics", Active),
-    ("linkage", Active),
-    ("struct_inherit", Removed),
-
-    ("quad_precision_float", Removed),
-
-    ("rustc_diagnostic_macros", Active),
-    ("unboxed_closures", Active),
-    ("import_shadowing", Removed),
-    ("advanced_slice_patterns", Active),
-    ("tuple_indexing", Accepted),
-    ("associated_types", Accepted),
-    ("visible_private_types", Active),
-    ("slicing_syntax", Active),
-    ("box_syntax", Active),
-    ("on_unimplemented", Active),
-    ("simd_ffi", Active),
-
-    ("if_let", Accepted),
-    ("while_let", Accepted),
-
-    ("plugin", Active),
-    ("start", Active),
-    ("main", Active),
+// If you change this list without updating src/doc/reference.md, @cmr will be sad
+// Don't ever remove anything from this list; set them to 'Removed'.
+// The version numbers here correspond to the version in which the current status
+// was set. This is most important for knowing when a particular feature became
+// stable (active).
+// NB: The featureck.py script parses this information directly out of the source
+// so take care when modifying it.
+static KNOWN_FEATURES: &'static [(&'static str, &'static str, Status)] = &[
+    ("globs", "1.0.0", Accepted),
+    ("macro_rules", "1.0.0", Accepted),
+    ("struct_variant", "1.0.0", Accepted),
+    ("asm", "1.0.0", Active),
+    ("managed_boxes", "1.0.0", Removed),
+    ("non_ascii_idents", "1.0.0", Active),
+    ("thread_local", "1.0.0", Active),
+    ("link_args", "1.0.0", Active),
+    ("phase", "1.0.0", Removed),
+    ("plugin_registrar", "1.0.0", Active),
+    ("log_syntax", "1.0.0", Active),
+    ("trace_macros", "1.0.0", Active),
+    ("concat_idents", "1.0.0", Active),
+    ("unsafe_destructor", "1.0.0", Active),
+    ("intrinsics", "1.0.0", Active),
+    ("lang_items", "1.0.0", Active),
+
+    ("simd", "1.0.0", Active),
+    ("default_type_params", "1.0.0", Accepted),
+    ("quote", "1.0.0", Active),
+    ("link_llvm_intrinsics", "1.0.0", Active),
+    ("linkage", "1.0.0", Active),
+    ("struct_inherit", "1.0.0", Removed),
+
+    ("quad_precision_float", "1.0.0", Removed),
+
+    ("rustc_diagnostic_macros", "1.0.0", Active),
+    ("unboxed_closures", "1.0.0", Active),
+    ("import_shadowing", "1.0.0", Removed),
+    ("advanced_slice_patterns", "1.0.0", Active),
+    ("tuple_indexing", "1.0.0", Accepted),
+    ("associated_types", "1.0.0", Accepted),
+    ("visible_private_types", "1.0.0", Active),
+    ("slicing_syntax", "1.0.0", Active),
+    ("box_syntax", "1.0.0", Active),
+    ("on_unimplemented", "1.0.0", Active),
+    ("simd_ffi", "1.0.0", Active),
+
+    ("if_let", "1.0.0", Accepted),
+    ("while_let", "1.0.0", Accepted),
+
+    ("plugin", "1.0.0", Active),
+    ("start", "1.0.0", Active),
+    ("main", "1.0.0", Active),
 
     // A temporary feature gate used to enable parser extensions needed
     // to bootstrap fix for #5723.
-    ("issue_5723_bootstrap", Accepted),
+    ("issue_5723_bootstrap", "1.0.0", Accepted),
 
     // A way to temporarily opt out of opt in copy. This will *never* be accepted.
-    ("opt_out_copy", Removed),
+    ("opt_out_copy", "1.0.0", Removed),
 
     // A way to temporarily opt out of the new orphan rules. This will *never* be accepted.
-    ("old_orphan_check", Deprecated),
+    ("old_orphan_check", "1.0.0", Deprecated),
 
     // A way to temporarily opt out of the new impl rules. This will *never* be accepted.
-    ("old_impl_check", Deprecated),
+    ("old_impl_check", "1.0.0", Deprecated),
 
     // OIBIT specific features
-    ("optin_builtin_traits", Active),
+    ("optin_builtin_traits", "1.0.0", Active),
 
     // int and uint are now deprecated
-    ("int_uint", Active),
+    ("int_uint", "1.0.0", Active),
 
     // These are used to test this portion of the compiler, they don't actually
     // mean anything
-    ("test_accepted_feature", Accepted),
-    ("test_removed_feature", Removed),
+    ("test_accepted_feature", "1.0.0", Accepted),
+    ("test_removed_feature", "1.0.0", Removed),
+
+    // Allows use of #[staged_api]
+    ("staged_api", "1.0.0", Active),
 ];
 
 enum Status {
@@ -123,7 +135,6 @@ enum Status {
 }
 
 /// A set of features to be used by later passes.
-#[derive(Copy)]
 pub struct Features {
     pub unboxed_closures: bool,
     pub rustc_diagnostic_macros: bool,
@@ -131,6 +142,7 @@ pub struct Features {
     pub quote: bool,
     pub old_orphan_check: bool,
     pub simd_ffi: bool,
+    pub lib_features: Vec<(InternedString, Span)>
 }
 
 impl Features {
@@ -142,6 +154,7 @@ impl Features {
             quote: false,
             old_orphan_check: false,
             simd_ffi: false,
+            lib_features: Vec::new()
         }
     }
 }
@@ -155,19 +168,13 @@ struct Context<'a> {
 impl<'a> Context<'a> {
     fn gate_feature(&self, feature: &str, span: Span, explain: &str) {
         if !self.has_feature(feature) {
-            self.span_handler.span_err(span, explain);
-            self.span_handler.span_help(span, &format!("add #![feature({})] to the \
-                                                       crate attributes to enable",
-                                                      feature)[]);
+            emit_feature_err(self.span_handler, feature, span, explain);
         }
     }
 
     fn warn_feature(&self, feature: &str, span: Span, explain: &str) {
         if !self.has_feature(feature) {
-            self.span_handler.span_warn(span, explain);
-            self.span_handler.span_help(span, &format!("add #![feature({})] to the \
-                                                       crate attributes to silence this warning",
-                                                      feature)[]);
+            emit_feature_warn(self.span_handler, feature, span, explain);
         }
     }
     fn has_feature(&self, feature: &str) -> bool {
@@ -175,6 +182,22 @@ impl<'a> Context<'a> {
     }
 }
 
+pub fn emit_feature_err(diag: &SpanHandler, feature: &str, span: Span, explain: &str) {
+    diag.span_err(span, explain);
+    diag.span_help(span, &format!("add #![feature({})] to the \
+                                   crate attributes to enable",
+                                  feature)[]);
+}
+
+pub fn emit_feature_warn(diag: &SpanHandler, feature: &str, span: Span, explain: &str) {
+    diag.span_warn(span, explain);
+    if diag.handler.can_emit_warnings {
+        diag.span_help(span, &format!("add #![feature({})] to the \
+                                       crate attributes to silence this warning",
+                                      feature)[]);
+    }
+}
+
 struct MacroVisitor<'a> {
     context: &'a Context<'a>
 }
@@ -416,6 +439,11 @@ impl<'a, 'v> Visitor<'v> for PostExpansionVisitor<'a> {
     }
 
     fn visit_attribute(&mut self, attr: &ast::Attribute) {
+        if attr.check_name("staged_api") {
+            self.gate_feature("staged_api", attr.span,
+                              "staged_api is for use by rustc only");
+        }
+
         if attr::contains_name(slice::ref_slice(attr), "lang") {
             self.gate_feature("lang_items",
                               attr.span,
@@ -462,7 +490,7 @@ impl<'a, 'v> Visitor<'v> for PostExpansionVisitor<'a> {
 
 fn check_crate_inner<F>(cm: &CodeMap, span_handler: &SpanHandler, krate: &ast::Crate,
                         check: F)
-                       -> (Features, Vec<Span>)
+                       -> Features
     where F: FnOnce(&mut Context, &ast::Crate)
 {
     let mut cx = Context {
@@ -495,26 +523,26 @@ fn check_crate_inner<F>(cm: &CodeMap, span_handler: &SpanHandler, krate: &ast::C
                         }
                     };
                     match KNOWN_FEATURES.iter()
-                                        .find(|& &(n, _)| name == n) {
-                        Some(&(name, Active)) => {
+                                        .find(|& &(n, _, _)| name == n) {
+                        Some(&(name, _, Active)) => {
                             cx.features.push(name);
                         }
-                        Some(&(name, Deprecated)) => {
+                        Some(&(name, _, Deprecated)) => {
                             cx.features.push(name);
                             span_handler.span_warn(
                                 mi.span,
                                 "feature is deprecated and will only be available \
                                  for a limited time, please rewrite code that relies on it");
                         }
-                        Some(&(_, Removed)) => {
+                        Some(&(_, _, Removed)) => {
                             span_handler.span_err(mi.span, "feature has been removed");
                         }
-                        Some(&(_, Accepted)) => {
+                        Some(&(_, _, Accepted)) => {
                             span_handler.span_warn(mi.span, "feature has been added to Rust, \
                                                              directive not necessary");
                         }
                         None => {
-                            unknown_features.push(mi.span);
+                            unknown_features.push((name, mi.span));
                         }
                     }
                 }
@@ -524,26 +552,27 @@ fn check_crate_inner<F>(cm: &CodeMap, span_handler: &SpanHandler, krate: &ast::C
 
     check(&mut cx, krate);
 
-    (Features {
+    Features {
         unboxed_closures: cx.has_feature("unboxed_closures"),
         rustc_diagnostic_macros: cx.has_feature("rustc_diagnostic_macros"),
         visible_private_types: cx.has_feature("visible_private_types"),
         quote: cx.has_feature("quote"),
         old_orphan_check: cx.has_feature("old_orphan_check"),
         simd_ffi: cx.has_feature("simd_ffi"),
-    },
-    unknown_features)
+        lib_features: unknown_features
+    }
 }
 
 pub fn check_crate_macros(cm: &CodeMap, span_handler: &SpanHandler, krate: &ast::Crate)
--> (Features, Vec<Span>) {
+-> Features {
     check_crate_inner(cm, span_handler, krate,
                       |ctx, krate| visit::walk_crate(&mut MacroVisitor { context: ctx }, krate))
 }
 
 pub fn check_crate(cm: &CodeMap, span_handler: &SpanHandler, krate: &ast::Crate)
--> (Features, Vec<Span>) {
+-> Features {
     check_crate_inner(cm, span_handler, krate,
                       |ctx, krate| visit::walk_crate(&mut PostExpansionVisitor { context: ctx },
                                                      krate))
 }
+
diff --git a/src/libsyntax/fold.rs b/src/libsyntax/fold.rs
index bf822599a88..a1362f5382c 100644
--- a/src/libsyntax/fold.rs
+++ b/src/libsyntax/fold.rs
@@ -536,9 +536,10 @@ pub fn noop_fold_parenthesized_parameter_data<T: Folder>(data: ParenthesizedPara
                                                          fld: &mut T)
                                                          -> ParenthesizedParameterData
 {
-    let ParenthesizedParameterData { inputs, output } = data;
+    let ParenthesizedParameterData { inputs, output, span } = data;
     ParenthesizedParameterData { inputs: inputs.move_map(|ty| fld.fold_ty(ty)),
-                                 output: output.map(|ty| fld.fold_ty(ty)) }
+                                 output: output.map(|ty| fld.fold_ty(ty)),
+                                 span: fld.new_span(span) }
 }
 
 pub fn noop_fold_local<T: Folder>(l: P<Local>, fld: &mut T) -> P<Local> {
diff --git a/src/libsyntax/lib.rs b/src/libsyntax/lib.rs
index fa675a9fcaa..ff4c7b565cb 100644
--- a/src/libsyntax/lib.rs
+++ b/src/libsyntax/lib.rs
@@ -15,7 +15,8 @@
 //! This API is completely unstable and subject to change.
 
 #![crate_name = "syntax"]
-#![unstable]
+#![unstable(feature = "rustc_private")]
+#![feature(staged_api)]
 #![staged_api]
 #![crate_type = "dylib"]
 #![crate_type = "rlib"]
@@ -28,7 +29,16 @@
 #![feature(box_syntax)]
 #![feature(quote, unsafe_destructor)]
 #![allow(unknown_features)] #![feature(int_uint)]
-#![allow(unstable)]
+#![feature(collections)]
+#![feature(core)]
+#![feature(hash)]
+#![feature(io)]
+#![feature(libc)]
+#![feature(os)]
+#![feature(path)]
+#![feature(rustc_private)]
+#![feature(std_misc)]
+#![feature(unicode)]
 
 extern crate arena;
 extern crate fmt_macros;
diff --git a/src/libsyntax/parse/lexer/mod.rs b/src/libsyntax/parse/lexer/mod.rs
index 92a89c17579..99be1b11b11 100644
--- a/src/libsyntax/parse/lexer/mod.rs
+++ b/src/libsyntax/parse/lexer/mod.rs
@@ -1486,7 +1486,7 @@ mod test {
 
     fn mk_sh() -> diagnostic::SpanHandler {
         let emitter = diagnostic::EmitterWriter::new(box util::NullWriter, None);
-        let handler = diagnostic::mk_handler(box emitter);
+        let handler = diagnostic::mk_handler(true, box emitter);
         diagnostic::mk_span_handler(handler, CodeMap::new())
     }
 
diff --git a/src/libsyntax/parse/mod.rs b/src/libsyntax/parse/mod.rs
index 2b4087dba58..4bd476885a0 100644
--- a/src/libsyntax/parse/mod.rs
+++ b/src/libsyntax/parse/mod.rs
@@ -45,7 +45,7 @@ pub struct ParseSess {
 
 pub fn new_parse_sess() -> ParseSess {
     ParseSess {
-        span_diagnostic: mk_span_handler(default_handler(Auto, None), CodeMap::new()),
+        span_diagnostic: mk_span_handler(default_handler(Auto, None, true), CodeMap::new()),
         included_mod_stack: RefCell::new(Vec::new()),
         node_id: Cell::new(1),
     }
diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs
index fbea265597c..4c1ae532d13 100644
--- a/src/libsyntax/parse/parser.rs
+++ b/src/libsyntax/parse/parser.rs
@@ -1796,6 +1796,8 @@ impl<'a> Parser<'a> {
                     bindings: OwnedSlice::from_vec(bindings),
                 })
             } else if self.eat(&token::OpenDelim(token::Paren)) {
+                let lo = self.last_span.lo;
+
                 let inputs = self.parse_seq_to_end(
                     &token::CloseDelim(token::Paren),
                     seq_sep_trailing_allowed(token::Comma),
@@ -1807,9 +1809,12 @@ impl<'a> Parser<'a> {
                     None
                 };
 
+                let hi = self.last_span.hi;
+
                 ast::ParenthesizedParameters(ast::ParenthesizedParameterData {
+                    span: mk_sp(lo, hi),
                     inputs: inputs,
-                    output: output_ty
+                    output: output_ty,
                 })
             } else {
                 ast::PathParameters::none()
diff --git a/src/libsyntax/test.rs b/src/libsyntax/test.rs
index 8933d3a9669..a7679adca2e 100644
--- a/src/libsyntax/test.rs
+++ b/src/libsyntax/test.rs
@@ -279,6 +279,24 @@ fn strip_test_functions(krate: ast::Crate) -> ast::Crate {
     })
 }
 
+/// Craft a span that will be ignored by the stability lint's
+/// call to codemap's is_internal check.
+/// The expanded code calls some unstable functions in the test crate.
+fn ignored_span(cx: &TestCtxt, sp: Span) -> Span {
+    let info = ExpnInfo {
+        call_site: DUMMY_SP,
+        callee: NameAndSpan {
+            name: "test".to_string(),
+            format: MacroAttribute,
+            span: None
+        }
+    };
+    let expn_id = cx.sess.span_diagnostic.cm.record_expansion(info);
+    let mut sp = sp;
+    sp.expn_id = expn_id;
+    return sp;
+}
+
 #[derive(PartialEq)]
 enum HasTestSignature {
     Yes,
@@ -407,6 +425,65 @@ fn mk_std(cx: &TestCtxt) -> P<ast::Item> {
     })
 }
 
+fn mk_main(cx: &mut TestCtxt) -> P<ast::Item> {
+    // Writing this out by hand with 'ignored_span':
+    //        pub fn main() {
+    //            #![main]
+    //            use std::slice::AsSlice;
+    //            test::test_main_static(::std::os::args().as_slice(), TESTS);
+    //        }
+
+    let sp = ignored_span(cx, DUMMY_SP);
+    let ecx = &cx.ext_cx;
+
+    // std::slice::AsSlice
+    let as_slice_path = ecx.path(sp, vec![token::str_to_ident("std"),
+                                          token::str_to_ident("slice"),
+                                          token::str_to_ident("AsSlice")]);
+    // test::test_main_static
+    let test_main_path = ecx.path(sp, vec![token::str_to_ident("test"),
+                                           token::str_to_ident("test_main_static")]);
+    // ::std::os::args
+    let os_args_path = ecx.path_global(sp, vec![token::str_to_ident("std"),
+                                                token::str_to_ident("os"),
+                                                token::str_to_ident("args")]);
+    // use std::slice::AsSlice
+    let as_slice_path = P(nospan(ast::ViewPathSimple(token::str_to_ident("AsSlice"),
+                                                     as_slice_path)));
+    let use_as_slice = ecx.item_use(sp, ast::Inherited, as_slice_path);
+    let use_as_slice = ecx.stmt_item(sp, use_as_slice);
+    // ::std::os::args()
+    let os_args_path_expr = ecx.expr_path(os_args_path);
+    let call_os_args = ecx.expr_call(sp, os_args_path_expr, vec![]);
+    // ::std::os::args().as_slice()
+    let call_as_slice = ecx.expr_method_call(sp, call_os_args,
+                                             token::str_to_ident("as_slice"), vec![]);
+    // test::test_main_static(...)
+    let test_main_path_expr = ecx.expr_path(test_main_path);
+    let tests_ident_expr = ecx.expr_ident(sp, token::str_to_ident("TESTS"));
+    let call_test_main = ecx.expr_call(sp, test_main_path_expr,
+                                       vec![call_as_slice, tests_ident_expr]);
+    let call_test_main = ecx.stmt_expr(call_test_main);
+    // #![main]
+    let main_meta = ecx.meta_word(sp, token::intern_and_get_ident("main"));
+    let main_attr = ecx.attribute(sp, main_meta);
+    // pub fn main() { ... }
+    let main_ret_ty = ecx.ty(sp, ast::TyTup(vec![]));
+    let main_body = ecx.block_all(sp, vec![use_as_slice, call_test_main], None);
+    let main = ast::ItemFn(ecx.fn_decl(vec![], main_ret_ty),
+                           ast::Unsafety::Normal, ::abi::Rust, empty_generics(), main_body);
+    let main = P(ast::Item {
+        ident: token::str_to_ident("main"),
+        attrs: vec![main_attr],
+        id: ast::DUMMY_NODE_ID,
+        node: main,
+        vis: ast::Public,
+        span: sp
+    });
+
+    return main;
+}
+
 fn mk_test_module(cx: &mut TestCtxt) -> (P<ast::Item>, Option<P<ast::Item>>) {
     // Link to test crate
     let import = mk_std(cx);
@@ -416,13 +493,7 @@ fn mk_test_module(cx: &mut TestCtxt) -> (P<ast::Item>, Option<P<ast::Item>>) {
 
     // The synthesized main function which will call the console test runner
     // with our list of tests
-    let mainfn = (quote_item!(&mut cx.ext_cx,
-        pub fn main() {
-            #![main]
-            use std::slice::AsSlice;
-            test::test_main_static(::std::os::args().as_slice(), TESTS);
-        }
-    )).unwrap();
+    let mainfn = mk_main(cx);
 
     let testmod = ast::Mod {
         inner: DUMMY_SP,
@@ -431,16 +502,10 @@ fn mk_test_module(cx: &mut TestCtxt) -> (P<ast::Item>, Option<P<ast::Item>>) {
     let item_ = ast::ItemMod(testmod);
 
     let mod_ident = token::gensym_ident("__test");
-    let allow_unstable = {
-        let unstable = P(nospan(ast::MetaWord(InternedString::new("unstable"))));
-        let allow = P(nospan(ast::MetaList(InternedString::new("allow"),
-                                           vec![unstable])));
-        attr::mk_attr_inner(attr::mk_attr_id(), allow)
-    };
     let item = P(ast::Item {
         id: ast::DUMMY_NODE_ID,
         ident: mod_ident,
-        attrs: vec![allow_unstable],
+        attrs: vec![],
         node: item_,
         vis: ast::Public,
         span: DUMMY_SP,
@@ -537,7 +602,7 @@ fn mk_test_desc_and_fn_rec(cx: &TestCtxt, test: &Test) -> P<ast::Expr> {
     // __test_reexports, causing it to be reinterned, losing the
     // gensym information.
 
-    let span = test.span;
+    let span = ignored_span(cx, test.span);
     let path = test.path.clone();
     let ecx = &cx.ext_cx;
     let self_id = ecx.ident_of("self");
diff --git a/src/libsyntax/util/small_vector.rs b/src/libsyntax/util/small_vector.rs
index d8bac19805b..21a7d680847 100644
--- a/src/libsyntax/util/small_vector.rs
+++ b/src/libsyntax/util/small_vector.rs
@@ -112,7 +112,8 @@ impl<T> SmallVector<T> {
     }
 
     /// Deprecated: use `into_iter`.
-    #[deprecated = "use into_iter"]
+    #[unstable(feature = "rustc_private")]
+    #[deprecated(since = "1.0.0", reason = "use into_iter")]
     pub fn move_iter(self) -> IntoIter<T> {
         self.into_iter()
     }
diff --git a/src/libterm/lib.rs b/src/libterm/lib.rs
index 94c810833fc..aa3af76d46c 100644
--- a/src/libterm/lib.rs
+++ b/src/libterm/lib.rs
@@ -39,7 +39,9 @@
 //! [ti]: https://en.wikipedia.org/wiki/Terminfo
 
 #![crate_name = "term"]
-#![unstable = "use the crates.io `term` library instead"]
+#![unstable(feature = "rustc_private",
+            reason = "use the crates.io `term` library instead")]
+#![feature(staged_api)]
 #![staged_api]
 #![crate_type = "rlib"]
 #![crate_type = "dylib"]
@@ -52,8 +54,15 @@
 #![feature(slicing_syntax)]
 #![feature(box_syntax)]
 #![allow(unknown_features)] #![feature(int_uint)]
-#![allow(unstable)]
 #![deny(missing_docs)]
+#![feature(collections)]
+#![feature(core)]
+#![feature(io)]
+#![feature(os)]
+#![feature(path)]
+#![feature(rustc_private)]
+#![feature(std_misc)]
+#![feature(unicode)]
 
 #[macro_use] extern crate log;
 
diff --git a/src/libtest/lib.rs b/src/libtest/lib.rs
index 2e59b15b6d9..43a1bbd6c02 100644
--- a/src/libtest/lib.rs
+++ b/src/libtest/lib.rs
@@ -24,7 +24,8 @@
 // build off of.
 
 #![crate_name = "test"]
-#![unstable]
+#![unstable(feature = "test")]
+#![feature(staged_api)]
 #![staged_api]
 #![crate_type = "rlib"]
 #![crate_type = "dylib"]
@@ -35,7 +36,14 @@
 #![feature(asm, slicing_syntax)]
 #![feature(box_syntax)]
 #![allow(unknown_features)] #![feature(int_uint)]
-#![allow(unstable)]
+#![feature(collections)]
+#![feature(core)]
+#![feature(io)]
+#![feature(os)]
+#![feature(path)]
+#![feature(rustc_private)]
+#![feature(std_misc)]
+#![feature(hash)]
 
 extern crate getopts;
 extern crate serialize;
diff --git a/src/libunicode/lib.rs b/src/libunicode/lib.rs
index d812d249c5b..02f738c9d29 100644
--- a/src/libunicode/lib.rs
+++ b/src/libunicode/lib.rs
@@ -21,7 +21,8 @@
 //! (yet) aim to provide a full set of Unicode tables.
 
 #![crate_name = "unicode"]
-#![unstable]
+#![unstable(feature = "unicode")]
+#![feature(staged_api)]
 #![staged_api]
 #![crate_type = "rlib"]
 #![doc(html_logo_url = "http://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
@@ -31,7 +32,7 @@
 #![no_std]
 #![feature(slicing_syntax)]
 #![allow(unknown_features)] #![feature(int_uint)]
-#![allow(unstable)]
+#![feature(core)]
 
 extern crate core;
 
@@ -59,7 +60,7 @@ mod u_str;
 /// (inclusive) are allowed. A `char` can always be safely cast to a `u32`;
 /// however the converse is not always true due to the above range limits
 /// and, as such, should be performed via the `from_u32` function..
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 pub mod char {
     pub use core::char::{MAX, from_u32, from_digit};
 
diff --git a/src/libunicode/u_char.rs b/src/libunicode/u_char.rs
index 4142a62ba66..467fed5d246 100644
--- a/src/libunicode/u_char.rs
+++ b/src/libunicode/u_char.rs
@@ -19,7 +19,7 @@ use core::option::Option;
 use tables::{derived_property, property, general_category, conversions, charwidth};
 
 /// Functionality for manipulating `char`.
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 pub trait CharExt {
     /// Checks if a `char` parses as a numeric digit in the given radix.
     ///
@@ -34,7 +34,8 @@ pub trait CharExt {
     /// # Panics
     ///
     /// Panics if given a radix > 36.
-    #[unstable = "pending integer conventions"]
+    #[unstable(feature = "unicode",
+               reason = "pending integer conventions")]
     fn is_digit(self, radix: uint) -> bool;
 
     /// Converts a character to the corresponding digit.
@@ -48,7 +49,8 @@ pub trait CharExt {
     /// # Panics
     ///
     /// Panics if given a radix outside the range [0..36].
-    #[unstable = "pending integer conventions"]
+    #[unstable(feature = "unicode",
+               reason = "pending integer conventions")]
     fn to_digit(self, radix: uint) -> Option<uint>;
 
     /// Returns an iterator that yields the hexadecimal Unicode escape
@@ -57,7 +59,7 @@ pub trait CharExt {
     /// All characters are escaped with Rust syntax of the form `\\u{NNNN}`
     /// where `NNNN` is the shortest hexadecimal representation of the code
     /// point.
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     fn escape_unicode(self) -> char::EscapeUnicode;
 
     /// Returns an iterator that yields the 'default' ASCII and
@@ -72,17 +74,17 @@ pub trait CharExt {
     ///   escaped.
     /// * Any other chars in the range [0x20,0x7e] are not escaped.
     /// * Any other chars are given hex Unicode escapes; see `escape_unicode`.
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     fn escape_default(self) -> char::EscapeDefault;
 
     /// Returns the amount of bytes this character would need if encoded in
     /// UTF-8.
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     fn len_utf8(self) -> uint;
 
     /// Returns the amount of bytes this character would need if encoded in
     /// UTF-16.
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     fn len_utf16(self) -> uint;
 
     /// Encodes this character as UTF-8 into the provided byte buffer,
@@ -90,7 +92,8 @@ pub trait CharExt {
     ///
     /// If the buffer is not large enough, nothing will be written into it
     /// and a `None` will be returned.
-    #[unstable = "pending decision about Iterator/Writer/Reader"]
+    #[unstable(feature = "unicode",
+               reason = "pending decision about Iterator/Writer/Reader")]
     fn encode_utf8(self, dst: &mut [u8]) -> Option<uint>;
 
     /// Encodes this character as UTF-16 into the provided `u16` buffer,
@@ -98,12 +101,13 @@ pub trait CharExt {
     ///
     /// If the buffer is not large enough, nothing will be written into it
     /// and a `None` will be returned.
-    #[unstable = "pending decision about Iterator/Writer/Reader"]
+    #[unstable(feature = "unicode",
+               reason = "pending decision about Iterator/Writer/Reader")]
     fn encode_utf16(self, dst: &mut [u16]) -> Option<uint>;
 
     /// Returns whether the specified character is considered a Unicode
     /// alphabetic code point.
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     fn is_alphabetic(self) -> bool;
 
     /// Returns whether the specified character satisfies the 'XID_Start'
@@ -112,7 +116,8 @@ pub trait CharExt {
     /// 'XID_Start' is a Unicode Derived Property specified in
     /// [UAX #31](http://unicode.org/reports/tr31/#NFKC_Modifications),
     /// mostly similar to ID_Start but modified for closure under NFKx.
-    #[unstable = "mainly needed for compiler internals"]
+    #[unstable(feature = "unicode",
+               reason = "mainly needed for compiler internals")]
     fn is_xid_start(self) -> bool;
 
     /// Returns whether the specified `char` satisfies the 'XID_Continue'
@@ -121,45 +126,46 @@ pub trait CharExt {
     /// 'XID_Continue' is a Unicode Derived Property specified in
     /// [UAX #31](http://unicode.org/reports/tr31/#NFKC_Modifications),
     /// mostly similar to 'ID_Continue' but modified for closure under NFKx.
-    #[unstable = "mainly needed for compiler internals"]
+    #[unstable(feature = "unicode",
+               reason = "mainly needed for compiler internals")]
     fn is_xid_continue(self) -> bool;
 
     /// Indicates whether a character is in lowercase.
     ///
     /// This is defined according to the terms of the Unicode Derived Core
     /// Property `Lowercase`.
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     fn is_lowercase(self) -> bool;
 
     /// Indicates whether a character is in uppercase.
     ///
     /// This is defined according to the terms of the Unicode Derived Core
     /// Property `Uppercase`.
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     fn is_uppercase(self) -> bool;
 
     /// Indicates whether a character is whitespace.
     ///
     /// Whitespace is defined in terms of the Unicode Property `White_Space`.
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     fn is_whitespace(self) -> bool;
 
     /// Indicates whether a character is alphanumeric.
     ///
     /// Alphanumericness is defined in terms of the Unicode General Categories
     /// 'Nd', 'Nl', 'No' and the Derived Core Property 'Alphabetic'.
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     fn is_alphanumeric(self) -> bool;
 
     /// Indicates whether a character is a control code point.
     ///
     /// Control code points are defined in terms of the Unicode General
     /// Category `Cc`.
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     fn is_control(self) -> bool;
 
     /// Indicates whether the character is numeric (Nd, Nl, or No).
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     fn is_numeric(self) -> bool;
 
     /// Converts a character to its lowercase equivalent.
@@ -171,7 +177,8 @@ pub trait CharExt {
     ///
     /// Returns the lowercase equivalent of the character, or the character
     /// itself if no conversion is possible.
-    #[unstable = "pending case transformation decisions"]
+    #[unstable(feature = "unicode",
+               reason = "pending case transformation decisions")]
     fn to_lowercase(self) -> char;
 
     /// Converts a character to its uppercase equivalent.
@@ -194,7 +201,8 @@ pub trait CharExt {
     /// [`SpecialCasing`.txt`]: ftp://ftp.unicode.org/Public/UNIDATA/SpecialCasing.txt
     ///
     /// [2]: http://www.unicode.org/versions/Unicode4.0.0/ch03.pdf#G33992
-    #[unstable = "pending case transformation decisions"]
+    #[unstable(feature = "unicode",
+               reason = "pending case transformation decisions")]
     fn to_uppercase(self) -> char;
 
     /// Returns this character's displayed width in columns, or `None` if it is a
@@ -206,30 +214,35 @@ pub trait CharExt {
     /// [Unicode Standard Annex #11](http://www.unicode.org/reports/tr11/)
     /// recommends that these characters be treated as 1 column (i.e.,
     /// `is_cjk` = `false`) if the context cannot be reliably determined.
-    #[unstable = "needs expert opinion. is_cjk flag stands out as ugly"]
+    #[unstable(feature = "unicode",
+               reason = "needs expert opinion. is_cjk flag stands out as ugly")]
     fn width(self, is_cjk: bool) -> Option<uint>;
 }
 
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 impl CharExt for char {
-    #[unstable = "pending integer conventions"]
+    #[unstable(feature = "unicode",
+               reason = "pending integer conventions")]
     fn is_digit(self, radix: uint) -> bool { C::is_digit(self, radix) }
-    #[unstable = "pending integer conventions"]
+    #[unstable(feature = "unicode",
+               reason = "pending integer conventions")]
     fn to_digit(self, radix: uint) -> Option<uint> { C::to_digit(self, radix) }
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     fn escape_unicode(self) -> char::EscapeUnicode { C::escape_unicode(self) }
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     fn escape_default(self) -> char::EscapeDefault { C::escape_default(self) }
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     fn len_utf8(self) -> uint { C::len_utf8(self) }
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     fn len_utf16(self) -> uint { C::len_utf16(self) }
-    #[unstable = "pending decision about Iterator/Writer/Reader"]
+    #[unstable(feature = "unicode",
+               reason = "pending decision about Iterator/Writer/Reader")]
     fn encode_utf8(self, dst: &mut [u8]) -> Option<uint> { C::encode_utf8(self, dst) }
-    #[unstable = "pending decision about Iterator/Writer/Reader"]
+    #[unstable(feature = "unicode",
+               reason = "pending decision about Iterator/Writer/Reader")]
     fn encode_utf16(self, dst: &mut [u16]) -> Option<uint> { C::encode_utf16(self, dst) }
 
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     fn is_alphabetic(self) -> bool {
         match self {
             'a' ... 'z' | 'A' ... 'Z' => true,
@@ -238,13 +251,15 @@ impl CharExt for char {
         }
     }
 
-    #[unstable = "mainly needed for compiler internals"]
+    #[unstable(feature = "unicode",
+               reason = "mainly needed for compiler internals")]
     fn is_xid_start(self) -> bool { derived_property::XID_Start(self) }
 
-    #[unstable = "mainly needed for compiler internals"]
+    #[unstable(feature = "unicode",
+               reason = "mainly needed for compiler internals")]
     fn is_xid_continue(self) -> bool { derived_property::XID_Continue(self) }
 
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     fn is_lowercase(self) -> bool {
         match self {
             'a' ... 'z' => true,
@@ -253,7 +268,7 @@ impl CharExt for char {
         }
     }
 
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     fn is_uppercase(self) -> bool {
         match self {
             'A' ... 'Z' => true,
@@ -262,7 +277,7 @@ impl CharExt for char {
         }
     }
 
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     fn is_whitespace(self) -> bool {
         match self {
             ' ' | '\x09' ... '\x0d' => true,
@@ -271,15 +286,15 @@ impl CharExt for char {
         }
     }
 
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     fn is_alphanumeric(self) -> bool {
         self.is_alphabetic() || self.is_numeric()
     }
 
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     fn is_control(self) -> bool { general_category::Cc(self) }
 
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     fn is_numeric(self) -> bool {
         match self {
             '0' ... '9' => true,
@@ -288,12 +303,15 @@ impl CharExt for char {
         }
     }
 
-    #[unstable = "pending case transformation decisions"]
+    #[unstable(feature = "unicode",
+               reason = "pending case transformation decisions")]
     fn to_lowercase(self) -> char { conversions::to_lower(self) }
 
-    #[unstable = "pending case transformation decisions"]
+    #[unstable(feature = "unicode",
+               reason = "pending case transformation decisions")]
     fn to_uppercase(self) -> char { conversions::to_upper(self) }
 
-    #[unstable = "needs expert opinion. is_cjk flag stands out as ugly"]
+    #[unstable(feature = "unicode",
+               reason = "needs expert opinion. is_cjk flag stands out as ugly")]
     fn width(self, is_cjk: bool) -> Option<uint> { charwidth::width(self, is_cjk) }
 }
diff --git a/src/libunicode/u_str.rs b/src/libunicode/u_str.rs
index cf19e019f03..b4bafe31ff2 100644
--- a/src/libunicode/u_str.rs
+++ b/src/libunicode/u_str.rs
@@ -30,7 +30,7 @@ use u_char::CharExt as UCharExt; // conflicts with core::prelude::CharExt
 use tables::grapheme::GraphemeCat;
 
 /// An iterator over the words of a string, separated by a sequence of whitespace
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 pub struct Words<'a> {
     inner: Filter<&'a str, Split<'a, fn(char) -> bool>, fn(&&str) -> bool>,
 }
diff --git a/src/rustbook/main.rs b/src/rustbook/main.rs
index cbd29004097..3e571bad09c 100644
--- a/src/rustbook/main.rs
+++ b/src/rustbook/main.rs
@@ -9,7 +9,12 @@
 // except according to those terms.
 
 #![feature(slicing_syntax, box_syntax)]
-#![allow(unstable)]
+#![feature(collections)]
+#![feature(core)]
+#![feature(io)]
+#![feature(os)]
+#![feature(path)]
+#![feature(rustdoc)]
 
 extern crate rustdoc;
 
diff --git a/src/test/auxiliary/inherited_stability.rs b/src/test/auxiliary/inherited_stability.rs
index 7a01ce3de0b..77eb82f8022 100644
--- a/src/test/auxiliary/inherited_stability.rs
+++ b/src/test/auxiliary/inherited_stability.rs
@@ -9,52 +9,47 @@
 // except according to those terms.
 #![crate_name="inherited_stability"]
 #![crate_type = "lib"]
-#![unstable]
+#![unstable(feature = "test_feature")]
+#![feature(staged_api)]
 #![staged_api]
 
-pub fn experimental() {}
+pub fn unstable() {}
 
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 pub fn stable() {}
 
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 pub mod stable_mod {
-    pub fn experimental() {}
+    pub fn unstable() {}
 
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     pub fn stable() {}
 }
 
-#[unstable]
+#[unstable(feature = "test_feature")]
 pub mod unstable_mod {
-    #[unstable]
-    pub fn experimental() {}
+    #[stable(feature = "test_feature", since = "1.0.0")]
+    #[deprecated(since = "1.0.0")]
+    pub fn deprecated() {}
 
     pub fn unstable() {}
 }
 
-pub mod experimental_mod {
-    pub fn experimental() {}
-
-    #[stable]
-    pub fn stable() {}
-}
-
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 pub trait Stable {
-    fn experimental(&self);
+    fn unstable(&self);
 
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     fn stable(&self);
 }
 
 impl Stable for uint {
-    fn experimental(&self) {}
+    fn unstable(&self) {}
     fn stable(&self) {}
 }
 
-pub enum Experimental {
-    ExperimentalVariant,
-    #[stable]
+pub enum Unstable {
+    UnstableVariant,
+    #[stable(feature = "rust1", since = "1.0.0")]
     StableVariant
 }
diff --git a/src/test/auxiliary/lint_output_format.rs b/src/test/auxiliary/lint_output_format.rs
index adbb90fe6c8..1977e2aad28 100755
--- a/src/test/auxiliary/lint_output_format.rs
+++ b/src/test/auxiliary/lint_output_format.rs
@@ -10,19 +10,22 @@
 
 #![crate_name="lint_output_format"]
 #![crate_type = "lib"]
+#![feature(staged_api)]
 #![staged_api]
+#![unstable(feature = "test_feature")]
 
-#[deprecated]
+#[stable(feature = "test_feature", since = "1.0.0")]
+#[deprecated(since = "1.0.0")]
 pub fn foo() -> uint {
     20
 }
 
-#[unstable]
+#[unstable(feature = "test_feature")]
 pub fn bar() -> uint {
     40
 }
 
-#[unstable]
+#[unstable(feature = "test_feature")]
 pub fn baz() -> uint {
     30
 }
diff --git a/src/test/auxiliary/lint_stability.rs b/src/test/auxiliary/lint_stability.rs
index 73724713b21..3679557d06b 100644
--- a/src/test/auxiliary/lint_stability.rs
+++ b/src/test/auxiliary/lint_stability.rs
@@ -9,64 +9,63 @@
 // except according to those terms.
 #![crate_name="lint_stability"]
 #![crate_type = "lib"]
+#![feature(staged_api)]
 #![staged_api]
 
-#[deprecated]
+#[stable(feature = "test_feature", since = "1.0.0")]
+#[deprecated(since = "1.0.0")]
 pub fn deprecated() {}
-#[deprecated="text"]
+#[stable(feature = "test_feature", since = "1.0.0")]
+#[deprecated(since = "1.0.0", reason = "text")]
 pub fn deprecated_text() {}
 
-#[unstable]
-pub fn experimental() {}
-#[unstable="text"]
-pub fn experimental_text() {}
+#[unstable(feature = "test_feature")]
+#[deprecated(since = "1.0.0")]
+pub fn deprecated_unstable() {}
+#[unstable(feature = "test_feature")]
+#[deprecated(since = "1.0.0", reason = "text")]
+pub fn deprecated_unstable_text() {}
 
-#[unstable]
+#[unstable(feature = "test_feature")]
 pub fn unstable() {}
-#[unstable="text"]
+#[unstable(feature = "test_feature", reason = "text")]
 pub fn unstable_text() {}
 
 pub fn unmarked() {}
 
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 pub fn stable() {}
-#[stable="text"]
+#[stable(feature = "rust1", since = "1.0.0", reason = "text")]
 pub fn stable_text() {}
 
-#[locked]
-pub fn locked() {}
-#[locked="text"]
-pub fn locked_text() {}
-
-#[frozen]
-pub fn frozen() {}
-#[frozen="text"]
-pub fn frozen_text() {}
-
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 pub struct MethodTester;
 
 impl MethodTester {
-    #[deprecated]
+    #[stable(feature = "test_feature", since = "1.0.0")]
+    #[deprecated(since = "1.0.0")]
     pub fn method_deprecated(&self) {}
-    #[deprecated="text"]
+    #[stable(feature = "test_feature", since = "1.0.0")]
+    #[deprecated(since = "1.0.0", reason = "text")]
     pub fn method_deprecated_text(&self) {}
 
-    #[unstable]
-    pub fn method_experimental(&self) {}
-    #[unstable="text"]
-    pub fn method_experimental_text(&self) {}
+    #[unstable(feature = "test_feature")]
+    #[deprecated(since = "1.0.0")]
+    pub fn method_deprecated_unstable(&self) {}
+    #[unstable(feature = "test_feature")]
+    #[deprecated(since = "1.0.0", reason = "text")]
+    pub fn method_deprecated_unstable_text(&self) {}
 
-    #[unstable]
+    #[unstable(feature = "test_feature")]
     pub fn method_unstable(&self) {}
-    #[unstable="text"]
+    #[unstable(feature = "test_feature", reason = "text")]
     pub fn method_unstable_text(&self) {}
 
     pub fn method_unmarked(&self) {}
 
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     pub fn method_stable(&self) {}
-    #[stable="text"]
+    #[stable(feature = "rust1", since = "1.0.0", reason = "text")]
     pub fn method_stable_text(&self) {}
 
     #[locked]
@@ -81,26 +80,30 @@ impl MethodTester {
 }
 
 pub trait Trait {
-    #[deprecated]
+    #[stable(feature = "test_feature", since = "1.0.0")]
+    #[deprecated(since = "1.0.0")]
     fn trait_deprecated(&self) {}
-    #[deprecated="text"]
+    #[stable(feature = "test_feature", since = "1.0.0")]
+    #[deprecated(since = "1.0.0", reason = "text")]
     fn trait_deprecated_text(&self) {}
 
-    #[unstable]
-    fn trait_experimental(&self) {}
-    #[unstable="text"]
-    fn trait_experimental_text(&self) {}
+    #[unstable(feature = "test_feature")]
+    #[deprecated(since = "1.0.0")]
+    fn trait_deprecated_unstable(&self) {}
+    #[unstable(feature = "test_feature")]
+    #[deprecated(since = "1.0.0", reason = "text")]
+    fn trait_deprecated_unstable_text(&self) {}
 
-    #[unstable]
+    #[unstable(feature = "test_feature")]
     fn trait_unstable(&self) {}
-    #[unstable="text"]
+    #[unstable(feature = "test_feature", reason = "text")]
     fn trait_unstable_text(&self) {}
 
     fn trait_unmarked(&self) {}
 
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     fn trait_stable(&self) {}
-    #[stable="text"]
+    #[stable(feature = "rust1", since = "1.0.0", reason = "text")]
     fn trait_stable_text(&self) {}
 
     #[locked]
@@ -116,67 +119,59 @@ pub trait Trait {
 
 impl Trait for MethodTester {}
 
-#[unstable]
-pub trait ExperimentalTrait {}
+#[unstable(feature = "test_feature")]
+pub trait UnstableTrait {}
 
-#[deprecated]
+#[stable(feature = "test_feature", since = "1.0.0")]
+#[deprecated(since = "1.0.0")]
 pub struct DeprecatedStruct { pub i: int }
-#[unstable]
-pub struct ExperimentalStruct { pub i: int }
-#[unstable]
+#[unstable(feature = "test_feature")]
+#[deprecated(since = "1.0.0")]
+pub struct DeprecatedUnstableStruct { pub i: int }
+#[unstable(feature = "test_feature")]
 pub struct UnstableStruct { pub i: int }
 pub struct UnmarkedStruct { pub i: int }
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 pub struct StableStruct { pub i: int }
-#[frozen]
-pub struct FrozenStruct { pub i: int }
-#[locked]
-pub struct LockedStruct { pub i: int }
 
-#[deprecated]
+#[stable(feature = "test_feature", since = "1.0.0")]
+#[deprecated(since = "1.0.0")]
 pub struct DeprecatedUnitStruct;
-#[unstable]
-pub struct ExperimentalUnitStruct;
-#[unstable]
+#[unstable(feature = "test_feature")]
+#[deprecated(since = "1.0.0")]
+pub struct DeprecatedUnstableUnitStruct;
+#[unstable(feature = "test_feature")]
 pub struct UnstableUnitStruct;
 pub struct UnmarkedUnitStruct;
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 pub struct StableUnitStruct;
-#[frozen]
-pub struct FrozenUnitStruct;
-#[locked]
-pub struct LockedUnitStruct;
 
 pub enum Enum {
-    #[deprecated]
+    #[stable(feature = "test_feature", since = "1.0.0")]
+    #[deprecated(since = "1.0.0")]
     DeprecatedVariant,
-    #[unstable]
-    ExperimentalVariant,
-    #[unstable]
+    #[unstable(feature = "test_feature")]
+    #[deprecated(since = "1.0.0")]
+    DeprecatedUnstableVariant,
+    #[unstable(feature = "test_feature")]
     UnstableVariant,
 
     UnmarkedVariant,
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     StableVariant,
-    #[frozen]
-    FrozenVariant,
-    #[locked]
-    LockedVariant,
 }
 
-#[deprecated]
+#[stable(feature = "test_feature", since = "1.0.0")]
+#[deprecated(since = "1.0.0")]
 pub struct DeprecatedTupleStruct(pub int);
-#[unstable]
-pub struct ExperimentalTupleStruct(pub int);
-#[unstable]
+#[unstable(feature = "test_feature")]
+#[deprecated(since = "1.0.0")]
+pub struct DeprecatedUnstableTupleStruct(pub int);
+#[unstable(feature = "test_feature")]
 pub struct UnstableTupleStruct(pub int);
 pub struct UnmarkedTupleStruct(pub int);
-#[stable]
+#[stable(feature = "rust1", since = "1.0.0")]
 pub struct StableTupleStruct(pub int);
-#[frozen]
-pub struct FrozenTupleStruct(pub int);
-#[locked]
-pub struct LockedTupleStruct(pub int);
 
 #[macro_export]
 macro_rules! macro_test {
diff --git a/src/test/auxiliary/stability_cfg1.rs b/src/test/auxiliary/stability_cfg1.rs
index de806c65beb..3a92cf59611 100644
--- a/src/test/auxiliary/stability_cfg1.rs
+++ b/src/test/auxiliary/stability_cfg1.rs
@@ -9,5 +9,6 @@
 // except according to those terms.
 
 #![cfg_attr(foo, experimental)]
-#![cfg_attr(not(foo), stable)]
+#![cfg_attr(not(foo), stable(feature = "test_feature", since = "1.0.0"))]
+#![feature(staged_api)]
 #![staged_api]
diff --git a/src/test/auxiliary/stability_cfg2.rs b/src/test/auxiliary/stability_cfg2.rs
index 842f35b08ae..d9ed76e5c58 100644
--- a/src/test/auxiliary/stability_cfg2.rs
+++ b/src/test/auxiliary/stability_cfg2.rs
@@ -10,6 +10,7 @@
 
 // compile-flags:--cfg foo
 
-#![cfg_attr(foo, unstable)]
-#![cfg_attr(not(foo), stable)]
+#![cfg_attr(foo, unstable(feature = "test_feature"))]
+#![cfg_attr(not(foo), stable(feature = "test_feature", since = "1.0.0"))]
+#![feature(staged_api)]
 #![staged_api]
diff --git a/src/test/bench/shootout-mandelbrot.rs b/src/test/bench/shootout-mandelbrot.rs
index d261f3f3cf2..0bd69b73214 100644
--- a/src/test/bench/shootout-mandelbrot.rs
+++ b/src/test/bench/shootout-mandelbrot.rs
@@ -39,7 +39,6 @@
 // OF THE POSSIBILITY OF SUCH DAMAGE.
 
 #![feature(simd)]
-#![allow(unstable)]
 
 // ignore-pretty very bad with line comments
 
diff --git a/src/test/compile-fail/associated-type-projection-from-supertrait.rs b/src/test/compile-fail/associated-type-projection-from-supertrait.rs
index abaf79fb4cb..b388b6a28e3 100644
--- a/src/test/compile-fail/associated-type-projection-from-supertrait.rs
+++ b/src/test/compile-fail/associated-type-projection-from-supertrait.rs
@@ -40,8 +40,8 @@ impl Car for ModelU { }
 
 fn dent<C:Car>(c: C, color: C::Color) { c.chip_paint(color) }
 fn a() { dent(ModelT, Black); }
-fn b() { dent(ModelT, Blue); } //~ ERROR type mismatch
-fn c() { dent(ModelU, Black); } //~ ERROR type mismatch
+fn b() { dent(ModelT, Blue); } //~ ERROR mismatched types
+fn c() { dent(ModelU, Black); } //~ ERROR mismatched types
 fn d() { dent(ModelU, Blue); }
 
 ///////////////////////////////////////////////////////////////////////////
diff --git a/src/test/compile-fail/associated-types-path-2.rs b/src/test/compile-fail/associated-types-path-2.rs
index 5cb9aca8beb..55ba65d6102 100644
--- a/src/test/compile-fail/associated-types-path-2.rs
+++ b/src/test/compile-fail/associated-types-path-2.rs
@@ -25,7 +25,7 @@ pub fn f2<T: Foo>(a: T) -> T::A {
 
 pub fn f1_int_int() {
     f1(2is, 4is);
-    //~^ ERROR type mismatch resolving
+    //~^ ERROR mismatched types
     //~| expected usize
     //~| found isize
 }
@@ -51,8 +51,6 @@ pub fn f2_int() {
     //~^ ERROR mismatched types
     //~| expected `isize`
     //~| found `usize`
-    //~| expected isize
-    //~| found usize
 }
 
 pub fn main() { }
diff --git a/src/test/compile-fail/borrowck-overloaded-call.rs b/src/test/compile-fail/borrowck-overloaded-call.rs
index 7d35a27c0ae..04d73cc36f0 100644
--- a/src/test/compile-fail/borrowck-overloaded-call.rs
+++ b/src/test/compile-fail/borrowck-overloaded-call.rs
@@ -17,7 +17,9 @@ struct SFn {
     y: isize,
 }
 
-impl Fn<(isize,),isize> for SFn {
+impl Fn<(isize,)> for SFn {
+    type Output = isize;
+
     extern "rust-call" fn call(&self, (z,): (isize,)) -> isize {
         self.x * self.y * z
     }
@@ -28,7 +30,9 @@ struct SFnMut {
     y: isize,
 }
 
-impl FnMut<(isize,),isize> for SFnMut {
+impl FnMut<(isize,)> for SFnMut {
+    type Output = isize;
+
     extern "rust-call" fn call_mut(&mut self, (z,): (isize,)) -> isize {
         self.x * self.y * z
     }
@@ -38,7 +42,9 @@ struct SFnOnce {
     x: String,
 }
 
-impl FnOnce<(String,),usize> for SFnOnce {
+impl FnOnce<(String,)> for SFnOnce {
+    type Output = usize;
+
     extern "rust-call" fn call_once(self, (z,): (String,)) -> usize {
         self.x.len() + z.len()
     }
diff --git a/src/test/compile-fail/enable-unstable-lib-feature.rs b/src/test/compile-fail/enable-unstable-lib-feature.rs
new file mode 100644
index 00000000000..c65b2366bf1
--- /dev/null
+++ b/src/test/compile-fail/enable-unstable-lib-feature.rs
@@ -0,0 +1,23 @@
+// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// Test that enabling an unstable feature disables warnings
+
+// aux-build:stability_cfg2.rs
+
+#![feature(test_feature)]
+#![deny(non_snake_case)] // To trigger a hard error
+
+// Shouldn't generate a warning about unstable features
+extern crate stability_cfg2;
+
+pub fn BOGUS() { } //~ ERROR
+
+pub fn main() { }
diff --git a/src/test/compile-fail/extern-wrong-value-type.rs b/src/test/compile-fail/extern-wrong-value-type.rs
index d7586af291e..db3373ea027 100644
--- a/src/test/compile-fail/extern-wrong-value-type.rs
+++ b/src/test/compile-fail/extern-wrong-value-type.rs
@@ -16,5 +16,7 @@ fn is_fn<F>(_: F) where F: Fn() {}
 fn main() {
     // extern functions are extern "C" fn
     let _x: extern "C" fn() = f; // OK
-    is_fn(f); //~ ERROR the trait `core::ops::Fn()` is not implemented for the type `extern "C" fn()
+    is_fn(f);
+    //~^ ERROR the trait `core::ops::Fn<()>` is not implemented for the type `extern "C" fn()
+    //~| ERROR the trait `core::ops::Fn<()>` is not implemented for the type `extern "C" fn()
 }
diff --git a/src/test/compile-fail/fail-no-dead-code-core.rs b/src/test/compile-fail/fail-no-dead-code-core.rs
index ee86c6ca1f0..9923db3c566 100644
--- a/src/test/compile-fail/fail-no-dead-code-core.rs
+++ b/src/test/compile-fail/fail-no-dead-code-core.rs
@@ -10,7 +10,7 @@
 
 #![deny(dead_code)]
 #![allow(unreachable_code)]
-#![allow(unstable)]
+#![feature(core)]
 
 #[macro_use] extern crate core;
 
diff --git a/src/test/compile-fail/feature-gate-unboxed-closures-manual-impls.rs b/src/test/compile-fail/feature-gate-unboxed-closures-manual-impls.rs
index cdb207f705f..e5e5ddadafc 100644
--- a/src/test/compile-fail/feature-gate-unboxed-closures-manual-impls.rs
+++ b/src/test/compile-fail/feature-gate-unboxed-closures-manual-impls.rs
@@ -8,18 +8,38 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+// Test that manual impls of the `Fn` traits are not possible without
+// a feature gate. In fact, the specialized check for these cases
+// never triggers (yet), because they encounter other problems around
+// angle bracket vs parentheses notation.
+
 #![allow(dead_code)]
 
 struct Foo;
-impl Fn() for Foo { //~ ERROR manual implementations of `Fn` are experimental
+impl Fn<()> for Foo {
+    //~^ ERROR angle-bracket notation is not stable when used with the `Fn` family of traits
+    type Output = ();
+
+    extern "rust-call" fn call(&self, args: ()) -> () {}
+}
+struct Foo1;
+impl Fn() for Foo1 {
+    //~^ ERROR associated type bindings are not allowed here
+
     extern "rust-call" fn call(&self, args: ()) -> () {}
 }
 struct Bar;
-impl FnMut() for Bar { //~ ERROR manual implementations of `FnMut` are experimental
+impl FnMut<()> for Bar {
+    //~^ ERROR angle-bracket notation is not stable when used with the `Fn` family of traits
+    type Output = ();
+
     extern "rust-call" fn call_mut(&self, args: ()) -> () {}
 }
 struct Baz;
-impl FnOnce() for Baz { //~ ERROR manual implementations of `FnOnce` are experimental
+impl FnOnce<()> for Baz {
+    //~^ ERROR angle-bracket notation is not stable when used with the `Fn` family of traits
+    type Output = ();
+
     extern "rust-call" fn call_once(&self, args: ()) -> () {}
 }
 
diff --git a/src/test/compile-fail/fn-trait-formatting.rs b/src/test/compile-fail/fn-trait-formatting.rs
index f19e27640cb..460e05c8438 100644
--- a/src/test/compile-fail/fn-trait-formatting.rs
+++ b/src/test/compile-fail/fn-trait-formatting.rs
@@ -34,5 +34,7 @@ fn main() {
     //~| expected ()
     //~| found box
 
-    needs_fn(1is); //~ ERROR `core::ops::Fn(isize) -> isize`
+    needs_fn(1is);
+    //~^ ERROR `core::ops::Fn<(isize,)>`
+    //~| ERROR `core::ops::Fn<(isize,)>`
 }
diff --git a/src/test/compile-fail/issue-15094.rs b/src/test/compile-fail/issue-15094.rs
index 2c03a9e0733..977586483b0 100644
--- a/src/test/compile-fail/issue-15094.rs
+++ b/src/test/compile-fail/issue-15094.rs
@@ -16,7 +16,9 @@ struct Debuger<T> {
     x: T
 }
 
-impl<T: fmt::Debug> ops::Fn<(), ()> for Debuger<T> {
+impl<T: fmt::Debug> ops::Fn<(),> for Debuger<T> {
+    type Output = ();
+
     fn call(&self, _args: ()) {
 //~^ ERROR `call` has an incompatible type for trait: expected "rust-call" fn, found "Rust" fn
         println!("{:?}", self.x);
diff --git a/src/test/compile-fail/issue-17337.rs b/src/test/compile-fail/issue-17337.rs
index 24425e5eeec..ff640793afe 100644
--- a/src/test/compile-fail/issue-17337.rs
+++ b/src/test/compile-fail/issue-17337.rs
@@ -8,13 +8,15 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+#![feature(staged_api)]
 #![staged_api]
 #![deny(deprecated)]
 
 struct Foo;
 
 impl Foo {
-    #[deprecated]
+    #[unstable(feature = "test_feature")]
+    #[deprecated(since = "1.0.0")]
     fn foo(self) {}
 }
 
diff --git a/src/test/compile-fail/issue-17545.rs b/src/test/compile-fail/issue-17545.rs
index 0501a3013cc..84800218efc 100644
--- a/src/test/compile-fail/issue-17545.rs
+++ b/src/test/compile-fail/issue-17545.rs
@@ -10,7 +10,7 @@
 
 #![feature(unboxed_closures)]
 
-pub fn foo<'a, F: Fn<(&'a (),), ()>>(bar: F) {
+pub fn foo<'a, F: Fn(&'a ())>(bar: F) {
     bar.call((
         &(), //~ ERROR borrowed value does not live long enough
     ));
diff --git a/src/test/compile-fail/issue-17999.rs b/src/test/compile-fail/issue-17999.rs
index eaefe55e066..a8804a6df06 100644
--- a/src/test/compile-fail/issue-17999.rs
+++ b/src/test/compile-fail/issue-17999.rs
@@ -9,7 +9,7 @@
 // except according to those terms.
 
 #![deny(unused_variables)]
-#![allow(unstable)]
+#![feature(core)]
 
 fn main() {
     for _ in range(1is, 101) {
diff --git a/src/test/compile-fail/issue-18400.rs b/src/test/compile-fail/issue-18400.rs
index a6662e78f3e..f3b2b3d5667 100644
--- a/src/test/compile-fail/issue-18400.rs
+++ b/src/test/compile-fail/issue-18400.rs
@@ -32,5 +32,8 @@ fn main() {
     let bits: &[_] = &[0, 1];
 
     0.contains(bits);
-//~^ ERROR the trait `Set<_>` is not implemented for the type `_`
+    //~^ ERROR overflow
+    //~| ERROR overflow
+    //~| ERROR overflow
+    //~| ERROR mismatched types
 }
diff --git a/src/test/compile-fail/issue-20711-2.rs b/src/test/compile-fail/issue-20711-2.rs
index f5f5c4fe8d7..9f0e81a662f 100644
--- a/src/test/compile-fail/issue-20711-2.rs
+++ b/src/test/compile-fail/issue-20711-2.rs
@@ -13,7 +13,7 @@ struct Foo;
 impl Foo {
     fn foo() {}
 
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
 } //~ ERROR expected `fn`, found `}`
 
 fn main() {}
diff --git a/src/test/compile-fail/issue-20711.rs b/src/test/compile-fail/issue-20711.rs
index b065355394c..5f0f0fc05a9 100644
--- a/src/test/compile-fail/issue-20711.rs
+++ b/src/test/compile-fail/issue-20711.rs
@@ -11,7 +11,7 @@
 struct Foo;
 
 impl Foo {
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
 } //~ ERROR expected `fn`, found `}`
 
 fn main() {}
diff --git a/src/test/compile-fail/issue-21160.rs b/src/test/compile-fail/issue-21160.rs
index 0ee38166935..45b7fbbd0b4 100644
--- a/src/test/compile-fail/issue-21160.rs
+++ b/src/test/compile-fail/issue-21160.rs
@@ -16,6 +16,6 @@ impl Bar {
 
 #[derive(Hash)]
 struct Foo(Bar);
-//~^ error: the trait `core::hash::Hash<__S>` is not implemented for the type `Bar`
+//~^ error: the trait `core::hash::Hash<_>` is not implemented for the type `Bar`
 
 fn main() {}
diff --git a/src/test/compile-fail/issue-21356.rs b/src/test/compile-fail/issue-21356.rs
index 979534ab30c..fefd432e229 100644
--- a/src/test/compile-fail/issue-21356.rs
+++ b/src/test/compile-fail/issue-21356.rs
@@ -9,6 +9,6 @@
 // except according to those terms.
 
 macro_rules! test { ($wrong:t_ty ..) => () }
-                  //~^ ERROR: unrecognized builtin nonterminal `t_ty`
+                  //~^ ERROR: invalid fragment specifier `t_ty`
 
 fn main() {}
diff --git a/src/test/compile-fail/lint-ctypes.rs b/src/test/compile-fail/lint-ctypes.rs
index 5706453a220..3f25e9c7b76 100644
--- a/src/test/compile-fail/lint-ctypes.rs
+++ b/src/test/compile-fail/lint-ctypes.rs
@@ -9,7 +9,7 @@
 // except according to those terms.
 
 #![deny(improper_ctypes)]
-#![allow(unstable)]
+#![feature(libc)]
 
 extern crate libc;
 
diff --git a/src/test/compile-fail/lint-dead-code-1.rs b/src/test/compile-fail/lint-dead-code-1.rs
index ceba33360d9..dc591943731 100644
--- a/src/test/compile-fail/lint-dead-code-1.rs
+++ b/src/test/compile-fail/lint-dead-code-1.rs
@@ -13,8 +13,8 @@
 #![allow(non_camel_case_types)]
 #![allow(non_upper_case_globals)]
 #![allow(missing_copy_implementations)]
-#![allow(unstable)]
 #![deny(dead_code)]
+#![feature(core)]
 
 #![crate_type="lib"]
 
diff --git a/src/test/compile-fail/lint-dead-code-3.rs b/src/test/compile-fail/lint-dead-code-3.rs
index 89ab78968d0..be135978d2d 100644
--- a/src/test/compile-fail/lint-dead-code-3.rs
+++ b/src/test/compile-fail/lint-dead-code-3.rs
@@ -10,8 +10,8 @@
 
 #![allow(unused_variables)]
 #![allow(non_camel_case_types)]
-#![allow(unstable)]
 #![deny(dead_code)]
+#![feature(libc)]
 
 #![crate_type="lib"]
 
diff --git a/src/test/compile-fail/lint-dead-code-4.rs b/src/test/compile-fail/lint-dead-code-4.rs
index 3221be220d9..22570bad616 100644
--- a/src/test/compile-fail/lint-dead-code-4.rs
+++ b/src/test/compile-fail/lint-dead-code-4.rs
@@ -10,8 +10,10 @@
 
 #![allow(unused_variables)]
 #![allow(non_camel_case_types)]
-#![allow(unstable)]
 #![deny(dead_code)]
+#![feature(libc)]
+#![feature(core)]
+#![feature(collections)]
 
 extern crate libc;
 
diff --git a/src/test/compile-fail/lint-exceeding-bitshifts.rs b/src/test/compile-fail/lint-exceeding-bitshifts.rs
index 4c880eda099..98853a2e9a1 100644
--- a/src/test/compile-fail/lint-exceeding-bitshifts.rs
+++ b/src/test/compile-fail/lint-exceeding-bitshifts.rs
@@ -10,8 +10,8 @@
 
 #![deny(exceeding_bitshifts)]
 #![allow(unused_variables)]
-#![allow(unstable)]
 #![allow(dead_code)]
+#![feature(core)]
 
 fn main() {
       let n = 1u8 << 7;
diff --git a/src/test/compile-fail/lint-forbid-attr.rs b/src/test/compile-fail/lint-forbid-attr.rs
index d1fcf62115b..fcc8fb6f933 100644
--- a/src/test/compile-fail/lint-forbid-attr.rs
+++ b/src/test/compile-fail/lint-forbid-attr.rs
@@ -8,8 +8,8 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#![forbid(unstable)]
+#![forbid(deprecated)]
 
-#[allow(unstable)] //~ ERROR allow(unstable) overruled by outer forbid(unstable)
+#[allow(deprecated)] //~ ERROR allow(deprecated) overruled by outer forbid(deprecated)
 fn main() {
 }
diff --git a/src/test/compile-fail/lint-forbid-cmdline.rs b/src/test/compile-fail/lint-forbid-cmdline.rs
index e3be0d06a35..be927297be7 100644
--- a/src/test/compile-fail/lint-forbid-cmdline.rs
+++ b/src/test/compile-fail/lint-forbid-cmdline.rs
@@ -8,9 +8,10 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-// compile-flags: -F unstable
+// compile-flags: -F deprecated
 
+#![feature(staged_api)]
 #![staged_api]
-#[allow(unstable)] //~ ERROR allow(unstable) overruled by outer forbid(unstable)
+#[allow(deprecated)] //~ ERROR allow(deprecated) overruled by outer forbid(deprecated)
 fn main() {
 }
diff --git a/src/test/compile-fail/lint-output-format.rs b/src/test/compile-fail/lint-output-format.rs
index 10217481bf3..ec4e3c774db 100644
--- a/src/test/compile-fail/lint-output-format.rs
+++ b/src/test/compile-fail/lint-output-format.rs
@@ -8,13 +8,15 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-// compile-flags:-F unstable
+// compile-flags: -F unused_features
 // aux-build:lint_output_format.rs
 
-extern crate lint_output_format; //~ ERROR: use of unmarked item
+#![feature(foo)] //~ ERROR unused or unknown feature
+
+extern crate lint_output_format; //~ WARNING: use of unstable library feature
 use lint_output_format::{foo, bar};
 
 fn main() {
     let _x = foo(); //~ WARNING #[warn(deprecated)] on by default
-    let _y = bar(); //~ ERROR [-F unstable]
+    let _y = bar(); //~ WARNING: use of unstable library feature
 }
diff --git a/src/test/compile-fail/lint-stability.rs b/src/test/compile-fail/lint-stability.rs
index eab5e98d68f..5b093a8556c 100644
--- a/src/test/compile-fail/lint-stability.rs
+++ b/src/test/compile-fail/lint-stability.rs
@@ -12,19 +12,19 @@
 // aux-build:inherited_stability.rs
 // aux-build:stability_cfg1.rs
 // aux-build:stability_cfg2.rs
+// ignore-tidy-linelength
 
-#![deny(unstable)]
 #![deny(deprecated)]
-#![deny(unstable)]
 #![allow(dead_code)]
+#![feature(staged_api)]
 #![staged_api]
 
 #[macro_use]
-extern crate lint_stability; //~ ERROR: use of unmarked item
+extern crate lint_stability; //~ ERROR: use of unmarked library feature
 
 mod cross_crate {
     extern crate stability_cfg1;
-    extern crate stability_cfg2; //~ ERROR: use of unstable item
+    extern crate stability_cfg2; //~ WARNING: use of unstable library feature
 
     use lint_stability::*;
 
@@ -39,25 +39,31 @@ mod cross_crate {
         foo.method_deprecated_text(); //~ ERROR use of deprecated item: text
         foo.trait_deprecated_text(); //~ ERROR use of deprecated item: text
 
-        experimental(); //~ ERROR use of unstable item
-        foo.method_experimental(); //~ ERROR use of unstable item
-        foo.trait_experimental(); //~ ERROR use of unstable item
+        deprecated_unstable(); //~ ERROR use of deprecated item
+        //~^ WARNING use of unstable library feature
+        foo.method_deprecated_unstable(); //~ ERROR use of deprecated item
+        //~^ WARNING use of unstable library feature
+        foo.trait_deprecated_unstable(); //~ ERROR use of deprecated item
+        //~^ WARNING use of unstable library feature
 
-        experimental_text(); //~ ERROR use of unstable item: text
-        foo.method_experimental_text(); //~ ERROR use of unstable item: text
-        foo.trait_experimental_text(); //~ ERROR use of unstable item: text
+        deprecated_unstable_text(); //~ ERROR use of deprecated item: text
+        //~^ WARNING use of unstable library feature
+        foo.method_deprecated_unstable_text(); //~ ERROR use of deprecated item: text
+        //~^ WARNING use of unstable library feature
+        foo.trait_deprecated_unstable_text(); //~ ERROR use of deprecated item: text
+        //~^ WARNING use of unstable library feature
 
-        unstable(); //~ ERROR use of unstable item
-        foo.method_unstable(); //~ ERROR use of unstable item
-        foo.trait_unstable(); //~ ERROR use of unstable item
+        unstable(); //~ WARNING use of unstable library feature
+        foo.method_unstable(); //~ WARNING use of unstable library feature
+        foo.trait_unstable(); //~ WARNING use of unstable library feature
 
-        unstable_text(); //~ ERROR use of unstable item: text
-        foo.method_unstable_text(); //~ ERROR use of unstable item: text
-        foo.trait_unstable_text(); //~ ERROR use of unstable item: text
+        unstable_text(); //~ WARNING use of unstable library feature 'test_feature': text
+        foo.method_unstable_text(); //~ WARNING use of unstable library feature 'test_feature': text
+        foo.trait_unstable_text(); //~ WARNING use of unstable library feature 'test_feature': text
 
-        unmarked(); //~ ERROR use of unmarked item
-        foo.method_unmarked(); //~ ERROR use of unmarked item
-        foo.trait_unmarked(); //~ ERROR use of unmarked item
+        unmarked(); //~ ERROR use of unmarked library feature
+        foo.method_unmarked(); //~ ERROR use of unmarked library feature
+        foo.trait_unmarked(); //~ ERROR use of unmarked library feature
 
         stable();
         foo.method_stable();
@@ -67,53 +73,33 @@ mod cross_crate {
         foo.method_stable_text();
         foo.trait_stable_text();
 
-        frozen();
-        foo.method_frozen();
-        foo.trait_frozen();
-
-        frozen_text();
-        foo.method_frozen_text();
-        foo.trait_frozen_text();
-
-        locked();
-        foo.method_locked();
-        foo.trait_locked();
-
-        locked_text();
-        foo.method_locked_text();
-        foo.trait_locked_text();
-
         let _ = DeprecatedStruct { i: 0 }; //~ ERROR use of deprecated item
-        let _ = ExperimentalStruct { i: 0 }; //~ ERROR use of unstable item
-        let _ = UnstableStruct { i: 0 }; //~ ERROR use of unstable item
-        let _ = UnmarkedStruct { i: 0 }; //~ ERROR use of unmarked item
+        let _ = DeprecatedUnstableStruct { i: 0 }; //~ ERROR use of deprecated item
+        //~^ WARNING use of unstable library feature
+        let _ = UnstableStruct { i: 0 }; //~ WARNING use of unstable library feature
+        let _ = UnmarkedStruct { i: 0 }; //~ ERROR use of unmarked library feature
         let _ = StableStruct { i: 0 };
-        let _ = FrozenStruct { i: 0 };
-        let _ = LockedStruct { i: 0 };
 
         let _ = DeprecatedUnitStruct; //~ ERROR use of deprecated item
-        let _ = ExperimentalUnitStruct; //~ ERROR use of unstable item
-        let _ = UnstableUnitStruct; //~ ERROR use of unstable item
-        let _ = UnmarkedUnitStruct; //~ ERROR use of unmarked item
+        let _ = DeprecatedUnstableUnitStruct; //~ ERROR use of deprecated item
+        //~^ WARNING use of unstable library feature
+        let _ = UnstableUnitStruct; //~ WARNING use of unstable library feature
+        let _ = UnmarkedUnitStruct; //~ ERROR use of unmarked library feature
         let _ = StableUnitStruct;
-        let _ = FrozenUnitStruct;
-        let _ = LockedUnitStruct;
 
         let _ = Enum::DeprecatedVariant; //~ ERROR use of deprecated item
-        let _ = Enum::ExperimentalVariant; //~ ERROR use of unstable item
-        let _ = Enum::UnstableVariant; //~ ERROR use of unstable item
-        let _ = Enum::UnmarkedVariant; //~ ERROR use of unmarked item
+        let _ = Enum::DeprecatedUnstableVariant; //~ ERROR use of deprecated item
+        //~^ WARNING use of unstable library feature
+        let _ = Enum::UnstableVariant; //~ WARNING use of unstable library feature
+        let _ = Enum::UnmarkedVariant; //~ ERROR use of unmarked library feature
         let _ = Enum::StableVariant;
-        let _ = Enum::FrozenVariant;
-        let _ = Enum::LockedVariant;
 
         let _ = DeprecatedTupleStruct (1); //~ ERROR use of deprecated item
-        let _ = ExperimentalTupleStruct (1); //~ ERROR use of unstable item
-        let _ = UnstableTupleStruct (1); //~ ERROR use of unstable item
-        let _ = UnmarkedTupleStruct (1); //~ ERROR use of unmarked item
+        let _ = DeprecatedUnstableTupleStruct (1); //~ ERROR use of deprecated item
+        //~^ WARNING use of unstable library feature
+        let _ = UnstableTupleStruct (1); //~ WARNING use of unstable library feature
+        let _ = UnmarkedTupleStruct (1); //~ ERROR use of unmarked library feature
         let _ = StableTupleStruct (1);
-        let _ = FrozenTupleStruct (1);
-        let _ = LockedTupleStruct (1);
 
         // At the moment, the lint checker only checks stability in
         // in the arguments of macros.
@@ -122,6 +108,8 @@ mod cross_crate {
         // on macros themselves are not yet linted.
         macro_test!();
         macro_test_arg!(deprecated_text()); //~ ERROR use of deprecated item: text
+        macro_test_arg!(deprecated_unstable_text()); //~ ERROR use of deprecated item: text
+        //~^ WARNING use of unstable library feature
         macro_test_arg!(macro_test_arg!(deprecated_text())); //~ ERROR use of deprecated item: text
         macro_test_arg_nested!(deprecated_text);
     }
@@ -129,222 +117,164 @@ mod cross_crate {
     fn test_method_param<F: Trait>(foo: F) {
         foo.trait_deprecated(); //~ ERROR use of deprecated item
         foo.trait_deprecated_text(); //~ ERROR use of deprecated item: text
-        foo.trait_experimental(); //~ ERROR use of unstable item
-        foo.trait_experimental_text(); //~ ERROR use of unstable item: text
-        foo.trait_unstable(); //~ ERROR use of unstable item
-        foo.trait_unstable_text(); //~ ERROR use of unstable item: text
-        foo.trait_unmarked(); //~ ERROR use of unmarked item
+        foo.trait_deprecated_unstable(); //~ ERROR use of deprecated item
+        //~^ WARNING use of unstable library feature
+        foo.trait_deprecated_unstable_text(); //~ ERROR use of deprecated item: text
+        //~^ WARNING use of unstable library feature
+        foo.trait_unstable(); //~ WARNING use of unstable library feature
+        foo.trait_unstable_text(); //~ WARNING use of unstable library feature 'test_feature': text
+        foo.trait_unmarked(); //~ ERROR use of unmarked library feature
         foo.trait_stable();
     }
 
     fn test_method_object(foo: &Trait) {
         foo.trait_deprecated(); //~ ERROR use of deprecated item
         foo.trait_deprecated_text(); //~ ERROR use of deprecated item: text
-        foo.trait_experimental(); //~ ERROR use of unstable item
-        foo.trait_experimental_text(); //~ ERROR use of unstable item: text
-        foo.trait_unstable(); //~ ERROR use of unstable item
-        foo.trait_unstable_text(); //~ ERROR use of unstable item: text
-        foo.trait_unmarked(); //~ ERROR use of unmarked item
+        foo.trait_deprecated_unstable(); //~ ERROR use of deprecated item
+        //~^ WARNING use of unstable library feature
+        foo.trait_deprecated_unstable_text(); //~ ERROR use of deprecated item: text
+        //~^ WARNING use of unstable library feature
+        foo.trait_unstable(); //~ WARNING use of unstable library feature
+        foo.trait_unstable_text(); //~ WARNING use of unstable library feature 'test_feature': text
+        foo.trait_unmarked(); //~ ERROR use of unmarked library feature
         foo.trait_stable();
     }
 
     struct S;
 
-    impl ExperimentalTrait for S { } //~ ERROR use of unstable item
+    impl UnstableTrait for S { } //~ WARNING use of unstable library feature
 
-    trait LocalTrait : ExperimentalTrait { } //~ ERROR use of unstable item
+    trait LocalTrait : UnstableTrait { } //~ WARNING use of unstable library feature
 }
 
 mod inheritance {
-    extern crate inherited_stability; //~ ERROR: use of unstable item
+    extern crate inherited_stability; //~ WARNING: use of unstable library feature
     use self::inherited_stability::*;
 
     fn test_inheritance() {
-        experimental(); //~ ERROR use of unstable item
+        unstable(); //~ WARNING use of unstable library feature
         stable();
 
-        stable_mod::experimental(); //~ ERROR use of unstable item
+        stable_mod::unstable(); //~ WARNING use of unstable library feature
         stable_mod::stable();
 
-        unstable_mod::experimental(); //~ ERROR use of unstable item
-        unstable_mod::unstable(); //~ ERROR use of unstable item
-
-        experimental_mod::experimental(); //~ ERROR use of unstable item
-        experimental_mod::stable();
+        unstable_mod::deprecated(); //~ ERROR use of deprecated item
+        unstable_mod::unstable(); //~ WARNING use of unstable library feature
 
-        let _ = Experimental::ExperimentalVariant; //~ ERROR use of unstable item
-        let _ = Experimental::StableVariant;
+        let _ = Unstable::UnstableVariant; //~ WARNING use of unstable library feature
+        let _ = Unstable::StableVariant;
 
         let x: usize = 0;
-        x.experimental(); //~ ERROR use of unstable item
+        x.unstable(); //~ WARNING use of unstable library feature
         x.stable();
     }
 }
 
 mod this_crate {
-    #[deprecated]
+    #[unstable(feature = "test_feature")]
+    #[deprecated(since = "1.0.0")]
     pub fn deprecated() {}
-    #[deprecated="text"]
+    #[unstable(feature = "test_feature")]
+    #[deprecated(since = "1.0.0", reason = "text")]
     pub fn deprecated_text() {}
 
-    #[unstable]
-    pub fn experimental() {}
-    #[unstable="text"]
-    pub fn experimental_text() {}
-
-    #[unstable]
+    #[unstable(feature = "test_feature")]
     pub fn unstable() {}
-    #[unstable="text"]
+    #[unstable(feature = "test_feature", reason = "text")]
     pub fn unstable_text() {}
 
     pub fn unmarked() {}
 
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     pub fn stable() {}
-    #[stable="text"]
+    #[stable(feature = "rust1", since = "1.0.0", reason = "text")]
     pub fn stable_text() {}
 
-    #[locked]
-    pub fn locked() {}
-    #[locked="text"]
-    pub fn locked_text() {}
-
-    #[frozen]
-    pub fn frozen() {}
-    #[frozen="text"]
-    pub fn frozen_text() {}
-
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     pub struct MethodTester;
 
     impl MethodTester {
-        #[deprecated]
+        #[unstable(feature = "test_feature")]
+        #[deprecated(since = "1.0.0")]
         pub fn method_deprecated(&self) {}
-        #[deprecated="text"]
+        #[unstable(feature = "test_feature")]
+        #[deprecated(since = "1.0.0", reason = "text")]
         pub fn method_deprecated_text(&self) {}
 
-        #[unstable]
-        pub fn method_experimental(&self) {}
-        #[unstable="text"]
-        pub fn method_experimental_text(&self) {}
-
-        #[unstable]
+        #[unstable(feature = "test_feature")]
         pub fn method_unstable(&self) {}
-        #[unstable="text"]
+        #[unstable(feature = "test_feature", reason = "text")]
         pub fn method_unstable_text(&self) {}
 
         pub fn method_unmarked(&self) {}
 
-        #[stable]
+        #[stable(feature = "rust1", since = "1.0.0")]
         pub fn method_stable(&self) {}
-        #[stable="text"]
+        #[stable(feature = "rust1", since = "1.0.0", reason = "text")]
         pub fn method_stable_text(&self) {}
-
-        #[locked]
-        pub fn method_locked(&self) {}
-        #[locked="text"]
-        pub fn method_locked_text(&self) {}
-
-        #[frozen]
-        pub fn method_frozen(&self) {}
-        #[frozen="text"]
-        pub fn method_frozen_text(&self) {}
     }
 
     pub trait Trait {
-        #[deprecated]
+        #[unstable(feature = "test_feature")]
+        #[deprecated(since = "1.0.0")]
         fn trait_deprecated(&self) {}
-        #[deprecated="text"]
+        #[unstable(feature = "test_feature")]
+        #[deprecated(since = "1.0.0", reason = "text")]
         fn trait_deprecated_text(&self) {}
 
-        #[unstable]
-        fn trait_experimental(&self) {}
-        #[unstable="text"]
-        fn trait_experimental_text(&self) {}
-
-        #[unstable]
+        #[unstable(feature = "test_feature")]
         fn trait_unstable(&self) {}
-        #[unstable="text"]
+        #[unstable(feature = "test_feature", reason = "text")]
         fn trait_unstable_text(&self) {}
 
         fn trait_unmarked(&self) {}
 
-        #[stable]
+        #[stable(feature = "rust1", since = "1.0.0")]
         fn trait_stable(&self) {}
-        #[stable="text"]
+        #[stable(feature = "rust1", since = "1.0.0", reason = "text")]
         fn trait_stable_text(&self) {}
-
-        #[locked]
-        fn trait_locked(&self) {}
-        #[locked="text"]
-        fn trait_locked_text(&self) {}
-
-        #[frozen]
-        fn trait_frozen(&self) {}
-        #[frozen="text"]
-        fn trait_frozen_text(&self) {}
     }
 
     impl Trait for MethodTester {}
 
-    #[deprecated]
+    #[unstable(feature = "test_feature")]
+    #[deprecated(since = "1.0.0")]
     pub struct DeprecatedStruct { i: isize }
-    #[unstable]
-    pub struct ExperimentalStruct { i: isize }
-    #[unstable]
+    #[unstable(feature = "test_feature")]
     pub struct UnstableStruct { i: isize }
     pub struct UnmarkedStruct { i: isize }
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     pub struct StableStruct { i: isize }
-    #[frozen]
-    pub struct FrozenStruct { i: isize }
-    #[locked]
-    pub struct LockedStruct { i: isize }
 
-    #[deprecated]
+    #[unstable(feature = "test_feature")]
+    #[deprecated(since = "1.0.0")]
     pub struct DeprecatedUnitStruct;
-    #[unstable]
-    pub struct ExperimentalUnitStruct;
-    #[unstable]
+    #[unstable(feature = "test_feature")]
     pub struct UnstableUnitStruct;
     pub struct UnmarkedUnitStruct;
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     pub struct StableUnitStruct;
-    #[frozen]
-    pub struct FrozenUnitStruct;
-    #[locked]
-    pub struct LockedUnitStruct;
 
     pub enum Enum {
-        #[deprecated]
+        #[unstable(feature = "test_feature")]
+        #[deprecated(since = "1.0.0")]
         DeprecatedVariant,
-        #[unstable]
-        ExperimentalVariant,
-        #[unstable]
+        #[unstable(feature = "test_feature")]
         UnstableVariant,
 
         UnmarkedVariant,
-        #[stable]
+        #[stable(feature = "rust1", since = "1.0.0")]
         StableVariant,
-        #[frozen]
-        FrozenVariant,
-        #[locked]
-        LockedVariant,
     }
 
-    #[deprecated]
+    #[unstable(feature = "test_feature")]
+    #[deprecated(since = "1.0.0")]
     pub struct DeprecatedTupleStruct(isize);
-    #[unstable]
-    pub struct ExperimentalTupleStruct(isize);
-    #[unstable]
+    #[unstable(feature = "test_feature")]
     pub struct UnstableTupleStruct(isize);
     pub struct UnmarkedTupleStruct(isize);
-    #[stable]
+    #[stable(feature = "rust1", since = "1.0.0")]
     pub struct StableTupleStruct(isize);
-    #[frozen]
-    pub struct FrozenTupleStruct(isize);
-    #[locked]
-    pub struct LockedTupleStruct(isize);
 
     fn test() {
         // Only the deprecated cases of the following should generate
@@ -361,14 +291,6 @@ mod this_crate {
         foo.method_deprecated_text(); //~ ERROR use of deprecated item: text
         foo.trait_deprecated_text(); //~ ERROR use of deprecated item: text
 
-        experimental();
-        foo.method_experimental();
-        foo.trait_experimental();
-
-        experimental_text();
-        foo.method_experimental_text();
-        foo.trait_experimental_text();
-
         unstable();
         foo.method_unstable();
         foo.trait_unstable();
@@ -389,60 +311,30 @@ mod this_crate {
         foo.method_stable_text();
         foo.trait_stable_text();
 
-        frozen();
-        foo.method_frozen();
-        foo.trait_frozen();
-
-        frozen_text();
-        foo.method_frozen_text();
-        foo.trait_frozen_text();
-
-        locked();
-        foo.method_locked();
-        foo.trait_locked();
-
-        locked_text();
-        foo.method_locked_text();
-        foo.trait_locked_text();
-
         let _ = DeprecatedStruct { i: 0 }; //~ ERROR use of deprecated item
-        let _ = ExperimentalStruct { i: 0 };
         let _ = UnstableStruct { i: 0 };
         let _ = UnmarkedStruct { i: 0 };
         let _ = StableStruct { i: 0 };
-        let _ = FrozenStruct { i: 0 };
-        let _ = LockedStruct { i: 0 };
 
         let _ = DeprecatedUnitStruct; //~ ERROR use of deprecated item
-        let _ = ExperimentalUnitStruct;
         let _ = UnstableUnitStruct;
         let _ = UnmarkedUnitStruct;
         let _ = StableUnitStruct;
-        let _ = FrozenUnitStruct;
-        let _ = LockedUnitStruct;
 
         let _ = Enum::DeprecatedVariant; //~ ERROR use of deprecated item
-        let _ = Enum::ExperimentalVariant;
         let _ = Enum::UnstableVariant;
         let _ = Enum::UnmarkedVariant;
         let _ = Enum::StableVariant;
-        let _ = Enum::FrozenVariant;
-        let _ = Enum::LockedVariant;
 
         let _ = DeprecatedTupleStruct (1); //~ ERROR use of deprecated item
-        let _ = ExperimentalTupleStruct (1);
         let _ = UnstableTupleStruct (1);
         let _ = UnmarkedTupleStruct (1);
         let _ = StableTupleStruct (1);
-        let _ = FrozenTupleStruct (1);
-        let _ = LockedTupleStruct (1);
     }
 
     fn test_method_param<F: Trait>(foo: F) {
         foo.trait_deprecated(); //~ ERROR use of deprecated item
         foo.trait_deprecated_text(); //~ ERROR use of deprecated item: text
-        foo.trait_experimental();
-        foo.trait_experimental_text();
         foo.trait_unstable();
         foo.trait_unstable_text();
         foo.trait_unmarked();
@@ -452,29 +344,30 @@ mod this_crate {
     fn test_method_object(foo: &Trait) {
         foo.trait_deprecated(); //~ ERROR use of deprecated item
         foo.trait_deprecated_text(); //~ ERROR use of deprecated item: text
-        foo.trait_experimental();
-        foo.trait_experimental_text();
         foo.trait_unstable();
         foo.trait_unstable_text();
         foo.trait_unmarked();
         foo.trait_stable();
     }
 
-    #[deprecated]
+    #[unstable(feature = "test_feature")]
+    #[deprecated(since = "1.0.0")]
     fn test_fn_body() {
         fn fn_in_body() {}
         fn_in_body();
     }
 
     impl MethodTester {
-        #[deprecated]
+        #[unstable(feature = "test_feature")]
+        #[deprecated(since = "1.0.0")]
         fn test_method_body(&self) {
             fn fn_in_body() {}
             fn_in_body();
         }
     }
 
-    #[deprecated]
+    #[unstable(feature = "test_feature")]
+    #[deprecated(since = "1.0.0")]
     pub trait DeprecatedTrait {}
 
     struct S;
diff --git a/src/test/compile-fail/lint-unknown-feature-default.rs b/src/test/compile-fail/lint-unknown-feature-default.rs
new file mode 100644
index 00000000000..d5e9cc630c3
--- /dev/null
+++ b/src/test/compile-fail/lint-unknown-feature-default.rs
@@ -0,0 +1,15 @@
+// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// Tests the default for the unused_features lint
+
+#![feature(this_is_not_a_feature)] //~ ERROR: unused or unknown feature
+
+fn main() { }
diff --git a/src/test/compile-fail/lint-unknown-feature.rs b/src/test/compile-fail/lint-unknown-feature.rs
index 6252e01749b..ac1720b339e 100644
--- a/src/test/compile-fail/lint-unknown-feature.rs
+++ b/src/test/compile-fail/lint-unknown-feature.rs
@@ -8,8 +8,8 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#![deny(unknown_features)]
+#![deny(unused_features)]
 
-#![feature(this_is_not_a_feature)] //~ ERROR: unknown feature
+#![feature(this_is_not_a_feature)] //~ ERROR: unused or unknown feature
 
 fn main() {}
diff --git a/src/test/compile-fail/lint-unused-extern-crate.rs b/src/test/compile-fail/lint-unused-extern-crate.rs
index ae156356b79..03bb7cc1f15 100644
--- a/src/test/compile-fail/lint-unused-extern-crate.rs
+++ b/src/test/compile-fail/lint-unused-extern-crate.rs
@@ -12,7 +12,9 @@
 
 #![deny(unused_extern_crates)]
 #![allow(unused_variables)]
-#![allow(unstable)]
+#![feature(libc)]
+#![feature(collections)]
+#![feature(rand)]
 
 extern crate libc; //~ ERROR: unused extern crate
 
diff --git a/src/test/compile-fail/lint-uppercase-variables.rs b/src/test/compile-fail/lint-uppercase-variables.rs
index 6f1e997e7bf..057b8e3acc6 100644
--- a/src/test/compile-fail/lint-uppercase-variables.rs
+++ b/src/test/compile-fail/lint-uppercase-variables.rs
@@ -11,8 +11,9 @@
 // ignore-tidy-linelength
 
 #![allow(dead_code)]
-#![allow(unstable)]
 #![deny(non_snake_case)]
+#![feature(path)]
+#![feature(io)]
 
 use std::old_io::File;
 use std::old_io::IoError;
diff --git a/src/test/compile-fail/liveness-unused.rs b/src/test/compile-fail/liveness-unused.rs
index f27ee376f52..4a3f7e9cad9 100644
--- a/src/test/compile-fail/liveness-unused.rs
+++ b/src/test/compile-fail/liveness-unused.rs
@@ -10,8 +10,9 @@
 
 #![deny(unused_variables)]
 #![deny(unused_assignments)]
-#![allow(unstable)]
 #![allow(dead_code, non_camel_case_types)]
+#![feature(core)]
+#![feature(os)]
 
 fn f1(x: isize) {
     //~^ ERROR unused variable: `x`
diff --git a/src/test/compile-fail/missing_debug_impls.rs b/src/test/compile-fail/missing_debug_impls.rs
index 4adae2f3680..5b781a40fe5 100644
--- a/src/test/compile-fail/missing_debug_impls.rs
+++ b/src/test/compile-fail/missing_debug_impls.rs
@@ -10,7 +10,8 @@
 
 // compile-flags: --crate-type lib
 #![deny(missing_debug_implementations)]
-#![allow(unused, unstable, missing_copy_implementations)]
+#![allow(unused, missing_copy_implementations)]
+#![feature(core)]
 
 use std::fmt;
 
diff --git a/src/test/compile-fail/overloaded-calls-bad.rs b/src/test/compile-fail/overloaded-calls-bad.rs
index d784ba2d0d6..61752e62abd 100644
--- a/src/test/compile-fail/overloaded-calls-bad.rs
+++ b/src/test/compile-fail/overloaded-calls-bad.rs
@@ -17,7 +17,9 @@ struct S {
     y: isize,
 }
 
-impl FnMut<(isize,),isize> for S {
+impl FnMut<(isize,)> for S {
+    type Output = isize;
+
     extern "rust-call" fn call_mut(&mut self, (z,): (isize,)) -> isize {
         self.x * self.y * z
     }
diff --git a/src/test/compile-fail/overloaded-calls-nontuple.rs b/src/test/compile-fail/overloaded-calls-nontuple.rs
index c06ab04cd84..41ecf714613 100644
--- a/src/test/compile-fail/overloaded-calls-nontuple.rs
+++ b/src/test/compile-fail/overloaded-calls-nontuple.rs
@@ -17,7 +17,8 @@ struct S {
     y: isize,
 }
 
-impl FnMut<isize,isize> for S {
+impl FnMut<isize> for S {
+    type Output = isize;
     extern "rust-call" fn call_mut(&mut self, z: isize) -> isize {
         self.x + self.y + z
     }
diff --git a/src/test/compile-fail/regions-infer-invariance-due-to-mutability-4.rs b/src/test/compile-fail/regions-infer-invariance-due-to-mutability-4.rs
index 2e634dfe3eb..2a246124f6f 100644
--- a/src/test/compile-fail/regions-infer-invariance-due-to-mutability-4.rs
+++ b/src/test/compile-fail/regions-infer-invariance-due-to-mutability-4.rs
@@ -9,15 +9,15 @@
 // except according to those terms.
 
 
-struct invariant<'a> {
+struct Invariant<'a> {
     f: Box<for<'b> FnOnce() -> &'b mut &'a isize + 'static>,
 }
 
-fn to_same_lifetime<'r>(bi: invariant<'r>) {
-    let bj: invariant<'r> = bi;
+fn to_same_lifetime<'r>(bi: Invariant<'r>) {
+    let bj: Invariant<'r> = bi;
 }
 
-fn to_longer_lifetime<'r>(bi: invariant<'r>) -> invariant<'static> {
+fn to_longer_lifetime<'r>(bi: Invariant<'r>) -> Invariant<'static> {
     bi //~ ERROR mismatched types
 }
 
diff --git a/src/test/compile-fail/shift-various-bad-types.rs b/src/test/compile-fail/shift-various-bad-types.rs
index 66aef0ec3a1..901ae1d5e2a 100644
--- a/src/test/compile-fail/shift-various-bad-types.rs
+++ b/src/test/compile-fail/shift-various-bad-types.rs
@@ -29,7 +29,7 @@ fn foo(p: &Panolpy) {
     // known to be an integer, but meh.
     let x;
     22 >> x;
-    //~^ ERROR right-hand-side of a shift operation must have integral type
+    //~^ ERROR the type of this value must be known in this context
 
     22 >> 1;
     // Integer literal types are OK
diff --git a/src/test/compile-fail/simd-binop.rs b/src/test/compile-fail/simd-binop.rs
index 0c2d8972ce7..f028c9af462 100644
--- a/src/test/compile-fail/simd-binop.rs
+++ b/src/test/compile-fail/simd-binop.rs
@@ -10,7 +10,6 @@
 
 // ignore-tidy-linelength
 
-#![allow(unstable)]
 
 use std::simd::f32x4;
 
diff --git a/src/test/compile-fail/slice-mut.rs b/src/test/compile-fail/slice-mut.rs
index a1747f3b6bd..e6acc325451 100644
--- a/src/test/compile-fail/slice-mut.rs
+++ b/src/test/compile-fail/slice-mut.rs
@@ -13,9 +13,10 @@
 fn main() {
     let x: &[isize] = &[1, 2, 3, 4, 5];
     // Immutable slices are not mutable.
+
     let y: &mut[_] = &x[2..4];
     //~^ ERROR mismatched types
     //~| expected `&mut [_]`
-    //~| found `&_`
+    //~| found `&[isize]`
     //~| values differ in mutability
 }
diff --git a/src/test/compile-fail/stability-attribute-sanity.rs b/src/test/compile-fail/stability-attribute-sanity.rs
new file mode 100644
index 00000000000..dcbb1880b10
--- /dev/null
+++ b/src/test/compile-fail/stability-attribute-sanity.rs
@@ -0,0 +1,95 @@
+// 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 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// Various checks that stability attributes are used correctly, per RFC 507
+
+#![feature(staged_api)]
+#![staged_api]
+
+mod bogus_attribute_types_1 {
+    #[stable(feature = "a", since = "a", reason)] //~ ERROR incorrect meta item
+    fn f1() { }
+
+    #[stable(feature = "a", since, reason = "a")] //~ ERROR incorrect meta item
+    fn f2() { }
+
+    #[stable(feature, since = "a", reason = "a")] //~ ERROR incorrect meta item
+    fn f3() { }
+
+    #[stable(feature = "a", since = "a", reason(b))] //~ ERROR incorrect meta item
+    fn f4() { }
+
+    #[stable(feature = "a", since(b), reason = "a")] //~ ERROR incorrect meta item
+    fn f5() { }
+
+    #[stable(feature(b), since = "a", reason = "a")] //~ ERROR incorrect meta item
+    fn f6() { }
+}
+
+mod bogus_attribute_types_2 {
+    #[unstable] //~ ERROR incorrect stability attribute type
+    fn f1() { }
+
+    #[unstable = "a"] //~ ERROR incorrect stability attribute type
+    fn f2() { }
+
+    #[stable] //~ ERROR incorrect stability attribute type
+    fn f3() { }
+
+    #[stable = "a"] //~ ERROR incorrect stability attribute type
+    fn f4() { }
+
+    #[stable(feature = "a", since = "b")]
+    #[deprecated] //~ ERROR incorrect stability attribute type
+    fn f5() { }
+
+    #[stable(feature = "a", since = "b")]
+    #[deprecated = "a"] //~ ERROR incorrect stability attribute type
+    fn f6() { }
+}
+
+mod missing_feature_names {
+    #[unstable(since = "a")] //~ ERROR missing 'feature'
+    fn f1() { }
+
+    #[stable(since = "a")] //~ ERROR missing 'feature'
+    fn f2() { }
+}
+
+mod missing_version {
+    #[stable(feature = "a")] //~ ERROR missing 'since'
+    fn f1() { }
+
+    #[stable(feature = "a", since = "b")]
+    #[deprecated(reason = "a")] //~ ERROR missing 'since'
+    fn f2() { }
+}
+
+#[unstable(feature = "a", since = "b")]
+#[stable(feature = "a", since = "b")]
+fn multiple1() { } //~ ERROR multiple stability levels
+
+#[unstable(feature = "a", since = "b")]
+#[unstable(feature = "a", since = "b")]
+fn multiple2() { } //~ ERROR multiple stability levels
+
+#[stable(feature = "a", since = "b")]
+#[stable(feature = "a", since = "b")]
+fn multiple3() { } //~ ERROR multiple stability levels
+
+#[stable(feature = "a", since = "b")]
+#[deprecated(since = "b")]
+#[deprecated(since = "b")]
+fn multiple4() { } //~ ERROR multiple deprecated attributes
+
+#[deprecated(since = "a")]
+fn deprecated_without_unstable_or_stable() { } //~ ERROR deprecated attribute must be paired
+
+fn main() { }
diff --git a/src/test/compile-fail/simd-experimental.rs b/src/test/compile-fail/staged_api.rs
index aea970f90b2..53d687b5cfe 100644
--- a/src/test/compile-fail/simd-experimental.rs
+++ b/src/test/compile-fail/staged_api.rs
@@ -1,4 +1,4 @@
-// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
+// 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.
 //
@@ -8,10 +8,6 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#![deny(unstable)]
+#![staged_api] //~ ERROR staged_api is for use by rustc only
 
-use std::simd;
-
-fn main() {
-    let _ = simd::i64x2(0, 0); //~ ERROR: experimental
-}
+fn main() { }
diff --git a/src/test/compile-fail/traits-multidispatch-bad.rs b/src/test/compile-fail/traits-multidispatch-bad.rs
index e9a4005b4b4..2e29a61846e 100644
--- a/src/test/compile-fail/traits-multidispatch-bad.rs
+++ b/src/test/compile-fail/traits-multidispatch-bad.rs
@@ -26,7 +26,7 @@ where T : Convert<U>
 }
 
 fn a() {
-    test(22is, 44is); //~ ERROR not implemented
+    test(22is, 44is); //~ ERROR mismatched types
 }
 
 fn main() {}
diff --git a/src/test/compile-fail/unboxed-closure-feature-gate.rs b/src/test/compile-fail/unboxed-closure-feature-gate.rs
index 5eb67a9bb71..3536244f011 100644
--- a/src/test/compile-fail/unboxed-closure-feature-gate.rs
+++ b/src/test/compile-fail/unboxed-closure-feature-gate.rs
@@ -11,7 +11,8 @@
 // Check that parenthetical notation is feature-gated except with the
 // `Fn` traits.
 
-trait Foo<A,R> {
+trait Foo<A> {
+    type Output;
 }
 
 fn main() {
diff --git a/src/test/compile-fail/unboxed-closure-sugar-default.rs b/src/test/compile-fail/unboxed-closure-sugar-default.rs
index 0d9e406b086..870377bc1ad 100644
--- a/src/test/compile-fail/unboxed-closure-sugar-default.rs
+++ b/src/test/compile-fail/unboxed-closure-sugar-default.rs
@@ -14,8 +14,9 @@
 #![feature(unboxed_closures)]
 #![allow(dead_code)]
 
-trait Foo<T,U,V=T> {
-    fn dummy(&self, t: T, u: U, v: V);
+trait Foo<T,V=T> {
+    type Output;
+    fn dummy(&self, t: T, v: V);
 }
 
 trait Eq<X: ?Sized> { }
@@ -24,14 +25,14 @@ fn eq<A: ?Sized,B: ?Sized>() where A : Eq<B> { }
 
 fn test<'a,'b>() {
     // Parens are equivalent to omitting default in angle.
-    eq::< Foo<(isize,),()>,               Foo(isize)                      >();
+    eq::< Foo<(isize,),Output=()>,                   Foo(isize)                      >();
 
     // In angle version, we supply something other than the default
-    eq::< Foo<(isize,),(),isize>,           Foo(isize)                      >();
+    eq::< Foo<(isize,),isize,Output=()>,      Foo(isize)                      >();
     //~^ ERROR not implemented
 
     // Supply default explicitly.
-    eq::< Foo<(isize,),(),(isize,)>,        Foo(isize)                      >();
+    eq::< Foo<(isize,),(isize,),Output=()>,   Foo(isize)                      >();
 }
 
 fn main() { }
diff --git a/src/test/compile-fail/unboxed-closure-sugar-equiv.rs b/src/test/compile-fail/unboxed-closure-sugar-equiv.rs
index 9dff0e9e01e..dc5576aee65 100644
--- a/src/test/compile-fail/unboxed-closure-sugar-equiv.rs
+++ b/src/test/compile-fail/unboxed-closure-sugar-equiv.rs
@@ -16,8 +16,9 @@
 #![feature(unboxed_closures)]
 #![allow(dead_code)]
 
-trait Foo<T,U> {
-    fn dummy(&self, t: T, u: U);
+trait Foo<T> {
+    type Output;
+    fn dummy(&self, t: T, u: Self::Output);
 }
 
 trait Eq<X: ?Sized> { }
@@ -26,31 +27,32 @@ fn eq<A: ?Sized,B: ?Sized +Eq<A>>() { }
 
 fn test<'a,'b>() {
     // No errors expected:
-    eq::< Foo<(),()>,                   Foo()                         >();
-    eq::< Foo<(isize,),()>,               Foo(isize)                      >();
-    eq::< Foo<(isize,usize),()>,           Foo(isize,usize)                 >();
-    eq::< Foo<(isize,usize),usize>,         Foo(isize,usize) -> usize         >();
-    eq::< Foo<(&'a isize,&'b usize),usize>, Foo(&'a isize,&'b usize) -> usize >();
+    eq::< Foo<(),Output=()>,                       Foo()                         >();
+    eq::< Foo<(isize,),Output=()>,                 Foo(isize)                      >();
+    eq::< Foo<(isize,usize),Output=()>,            Foo(isize,usize)                 >();
+    eq::< Foo<(isize,usize),Output=usize>,         Foo(isize,usize) -> usize         >();
+    eq::< Foo<(&'a isize,&'b usize),Output=usize>, Foo(&'a isize,&'b usize) -> usize >();
 
     // Test that anonymous regions in `()` form are equivalent
     // to fresh bound regions, and that we can intermingle
     // named and anonymous as we choose:
-    eq::< for<'x,'y> Foo<(&'x isize,&'y usize),usize>,
+    eq::< for<'x,'y> Foo<(&'x isize,&'y usize),Output=usize>,
           for<'x,'y> Foo(&'x isize,&'y usize) -> usize            >();
-    eq::< for<'x,'y> Foo<(&'x isize,&'y usize),usize>,
+    eq::< for<'x,'y> Foo<(&'x isize,&'y usize),Output=usize>,
           for<'x> Foo(&'x isize,&usize) -> usize                  >();
-    eq::< for<'x,'y> Foo<(&'x isize,&'y usize),usize>,
+    eq::< for<'x,'y> Foo<(&'x isize,&'y usize),Output=usize>,
           for<'y> Foo(&isize,&'y usize) -> usize                  >();
-    eq::< for<'x,'y> Foo<(&'x isize,&'y usize),usize>,
+    eq::< for<'x,'y> Foo<(&'x isize,&'y usize),Output=usize>,
           Foo(&isize,&usize) -> usize                             >();
 
     // lifetime elision
-    eq::< for<'x> Foo<(&'x isize,), &'x isize>,
+    eq::< for<'x> Foo<(&'x isize,), Output=&'x isize>,
           Foo(&isize) -> &isize                                   >();
 
     // Errors expected:
-    eq::< Foo<(),()>,                   Foo(char)                     >();
-    //~^ ERROR not implemented
+    eq::< Foo<(),Output=()>,
+          Foo(char)                                               >();
+    //~^^ ERROR not implemented
 }
 
 fn main() { }
diff --git a/src/test/compile-fail/unboxed-closure-sugar-lifetime-elision.rs b/src/test/compile-fail/unboxed-closure-sugar-lifetime-elision.rs
index 29429c708d2..d2f781bba11 100644
--- a/src/test/compile-fail/unboxed-closure-sugar-lifetime-elision.rs
+++ b/src/test/compile-fail/unboxed-closure-sugar-lifetime-elision.rs
@@ -16,8 +16,9 @@
 #![feature(unboxed_closures)]
 #![allow(dead_code)]
 
-trait Foo<T,U> {
-    fn dummy(&self, t: T, u: U);
+trait Foo<T> {
+    type Output;
+    fn dummy(&self, t: T);
 }
 
 trait Eq<X: ?Sized> { }
@@ -25,9 +26,9 @@ impl<X: ?Sized> Eq<X> for X { }
 fn eq<A: ?Sized,B: ?Sized +Eq<A>>() { }
 
 fn main() {
-    eq::< for<'a> Foo<(&'a isize,), &'a isize>,
+    eq::< for<'a> Foo<(&'a isize,), Output=&'a isize>,
           Foo(&isize) -> &isize                                   >();
-    eq::< for<'a> Foo<(&'a isize,), (&'a isize, &'a isize)>,
+    eq::< for<'a> Foo<(&'a isize,), Output=(&'a isize, &'a isize)>,
           Foo(&isize) -> (&isize, &isize)                           >();
 
     let _: Foo(&isize, &usize) -> &usize; //~ ERROR missing lifetime specifier
diff --git a/src/test/compile-fail/unboxed-closure-sugar-not-used-on-fn.rs b/src/test/compile-fail/unboxed-closure-sugar-not-used-on-fn.rs
index 21844e5b986..1f0d5aae36d 100644
--- a/src/test/compile-fail/unboxed-closure-sugar-not-used-on-fn.rs
+++ b/src/test/compile-fail/unboxed-closure-sugar-not-used-on-fn.rs
@@ -11,11 +11,11 @@
 
 // Test that the `Fn` traits require `()` form without a feature gate.
 
-fn bar1(x: &Fn<(),()>) {
+fn bar1(x: &Fn<()>) {
     //~^ ERROR angle-bracket notation is not stable when used with the `Fn` family
 }
 
-fn bar2<T>(x: &T) where T: Fn<(),()> {
+fn bar2<T>(x: &T) where T: Fn<()> {
     //~^ ERROR angle-bracket notation is not stable when used with the `Fn` family
 }
 
diff --git a/src/test/compile-fail/unboxed-closure-sugar-region.rs b/src/test/compile-fail/unboxed-closure-sugar-region.rs
index c8dd33c11fd..75688e44e80 100644
--- a/src/test/compile-fail/unboxed-closure-sugar-region.rs
+++ b/src/test/compile-fail/unboxed-closure-sugar-region.rs
@@ -17,8 +17,9 @@
 
 use std::marker;
 
-trait Foo<'a,T,U> {
-    fn dummy(&'a self) -> &'a (T,U);
+trait Foo<'a,T> {
+    type Output;
+    fn dummy(&'a self) -> &'a (T,Self::Output);
 }
 
 trait Eq<X: ?Sized> { }
@@ -29,16 +30,17 @@ fn same_type<A,B:Eq<A>>(a: A, b: B) { }
 
 fn test<'a,'b>() {
     // Parens are equivalent to omitting default in angle.
-    eq::< Foo<(isize,),()>,               Foo(isize)                      >();
+    eq::< Foo<(isize,),Output=()>,               Foo(isize)                      >();
 
     // Here we specify 'static explicitly in angle-bracket version.
     // Parenthesized winds up getting inferred.
-    eq::< Foo<'static, (isize,),()>,      Foo(isize)                      >();
+    eq::< Foo<'static, (isize,),Output=()>,      Foo(isize)                      >();
 }
 
-fn test2(x: &Foo<(isize,),()>, y: &Foo(isize)) {
+fn test2(x: &Foo<(isize,),Output=()>, y: &Foo(isize)) {
     // Here, the omitted lifetimes are expanded to distinct things.
     same_type(x, y) //~ ERROR cannot infer
+                    //~^ ERROR cannot infer
 }
 
 fn main() { }
diff --git a/src/test/compile-fail/unboxed-closure-sugar-used-on-struct-1.rs b/src/test/compile-fail/unboxed-closure-sugar-used-on-struct-1.rs
index a6184caf68b..a3991a87b78 100644
--- a/src/test/compile-fail/unboxed-closure-sugar-used-on-struct-1.rs
+++ b/src/test/compile-fail/unboxed-closure-sugar-used-on-struct-1.rs
@@ -11,13 +11,14 @@
 
 // Test that parentheses form doesn't work with struct types appearing in local variables.
 
-struct Bar<A,R> {
-    f: A, r: R
+struct Bar<A> {
+    f: A
 }
 
 fn bar() {
     let x: Box<Bar()> = panic!();
     //~^ ERROR parenthesized parameters may only be used with a trait
+    //~^^ ERROR associated type bindings are not allowed here
 }
 
 fn main() { }
diff --git a/src/test/compile-fail/unboxed-closure-sugar-used-on-struct.rs b/src/test/compile-fail/unboxed-closure-sugar-used-on-struct.rs
index d5fb505715e..ad85cdcaa03 100644
--- a/src/test/compile-fail/unboxed-closure-sugar-used-on-struct.rs
+++ b/src/test/compile-fail/unboxed-closure-sugar-used-on-struct.rs
@@ -10,12 +10,13 @@
 
 // Test that parentheses form doesn't work with struct types appearing in argument types.
 
-struct Bar<A,R> {
-    f: A, r: R
+struct Bar<A> {
+    f: A
 }
 
 fn foo(b: Box<Bar()>) {
     //~^ ERROR parenthesized parameters may only be used with a trait
+    //~^^ ERROR associated type bindings are not allowed here
 }
 
 fn main() { }
diff --git a/src/test/compile-fail/unboxed-closure-sugar-wrong-number-number-type-parameters-1.rs b/src/test/compile-fail/unboxed-closure-sugar-wrong-number-number-type-parameters-1.rs
index d9efab974d8..c9837da58e7 100644
--- a/src/test/compile-fail/unboxed-closure-sugar-wrong-number-number-type-parameters-1.rs
+++ b/src/test/compile-fail/unboxed-closure-sugar-wrong-number-number-type-parameters-1.rs
@@ -12,7 +12,7 @@
 
 trait One<A> { fn foo(&self) -> A; }
 
-fn foo(_: &One()) //~ ERROR wrong number of type arguments
+fn foo(_: &One()) //~ ERROR no associated type `Output` defined in `One<()>`
 {}
 
 fn main() { }
diff --git a/src/test/compile-fail/unboxed-closure-sugar-wrong-trait.rs b/src/test/compile-fail/unboxed-closure-sugar-wrong-trait.rs
index b58e08355c1..e63f510b890 100644
--- a/src/test/compile-fail/unboxed-closure-sugar-wrong-trait.rs
+++ b/src/test/compile-fail/unboxed-closure-sugar-wrong-trait.rs
@@ -13,7 +13,7 @@
 trait Trait {}
 
 fn f<F:Trait(isize) -> isize>(x: F) {}
-//~^ ERROR wrong number of type arguments: expected 0, found 2
+//~^ ERROR wrong number of type arguments: expected 0, found 1
 
 fn main() {}
 
diff --git a/src/test/compile-fail/unboxed-closures-fnmut-as-fn.rs b/src/test/compile-fail/unboxed-closures-fnmut-as-fn.rs
index fc87ec9f959..bbafd5109ed 100644
--- a/src/test/compile-fail/unboxed-closures-fnmut-as-fn.rs
+++ b/src/test/compile-fail/unboxed-closures-fnmut-as-fn.rs
@@ -18,7 +18,9 @@ use std::ops::{Fn,FnMut,FnOnce};
 
 struct S;
 
-impl FnMut<(isize,),isize> for S {
+impl FnMut<(isize,)> for S {
+    type Output = isize;
+
     extern "rust-call" fn call_mut(&mut self, (x,): (isize,)) -> isize {
         x * x
     }
@@ -29,6 +31,8 @@ fn call_it<F:Fn(isize)->isize>(f: &F, x: isize) -> isize {
 }
 
 fn main() {
-    let x = call_it(&S, 22); //~ ERROR not implemented
+    let x = call_it(&S, 22);
+    //~^ ERROR not implemented
+    //~| ERROR not implemented
 }
 
diff --git a/src/test/compile-fail/unboxed-closures-unsafe-extern-fn.rs b/src/test/compile-fail/unboxed-closures-unsafe-extern-fn.rs
index ab909717cab..23f7ee2b010 100644
--- a/src/test/compile-fail/unboxed-closures-unsafe-extern-fn.rs
+++ b/src/test/compile-fail/unboxed-closures-unsafe-extern-fn.rs
@@ -21,7 +21,9 @@ fn call_it_mut<F:FnMut(&isize)->isize>(_: &mut F, _: isize) -> isize { 0 }
 fn call_it_once<F:FnOnce(&isize)->isize>(_: F, _: isize) -> isize { 0 }
 
 fn a() {
-    let x = call_it(&square, 22); //~ ERROR not implemented
+    let x = call_it(&square, 22);
+    //~^ ERROR not implemented
+    //~| ERROR not implemented
 }
 
 fn b() {
diff --git a/src/test/compile-fail/unboxed-closures-vtable-mismatch.rs b/src/test/compile-fail/unboxed-closures-vtable-mismatch.rs
index 95673a51319..305dd33e5a0 100644
--- a/src/test/compile-fail/unboxed-closures-vtable-mismatch.rs
+++ b/src/test/compile-fail/unboxed-closures-vtable-mismatch.rs
@@ -12,13 +12,15 @@
 
 use std::ops::FnMut;
 
-fn call_it<F:FnMut<(isize,isize),isize>>(y: isize, mut f: F) -> isize {
+fn call_it<F:FnMut(isize,isize)->isize>(y: isize, mut f: F) -> isize {
     f(2, y)
 }
 
 pub fn main() {
     let f = |&mut: x: usize, y: isize| -> isize { (x as isize) + y };
-    let z = call_it(3, f);  //~ ERROR type mismatch
+    let z = call_it(3, f);
+    //~^ ERROR type mismatch
+    //~| ERROR type mismatch
     println!("{}", z);
 }
 
diff --git a/src/test/compile-fail/unboxed-closures-wrong-abi.rs b/src/test/compile-fail/unboxed-closures-wrong-abi.rs
index 4a0b55558c0..96619bef36f 100644
--- a/src/test/compile-fail/unboxed-closures-wrong-abi.rs
+++ b/src/test/compile-fail/unboxed-closures-wrong-abi.rs
@@ -21,7 +21,9 @@ fn call_it_mut<F:FnMut(&isize)->isize>(_: &mut F, _: isize) -> isize { 0 }
 fn call_it_once<F:FnOnce(&isize)->isize>(_: F, _: isize) -> isize { 0 }
 
 fn a() {
-    let x = call_it(&square, 22); //~ ERROR not implemented
+    let x = call_it(&square, 22);
+    //~^ ERROR not implemented
+    //~| ERROR not implemented
 }
 
 fn b() {
diff --git a/src/test/compile-fail/unboxed-closures-wrong-arg-type-extern-fn.rs b/src/test/compile-fail/unboxed-closures-wrong-arg-type-extern-fn.rs
index b2fdf792630..ebcbdbbc006 100644
--- a/src/test/compile-fail/unboxed-closures-wrong-arg-type-extern-fn.rs
+++ b/src/test/compile-fail/unboxed-closures-wrong-arg-type-extern-fn.rs
@@ -22,7 +22,9 @@ fn call_it_mut<F:FnMut(&isize)->isize>(_: &mut F, _: isize) -> isize { 0 }
 fn call_it_once<F:FnOnce(&isize)->isize>(_: F, _: isize) -> isize { 0 }
 
 fn a() {
-    let x = call_it(&square, 22); //~ ERROR not implemented
+    let x = call_it(&square, 22);
+    //~^ ERROR not implemented
+    //~| ERROR not implemented
 }
 
 fn b() {
diff --git a/src/test/compile-fail/unboxed-closures-wrong-trait.rs b/src/test/compile-fail/unboxed-closures-wrong-trait.rs
index e4255d0024f..2ada0dd22e7 100644
--- a/src/test/compile-fail/unboxed-closures-wrong-trait.rs
+++ b/src/test/compile-fail/unboxed-closures-wrong-trait.rs
@@ -18,5 +18,6 @@ fn main() {
     let z: isize = 7;
     assert_eq!(c(|&mut: x: isize, y| x + y + z), 10);
     //~^ ERROR not implemented
+    //~| ERROR not implemented
 }
 
diff --git a/src/test/compile-fail/unused-attr.rs b/src/test/compile-fail/unused-attr.rs
index b04f2edd142..50217ff9e5d 100644
--- a/src/test/compile-fail/unused-attr.rs
+++ b/src/test/compile-fail/unused-attr.rs
@@ -9,7 +9,7 @@
 // except according to those terms.
 #![deny(unused_attributes)]
 #![allow(dead_code, unused_imports)]
-#![allow(unstable)]
+#![feature(core)]
 
 #![foo] //~ ERROR unused attribute
 
diff --git a/src/test/compile-fail/variance-object-types.rs b/src/test/compile-fail/variance-object-types.rs
new file mode 100644
index 00000000000..972ec96f5f2
--- /dev/null
+++ b/src/test/compile-fail/variance-object-types.rs
@@ -0,0 +1,24 @@
+// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// Test that Cell is considered invariant with respect to its
+// type.
+
+use std::cell::Cell;
+
+// For better or worse, associated types are invariant, and hence we
+// get an invariant result for `'a`.
+#[rustc_variance]
+struct Foo<'a> { //~ ERROR regions=[[o];[];[]]
+    x: Box<Fn(i32) -> &'a i32 + 'static>
+}
+
+fn main() {
+}
diff --git a/src/test/debuginfo/simd.rs b/src/test/debuginfo/simd.rs
index 4aaa3e0b75f..578ea4479ec 100644
--- a/src/test/debuginfo/simd.rs
+++ b/src/test/debuginfo/simd.rs
@@ -41,7 +41,6 @@
 
 // gdb-command:continue
 
-#![allow(unstable)]
 #![allow(unused_variables)]
 #![omit_gdb_pretty_printer_section]
 
diff --git a/src/test/run-make/allow-non-lint-warnings-cmdline/1 b/src/test/run-make/allow-non-lint-warnings-cmdline/1
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/src/test/run-make/allow-non-lint-warnings-cmdline/1
diff --git a/src/test/run-make/allow-non-lint-warnings-cmdline/Makefile b/src/test/run-make/allow-non-lint-warnings-cmdline/Makefile
new file mode 100644
index 00000000000..961342591aa
--- /dev/null
+++ b/src/test/run-make/allow-non-lint-warnings-cmdline/Makefile
@@ -0,0 +1,12 @@
+-include ../tools.mk
+
+# Test that -A warnings makes the 'empty trait list for derive' warning go away
+OUT=$(shell $(RUSTC) foo.rs -A warnings 2>&1 | grep "warning" )
+
+all: foo
+	test -z '$(OUT)'
+
+# This is just to make sure the above command actually succeeds
+foo:
+	$(RUSTC) foo.rs -A warnings
+
diff --git a/src/test/run-make/allow-non-lint-warnings-cmdline/foo.rs b/src/test/run-make/allow-non-lint-warnings-cmdline/foo.rs
new file mode 100644
index 00000000000..19ce5d0a7ca
--- /dev/null
+++ b/src/test/run-make/allow-non-lint-warnings-cmdline/foo.rs
@@ -0,0 +1,15 @@
+// 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 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#[derive()]
+#[derive(Copy)]
+pub struct Foo;
+
+pub fn main() { }
diff --git a/src/test/run-make/allow-warnings-cmdline-stability/1 b/src/test/run-make/allow-warnings-cmdline-stability/1
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/src/test/run-make/allow-warnings-cmdline-stability/1
diff --git a/src/test/run-make/allow-warnings-cmdline-stability/Makefile b/src/test/run-make/allow-warnings-cmdline-stability/Makefile
new file mode 100644
index 00000000000..64b7f58caea
--- /dev/null
+++ b/src/test/run-make/allow-warnings-cmdline-stability/Makefile
@@ -0,0 +1,19 @@
+-include ../tools.mk
+
+# Test that -A warnings makes the 'empty trait list for derive' warning go away
+DEP=$(shell $(RUSTC) bar.rs)
+OUT=$(shell $(RUSTC) foo.rs -A warnings 2>&1 | grep "warning" )
+
+all: foo bar
+	test -z '$(OUT)'
+
+# These are just to ensure that the above commands actually work
+bar:
+	$(RUSTC) bar.rs
+
+foo: bar
+	$(RUSTC) foo.rs -A warnings
+
+
+
+
diff --git a/src/test/run-make/allow-warnings-cmdline-stability/bar.rs b/src/test/run-make/allow-warnings-cmdline-stability/bar.rs
new file mode 100644
index 00000000000..6a683d96b03
--- /dev/null
+++ b/src/test/run-make/allow-warnings-cmdline-stability/bar.rs
@@ -0,0 +1,16 @@
+// 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 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#![crate_type = "lib"]
+#![feature(staged_api)]
+#![staged_api]
+#![unstable(feature = "test_feature")]
+
+pub fn baz() { }
diff --git a/src/test/run-make/allow-warnings-cmdline-stability/foo.rs b/src/test/run-make/allow-warnings-cmdline-stability/foo.rs
new file mode 100644
index 00000000000..fb23a214016
--- /dev/null
+++ b/src/test/run-make/allow-warnings-cmdline-stability/foo.rs
@@ -0,0 +1,13 @@
+// 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 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+extern crate bar;
+
+pub fn main() { bar::baz() }
diff --git a/src/test/run-pass/associated-types-issue-21212.rs b/src/test/run-pass/associated-types-issue-21212.rs
new file mode 100644
index 00000000000..ced44250e4d
--- /dev/null
+++ b/src/test/run-pass/associated-types-issue-21212.rs
@@ -0,0 +1,28 @@
+// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// Regression test for #21212: an overflow occurred during trait
+// checking where normalizing `Self::Input` led to normalizing the
+// where clauses in the environment which in turn required normalizing
+// `Self::Input`.
+
+pub trait Parser {
+    type Input;
+
+    fn parse(input: <Self as Parser>::Input) {
+        panic!()
+    }
+}
+impl <P> Parser for P  {
+    type Input = ();
+}
+
+fn main() {
+}
diff --git a/src/test/run-pass/associated-types-normalize-in-bounds-binding.rs b/src/test/run-pass/associated-types-normalize-in-bounds-binding.rs
new file mode 100644
index 00000000000..dd5814f875b
--- /dev/null
+++ b/src/test/run-pass/associated-types-normalize-in-bounds-binding.rs
@@ -0,0 +1,42 @@
+// 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 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// Test that we normalize associated types that appear in a bound that
+// contains a binding. Issue #21664.
+
+#![allow(dead_code)]
+
+pub trait Integral {
+    type Opposite;
+}
+
+impl Integral for i32 {
+    type Opposite = u32;
+}
+
+impl Integral for u32 {
+    type Opposite = i32;
+}
+
+pub trait FnLike<A> {
+    type R;
+}
+
+fn foo<T>()
+    where T : FnLike<<i32 as Integral>::Opposite, R=bool>
+{
+    bar::<T>();
+}
+
+fn bar<T>()
+    where T : FnLike<u32, R=bool>
+{}
+
+fn main() { }
diff --git a/src/test/run-pass/associated-types-normalize-unifield-struct.rs b/src/test/run-pass/associated-types-normalize-unifield-struct.rs
index c517f61de0c..5aafe93067c 100644
--- a/src/test/run-pass/associated-types-normalize-unifield-struct.rs
+++ b/src/test/run-pass/associated-types-normalize-unifield-struct.rs
@@ -11,7 +11,6 @@
 // Regression test for issue #21010: Normalize associated types in
 // various special paths in the `type_is_immediate` function.
 
-#![allow(unstable)]
 
 pub trait OffsetState: Sized {}
 pub trait Offset { type State: OffsetState; }
diff --git a/src/test/run-pass/bare-fn-implements-fn-mut.rs b/src/test/run-pass/bare-fn-implements-fn-mut.rs
index 9d104afd646..fae83d4aa65 100644
--- a/src/test/run-pass/bare-fn-implements-fn-mut.rs
+++ b/src/test/run-pass/bare-fn-implements-fn-mut.rs
@@ -12,7 +12,7 @@
 
 use std::ops::FnMut;
 
-fn call_f<F:FnMut<(),()>>(mut f: F) {
+fn call_f<F:FnMut()>(mut f: F) {
     f();
 }
 
@@ -20,7 +20,7 @@ fn f() {
     println!("hello");
 }
 
-fn call_g<G:FnMut<(String,String),String>>(mut g: G, x: String, y: String)
+fn call_g<G:FnMut(String,String) -> String>(mut g: G, x: String, y: String)
           -> String {
     g(x, y)
 }
diff --git a/src/test/run-pass/hrtb-parse.rs b/src/test/run-pass/hrtb-parse.rs
index 41b7c0fae07..d5307c09103 100644
--- a/src/test/run-pass/hrtb-parse.rs
+++ b/src/test/run-pass/hrtb-parse.rs
@@ -22,23 +22,23 @@ trait Get<A,R> {
 // Parse HRTB with explicit `for` in a where-clause:
 
 fn foo00<T>(t: T)
-    where T : for<'a> Get<&'a int, &'a int>
+    where T : for<'a> Get<&'a i32, &'a i32>
 {
 }
 
-fn foo01<T: for<'a> Get<&'a int, &'a int>>(t: T)
+fn foo01<T: for<'a> Get<&'a i32, &'a i32>>(t: T)
 {
 }
 
 // Parse HRTB with explicit `for` in various sorts of types:
 
-fn foo10(t: Box<for<'a> Get<int, int>>) { }
-fn foo11(t: Box<for<'a> Get(int) -> int>) { }
+fn foo10(t: Box<for<'a> Get<i32, i32>>) { }
+fn foo11(t: Box<for<'a> Fn(i32) -> i32>) { }
 
-fn foo20(t: for<'a> fn(int) -> int) { }
-fn foo21(t: for<'a> unsafe fn(int) -> int) { }
-fn foo22(t: for<'a> extern "C" fn(int) -> int) { }
-fn foo23(t: for<'a> unsafe extern "C" fn(int) -> int) { }
+fn foo20(t: for<'a> fn(i32) -> i32) { }
+fn foo21(t: for<'a> unsafe fn(i32) -> i32) { }
+fn foo22(t: for<'a> extern "C" fn(i32) -> i32) { }
+fn foo23(t: for<'a> unsafe extern "C" fn(i32) -> i32) { }
 
 fn main() {
 }
diff --git a/src/test/run-pass/hrtb-trait-object-paren-notation.rs b/src/test/run-pass/hrtb-trait-object-paren-notation.rs
index e17e0ae2189..1b62a8e809c 100644
--- a/src/test/run-pass/hrtb-trait-object-paren-notation.rs
+++ b/src/test/run-pass/hrtb-trait-object-paren-notation.rs
@@ -16,7 +16,7 @@ trait FnLike<A,R> {
     fn call(&self, arg: A) -> R;
 }
 
-type FnObject<'b> = for<'a> FnLike(&'a int) -> (&'a int) + 'b;
+type FnObject<'b> = for<'a> FnLike<(&'a i32,), &'a i32> + 'b;
 
 struct Identity;
 
diff --git a/src/test/run-pass/ifmt.rs b/src/test/run-pass/ifmt.rs
index e273baef256..56de6726bfb 100644
--- a/src/test/run-pass/ifmt.rs
+++ b/src/test/run-pass/ifmt.rs
@@ -14,7 +14,6 @@
 #![deny(warnings)]
 #![allow(unused_must_use)]
 #![allow(unknown_features)]
-#![allow(unstable)]
 #![feature(box_syntax)]
 
 use std::fmt;
diff --git a/src/test/run-pass/into-iterator-type-inference-shift.rs b/src/test/run-pass/into-iterator-type-inference-shift.rs
new file mode 100644
index 00000000000..26a0abc76ae
--- /dev/null
+++ b/src/test/run-pass/into-iterator-type-inference-shift.rs
@@ -0,0 +1,41 @@
+// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// Regression test for type inference failure around shifting. In this
+// case, the iteration yields an int, but we hadn't run the full type
+// propagation yet, and so we just saw a type variable, yielding an
+// error.
+
+use std::u8;
+
+trait IntoIterator {
+    type Iter: Iterator;
+
+    fn into_iter(self) -> Self::Iter;
+}
+
+impl<I> IntoIterator for I where I: Iterator {
+    type Iter = I;
+
+    fn into_iter(self) -> I {
+        self
+    }
+}
+
+fn desugared_for_loop_bad(byte: u8) -> u8 {
+    let mut result = 0;
+    let mut x = IntoIterator::into_iter(range(0, u8::BITS));
+    let mut y = Iterator::next(&mut x);
+    let mut z = y.unwrap();
+    byte >> z;
+    1
+}
+
+fn main() {}
diff --git a/src/test/run-pass/issue-11958.rs b/src/test/run-pass/issue-11958.rs
index f557f662e81..13177880c5a 100644
--- a/src/test/run-pass/issue-11958.rs
+++ b/src/test/run-pass/issue-11958.rs
@@ -12,7 +12,6 @@
 
 // Pretty printing tests complain about `use std::predule::*`
 #![allow(unused_imports)]
-#![allow(unstable)]
 
 // We shouldn't need to rebind a moved upvar as mut if it's already
 // marked as mut
diff --git a/src/test/run-pass/issue-13655.rs b/src/test/run-pass/issue-13655.rs
index 6fdaac99204..81a8b29461c 100644
--- a/src/test/run-pass/issue-13655.rs
+++ b/src/test/run-pass/issue-13655.rs
@@ -13,7 +13,8 @@ use std::ops::Fn;
 
 struct Foo<T>(T);
 
-impl<T: Copy> Fn<(), T> for Foo<T> {
+impl<T: Copy> Fn<()> for Foo<T> {
+    type Output = T;
     extern "rust-call" fn call(&self, _: ()) -> T {
       match *self {
         Foo(t) => t
diff --git a/src/test/run-pass/issue-14958.rs b/src/test/run-pass/issue-14958.rs
index 1ffd349a653..814a743648d 100644
--- a/src/test/run-pass/issue-14958.rs
+++ b/src/test/run-pass/issue-14958.rs
@@ -14,7 +14,8 @@ trait Foo {}
 
 struct Bar;
 
-impl<'a> std::ops::Fn<(&'a (Foo+'a),), ()> for Bar {
+impl<'a> std::ops::Fn<(&'a (Foo+'a),)> for Bar {
+    type Output = ();
     extern "rust-call" fn call(&self, _: (&'a Foo,)) {}
 }
 
diff --git a/src/test/run-pass/issue-14959.rs b/src/test/run-pass/issue-14959.rs
index 99472bb3610..33281d7d78f 100644
--- a/src/test/run-pass/issue-14959.rs
+++ b/src/test/run-pass/issue-14959.rs
@@ -33,7 +33,9 @@ impl Alloy {
     }
 }
 
-impl<'a, 'b> Fn<(&'b mut (Response+'b),),()> for SendFile<'a> {
+impl<'a, 'b> Fn<(&'b mut (Response+'b),)> for SendFile<'a> {
+    type Output = ();
+
     extern "rust-call" fn call(&self, (_res,): (&'b mut (Response+'b),)) {}
 }
 
diff --git a/src/test/run-pass/issue-16668.rs b/src/test/run-pass/issue-16668.rs
index 75b1e11ddc1..e82add61aa3 100644
--- a/src/test/run-pass/issue-16668.rs
+++ b/src/test/run-pass/issue-16668.rs
@@ -15,7 +15,7 @@
 #![feature(unboxed_closures)]
 
 struct Parser<'a, I, O> {
-    parse: Box<FnMut<(I,), Result<O, String>> + 'a>
+    parse: Box<FnMut(I) -> Result<O, String> + 'a>
 }
 
 impl<'a, I, O: 'a> Parser<'a, I, O> {
diff --git a/src/test/run-pass/issue-16671.rs b/src/test/run-pass/issue-16671.rs
index 56b2e038a7b..124b0205fae 100644
--- a/src/test/run-pass/issue-16671.rs
+++ b/src/test/run-pass/issue-16671.rs
@@ -14,7 +14,6 @@
 
 // Pretty printing tests complain about `use std::predule::*`
 #![allow(unused_imports)]
-#![allow(unstable)]
 
 // A var moved into a proc, that has a mutable loan path should
 // not trigger a misleading unused_mut warning.
diff --git a/src/test/run-pass/issue-16739.rs b/src/test/run-pass/issue-16739.rs
index cb6f068cf45..389baecafd1 100644
--- a/src/test/run-pass/issue-16739.rs
+++ b/src/test/run-pass/issue-16739.rs
@@ -15,27 +15,30 @@
 // Test that unboxing shim for calling rust-call ABI methods through a
 // trait box works and does not cause an ICE.
 
-struct Foo { foo: uint }
+struct Foo { foo: u32 }
 
-impl FnMut<(), uint> for Foo {
-    extern "rust-call" fn call_mut(&mut self, _: ()) -> uint { self.foo }
+impl FnMut<()> for Foo {
+    type Output = u32;
+    extern "rust-call" fn call_mut(&mut self, _: ()) -> u32 { self.foo }
 }
 
-impl FnMut<(uint,), uint> for Foo {
-    extern "rust-call" fn call_mut(&mut self, (x,): (uint,)) -> uint { self.foo + x }
+impl FnMut<(u32,)> for Foo {
+    type Output = u32;
+    extern "rust-call" fn call_mut(&mut self, (x,): (u32,)) -> u32 { self.foo + x }
 }
 
-impl FnMut<(uint, uint), uint> for Foo {
-    extern "rust-call" fn call_mut(&mut self, (x, y): (uint, uint)) -> uint { self.foo + x + y }
+impl FnMut<(u32,u32)> for Foo {
+    type Output = u32;
+    extern "rust-call" fn call_mut(&mut self, (x, y): (u32, u32)) -> u32 { self.foo + x + y }
 }
 
 fn main() {
-    let mut f = box Foo { foo: 42 } as Box<FnMut<(), uint>>;
+    let mut f = box Foo { foo: 42 } as Box<FnMut() -> u32>;
     assert_eq!(f.call_mut(()), 42);
 
-    let mut f = box Foo { foo: 40 } as Box<FnMut<(uint,), uint>>;
+    let mut f = box Foo { foo: 40 } as Box<FnMut(u32) -> u32>;
     assert_eq!(f.call_mut((2,)), 42);
 
-    let mut f = box Foo { foo: 40 } as Box<FnMut<(uint, uint), uint>>;
+    let mut f = box Foo { foo: 40 } as Box<FnMut(u32, u32) -> u32>;
     assert_eq!(f.call_mut((1, 1)), 42);
 }
diff --git a/src/test/run-pass/issue-19499.rs b/src/test/run-pass/issue-19499.rs
new file mode 100644
index 00000000000..04017da9775
--- /dev/null
+++ b/src/test/run-pass/issue-19499.rs
@@ -0,0 +1,20 @@
+// 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 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// Regression test for issue #19499. Due to incorrect caching of trait
+// results for closures with upvars whose types were not fully
+// computed, this rather bizarre little program (along with many more
+// reasonable examples) let to ambiguity errors about not being able
+// to infer sufficient type information.
+
+fn main() {
+    let n = 0;
+    let it = Some(1_us).into_iter().inspect(|_| {n;});
+}
diff --git a/src/test/run-pass/issue-21058.rs b/src/test/run-pass/issue-21058.rs
index cbce577451f..044d43a57fa 100644
--- a/src/test/run-pass/issue-21058.rs
+++ b/src/test/run-pass/issue-21058.rs
@@ -8,7 +8,6 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#![allow(unstable)]
 
 struct NT(str);
 struct DST { a: u32, b: str }
diff --git a/src/test/run-pass/issue-21245.rs b/src/test/run-pass/issue-21245.rs
new file mode 100644
index 00000000000..9205b247e13
--- /dev/null
+++ b/src/test/run-pass/issue-21245.rs
@@ -0,0 +1,62 @@
+// 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 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// Regression test for issue #21245. Check that we are able to infer
+// the types in these examples correctly. It used to be that
+// insufficient type propagation caused the type of the iterator to be
+// incorrectly unified with the `*const` type to which it is coerced.
+
+use std::ptr;
+
+trait IntoIterator {
+    type Iter: Iterator;
+
+    fn into_iter(self) -> Self::Iter;
+}
+
+impl<I> IntoIterator for I where I: Iterator {
+    type Iter = I;
+
+    fn into_iter(self) -> I {
+        self
+    }
+}
+
+fn desugared_for_loop_bad<T>(v: Vec<T>) {
+    match IntoIterator::into_iter(v.iter()) {
+        mut iter => {
+            loop {
+                match ::std::iter::Iterator::next(&mut iter) {
+                    ::std::option::Option::Some(x) => {
+                        unsafe { ptr::read(x); }
+                    },
+                    ::std::option::Option::None => break
+                }
+            }
+        }
+    }
+}
+
+fn desugared_for_loop_good<T>(v: Vec<T>) {
+    match v.iter().into_iter() {
+        mut iter => {
+            loop {
+                match ::std::iter::Iterator::next(&mut iter) {
+                    ::std::option::Option::Some(x) => {
+                        unsafe { ptr::read(x); }
+                    },
+                    ::std::option::Option::None => break
+                }
+            }
+        }
+    }
+}
+
+fn main() {}
diff --git a/src/test/run-pass/object-method-numbering.rs b/src/test/run-pass/object-method-numbering.rs
new file mode 100644
index 00000000000..8da753acb96
--- /dev/null
+++ b/src/test/run-pass/object-method-numbering.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 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// Test for using an object with an associated type binding as the
+// instantiation for a generic type with a bound.
+
+trait SomeTrait {
+    type SomeType;
+
+    fn get(&self) -> Self::SomeType;
+}
+
+fn get_int<T:SomeTrait<SomeType=i32>+?Sized>(x: &T) -> i32 {
+    x.get()
+}
+
+impl SomeTrait for i32 {
+    type SomeType = i32;
+    fn get(&self) -> i32 {
+        *self
+    }
+}
+
+fn main() {
+    let x = 22_i32;
+    let x1: &SomeTrait<SomeType=i32> = &x;
+    let y = get_int(x1);
+    assert_eq!(x, y);
+}
diff --git a/src/test/run-pass/overloaded-calls-param-vtables.rs b/src/test/run-pass/overloaded-calls-param-vtables.rs
index 56887636d5d..2838909c1be 100644
--- a/src/test/run-pass/overloaded-calls-param-vtables.rs
+++ b/src/test/run-pass/overloaded-calls-param-vtables.rs
@@ -17,13 +17,15 @@ use std::ops::Add;
 
 struct G<A>;
 
-impl<'a, A: Add<int, Output=int>> Fn<(A,), int> for G<A> {
-    extern "rust-call" fn call(&self, (arg,): (A,)) -> int {
+impl<'a, A: Add<i32, Output=i32>> Fn<(A,)> for G<A> {
+    type Output = i32;
+
+    extern "rust-call" fn call(&self, (arg,): (A,)) -> i32 {
         arg.add(1)
     }
 }
 
 fn main() {
     // ICE trigger
-    G(1i);
+    G(1_i32);
 }
diff --git a/src/test/run-pass/overloaded-calls-simple.rs b/src/test/run-pass/overloaded-calls-simple.rs
index bb5b88d3674..f9e838d9b3d 100644
--- a/src/test/run-pass/overloaded-calls-simple.rs
+++ b/src/test/run-pass/overloaded-calls-simple.rs
@@ -13,34 +13,37 @@
 use std::ops::{Fn, FnMut, FnOnce};
 
 struct S1 {
-    x: int,
-    y: int,
+    x: i32,
+    y: i32,
 }
 
-impl FnMut<(int,),int> for S1 {
-    extern "rust-call" fn call_mut(&mut self, (z,): (int,)) -> int {
+impl FnMut<(i32,)> for S1 {
+    type Output = i32;
+    extern "rust-call" fn call_mut(&mut self, (z,): (i32,)) -> i32 {
         self.x * self.y * z
     }
 }
 
 struct S2 {
-    x: int,
-    y: int,
+    x: i32,
+    y: i32,
 }
 
-impl Fn<(int,),int> for S2 {
-    extern "rust-call" fn call(&self, (z,): (int,)) -> int {
+impl Fn<(i32,)> for S2 {
+    type Output = i32;
+    extern "rust-call" fn call(&self, (z,): (i32,)) -> i32 {
         self.x * self.y * z
     }
 }
 
 struct S3 {
-    x: int,
-    y: int,
+    x: i32,
+    y: i32,
 }
 
-impl FnOnce<(int,int),int> for S3 {
-    extern "rust-call" fn call_once(self, (z,zz): (int,int)) -> int {
+impl FnOnce<(i32,i32)> for S3 {
+    type Output = i32;
+    extern "rust-call" fn call_once(self, (z,zz): (i32,i32)) -> i32 {
         self.x * self.y * z * zz
     }
 }
diff --git a/src/test/run-pass/overloaded-calls-zero-args.rs b/src/test/run-pass/overloaded-calls-zero-args.rs
index 809a251fe80..ce7395673b3 100644
--- a/src/test/run-pass/overloaded-calls-zero-args.rs
+++ b/src/test/run-pass/overloaded-calls-zero-args.rs
@@ -13,12 +13,13 @@
 use std::ops::{FnMut};
 
 struct S {
-    x: int,
-    y: int,
+    x: i32,
+    y: i32,
 }
 
-impl FnMut<(),int> for S {
-    extern "rust-call" fn call_mut(&mut self, (): ()) -> int {
+impl FnMut<()> for S {
+    type Output = i32;
+    extern "rust-call" fn call_mut(&mut self, (): ()) -> i32 {
         self.x * self.y
     }
 }
diff --git a/src/test/run-pass/simd-binop.rs b/src/test/run-pass/simd-binop.rs
index 690ad351247..482eea19823 100644
--- a/src/test/run-pass/simd-binop.rs
+++ b/src/test/run-pass/simd-binop.rs
@@ -8,7 +8,6 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#![allow(unstable)]
 
 use std::simd::{i32x4, f32x4, u32x4};
 
diff --git a/src/test/run-pass/simd-issue-10604.rs b/src/test/run-pass/simd-issue-10604.rs
index 6f0db23e2a6..7f1be4b7d70 100644
--- a/src/test/run-pass/simd-issue-10604.rs
+++ b/src/test/run-pass/simd-issue-10604.rs
@@ -9,7 +9,6 @@
 // except according to those terms.
 
 
-#![allow(unstable)]
 #![feature(simd)]
 
 pub fn main() {
diff --git a/src/test/run-pass/tcp-connect-timeouts.rs b/src/test/run-pass/tcp-connect-timeouts.rs
index 4f67baa69b2..23c5501b4a4 100644
--- a/src/test/run-pass/tcp-connect-timeouts.rs
+++ b/src/test/run-pass/tcp-connect-timeouts.rs
@@ -16,7 +16,6 @@
 // one test task to ensure that errors are timeouts, not file descriptor
 // exhaustion.
 
-#![allow(unstable)]
 #![reexport_test_harness_main = "test_main"]
 
 #![allow(unused_imports)]
diff --git a/src/test/run-pass/unboxed-closures-boxed.rs b/src/test/run-pass/unboxed-closures-boxed.rs
index dc35d5bf2ca..27528ca5d56 100644
--- a/src/test/run-pass/unboxed-closures-boxed.rs
+++ b/src/test/run-pass/unboxed-closures-boxed.rs
@@ -14,9 +14,9 @@
 
 use std::ops::FnMut;
 
- fn make_adder(x: int) -> Box<FnMut<(int,),int>+'static> {
-    (box move |&mut: y: int| -> int { x + y }) as
-        Box<FnMut<(int,),int>+'static>
+ fn make_adder(x: i32) -> Box<FnMut(i32)->i32+'static> {
+    (box move |&mut: y: i32| -> i32 { x + y }) as
+        Box<FnMut(i32)->i32+'static>
 }
 
 pub fn main() {
diff --git a/src/test/run-pass/unboxed-closures-fn-as-fnmut-and-fnonce.rs b/src/test/run-pass/unboxed-closures-fn-as-fnmut-and-fnonce.rs
index 8af0547e5e5..5d6029e703b 100644
--- a/src/test/run-pass/unboxed-closures-fn-as-fnmut-and-fnonce.rs
+++ b/src/test/run-pass/unboxed-closures-fn-as-fnmut-and-fnonce.rs
@@ -18,21 +18,22 @@ use std::ops::{Fn,FnMut,FnOnce};
 
 struct S;
 
-impl Fn<(int,),int> for S {
-    extern "rust-call" fn call(&self, (x,): (int,)) -> int {
+impl Fn<(i32,)> for S {
+    type Output = i32;
+    extern "rust-call" fn call(&self, (x,): (i32,)) -> i32 {
         x * x
     }
 }
 
-fn call_it<F:Fn(int)->int>(f: &F, x: int) -> int {
+fn call_it<F:Fn(i32)->i32>(f: &F, x: i32) -> i32 {
     f(x)
 }
 
-fn call_it_mut<F:FnMut(int)->int>(f: &mut F, x: int) -> int {
+fn call_it_mut<F:FnMut(i32)->i32>(f: &mut F, x: i32) -> i32 {
     f(x)
 }
 
-fn call_it_once<F:FnOnce(int)->int>(f: F, x: int) -> int {
+fn call_it_once<F:FnOnce(i32)->i32>(f: F, x: i32) -> i32 {
     f(x)
 }
 
diff --git a/src/test/run-pass/unboxed-closures-fnmut-as-fnonce.rs b/src/test/run-pass/unboxed-closures-fnmut-as-fnonce.rs
index 068080e256d..95dae41c684 100644
--- a/src/test/run-pass/unboxed-closures-fnmut-as-fnonce.rs
+++ b/src/test/run-pass/unboxed-closures-fnmut-as-fnonce.rs
@@ -18,17 +18,19 @@ use std::ops::{FnMut,FnOnce};
 
 struct S;
 
-impl FnMut<(int,),int> for S {
-    extern "rust-call" fn call_mut(&mut self, (x,): (int,)) -> int {
+impl FnMut<(i32,)> for S {
+    type Output = i32;
+
+    extern "rust-call" fn call_mut(&mut self, (x,): (i32,)) -> i32 {
         x * x
     }
 }
 
-fn call_it_mut<F:FnMut(int)->int>(f: &mut F, x: int) -> int {
+fn call_it_mut<F:FnMut(i32)->i32>(f: &mut F, x: i32) -> i32 {
     f(x)
 }
 
-fn call_it_once<F:FnOnce(int)->int>(f: F, x: int) -> int {
+fn call_it_once<F:FnOnce(i32)->i32>(f: F, x: i32) -> i32 {
     f(x)
 }
 
diff --git a/src/test/run-pass/unboxed-closures-generic.rs b/src/test/run-pass/unboxed-closures-generic.rs
index 0edeeb8d198..04c124946c9 100644
--- a/src/test/run-pass/unboxed-closures-generic.rs
+++ b/src/test/run-pass/unboxed-closures-generic.rs
@@ -12,12 +12,12 @@
 
 use std::ops::FnMut;
 
-fn call_it<F:FnMut<(int,int),int>>(y: int, mut f: F) -> int {
+fn call_it<F:FnMut(i32,i32)->i32>(y: i32, mut f: F) -> i32 {
     f(2, y)
 }
 
 pub fn main() {
-    let f = |&mut: x: int, y: int| -> int { x + y };
+    let f = |&mut: x: i32, y: i32| -> i32 { x + y };
     let z = call_it(3, f);
     println!("{}", z);
     assert_eq!(z, 5);
diff --git a/src/test/run-pass/unboxed-closures-manual-impl.rs b/src/test/run-pass/unboxed-closures-manual-impl.rs
index 88c9ceae4a1..37075de0405 100644
--- a/src/test/run-pass/unboxed-closures-manual-impl.rs
+++ b/src/test/run-pass/unboxed-closures-manual-impl.rs
@@ -15,17 +15,19 @@ use std::ops::FnMut;
 
 struct S;
 
-impl FnMut<(int,),int> for S {
-    extern "rust-call" fn call_mut(&mut self, (x,): (int,)) -> int {
+impl FnMut<(i32,)> for S {
+    type Output = i32;
+
+    extern "rust-call" fn call_mut(&mut self, (x,): (i32,)) -> i32 {
         x * x
     }
 }
 
-fn call_it<F:FnMut(int)->int>(mut f: F, x: int) -> int {
+fn call_it<F:FnMut(i32)->i32>(mut f: F, x: i32) -> i32 {
     f(x) + 3
 }
 
-fn call_box(f: &mut FnMut(int) -> int, x: int) -> int {
+fn call_box(f: &mut FnMut(i32) -> i32, x: i32) -> i32 {
     f(x) + 3
 }
 
diff --git a/src/test/run-pass/unboxed-closures-monomorphization.rs b/src/test/run-pass/unboxed-closures-monomorphization.rs
index c1b7166b24e..6d192daca2f 100644
--- a/src/test/run-pass/unboxed-closures-monomorphization.rs
+++ b/src/test/run-pass/unboxed-closures-monomorphization.rs
@@ -16,17 +16,17 @@
 #![feature(unboxed_closures)]
 
 fn main(){
-    fn bar<'a, T:Clone+'a> (t: T) -> Box<FnMut<(),T> + 'a> {
+    fn bar<'a, T:Clone+'a> (t: T) -> Box<FnMut()->T + 'a> {
         box move |&mut:| t.clone()
     }
 
-    let mut f = bar(42u);
+    let mut f = bar(42_u32);
     assert_eq!(f.call_mut(()), 42);
 
     let mut f = bar("forty-two");
     assert_eq!(f.call_mut(()), "forty-two");
 
-    let x = 42u;
+    let x = 42_u32;
     let mut f = bar(&x);
     assert_eq!(f.call_mut(()), &x);
 
diff --git a/src/test/run-pass/unboxed-closures-sugar-object.rs b/src/test/run-pass/unboxed-closures-sugar-object.rs
index d65de438514..fff841a2f05 100644
--- a/src/test/run-pass/unboxed-closures-sugar-object.rs
+++ b/src/test/run-pass/unboxed-closures-sugar-object.rs
@@ -29,7 +29,7 @@ impl<X> Getter<X,X> for Identity {
 }
 
 fn main() {
-    let x: &Getter(int) -> (int,) = &Identity;
+    let x: &Getter<(i32,), (i32,)> = &Identity;
     let (y,) = x.get((22,));
     assert_eq!(y, 22);
 }