From 9f91a4df83a3fbc1861ec15eec5ecc4a667c1757 Mon Sep 17 00:00:00 2001 From: Ian Douglas Scott Date: Tue, 20 Jun 2017 16:04:38 -0700 Subject: [PATCH 01/12] Redox: Use create() instead of open() when setting env variable --- src/libstd/sys/redox/os.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libstd/sys/redox/os.rs b/src/libstd/sys/redox/os.rs index 9d459581dd40c..e38b7b29f4837 100644 --- a/src/libstd/sys/redox/os.rs +++ b/src/libstd/sys/redox/os.rs @@ -179,7 +179,7 @@ pub fn getenv(key: &OsStr) -> io::Result> { pub fn setenv(key: &OsStr, value: &OsStr) -> io::Result<()> { if ! key.is_empty() { - let mut file = ::fs::File::open(&("env:".to_owned() + key.to_str().unwrap()))?; + let mut file = ::fs::File::create(&("env:".to_owned() + key.to_str().unwrap()))?; file.write_all(value.as_bytes())?; file.set_len(value.len() as u64)?; } From 43b9cb3c1db2d1906e62966fd92aee0f1cdff7b3 Mon Sep 17 00:00:00 2001 From: "Zack M. Davis" Date: Tue, 20 Jun 2017 16:23:59 -0700 Subject: [PATCH 02/12] add extended information for E0562; impl Trait can only be a return type --- src/librustc_typeck/diagnostics.rs | 42 ++++++++++++++++++++++++++++-- 1 file changed, 40 insertions(+), 2 deletions(-) diff --git a/src/librustc_typeck/diagnostics.rs b/src/librustc_typeck/diagnostics.rs index f72af2084f022..b9513ec1556d1 100644 --- a/src/librustc_typeck/diagnostics.rs +++ b/src/librustc_typeck/diagnostics.rs @@ -3938,6 +3938,46 @@ let s = Simba { mother: 1, father: 0 }; // ok! ``` "##, +E0562: r##" +Abstract return types (written `impl Trait` for some trait `Trait`) are only +allowed as function return types. + +Erroneous code example: + +```compile_fail,E0562 +#![feature(conservative_impl_trait)] + +fn main() { + let count_to_ten: impl Iterator = 0..10; + // error: `impl Trait` not allowed outside of function and inherent method + // return types + for i in count_to_ten { + println!("{}", i); + } +} +``` + +Make sure `impl Trait` only appears in return-type position. + +``` +#![feature(conservative_impl_trait)] + +fn count_to_n(n: usize) -> impl Iterator { + 0..n +} + +fn main() { + for i in count_to_n(10) { // ok! + println!("{}", i); + } +} +``` + +See [RFC 1522] for more details. + +[RFC 1522]: https://github.com/rust-lang/rfcs/blob/master/text/1522-conservative-impl-trait.md +"##, + E0570: r##" The requested ABI is unsupported by the current target. @@ -4287,8 +4327,6 @@ register_diagnostics! { E0436, // functional record update requires a struct E0521, // redundant default implementations of trait E0533, // `{}` does not name a unit variant, unit struct or a constant - E0562, // `impl Trait` not allowed outside of function - // and inherent method return types E0563, // cannot determine a type for this `impl Trait`: {} E0564, // only named lifetimes are allowed in `impl Trait`, // but `{}` was found in the type `{}` From 12b11d83464241cd074fa67e2224f32b0c40720e Mon Sep 17 00:00:00 2001 From: Michael Woerister Date: Thu, 22 Jun 2017 10:27:45 +0200 Subject: [PATCH 03/12] Print -Zincremental-info to stderr instead of stdout. --- src/librustc_incremental/persist/file_format.rs | 6 +++--- src/librustc_incremental/persist/fs.rs | 4 ++-- src/librustc_incremental/persist/load.rs | 16 ++++++++-------- src/librustc_incremental/persist/save.rs | 10 +++++----- src/librustc_trans/back/write.rs | 2 +- src/librustc_trans/base.rs | 6 +++--- 6 files changed, 22 insertions(+), 22 deletions(-) diff --git a/src/librustc_incremental/persist/file_format.rs b/src/librustc_incremental/persist/file_format.rs index 5c20f65274f54..13b019af2eaa1 100644 --- a/src/librustc_incremental/persist/file_format.rs +++ b/src/librustc_incremental/persist/file_format.rs @@ -117,9 +117,9 @@ fn report_format_mismatch(sess: &Session, file: &Path, message: &str) { debug!("read_file: {}", message); if sess.opts.debugging_opts.incremental_info { - println!("incremental: ignoring cache artifact `{}`: {}", - file.file_name().unwrap().to_string_lossy(), - message); + eprintln!("incremental: ignoring cache artifact `{}`: {}", + file.file_name().unwrap().to_string_lossy(), + message); } } diff --git a/src/librustc_incremental/persist/fs.rs b/src/librustc_incremental/persist/fs.rs index 2a4a01cd4a453..28d33d9528692 100644 --- a/src/librustc_incremental/persist/fs.rs +++ b/src/librustc_incremental/persist/fs.rs @@ -435,8 +435,8 @@ fn copy_files(target_dir: &Path, } if print_stats_on_success { - println!("incremental: session directory: {} files hard-linked", files_linked); - println!("incremental: session directory: {} files copied", files_copied); + eprintln!("incremental: session directory: {} files hard-linked", files_linked); + eprintln!("incremental: session directory: {} files copied", files_copied); } Ok(files_linked > 0 || files_copied == 0) diff --git a/src/librustc_incremental/persist/load.rs b/src/librustc_incremental/persist/load.rs index 28a00bf4aa6c8..586bb79e596e1 100644 --- a/src/librustc_incremental/persist/load.rs +++ b/src/librustc_incremental/persist/load.rs @@ -151,8 +151,8 @@ pub fn decode_dep_graph<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, if prev_commandline_args_hash != tcx.sess.opts.dep_tracking_hash() { if tcx.sess.opts.debugging_opts.incremental_info { - println!("incremental: completely ignoring cache because of \ - differing commandline arguments"); + eprintln!("incremental: completely ignoring cache because of \ + differing commandline arguments"); } // We can't reuse the cache, purge it. debug!("decode_dep_graph: differing commandline arg hashes"); @@ -309,8 +309,8 @@ fn reconcile_work_products<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, all_files_exist = false; if tcx.sess.opts.debugging_opts.incremental_info { - println!("incremental: could not find file for up-to-date work product: {}", - path.display()); + eprintln!("incremental: could not find file for \ + up-to-date work product: {}", path.display()); } } } @@ -418,10 +418,10 @@ fn process_edge<'a, 'tcx, 'edges>( format!("{:?}", blame) }; - println!("incremental: module {:?} is dirty because {:?} \ - changed or was removed", - wp_id, - blame_str); + eprintln!("incremental: module {:?} is dirty because {:?} \ + changed or was removed", + wp_id, + blame_str); } } } diff --git a/src/librustc_incremental/persist/save.rs b/src/librustc_incremental/persist/save.rs index 867452d97e8fb..1bdd4f851fb13 100644 --- a/src/librustc_incremental/persist/save.rs +++ b/src/librustc_incremental/persist/save.rs @@ -47,8 +47,8 @@ pub fn save_dep_graph<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, let query = tcx.dep_graph.query(); if tcx.sess.opts.debugging_opts.incremental_info { - println!("incremental: {} nodes in dep-graph", query.graph.len_nodes()); - println!("incremental: {} edges in dep-graph", query.graph.len_edges()); + eprintln!("incremental: {} nodes in dep-graph", query.graph.len_nodes()); + eprintln!("incremental: {} edges in dep-graph", query.graph.len_edges()); } let mut hcx = HashContext::new(tcx, incremental_hashes_map); @@ -258,9 +258,9 @@ pub fn encode_dep_graph(tcx: TyCtxt, graph.encode(encoder)?; if tcx.sess.opts.debugging_opts.incremental_info { - println!("incremental: {} nodes in reduced dep-graph", graph.nodes.len()); - println!("incremental: {} edges in serialized dep-graph", graph.edge_list_data.len()); - println!("incremental: {} hashes in serialized dep-graph", graph.hashes.len()); + eprintln!("incremental: {} nodes in reduced dep-graph", graph.nodes.len()); + eprintln!("incremental: {} edges in serialized dep-graph", graph.edge_list_data.len()); + eprintln!("incremental: {} hashes in serialized dep-graph", graph.hashes.len()); } if tcx.sess.opts.debugging_opts.incremental_dump_hash { diff --git a/src/librustc_trans/back/write.rs b/src/librustc_trans/back/write.rs index 549cb2567cfbb..7e99ea0ee1977 100644 --- a/src/librustc_trans/back/write.rs +++ b/src/librustc_trans/back/write.rs @@ -893,7 +893,7 @@ fn dump_incremental_data(trans: &CrateTranslation) { ModuleSource::Translated(..) => (), } } - println!("incremental: re-using {} out of {} modules", reuse, trans.modules.len()); + eprintln!("incremental: re-using {} out of {} modules", reuse, trans.modules.len()); } struct WorkItem { diff --git a/src/librustc_trans/base.rs b/src/librustc_trans/base.rs index 54bc22963f5f7..2589a3538a940 100644 --- a/src/librustc_trans/base.rs +++ b/src/librustc_trans/base.rs @@ -1150,9 +1150,9 @@ pub fn trans_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, Some(work_product) } else { if scx.sess().opts.debugging_opts.incremental_info { - println!("incremental: CGU `{}` invalidated because of \ - changed partitioning hash.", - cgu.name()); + eprintln!("incremental: CGU `{}` invalidated because of \ + changed partitioning hash.", + cgu.name()); } debug!("trans_reuse_previous_work_products: \ not reusing {:?} because hash changed to {:?}", From fc581457ecc6a86ba31d210fe93744577679c9ce Mon Sep 17 00:00:00 2001 From: Letheed Date: Thu, 22 Jun 2017 15:48:20 +0200 Subject: [PATCH 04/12] Fix ref as mutable ref in std::rc::Rc doc --- src/liballoc/rc.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/liballoc/rc.rs b/src/liballoc/rc.rs index 21a56ff9899e3..94fe36d01a5a5 100644 --- a/src/liballoc/rc.rs +++ b/src/liballoc/rc.rs @@ -273,7 +273,7 @@ struct RcBox { /// See the [module-level documentation](./index.html) for more details. /// /// The inherent methods of `Rc` are all associated functions, which means -/// that you have to call them as e.g. [`Rc::get_mut(&value)`][get_mut] instead of +/// that you have to call them as e.g. [`Rc::get_mut(&mut value)`][get_mut] instead of /// `value.get_mut()`. This avoids conflicts with methods of the inner /// type `T`. /// From 14df54989aecb437e9cf6f3e066553cfbc979e26 Mon Sep 17 00:00:00 2001 From: Chris MacNaughton Date: Thu, 22 Jun 2017 12:01:22 +0200 Subject: [PATCH 05/12] Ensure Guard types impl Display & Debug Fixes #24372 --- src/libcore/cell.rs | 14 ++++++++++++++ src/libstd/sync/mutex.rs | 7 +++++++ src/libstd/sync/rwlock.rs | 14 ++++++++++++++ 3 files changed, 35 insertions(+) diff --git a/src/libcore/cell.rs b/src/libcore/cell.rs index e75401f6ce031..1eebf67ad04cb 100644 --- a/src/libcore/cell.rs +++ b/src/libcore/cell.rs @@ -942,6 +942,13 @@ impl<'b, T: ?Sized> Ref<'b, T> { #[unstable(feature = "coerce_unsized", issue = "27732")] impl<'b, T: ?Sized + Unsize, U: ?Sized> CoerceUnsized> for Ref<'b, T> {} +#[stable(feature = "std_guard_impls", since = "1.20")] +impl<'a, T: ?Sized + fmt::Display> fmt::Display for Ref<'a, T> { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + self.value.fmt(f) + } +} + impl<'b, T: ?Sized> RefMut<'b, T> { /// Make a new `RefMut` for a component of the borrowed data, e.g. an enum /// variant. @@ -1034,6 +1041,13 @@ impl<'b, T: ?Sized> DerefMut for RefMut<'b, T> { #[unstable(feature = "coerce_unsized", issue = "27732")] impl<'b, T: ?Sized + Unsize, U: ?Sized> CoerceUnsized> for RefMut<'b, T> {} +#[stable(feature = "std_guard_impls", since = "1.20")] +impl<'a, T: ?Sized + fmt::Display> fmt::Display for RefMut<'a, T> { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + self.value.fmt(f) + } +} + /// The core primitive for interior mutability in Rust. /// /// `UnsafeCell` is a type that wraps some `T` and indicates unsafe interior operations on the diff --git a/src/libstd/sync/mutex.rs b/src/libstd/sync/mutex.rs index 9a242a96d46e3..fc6c7de9ef083 100644 --- a/src/libstd/sync/mutex.rs +++ b/src/libstd/sync/mutex.rs @@ -440,6 +440,13 @@ impl<'a, T: ?Sized + fmt::Debug> fmt::Debug for MutexGuard<'a, T> { } } +#[stable(feature = "std_guard_impls", since = "1.20")] +impl<'a, T: ?Sized + fmt::Display> fmt::Display for MutexGuard<'a, T> { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + (**self).fmt(f) + } +} + pub fn guard_lock<'a, T: ?Sized>(guard: &MutexGuard<'a, T>) -> &'a sys::Mutex { &guard.__lock.inner } diff --git a/src/libstd/sync/rwlock.rs b/src/libstd/sync/rwlock.rs index 95bc8d3093286..944801e8a3bf0 100644 --- a/src/libstd/sync/rwlock.rs +++ b/src/libstd/sync/rwlock.rs @@ -370,6 +370,13 @@ impl<'a, T: fmt::Debug> fmt::Debug for RwLockReadGuard<'a, T> { } } +#[stable(feature = "std_guard_impls", since = "1.20")] +impl<'a, T: ?Sized + fmt::Display> fmt::Display for RwLockReadGuard<'a, T> { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + (**self).fmt(f) + } +} + #[stable(feature = "std_debug", since = "1.16.0")] impl<'a, T: fmt::Debug> fmt::Debug for RwLockWriteGuard<'a, T> { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { @@ -379,6 +386,13 @@ impl<'a, T: fmt::Debug> fmt::Debug for RwLockWriteGuard<'a, T> { } } +#[stable(feature = "std_guard_impls", since = "1.20")] +impl<'a, T: ?Sized + fmt::Display> fmt::Display for RwLockWriteGuard<'a, T> { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + (**self).fmt(f) + } +} + #[stable(feature = "rust1", since = "1.0.0")] impl<'rwlock, T: ?Sized> Deref for RwLockReadGuard<'rwlock, T> { type Target = T; From 526afcb0a341c6036c069e113ebecf574c861c9f Mon Sep 17 00:00:00 2001 From: Ian Douglas Scott Date: Thu, 22 Jun 2017 10:42:10 -0700 Subject: [PATCH 06/12] Set CXX_ in bootstrap --- src/bootstrap/lib.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/bootstrap/lib.rs b/src/bootstrap/lib.rs index ca8cc3212d7c7..3a43cc0c29d8e 100644 --- a/src/bootstrap/lib.rs +++ b/src/bootstrap/lib.rs @@ -450,6 +450,7 @@ impl Build { // FIXME: the guard against msvc shouldn't need to be here if !target.contains("msvc") { cargo.env(format!("CC_{}", target), self.cc(target)) + .env(format!("CXX_{}", target), self.cxx(target)) .env(format!("AR_{}", target), self.ar(target).unwrap()) // only msvc is None .env(format!("CFLAGS_{}", target), self.cflags(target).join(" ")); } From f98ffb5bc348d1b11f10ebd5f4c5e2fe2813e167 Mon Sep 17 00:00:00 2001 From: Ian Douglas Scott Date: Thu, 22 Jun 2017 11:51:32 -0700 Subject: [PATCH 07/12] Make Build.cxx() return a Result instead of panicking --- src/bootstrap/check.rs | 2 +- src/bootstrap/compile.rs | 2 +- src/bootstrap/lib.rs | 17 ++++++++++------- src/bootstrap/native.rs | 2 +- src/bootstrap/sanity.rs | 2 +- 5 files changed, 14 insertions(+), 11 deletions(-) diff --git a/src/bootstrap/check.rs b/src/bootstrap/check.rs index 068efe18cce3d..277728b90b763 100644 --- a/src/bootstrap/check.rs +++ b/src/bootstrap/check.rs @@ -265,7 +265,7 @@ pub fn compiletest(build: &Build, let llvm_components = output(Command::new(&llvm_config).arg("--components")); let llvm_cxxflags = output(Command::new(&llvm_config).arg("--cxxflags")); cmd.arg("--cc").arg(build.cc(target)) - .arg("--cxx").arg(build.cxx(target)) + .arg("--cxx").arg(build.cxx(target).unwrap()) .arg("--cflags").arg(build.cflags(target).join(" ")) .arg("--llvm-components").arg(llvm_components.trim()) .arg("--llvm-cxxflags").arg(llvm_cxxflags.trim()); diff --git a/src/bootstrap/compile.rs b/src/bootstrap/compile.rs index f92a199fa3fea..c8ab3a8fc1d99 100644 --- a/src/bootstrap/compile.rs +++ b/src/bootstrap/compile.rs @@ -291,7 +291,7 @@ pub fn rustc(build: &Build, target: &str, compiler: &Compiler) { !target.contains("windows") && !target.contains("apple") { cargo.env("LLVM_STATIC_STDCPP", - compiler_file(build.cxx(target), "libstdc++.a")); + compiler_file(build.cxx(target).unwrap(), "libstdc++.a")); } if build.config.llvm_link_shared { cargo.env("LLVM_LINK_SHARED", "1"); diff --git a/src/bootstrap/lib.rs b/src/bootstrap/lib.rs index 3a43cc0c29d8e..ce7cde8fc9494 100644 --- a/src/bootstrap/lib.rs +++ b/src/bootstrap/lib.rs @@ -450,9 +450,12 @@ impl Build { // FIXME: the guard against msvc shouldn't need to be here if !target.contains("msvc") { cargo.env(format!("CC_{}", target), self.cc(target)) - .env(format!("CXX_{}", target), self.cxx(target)) .env(format!("AR_{}", target), self.ar(target).unwrap()) // only msvc is None .env(format!("CFLAGS_{}", target), self.cflags(target).join(" ")); + + if let Ok(cxx) = self.cxx(target) { + cargo.env(format!("CXX_{}", target), cxx); + } } if self.config.extended && compiler.is_final_stage(self) { @@ -839,13 +842,13 @@ impl Build { self.cc[target].1.as_ref().map(|p| &**p) } - /// Returns the path to the C++ compiler for the target specified, may panic - /// if no C++ compiler was configured for the target. - fn cxx(&self, target: &str) -> &Path { + /// Returns the path to the C++ compiler for the target specified. + fn cxx(&self, target: &str) -> Result<&Path, String> { match self.cxx.get(target) { - Some(p) => p.path(), - None => panic!("\n\ntarget `{}` is not configured as a host, - only as a target\n\n", target), + Some(p) => Ok(p.path()), + None => Err(format!( + "target `{}` is not configured as a host, only as a target", + target)) } } diff --git a/src/bootstrap/native.rs b/src/bootstrap/native.rs index a23be37b15e0e..f150df6cdcdb0 100644 --- a/src/bootstrap/native.rs +++ b/src/bootstrap/native.rs @@ -155,7 +155,7 @@ pub fn llvm(build: &Build, target: &str) { } let cc = build.cc(target); - let cxx = build.cxx(target); + let cxx = build.cxx(target).unwrap(); // Handle msvc + ninja + ccache specially (this is what the bots use) if target.contains("msvc") && diff --git a/src/bootstrap/sanity.rs b/src/bootstrap/sanity.rs index 5ccd131b77ae4..46d047bb015e5 100644 --- a/src/bootstrap/sanity.rs +++ b/src/bootstrap/sanity.rs @@ -139,7 +139,7 @@ pub fn check(build: &mut Build) { } } for host in build.config.host.iter() { - need_cmd(build.cxx(host).as_ref()); + need_cmd(build.cxx(host).unwrap().as_ref()); } // The msvc hosts don't use jemalloc, turn it off globally to From 0883ce1b43ab2e3dd28c76e1c525c8db72cadef1 Mon Sep 17 00:00:00 2001 From: Alex Burka Date: Thu, 22 Jun 2017 19:10:56 +0000 Subject: [PATCH 08/12] change span label for E0435 (fix #41871) --- src/librustc_resolve/lib.rs | 2 +- src/test/compile-fail/E0435.rs | 2 +- src/test/compile-fail/non-constant-expr-for-vec-repeat.rs | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs index b20cd8908be18..8c11aa7def8a5 100644 --- a/src/librustc_resolve/lib.rs +++ b/src/librustc_resolve/lib.rs @@ -325,7 +325,7 @@ fn resolve_struct_error<'sess, 'a>(resolver: &'sess Resolver, span, E0435, "attempt to use a non-constant value in a constant"); - err.span_label(span, "non-constant used with constant"); + err.span_label(span, "non-constant value"); err } ResolutionError::BindingShadowsSomethingUnacceptable(what_binding, name, binding) => { diff --git a/src/test/compile-fail/E0435.rs b/src/test/compile-fail/E0435.rs index b15bf44fbd063..50a6d174e222a 100644 --- a/src/test/compile-fail/E0435.rs +++ b/src/test/compile-fail/E0435.rs @@ -11,5 +11,5 @@ fn main () { let foo = 42u32; let _: [u8; foo]; //~ ERROR E0435 - //~| NOTE non-constant used with constant + //~| NOTE non-constant value } diff --git a/src/test/compile-fail/non-constant-expr-for-vec-repeat.rs b/src/test/compile-fail/non-constant-expr-for-vec-repeat.rs index 1eda508778402..7c2eaecda670f 100644 --- a/src/test/compile-fail/non-constant-expr-for-vec-repeat.rs +++ b/src/test/compile-fail/non-constant-expr-for-vec-repeat.rs @@ -14,6 +14,6 @@ fn main() { fn bar(n: usize) { let _x = [0; n]; //~^ ERROR attempt to use a non-constant value in a constant [E0435] - //~| NOTE non-constant used with constant + //~| NOTE non-constant value } } From 369d4f18838027573e73b433b8cb25c96280fb0c Mon Sep 17 00:00:00 2001 From: Alex Burka Date: Thu, 22 Jun 2017 19:13:09 +0000 Subject: [PATCH 09/12] remove duplicate E0435 test --- ...eat.rs => non-constant-expr-for-arr-len.rs} | 2 +- .../non-constant-expr-for-fixed-len-vec.rs | 18 ------------------ 2 files changed, 1 insertion(+), 19 deletions(-) rename src/test/compile-fail/{non-constant-expr-for-vec-repeat.rs => non-constant-expr-for-arr-len.rs} (91%) delete mode 100644 src/test/compile-fail/non-constant-expr-for-fixed-len-vec.rs diff --git a/src/test/compile-fail/non-constant-expr-for-vec-repeat.rs b/src/test/compile-fail/non-constant-expr-for-arr-len.rs similarity index 91% rename from src/test/compile-fail/non-constant-expr-for-vec-repeat.rs rename to src/test/compile-fail/non-constant-expr-for-arr-len.rs index 7c2eaecda670f..17df7ae2347f2 100644 --- a/src/test/compile-fail/non-constant-expr-for-vec-repeat.rs +++ b/src/test/compile-fail/non-constant-expr-for-arr-len.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// Check that non constant exprs fail for vector repeat syntax +// Check that non constant exprs fail for array repeat syntax fn main() { fn bar(n: usize) { diff --git a/src/test/compile-fail/non-constant-expr-for-fixed-len-vec.rs b/src/test/compile-fail/non-constant-expr-for-fixed-len-vec.rs deleted file mode 100644 index 52cd4e8a3ed95..0000000000000 --- a/src/test/compile-fail/non-constant-expr-for-fixed-len-vec.rs +++ /dev/null @@ -1,18 +0,0 @@ -// Copyright 2012-2013 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// Check that non-constant exprs do fail as count in fixed length vec type - -fn main() { - fn bar(n: isize) { - let _x: [isize; n]; - //~^ ERROR attempt to use a non-constant value in a constant [E0435] - } -} From 4711982314ba33cab83704c26484b501c8652774 Mon Sep 17 00:00:00 2001 From: kennytm Date: Tue, 20 Jun 2017 15:15:16 +0800 Subject: [PATCH 10/12] Removed as many "```ignore" as possible. Replaced by adding extra imports, adding hidden code (`# ...`), modifying examples to be runnable (sorry Homura), specifying non-Rust code, and converting to should_panic, no_run, or compile_fail. Remaining "```ignore"s received an explanation why they are being ignored. --- src/liballoc/boxed.rs | 4 +- src/liballoc/fmt.rs | 2 +- src/liballoc/raw_vec.rs | 22 +++- src/liballoc/string.rs | 2 +- src/liballoc/vec.rs | 2 +- src/libcore/iter/mod.rs | 2 +- src/libcore/marker.rs | 2 +- src/libcore/mem.rs | 15 ++- src/libcore/ops/place.rs | 18 ++- src/libcore/ops/range.rs | 7 +- src/libcore/panicking.rs | 6 +- src/libcore/ptr.rs | 12 +- src/libgraphviz/lib.rs | 2 +- src/librustc/diagnostics.rs | 99 +++++++++----- src/librustc_borrowck/borrowck/check_loans.rs | 11 +- src/librustc_borrowck/diagnostics.rs | 32 ++++- src/librustc_const_eval/diagnostics.rs | 8 +- src/librustc_metadata/diagnostics.rs | 6 +- src/librustc_metadata/locator.rs | 2 +- src/librustc_mir/build/matches/mod.rs | 3 +- src/librustc_mir/build/scope.rs | 7 +- src/librustc_passes/diagnostics.rs | 8 +- src/librustc_plugin/lib.rs | 16 ++- src/librustc_privacy/diagnostics.rs | 10 +- src/librustc_resolve/diagnostics.rs | 98 ++++++++------ src/librustc_trans/diagnostics.rs | 2 +- src/librustc_typeck/diagnostics.rs | 121 +++++++++++++----- src/librustdoc/html/markdown.rs | 2 +- src/libserialize/json.rs | 2 +- src/libstd/macros.rs | 8 +- src/libstd/memchr.rs | 4 +- src/libstd/prelude/mod.rs | 5 +- src/libstd/primitive_docs.rs | 6 +- src/libstd/process.rs | 8 +- src/libstd/sys/redox/ext/fs.rs | 52 +++++--- src/libstd/sys/unix/ext/fs.rs | 22 +++- src/libstd/sys/windows/ext/fs.rs | 8 +- src/libstd/sys_common/thread_local.rs | 8 +- src/libsyntax/ast.rs | 8 +- src/libsyntax/diagnostic_list.rs | 6 +- src/libsyntax/parse/parser.rs | 2 +- src/libsyntax/print/pp.rs | 2 +- src/libsyntax_ext/deriving/encodable.rs | 12 +- src/libsyntax_ext/deriving/generic/mod.rs | 12 +- src/libsyntax_ext/format.rs | 3 +- 45 files changed, 458 insertions(+), 231 deletions(-) diff --git a/src/liballoc/boxed.rs b/src/liballoc/boxed.rs index 2f867912f5824..4a43018e973b1 100644 --- a/src/liballoc/boxed.rs +++ b/src/liballoc/boxed.rs @@ -42,8 +42,10 @@ //! Recursive structures must be boxed, because if the definition of `Cons` //! looked like this: //! -//! ```rust,ignore +//! ```compile_fail,E0072 +//! # enum List { //! Cons(T, List), +//! # } //! ``` //! //! It wouldn't work. This is because the size of a `List` depends on how many diff --git a/src/liballoc/fmt.rs b/src/liballoc/fmt.rs index 62a8816462191..1bd95fb82aa4d 100644 --- a/src/liballoc/fmt.rs +++ b/src/liballoc/fmt.rs @@ -230,7 +230,7 @@ //! There are a number of related macros in the `format!` family. The ones that //! are currently implemented are: //! -//! ```ignore +//! ```ignore (only-for-syntax-highlight) //! format! // described above //! write! // first argument is a &mut io::Write, the destination //! writeln! // same as write but appends a newline diff --git a/src/liballoc/raw_vec.rs b/src/liballoc/raw_vec.rs index 7117c4468211e..c56a93c046041 100644 --- a/src/liballoc/raw_vec.rs +++ b/src/liballoc/raw_vec.rs @@ -244,7 +244,11 @@ impl RawVec { /// /// # Examples /// - /// ```ignore + /// ``` + /// # #![feature(alloc)] + /// # extern crate alloc; + /// # use std::ptr; + /// # use alloc::raw_vec::RawVec; /// struct MyVec { /// buf: RawVec, /// len: usize, @@ -261,6 +265,10 @@ impl RawVec { /// self.len += 1; /// } /// } + /// # fn main() { + /// # let mut vec = MyVec { buf: RawVec::new(), len: 0 }; + /// # vec.push(1); + /// # } /// ``` #[inline(never)] #[cold] @@ -440,13 +448,17 @@ impl RawVec { /// /// # Examples /// - /// ```ignore + /// ``` + /// # #![feature(alloc)] + /// # extern crate alloc; + /// # use std::ptr; + /// # use alloc::raw_vec::RawVec; /// struct MyVec { /// buf: RawVec, /// len: usize, /// } /// - /// impl MyVec { + /// impl MyVec { /// pub fn push_all(&mut self, elems: &[T]) { /// self.buf.reserve(self.len, elems.len()); /// // reserve would have aborted or panicked if the len exceeded @@ -459,6 +471,10 @@ impl RawVec { /// } /// } /// } + /// # fn main() { + /// # let mut vector = MyVec { buf: RawVec::new(), len: 0 }; + /// # vector.push_all(&[1, 3, 5, 7, 9]); + /// # } /// ``` pub fn reserve(&mut self, used_cap: usize, needed_extra_cap: usize) { unsafe { diff --git a/src/liballoc/string.rs b/src/liballoc/string.rs index 2cb81029f95e2..79d1ccf637d37 100644 --- a/src/liballoc/string.rs +++ b/src/liballoc/string.rs @@ -124,7 +124,7 @@ use boxed::Box; /// similar, but without the UTF-8 constraint. The second implication is that /// you cannot index into a `String`: /// -/// ```ignore +/// ```compile_fail,E0277 /// let s = "hello"; /// /// println!("The first letter of s is {}", s[0]); // ERROR!!! diff --git a/src/liballoc/vec.rs b/src/liballoc/vec.rs index c9c7a27c614fa..5d1999a42629a 100644 --- a/src/liballoc/vec.rs +++ b/src/liballoc/vec.rs @@ -156,7 +156,7 @@ use Bound::{Excluded, Included, Unbounded}; /// However be careful: if you try to access an index which isn't in the `Vec`, /// your software will panic! You cannot do this: /// -/// ```ignore +/// ```should_panic /// let v = vec![0, 2, 4, 6]; /// println!("{}", v[6]); // it will panic! /// ``` diff --git a/src/libcore/iter/mod.rs b/src/libcore/iter/mod.rs index c91fd16391aaf..d6a9be4437d43 100644 --- a/src/libcore/iter/mod.rs +++ b/src/libcore/iter/mod.rs @@ -211,7 +211,7 @@ //! There's one more subtle bit here: the standard library contains an //! interesting implementation of [`IntoIterator`]: //! -//! ```ignore +//! ```ignore (only-for-syntax-highlight) //! impl IntoIterator for I //! ``` //! diff --git a/src/libcore/marker.rs b/src/libcore/marker.rs index 3bed425943f78..e8fd729b638be 100644 --- a/src/libcore/marker.rs +++ b/src/libcore/marker.rs @@ -434,7 +434,7 @@ macro_rules! impls{ /// example, here is a struct `Slice` that has two pointers of type `*const T`, /// presumably pointing into an array somewhere: /// -/// ```ignore +/// ```compile_fail,E0392 /// struct Slice<'a, T> { /// start: *const T, /// end: *const T, diff --git a/src/libcore/mem.rs b/src/libcore/mem.rs index 509b396f211bb..bba42752f50c6 100644 --- a/src/libcore/mem.rs +++ b/src/libcore/mem.rs @@ -328,11 +328,18 @@ pub fn align_of_val(val: &T) -> usize { /// /// Here's an example of how a collection might make use of needs_drop: /// -/// ```ignore +/// ``` /// #![feature(needs_drop)] /// use std::{mem, ptr}; /// -/// pub struct MyCollection { /* ... */ } +/// pub struct MyCollection { +/// # data: [T; 1], +/// /* ... */ +/// } +/// # impl MyCollection { +/// # fn iter_mut(&mut self) -> &mut [T] { &mut self.data } +/// # fn free_buffer(&mut self) {} +/// # } /// /// impl Drop for MyCollection { /// fn drop(&mut self) { @@ -575,7 +582,7 @@ pub fn swap(x: &mut T, y: &mut T) { /// `replace` allows consumption of a struct field by replacing it with another value. /// Without `replace` you can run into issues like these: /// -/// ```ignore +/// ```compile_fail,E0507 /// struct Buffer { buf: Vec } /// /// impl Buffer { @@ -645,7 +652,7 @@ pub fn replace(dest: &mut T, mut src: T) -> T { /// /// Borrows are based on lexical scope, so this produces an error: /// -/// ```ignore +/// ```compile_fail,E0502 /// let mut v = vec![1, 2, 3]; /// let x = &v[0]; /// diff --git a/src/libcore/ops/place.rs b/src/libcore/ops/place.rs index 996a741c96f93..19da887cbbfbe 100644 --- a/src/libcore/ops/place.rs +++ b/src/libcore/ops/place.rs @@ -38,7 +38,13 @@ pub trait Place { /// /// `PLACE <- EXPR` effectively desugars into: /// -/// ```rust,ignore +/// ``` +/// # #![feature(placement_new_protocol, box_heap)] +/// # use std::ops::{Placer, Place, InPlace}; +/// # #[allow(non_snake_case)] +/// # fn main() { +/// # let PLACE = std::boxed::HEAP; +/// # let EXPR = 1; /// let p = PLACE; /// let mut place = Placer::make_place(p); /// let raw_place = Place::pointer(&mut place); @@ -47,6 +53,7 @@ pub trait Place { /// std::ptr::write(raw_place, value); /// InPlace::finalize(place) /// } +/// # ; } /// ``` /// /// The type of `PLACE <- EXPR` is derived from the type of `PLACE`; @@ -89,14 +96,21 @@ pub trait InPlace: Place { /// /// `box EXPR` effectively desugars into: /// -/// ```rust,ignore +/// ``` +/// # #![feature(placement_new_protocol)] +/// # use std::ops::{BoxPlace, Place, Boxed}; +/// # #[allow(non_snake_case)] +/// # fn main() { +/// # let EXPR = 1; /// let mut place = BoxPlace::make_place(); /// let raw_place = Place::pointer(&mut place); /// let value = EXPR; +/// # let _: Box<_> = /// unsafe { /// ::std::ptr::write(raw_place, value); /// Boxed::finalize(place) /// } +/// # ; } /// ``` /// /// The type of `box EXPR` is supplied from its surrounding diff --git a/src/libcore/ops/range.rs b/src/libcore/ops/range.rs index 70c35df87ddaf..33258b7a875c5 100644 --- a/src/libcore/ops/range.rs +++ b/src/libcore/ops/range.rs @@ -26,7 +26,7 @@ use fmt; /// It does not have an `IntoIterator` implementation, so you can't use it in a /// `for` loop directly. This won't compile: /// -/// ```ignore +/// ```compile_fail,E0277 /// for i in .. { /// // ... /// } @@ -184,7 +184,7 @@ impl> RangeFrom { /// It does not have an `IntoIterator` implementation, so you can't use it in a /// `for` loop directly. This won't compile: /// -/// ```ignore +/// ```compile_fail,E0277 /// for i in ..5 { /// // ... /// } @@ -313,7 +313,8 @@ impl> RangeInclusive { /// It does not have an `IntoIterator` implementation, so you can't use it in a /// `for` loop directly. This won't compile: /// -/// ```ignore +/// ```compile_fail,E0277 +/// #![feature(inclusive_range_syntax)] /// for i in ...5 { /// // ... /// } diff --git a/src/libcore/panicking.rs b/src/libcore/panicking.rs index 93ddfa72f63ca..60b7669f3b2d9 100644 --- a/src/libcore/panicking.rs +++ b/src/libcore/panicking.rs @@ -15,8 +15,10 @@ //! useful an upstream crate must define panicking for libcore to use. The current //! interface for panicking is: //! -//! ```ignore -//! fn panic_impl(fmt: fmt::Arguments, &(&'static str, u32)) -> !; +//! ``` +//! # use std::fmt; +//! fn panic_impl(fmt: fmt::Arguments, file_line: &(&'static str, u32)) -> ! +//! # { loop {} } //! ``` //! //! This definition allows for panicking with any general message, but it does not diff --git a/src/libcore/ptr.rs b/src/libcore/ptr.rs index f89f86e18a149..54ae9e0d628d5 100644 --- a/src/libcore/ptr.rs +++ b/src/libcore/ptr.rs @@ -408,11 +408,11 @@ impl *const T { /// /// Basic usage: /// - /// ```ignore - /// let val: *const u8 = &10u8 as *const u8; + /// ``` + /// let ptr: *const u8 = &10u8 as *const u8; /// /// unsafe { - /// if let Some(val_back) = val.as_ref() { + /// if let Some(val_back) = ptr.as_ref() { /// println!("We got back the value: {}!", val_back); /// } /// } @@ -570,11 +570,11 @@ impl *mut T { /// /// Basic usage: /// - /// ```ignore - /// let val: *mut u8 = &mut 10u8 as *mut u8; + /// ``` + /// let ptr: *mut u8 = &mut 10u8 as *mut u8; /// /// unsafe { - /// if let Some(val_back) = val.as_ref() { + /// if let Some(val_back) = ptr.as_ref() { /// println!("We got back the value: {}!", val_back); /// } /// } diff --git a/src/libgraphviz/lib.rs b/src/libgraphviz/lib.rs index 6a5edc9f9e90f..7412a01e11e1e 100644 --- a/src/libgraphviz/lib.rs +++ b/src/libgraphviz/lib.rs @@ -111,7 +111,7 @@ //! //! Output from first example (in `example1.dot`): //! -//! ```ignore +//! ```dot //! digraph example1 { //! N0[label="N0"]; //! N1[label="N1"]; diff --git a/src/librustc/diagnostics.rs b/src/librustc/diagnostics.rs index 4d378b0bf7dd3..5e36bd8ec2772 100644 --- a/src/librustc/diagnostics.rs +++ b/src/librustc/diagnostics.rs @@ -198,7 +198,12 @@ impl Trait for u8 { Now, if we have the following code: -```ignore +```compile_fail,E0038 +# trait Trait { fn foo(&self, on: T); } +# impl Trait for String { fn foo(&self, on: T) {} } +# impl Trait for u8 { fn foo(&self, on: T) {} } +# impl Trait for bool { fn foo(&self, on: T) {} } +# // etc. fn call_foo(thing: Box) { thing.foo(true); // this could be any one of the 8 types above thing.foo(1); @@ -565,8 +570,9 @@ fn foo(argc: isize, argv: *const *const u8) -> isize { 0 } // ok! ``` "##, -// isn't thrown anymore E0139: r##" +#### Note: this error code is no longer emitted by the compiler. + There are various restrictions on transmuting between types in Rust; for example types being transmuted must have the same size. To apply all these restrictions, the compiler must know the exact types that may be transmuted. When type @@ -602,22 +608,24 @@ If it's possible, hand-monomorphize the code by writing the function for each possible type substitution. It's possible to use traits to do this cleanly, for example: -```ignore +``` +use std::mem::transmute; + struct Foo(Vec); -trait MyTransmutableType { +trait MyTransmutableType: Sized { fn transmute(Vec) -> Foo; } impl MyTransmutableType for u8 { - fn transmute(x: Foo) -> Vec { - transmute(x) + fn transmute(x: Vec) -> Foo { + unsafe { transmute(x) } } } impl MyTransmutableType for String { - fn transmute(x: Foo) -> Vec { - transmute(x) + fn transmute(x: Vec) -> Foo { + unsafe { transmute(x) } } } @@ -635,8 +643,14 @@ is a size mismatch in one of the impls. It is also possible to manually transmute: -```ignore -ptr::read(&v as *const _ as *const SomeType) // `v` transmuted to `SomeType` +``` +# use std::ptr; +# let v = Some("value"); +# type SomeType = &'static [u8]; +unsafe { + ptr::read(&v as *const _ as *const SomeType) // `v` transmuted to `SomeType` +} +# ; ``` Note that this does not move `v` (unlike `transmute`), and may need a @@ -662,7 +676,7 @@ them yourself. You can build a free-standing crate by adding `#![no_std]` to the crate attributes: -```ignore +```ignore (only-for-syntax-highlight) #![no_std] ``` @@ -764,7 +778,7 @@ foo(3_i8); Here is that same example again, with some explanatory comments: -```ignore +```compile_fail,E0271 trait Trait { type AssociatedType; } fn foo(t: T) where T: Trait { @@ -784,7 +798,7 @@ fn foo(t: T) where T: Trait { } impl Trait for i8 { type AssociatedType = &'static str; } -~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +//~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // | | // `i8` does have | // implementation | @@ -816,7 +830,7 @@ The above fails because of an analogous type mismatch, though may be harder to see. Again, here are some explanatory comments for the same example: -```ignore +```compile_fail { let vs = vec![1, 2, 3, 4]; @@ -1416,6 +1430,8 @@ trait SecondTrait : FirstTrait { "##, E0398: r##" +#### Note: this error code is no longer emitted by the compiler. + In Rust 1.3, the default object lifetime bounds are expected to change, as described in [RFC 1156]. You are getting a warning because the compiler thinks it is possible that this change will cause a compilation error in your @@ -1433,14 +1449,16 @@ time, this means that you will want to change the signature of a function that you are calling. For example, if the error is reported on a call like `foo(x)`, and `foo` is defined as follows: -```ignore -fn foo(arg: &Box) { ... } +``` +# trait SomeTrait {} +fn foo(arg: &Box) { /* ... */ } ``` You might change it to: -```ignore -fn foo<'a>(arg: &Box) { ... } +``` +# trait SomeTrait {} +fn foo<'a>(arg: &'a Box) { /* ... */ } ``` This explicitly states that you expect the trait object `SomeTrait` to contain @@ -1809,24 +1827,29 @@ specified exit code, use `std::process::exit`. E0591: r##" Per [RFC 401][rfc401], if you have a function declaration `foo`: -```rust,ignore +``` // For the purposes of this explanation, all of these // different kinds of `fn` declarations are equivalent: -fn foo(x: i32) { ... } -extern "C" fn foo(x: i32); -impl i32 { fn foo(x: self) { ... } } +struct S; +fn foo(x: S) { /* ... */ } +# #[cfg(for_demonstration_only)] +extern "C" { fn foo(x: S); } +# #[cfg(for_demonstration_only)] +impl S { fn foo(self) { /* ... */ } } ``` -the type of `foo` is **not** `fn(i32)`, as one might expect. +the type of `foo` is **not** `fn(S)`, as one might expect. Rather, it is a unique, zero-sized marker type written here as `typeof(foo)`. -However, `typeof(foo)` can be _coerced_ to a function pointer `fn(i32)`, +However, `typeof(foo)` can be _coerced_ to a function pointer `fn(S)`, so you rarely notice this: -```rust,ignore -let x: fn(i32) = foo; // OK, coerces +``` +# struct S; +# fn foo(_: S) {} +let x: fn(S) = foo; // OK, coerces ``` -The reason that this matter is that the type `fn(i32)` is not specific to +The reason that this matter is that the type `fn(S)` is not specific to any particular function: it's a function _pointer_. So calling `x()` results in a virtual call, whereas `foo()` is statically dispatched, because the type of `foo` tells us precisely what function is being called. @@ -1837,14 +1860,17 @@ when using **transmute** to convert a fn item into a fn pointer. This is sometimes done as part of an FFI: -```rust,ignore +```compile_fail,E0591 extern "C" fn foo(userdata: Box) { - ... + /* ... */ } +# fn callback(_: extern "C" fn(*mut i32)) {} +# use std::mem::transmute; +# unsafe { let f: extern "C" fn(*mut i32) = transmute(foo); callback(f); - +# } ``` Here, transmute is being used to convert the types of the fn arguments. @@ -1856,8 +1882,15 @@ This pattern should be rewritten. There are a few possible ways to do this: - change the original fn declaration to match the expected signature, and do the cast in the fn body (the prefered option) - cast the fn item fo a fn pointer before calling transmute, as shown here: - - `let f: extern "C" fn(*mut i32) = transmute(foo as extern "C" fn(_))` - - `let f: extern "C" fn(*mut i32) = transmute(foo as usize) /* works too */` + + ``` + # extern "C" fn foo(_: Box) {} + # use std::mem::transmute; + # unsafe { + let f: extern "C" fn(*mut i32) = transmute(foo as extern "C" fn(_)); + let f: extern "C" fn(*mut i32) = transmute(foo as usize); // works too + # } + ``` The same applies to transmutes to `*mut fn()`, which were observedin practice. Note though that use of this type is generally incorrect. @@ -1905,7 +1938,7 @@ An unknown lint was used on the command line. Erroneous example: -```ignore +```sh rustc -D bogus omse_file.rs ``` diff --git a/src/librustc_borrowck/borrowck/check_loans.rs b/src/librustc_borrowck/borrowck/check_loans.rs index ae2be28c198bf..b84cd212c4ab4 100644 --- a/src/librustc_borrowck/borrowck/check_loans.rs +++ b/src/librustc_borrowck/borrowck/check_loans.rs @@ -755,15 +755,20 @@ impl<'a, 'tcx> CheckLoanCtxt<'a, 'tcx> { /// /// For example: /// - /// ```ignore + /// ``` /// let a: i32; /// a = 10; // ok, even though a is uninitialized + /// ``` /// + /// ``` /// struct Point { x: u32, y: u32 } - /// let p: Point; + /// let mut p: Point; /// p.x = 22; // ok, even though `p` is uninitialized + /// ``` /// - /// let p: Box; + /// ```compile_fail,E0381 + /// # struct Point { x: u32, y: u32 } + /// let mut p: Box; /// (*p).x = 22; // not ok, p is uninitialized, can't deref /// ``` fn check_if_assigned_path_is_moved(&self, diff --git a/src/librustc_borrowck/diagnostics.rs b/src/librustc_borrowck/diagnostics.rs index c114c66559ff6..38dcc73123691 100644 --- a/src/librustc_borrowck/diagnostics.rs +++ b/src/librustc_borrowck/diagnostics.rs @@ -153,10 +153,13 @@ structure that is currently uninitialized. For example, this can happen when a drop has taken place: -```ignore +```compile_fail,E0383 struct Foo { a: u32, } +impl Drop for Foo { + fn drop(&mut self) { /* ... */ } +} let mut x = Foo { a: 1 }; drop(x); // `x` is now uninitialized @@ -169,6 +172,9 @@ This error can be fixed by fully reinitializing the structure in question: struct Foo { a: u32, } +impl Drop for Foo { + fn drop(&mut self) { /* ... */ } +} let mut x = Foo { a: 1 }; drop(x); @@ -944,10 +950,9 @@ fn main() { } ``` -Moving out of a member of a mutably borrowed struct is fine if you put something -back. `mem::replace` can be used for that: +Moving a member out of a mutably borrowed struct will also cause E0507 error: -```ignore +```compile_fail,E0507 struct TheDarkKnight; impl TheDarkKnight { @@ -959,18 +964,31 @@ struct Batcave { } fn main() { - use std::mem; - let mut cave = Batcave { knight: TheDarkKnight }; let borrowed = &mut cave; borrowed.knight.nothing_is_true(); // E0507 - mem::replace(&mut borrowed.knight, TheDarkKnight).nothing_is_true(); // ok! } ``` +It is fine only if you put something back. `mem::replace` can be used for that: + +``` +# struct TheDarkKnight; +# impl TheDarkKnight { fn nothing_is_true(self) {} } +# struct Batcave { knight: TheDarkKnight } +use std::mem; + +let mut cave = Batcave { + knight: TheDarkKnight +}; +let borrowed = &mut cave; + +mem::replace(&mut borrowed.knight, TheDarkKnight).nothing_is_true(); // ok! +``` + You can find more information about borrowing in the rust-book: http://doc.rust-lang.org/book/first-edition/references-and-borrowing.html "##, diff --git a/src/librustc_const_eval/diagnostics.rs b/src/librustc_const_eval/diagnostics.rs index 4fc7ef8035eb5..56d08184a0f17 100644 --- a/src/librustc_const_eval/diagnostics.rs +++ b/src/librustc_const_eval/diagnostics.rs @@ -436,17 +436,19 @@ that happens. Qualified names are good practice, and most code works well with them. But if you prefer them unqualified, you can import the variants into scope: -```ignore +``` use Method::*; enum Method { GET, POST } +# fn main() {} ``` If you want others to be able to import variants from your module directly, use `pub use`: -```ignore +``` pub use Method::*; -enum Method { GET, POST } +pub enum Method { GET, POST } +# fn main() {} ``` "##, diff --git a/src/librustc_metadata/diagnostics.rs b/src/librustc_metadata/diagnostics.rs index 9a174e05eabd4..1fa1a896dd6b6 100644 --- a/src/librustc_metadata/diagnostics.rs +++ b/src/librustc_metadata/diagnostics.rs @@ -21,7 +21,7 @@ A link name was given with an empty name. Erroneous code example: The rust compiler cannot link to an external library if you don't give it its name. Example: -```ignore +```no_run #[link(name = "some_lib")] extern {} // ok! ``` "##, @@ -32,7 +32,7 @@ as frameworks are specific to that operating system. Erroneous code example: -```ignore +```ignore (should-compile_fail-but-cannot-doctest-conditionally-without-macos) #[link(name = "FooCoreServices", kind = "framework")] extern {} // OS used to compile is Linux for example ``` @@ -75,7 +75,7 @@ A link was used without a name parameter. Erroneous code example: Please add the name parameter to allow the rust compiler to find the library you want. Example: -```ignore +```no_run #[link(kind = "dylib", name = "some_lib")] extern {} // ok! ``` "##, diff --git a/src/librustc_metadata/locator.rs b/src/librustc_metadata/locator.rs index 7a3575cb50bd7..ff74698deab3f 100644 --- a/src/librustc_metadata/locator.rs +++ b/src/librustc_metadata/locator.rs @@ -150,7 +150,7 @@ //! the compiler. For example, if crate A wanted to use Bv1 and Bv2, then it //! would look something like: //! -//! ```ignore +//! ```compile_fail,E0463 //! extern crate b1; //! extern crate b2; //! diff --git a/src/librustc_mir/build/matches/mod.rs b/src/librustc_mir/build/matches/mod.rs index 2505e2f8211b0..54f285480ab53 100644 --- a/src/librustc_mir/build/matches/mod.rs +++ b/src/librustc_mir/build/matches/mod.rs @@ -471,7 +471,8 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { /// But there may also be candidates that the test just doesn't /// apply to. The classical example involves wildcards: /// - /// ```rust,ignore + /// ``` + /// # let (x, y, z) = (true, true, true); /// match (x, y, z) { /// (true, _, true) => true, // (0) /// (_, true, _) => true, // (1) diff --git a/src/librustc_mir/build/scope.rs b/src/librustc_mir/build/scope.rs index 469fd5750a2f9..2244ffde3c9d0 100644 --- a/src/librustc_mir/build/scope.rs +++ b/src/librustc_mir/build/scope.rs @@ -47,11 +47,12 @@ set of scheduled drops up front, and so whenever we exit from the scope we only drop the values scheduled thus far. For example, consider the scope S corresponding to this loop: -```rust,ignore +``` +# let cond = true; loop { - let x = ...; + let x = ..; if cond { break; } - let y = ...; + let y = ..; } ``` diff --git a/src/librustc_passes/diagnostics.rs b/src/librustc_passes/diagnostics.rs index 036a52d5a3db3..464dd72e56986 100644 --- a/src/librustc_passes/diagnostics.rs +++ b/src/librustc_passes/diagnostics.rs @@ -154,7 +154,7 @@ E0449: r##" A visibility qualifier was used when it was unnecessary. Erroneous code examples: -```compile_fail +```compile_fail,E0449 struct Bar; trait Foo { @@ -171,7 +171,7 @@ pub impl Foo for Bar { // error: unnecessary visibility qualifier To fix this error, please remove the visibility qualifier when it is not required. Example: -```ignore +``` struct Bar; trait Foo { @@ -184,8 +184,8 @@ impl Bar {} // Trait methods share the visibility of the trait, so `pub` is // unnecessary in either case -pub impl Foo for Bar { - pub fn foo() {} +impl Foo for Bar { + fn foo() {} } ``` "##, diff --git a/src/librustc_plugin/lib.rs b/src/librustc_plugin/lib.rs index d43625e3c23ff..1de31c5d79154 100644 --- a/src/librustc_plugin/lib.rs +++ b/src/librustc_plugin/lib.rs @@ -20,21 +20,31 @@ //! To define a plugin, build a dylib crate with a //! `#[plugin_registrar]` function: //! -//! ```rust,ignore +//! ```no_run //! #![crate_name = "myplugin"] //! #![crate_type = "dylib"] //! #![feature(plugin_registrar)] +//! #![feature(rustc_private)] //! -//! extern crate rustc; +//! extern crate rustc_plugin; +//! extern crate syntax; +//! extern crate syntax_pos; //! //! use rustc_plugin::Registry; +//! use syntax::ext::base::{ExtCtxt, MacResult}; +//! use syntax_pos::Span; +//! use syntax::tokenstream::TokenTree; //! //! #[plugin_registrar] //! pub fn plugin_registrar(reg: &mut Registry) { //! reg.register_macro("mymacro", expand_mymacro); //! } //! -//! fn expand_mymacro(...) { // details elided +//! fn expand_mymacro(cx: &mut ExtCtxt, span: Span, tt: &[TokenTree]) -> Box { +//! unimplemented!() +//! } +//! +//! # fn main() {} //! ``` //! //! WARNING: We currently don't check that the registrar function diff --git a/src/librustc_privacy/diagnostics.rs b/src/librustc_privacy/diagnostics.rs index 49f2ccb7c57f5..f8559954db12b 100644 --- a/src/librustc_privacy/diagnostics.rs +++ b/src/librustc_privacy/diagnostics.rs @@ -32,7 +32,7 @@ To solve this error, please ensure that the trait is also public. The trait can be made inaccessible if necessary by placing it into a private inner module, but it still has to be marked with `pub`. Example: -```ignore +``` pub trait Foo { // we set the Foo trait public fn dummy(&self) { } } @@ -75,9 +75,11 @@ mod Foo { "##, E0447: r##" +#### Note: this error code is no longer emitted by the compiler. + The `pub` keyword was used inside a function. Erroneous code example: -```ignore +``` fn foo() { pub struct Bar; // error: visibility has no effect inside functions } @@ -100,7 +102,7 @@ pub enum Foo { Since the enum is already public, adding `pub` on one its elements is unnecessary. Example: -```compile_fail, +```compile_fail enum Foo { pub Bar, // not ok! } @@ -108,7 +110,7 @@ enum Foo { This is the correct syntax: -```ignore +``` pub enum Foo { Bar, // ok! } diff --git a/src/librustc_resolve/diagnostics.rs b/src/librustc_resolve/diagnostics.rs index 87c85a5fc96b8..34f3ff276ccd9 100644 --- a/src/librustc_resolve/diagnostics.rs +++ b/src/librustc_resolve/diagnostics.rs @@ -50,7 +50,7 @@ variable declarations and expression statements. Here is an example that demonstrates the error: -```ignore +``` fn f() { // Variable declaration before import let x = 0; @@ -86,7 +86,7 @@ items under a new local name. An example of this error: -```ignore +``` use foo::baz; use bar::*; // error, do `use foo::baz as quux` instead on the previous line @@ -188,15 +188,15 @@ already been imported. Erroneous code example: ```compile_fail,E0254 -extern crate alloc; +extern crate core; mod foo { - pub trait alloc { + pub trait core { fn do_something(); } } -use foo::alloc; // error: an extern crate named `alloc` has already +use foo::core; // error: an extern crate named `core` has already // been imported in this module fn main() {} @@ -205,16 +205,16 @@ fn main() {} To fix issue issue, you have to rename at least one of the two imports. Example: -```ignore -extern crate alloc as liballoc; // ok! +``` +extern crate core as libcore; // ok! mod foo { - pub trait alloc { + pub trait core { fn do_something(); } } -use foo::alloc; +use foo::core; fn main() {} ``` @@ -295,8 +295,9 @@ that has been imported into the current module. Erroneous code example: ```compile_fail,E0259 -extern crate std; -extern crate libc as std; +# #![feature(libc)] +extern crate core; +extern crate libc as core; fn main() {} ``` @@ -306,9 +307,12 @@ external crate imported into the current module. Correct example: -```ignore -extern crate std; +``` +# #![feature(libc)] +extern crate core; extern crate libc as other_name; + +fn main() {} ``` "##, @@ -317,26 +321,26 @@ The name for an item declaration conflicts with an external crate's name. Erroneous code example: -```ignore,E0260 -extern crate abc; +```compile_fail,E0260 +extern crate core; -struct abc; +struct core; ``` There are two possible solutions: Solution #1: Rename the item. -```ignore -extern crate abc; +``` +extern crate core; struct xyz; ``` Solution #2: Import the crate with a different name. -```ignore -extern crate abc as xyz; +``` +extern crate core as xyz; struct abc; ``` @@ -509,7 +513,8 @@ This may require additional type hints in the function body. In case the item is a function inside an `impl`, defining a private helper function might be easier: -```ignore +``` +# struct Foo(T); impl Foo { pub fn foo(&self, x: T) { self.bar(x); @@ -584,7 +589,8 @@ impl SomeTrait for Foo {} // error: trait `SomeTrait` is not in scope Please verify that the name of the trait wasn't misspelled and ensure that it was imported. Example: -```ignore +``` +# #[cfg(for_demonstration_only)] // solution 1: use some_file::SomeTrait; @@ -721,7 +727,7 @@ Here, `y` is bound by-value in one case and by-reference in the other. To fix this error, just use the same mode in both cases. Generally using `ref` or `ref mut` where not already used will fix this: -```ignore +``` let x = (0, 2); match x { (0, ref y) | (ref y, 0) => { /* use y */} @@ -905,7 +911,8 @@ match (1, 2) { Or maybe did you mean to unify? Consider using a guard: -```ignore +``` +# let (A, B, C) = (1, 2, 3); match (A, B, C) { (x, x2, see) if x == x2 => { /* A and B are equal, do one thing */ } (y, z, see) => { /* A and B unequal; do another thing */ } @@ -1045,9 +1052,12 @@ let x = unknown_variable; // ok! If the item is not defined in the current module, it must be imported using a `use` statement, like so: -```ignore +``` +# mod foo { pub fn bar() {} } +# fn main() { use foo::bar; bar(); +# } ``` If the item you are importing is not defined in some super-module of the @@ -1130,8 +1140,11 @@ use something::{self, self}; // error: `self` import can only appear once in Please verify you didn't misspell the import name or remove the duplicated `self` import. Example: -```ignore -use something::self; // ok! +``` +# mod something {} +# fn main() { +use something::{self}; // ok! +# } ``` "##, @@ -1164,21 +1177,23 @@ prefixes, respectively. Also verify that you didn't misspell the import name and that the import exists in the module from where you tried to import it. Example: -```ignore +``` use self::something::Foo; // ok! mod something { pub struct Foo; } +# fn main() {} ``` Or, if you tried to use a module from an external crate, you may have missed the `extern crate` declaration (which is usually placed in the crate root): -```ignore -extern crate homura; // Required to use the `homura` crate +``` +extern crate core; // Required to use the `core` crate -use homura::Madoka; +use core::any; +# fn main() {} ``` "##, @@ -1339,7 +1354,7 @@ extern crate core as another_crate; This is a syntax error at the level of attribute declarations. The proper syntax for macro imports is the following: -```ignore +```ignore (cannot-doctest-multicrate-project) // In some_crate: #[macro_export] macro_rules! get_tacos { @@ -1383,7 +1398,7 @@ Decide which macros you would like to export and list them properly. These are proper reexport declarations: -```ignore +```ignore (cannot-doctest-multicrate-project) #[macro_reexport(some_macro, another_macro)] extern crate macros_for_good; ``` @@ -1396,9 +1411,9 @@ Example of erroneous code: ```compile_fail,E0468 mod foo { - #[macro_use(helpful_macro)] // error: must be at crate root to import + #[macro_use(debug_assert)] // error: must be at crate root to import extern crate core; // macros from another crate - helpful_macro!(...); + fn run_macro() { debug_assert!(true); } } ``` @@ -1408,13 +1423,14 @@ macros. Either move the macro import to crate root or do without the foreign macros. This will work: -```ignore -#[macro_use(helpful_macro)] -extern crate some_crate; +``` +#[macro_use(debug_assert)] +extern crate core; mod foo { - helpful_macro!(...) + fn run_macro() { debug_assert!(true); } } +# fn main() {} ``` "##, @@ -1442,7 +1458,7 @@ in question exports them. A working version would be: -```ignore +```ignore (cannot-doctest-multicrate-project) // In some_crate crate: #[macro_export] macro_rules! eat { @@ -1484,7 +1500,7 @@ in question exports them. A working version: -```ignore +```ignore (cannot-doctest-multicrate-project) // In some_crate crate: #[macro_export] macro_rules! eat { diff --git a/src/librustc_trans/diagnostics.rs b/src/librustc_trans/diagnostics.rs index 18d31448b1a24..df71fd4b19b6a 100644 --- a/src/librustc_trans/diagnostics.rs +++ b/src/librustc_trans/diagnostics.rs @@ -16,7 +16,7 @@ E0511: r##" Invalid monomorphization of an intrinsic function was used. Erroneous code example: -```ignore +```ignore (error-emitted-at-codegen-which-cannot-be-handled-by-compile_fail) #![feature(platform_intrinsics)] extern "platform-intrinsic" { diff --git a/src/librustc_typeck/diagnostics.rs b/src/librustc_typeck/diagnostics.rs index a898a75d0c976..5b8170d7ddee4 100644 --- a/src/librustc_typeck/diagnostics.rs +++ b/src/librustc_typeck/diagnostics.rs @@ -226,8 +226,10 @@ size of trait implementors isn't fixed, this type has no compile-time size. Therefore, all accesses to trait types must be through pointers. If you encounter this error you should try to avoid dereferencing the pointer. -```ignore -let trait_obj: &SomeTrait = ...; +```compile_fail,E0033 +# trait SomeTrait { fn method_one(&self){} fn method_two(&self){} } +# impl SomeTrait for T {} +let trait_obj: &SomeTrait = &"some_value"; // This tries to implicitly dereference to create an unsized local variable. let &invalid = trait_obj; @@ -407,7 +409,11 @@ fn main() { Please note on the last example that we could have called `method` like this: -```ignore +``` +# struct Test; +# impl Test { fn method(&self, v: &[T]) -> usize { v.len() } } +# let x = Test; +# let v = &[0]; x.method(v); ``` "##, @@ -684,9 +690,8 @@ External C functions are allowed to be variadic. However, a variadic function takes a minimum number of arguments. For example, consider C's variadic `printf` function: -```ignore -extern crate libc; -use libc::{ c_char, c_int }; +``` +use std::os::raw::{c_char, c_int}; extern "C" { fn printf(_: *const c_char, ...) -> c_int; @@ -696,16 +701,35 @@ extern "C" { Using this declaration, it must be called with at least one argument, so simply calling `printf()` is invalid. But the following uses are allowed: -```ignore +``` +# #![feature(static_nobundle)] +# use std::os::raw::{c_char, c_int}; +# #[cfg_attr(all(windows, target_env = "msvc"), +# link(name = "legacy_stdio_definitions", kind = "static-nobundle"))] +# extern "C" { fn printf(_: *const c_char, ...) -> c_int; } +# fn main() { unsafe { use std::ffi::CString; - printf(CString::new("test\n").unwrap().as_ptr()); - printf(CString::new("number = %d\n").unwrap().as_ptr(), 3); - printf(CString::new("%d, %d\n").unwrap().as_ptr(), 10, 5); + let fmt = CString::new("test\n").unwrap(); + printf(fmt.as_ptr()); + + let fmt = CString::new("number = %d\n").unwrap(); + printf(fmt.as_ptr(), 3); + + let fmt = CString::new("%d, %d\n").unwrap(); + printf(fmt.as_ptr(), 10, 5); } +# } ``` "##, +// ^ Note: On MSVC 2015, the `printf` function is "inlined" in the C code, and +// the C runtime does not contain the `printf` definition. This leads to linker +// error from the doc test (issue #42830). +// This can be fixed by linking to the static library +// `legacy_stdio_definitions.lib` (see https://stackoverflow.com/a/36504365/). +// If this compatibility library is removed in the future, consider changing +// `printf` in this example to another well-known variadic function. E0061: r##" The number of arguments passed to a function must match the number of arguments @@ -924,13 +948,15 @@ fn main() { "##, E0073: r##" +#### Note: this error code is no longer emitted by the compiler. + You cannot define a struct (or enum) `Foo` that requires an instance of `Foo` in order to make a new `Foo` value. This is because there would be no way a first instance of `Foo` could be made to initialize another instance! Here's an example of a struct that has this problem: -```ignore +``` struct Foo { x: Box } // error ``` @@ -944,6 +970,8 @@ Now it's possible to create at least one instance of `Foo`: `Foo { x: None }`. "##, E0074: r##" +#### Note: this error code is no longer emitted by the compiler. + When using the `#[simd]` attribute on a tuple struct, the components of the tuple struct must all be of a concrete, nongeneric type so the compiler can reason about how to use SIMD with them. This error will occur if the types @@ -951,7 +979,7 @@ are generic. This will cause an error: -```ignore +``` #![feature(repr_simd)] #[repr(simd)] @@ -1078,13 +1106,16 @@ encountered, so a conflict occurs. "##, E0082: r##" +#### Note: this error code is no longer emitted by the compiler. + When you specify enum discriminants with `=`, the compiler expects `isize` values by default. Or you can add the `repr` attibute to the enum declaration for an explicit choice of the discriminant type. In either cases, the discriminant values must fall within a valid range for the expected type; otherwise this error is raised. For example: -```ignore +```compile_fail +# #![deny(overflowing_literals)] #[repr(u8)] enum Thing { A = 1024, @@ -1095,7 +1126,8 @@ enum Thing { Here, 1024 lies outside the valid range for `u8`, so the discriminant for `A` is invalid. Here is another, more subtle example which depends on target word size: -```ignore +```compile_fail,E0080 +# #[repr(i32)] enum DependsOnPointerSize { A = 1 << 32, } @@ -1448,11 +1480,12 @@ impl Drop for u32 {} To avoid this kind of error, ensure that at least one local type is referenced by the `impl`: -```ignore +``` pub struct Foo; // you define your type in your crate impl Drop for Foo { // and you can implement the trait on it! // code of trait implementation here +# fn drop(&mut self) { } } impl From for i32 { // or you use a type from your crate as @@ -1644,7 +1677,8 @@ It is not possible to declare type parameters on a function that has the `start` attribute. Such a function must have the following type signature (for more information: http://doc.rust-lang.org/stable/book/first-edition/no-stdlib.html): -```ignore +``` +# let _: fn(isize, *const *const u8) -> isize; ``` @@ -1812,10 +1846,12 @@ information see the [opt-in builtin traits RFC][RFC 19]. "##, E0193: r##" +#### Note: this error code is no longer emitted by the compiler. + `where` clauses must use generic type parameters: it does not make sense to use them otherwise. An example causing this error: -```ignore +``` trait Foo { fn bar(&self); } @@ -2265,17 +2301,20 @@ If `ForeignTrait` is a trait defined in some external crate `foo`, then the following trait `impl` is an error: ```compile_fail,E0210 -extern crate alloc; -use alloc::range::RangeArgument; +# #[cfg(for_demonstration_only)] +extern crate foo; +# #[cfg(for_demonstration_only)] +use foo::ForeignTrait; +# use std::panic::UnwindSafe as ForeignTrait; -impl RangeArgument for T { } // error - -fn main() {} +impl ForeignTrait for T { } // error +# fn main() {} ``` To work around this, it can be covered with a local type, `MyType`: -```ignore +``` +# use std::panic::UnwindSafe as ForeignTrait; struct MyType(T); impl ForeignTrait for MyType { } // Ok ``` @@ -2286,7 +2325,7 @@ For another example of an error, suppose there's another trait defined in `foo` named `ForeignTrait2` that takes two type parameters. Then this `impl` results in the same rule violation: -```compile_fail +```ignore (cannot-doctest-multicrate-project) struct MyType2; impl ForeignTrait2> for MyType2 { } // error ``` @@ -2297,7 +2336,7 @@ is uncovered, and so runs afoul of the orphan rule. Consider one more example: -```ignore +```ignore (cannot-doctest-multicrate-project) impl ForeignTrait2, T> for MyType2 { } // Ok ``` @@ -2308,7 +2347,7 @@ violate the orphan rule; it is permitted. To see why that last example was allowed, you need to understand the general rule. Unfortunately this rule is a bit tricky to state. Consider an `impl`: -```ignore +```ignore (only-for-syntax-highlight) impl ForeignTrait for T0 { ... } ``` @@ -2590,13 +2629,17 @@ fn baz(x: &>::A) {} To solve this error, please move the type bindings in the type parameter declaration: -```ignore +``` +# struct Bar; +# trait Foo { type A; } fn baz>(x: &::A) {} // ok! ``` Or in the `where` clause: -```ignore +``` +# struct Bar; +# trait Foo { type A; } fn baz(x: &::A) where I: Foo {} ``` "##, @@ -2935,12 +2978,19 @@ impl CoerceUnsized> for MyType [`CoerceUnsized`]: https://doc.rust-lang.org/std/ops/trait.CoerceUnsized.html "##, +/* +// Associated consts can now be accessed through generic type parameters, and +// this error is no longer emitted. +// +// FIXME: consider whether to leave it in the error index, or remove it entirely +// as associated consts is not stabilized yet. + E0329: r##" An attempt was made to access an associated constant through either a generic type parameter or `Self`. This is not supported yet. An example causing this error is shown below: -```ignore +``` #![feature(associated_consts)] trait Foo { @@ -2961,7 +3011,7 @@ fn get_bar_bad(t: F) -> f64 { Currently, the value of `BAR` for a particular type can only be accessed through a concrete type, as shown below: -```ignore +``` #![feature(associated_consts)] trait Foo { @@ -2975,6 +3025,7 @@ fn get_bar_good() -> f64 { } ``` "##, +*/ E0366: r##" An attempt was made to implement `Drop` on a concrete specialization of a @@ -4349,14 +4400,20 @@ f.method; // error: attempted to take value of method `method` on type `Foo` If you want to use a method, add `()` after it: -```ignore +``` +# struct Foo { x: u32 } +# impl Foo { fn method(&self) {} } +# let f = Foo { x: 0 }; f.method(); ``` However, if you wanted to access a field of a struct check that the field name is spelled correctly. Example: -```ignore +``` +# struct Foo { x: u32 } +# impl Foo { fn method(&self) {} } +# let f = Foo { x: 0 }; println!("{}", f.x); ``` "##, diff --git a/src/librustdoc/html/markdown.rs b/src/librustdoc/html/markdown.rs index ec4a23b0417bc..bea13397eca4b 100644 --- a/src/librustdoc/html/markdown.rs +++ b/src/librustdoc/html/markdown.rs @@ -15,7 +15,7 @@ //! functionality through a unit-struct, `Markdown`, which has an implementation //! of `fmt::Display`. Example usage: //! -//! ```rust,ignore +//! ``` //! use rustdoc::html::markdown::Markdown; //! //! let s = "My *markdown* _text_"; diff --git a/src/libserialize/json.rs b/src/libserialize/json.rs index 07417565e314f..dae0b5f01238b 100644 --- a/src/libserialize/json.rs +++ b/src/libserialize/json.rs @@ -36,7 +36,7 @@ //! Arrays are enclosed in square brackets ([ ... ]) and objects in curly brackets ({ ... }). //! A simple JSON document encoding a person, their age, address and phone numbers could look like //! -//! ```ignore +//! ```json //! { //! "FirstName": "John", //! "LastName": "Doe", diff --git a/src/libstd/macros.rs b/src/libstd/macros.rs index 82c4f0830a626..9a4c5ec8f6b2e 100644 --- a/src/libstd/macros.rs +++ b/src/libstd/macros.rs @@ -444,7 +444,7 @@ pub mod builtin { /// /// # Examples /// - /// ```rust,ignore + /// ```ignore (cannot-doctest-external-file-dependency) /// let secret_key = include_str!("secret-key.ascii"); /// ``` #[stable(feature = "rust1", since = "1.0.0")] @@ -461,7 +461,7 @@ pub mod builtin { /// /// # Examples /// - /// ```rust,ignore + /// ```ignore (cannot-doctest-external-file-dependency) /// let secret_key = include_bytes!("secret-key.bin"); /// ``` #[stable(feature = "rust1", since = "1.0.0")] @@ -530,13 +530,13 @@ pub mod builtin { /// /// File 'my_str.in': /// - /// ```ignore + /// ```ignore (only-for-syntax-highlight) /// "Hello World!" /// ``` /// /// File 'main.rs': /// - /// ```ignore + /// ```ignore (cannot-doctest-external-file-dependency) /// fn main() { /// let my_str = include!("my_str.in"); /// println!("{}", my_str); diff --git a/src/libstd/memchr.rs b/src/libstd/memchr.rs index 7c8c97a6caf9c..98642f86f4dc2 100644 --- a/src/libstd/memchr.rs +++ b/src/libstd/memchr.rs @@ -24,7 +24,7 @@ /// /// This shows how to find the first position of a byte in a byte string. /// -/// ```rust,ignore +/// ```ignore (cannot-doctest-private-modules) /// use memchr::memchr; /// /// let haystack = b"the quick brown fox"; @@ -44,7 +44,7 @@ pub fn memchr(needle: u8, haystack: &[u8]) -> Option { /// /// This shows how to find the last position of a byte in a byte string. /// -/// ```rust,ignore +/// ```ignore (cannot-doctest-private-modules) /// use memchr::memrchr; /// /// let haystack = b"the quick brown fox"; diff --git a/src/libstd/prelude/mod.rs b/src/libstd/prelude/mod.rs index 195662637f013..49cdba21a1d37 100644 --- a/src/libstd/prelude/mod.rs +++ b/src/libstd/prelude/mod.rs @@ -22,13 +22,14 @@ //! //! On a technical level, Rust inserts //! -//! ```ignore +//! ``` //! extern crate std; //! ``` //! //! into the crate root of every crate, and //! -//! ```ignore +//! ``` +//! # #[allow(unused_imports)] //! use std::prelude::v1::*; //! ``` //! diff --git a/src/libstd/primitive_docs.rs b/src/libstd/primitive_docs.rs index 61ff8daddf0a6..869299e21448a 100644 --- a/src/libstd/primitive_docs.rs +++ b/src/libstd/primitive_docs.rs @@ -320,7 +320,7 @@ mod prim_pointer { } /// /// An array itself is not iterable: /// -/// ```ignore +/// ```compile_fail,E0277 /// let array: [i32; 3] = [0; 3]; /// /// for x in array { } @@ -480,8 +480,10 @@ mod prim_str { } /// Tuples are *heterogeneous*. This means that each element of the tuple can /// have a different type. In that tuple above, it has the type: /// -/// ```rust,ignore +/// ``` +/// # let _: /// (&'static str, i32, char) +/// # = ("hello", 5, 'c'); /// ``` /// /// Tuples are a *sequence*. This means that they can be accessed by position; diff --git a/src/libstd/process.rs b/src/libstd/process.rs index 4632c8a918e6e..df6a648b7b162 100644 --- a/src/libstd/process.rs +++ b/src/libstd/process.rs @@ -349,15 +349,19 @@ impl Command { /// /// Only one argument can be passed per use. So instead of: /// - /// ```ignore + /// ```no_run + /// # std::process::Command::new("sh") /// .arg("-C /path/to/repo") + /// # ; /// ``` /// /// usage would be: /// - /// ```ignore + /// ```no_run + /// # std::process::Command::new("sh") /// .arg("-C") /// .arg("/path/to/repo") + /// # ; /// ``` /// /// To pass multiple arguments see [`args`]. diff --git a/src/libstd/sys/redox/ext/fs.rs b/src/libstd/sys/redox/ext/fs.rs index fc81cc737d9f0..4437cf43920c5 100644 --- a/src/libstd/sys/redox/ext/fs.rs +++ b/src/libstd/sys/redox/ext/fs.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -//! Unix-specific extensions to primitives in the `std::fs` module. +//! Redox-specific extensions to primitives in the `std::fs` module. #![stable(feature = "rust1", since = "1.0.0")] @@ -18,23 +18,25 @@ use path::Path; use sys; use sys_common::{FromInner, AsInner, AsInnerMut}; -/// Unix-specific extensions to `Permissions` +/// Redox-specific extensions to `Permissions` #[stable(feature = "fs_ext", since = "1.1.0")] pub trait PermissionsExt { - /// Returns the underlying raw `mode_t` bits that are the standard Unix + /// Returns the underlying raw `mode_t` bits that are the standard Redox /// permissions for this file. /// /// # Examples /// - /// ```rust,ignore + /// ```no_run /// use std::fs::File; - /// use std::os::unix::fs::PermissionsExt; + /// use std::os::redox::fs::PermissionsExt; /// + /// # fn run() -> std::io::Result<()> { /// let f = File::create("foo.txt")?; /// let metadata = f.metadata()?; /// let permissions = metadata.permissions(); /// /// println!("permissions: {}", permissions.mode()); + /// # Ok(()) } /// ``` #[stable(feature = "fs_ext", since = "1.1.0")] fn mode(&self) -> u32; @@ -43,28 +45,30 @@ pub trait PermissionsExt { /// /// # Examples /// - /// ```rust,ignore + /// ```no_run /// use std::fs::File; - /// use std::os::unix::fs::PermissionsExt; + /// use std::os::redox::fs::PermissionsExt; /// + /// # fn run() -> std::io::Result<()> { /// let f = File::create("foo.txt")?; /// let metadata = f.metadata()?; /// let mut permissions = metadata.permissions(); /// /// permissions.set_mode(0o644); // Read/write for owner and read for others. /// assert_eq!(permissions.mode(), 0o644); + /// # Ok(()) } /// ``` #[stable(feature = "fs_ext", since = "1.1.0")] fn set_mode(&mut self, mode: u32); - /// Creates a new instance of `Permissions` from the given set of Unix + /// Creates a new instance of `Permissions` from the given set of Redox /// permission bits. /// /// # Examples /// - /// ```rust,ignore + /// ``` /// use std::fs::Permissions; - /// use std::os::unix::fs::PermissionsExt; + /// use std::os::redox::fs::PermissionsExt; /// /// // Read/write for owner and read for others. /// let permissions = Permissions::from_mode(0o644); @@ -89,7 +93,7 @@ impl PermissionsExt for Permissions { } } -/// Unix-specific extensions to `OpenOptions` +/// Redox-specific extensions to `OpenOptions` #[stable(feature = "fs_ext", since = "1.1.0")] pub trait OpenOptionsExt { /// Sets the mode bits that a new file will be created with. @@ -102,14 +106,17 @@ pub trait OpenOptionsExt { /// /// # Examples /// - /// ```rust,ignore + /// ```no_run + /// # #![feature(libc)] /// extern crate libc; /// use std::fs::OpenOptions; - /// use std::os::unix::fs::OpenOptionsExt; + /// use std::os::redox::fs::OpenOptionsExt; /// + /// # fn main() { /// let mut options = OpenOptions::new(); /// options.mode(0o644); // Give read/write for owner and read for others. /// let file = options.open("foo.txt"); + /// # } /// ``` #[stable(feature = "fs_ext", since = "1.1.0")] fn mode(&mut self, mode: u32) -> &mut Self; @@ -124,17 +131,20 @@ pub trait OpenOptionsExt { /// /// # Examples /// - /// ```rust,ignore + /// ```no_run + /// # #![feature(libc)] /// extern crate libc; /// use std::fs::OpenOptions; - /// use std::os::unix::fs::OpenOptionsExt; + /// use std::os::redox::fs::OpenOptionsExt; /// + /// # fn main() { /// let mut options = OpenOptions::new(); /// options.write(true); - /// if cfg!(unix) { + /// if cfg!(target_os = "redox") { /// options.custom_flags(libc::O_NOFOLLOW); /// } /// let file = options.open("foo.txt"); + /// # } /// ``` #[stable(feature = "open_options_ext", since = "1.10.0")] fn custom_flags(&mut self, flags: i32) -> &mut Self; @@ -226,7 +236,7 @@ impl MetadataExt for fs::Metadata { } } -/// Add special unix types (block/char device, fifo and socket) +/// Add special Redox types (block/char device, fifo and socket) #[stable(feature = "file_type_ext", since = "1.5.0")] pub trait FileTypeExt { /// Returns whether this file type is a block device. @@ -267,7 +277,7 @@ impl FileTypeExt for fs::FileType { /// # Examples /// /// ``` -/// use std::os::unix::fs; +/// use std::os::redox::fs; /// /// # fn foo() -> std::io::Result<()> { /// fs::symlink("a.txt", "b.txt")?; @@ -281,16 +291,16 @@ pub fn symlink, Q: AsRef>(src: P, dst: Q) -> io::Result<()> } #[stable(feature = "dir_builder", since = "1.6.0")] -/// An extension trait for `fs::DirBuilder` for unix-specific options. +/// An extension trait for `fs::DirBuilder` for Redox-specific options. pub trait DirBuilderExt { /// Sets the mode to create new directories with. This option defaults to /// 0o777. /// /// # Examples /// - /// ```ignore + /// ```no_run /// use std::fs::DirBuilder; - /// use std::os::unix::fs::DirBuilderExt; + /// use std::os::redox::fs::DirBuilderExt; /// /// let mut builder = DirBuilder::new(); /// builder.mode(0o755); diff --git a/src/libstd/sys/unix/ext/fs.rs b/src/libstd/sys/unix/ext/fs.rs index 17de46636b5c9..26710bf61d510 100644 --- a/src/libstd/sys/unix/ext/fs.rs +++ b/src/libstd/sys/unix/ext/fs.rs @@ -73,15 +73,17 @@ pub trait PermissionsExt { /// /// # Examples /// - /// ```rust,ignore + /// ```no_run /// use std::fs::File; /// use std::os::unix::fs::PermissionsExt; /// + /// # fn run() -> std::io::Result<()> { /// let f = File::create("foo.txt")?; /// let metadata = f.metadata()?; /// let permissions = metadata.permissions(); /// /// println!("permissions: {}", permissions.mode()); + /// # Ok(()) } /// ``` #[stable(feature = "fs_ext", since = "1.1.0")] fn mode(&self) -> u32; @@ -90,16 +92,18 @@ pub trait PermissionsExt { /// /// # Examples /// - /// ```rust,ignore + /// ```no_run /// use std::fs::File; /// use std::os::unix::fs::PermissionsExt; /// + /// # fn run() -> std::io::Result<()> { /// let f = File::create("foo.txt")?; /// let metadata = f.metadata()?; /// let mut permissions = metadata.permissions(); /// /// permissions.set_mode(0o644); // Read/write for owner and read for others. /// assert_eq!(permissions.mode(), 0o644); + /// # Ok(()) } /// ``` #[stable(feature = "fs_ext", since = "1.1.0")] fn set_mode(&mut self, mode: u32); @@ -109,7 +113,7 @@ pub trait PermissionsExt { /// /// # Examples /// - /// ```rust,ignore + /// ``` /// use std::fs::Permissions; /// use std::os::unix::fs::PermissionsExt; /// @@ -149,14 +153,17 @@ pub trait OpenOptionsExt { /// /// # Examples /// - /// ```rust,ignore + /// ```no_run + /// # #![feature(libc)] /// extern crate libc; /// use std::fs::OpenOptions; /// use std::os::unix::fs::OpenOptionsExt; /// + /// # fn main() { /// let mut options = OpenOptions::new(); /// options.mode(0o644); // Give read/write for owner and read for others. /// let file = options.open("foo.txt"); + /// # } /// ``` #[stable(feature = "fs_ext", since = "1.1.0")] fn mode(&mut self, mode: u32) -> &mut Self; @@ -171,17 +178,20 @@ pub trait OpenOptionsExt { /// /// # Examples /// - /// ```rust,ignore + /// ```no_run + /// # #![feature(libc)] /// extern crate libc; /// use std::fs::OpenOptions; /// use std::os::unix::fs::OpenOptionsExt; /// + /// # fn main() { /// let mut options = OpenOptions::new(); /// options.write(true); /// if cfg!(unix) { /// options.custom_flags(libc::O_NOFOLLOW); /// } /// let file = options.open("foo.txt"); + /// # } /// ``` #[stable(feature = "open_options_ext", since = "1.10.0")] fn custom_flags(&mut self, flags: i32) -> &mut Self; @@ -353,7 +363,7 @@ pub trait DirBuilderExt { /// /// # Examples /// - /// ```ignore + /// ```no_run /// use std::fs::DirBuilder; /// use std::os::unix::fs::DirBuilderExt; /// diff --git a/src/libstd/sys/windows/ext/fs.rs b/src/libstd/sys/windows/ext/fs.rs index 2d00cb38ec4fc..67348a0049417 100644 --- a/src/libstd/sys/windows/ext/fs.rs +++ b/src/libstd/sys/windows/ext/fs.rs @@ -169,8 +169,10 @@ pub trait OpenOptionsExt { /// /// # Examples /// - /// ```ignore + /// ```no_run + /// # #[cfg(for_demonstration_only)] /// extern crate winapi; + /// # mod winapi { pub const FILE_FLAG_DELETE_ON_CLOSE: u32 = 0x04000000; } /// /// use std::fs::OpenOptions; /// use std::os::windows::prelude::*; @@ -204,8 +206,10 @@ pub trait OpenOptionsExt { /// /// # Examples /// - /// ```ignore + /// ```no_run + /// # #[cfg(for_demonstration_only)] /// extern crate winapi; + /// # mod winapi { pub const FILE_ATTRIBUTE_HIDDEN: u32 = 2; } /// /// use std::fs::OpenOptions; /// use std::os::windows::prelude::*; diff --git a/src/libstd/sys_common/thread_local.rs b/src/libstd/sys_common/thread_local.rs index 0ade90e64c307..9ba023b57e6a3 100644 --- a/src/libstd/sys_common/thread_local.rs +++ b/src/libstd/sys_common/thread_local.rs @@ -33,7 +33,7 @@ //! Using a dynamically allocated TLS key. Note that this key can be shared //! among many threads via an `Arc`. //! -//! ```rust,ignore +//! ```ignore (cannot-doctest-private-modules) //! let key = Key::new(None); //! assert!(key.get().is_null()); //! key.set(1 as *mut u8); @@ -45,7 +45,7 @@ //! Sometimes a statically allocated key is either required or easier to work //! with, however. //! -//! ```rust,ignore +//! ```ignore (cannot-doctest-private-modules) //! static KEY: StaticKey = INIT; //! //! unsafe { @@ -74,7 +74,7 @@ use sys_common::mutex::Mutex; /// /// # Examples /// -/// ```ignore +/// ```ignore (cannot-doctest-private-modules) /// use tls::os::{StaticKey, INIT}; /// /// static KEY: StaticKey = INIT; @@ -105,7 +105,7 @@ pub struct StaticKey { /// /// # Examples /// -/// ```rust,ignore +/// ```ignore (cannot-doctest-private-modules) /// use tls::os::Key; /// /// let key = Key::new(None); diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs index 2eb39bc26b5cb..8bd58ec7a52d5 100644 --- a/src/libsyntax/ast.rs +++ b/src/libsyntax/ast.rs @@ -775,10 +775,10 @@ pub struct Local { /// /// E.g. `0...10 => { println!("match!") }` as in /// -/// ```rust,ignore -/// match n { +/// ``` +/// match 123 { /// 0...10 => { println!("match!") }, -/// // .. +/// _ => { println!("no match!") }, /// } /// ``` #[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)] @@ -977,7 +977,7 @@ pub enum ExprKind { /// separately. `position` represents the index of the associated /// item qualified with this Self type. /// -/// ```rust,ignore +/// ```ignore (only-for-syntax-highlight) /// as a::b::Trait>::AssociatedItem /// ^~~~~ ~~~~~~~~~~~~~~^ /// ty position = 3 diff --git a/src/libsyntax/diagnostic_list.rs b/src/libsyntax/diagnostic_list.rs index 01d1277ea6265..508feca9731f2 100644 --- a/src/libsyntax/diagnostic_list.rs +++ b/src/libsyntax/diagnostic_list.rs @@ -51,12 +51,14 @@ fn main() {} The parenthesized `inline` attribute requires the parameter to be specified: -```ignore +``` #[inline(always)] fn something() {} +``` -// or: +or: +``` #[inline(never)] fn something() {} ``` diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index 0b145c54f619c..851a638e14842 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -4436,7 +4436,7 @@ impl<'a> Parser<'a> { /// Parses an optional `where` clause and places it in `generics`. /// - /// ```ignore + /// ```ignore (only-for-syntax-highlight) /// where T : Trait + 'b, 'a : 'b /// ``` pub fn parse_where_clause(&mut self) -> PResult<'a, WhereClause> { diff --git a/src/libsyntax/print/pp.rs b/src/libsyntax/print/pp.rs index e893c859247c6..82b5d7e284bc6 100644 --- a/src/libsyntax/print/pp.rs +++ b/src/libsyntax/print/pp.rs @@ -11,7 +11,7 @@ //! This pretty-printer is a direct reimplementation of Philip Karlton's //! Mesa pretty-printer, as described in appendix A of //! -//! ````ignore +//! ````text //! STAN-CS-79-770: "Pretty Printing", by Derek C. Oppen. //! Stanford Department of Computer Science, 1979. //! ```` diff --git a/src/libsyntax_ext/deriving/encodable.rs b/src/libsyntax_ext/deriving/encodable.rs index 9d155c22ad031..33f742282c172 100644 --- a/src/libsyntax_ext/deriving/encodable.rs +++ b/src/libsyntax_ext/deriving/encodable.rs @@ -14,14 +14,15 @@ //! //! For example, a type like: //! -//! ```ignore +//! ``` //! #[derive(Encodable, Decodable)] //! struct Node { id: usize } //! ``` //! //! would generate two implementations like: //! -//! ```ignore +//! ``` +//! # struct Node { id: usize } //! impl, E> Encodable for Node { //! fn encode(&self, s: &mut S) -> Result<(), E> { //! s.emit_struct("Node", 1, |this| { @@ -48,14 +49,17 @@ //! Other interesting scenarios are when the item has type parameters or //! references other non-built-in types. A type definition like: //! -//! ```ignore +//! ``` +//! # #[derive(Encodable, Decodable)] struct Span; //! #[derive(Encodable, Decodable)] //! struct Spanned { node: T, span: Span } //! ``` //! //! would yield functions like: //! -//! ```ignore +//! ``` +//! # #[derive(Encodable, Decodable)] struct Span; +//! # struct Spanned { node: T, span: Span } //! impl< //! S: Encoder, //! E, diff --git a/src/libsyntax_ext/deriving/generic/mod.rs b/src/libsyntax_ext/deriving/generic/mod.rs index be7883cad5f38..3a15b82d19f69 100644 --- a/src/libsyntax_ext/deriving/generic/mod.rs +++ b/src/libsyntax_ext/deriving/generic/mod.rs @@ -456,7 +456,7 @@ impl<'a> TraitDef<'a> { /// Given that we are deriving a trait `DerivedTrait` for a type like: /// - /// ```ignore + /// ```ignore (only-for-syntax-highlight) /// struct Struct<'a, ..., 'z, A, B: DeclaredTrait, C, ..., Z> where C: WhereTrait { /// a: A, /// b: B::Item, @@ -469,7 +469,7 @@ impl<'a> TraitDef<'a> { /// /// create an impl like: /// - /// ```ignore + /// ```ignore (only-for-syntax-highlight) /// impl<'a, ..., 'z, A, B: DeclaredTrait, C, ... Z> where /// C: WhereTrait, /// A: DerivedTrait + B1 + ... + BN, @@ -933,8 +933,9 @@ impl<'a> MethodDef<'a> { } } - /// ```ignore + /// ``` /// #[derive(PartialEq)] + /// # struct Dummy; /// struct A { x: i32, y: i32 } /// /// // equivalent to: @@ -1040,8 +1041,9 @@ impl<'a> MethodDef<'a> { &StaticStruct(struct_def, summary)) } - /// ```ignore + /// ``` /// #[derive(PartialEq)] + /// # struct Dummy; /// enum A { /// A1, /// A2(i32) @@ -1624,7 +1626,7 @@ pub fn cs_fold(use_foldl: bool, /// Call the method that is being derived on all the fields, and then /// process the collected results. i.e. /// -/// ```ignore +/// ```ignore (only-for-syntax-highlight) /// f(cx, span, vec![self_1.method(__arg_1_1, __arg_2_1), /// self_2.method(__arg_1_2, __arg_2_2)]) /// ``` diff --git a/src/libsyntax_ext/format.rs b/src/libsyntax_ext/format.rs index 24c1dfe289b1e..a6768c07fe13b 100644 --- a/src/libsyntax_ext/format.rs +++ b/src/libsyntax_ext/format.rs @@ -117,7 +117,8 @@ struct Context<'a, 'b: 'a> { /// expressions. /// /// If parsing succeeds, the return value is: -/// ```ignore +/// +/// ```text /// Some((fmtstr, parsed arguments, index map for named arguments)) /// ``` fn parse_args(ecx: &mut ExtCtxt, From 2c8916581472f5f9892c306632bb2b3d8bc96bc4 Mon Sep 17 00:00:00 2001 From: kennytm Date: Tue, 20 Jun 2017 15:53:03 +0800 Subject: [PATCH 11/12] Modify --explain to handle hidden code (`# ...`) and indented code blocks. --- src/librustc_driver/lib.rs | 19 ++++++++---- src/test/ui/explain.rs | 11 +++++++ src/test/ui/explain.stdout | 63 ++++++++++++++++++++++++++++++++++++++ 3 files changed, 87 insertions(+), 6 deletions(-) create mode 100644 src/test/ui/explain.rs create mode 100644 src/test/ui/explain.stdout diff --git a/src/librustc_driver/lib.rs b/src/librustc_driver/lib.rs index b4a4aaaaf5c81..54e7c398fe6a6 100644 --- a/src/librustc_driver/lib.rs +++ b/src/librustc_driver/lib.rs @@ -355,14 +355,21 @@ fn handle_explain(code: &str, }; match descriptions.find_description(&normalised) { Some(ref description) => { + let mut is_in_code_block = false; // Slice off the leading newline and print. - print!("{}", &(&description[1..]).split("\n").map(|x| { - format!("{}\n", if x.starts_with("```") { - "```" + for line in description[1..].lines() { + let indent_level = line.find(|c: char| !c.is_whitespace()) + .unwrap_or_else(|| line.len()); + let dedented_line = &line[indent_level..]; + if dedented_line.starts_with("```") { + is_in_code_block = !is_in_code_block; + println!("{}", &line[..(indent_level+3)]); + } else if is_in_code_block && dedented_line.starts_with("# ") { + continue; } else { - x - }) - }).collect::()); + println!("{}", line); + } + } } None => { early_error(output, &format!("no extended information for {}", code)); diff --git a/src/test/ui/explain.rs b/src/test/ui/explain.rs new file mode 100644 index 0000000000000..17fb59935dd16 --- /dev/null +++ b/src/test/ui/explain.rs @@ -0,0 +1,11 @@ +// Copyright 2017 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// compile-flags: --explain E0591 diff --git a/src/test/ui/explain.stdout b/src/test/ui/explain.stdout new file mode 100644 index 0000000000000..0bbbd95320a8c --- /dev/null +++ b/src/test/ui/explain.stdout @@ -0,0 +1,63 @@ +Per [RFC 401][rfc401], if you have a function declaration `foo`: + +``` +// For the purposes of this explanation, all of these +// different kinds of `fn` declarations are equivalent: +struct S; +fn foo(x: S) { /* ... */ } +extern "C" { fn foo(x: S); } +impl S { fn foo(self) { /* ... */ } } +``` + +the type of `foo` is **not** `fn(S)`, as one might expect. +Rather, it is a unique, zero-sized marker type written here as `typeof(foo)`. +However, `typeof(foo)` can be _coerced_ to a function pointer `fn(S)`, +so you rarely notice this: + +``` +let x: fn(S) = foo; // OK, coerces +``` + +The reason that this matter is that the type `fn(S)` is not specific to +any particular function: it's a function _pointer_. So calling `x()` results +in a virtual call, whereas `foo()` is statically dispatched, because the type +of `foo` tells us precisely what function is being called. + +As noted above, coercions mean that most code doesn't have to be +concerned with this distinction. However, you can tell the difference +when using **transmute** to convert a fn item into a fn pointer. + +This is sometimes done as part of an FFI: + +``` +extern "C" fn foo(userdata: Box) { + /* ... */ +} + +let f: extern "C" fn(*mut i32) = transmute(foo); +callback(f); +``` + +Here, transmute is being used to convert the types of the fn arguments. +This pattern is incorrect because, because the type of `foo` is a function +**item** (`typeof(foo)`), which is zero-sized, and the target type (`fn()`) +is a function pointer, which is not zero-sized. +This pattern should be rewritten. There are a few possible ways to do this: + +- change the original fn declaration to match the expected signature, + and do the cast in the fn body (the prefered option) +- cast the fn item fo a fn pointer before calling transmute, as shown here: + + ``` + let f: extern "C" fn(*mut i32) = transmute(foo as extern "C" fn(_)); + let f: extern "C" fn(*mut i32) = transmute(foo as usize); // works too + ``` + +The same applies to transmutes to `*mut fn()`, which were observedin practice. +Note though that use of this type is generally incorrect. +The intention is typically to describe a function pointer, but just `fn()` +alone suffices for that. `*mut fn()` is a pointer to a fn pointer. +(Since these values are typically just passed to C code, however, this rarely +makes a difference in practice.) + +[rfc401]: https://github.com/rust-lang/rfcs/blob/master/text/0401-coercions.md From 9addd3ba657e0d37c3fa5296262474db91d26d8f Mon Sep 17 00:00:00 2001 From: kennytm Date: Wed, 21 Jun 2017 01:00:02 +0800 Subject: [PATCH 12/12] Added a tidy check to disallow "```ignore" and "```rust,ignore". --- src/tools/tidy/src/style.rs | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/src/tools/tidy/src/style.rs b/src/tools/tidy/src/style.rs index f5f1abc4b12a9..b42beb37821ce 100644 --- a/src/tools/tidy/src/style.rs +++ b/src/tools/tidy/src/style.rs @@ -18,6 +18,7 @@ //! * No CR characters //! * No `TODO` or `XXX` directives //! * A valid license header is at the top +//! * No unexplained ` ```ignore ` or ` ```rust,ignore ` doc tests //! //! A number of these checks can be opted-out of with various directives like //! `// ignore-tidy-linelength`. @@ -38,6 +39,17 @@ http://www.apache.org/licenses/LICENSE-2.0> or the MIT license option. This file may not be copied, modified, or distributed except according to those terms."; +const UNEXPLAINED_IGNORE_DOCTEST_INFO: &str = r#"unexplained "```ignore" doctest; try one: + +* make the test actually pass, by adding necessary imports and declarations, or +* use "```text", if the code is not Rust code, or +* use "```compile_fail,Ennnn", if the code is expected to fail at compile time, or +* use "```should_panic", if the code is expected to fail at run time, or +* use "```no_run", if the code should type-check but not necessary linkable/runnable, or +* explain it like "```ignore (cannot-test-this-because-xxxx)", if the annotation cannot be avoided. + +"#; + /// Parser states for line_is_url. #[derive(PartialEq)] #[allow(non_camel_case_types)] @@ -138,6 +150,9 @@ pub fn check(path: &Path, bad: &mut bool) { err("XXX is deprecated; use FIXME") } } + if line.ends_with("```ignore") || line.ends_with("```rust,ignore") { + err(UNEXPLAINED_IGNORE_DOCTEST_INFO); + } } if !licenseck(file, &contents) { tidy_error!(bad, "{}: incorrect license", file.display());