diff --git a/Cargo.lock b/Cargo.lock index 08155c51d97..16f2ffc2815 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2252,9 +2252,9 @@ dependencies = [ [[package]] name = "openssl" -version = "0.10.16" +version = "0.10.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ec7bd7ca4cce6dbdc77e7c1230682740d307d1218a87fb0349a571272be749f9" +checksum = "2f372b2b53ce10fb823a337aaa674e3a7d072b957c6264d0f4ff0bd86e657449" dependencies = [ "bitflags", "cfg-if", @@ -2281,15 +2281,15 @@ dependencies = [ [[package]] name = "openssl-sys" -version = "0.9.43" +version = "0.9.52" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "33c86834957dd5b915623e94f2f4ab2c70dd8f6b70679824155d5ae21dbd495d" +checksum = "c977d08e1312e2f7e4b86f9ebaa0ed3b19d1daff75fae88bbb88108afbd801fc" dependencies = [ + "autocfg", "cc", "libc", "openssl-src", "pkg-config", - "rustc_version", "vcpkg", ] diff --git a/src/bootstrap/flags.rs b/src/bootstrap/flags.rs index d9580b59815..7b49cc0a929 100644 --- a/src/bootstrap/flags.rs +++ b/src/bootstrap/flags.rs @@ -448,12 +448,12 @@ Arguments: Flags { verbose: matches.opt_count("verbose"), - stage: matches.opt_str("stage").map(|j| j.parse().unwrap()), + stage: matches.opt_str("stage").map(|j| j.parse().expect("`stage` should be a number")), dry_run: matches.opt_present("dry-run"), on_fail: matches.opt_str("on-fail"), rustc_error_format: matches.opt_str("error-format"), keep_stage: matches.opt_strs("keep-stage") - .into_iter().map(|j| j.parse().unwrap()) + .into_iter().map(|j| j.parse().expect("`keep-stage` should be a number")) .collect(), host: split(&matches.opt_strs("host")) .into_iter() @@ -464,7 +464,7 @@ Arguments: .map(|x| INTERNER.intern_string(x)) .collect::>(), config: cfg_file, - jobs: matches.opt_str("jobs").map(|j| j.parse().unwrap()), + jobs: matches.opt_str("jobs").map(|j| j.parse().expect("`jobs` should be a number")), cmd, incremental: matches.opt_present("incremental"), exclude: split(&matches.opt_strs("exclude")) diff --git a/src/doc/rustdoc/src/SUMMARY.md b/src/doc/rustdoc/src/SUMMARY.md index 46528187c11..d4202f5b367 100644 --- a/src/doc/rustdoc/src/SUMMARY.md +++ b/src/doc/rustdoc/src/SUMMARY.md @@ -1,8 +1,10 @@ # The Rustdoc Book - [What is rustdoc?](what-is-rustdoc.md) +- [How to write documentation](how-to-write-documentation.md) - [Command-line arguments](command-line-arguments.md) - [The `#[doc]` attribute](the-doc-attribute.md) - [Documentation tests](documentation-tests.md) +- [Lints](lints.md) - [Passes](passes.md) - [Unstable features](unstable-features.md) diff --git a/src/doc/rustdoc/src/how-to-write-documentation.md b/src/doc/rustdoc/src/how-to-write-documentation.md new file mode 100644 index 00000000000..dd3aa5d4b69 --- /dev/null +++ b/src/doc/rustdoc/src/how-to-write-documentation.md @@ -0,0 +1,82 @@ +# How to write documentation + +This chapter covers not only how to write documentation but specifically +how to write **good** documentation. Something to keep in mind when +writing documentation is that your audience is not just yourself but others +who simply don't have the context you do. It is important to be as clear +as you can, and as complete as possible. As a rule of thumb: the more +documentation you write for your crate the better. If an item is public +then it should be documented. + +## Basic structure + +It is recommended that each item's documentation follows this basic structure: + +```text +[short sentence explaining what it is] + +[more detailed explanation] + +[at least one code example that users can copy/paste to try it] + +[even more advanced explanations if necessary] +``` + +This basic structure should be straightforward to follow when writing your +documentation and, while you might think that a code example is trivial, +the examples are really important because they can help your users to +understand what an item is, how it is used, and for what purpose it exists. + +Let's see an example coming from the [standard library] by taking a look at the +[`std::env::args()`][env::args] function: + +``````text +Returns the arguments which this program was started with (normally passed +via the command line). + +The first element is traditionally the path of the executable, but it can be +set to arbitrary text, and may not even exist. This means this property should +not be relied upon for security purposes. + +On Unix systems shell usually expands unquoted arguments with glob patterns +(such as `*` and `?`). On Windows this is not done, and such arguments are +passed as-is. + +# Panics + +The returned iterator will panic during iteration if any argument to the +process is not valid unicode. If this is not desired, +use the [`args_os`] function instead. + +# Examples + +``` +use std::env; + +// Prints each argument on a separate line +for argument in env::args() { + println!("{}", argument); +} +``` + +[`args_os`]: ./fn.args_os.html +`````` + +As you can see, it follows the structure detailed above: it starts with a short +sentence explaining what the functions does, then it provides more information +and finally provides a code example. + +## Markdown + +`rustdoc` is using the [commonmark markdown specification]. You might be +interested into taking a look at their website to see what's possible to do. + +## Lints + +To be sure that you didn't miss any item without documentation or code examples, +you can take a look at the rustdoc lints [here][rustdoc-lints]. + +[standard library]: https://doc.rust-lang.org/stable/std/index.html +[env::args]: https://doc.rust-lang.org/stable/std/env/fn.args.html +[commonmark markdown specification]: https://commonmark.org/ +[rustdoc-lints]: lints.md diff --git a/src/doc/rustdoc/src/lints.md b/src/doc/rustdoc/src/lints.md new file mode 100644 index 00000000000..beb2556872d --- /dev/null +++ b/src/doc/rustdoc/src/lints.md @@ -0,0 +1,119 @@ +# Lints + +`rustdoc` provides lints to help you writing and testing your documentation. You +can use them like any other lints by doing this: + +```rust,ignore +#![allow(missing_docs)] // allowing the lint, no message +#![warn(missing_docs)] // warn if there is missing docs +#![deny(missing_docs)] // rustdoc will fail if there is missing docs +``` + +Here is the list of the lints provided by `rustdoc`: + +## intra_doc_link_resolution_failure + +This lint **warns by default** and is **nightly-only**. This lint detects when +an intra-doc link fails to get resolved. For example: + +```rust +/// I want to link to [`Inexistent`] but it doesn't exist! +pub fn foo() {} +``` + +You'll get a warning saying: + +```text +error: `[`Inexistent`]` cannot be resolved, ignoring it... +``` + +## missing_docs + +This lint is **allowed by default**. It detects items missing documentation. +For example: + +```rust +#![warn(missing_docs)] + +pub fn undocumented() {} +# fn main() {} +``` + +The `undocumented` function will then have the following warning: + +```text +warning: missing documentation for a function + --> your-crate/lib.rs:3:1 + | + 3 | pub fn undocumented() {} + | ^^^^^^^^^^^^^^^^^^^^^ +``` + +## missing_doc_code_examples + +This lint is **allowed by default**. It detects when a documentation block +is missing a code example. For example: + +```rust +#![warn(missing_doc_code_examples)] + +/// There is no code example! +pub fn no_code_example() {} +# fn main() {} +``` + +The `no_code_example` function will then have the following warning: + +```text +warning: Missing code example in this documentation + --> your-crate/lib.rs:3:1 + | +LL | /// There is no code example! + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +``` + +To fix the lint, you need to add a code example into the documentation block: + +```rust +/// There is no code example! +/// +/// ``` +/// println!("calling no_code_example..."); +/// no_code_example(); +/// println!("we called no_code_example!"); +/// ``` +pub fn no_code_example() {} +``` + +## private_doc_tests + +This lint is **allowed by default**. It detects documentation tests when they +are on a private item. For example: + +```rust +#![warn(private_doc_tests)] + +mod foo { + /// private doc test + /// + /// ``` + /// assert!(false); + /// ``` + fn bar() {} +} +# fn main() {} +``` + +Which will give: + +```text +warning: Documentation test in private item + --> your-crate/lib.rs:4:1 + | + 4 | / /// private doc test + 5 | | /// + 6 | | /// ``` + 7 | | /// assert!(false); + 8 | | /// ``` + | |___________^ +``` diff --git a/src/libcore/num/mod.rs b/src/libcore/num/mod.rs index 4b9e82c7cfe..b5d61a3fd4e 100644 --- a/src/libcore/num/mod.rs +++ b/src/libcore/num/mod.rs @@ -235,7 +235,6 @@ depending on the target pointer size. "} } -// `Int` + `SignedInt` implemented for signed integers macro_rules! int_impl { ($SelfT:ty, $ActualT:ident, $UnsignedT:ty, $BITS:expr, $Min:expr, $Max:expr, $Feature:expr, $EndFeature:expr, $rot:expr, $rot_op:expr, $rot_result:expr, $swap_op:expr, $swapped:expr, @@ -2303,7 +2302,6 @@ impl isize { usize_isize_to_xe_bytes_doc!(), usize_isize_from_xe_bytes_doc!() } } -// `Int` + `UnsignedInt` implemented for unsigned integers macro_rules! uint_impl { ($SelfT:ty, $ActualT:ty, $BITS:expr, $MaxV:expr, $Feature:expr, $EndFeature:expr, $rot:expr, $rot_op:expr, $rot_result:expr, $swap_op:expr, $swapped:expr, diff --git a/src/librustc/middle/stability.rs b/src/librustc/middle/stability.rs index 93d0627ac6e..fabb0a59da8 100644 --- a/src/librustc/middle/stability.rs +++ b/src/librustc/middle/stability.rs @@ -22,8 +22,9 @@ use syntax::attr::{self, Stability, Deprecation, RustcDeprecation}; use crate::ty::{self, TyCtxt}; use crate::util::nodemap::{FxHashSet, FxHashMap}; -use std::mem::replace; use std::cmp::Ordering; +use std::mem::replace; +use std::num::NonZeroU32; #[derive(PartialEq, Clone, Copy, Debug)] pub enum StabilityLevel { @@ -441,7 +442,7 @@ impl<'tcx> Index<'tcx> { let stability = tcx.intern_stability(Stability { level: attr::StabilityLevel::Unstable { reason: Some(Symbol::intern(reason)), - issue: 27812, + issue: NonZeroU32::new(27812), is_soft: false, }, feature: sym::rustc_private, @@ -488,7 +489,7 @@ pub fn report_unstable( sess: &Session, feature: Symbol, reason: Option, - issue: u32, + issue: Option, is_soft: bool, span: Span, soft_handler: impl FnOnce(&'static lint::Lint, Span, &str), @@ -520,7 +521,7 @@ pub fn report_unstable( soft_handler(lint::builtin::SOFT_UNSTABLE, span, &msg) } else { emit_feature_err( - &sess.parse_sess, feature, span, GateIssue::Library(Some(issue)), &msg + &sess.parse_sess, feature, span, GateIssue::Library(issue), &msg ); } } @@ -637,7 +638,7 @@ pub enum EvalResult { Deny { feature: Symbol, reason: Option, - issue: u32, + issue: Option, is_soft: bool, }, /// The item does not have the `#[stable]` or `#[unstable]` marker assigned. @@ -758,7 +759,7 @@ impl<'tcx> TyCtxt<'tcx> { // the `-Z force-unstable-if-unmarked` flag present (we're // compiling a compiler crate), then let this missing feature // annotation slide. - if feature == sym::rustc_private && issue == 27812 { + if feature == sym::rustc_private && issue == NonZeroU32::new(27812) { if self.sess.opts.debugging_opts.force_unstable_if_unmarked { return EvalResult::Allow; } diff --git a/src/librustc/session/code_stats.rs b/src/librustc/session/code_stats.rs index 0f535249b5e..5baf0c5948f 100644 --- a/src/librustc/session/code_stats.rs +++ b/src/librustc/session/code_stats.rs @@ -1,6 +1,7 @@ use rustc_target::abi::{Align, Size}; use rustc_data_structures::fx::{FxHashSet}; use std::cmp::{self, Ordering}; +use rustc_data_structures::sync::Lock; #[derive(Clone, PartialEq, Eq, Hash, Debug)] pub struct VariantInfo { @@ -44,13 +45,13 @@ pub struct TypeSizeInfo { pub variants: Vec, } -#[derive(PartialEq, Eq, Debug, Default)] +#[derive(Default)] pub struct CodeStats { - type_sizes: FxHashSet, + type_sizes: Lock>, } impl CodeStats { - pub fn record_type_size(&mut self, + pub fn record_type_size(&self, kind: DataTypeKind, type_desc: S, align: Align, @@ -73,11 +74,12 @@ impl CodeStats { opt_discr_size: opt_discr_size.map(|s| s.bytes()), variants, }; - self.type_sizes.insert(info); + self.type_sizes.borrow_mut().insert(info); } pub fn print_type_sizes(&self) { - let mut sorted: Vec<_> = self.type_sizes.iter().collect(); + let type_sizes = self.type_sizes.borrow(); + let mut sorted: Vec<_> = type_sizes.iter().collect(); // Primary sort: large-to-small. // Secondary sort: description (dictionary order) diff --git a/src/librustc/session/mod.rs b/src/librustc/session/mod.rs index 92e8e92d02a..9792223ea15 100644 --- a/src/librustc/session/mod.rs +++ b/src/librustc/session/mod.rs @@ -41,6 +41,7 @@ use std::cell::{self, RefCell}; use std::env; use std::fmt; use std::io::Write; +use std::num::NonZeroU32; use std::path::PathBuf; use std::time::Duration; use std::sync::Arc; @@ -124,7 +125,7 @@ pub struct Session { pub perf_stats: PerfStats, /// Data about code being compiled, gathered during compilation. - pub code_stats: Lock, + pub code_stats: CodeStats, /// If `-zfuel=crate=n` is specified, `Some(crate)`. optimization_fuel_crate: Option, @@ -183,7 +184,7 @@ enum DiagnosticBuilderMethod { pub enum DiagnosticMessageId { ErrorId(u16), // EXXXX error code as integer LintId(lint::LintId), - StabilityId(u32), // issue number + StabilityId(Option), // issue number } impl From<&'static lint::Lint> for DiagnosticMessageId { diff --git a/src/librustc/ty/layout.rs b/src/librustc/ty/layout.rs index e5f22277f8e..972452601dd 100644 --- a/src/librustc/ty/layout.rs +++ b/src/librustc/ty/layout.rs @@ -1614,13 +1614,13 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> { // (delay format until we actually need it) let record = |kind, packed, opt_discr_size, variants| { let type_desc = format!("{:?}", layout.ty); - self.tcx.sess.code_stats.borrow_mut().record_type_size(kind, - type_desc, - layout.align.abi, - layout.size, - packed, - opt_discr_size, - variants); + self.tcx.sess.code_stats.record_type_size(kind, + type_desc, + layout.align.abi, + layout.size, + packed, + opt_discr_size, + variants); }; let adt_def = match layout.ty.kind { diff --git a/src/librustc_driver/lib.rs b/src/librustc_driver/lib.rs index f2da4ae71f5..10bc6599e75 100644 --- a/src/librustc_driver/lib.rs +++ b/src/librustc_driver/lib.rs @@ -393,7 +393,7 @@ pub fn run_compiler( mem::drop(compiler.global_ctxt()?.take()); if sess.opts.debugging_opts.print_type_sizes { - sess.code_stats.borrow().print_type_sizes(); + sess.code_stats.print_type_sizes(); } compiler.link()?; diff --git a/src/librustc_errors/lib.rs b/src/librustc_errors/lib.rs index fb5cccf61a7..8ee28875c62 100644 --- a/src/librustc_errors/lib.rs +++ b/src/librustc_errors/lib.rs @@ -15,8 +15,6 @@ use Level::*; use emitter::{Emitter, EmitterWriter, is_case_difference}; use registry::Registry; -#[cfg(target_arch = "x86_64")] -use rustc_data_structures::static_assert_size; use rustc_data_structures::sync::{self, Lrc, Lock}; use rustc_data_structures::fx::{FxHashSet, FxIndexMap}; use rustc_data_structures::stable_hasher::StableHasher; @@ -54,7 +52,7 @@ pub type PResult<'a, T> = Result>; // `PResult` is used a lot. Make sure it doesn't unintentionally get bigger. // (See also the comment on `DiagnosticBuilderInner`.) #[cfg(target_arch = "x86_64")] -static_assert_size!(PResult<'_, bool>, 16); +rustc_data_structures::static_assert_size!(PResult<'_, bool>, 16); /// Indicates the confidence in the correctness of a suggestion. /// diff --git a/src/librustc_target/spec/windows_base.rs b/src/librustc_target/spec/windows_base.rs index 38db9cd356c..ce7b338345c 100644 --- a/src/librustc_target/spec/windows_base.rs +++ b/src/librustc_target/spec/windows_base.rs @@ -4,33 +4,6 @@ use std::default::Default; pub fn opts() -> TargetOptions { let mut pre_link_args = LinkArgs::new(); pre_link_args.insert(LinkerFlavor::Gcc, vec![ - // And here, we see obscure linker flags #45. On windows, it has been - // found to be necessary to have this flag to compile liblibc. - // - // First a bit of background. On Windows, the file format is not ELF, - // but COFF (at least according to LLVM). COFF doesn't officially allow - // for section names over 8 characters, apparently. Our metadata - // section, ".note.rustc", you'll note is over 8 characters. - // - // On more recent versions of gcc on mingw, apparently the section name - // is *not* truncated, but rather stored elsewhere in a separate lookup - // table. On older versions of gcc, they apparently always truncated th - // section names (at least in some cases). Truncating the section name - // actually creates "invalid" objects [1] [2], but only for some - // introspection tools, not in terms of whether it can be loaded. - // - // Long story short, passing this flag forces the linker to *not* - // truncate section names (so we can find the metadata section after - // it's compiled). The real kicker is that rust compiled just fine on - // windows for quite a long time *without* this flag, so I have no idea - // why it suddenly started failing for liblibc. Regardless, we - // definitely don't want section name truncation, so we're keeping this - // flag for windows. - // - // [1] - https://sourceware.org/bugzilla/show_bug.cgi?id=13130 - // [2] - https://code.google.com/p/go/issues/detail?id=2139 - "-Wl,--enable-long-section-names".to_string(), - // Tell GCC to avoid linker plugins, because we are not bundling // them with Windows installer, and Rust does its own LTO anyways. "-fno-use-linker-plugin".to_string(), diff --git a/src/librustc_typeck/error_codes.rs b/src/librustc_typeck/error_codes.rs index f21fc2df8b9..560abeb7057 100644 --- a/src/librustc_typeck/error_codes.rs +++ b/src/librustc_typeck/error_codes.rs @@ -3,9 +3,9 @@ syntax::register_diagnostics! { E0023: r##" -A pattern used to match against an enum variant must provide a sub-pattern for -each field of the enum variant. This error indicates that a pattern attempted to -extract an incorrect number of fields from a variant. +A pattern attempted to extract an incorrect number of fields from a variant. + +Erroneous code example: ``` enum Fruit { @@ -14,6 +14,9 @@ enum Fruit { } ``` +A pattern used to match against an enum variant must provide a sub-pattern for +each field of the enum variant. + Here the `Apple` variant has two fields, and should be matched against like so: ``` @@ -53,8 +56,9 @@ uses the same number. "##, E0025: r##" -Each field of a struct can only be bound once in a pattern. Erroneous code -example: +Each field of a struct can only be bound once in a pattern. + +Erroneous code example: ```compile_fail,E0025 struct Foo { @@ -89,65 +93,47 @@ fn main(){ "##, E0026: r##" -This error indicates that a struct pattern attempted to extract a non-existent -field from a struct. Struct fields are identified by the name used before the -colon `:` so struct patterns should resemble the declaration of the struct type -being matched. +A struct pattern attempted to extract a non-existent field from a struct. -``` -// Correct matching. -struct Thing { - x: u32, - y: u32 -} - -let thing = Thing { x: 1, y: 2 }; - -match thing { - Thing { x: xfield, y: yfield } => {} -} -``` - -If you are using shorthand field patterns but want to refer to the struct field -by a different name, you should rename it explicitly. - -Change this: +Erroneous code example: ```compile_fail,E0026 struct Thing { x: u32, - y: u32 + y: u32, } let thing = Thing { x: 0, y: 0 }; match thing { - Thing { x, z } => {} + Thing { x, z } => {} // error: `Thing::z` field doesn't exist } ``` -To this: +If you are using shorthand field patterns but want to refer to the struct field +by a different name, you should rename it explicitly. Struct fields are +identified by the name used before the colon `:` so struct patterns should +resemble the declaration of the struct type being matched. ``` struct Thing { x: u32, - y: u32 + y: u32, } let thing = Thing { x: 0, y: 0 }; match thing { - Thing { x, y: z } => {} + Thing { x, y: z } => {} // we renamed `y` to `z` } ``` "##, E0027: r##" -This error indicates that a pattern for a struct fails to specify a sub-pattern -for every one of the struct's fields. Ensure that each field from the struct's -definition is mentioned in the pattern, or use `..` to ignore unwanted fields. +A pattern for a struct fails to specify a sub-pattern for every one of the +struct's fields. -For example: +Erroneous code example: ```compile_fail,E0027 struct Dog { @@ -163,7 +149,8 @@ match d { } ``` -This is correct (explicit): +To fix this error, ensure that each field from the struct's definition is +mentioned in the pattern, or use `..` to ignore unwanted fields. Example: ``` struct Dog { @@ -185,11 +172,9 @@ match d { "##, E0029: r##" -In a match expression, only numbers and characters can be matched against a -range. This is because the compiler checks that the range is non-empty at -compile-time, and is unable to evaluate arbitrary comparison functions. If you -want to capture values of an orderable type between two end-points, you can use -a guard. +Something other than numbers and characters has been used for a range. + +Erroneous code example: ```compile_fail,E0029 let string = "salutations !"; @@ -207,14 +192,18 @@ match string { _ => {} } ``` + +In a match expression, only numbers and characters can be matched against a +range. This is because the compiler checks that the range is non-empty at +compile-time, and is unable to evaluate arbitrary comparison functions. If you +want to capture values of an orderable type between two end-points, you can use +a guard. "##, E0033: r##" -This error indicates that a pointer to a trait type cannot be implicitly -dereferenced by a pattern. Every trait defines a type, but because the -size of trait implementers 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. +A trait type has been dereferenced. + +Erroneous code example: ```compile_fail,E0033 # trait SomeTrait { fn method_one(&self){} fn method_two(&self){} } @@ -229,6 +218,12 @@ trait_obj.method_one(); trait_obj.method_two(); ``` +A pointer to a trait type cannot be implicitly dereferenced by a pattern. Every +trait defines a type, but because the size of trait implementers 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. + You can read more about trait objects in the [Trait Objects] section of the Reference. @@ -237,7 +232,9 @@ Reference. E0034: r##" The compiler doesn't know what method to call because more than one method -has the same prototype. Erroneous code example: +has the same prototype. + +Erroneous code example: ```compile_fail,E0034 struct Test; @@ -323,11 +320,9 @@ fn main() { "##, E0040: r##" -It is not allowed to manually call destructors in Rust. It is also not -necessary to do this since `drop` is called automatically whenever a value goes -out of scope. +It is not allowed to manually call destructors in Rust. -Here's an example of this error: +Erroneous code example: ```compile_fail,E0040 struct Foo { @@ -345,11 +340,33 @@ fn main() { x.drop(); // error: explicit use of destructor method } ``` + +It is unnecessary to do this since `drop` is called automatically whenever a +value goes out of scope. However, if you really need to drop a value by hand, +you can use the `std::mem::drop` function: + +``` +struct Foo { + x: i32, +} + +impl Drop for Foo { + fn drop(&mut self) { + println!("kaboom"); + } +} + +fn main() { + let mut x = Foo { x: -7 }; + drop(x); // ok! +} +``` "##, E0044: r##" You cannot use type or const parameters on foreign items. -Example of erroneous code: + +Erroneous code example: ```compile_fail,E0044 extern { fn some_func(x: T); } @@ -365,21 +382,21 @@ extern { fn some_func_i64(x: i64); } "##, E0045: r##" -Rust only supports variadic parameters for interoperability with C code in its -FFI. As such, variadic parameters can only be used with functions which are -using the C ABI. Examples of erroneous code: +Variadic parameters have been used on a non-C ABI function. -```compile_fail +Erroneous code example: + +```compile_fail,E0045 #![feature(unboxed_closures)] -extern "rust-call" { fn foo(x: u8, ...); } - -// or - -fn foo(x: u8, ...) {} +extern "rust-call" { + fn foo(x: u8, ...); // error! +} ``` -To fix such code, put them in an extern "C" block: +Rust only supports variadic parameters for interoperability with C code in its +FFI. As such, variadic parameters can only be used with functions which are +using the C ABI. To fix such code, put them in an extern "C" block: ``` extern "C" { @@ -389,7 +406,9 @@ extern "C" { "##, E0046: r##" -Items are missing in a trait implementation. Erroneous code example: +Items are missing in a trait implementation. + +Erroneous code example: ```compile_fail,E0046 trait Foo { @@ -421,11 +440,10 @@ impl Foo for Bar { "##, E0049: r##" -This error indicates that an attempted implementation of a trait method -has the wrong number of type or const parameters. +An attempted implementation of a trait method has the wrong number of type or +const parameters. -For example, the trait below has a method `foo` with a type parameter `T`, -but the implementation of `foo` for the type `Bar` is missing this parameter: +Erroneous code example: ```compile_fail,E0049 trait Foo { @@ -440,15 +458,31 @@ impl Foo for Bar { fn foo(x: bool) -> Self { Bar } } ``` + +For example, the `Foo` trait has a method `foo` with a type parameter `T`, +but the implementation of `foo` for the type `Bar` is missing this parameter. +To fix this error, they must have the same type parameters: + +``` +trait Foo { + fn foo(x: T) -> Self; +} + +struct Bar; + +impl Foo for Bar { + fn foo(x: T) -> Self { // ok! + Bar + } +} +``` "##, E0050: r##" -This error indicates that an attempted implementation of a trait method -has the wrong number of function parameters. +An attempted implementation of a trait method has the wrong number of function +parameters. -For example, the trait below has a method `foo` with two function parameters -(`&self` and `u8`), but the implementation of `foo` for the type `Bar` omits -the `u8` parameter: +Erroneous code example: ```compile_fail,E0050 trait Foo { @@ -463,13 +497,31 @@ impl Foo for Bar { fn foo(&self) -> bool { true } } ``` + +For example, the `Foo` trait has a method `foo` with two function parameters +(`&self` and `u8`), but the implementation of `foo` for the type `Bar` omits +the `u8` parameter. To fix this error, they must have the same parameters: + +``` +trait Foo { + fn foo(&self, x: u8) -> bool; +} + +struct Bar; + +impl Foo for Bar { + fn foo(&self, x: u8) -> bool { // ok! + true + } +} +``` "##, E0053: r##" The parameters of any trait method must match between a trait implementation and the trait definition. -Here are a couple examples of this error: +Erroneous code example: ```compile_fail,E0053 trait Foo { @@ -490,8 +542,9 @@ impl Foo for Bar { "##, E0054: r##" -It is not allowed to cast to a bool. If you are trying to cast a numeric type -to a bool, you can compare it with zero instead: +It is not allowed to cast to a bool. + +Erroneous code example: ```compile_fail,E0054 let x = 5; @@ -500,6 +553,9 @@ let x = 5; let x_is_nonzero = x as bool; ``` +If you are trying to cast a numeric type to a bool, you can compare it with +zero instead: + ``` let x = 5; diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index 97f41fdc5ba..3d42d5bb0ca 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -39,6 +39,7 @@ use std::fmt; use std::hash::{Hash, Hasher}; use std::default::Default; use std::{mem, slice, vec}; +use std::num::NonZeroU32; use std::iter::FromIterator; use std::rc::Rc; use std::cell::RefCell; @@ -4399,7 +4400,7 @@ pub struct Stability { pub since: String, pub deprecation: Option, pub unstable_reason: Option, - pub issue: Option, + pub issue: Option, } #[derive(Clone, Debug)] @@ -4428,7 +4429,7 @@ impl Clean for attr::Stability { _ => None, }, issue: match self.level { - attr::Unstable {issue, ..} => Some(issue), + attr::Unstable {issue, ..} => issue, _ => None, } } diff --git a/src/libstd/collections/hash/set.rs b/src/libstd/collections/hash/set.rs index 092fb443468..a038ee80210 100644 --- a/src/libstd/collections/hash/set.rs +++ b/src/libstd/collections/hash/set.rs @@ -551,7 +551,7 @@ impl HashSet #[inline] #[stable(feature = "rust1", since = "1.0.0")] pub fn union<'a>(&'a self, other: &'a HashSet) -> Union<'a, T, S> { - if self.len() <= other.len() { + if self.len() >= other.len() { Union { iter: self.iter().chain(other.difference(self)), } diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs index c83931a0668..13bf6752ba2 100644 --- a/src/libsyntax/ast.rs +++ b/src/libsyntax/ast.rs @@ -38,9 +38,6 @@ use rustc_data_structures::thin_vec::ThinVec; use rustc_index::vec::Idx; use rustc_serialize::{self, Decoder, Encoder}; -#[cfg(target_arch = "x86_64")] -use rustc_data_structures::static_assert_size; - use std::fmt; #[cfg(test)] @@ -1028,7 +1025,7 @@ pub struct Expr { // `Expr` is used a lot. Make sure it doesn't unintentionally get bigger. #[cfg(target_arch = "x86_64")] -static_assert_size!(Expr, 96); +rustc_data_structures::static_assert_size!(Expr, 96); impl Expr { /// Returns `true` if this expression would be valid somewhere that expects a value; diff --git a/src/libsyntax/attr/builtin.rs b/src/libsyntax/attr/builtin.rs index d0a31b330ab..2b759c205f5 100644 --- a/src/libsyntax/attr/builtin.rs +++ b/src/libsyntax/attr/builtin.rs @@ -6,6 +6,7 @@ use crate::print::pprust; use crate::sess::ParseSess; use errors::{Applicability, Handler}; +use std::num::NonZeroU32; use syntax_pos::hygiene::Transparency; use syntax_pos::{symbol::Symbol, symbol::sym, Span}; @@ -157,7 +158,7 @@ pub struct Stability { #[derive(RustcEncodable, RustcDecodable, PartialEq, PartialOrd, Copy, Clone, Debug, Eq, Hash)] pub enum StabilityLevel { // Reason for the current stability level and the relevant rust-lang issue - Unstable { reason: Option, issue: u32, is_soft: bool }, + Unstable { reason: Option, issue: Option, is_soft: bool }, Stable { since: Symbol }, } @@ -394,18 +395,28 @@ fn find_stability_generic<'a, I>(sess: &ParseSess, match (feature, reason, issue) { (Some(feature), reason, Some(issue)) => { + let issue = match &*issue.as_str() { + // FIXME(rossmacarthur): remove "0" because "none" should be used + // See #41260 + "none" | "0" => None, + issue => { + if let Ok(num) = issue.parse() { + NonZeroU32::new(num) + } else { + span_err!( + diagnostic, + attr.span, + E0545, + "incorrect 'issue'" + ); + continue + } + } + }; stab = Some(Stability { level: Unstable { reason, - issue: { - if let Ok(issue) = issue.as_str().parse() { - issue - } else { - span_err!(diagnostic, attr.span, E0545, - "incorrect 'issue'"); - continue - } - }, + issue, is_soft, }, feature, diff --git a/src/libsyntax/feature_gate/active.rs b/src/libsyntax/feature_gate/active.rs index d59d0f0e28e..2819ee273d9 100644 --- a/src/libsyntax/feature_gate/active.rs +++ b/src/libsyntax/feature_gate/active.rs @@ -207,10 +207,10 @@ declare_features! ( /// Allows using `#![needs_allocator]`, an implementation detail of `#[global_allocator]`. (active, allocator_internals, "1.20.0", None, None), - // no-tracking-issue-end - /// Added for testing E0705; perma-unstable. - (active, test_2018_feature, "1.31.0", Some(0), Some(Edition::Edition2018)), + (active, test_2018_feature, "1.31.0", None, Some(Edition::Edition2018)), + + // no-tracking-issue-end // ------------------------------------------------------------------------- // feature-group-end: internal feature gates diff --git a/src/libsyntax/feature_gate/check.rs b/src/libsyntax/feature_gate/check.rs index 4742e01d7f4..3bf1e24bf12 100644 --- a/src/libsyntax/feature_gate/check.rs +++ b/src/libsyntax/feature_gate/check.rs @@ -18,6 +18,7 @@ use syntax_pos::{Span, DUMMY_SP, MultiSpan}; use log::debug; use std::env; +use std::num::NonZeroU32; #[derive(Copy, Clone, Debug)] pub enum Stability { @@ -55,25 +56,28 @@ pub fn check_attribute(attr: &ast::Attribute, parse_sess: &ParseSess, features: PostExpansionVisitor { parse_sess, features }.visit_attribute(attr) } -fn find_lang_feature_issue(feature: Symbol) -> Option { +fn find_lang_feature_issue(feature: Symbol) -> Option { if let Some(info) = ACTIVE_FEATURES.iter().find(|t| t.name == feature) { // FIXME (#28244): enforce that active features have issue numbers - // assert!(info.issue.is_some()) - info.issue + // assert!(info.issue().is_some()) + info.issue() } else { // search in Accepted, Removed, or Stable Removed features - let found = ACCEPTED_FEATURES.iter().chain(REMOVED_FEATURES).chain(STABLE_REMOVED_FEATURES) + let found = ACCEPTED_FEATURES + .iter() + .chain(REMOVED_FEATURES) + .chain(STABLE_REMOVED_FEATURES) .find(|t| t.name == feature); match found { - Some(&Feature { issue, .. }) => issue, - None => panic!("Feature `{}` is not declared anywhere", feature), + Some(found) => found.issue(), + None => panic!("feature `{}` is not declared anywhere", feature), } } } pub enum GateIssue { Language, - Library(Option) + Library(Option) } #[derive(Debug, Copy, Clone, PartialEq)] @@ -126,14 +130,11 @@ fn leveled_feature_err<'a, S: Into>( GateStrength::Soft => diag.struct_span_warn(span, explain), }; - match issue { - None | Some(0) => {} // We still accept `0` as a stand-in for backwards compatibility - Some(n) => { - err.note(&format!( - "for more information, see https://github.com/rust-lang/rust/issues/{}", - n, - )); - } + if let Some(n) = issue { + err.note(&format!( + "for more information, see https://github.com/rust-lang/rust/issues/{}", + n, + )); } // #23973: do not suggest `#![feature(...)]` if we are in beta/stable diff --git a/src/libsyntax/feature_gate/mod.rs b/src/libsyntax/feature_gate/mod.rs index ba970618c0e..c4418c0f0f6 100644 --- a/src/libsyntax/feature_gate/mod.rs +++ b/src/libsyntax/feature_gate/mod.rs @@ -18,8 +18,9 @@ mod active; mod builtin_attrs; mod check; -use std::fmt; use crate::{edition::Edition, symbol::Symbol}; +use std::fmt; +use std::num::NonZeroU32; use syntax_pos::Span; #[derive(Clone, Copy)] @@ -46,11 +47,17 @@ pub struct Feature { state: State, name: Symbol, since: &'static str, - issue: Option, + issue: Option, // FIXME: once #58732 is done make this an Option edition: Option, description: &'static str, } +impl Feature { + fn issue(&self) -> Option { + self.issue.and_then(|i| NonZeroU32::new(i)) + } +} + pub use active::{Features, INCOMPLETE_FEATURES}; pub use builtin_attrs::{ AttributeGate, AttributeType, GatedCfg, diff --git a/src/libsyntax/token.rs b/src/libsyntax/token.rs index c70e3442703..ab798e93d67 100644 --- a/src/libsyntax/token.rs +++ b/src/libsyntax/token.rs @@ -14,8 +14,6 @@ use syntax_pos::{self, Span, DUMMY_SP}; use std::fmt; use std::mem; -#[cfg(target_arch = "x86_64")] -use rustc_data_structures::static_assert_size; use rustc_data_structures::sync::Lrc; #[derive(Clone, PartialEq, RustcEncodable, RustcDecodable, Hash, Debug, Copy)] @@ -261,7 +259,7 @@ pub enum TokenKind { // `TokenKind` is used a lot. Make sure it doesn't unintentionally get bigger. #[cfg(target_arch = "x86_64")] -static_assert_size!(TokenKind, 16); +rustc_data_structures::static_assert_size!(TokenKind, 16); #[derive(Clone, PartialEq, RustcEncodable, RustcDecodable, Debug)] pub struct Token { diff --git a/src/libsyntax/tokenstream.rs b/src/libsyntax/tokenstream.rs index 4d08d0974c1..2201f1ed6ca 100644 --- a/src/libsyntax/tokenstream.rs +++ b/src/libsyntax/tokenstream.rs @@ -16,8 +16,6 @@ use crate::token::{self, DelimToken, Token, TokenKind}; use syntax_pos::{Span, DUMMY_SP}; -#[cfg(target_arch = "x86_64")] -use rustc_data_structures::static_assert_size; use rustc_data_structures::sync::Lrc; use smallvec::{SmallVec, smallvec}; @@ -129,7 +127,7 @@ pub type TreeAndJoint = (TokenTree, IsJoint); // `TokenStream` is used a lot. Make sure it doesn't unintentionally get bigger. #[cfg(target_arch = "x86_64")] -static_assert_size!(TokenStream, 8); +rustc_data_structures::static_assert_size!(TokenStream, 8); #[derive(Clone, Copy, Debug, PartialEq, RustcEncodable, RustcDecodable)] pub enum IsJoint { diff --git a/src/libsyntax_ext/proc_macro_harness.rs b/src/libsyntax_ext/proc_macro_harness.rs index 792c97d8508..fbded7dc130 100644 --- a/src/libsyntax_ext/proc_macro_harness.rs +++ b/src/libsyntax_ext/proc_macro_harness.rs @@ -92,10 +92,12 @@ pub fn inject(sess: &ParseSess, impl<'a> CollectProcMacros<'a> { fn check_not_pub_in_root(&self, vis: &ast::Visibility, sp: Span) { if self.is_proc_macro_crate && self.in_root && vis.node.is_pub() { - self.handler.span_err(sp, - "`proc-macro` crate types cannot \ - export any items other than functions \ - tagged with `#[proc_macro_derive]` currently"); + self.handler.span_err( + sp, + "`proc-macro` crate types currently cannot export any items other \ + than functions tagged with `#[proc_macro]`, `#[proc_macro_derive]`, \ + or `#[proc_macro_attribute]`", + ); } } diff --git a/src/test/ui/feature-gate/unstable-attribute-allow-issue-none.rs b/src/test/ui/feature-gate/unstable-attribute-allow-issue-none.rs new file mode 100644 index 00000000000..3ce9de3fb1b --- /dev/null +++ b/src/test/ui/feature-gate/unstable-attribute-allow-issue-none.rs @@ -0,0 +1,13 @@ +// Check that an issue value can be explicitly set to "none" instead of "0" +#![crate_type = "lib"] +#![feature(staged_api)] +#![stable(feature = "stable_test_feature", since = "1.0.0")] + +#[unstable(feature = "unstable_test_feature", issue = "0")] +fn unstable_issue_0() {} + +#[unstable(feature = "unstable_test_feature", issue = "none")] +fn unstable_issue_none() {} + +#[unstable(feature = "unstable_test_feature", issue = "something")] //~ ERROR incorrect 'issue' +fn unstable_issue_not_allowed() {} diff --git a/src/test/ui/feature-gate/unstable-attribute-allow-issue-none.stderr b/src/test/ui/feature-gate/unstable-attribute-allow-issue-none.stderr new file mode 100644 index 00000000000..fc031f5f8c5 --- /dev/null +++ b/src/test/ui/feature-gate/unstable-attribute-allow-issue-none.stderr @@ -0,0 +1,8 @@ +error[E0545]: incorrect 'issue' + --> $DIR/unstable-attribute-allow-issue-none.rs:12:1 + | +LL | #[unstable(feature = "unstable_test_feature", issue = "something")] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to previous error + diff --git a/src/test/ui/proc-macro/exports.stderr b/src/test/ui/proc-macro/exports.stderr index 2f81921358d..0ecbdf98dd3 100644 --- a/src/test/ui/proc-macro/exports.stderr +++ b/src/test/ui/proc-macro/exports.stderr @@ -1,22 +1,22 @@ -error: `proc-macro` crate types cannot export any items other than functions tagged with `#[proc_macro_derive]` currently +error: `proc-macro` crate types currently cannot export any items other than functions tagged with `#[proc_macro]`, `#[proc_macro_derive]`, or `#[proc_macro_attribute]` --> $DIR/exports.rs:7:1 | LL | pub fn a() {} | ^^^^^^^^^^^^^ -error: `proc-macro` crate types cannot export any items other than functions tagged with `#[proc_macro_derive]` currently +error: `proc-macro` crate types currently cannot export any items other than functions tagged with `#[proc_macro]`, `#[proc_macro_derive]`, or `#[proc_macro_attribute]` --> $DIR/exports.rs:8:1 | LL | pub struct B; | ^^^^^^^^^^^^^ -error: `proc-macro` crate types cannot export any items other than functions tagged with `#[proc_macro_derive]` currently +error: `proc-macro` crate types currently cannot export any items other than functions tagged with `#[proc_macro]`, `#[proc_macro_derive]`, or `#[proc_macro_attribute]` --> $DIR/exports.rs:9:1 | LL | pub enum C {} | ^^^^^^^^^^^^^ -error: `proc-macro` crate types cannot export any items other than functions tagged with `#[proc_macro_derive]` currently +error: `proc-macro` crate types currently cannot export any items other than functions tagged with `#[proc_macro]`, `#[proc_macro_derive]`, or `#[proc_macro_attribute]` --> $DIR/exports.rs:10:1 | LL | pub mod d {} diff --git a/src/test/ui/proc-macro/pub-at-crate-root.rs b/src/test/ui/proc-macro/pub-at-crate-root.rs index 7544245ff67..54cf333a45b 100644 --- a/src/test/ui/proc-macro/pub-at-crate-root.rs +++ b/src/test/ui/proc-macro/pub-at-crate-root.rs @@ -5,7 +5,7 @@ extern crate proc_macro; -pub mod a { //~ `proc-macro` crate types cannot export any items +pub mod a { //~ `proc-macro` crate types currently cannot export any items use proc_macro::TokenStream; #[proc_macro_derive(B)] diff --git a/src/test/ui/proc-macro/pub-at-crate-root.stderr b/src/test/ui/proc-macro/pub-at-crate-root.stderr index 66fa499d33b..3b69b7875bd 100644 --- a/src/test/ui/proc-macro/pub-at-crate-root.stderr +++ b/src/test/ui/proc-macro/pub-at-crate-root.stderr @@ -1,4 +1,4 @@ -error: `proc-macro` crate types cannot export any items other than functions tagged with `#[proc_macro_derive]` currently +error: `proc-macro` crate types currently cannot export any items other than functions tagged with `#[proc_macro]`, `#[proc_macro_derive]`, or `#[proc_macro_attribute]` --> $DIR/pub-at-crate-root.rs:8:1 | LL | / pub mod a {