[[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",
[[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",
]
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()
.map(|x| INTERNER.intern_string(x))
.collect::<Vec<_>>(),
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"))
# 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)
--- /dev/null
+# 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
--- /dev/null
+# 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 | | /// ```
+ | |___________^
+```
"}
}
-// `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,
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,
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 {
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,
sess: &Session,
feature: Symbol,
reason: Option<Symbol>,
- issue: u32,
+ issue: Option<NonZeroU32>,
is_soft: bool,
span: Span,
soft_handler: impl FnOnce(&'static lint::Lint, Span, &str),
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
);
}
}
Deny {
feature: Symbol,
reason: Option<Symbol>,
- issue: u32,
+ issue: Option<NonZeroU32>,
is_soft: bool,
},
/// The item does not have the `#[stable]` or `#[unstable]` marker assigned.
// 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;
}
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 {
pub variants: Vec<VariantInfo>,
}
-#[derive(PartialEq, Eq, Debug, Default)]
+#[derive(Default)]
pub struct CodeStats {
- type_sizes: FxHashSet<TypeSizeInfo>,
+ type_sizes: Lock<FxHashSet<TypeSizeInfo>>,
}
impl CodeStats {
- pub fn record_type_size<S: ToString>(&mut self,
+ pub fn record_type_size<S: ToString>(&self,
kind: DataTypeKind,
type_desc: S,
align: Align,
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)
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;
pub perf_stats: PerfStats,
/// Data about code being compiled, gathered during compilation.
- pub code_stats: Lock<CodeStats>,
+ pub code_stats: CodeStats,
/// If `-zfuel=crate=n` is specified, `Some(crate)`.
optimization_fuel_crate: Option<String>,
pub enum DiagnosticMessageId {
ErrorId(u16), // EXXXX error code as integer
LintId(lint::LintId),
- StabilityId(u32), // issue number
+ StabilityId(Option<NonZeroU32>), // issue number
}
impl From<&'static lint::Lint> for DiagnosticMessageId {
// (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 {
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()?;
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;
// `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.
///
ConstantValue(&'tcx ty::Const<'tcx>, Span),
/// Ranges of literal values (`2..=5` and `2..5`).
ConstantRange(u128, u128, Ty<'tcx>, RangeEnd, Span),
- /// Array patterns of length n.
- Slice(u64),
+ /// Array patterns of length `n`.
+ FixedLenSlice(u64),
+ /// Slice patterns. Captures any array constructor of `length >= i + j`.
+ VarLenSlice(u64, u64),
}
// Ignore spans when comparing, they don't carry semantic information as they are only for lints.
Constructor::ConstantRange(a_start, a_end, a_ty, a_range_end, _),
Constructor::ConstantRange(b_start, b_end, b_ty, b_range_end, _),
) => a_start == b_start && a_end == b_end && a_ty == b_ty && a_range_end == b_range_end,
- (Constructor::Slice(a), Constructor::Slice(b)) => a == b,
+ (Constructor::FixedLenSlice(a), Constructor::FixedLenSlice(b)) => a == b,
+ (
+ Constructor::VarLenSlice(a_prefix, a_suffix),
+ Constructor::VarLenSlice(b_prefix, b_suffix),
+ ) => a_prefix == b_prefix && a_suffix == b_suffix,
_ => false,
}
}
impl<'tcx> Constructor<'tcx> {
fn is_slice(&self) -> bool {
match self {
- Slice { .. } => true,
+ FixedLenSlice { .. } | VarLenSlice { .. } => true,
_ => false,
}
}
ty::Const::from_bits(tcx, *hi, ty),
)
}
- Constructor::Slice(val) => format!("[{}]", val),
+ Constructor::FixedLenSlice(val) => format!("[{}]", val),
+ Constructor::VarLenSlice(prefix, suffix) => format!("[{}, .., {}]", prefix, suffix),
_ => bug!("bad constructor being displayed: `{:?}", self),
}
}
param_env: ty::ParamEnv<'tcx>,
other_ctors: &Vec<Constructor<'tcx>>,
) -> Vec<Constructor<'tcx>> {
- let mut refined_ctors = vec![self.clone()];
- for other_ctor in other_ctors {
- if other_ctor == self {
- // If a constructor appears in a `match` arm, we can
- // eliminate it straight away.
- refined_ctors = vec![]
- } else if let Some(interval) = IntRange::from_ctor(tcx, param_env, other_ctor) {
- // Refine the required constructors for the type by subtracting
- // the range defined by the current constructor pattern.
- refined_ctors = interval.subtract_from(tcx, param_env, refined_ctors);
+ match *self {
+ // Those constructors can only match themselves.
+ Single | Variant(_) => {
+ if other_ctors.iter().any(|c| c == self) {
+ vec![]
+ } else {
+ vec![self.clone()]
+ }
+ }
+ FixedLenSlice(self_len) => {
+ let overlaps = |c: &Constructor<'_>| match *c {
+ FixedLenSlice(other_len) => other_len == self_len,
+ VarLenSlice(prefix, suffix) => prefix + suffix <= self_len,
+ _ => false,
+ };
+ if other_ctors.iter().any(overlaps) { vec![] } else { vec![self.clone()] }
}
+ VarLenSlice(..) => {
+ let mut remaining_ctors = vec![self.clone()];
+
+ // For each used ctor, subtract from the current set of constructors.
+ // Naming: we remove the "neg" constructors from the "pos" ones.
+ // Remember, `VarLenSlice(i, j)` covers the union of `FixedLenSlice` from
+ // `i + j` to infinity.
+ for neg_ctor in other_ctors {
+ remaining_ctors = remaining_ctors
+ .into_iter()
+ .flat_map(|pos_ctor| -> SmallVec<[Constructor<'tcx>; 1]> {
+ // Compute `pos_ctor \ neg_ctor`.
+ match (&pos_ctor, neg_ctor) {
+ (&FixedLenSlice(pos_len), &VarLenSlice(neg_prefix, neg_suffix)) => {
+ let neg_len = neg_prefix + neg_suffix;
+ if neg_len <= pos_len {
+ smallvec![]
+ } else {
+ smallvec![pos_ctor]
+ }
+ }
+ (
+ &VarLenSlice(pos_prefix, pos_suffix),
+ &VarLenSlice(neg_prefix, neg_suffix),
+ ) => {
+ let neg_len = neg_prefix + neg_suffix;
+ let pos_len = pos_prefix + pos_suffix;
+ if neg_len <= pos_len {
+ smallvec![]
+ } else {
+ (pos_len..neg_len).map(FixedLenSlice).collect()
+ }
+ }
+ (&VarLenSlice(pos_prefix, pos_suffix), &FixedLenSlice(neg_len)) => {
+ let pos_len = pos_prefix + pos_suffix;
+ if neg_len < pos_len {
+ smallvec![pos_ctor]
+ } else {
+ (pos_len..neg_len)
+ .map(FixedLenSlice)
+ // We know that `neg_len + 1 >= pos_len >= pos_suffix`.
+ .chain(Some(VarLenSlice(
+ neg_len + 1 - pos_suffix,
+ pos_suffix,
+ )))
+ .collect()
+ }
+ }
+ _ if pos_ctor == *neg_ctor => smallvec![],
+ _ => smallvec![pos_ctor],
+ }
+ })
+ .collect();
+
+ // If the constructors that have been considered so far already cover
+ // the entire range of `self`, no need to look at more constructors.
+ if remaining_ctors.is_empty() {
+ break;
+ }
+ }
- // If the constructor patterns that have been considered so far
- // already cover the entire range of values, then we know the
- // constructor is not missing, and we can move on to the next one.
- if refined_ctors.is_empty() {
- break;
+ remaining_ctors
}
- }
+ ConstantRange(..) | ConstantValue(..) => {
+ let mut remaining_ctors = vec![self.clone()];
+ for other_ctor in other_ctors {
+ if other_ctor == self {
+ // If a constructor appears in a `match` arm, we can
+ // eliminate it straight away.
+ remaining_ctors = vec![]
+ } else if let Some(interval) = IntRange::from_ctor(tcx, param_env, other_ctor) {
+ // Refine the required constructors for the type by subtracting
+ // the range defined by the current constructor pattern.
+ remaining_ctors = interval.subtract_from(tcx, param_env, remaining_ctors);
+ }
- // If a constructor has not been matched, then it is missing.
- // We add `refined_ctors` instead of `self`, because then we can
- // provide more detailed error information about precisely which
- // ranges have been omitted.
- refined_ctors
+ // If the constructor patterns that have been considered so far
+ // already cover the entire range of values, then we know the
+ // constructor is not missing, and we can move on to the next one.
+ if remaining_ctors.is_empty() {
+ break;
+ }
+ }
+
+ // If a constructor has not been matched, then it is missing.
+ // We add `remaining_ctors` instead of `self`, because then we can
+ // provide more detailed error information about precisely which
+ // ranges have been omitted.
+ remaining_ctors
+ }
+ }
}
/// This returns one wildcard pattern for each argument to this constructor.
&self,
cx: &MatchCheckCtxt<'a, 'tcx>,
ty: Ty<'tcx>,
- ) -> impl Iterator<Item = Pat<'tcx>> + DoubleEndedIterator {
- constructor_sub_pattern_tys(cx, self, ty).into_iter().map(|ty| Pat {
- ty,
- span: DUMMY_SP,
- kind: box PatKind::Wild,
- })
+ ) -> Vec<Pat<'tcx>> {
+ debug!("wildcard_subpatterns({:#?}, {:?})", self, ty);
+ match ty.kind {
+ ty::Tuple(ref fs) => {
+ fs.into_iter().map(|t| t.expect_ty()).map(Pat::wildcard_from_ty).collect()
+ }
+ ty::Slice(ty) | ty::Array(ty, _) => match *self {
+ FixedLenSlice(length) => (0..length).map(|_| Pat::wildcard_from_ty(ty)).collect(),
+ VarLenSlice(prefix, suffix) => {
+ (0..prefix + suffix).map(|_| Pat::wildcard_from_ty(ty)).collect()
+ }
+ ConstantValue(..) => vec![],
+ _ => bug!("bad slice pattern {:?} {:?}", self, ty),
+ },
+ ty::Ref(_, rty, _) => vec![Pat::wildcard_from_ty(rty)],
+ ty::Adt(adt, substs) => {
+ if adt.is_box() {
+ // Use T as the sub pattern type of Box<T>.
+ vec![Pat::wildcard_from_ty(substs.type_at(0))]
+ } else {
+ let variant = &adt.variants[self.variant_index_for_adt(cx, adt)];
+ let is_non_exhaustive =
+ variant.is_field_list_non_exhaustive() && !cx.is_local(ty);
+ variant
+ .fields
+ .iter()
+ .map(|field| {
+ let is_visible =
+ adt.is_enum() || field.vis.is_accessible_from(cx.module, cx.tcx);
+ let is_uninhabited = cx.is_uninhabited(field.ty(cx.tcx, substs));
+ match (is_visible, is_non_exhaustive, is_uninhabited) {
+ // Treat all uninhabited types in non-exhaustive variants as
+ // `TyErr`.
+ (_, true, true) => cx.tcx.types.err,
+ // Treat all non-visible fields as `TyErr`. They can't appear in
+ // any other pattern from this match (because they are private), so
+ // their type does not matter - but we don't want to know they are
+ // uninhabited.
+ (false, ..) => cx.tcx.types.err,
+ (true, ..) => {
+ let ty = field.ty(cx.tcx, substs);
+ match ty.kind {
+ // If the field type returned is an array of an unknown
+ // size return an TyErr.
+ ty::Array(_, len)
+ if len
+ .try_eval_usize(cx.tcx, cx.param_env)
+ .is_none() =>
+ {
+ cx.tcx.types.err
+ }
+ _ => ty,
+ }
+ }
+ }
+ })
+ .map(Pat::wildcard_from_ty)
+ .collect()
+ }
+ }
+ _ => vec![],
+ }
}
/// This computes the arity of a constructor. The arity of a constructor
match ty.kind {
ty::Tuple(ref fs) => fs.len() as u64,
ty::Slice(..) | ty::Array(..) => match *self {
- Slice(length) => length,
+ FixedLenSlice(length) => length,
+ VarLenSlice(prefix, suffix) => prefix + suffix,
ConstantValue(..) => 0,
_ => bug!("bad slice pattern {:?} {:?}", self, ty),
},
ty::Ref(..) => PatKind::Deref { subpattern: subpatterns.nth(0).unwrap() },
- ty::Slice(_) | ty::Array(..) => {
- PatKind::Slice { prefix: subpatterns.collect(), slice: None, suffix: vec![] }
- }
+ ty::Slice(_) | ty::Array(..) => match self {
+ FixedLenSlice(_) => {
+ PatKind::Slice { prefix: subpatterns.collect(), slice: None, suffix: vec![] }
+ }
+ VarLenSlice(prefix_len, _suffix_len) => {
+ let prefix = subpatterns.by_ref().take(*prefix_len as usize).collect();
+ let suffix = subpatterns.collect();
+ let wild = Pat::wildcard_from_ty(ty);
+ PatKind::Slice { prefix, slice: Some(wild), suffix }
+ }
+ _ => bug!("bad slice pattern {:?} {:?}", self, ty),
+ },
_ => match *self {
ConstantValue(value, _) => PatKind::Constant { value },
/// Like `apply`, but where all the subpatterns are wildcards `_`.
fn apply_wildcards<'a>(&self, cx: &MatchCheckCtxt<'a, 'tcx>, ty: Ty<'tcx>) -> Pat<'tcx> {
- let subpatterns = self.wildcard_subpatterns(cx, ty).rev();
+ let subpatterns = self.wildcard_subpatterns(cx, ty).into_iter().rev();
self.apply(cx, ty, subpatterns)
}
}
fn apply_wildcard(self, ty: Ty<'tcx>) -> Self {
match self {
UsefulWithWitness(witnesses) => {
- let wild = Pat { ty, span: DUMMY_SP, kind: box PatKind::Wild };
+ let wild = Pat::wildcard_from_ty(ty);
UsefulWithWitness(
witnesses
.into_iter()
#[derive(Copy, Clone, Debug)]
struct PatCtxt<'tcx> {
ty: Ty<'tcx>,
- max_slice_length: u64,
span: Span,
}
.collect(),
ty::Array(ref sub_ty, len) if len.try_eval_usize(cx.tcx, cx.param_env).is_some() => {
let len = len.eval_usize(cx.tcx, cx.param_env);
- if len != 0 && cx.is_uninhabited(sub_ty) { vec![] } else { vec![Slice(len)] }
+ if len != 0 && cx.is_uninhabited(sub_ty) { vec![] } else { vec![FixedLenSlice(len)] }
}
// Treat arrays of a constant but unknown length like slices.
ty::Array(ref sub_ty, _) | ty::Slice(ref sub_ty) => {
if cx.is_uninhabited(sub_ty) {
- vec![Slice(0)]
+ vec![FixedLenSlice(0)]
} else {
- (0..pcx.max_slice_length + 1).map(|length| Slice(length)).collect()
+ vec![VarLenSlice(0, 0)]
}
}
ty::Adt(def, substs) if def.is_enum() => def
ctors
}
-fn max_slice_length<'p, 'a, 'tcx, I>(cx: &mut MatchCheckCtxt<'a, 'tcx>, patterns: I) -> u64
-where
- I: Iterator<Item = &'p Pat<'tcx>>,
- 'tcx: 'p,
-{
- // The exhaustiveness-checking paper does not include any details on
- // checking variable-length slice patterns. However, they are matched
- // by an infinite collection of fixed-length array patterns.
- //
- // Checking the infinite set directly would take an infinite amount
- // of time. However, it turns out that for each finite set of
- // patterns `P`, all sufficiently large array lengths are equivalent:
- //
- // Each slice `s` with a "sufficiently-large" length `l ≥ L` that applies
- // to exactly the subset `Pₜ` of `P` can be transformed to a slice
- // `sₘ` for each sufficiently-large length `m` that applies to exactly
- // the same subset of `P`.
- //
- // Because of that, each witness for reachability-checking from one
- // of the sufficiently-large lengths can be transformed to an
- // equally-valid witness from any other length, so we only have
- // to check slice lengths from the "minimal sufficiently-large length"
- // and below.
- //
- // Note that the fact that there is a *single* `sₘ` for each `m`
- // not depending on the specific pattern in `P` is important: if
- // you look at the pair of patterns
- // `[true, ..]`
- // `[.., false]`
- // Then any slice of length ≥1 that matches one of these two
- // patterns can be trivially turned to a slice of any
- // other length ≥1 that matches them and vice-versa - for
- // but the slice from length 2 `[false, true]` that matches neither
- // of these patterns can't be turned to a slice from length 1 that
- // matches neither of these patterns, so we have to consider
- // slices from length 2 there.
- //
- // Now, to see that that length exists and find it, observe that slice
- // patterns are either "fixed-length" patterns (`[_, _, _]`) or
- // "variable-length" patterns (`[_, .., _]`).
- //
- // For fixed-length patterns, all slices with lengths *longer* than
- // the pattern's length have the same outcome (of not matching), so
- // as long as `L` is greater than the pattern's length we can pick
- // any `sₘ` from that length and get the same result.
- //
- // For variable-length patterns, the situation is more complicated,
- // because as seen above the precise value of `sₘ` matters.
- //
- // However, for each variable-length pattern `p` with a prefix of length
- // `plâ‚š` and suffix of length `slâ‚š`, only the first `plâ‚š` and the last
- // `slâ‚š` elements are examined.
- //
- // Therefore, as long as `L` is positive (to avoid concerns about empty
- // types), all elements after the maximum prefix length and before
- // the maximum suffix length are not examined by any variable-length
- // pattern, and therefore can be added/removed without affecting
- // them - creating equivalent patterns from any sufficiently-large
- // length.
- //
- // Of course, if fixed-length patterns exist, we must be sure
- // that our length is large enough to miss them all, so
- // we can pick `L = max(FIXED_LEN+1 ∪ {max(PREFIX_LEN) + max(SUFFIX_LEN)})`
- //
- // for example, with the above pair of patterns, all elements
- // but the first and last can be added/removed, so any
- // witness of length ≥2 (say, `[false, false, true]`) can be
- // turned to a witness from any other length ≥2.
-
- let mut max_prefix_len = 0;
- let mut max_suffix_len = 0;
- let mut max_fixed_len = 0;
-
- for row in patterns {
- match *row.kind {
- PatKind::Constant { value } => {
- // extract the length of an array/slice from a constant
- match (value.val, &value.ty.kind) {
- (_, ty::Array(_, n)) => {
- max_fixed_len = cmp::max(max_fixed_len, n.eval_usize(cx.tcx, cx.param_env))
- }
- (ConstValue::Slice { start, end, .. }, ty::Slice(_)) => {
- max_fixed_len = cmp::max(max_fixed_len, (end - start) as u64)
- }
- _ => {}
- }
- }
- PatKind::Slice { ref prefix, slice: None, ref suffix } => {
- let fixed_len = prefix.len() as u64 + suffix.len() as u64;
- max_fixed_len = cmp::max(max_fixed_len, fixed_len);
- }
- PatKind::Slice { ref prefix, slice: Some(_), ref suffix } => {
- max_prefix_len = cmp::max(max_prefix_len, prefix.len() as u64);
- max_suffix_len = cmp::max(max_suffix_len, suffix.len() as u64);
- }
- _ => {}
- }
- }
-
- cmp::max(max_fixed_len + 1, max_prefix_len + max_suffix_len)
-}
-
/// An inclusive interval, used for precise integer exhaustiveness checking.
/// `IntRange`s always store a contiguous range. This means that values are
/// encoded such that `0` encodes the minimum value for the integer,
// introducing uninhabited patterns for inaccessible fields. We
// need to figure out how to model that.
ty,
- max_slice_length: max_slice_length(cx, matrix.heads().chain(Some(v.head()))),
span,
};
debug!("is_useful_expand_first_col: pcx={:#?}, expanding {:#?}", pcx, v.head());
- if let Some(constructors) = pat_constructors(cx, v.head(), pcx) {
- debug!("is_useful - expanding constructors: {:#?}", constructors);
+ if let Some(constructor) = pat_constructor(cx, v.head(), pcx) {
+ debug!("is_useful - expanding constructor: {:#?}", constructor);
split_grouped_constructors(
cx.tcx,
cx.param_env,
- constructors,
+ pcx,
+ vec![constructor],
matrix,
- pcx.ty,
pcx.span,
Some(hir_id),
)
debug!("is_useful - expanding wildcard");
let used_ctors: Vec<Constructor<'_>> =
- matrix.heads().flat_map(|p| pat_constructors(cx, p, pcx).unwrap_or(vec![])).collect();
+ matrix.heads().filter_map(|p| pat_constructor(cx, p, pcx)).collect();
debug!("used_ctors = {:#?}", used_ctors);
// `all_ctors` are all the constructors for the given type, which
// should all be represented (or caught with the wild pattern `_`).
if missing_ctors.is_empty() && !is_non_exhaustive {
let (all_ctors, _) = missing_ctors.into_inner();
- split_grouped_constructors(
- cx.tcx,
- cx.param_env,
- all_ctors,
- matrix,
- pcx.ty,
- DUMMY_SP,
- None,
- )
- .into_iter()
- .map(|c| is_useful_specialized(cx, matrix, v, c, pcx.ty, witness_preference, hir_id))
- .find(|result| result.is_useful())
- .unwrap_or(NotUseful)
+ split_grouped_constructors(cx.tcx, cx.param_env, pcx, all_ctors, matrix, DUMMY_SP, None)
+ .into_iter()
+ .map(|c| {
+ is_useful_specialized(cx, matrix, v, c, pcx.ty, witness_preference, hir_id)
+ })
+ .find(|result| result.is_useful())
+ .unwrap_or(NotUseful)
} else {
let matrix = matrix.specialize_wildcard();
let v = v.to_tail();
) -> Usefulness<'tcx> {
debug!("is_useful_specialized({:#?}, {:#?}, {:?})", v, ctor, lty);
- let ctor_wild_subpatterns_owned: Vec<_> = ctor.wildcard_subpatterns(cx, lty).collect();
+ let ctor_wild_subpatterns_owned: Vec<_> = ctor.wildcard_subpatterns(cx, lty);
let ctor_wild_subpatterns: Vec<_> = ctor_wild_subpatterns_owned.iter().collect();
let matrix = matrix.specialize_constructor(cx, &ctor, &ctor_wild_subpatterns);
v.specialize_constructor(cx, &ctor, &ctor_wild_subpatterns)
.unwrap_or(NotUseful)
}
-/// Determines the constructors that the given pattern can be specialized to.
-///
-/// In most cases, there's only one constructor that a specific pattern
-/// represents, such as a specific enum variant or a specific literal value.
-/// Slice patterns, however, can match slices of different lengths. For instance,
-/// `[a, b, tail @ ..]` can match a slice of length 2, 3, 4 and so on.
-///
+/// Determines the constructor that the given pattern can be specialized to.
/// Returns `None` in case of a catch-all, which can't be specialized.
-fn pat_constructors<'tcx>(
+fn pat_constructor<'tcx>(
cx: &mut MatchCheckCtxt<'_, 'tcx>,
pat: &Pat<'tcx>,
pcx: PatCtxt<'tcx>,
-) -> Option<Vec<Constructor<'tcx>>> {
+) -> Option<Constructor<'tcx>> {
match *pat.kind {
- PatKind::AscribeUserType { ref subpattern, .. } => pat_constructors(cx, subpattern, pcx),
+ PatKind::AscribeUserType { ref subpattern, .. } => pat_constructor(cx, subpattern, pcx),
PatKind::Binding { .. } | PatKind::Wild => None,
- PatKind::Leaf { .. } | PatKind::Deref { .. } => Some(vec![Single]),
+ PatKind::Leaf { .. } | PatKind::Deref { .. } => Some(Single),
PatKind::Variant { adt_def, variant_index, .. } => {
- Some(vec![Variant(adt_def.variants[variant_index].def_id)])
+ Some(Variant(adt_def.variants[variant_index].def_id))
}
- PatKind::Constant { value } => Some(vec![ConstantValue(value, pat.span)]),
- PatKind::Range(PatRange { lo, hi, end }) => Some(vec![ConstantRange(
+ PatKind::Constant { value } => Some(ConstantValue(value, pat.span)),
+ PatKind::Range(PatRange { lo, hi, end }) => Some(ConstantRange(
lo.eval_bits(cx.tcx, cx.param_env, lo.ty),
hi.eval_bits(cx.tcx, cx.param_env, hi.ty),
lo.ty,
end,
pat.span,
- )]),
+ )),
PatKind::Array { .. } => match pcx.ty.kind {
- ty::Array(_, length) => Some(vec![Slice(length.eval_usize(cx.tcx, cx.param_env))]),
+ ty::Array(_, length) => Some(FixedLenSlice(length.eval_usize(cx.tcx, cx.param_env))),
_ => span_bug!(pat.span, "bad ty {:?} for array pattern", pcx.ty),
},
PatKind::Slice { ref prefix, ref slice, ref suffix } => {
- let pat_len = prefix.len() as u64 + suffix.len() as u64;
+ let prefix = prefix.len() as u64;
+ let suffix = suffix.len() as u64;
if slice.is_some() {
- Some((pat_len..pcx.max_slice_length + 1).map(Slice).collect())
+ Some(VarLenSlice(prefix, suffix))
} else {
- Some(vec![Slice(pat_len)])
+ Some(FixedLenSlice(prefix + suffix))
}
}
PatKind::Or { .. } => {
}
}
-/// This computes the types of the sub patterns that a constructor should be
-/// expanded to.
-///
-/// For instance, a tuple pattern (43u32, 'a') has sub pattern types [u32, char].
-fn constructor_sub_pattern_tys<'a, 'tcx>(
- cx: &MatchCheckCtxt<'a, 'tcx>,
- ctor: &Constructor<'tcx>,
- ty: Ty<'tcx>,
-) -> Vec<Ty<'tcx>> {
- debug!("constructor_sub_pattern_tys({:#?}, {:?})", ctor, ty);
- match ty.kind {
- ty::Tuple(ref fs) => fs.into_iter().map(|t| t.expect_ty()).collect(),
- ty::Slice(ty) | ty::Array(ty, _) => match *ctor {
- Slice(length) => (0..length).map(|_| ty).collect(),
- ConstantValue(..) => vec![],
- _ => bug!("bad slice pattern {:?} {:?}", ctor, ty),
- },
- ty::Ref(_, rty, _) => vec![rty],
- ty::Adt(adt, substs) => {
- if adt.is_box() {
- // Use T as the sub pattern type of Box<T>.
- vec![substs.type_at(0)]
- } else {
- let variant = &adt.variants[ctor.variant_index_for_adt(cx, adt)];
- let is_non_exhaustive = variant.is_field_list_non_exhaustive() && !cx.is_local(ty);
- variant
- .fields
- .iter()
- .map(|field| {
- let is_visible =
- adt.is_enum() || field.vis.is_accessible_from(cx.module, cx.tcx);
- let is_uninhabited = cx.is_uninhabited(field.ty(cx.tcx, substs));
- match (is_visible, is_non_exhaustive, is_uninhabited) {
- // Treat all uninhabited types in non-exhaustive variants as `TyErr`.
- (_, true, true) => cx.tcx.types.err,
- // Treat all non-visible fields as `TyErr`. They can't appear in any
- // other pattern from this match (because they are private), so their
- // type does not matter - but we don't want to know they are
- // uninhabited.
- (false, ..) => cx.tcx.types.err,
- (true, ..) => {
- let ty = field.ty(cx.tcx, substs);
- match ty.kind {
- // If the field type returned is an array of an unknown size
- // return an TyErr.
- ty::Array(_, len)
- if len.try_eval_usize(cx.tcx, cx.param_env).is_none() =>
- {
- cx.tcx.types.err
- }
- _ => ty,
- }
- }
- }
- })
- .collect()
- }
- }
- _ => vec![],
- }
-}
-
// checks whether a constant is equal to a user-written slice pattern. Only supports byte slices,
// meaning all other types will compare unequal and thus equal patterns often do not cause the
// second pattern to lint about unreachable match arms.
///
/// `hir_id` is `None` when we're evaluating the wildcard pattern, do not lint for overlapping in
/// ranges that case.
+///
+/// This also splits variable-length slices into fixed-length slices.
fn split_grouped_constructors<'p, 'tcx>(
tcx: TyCtxt<'tcx>,
param_env: ty::ParamEnv<'tcx>,
+ pcx: PatCtxt<'tcx>,
ctors: Vec<Constructor<'tcx>>,
matrix: &Matrix<'p, 'tcx>,
- ty: Ty<'tcx>,
span: Span,
hir_id: Option<HirId>,
) -> Vec<Constructor<'tcx>> {
+ let ty = pcx.ty;
let mut split_ctors = Vec::with_capacity(ctors.len());
for ctor in ctors.into_iter() {
match ctor {
- // For now, only ranges may denote groups of "subconstructors", so we only need to
- // special-case constant ranges.
ConstantRange(..) if should_treat_range_exhaustively(tcx, &ctor) => {
// We only care about finding all the subranges within the range of the constructor
// range. Anything else is irrelevant, because it is guaranteed to result in
split_ctors.push(IntRange::range_to_ctor(tcx, ty, range, span));
}
}
+ VarLenSlice(self_prefix, self_suffix) => {
+ // The exhaustiveness-checking paper does not include any details on
+ // checking variable-length slice patterns. However, they are matched
+ // by an infinite collection of fixed-length array patterns.
+ //
+ // Checking the infinite set directly would take an infinite amount
+ // of time. However, it turns out that for each finite set of
+ // patterns `P`, all sufficiently large array lengths are equivalent:
+ //
+ // Each slice `s` with a "sufficiently-large" length `l ≥ L` that applies
+ // to exactly the subset `Pₜ` of `P` can be transformed to a slice
+ // `sₘ` for each sufficiently-large length `m` that applies to exactly
+ // the same subset of `P`.
+ //
+ // Because of that, each witness for reachability-checking from one
+ // of the sufficiently-large lengths can be transformed to an
+ // equally-valid witness from any other length, so we only have
+ // to check slice lengths from the "minimal sufficiently-large length"
+ // and below.
+ //
+ // Note that the fact that there is a *single* `sₘ` for each `m`
+ // not depending on the specific pattern in `P` is important: if
+ // you look at the pair of patterns
+ // `[true, ..]`
+ // `[.., false]`
+ // Then any slice of length ≥1 that matches one of these two
+ // patterns can be trivially turned to a slice of any
+ // other length ≥1 that matches them and vice-versa - for
+ // but the slice from length 2 `[false, true]` that matches neither
+ // of these patterns can't be turned to a slice from length 1 that
+ // matches neither of these patterns, so we have to consider
+ // slices from length 2 there.
+ //
+ // Now, to see that that length exists and find it, observe that slice
+ // patterns are either "fixed-length" patterns (`[_, _, _]`) or
+ // "variable-length" patterns (`[_, .., _]`).
+ //
+ // For fixed-length patterns, all slices with lengths *longer* than
+ // the pattern's length have the same outcome (of not matching), so
+ // as long as `L` is greater than the pattern's length we can pick
+ // any `sₘ` from that length and get the same result.
+ //
+ // For variable-length patterns, the situation is more complicated,
+ // because as seen above the precise value of `sₘ` matters.
+ //
+ // However, for each variable-length pattern `p` with a prefix of length
+ // `plâ‚š` and suffix of length `slâ‚š`, only the first `plâ‚š` and the last
+ // `slâ‚š` elements are examined.
+ //
+ // Therefore, as long as `L` is positive (to avoid concerns about empty
+ // types), all elements after the maximum prefix length and before
+ // the maximum suffix length are not examined by any variable-length
+ // pattern, and therefore can be added/removed without affecting
+ // them - creating equivalent patterns from any sufficiently-large
+ // length.
+ //
+ // Of course, if fixed-length patterns exist, we must be sure
+ // that our length is large enough to miss them all, so
+ // we can pick `L = max(max(FIXED_LEN)+1, max(PREFIX_LEN) + max(SUFFIX_LEN))`
+ //
+ // for example, with the above pair of patterns, all elements
+ // but the first and last can be added/removed, so any
+ // witness of length ≥2 (say, `[false, false, true]`) can be
+ // turned to a witness from any other length ≥2.
+
+ let mut max_prefix_len = self_prefix;
+ let mut max_suffix_len = self_suffix;
+ let mut max_fixed_len = 0;
+
+ for row in matrix.heads() {
+ match *row.kind {
+ PatKind::Constant { value } => {
+ // extract the length of an array/slice from a constant
+ match (value.val, &value.ty.kind) {
+ (_, ty::Array(_, n)) => {
+ max_fixed_len =
+ cmp::max(max_fixed_len, n.eval_usize(tcx, param_env))
+ }
+ (ConstValue::Slice { start, end, .. }, ty::Slice(_)) => {
+ max_fixed_len = cmp::max(max_fixed_len, (end - start) as u64)
+ }
+ _ => {}
+ }
+ }
+ PatKind::Slice { ref prefix, slice: None, ref suffix } => {
+ let fixed_len = prefix.len() as u64 + suffix.len() as u64;
+ max_fixed_len = cmp::max(max_fixed_len, fixed_len);
+ }
+ PatKind::Slice { ref prefix, slice: Some(_), ref suffix } => {
+ max_prefix_len = cmp::max(max_prefix_len, prefix.len() as u64);
+ max_suffix_len = cmp::max(max_suffix_len, suffix.len() as u64);
+ }
+ _ => {}
+ }
+ }
+
+ // For diagnostics, we keep the prefix and suffix lengths separate, so in the case
+ // where `max_fixed_len + 1` is the largest, we adapt `max_prefix_len` accordingly,
+ // so that `L = max_prefix_len + max_suffix_len`.
+ if max_fixed_len + 1 >= max_prefix_len + max_suffix_len {
+ // The subtraction can't overflow thanks to the above check.
+ // The new `max_prefix_len` is also guaranteed to be larger than its previous
+ // value.
+ max_prefix_len = max_fixed_len + 1 - max_suffix_len;
+ }
+
+ // `ctor` originally covered the range `(self_prefix + self_suffix..infinity)`. We
+ // now split it into two: lengths smaller than `max_prefix_len + max_suffix_len`
+ // are treated independently as fixed-lengths slices, and lengths above are
+ // captured by a final VarLenSlice constructor.
+ split_ctors.extend(
+ (self_prefix + self_suffix..max_prefix_len + max_suffix_len).map(FixedLenSlice),
+ );
+ split_ctors.push(VarLenSlice(max_prefix_len, max_suffix_len));
+ }
// Any other constructor can be used unchanged.
_ => split_ctors.push(ctor),
}
PatKind::Array { ref prefix, ref slice, ref suffix }
| PatKind::Slice { ref prefix, ref slice, ref suffix } => match *constructor {
- Slice(..) => {
+ FixedLenSlice(..) | VarLenSlice(..) => {
let pat_len = prefix.len() + suffix.len();
if let Some(slice_count) = ctor_wild_subpatterns.len().checked_sub(pat_len) {
if slice_count == 0 || slice.is_some() {
use std::slice;
-use syntax_pos::{MultiSpan, Span, DUMMY_SP};
+use syntax_pos::{MultiSpan, Span};
crate fn check_match(tcx: TyCtxt<'_>, def_id: DefId) {
let body_id = match tcx.hir().as_local_hir_id(def_id) {
matrix: &Matrix<'_, 'tcx>,
hir_id: HirId,
) -> Result<(), Vec<super::Pat<'tcx>>> {
- let wild_pattern = super::Pat { ty, span: DUMMY_SP, kind: box PatKind::Wild };
+ let wild_pattern = super::Pat::wildcard_from_ty(ty);
match is_useful(cx, matrix, &PatStack::from_pattern(&wild_pattern), ConstructWitness, hir_id) {
NotUseful => Ok(()), // This is good, wildcard pattern isn't reachable.
UsefulWithWitness(pats) => Err(if pats.is_empty() {
use std::cmp::Ordering;
use std::fmt;
use syntax::ast;
-use syntax_pos::Span;
+use syntax_pos::{Span, DUMMY_SP};
#[derive(Clone, Debug)]
pub enum PatternError {
pub kind: Box<PatKind<'tcx>>,
}
+impl<'tcx> Pat<'tcx> {
+ pub(crate) fn wildcard_from_ty(ty: Ty<'tcx>) -> Self {
+ Pat { ty, span: DUMMY_SP, kind: Box::new(PatKind::Wild) }
+ }
+}
#[derive(Copy, Clone, Debug, PartialEq)]
pub struct PatTyProj<'tcx> {
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(),
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 {
}
```
+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:
```
"##,
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 {
"##,
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.
-
-```
-// Correct matching.
-struct Thing {
- x: u32,
- y: u32
-}
-
-let thing = Thing { x: 1, y: 2 };
+A struct pattern attempted to extract a non-existent field from a struct.
-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 {
}
```
-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 {
"##,
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 !";
_ => {}
}
```
+
+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){} }
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.
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;
"##,
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 {
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<T>(x: T); }
"##,
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
-#![feature(unboxed_closures)]
-
-extern "rust-call" { fn foo(x: u8, ...); }
+Erroneous code example:
-// or
+```compile_fail,E0045
+#![feature(unboxed_closures)]
-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" {
"##,
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 {
"##,
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 {
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<T: Default>(x: T) -> Self;
+}
+
+struct Bar;
+
+impl Foo for Bar {
+ fn foo<T: Default>(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 {
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 {
"##,
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;
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;
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;
pub since: String,
pub deprecation: Option<Deprecation>,
pub unstable_reason: Option<String>,
- pub issue: Option<u32>,
+ pub issue: Option<NonZeroU32>,
}
#[derive(Clone, Debug)]
_ => None,
},
issue: match self.level {
- attr::Unstable {issue, ..} => Some(issue),
+ attr::Unstable {issue, ..} => issue,
_ => None,
}
}
#[inline]
#[stable(feature = "rust1", since = "1.0.0")]
pub fn union<'a>(&'a self, other: &'a HashSet<T, S>) -> Union<'a, T, S> {
- if self.len() <= other.len() {
+ if self.len() >= other.len() {
Union {
iter: self.iter().chain(other.difference(self)),
}
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)]
// `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;
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};
#[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<Symbol>, issue: u32, is_soft: bool },
+ Unstable { reason: Option<Symbol>, issue: Option<NonZeroU32>, is_soft: bool },
Stable { since: Symbol },
}
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,
/// 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
use log::debug;
use std::env;
+use std::num::NonZeroU32;
#[derive(Copy, Clone, Debug)]
pub enum Stability {
PostExpansionVisitor { parse_sess, features }.visit_attribute(attr)
}
-fn find_lang_feature_issue(feature: Symbol) -> Option<u32> {
+fn find_lang_feature_issue(feature: Symbol) -> Option<NonZeroU32> {
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<u32>)
+ Library(Option<NonZeroU32>)
}
#[derive(Debug, Copy, Clone, PartialEq)]
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
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)]
state: State,
name: Symbol,
since: &'static str,
- issue: Option<u32>,
+ issue: Option<u32>, // FIXME: once #58732 is done make this an Option<NonZeroU32>
edition: Option<Edition>,
description: &'static str,
}
+impl Feature {
+ fn issue(&self) -> Option<NonZeroU32> {
+ self.issue.and_then(|i| NonZeroU32::new(i))
+ }
+}
+
pub use active::{Features, INCOMPLETE_FEATURES};
pub use builtin_attrs::{
AttributeGate, AttributeType, GatedCfg,
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)]
// `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 {
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};
// `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 {
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]`",
+ );
}
}
-error[E0005]: refutable pattern in function argument: `&[]`, `&[_]` and `&[_, _, _]` not covered
+error[E0005]: refutable pattern in function argument: `&[]`, `&[_]` and `&[_, _, _, ..]` not covered
--> $DIR/const_let_refutable.rs:3:16
|
LL | const fn slice([a, b]: &[i32]) -> i32 {
- | ^^^^^^ patterns `&[]`, `&[_]` and `&[_, _, _]` not covered
+ | ^^^^^^ patterns `&[]`, `&[_]` and `&[_, _, _, ..]` not covered
error[E0723]: can only call other `const fn` within a `const fn`, but `const <&i32 as std::ops::Add>::add` is not stable as `const fn`
--> $DIR/const_let_refutable.rs:4:5
--- /dev/null
+// 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() {}
--- /dev/null
+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
+
+++ /dev/null
-#![deny(unreachable_patterns)]
-
-fn main() {
- let s = &[0x00; 4][..]; //Slice of any value
- const MAGIC_TEST: &[u32] = &[4, 5, 6, 7]; //Const slice to pattern match with
- match s {
- MAGIC_TEST => (),
- [0x00, 0x00, 0x00, 0x00] => (),
- [4, 5, 6, 7] => (), // FIXME(oli-obk): this should warn, but currently does not
- _ => (),
- }
- match s {
- [0x00, 0x00, 0x00, 0x00] => (),
- MAGIC_TEST => (),
- [4, 5, 6, 7] => (), // FIXME(oli-obk): this should warn, but currently does not
- _ => (),
- }
- match s {
- [0x00, 0x00, 0x00, 0x00] => (),
- [4, 5, 6, 7] => (),
- MAGIC_TEST => (), // FIXME(oli-obk): this should warn, but currently does not
- _ => (),
- }
- const FOO: [u32; 1] = [4];
- match [99] {
- [0x00] => (),
- [4] => (),
- FOO => (), //~ ERROR unreachable pattern
- _ => (),
- }
-}
+++ /dev/null
-error: unreachable pattern
- --> $DIR/slice-pattern-const-2.rs:28:9
- |
-LL | FOO => (),
- | ^^^
- |
-note: lint level defined here
- --> $DIR/slice-pattern-const-2.rs:1:9
- |
-LL | #![deny(unreachable_patterns)]
- | ^^^^^^^^^^^^^^^^^^^^
-
-error: aborting due to previous error
-
+++ /dev/null
-#![deny(unreachable_patterns)]
-
-fn main() {
- let s = &["0x00"; 4][..]; //Slice of any value
- const MAGIC_TEST: &[&str] = &["4", "5", "6", "7"]; //Const slice to pattern match with
- match s {
- MAGIC_TEST => (),
- ["0x00", "0x00", "0x00", "0x00"] => (),
- ["4", "5", "6", "7"] => (), // FIXME(oli-obk): this should warn, but currently does not
- _ => (),
- }
- match s {
- ["0x00", "0x00", "0x00", "0x00"] => (),
- MAGIC_TEST => (),
- ["4", "5", "6", "7"] => (), // FIXME(oli-obk): this should warn, but currently does not
- _ => (),
- }
- match s {
- ["0x00", "0x00", "0x00", "0x00"] => (),
- ["4", "5", "6", "7"] => (),
- MAGIC_TEST => (), // FIXME(oli-obk): this should warn, but currently does not
- _ => (),
- }
- const FOO: [&str; 1] = ["boo"];
- match ["baa"] {
- ["0x00"] => (),
- ["boo"] => (),
- FOO => (), //~ ERROR unreachable pattern
- _ => (),
- }
-}
+++ /dev/null
-error: unreachable pattern
- --> $DIR/slice-pattern-const-3.rs:28:9
- |
-LL | FOO => (),
- | ^^^
- |
-note: lint level defined here
- --> $DIR/slice-pattern-const-3.rs:1:9
- |
-LL | #![deny(unreachable_patterns)]
- | ^^^^^^^^^^^^^^^^^^^^
-
-error: aborting due to previous error
-
+++ /dev/null
-#![deny(unreachable_patterns)]
-
-fn main() {
- let s = &[0x00; 4][..]; //Slice of any value
- const MAGIC_TEST: &[u8] = b"TEST"; //Const slice to pattern match with
- match s {
- MAGIC_TEST => (),
- [0x00, 0x00, 0x00, 0x00] => (),
- [84, 69, 83, 84] => (), //~ ERROR unreachable pattern
- _ => (),
- }
- match s {
- [0x00, 0x00, 0x00, 0x00] => (),
- MAGIC_TEST => (),
- [84, 69, 83, 84] => (), //~ ERROR unreachable pattern
- _ => (),
- }
- match s {
- [0x00, 0x00, 0x00, 0x00] => (),
- [84, 69, 83, 84] => (),
- MAGIC_TEST => (), //~ ERROR unreachable pattern
- _ => (),
- }
- const FOO: [u8; 1] = [4];
- match [99] {
- [0x00] => (),
- [4] => (),
- FOO => (), //~ ERROR unreachable pattern
- _ => (),
- }
- const BAR: &[u8; 1] = &[4];
- match &[99] {
- [0x00] => (),
- [4] => (),
- BAR => (), //~ ERROR unreachable pattern
- b"a" => (),
- _ => (),
- }
-
- const BOO: &[u8; 0] = &[];
- match &[] {
- [] => (),
- BOO => (), //~ ERROR unreachable pattern
- b"" => (), //~ ERROR unreachable pattern
- _ => (), //~ ERROR unreachable pattern
- }
-}
+++ /dev/null
-error: unreachable pattern
- --> $DIR/slice-pattern-const.rs:9:9
- |
-LL | [84, 69, 83, 84] => (),
- | ^^^^^^^^^^^^^^^^
- |
-note: lint level defined here
- --> $DIR/slice-pattern-const.rs:1:9
- |
-LL | #![deny(unreachable_patterns)]
- | ^^^^^^^^^^^^^^^^^^^^
-
-error: unreachable pattern
- --> $DIR/slice-pattern-const.rs:15:9
- |
-LL | [84, 69, 83, 84] => (),
- | ^^^^^^^^^^^^^^^^
-
-error: unreachable pattern
- --> $DIR/slice-pattern-const.rs:21:9
- |
-LL | MAGIC_TEST => (),
- | ^^^^^^^^^^
-
-error: unreachable pattern
- --> $DIR/slice-pattern-const.rs:28:9
- |
-LL | FOO => (),
- | ^^^
-
-error: unreachable pattern
- --> $DIR/slice-pattern-const.rs:35:9
- |
-LL | BAR => (),
- | ^^^
-
-error: unreachable pattern
- --> $DIR/slice-pattern-const.rs:43:9
- |
-LL | BOO => (),
- | ^^^
-
-error: unreachable pattern
- --> $DIR/slice-pattern-const.rs:44:9
- |
-LL | b"" => (),
- | ^^^
-
-error: unreachable pattern
- --> $DIR/slice-pattern-const.rs:45:9
- |
-LL | _ => (),
- | ^
-
-error: aborting due to 8 previous errors
-
|
= help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
-error[E0004]: non-exhaustive patterns: `&[]`, `&[_]`, `&[_, _]` and 3 more not covered
+error[E0004]: non-exhaustive patterns: `&[..]` not covered
--> $DIR/match-byte-array-patterns-2.rs:10:11
|
LL | match buf {
- | ^^^ patterns `&[]`, `&[_]`, `&[_, _]` and 3 more not covered
+ | ^^^ pattern `&[..]` not covered
|
= help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
fn check(list: &[Option<()>]) {
match list {
- //~^ ERROR `&[_, Some(_), None, _]` not covered
+ //~^ ERROR `&[_, Some(_), .., None, _]` not covered
&[] => {},
&[_] => {},
&[_, _] => {},
-error[E0004]: non-exhaustive patterns: `&[_, Some(_), None, _]` not covered
+error[E0004]: non-exhaustive patterns: `&[_, Some(_), .., None, _]` not covered
--> $DIR/match-slice-patterns.rs:4:11
|
LL | match list {
- | ^^^^ pattern `&[_, Some(_), None, _]` not covered
+ | ^^^^ pattern `&[_, Some(_), .., None, _]` not covered
|
= help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
}
let vec = vec![0.5f32];
let vec: &[f32] = &vec;
- match *vec { //~ ERROR non-exhaustive patterns: `[_, _, _, _]` not covered
+ match *vec { //~ ERROR non-exhaustive patterns: `[_, _, _, _, ..]` not covered
[0.1, 0.2, 0.3] => (),
[0.1, 0.2] => (),
[0.1] => (),
|
= help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
-error[E0004]: non-exhaustive patterns: `[_, _, _, _]` not covered
+error[E0004]: non-exhaustive patterns: `[_, _, _, _, ..]` not covered
--> $DIR/non-exhaustive-match.rs:47:11
|
LL | match *vec {
- | ^^^^ pattern `[_, _, _, _]` not covered
+ | ^^^^ pattern `[_, _, _, _, ..]` not covered
|
= help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
--- /dev/null
+#![deny(unreachable_patterns)]
+
+fn main() {
+ let s = &[0x00; 4][..]; //Slice of any value
+ const MAGIC_TEST: &[u32] = &[4, 5, 6, 7]; //Const slice to pattern match with
+ match s {
+ MAGIC_TEST => (),
+ [0x00, 0x00, 0x00, 0x00] => (),
+ [4, 5, 6, 7] => (), // FIXME(oli-obk): this should warn, but currently does not
+ _ => (),
+ }
+ match s {
+ [0x00, 0x00, 0x00, 0x00] => (),
+ MAGIC_TEST => (),
+ [4, 5, 6, 7] => (), // FIXME(oli-obk): this should warn, but currently does not
+ _ => (),
+ }
+ match s {
+ [0x00, 0x00, 0x00, 0x00] => (),
+ [4, 5, 6, 7] => (),
+ MAGIC_TEST => (), // FIXME(oli-obk): this should warn, but currently does not
+ _ => (),
+ }
+ const FOO: [u32; 1] = [4];
+ match [99] {
+ [0x00] => (),
+ [4] => (),
+ FOO => (), //~ ERROR unreachable pattern
+ _ => (),
+ }
+}
--- /dev/null
+error: unreachable pattern
+ --> $DIR/slice-pattern-const-2.rs:28:9
+ |
+LL | FOO => (),
+ | ^^^
+ |
+note: lint level defined here
+ --> $DIR/slice-pattern-const-2.rs:1:9
+ |
+LL | #![deny(unreachable_patterns)]
+ | ^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
--- /dev/null
+#![deny(unreachable_patterns)]
+
+fn main() {
+ let s = &["0x00"; 4][..]; //Slice of any value
+ const MAGIC_TEST: &[&str] = &["4", "5", "6", "7"]; //Const slice to pattern match with
+ match s {
+ MAGIC_TEST => (),
+ ["0x00", "0x00", "0x00", "0x00"] => (),
+ ["4", "5", "6", "7"] => (), // FIXME(oli-obk): this should warn, but currently does not
+ _ => (),
+ }
+ match s {
+ ["0x00", "0x00", "0x00", "0x00"] => (),
+ MAGIC_TEST => (),
+ ["4", "5", "6", "7"] => (), // FIXME(oli-obk): this should warn, but currently does not
+ _ => (),
+ }
+ match s {
+ ["0x00", "0x00", "0x00", "0x00"] => (),
+ ["4", "5", "6", "7"] => (),
+ MAGIC_TEST => (), // FIXME(oli-obk): this should warn, but currently does not
+ _ => (),
+ }
+ const FOO: [&str; 1] = ["boo"];
+ match ["baa"] {
+ ["0x00"] => (),
+ ["boo"] => (),
+ FOO => (), //~ ERROR unreachable pattern
+ _ => (),
+ }
+}
--- /dev/null
+error: unreachable pattern
+ --> $DIR/slice-pattern-const-3.rs:28:9
+ |
+LL | FOO => (),
+ | ^^^
+ |
+note: lint level defined here
+ --> $DIR/slice-pattern-const-3.rs:1:9
+ |
+LL | #![deny(unreachable_patterns)]
+ | ^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
--- /dev/null
+#![deny(unreachable_patterns)]
+
+fn main() {
+ let s = &[0x00; 4][..]; //Slice of any value
+ const MAGIC_TEST: &[u8] = b"TEST"; //Const slice to pattern match with
+ match s {
+ MAGIC_TEST => (),
+ [0x00, 0x00, 0x00, 0x00] => (),
+ [84, 69, 83, 84] => (), //~ ERROR unreachable pattern
+ _ => (),
+ }
+ match s {
+ [0x00, 0x00, 0x00, 0x00] => (),
+ MAGIC_TEST => (),
+ [84, 69, 83, 84] => (), //~ ERROR unreachable pattern
+ _ => (),
+ }
+ match s {
+ [0x00, 0x00, 0x00, 0x00] => (),
+ [84, 69, 83, 84] => (),
+ MAGIC_TEST => (), //~ ERROR unreachable pattern
+ _ => (),
+ }
+ const FOO: [u8; 1] = [4];
+ match [99] {
+ [0x00] => (),
+ [4] => (),
+ FOO => (), //~ ERROR unreachable pattern
+ _ => (),
+ }
+ const BAR: &[u8; 1] = &[4];
+ match &[99] {
+ [0x00] => (),
+ [4] => (),
+ BAR => (), //~ ERROR unreachable pattern
+ b"a" => (),
+ _ => (),
+ }
+
+ const BOO: &[u8; 0] = &[];
+ match &[] {
+ [] => (),
+ BOO => (), //~ ERROR unreachable pattern
+ b"" => (), //~ ERROR unreachable pattern
+ _ => (), //~ ERROR unreachable pattern
+ }
+}
--- /dev/null
+error: unreachable pattern
+ --> $DIR/slice-pattern-const.rs:9:9
+ |
+LL | [84, 69, 83, 84] => (),
+ | ^^^^^^^^^^^^^^^^
+ |
+note: lint level defined here
+ --> $DIR/slice-pattern-const.rs:1:9
+ |
+LL | #![deny(unreachable_patterns)]
+ | ^^^^^^^^^^^^^^^^^^^^
+
+error: unreachable pattern
+ --> $DIR/slice-pattern-const.rs:15:9
+ |
+LL | [84, 69, 83, 84] => (),
+ | ^^^^^^^^^^^^^^^^
+
+error: unreachable pattern
+ --> $DIR/slice-pattern-const.rs:21:9
+ |
+LL | MAGIC_TEST => (),
+ | ^^^^^^^^^^
+
+error: unreachable pattern
+ --> $DIR/slice-pattern-const.rs:28:9
+ |
+LL | FOO => (),
+ | ^^^
+
+error: unreachable pattern
+ --> $DIR/slice-pattern-const.rs:35:9
+ |
+LL | BAR => (),
+ | ^^^
+
+error: unreachable pattern
+ --> $DIR/slice-pattern-const.rs:43:9
+ |
+LL | BOO => (),
+ | ^^^
+
+error: unreachable pattern
+ --> $DIR/slice-pattern-const.rs:44:9
+ |
+LL | b"" => (),
+ | ^^^
+
+error: unreachable pattern
+ --> $DIR/slice-pattern-const.rs:45:9
+ |
+LL | _ => (),
+ | ^
+
+error: aborting due to 8 previous errors
+
--- /dev/null
+#![feature(slice_patterns)]
+
+fn main() {
+ let s: &[bool] = &[true; 0];
+ let s1: &[bool; 1] = &[false; 1];
+ let s2: &[bool; 2] = &[false; 2];
+ let s3: &[bool; 3] = &[false; 3];
+
+ match s1 {
+ [true, ..] => {}
+ [.., false] => {}
+ }
+ match s2 {
+ //~^ ERROR `&[false, true]` not covered
+ [true, ..] => {}
+ [.., false] => {}
+ }
+ match s3 {
+ //~^ ERROR `&[false, _, true]` not covered
+ [true, ..] => {}
+ [.., false] => {}
+ }
+ match s {
+ //~^ ERROR `&[false, .., true]` not covered
+ [] => {}
+ [true, ..] => {}
+ [.., false] => {}
+ }
+
+ match s3 {
+ //~^ ERROR `&[false, _, _]` not covered
+ [true, .., true] => {}
+ }
+ match s {
+ //~^ ERROR `&[_, ..]` not covered
+ [] => {}
+ }
+ match s {
+ //~^ ERROR `&[_, _, ..]` not covered
+ [] => {}
+ [_] => {}
+ }
+ match s {
+ //~^ ERROR `&[false, ..]` not covered
+ [] => {}
+ [true, ..] => {}
+ }
+ match s {
+ //~^ ERROR `&[false, _, ..]` not covered
+ [] => {}
+ [_] => {}
+ [true, ..] => {}
+ }
+ match s {
+ //~^ ERROR `&[_, .., false]` not covered
+ [] => {}
+ [_] => {}
+ [.., true] => {}
+ }
+
+ match s {
+ //~^ ERROR `&[_, _, .., true]` not covered
+ [] => {}
+ [_] => {}
+ [_, _] => {}
+ [.., false] => {}
+ }
+ match s {
+ //~^ ERROR `&[true, _, .., _]` not covered
+ [] => {}
+ [_] => {}
+ [_, _] => {}
+ [false, .., false] => {}
+ }
+}
--- /dev/null
+error[E0004]: non-exhaustive patterns: `&[false, true]` not covered
+ --> $DIR/slice-patterns-exhaustiveness.rs:13:11
+ |
+LL | match s2 {
+ | ^^ pattern `&[false, true]` not covered
+ |
+ = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+
+error[E0004]: non-exhaustive patterns: `&[false, _, true]` not covered
+ --> $DIR/slice-patterns-exhaustiveness.rs:18:11
+ |
+LL | match s3 {
+ | ^^ pattern `&[false, _, true]` not covered
+ |
+ = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+
+error[E0004]: non-exhaustive patterns: `&[false, .., true]` not covered
+ --> $DIR/slice-patterns-exhaustiveness.rs:23:11
+ |
+LL | match s {
+ | ^ pattern `&[false, .., true]` not covered
+ |
+ = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+
+error[E0004]: non-exhaustive patterns: `&[false, _, _]` not covered
+ --> $DIR/slice-patterns-exhaustiveness.rs:30:11
+ |
+LL | match s3 {
+ | ^^ pattern `&[false, _, _]` not covered
+ |
+ = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+
+error[E0004]: non-exhaustive patterns: `&[_, ..]` not covered
+ --> $DIR/slice-patterns-exhaustiveness.rs:34:11
+ |
+LL | match s {
+ | ^ pattern `&[_, ..]` not covered
+ |
+ = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+
+error[E0004]: non-exhaustive patterns: `&[_, _, ..]` not covered
+ --> $DIR/slice-patterns-exhaustiveness.rs:38:11
+ |
+LL | match s {
+ | ^ pattern `&[_, _, ..]` not covered
+ |
+ = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+
+error[E0004]: non-exhaustive patterns: `&[false, ..]` not covered
+ --> $DIR/slice-patterns-exhaustiveness.rs:43:11
+ |
+LL | match s {
+ | ^ pattern `&[false, ..]` not covered
+ |
+ = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+
+error[E0004]: non-exhaustive patterns: `&[false, _, ..]` not covered
+ --> $DIR/slice-patterns-exhaustiveness.rs:48:11
+ |
+LL | match s {
+ | ^ pattern `&[false, _, ..]` not covered
+ |
+ = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+
+error[E0004]: non-exhaustive patterns: `&[_, .., false]` not covered
+ --> $DIR/slice-patterns-exhaustiveness.rs:54:11
+ |
+LL | match s {
+ | ^ pattern `&[_, .., false]` not covered
+ |
+ = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+
+error[E0004]: non-exhaustive patterns: `&[_, _, .., true]` not covered
+ --> $DIR/slice-patterns-exhaustiveness.rs:61:11
+ |
+LL | match s {
+ | ^ pattern `&[_, _, .., true]` not covered
+ |
+ = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+
+error[E0004]: non-exhaustive patterns: `&[true, _, .., _]` not covered
+ --> $DIR/slice-patterns-exhaustiveness.rs:68:11
+ |
+LL | match s {
+ | ^ pattern `&[true, _, .., _]` not covered
+ |
+ = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+
+error: aborting due to 11 previous errors
+
+For more information about this error, try `rustc --explain E0004`.
--- /dev/null
+// check-pass
+#![feature(slice_patterns)]
+
+fn main() {
+ let s: &[bool] = &[true; 0];
+ let s0: &[bool; 0] = &[];
+ let s1: &[bool; 1] = &[false; 1];
+ let s2: &[bool; 2] = &[false; 2];
+
+ let [] = s0;
+ let [_] = s1;
+ let [_, _] = s2;
+
+ let [..] = s;
+ let [..] = s0;
+ let [..] = s1;
+ let [..] = s2;
+
+ let [_, ..] = s1;
+ let [.., _] = s1;
+ let [_, ..] = s2;
+ let [.., _] = s2;
+
+ let [_, _, ..] = s2;
+ let [_, .., _] = s2;
+ let [.., _, _] = s2;
+}
--- /dev/null
+#![feature(slice_patterns)]
+#![deny(unreachable_patterns)]
+
+fn main() {
+ let s: &[bool] = &[true; 0];
+
+ match s {
+ [true, ..] => {}
+ [true, ..] => {} //~ ERROR unreachable pattern
+ [true] => {} //~ ERROR unreachable pattern
+ [..] => {}
+ }
+ match s {
+ [.., true] => {}
+ [.., true] => {} //~ ERROR unreachable pattern
+ [true] => {} //~ ERROR unreachable pattern
+ [..] => {}
+ }
+ match s {
+ [false, .., true] => {}
+ [false, .., true] => {} //~ ERROR unreachable pattern
+ [false, true] => {} //~ ERROR unreachable pattern
+ [false] => {}
+ [..] => {}
+ }
+}
--- /dev/null
+error: unreachable pattern
+ --> $DIR/slice-patterns-reachability.rs:9:9
+ |
+LL | [true, ..] => {}
+ | ^^^^^^^^^^
+ |
+note: lint level defined here
+ --> $DIR/slice-patterns-reachability.rs:2:9
+ |
+LL | #![deny(unreachable_patterns)]
+ | ^^^^^^^^^^^^^^^^^^^^
+
+error: unreachable pattern
+ --> $DIR/slice-patterns-reachability.rs:10:9
+ |
+LL | [true] => {}
+ | ^^^^^^
+
+error: unreachable pattern
+ --> $DIR/slice-patterns-reachability.rs:15:9
+ |
+LL | [.., true] => {}
+ | ^^^^^^^^^^
+
+error: unreachable pattern
+ --> $DIR/slice-patterns-reachability.rs:16:9
+ |
+LL | [true] => {}
+ | ^^^^^^
+
+error: unreachable pattern
+ --> $DIR/slice-patterns-reachability.rs:21:9
+ |
+LL | [false, .., true] => {}
+ | ^^^^^^^^^^^^^^^^^
+
+error: unreachable pattern
+ --> $DIR/slice-patterns-reachability.rs:22:9
+ |
+LL | [false, true] => {}
+ | ^^^^^^^^^^^^^
+
+error: aborting due to 6 previous errors
+
-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 {}
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)]
-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 {
|
= help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
-error[E0004]: non-exhaustive patterns: `&[_]` not covered
+error[E0004]: non-exhaustive patterns: `&[_, ..]` not covered
--> $DIR/uninhabited-matches-feature-gated.rs:21:19
|
LL | let _ = match x {
- | ^ pattern `&[_]` not covered
+ | ^ pattern `&[_, ..]` not covered
|
= help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
-Subproject commit 3abdd2f1ced4cf3a44c7de88c5e39b3bb5037c4d
+Subproject commit 86b8643586aa39f36fb7a02e98c8d64d31415e70