Auto merge of #55347 - pietroalbini:rollup, r=pietroalbini

Rollup of 22 pull requests

Successful merges:

 - #53507 (Add doc for impl From for Waker)
 - #53931 (Gradually expanding libstd's keyword documentation)
 - #54965 (update tcp stream documentation)
 - #54977 (Accept `Option<Box<$t:ty>>` in macro argument)
 - #55138 (in which unused-parens suggestions heed what the user actually wrote)
 - #55173 (Suggest appropriate syntax on missing lifetime specifier in return type)
 - #55200 (Documents `From` implementations for `Stdio`)
 - #55245 (submodules: update clippy from 5afdf8b7 to b1d03437)
 - #55247 (Clarified code example in char primitive doc)
 - #55251 (Fix a typo in the documentation of RangeInclusive)
 - #55253 (only issue "variant of the expected type" suggestion for enums)
 - #55254 (Correct trailing ellipsis in name_from_pat)
 - #55269 (fix typos in various places)
 - #55282 (Remove redundant clone)
 - #55285 (Do some copy editing on the release notes)
 - #55291 (Update stdsimd submodule)
 - #55296 (Set RUST_BACKTRACE=0 for rustdoc-ui/failed-doctest-output.rs)
 - #55306 (Regression test for #54478.)
 - #55328 (Fix doc for new copysign functions)
 - #55340 (Operands no longer appear in places)
 - #55345 (Remove is_null)
 - #55348 (Update RELEASES.md after destabilization of non_modrs_mods)

Failed merges:

r? @ghost
This commit is contained in:
bors 2018-10-25 14:40:22 +00:00
commit 8ec22e7ec7
87 changed files with 1167 additions and 290 deletions

View File

@ -4,34 +4,31 @@ Version 1.30.0 (2018-10-25)
Language
--------
- [Procedural macros are now available.][52081] These kinds of macros allow for
more powerful code generation, there is a [new chapter available][proc-macros]
in Rust Programming Language book that goes further in depth.
more powerful code generation. There is a [new chapter available][proc-macros]
in the Rust Programming Language book that goes further in depth.
- [You can now use keywords as identifiers using the raw identifiers
syntax (`r#`).][53236] e.g. `let r#for = true;`
syntax (`r#`),][53236] e.g. `let r#for = true;`
- [Using anonymous parameters in traits is now deprecated with a warning and
will be a hard error in the 2018 edition.][53272]
- [You can now use `crate` in paths.][54404] This allows you to refer to the
crate root in the path. e.g. `use crate::foo;` refers to `foo` in `src/lib.rs`.
- [Using a external crate now no longer requires being prefixed with `::`.][54404]
e.g. previously using a external crate in a module without a use statement
required `let json = ::serde_json::from_str(foo);` can now be written
crate root in the path, e.g. `use crate::foo;` refers to `foo` in `src/lib.rs`.
- [Using a external crate no longer requires being prefixed with `::`.][54404]
Previously, using a external crate in a module without a use statement
required `let json = ::serde_json::from_str(foo);` but can now be written
as `let json = serde_json::from_str(foo);`.
- [You can now apply the `#[used]` attribute to static items to prevent the
compiler from optimising them away even if they appear to be unused.][51363]
compiler from optimising them away, even if they appear to be unused,][51363]
e.g. `#[used] static FOO: u32 = 1;`
- [You can now import and reexport macros from other crates with the `use`
syntax.][50911] Macros exported with `#[macro_export]` are now placed into
the root module of the crate. If your macro relies on calling other local
macros it is recommended to export with the
`#[macro_export(local_inner_macros)]` attribute so that users won't have to
import those macros.
- [`mod.rs` files are now optional.][54146] Previously if you had a `foo` module
with a `bar` submodule, you would have `src/foo/mod.rs` and `src/foo/bar.rs`.
Now you can have `src/foo.rs` and `src/foo/bar.rs` to achieve the same effect.
macros, it is recommended to export with the
`#[macro_export(local_inner_macros)]` attribute so users won't have to import
those macros.
- [You can now catch visibility keywords (e.g. `pub`, `pub(crate)`) in macros
using the `vis` specifier.][53370]
- [Non-macro attributes now allow all forms of literals not just
strings.][53044] e.g. Previously you would write `#[attr("true")]` you can now
- [Non-macro attributes now allow all forms of literals, not just
strings.][53044] Previously, you would write `#[attr("true")]`, and you can now
write `#[attr(true)]`.
- [You can now specify a function to handle a panic in the Rust runtime with the
`#[panic_handler]` attribute.][51366]
@ -54,9 +51,9 @@ Stabilized APIs
- [`Ipv6Addr::UNSPECIFIED`]
- [`Iterator::find_map`]
The following methods are a replacement methods for `trim_left`, `trim_right`,
`trim_left_matches`, and `trim_right_matches`. Which will be deprecated
in 1.33.0.
The following methods are replacement methods for `trim_left`, `trim_right`,
`trim_left_matches`, and `trim_right_matches`, which will be deprecated
in 1.33.0:
- [`str::trim_end_matches`]
- [`str::trim_end`]
- [`str::trim_start_matches`]
@ -76,12 +73,12 @@ Misc
----
- [`rustdoc` allows you to specify what edition to treat your code as with the
`--edition` option.][54057]
- [`rustdoc` now has the `--color` (Specify whether to output color) and
`--error-format` (Specify error format e.g. `json`) options.][53003]
- [`rustdoc` now has the `--color` (specify whether to output color) and
`--error-format` (specify error format, e.g. `json`) options.][53003]
- [We now distribute a `rust-gdbgui` script that invokes `gdbgui` with Rust
debug symbols.][53774]
- [Attributes from Rust tools such as `rustfmt` or `clippy` are now
available.][53459] e.g. `#[rustfmt::skip]` will skip formatting the next item.
available,][53459] e.g. `#[rustfmt::skip]` will skip formatting the next item.
[50911]: https://github.com/rust-lang/rust/pull/50911/
[51363]: https://github.com/rust-lang/rust/pull/51363/
@ -153,7 +150,7 @@ Compiler
Libraries
---------
- [`Once::call_once` now no longer requires `Once` to be `'static`.][52239]
- [`Once::call_once` no longer requires `Once` to be `'static`.][52239]
- [`BuildHasherDefault` now implements `PartialEq` and `Eq`.][52402]
- [`Box<CStr>`, `Box<OsStr>`, and `Box<Path>` now implement `Clone`.][51912]
- [Implemented `PartialEq<&str>` for `OsString` and `PartialEq<OsString>`
@ -169,10 +166,10 @@ Stabilized APIs
Cargo
-----
- [Cargo can silently fix some bad lockfiles ][cargo/5831] You can use
`--locked` to disable this behaviour.
- [Cargo can silently fix some bad lockfiles.][cargo/5831] You can use
`--locked` to disable this behavior.
- [`cargo-install` will now allow you to cross compile an install
using `--target`][cargo/5614]
using `--target`.][cargo/5614]
- [Added the `cargo-fix` subcommand to automatically move project code from
2015 edition to 2018.][cargo/5723]
- [`cargo doc` can now optionally document private types using the
@ -184,15 +181,15 @@ Misc
the specified level to that level.][52354] For example `--cap-lints warn`
will demote `deny` and `forbid` lints to `warn`.
- [`rustc` and `rustdoc` will now have the exit code of `1` if compilation
fails, and `101` if there is a panic.][52197]
fails and `101` if there is a panic.][52197]
- [A preview of clippy has been made available through rustup.][51122]
You can install the preview with `rustup component add clippy-preview`
You can install the preview with `rustup component add clippy-preview`.
Compatibility Notes
-------------------
- [`str::{slice_unchecked, slice_unchecked_mut}` are now deprecated.][51807]
Use `str::get_unchecked(begin..end)` instead.
- [`std::env::home_dir` is now deprecated for its unintuitive behaviour.][51656]
- [`std::env::home_dir` is now deprecated for its unintuitive behavior.][51656]
Consider using the `home_dir` function from
https://crates.io/crates/dirs instead.
- [`rustc` will no longer silently ignore invalid data in target spec.][52330]
@ -432,7 +429,7 @@ Language
be used as an identifier.
- [The dyn syntax is now available.][49968] This syntax is equivalent to the
bare `Trait` syntax, and should make it clearer when being used in tandem with
`impl Trait`. Since it is equivalent to the following syntax:
`impl Trait` because it is equivalent to the following syntax:
`&Trait == &dyn Trait`, `&mut Trait == &mut dyn Trait`, and
`Box<Trait> == Box<dyn Trait>`.
- [Attributes on generic parameters such as types and lifetimes are
@ -495,10 +492,10 @@ Cargo
a different directory than `target` for placing compilation artifacts.
- [Cargo will be adding automatic target inference for binaries, benchmarks,
examples, and tests in the Rust 2018 edition.][cargo/5335] If your project specifies
specific targets e.g. using `[[bin]]` and have other binaries in locations
specific targets, e.g. using `[[bin]]`, and have other binaries in locations
where cargo would infer a binary, Cargo will produce a warning. You can
disable this feature ahead of time by setting any of the following `autobins`,
`autobenches`, `autoexamples`, `autotests` to false.
disable this feature ahead of time by setting any of the following to false:
`autobins`, `autobenches`, `autoexamples`, `autotests`.
- [Cargo will now cache compiler information.][cargo/5359] This can be disabled by
setting `CARGO_CACHE_RUSTC_INFO=0` in your environment.
@ -514,8 +511,8 @@ Compatibility Notes
work.][49896] e.g. `::core::prelude::v1::StrExt::is_empty("")` will not
compile, `"".is_empty()` will still compile.
- [`Debug` output on `atomic::{AtomicBool, AtomicIsize, AtomicPtr, AtomicUsize}`
will only print the inner type.][48553] e.g.
`print!("{:?}", AtomicBool::new(true))` will print `true`
will only print the inner type.][48553] E.g.
`print!("{:?}", AtomicBool::new(true))` will print `true`,
not `AtomicBool(true)`.
- [The maximum number for `repr(align(N))` is now 2²⁹.][50378] Previously you
could enter higher numbers but they were not supported by LLVM. Up to 512MB
@ -578,7 +575,7 @@ Version 1.26.2 (2018-06-05)
Compatibility Notes
-------------------
- [The borrow checker was fixed to avoid unsoundness when using match ergonomics][51117]
- [The borrow checker was fixed to avoid unsoundness when using match ergonomics.][51117]
[51117]: https://github.com/rust-lang/rust/issues/51117
@ -589,18 +586,18 @@ Version 1.26.1 (2018-05-29)
Tools
-----
- [RLS now works on Windows][50646]
- [Rustfmt stopped badly formatting text in some cases][rustfmt/2695]
- [RLS now works on Windows.][50646]
- [Rustfmt stopped badly formatting text in some cases.][rustfmt/2695]
Compatibility Notes
--------
- [`fn main() -> impl Trait` no longer works for non-Termination
trait][50656]
trait.][50656]
This reverts an accidental stabilization.
- [`NaN > NaN` no longer returns true in const-fn contexts][50812]
- [Prohibit using turbofish for `impl Trait` in method arguments][50950]
- [`NaN > NaN` no longer returns true in const-fn contexts.][50812]
- [Prohibit using turbofish for `impl Trait` in method arguments.][50950]
[50646]: https://github.com/rust-lang/rust/issues/50646
[50656]: https://github.com/rust-lang/rust/pull/50656
@ -616,18 +613,18 @@ Language
- [Closures now implement `Copy` and/or `Clone` if all captured variables
implement either or both traits.][49299]
- [The inclusive range syntax e.g. `for x in 0..=10` is now stable.][47813]
- [The `'_` lifetime is now stable. The underscore lifetime can be used anywhere where a
- [The `'_` lifetime is now stable. The underscore lifetime can be used anywhere a
lifetime can be elided.][49458]
- [`impl Trait` is now stable allowing you to have abstract types in returns
or in function parameters.][49255] e.g. `fn foo() -> impl Iterator<Item=u8>` or
or in function parameters.][49255] E.g. `fn foo() -> impl Iterator<Item=u8>` or
`fn open(path: impl AsRef<Path>)`.
- [Pattern matching will now automatically apply dereferences.][49394]
- [128-bit integers in the form of `u128` and `i128` are now stable.][49101]
- [`main` can now return `Result<(), E: Debug>`][49162] in addition to `()`.
- [A lot of operations are now available in a const context.][46882] E.g. You
can now index into constant arrays, reference and dereference into constants,
and use Tuple struct constructors.
- [Fixed entry slice patterns are now stable.][48516] e.g.
and use tuple struct constructors.
- [Fixed entry slice patterns are now stable.][48516] E.g.
```rust
let points = [1, 2, 3, 4];
match points {
@ -1052,7 +1049,7 @@ Language
Compiler
--------
- [Enabled `TrapUnreachable` in LLVM which should mitigate the impact of
undefined behaviour.][45920]
undefined behavior.][45920]
- [rustc now suggests renaming import if names clash.][45660]
- [Display errors/warnings correctly when there are zero-width or
wide characters.][45711]

View File

@ -349,6 +349,7 @@ dependencies = [
"itertools 0.7.8 (registry+https://github.com/rust-lang/crates.io-index)",
"lazy_static 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
"regex 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
"walkdir 2.2.5 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]

View File

@ -594,7 +594,7 @@ class RustBuild(object):
return ''
def bootstrap_binary(self):
"""Return the path of the boostrap binary
"""Return the path of the bootstrap binary
>>> rb = RustBuild()
>>> rb.build_dir = "build"

View File

@ -277,7 +277,7 @@ def print_std_string_val(val, internal_dict):
#=--------------------------------------------------------------------------------------------------
def print_array_of_values(array_name, data_ptr_val, length, internal_dict):
"""Prints a contigous memory range, interpreting it as values of the
"""Prints a contiguous memory range, interpreting it as values of the
pointee-type of data_ptr_val."""
data_ptr_type = data_ptr_val.type

View File

@ -77,7 +77,7 @@ use self::Entry::*;
/// movie_reviews.insert("Office Space", "Deals with real issues in the workplace.");
/// movie_reviews.insert("Pulp Fiction", "Masterpiece.");
/// movie_reviews.insert("The Godfather", "Very enjoyable.");
/// movie_reviews.insert("The Blues Brothers", "Eye lyked it alot.");
/// movie_reviews.insert("The Blues Brothers", "Eye lyked it a lot.");
///
/// // check for a specific one.
/// if !movie_reviews.contains_key("Les Misérables") {

View File

@ -518,7 +518,7 @@ pub unsafe trait GlobalAlloc {
/// The block is described by the given `ptr` pointer and `layout`.
///
/// If this returns a non-null pointer, then ownership of the memory block
/// referenced by `ptr` has been transferred to this alloctor.
/// referenced by `ptr` has been transferred to this allocator.
/// The memory may or may not have been deallocated,
/// and should be considered unusable (unless of course it was
/// transferred back to the caller again via the return value of

View File

@ -1025,7 +1025,7 @@ extern "rust-intrinsic" {
/// // to avoid problems in case something further down panics.
/// src.set_len(0);
///
/// // The two regions cannot overlap becuase mutable references do
/// // The two regions cannot overlap because mutable references do
/// // not alias, and two different vectors cannot own the same
/// // memory.
/// ptr::copy_nonoverlapping(src_ptr, dst_ptr, src_len);

View File

@ -304,7 +304,7 @@ impl<Idx: PartialOrd<Idx>> RangeTo<Idx> {
}
}
/// An range bounded inclusively below and above (`start..=end`).
/// A range bounded inclusively below and above (`start..=end`).
///
/// The `RangeInclusive` `start..=end` contains all values with `x >= start`
/// and `x <= end`. It is empty unless `start <= end`.

View File

@ -102,7 +102,7 @@ pub use marker::Unpin;
/// value in place, preventing the value referenced by that pointer from being moved
/// unless it implements [`Unpin`].
///
/// See the [`pin` module] documentation for furthur explanation on pinning.
/// See the [`pin` module] documentation for further explanation on pinning.
///
/// [`Unpin`]: ../../std/marker/trait.Unpin.html
/// [`pin` module]: ../../std/pin/index.html

View File

@ -38,7 +38,7 @@
//! underlying object is live and no reference (just raw pointers) is used to
//! access the same memory.
//!
//! These axioms, along with careful use of [`offset`] for pointer arithmentic,
//! These axioms, along with careful use of [`offset`] for pointer arithmetic,
//! are enough to correctly implement many useful things in unsafe code. Stronger guarantees
//! will be provided eventually, as the [aliasing] rules are being determined. For more
//! information, see the [book] as well as the section in the reference devoted

View File

@ -188,6 +188,11 @@ impl LocalWaker {
}
impl From<LocalWaker> for Waker {
/// Converts a `LocalWaker` into a `Waker`.
///
/// This conversion turns a `!Sync` `LocalWaker` into a `Sync` `Waker`, allowing a wakeup
/// object to be sent to another thread, but giving up its ability to do specialized
/// thread-local wakeup behavior.
#[inline]
fn from(local_waker: LocalWaker) -> Self {
local_waker.0

View File

@ -40,7 +40,7 @@ impl ::std::fmt::Debug for CrateNum {
match self {
CrateNum::Index(id) => write!(fmt, "crate{}", id.private),
CrateNum::Invalid => write!(fmt, "invalid crate"),
CrateNum::BuiltinMacros => write!(fmt, "bultin macros crate"),
CrateNum::BuiltinMacros => write!(fmt, "builtin macros crate"),
CrateNum::ReservedForIncrCompCache => write!(fmt, "crate for decoding incr comp cache"),
}
}
@ -101,7 +101,7 @@ impl fmt::Display for CrateNum {
match self {
CrateNum::Index(id) => fmt::Display::fmt(&id.private, f),
CrateNum::Invalid => write!(f, "invalid crate"),
CrateNum::BuiltinMacros => write!(f, "bultin macros crate"),
CrateNum::BuiltinMacros => write!(f, "builtin macros crate"),
CrateNum::ReservedForIncrCompCache => write!(f, "crate for decoding incr comp cache"),
}
}

View File

@ -1147,7 +1147,7 @@ impl<'a> LoweringContext<'a> {
TyKind::Slice(ref ty) => hir::TyKind::Slice(self.lower_ty(ty, itctx)),
TyKind::Ptr(ref mt) => hir::TyKind::Ptr(self.lower_mt(mt, itctx)),
TyKind::Rptr(ref region, ref mt) => {
let span = t.span.shrink_to_lo();
let span = self.sess.source_map().next_point(t.span.shrink_to_lo());
let lifetime = match *region {
Some(ref lt) => self.lower_lifetime(lt),
None => self.elided_ref_lifetime(span),

View File

@ -180,7 +180,7 @@ impl<'a> State<'a> {
State {
s: pp::mk_printer(out, default_columns),
cm: Some(cm),
comments: comments.clone(),
comments,
literals: literals.unwrap_or_default().into_iter().peekable(),
cur_cmnt: 0,
boxes: Vec::new(),

View File

@ -44,7 +44,7 @@ impl<'cm> CachingSourceMapView<'cm> {
CachingSourceMapView {
source_map,
line_cache: [entry.clone(), entry.clone(), entry.clone()],
line_cache: [entry.clone(), entry.clone(), entry],
time_stamp: 0,
}
}

View File

@ -2235,21 +2235,46 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
};
let mut err = report_missing_lifetime_specifiers(self.tcx.sess, span, lifetime_refs.len());
let mut add_label = true;
if let Some(params) = error {
if lifetime_refs.len() == 1 {
self.report_elision_failure(&mut err, params);
add_label = add_label && self.report_elision_failure(&mut err, params, span);
}
}
if add_label {
add_missing_lifetime_specifiers_label(&mut err, span, lifetime_refs.len());
}
err.emit();
}
fn suggest_lifetime(&self, db: &mut DiagnosticBuilder<'_>, span: Span, msg: &str) -> bool {
match self.tcx.sess.source_map().span_to_snippet(span) {
Ok(ref snippet) => {
let (sugg, applicability) = if snippet == "&" {
("&'static ".to_owned(), Applicability::MachineApplicable)
} else if snippet == "'_" {
("'static".to_owned(), Applicability::MachineApplicable)
} else {
(format!("{} + 'static", snippet), Applicability::MaybeIncorrect)
};
db.span_suggestion_with_applicability(span, msg, sugg, applicability);
false
}
Err(_) => {
db.help(msg);
true
}
}
}
fn report_elision_failure(
&mut self,
db: &mut DiagnosticBuilder<'_>,
params: &[ElisionFailureInfo],
) {
span: Span,
) -> bool {
let mut m = String::new();
let len = params.len();
@ -2304,7 +2329,7 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
"this function's return type contains a borrowed value, but \
there is no value for it to be borrowed from"
);
help!(db, "consider giving it a 'static lifetime");
self.suggest_lifetime(db, span, "consider giving it a 'static lifetime")
} else if elided_len == 0 {
help!(
db,
@ -2312,11 +2337,8 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
an elided lifetime, but the lifetime cannot be derived from \
the arguments"
);
help!(
db,
"consider giving it an explicit bounded or 'static \
lifetime"
);
let msg = "consider giving it an explicit bounded or 'static lifetime";
self.suggest_lifetime(db, span, msg)
} else if elided_len == 1 {
help!(
db,
@ -2324,6 +2346,7 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
the signature does not say which {} it is borrowed from",
m
);
true
} else {
help!(
db,
@ -2331,6 +2354,7 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
the signature does not say whether it is borrowed from {}",
m
);
true
}
}
@ -2744,26 +2768,28 @@ fn insert_late_bound_lifetimes(
}
}
pub fn report_missing_lifetime_specifiers(
fn report_missing_lifetime_specifiers(
sess: &Session,
span: Span,
count: usize,
) -> DiagnosticBuilder<'_> {
let mut err = struct_span_err!(
struct_span_err!(
sess,
span,
E0106,
"missing lifetime specifier{}",
if count > 1 { "s" } else { "" }
);
let msg: Cow<'static, str> = if count > 1 {
format!("expected {} lifetime parameters", count).into()
} else {
"expected lifetime parameter".into()
};
err.span_label(span, msg);
err
)
}
fn add_missing_lifetime_specifiers_label(
err: &mut DiagnosticBuilder<'_>,
span: Span,
count: usize,
) {
if count > 1 {
err.span_label(span, format!("expected {} lifetime parameters", count));
} else {
err.span_label(span, "expected lifetime parameter");
};
}

View File

@ -632,7 +632,7 @@ pub fn read_target_uint(endianness: layout::Endian, mut source: &[u8]) -> Result
}
////////////////////////////////////////////////////////////////////////////////
// Methods to faciliate working with signed integers stored in a u128
// Methods to facilitate working with signed integers stored in a u128
////////////////////////////////////////////////////////////////////////////////
pub fn sign_extend(value: u128, size: Size) -> u128 {

View File

@ -181,7 +181,7 @@ impl<'tcx, Tag> Scalar<Tag> {
#[inline]
pub fn is_null_ptr(self, cx: impl HasDataLayout) -> bool {
match self {
Scalar::Bits { bits, size } => {
Scalar::Bits { bits, size } => {
assert_eq!(size as u64, cx.data_layout().pointer_size.bytes());
bits == 0
},
@ -189,14 +189,6 @@ impl<'tcx, Tag> Scalar<Tag> {
}
}
#[inline]
pub fn is_null(self) -> bool {
match self {
Scalar::Bits { bits, .. } => bits == 0,
Scalar::Ptr(_) => false
}
}
#[inline]
pub fn from_bool(b: bool) -> Self {
Scalar::Bits { bits: b as u128, size: 1 }

View File

@ -469,7 +469,7 @@ pub enum BorrowKind {
/// }
///
/// This can't be a shared borrow because mutably borrowing (*x as Some).0
/// should not prevent `if let None = x { ... }`, for example, becase the
/// should not prevent `if let None = x { ... }`, for example, because the
/// mutating `(*x as Some).0` can't affect the discriminant of `x`.
/// We can also report errors with this kind of borrow differently.
Shallow,
@ -2065,9 +2065,8 @@ pub struct SourceScopeLocalData {
///////////////////////////////////////////////////////////////////////////
// Operands
/// These are values that can appear inside an rvalue (or an index
/// place). They are intentionally limited to prevent rvalues from
/// being nested in one another.
/// These are values that can appear inside an rvalue. They are intentionally
/// limited to prevent rvalues from being nested in one another.
#[derive(Clone, PartialEq, RustcEncodable, RustcDecodable)]
pub enum Operand<'tcx> {
/// Copy: The value must be available for use afterwards.

View File

@ -412,7 +412,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
flags.push(("crate_local".to_owned(), None));
}
// Allow targetting all integers using `{integral}`, even if the exact type was resolved
// Allow targeting all integers using `{integral}`, even if the exact type was resolved
if self_ty.is_integral() {
flags.push(("_Self".to_owned(), Some("{integral}".to_owned())));
}

View File

@ -340,7 +340,7 @@ impl<'a, 'b, 'gcx, 'tcx> AssociatedTypeNormalizer<'a, 'b, 'gcx, 'tcx> {
let value = self.selcx.infcx().resolve_type_vars_if_possible(value);
if !value.has_projections() {
value.clone()
value
} else {
value.fold_with(self)
}

View File

@ -967,7 +967,7 @@ impl<'tcx> PolyFnSig<'tcx> {
self.map_bound_ref(|fn_sig| fn_sig.inputs_and_output)
}
pub fn output(&self) -> ty::Binder<Ty<'tcx>> {
self.map_bound_ref(|fn_sig| fn_sig.output().clone())
self.map_bound_ref(|fn_sig| fn_sig.output())
}
pub fn variadic(&self) -> bool {
self.skip_binder().variadic

View File

@ -761,7 +761,7 @@ impl Builder<'a, 'll, 'tcx> {
fty, asm, cons, volatile, alignstack, dia);
Some(self.call(v, inputs, None))
} else {
// LLVM has detected an issue with our constaints, bail out
// LLVM has detected an issue with our constraints, bail out
None
}
}

View File

@ -284,8 +284,13 @@ impl UnusedParens {
parser::contains_exterior_struct_lit(&inner)
};
if !necessary {
let pattern = pprust::expr_to_string(value);
Self::remove_outer_parens(cx, value.span, &pattern, msg);
let expr_text = if let Ok(snippet) = cx.sess().source_map()
.span_to_snippet(value.span) {
snippet
} else {
pprust::expr_to_string(value)
};
Self::remove_outer_parens(cx, value.span, &expr_text, msg);
}
}
}
@ -295,8 +300,13 @@ impl UnusedParens {
value: &ast::Pat,
msg: &str) {
if let ast::PatKind::Paren(_) = value.node {
let pattern = pprust::pat_to_string(value);
Self::remove_outer_parens(cx, value.span, &pattern, msg);
let pattern_text = if let Ok(snippet) = cx.sess().source_map()
.span_to_snippet(value.span) {
snippet
} else {
pprust::pat_to_string(value)
};
Self::remove_outer_parens(cx, value.span, &pattern_text, msg);
}
}

View File

@ -68,7 +68,7 @@ macro_rules! provide {
let $cdata = $tcx.crate_data_as_rc_any($def_id.krate);
let $cdata = $cdata.downcast_ref::<cstore::CrateMetadata>()
.expect("CrateStore crated ata is not a CrateMetadata");
.expect("CrateStore created data is not a CrateMetadata");
$compute
})*

View File

@ -129,7 +129,7 @@ pub fn op_to_const<'tcx>(
assert!(alloc.bytes.len() as u64 - ptr.offset.bytes() >= op.layout.size.bytes());
let mut alloc = alloc.clone();
alloc.align = align;
// FIXME shouldnt it be the case that `mark_static_initialized` has already
// FIXME shouldn't it be the case that `mark_static_initialized` has already
// interned this? I thought that is the entire point of that `FinishStatic` stuff?
let alloc = ecx.tcx.intern_const_alloc(alloc);
ConstValue::ByRef(ptr.alloc_id, alloc, ptr.offset)

View File

@ -2279,7 +2279,7 @@ fn demo<'a>(s: &'a mut S<'a>) -> &'a mut String { let p = &mut *(*s).data; p }
Note that this approach needs a reference to S with lifetime `'a`.
Nothing shorter than `'a` will suffice: a shorter lifetime would imply
that after `demo` finishes excuting, something else (such as the
that after `demo` finishes executing, something else (such as the
destructor!) could access `s.data` after the end of that shorter
lifetime, which would again violate the `&mut`-borrow's exclusive
access.

View File

@ -1048,7 +1048,7 @@ pub fn is_useful<'p, 'a: 'p, 'tcx: 'a>(cx: &mut MatchCheckCtxt<'a, 'tcx>,
if let Some(constructors) = pat_constructors(cx, v[0], pcx) {
debug!("is_useful - expanding constructors: {:#?}", constructors);
split_grouped_constructors(cx.tcx, constructors, matrix, pcx.ty).into_iter().map(|c|
is_useful_specialized(cx, matrix, v, c.clone(), pcx.ty, witness)
is_useful_specialized(cx, matrix, v, c, pcx.ty, witness)
).find(|result| result.is_useful()).unwrap_or(NotUseful)
} else {
debug!("is_useful - expanding wildcard");
@ -1096,7 +1096,7 @@ pub fn is_useful<'p, 'a: 'p, 'tcx: 'a>(cx: &mut MatchCheckCtxt<'a, 'tcx>,
if missing_ctors.is_empty() && !is_non_exhaustive {
split_grouped_constructors(cx.tcx, all_ctors, matrix, pcx.ty).into_iter().map(|c| {
is_useful_specialized(cx, matrix, v, c.clone(), pcx.ty, witness)
is_useful_specialized(cx, matrix, v, c, pcx.ty, witness)
}).find(|result| result.is_useful()).unwrap_or(NotUseful)
} else {
let matrix = rows.iter().filter_map(|r| {

View File

@ -556,7 +556,7 @@ impl<'a, 'mir, 'tcx: 'mir, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tc
)?;
}
} else {
// Uh, that shouln't happen... the function did not intend to return
// Uh, that shouldn't happen... the function did not intend to return
return err!(Unreachable);
}

View File

@ -94,7 +94,7 @@ impl<'a, 'b, 'c, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> HasDataLayout
}
}
// FIXME: Really we shouldnt clone memory, ever. Snapshot machinery should instad
// FIXME: Really we shouldn't clone memory, ever. Snapshot machinery should instead
// carefully copy only the reachable parts.
impl<'a, 'mir, 'tcx: 'a + 'mir, M: Machine<'a, 'mir, 'tcx>>
Clone for Memory<'a, 'mir, 'tcx, M>
@ -658,7 +658,7 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> Memory<'a, 'mir, 'tcx, M> {
}
/// It is the caller's responsibility to handle undefined and pointer bytes.
/// However, this still checks that there are no relocations on the *egdes*.
/// However, this still checks that there are no relocations on the *edges*.
#[inline]
fn get_bytes_with_undef_and_ptr(
&self,
@ -1098,7 +1098,7 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> Memory<'a, 'mir, 'tcx, M> {
Ok(())
}
/// Error if there are relocations overlapping with the egdes of the
/// Error if there are relocations overlapping with the edges of the
/// given memory range.
#[inline]
fn check_relocation_edges(&self, ptr: Pointer<M::PointerTag>, size: Size) -> EvalResult<'tcx> {

View File

@ -357,14 +357,14 @@ fn from_known_layout<'tcx>(
}
impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M> {
/// Try reading a value in memory; this is interesting particularily for ScalarPair.
/// Try reading a value in memory; this is interesting particularly for ScalarPair.
/// Return None if the layout does not permit loading this as a value.
pub(super) fn try_read_value_from_mplace(
&self,
mplace: MPlaceTy<'tcx, M::PointerTag>,
) -> EvalResult<'tcx, Option<Value<M::PointerTag>>> {
if mplace.layout.is_unsized() {
// Dont touch unsized
// Don't touch unsized
return Ok(None);
}
let (ptr, ptr_align) = mplace.to_scalar_ptr_align();

View File

@ -230,7 +230,7 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M>
),
}
}
// non-ZST also have to be dereferencable
// non-ZST also have to be dereferenceable
if size != Size::ZERO {
let ptr = try_validation!(place.ptr.to_ptr(),
"integer pointer in non-ZST reference", path);
@ -272,7 +272,7 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M>
// FIXME: Check if the signature matches
}
// This should be all the primitive types
ty::Never => bug!("Uninhabited type should have been catched earlier"),
ty::Never => bug!("Uninhabited type should have been caught earlier"),
_ => bug!("Unexpected primitive type {}", value.layout.ty)
}
Ok(())

View File

@ -166,12 +166,12 @@ impl<'a> AstValidator<'a> {
}
}
/// With eRFC 2497, we need to check whether an expression is ambigious and warn or error
/// With eRFC 2497, we need to check whether an expression is ambiguous and warn or error
/// depending on the edition, this function handles that.
fn while_if_let_ambiguity(&self, expr: &P<Expr>) {
if let Some((span, op_kind)) = self.while_if_let_expr_ambiguity(&expr) {
let mut err = self.err_handler().struct_span_err(
span, &format!("ambigious use of `{}`", op_kind.to_string())
span, &format!("ambiguous use of `{}`", op_kind.to_string())
);
err.note(
@ -193,9 +193,9 @@ impl<'a> AstValidator<'a> {
}
/// With eRFC 2497 adding if-let chains, there is a requirement that the parsing of
/// `&&` and `||` in a if-let statement be unambigious. This function returns a span and
/// a `BinOpKind` (either `&&` or `||` depending on what was ambigious) if it is determined
/// that the current expression parsed is ambigious and will break in future.
/// `&&` and `||` in a if-let statement be unambiguous. This function returns a span and
/// a `BinOpKind` (either `&&` or `||` depending on what was ambiguous) if it is determined
/// that the current expression parsed is ambiguous and will break in future.
fn while_if_let_expr_ambiguity(&self, expr: &P<Expr>) -> Option<(Span, BinOpKind)> {
debug!("while_if_let_expr_ambiguity: expr.node: {:?}", expr.node);
match &expr.node {
@ -203,12 +203,12 @@ impl<'a> AstValidator<'a> {
Some((expr.span, op.node))
},
ExprKind::Range(ref lhs, ref rhs, _) => {
let lhs_ambigious = lhs.as_ref()
let lhs_ambiguous = lhs.as_ref()
.and_then(|lhs| self.while_if_let_expr_ambiguity(lhs));
let rhs_ambigious = rhs.as_ref()
let rhs_ambiguous = rhs.as_ref()
.and_then(|rhs| self.while_if_let_expr_ambiguity(rhs));
lhs_ambigious.or(rhs_ambigious)
lhs_ambiguous.or(rhs_ambiguous)
}
_ => None,
}

View File

@ -430,7 +430,7 @@ impl Align {
}
/// Lower the alignment, if necessary, such that the given offset
/// is aligned to it (the offset is a multiple of the aligment).
/// is aligned to it (the offset is a multiple of the alignment).
pub fn restrict_for_offset(self, offset: Size) -> Align {
self.min(Align::max_for_offset(offset))
}

View File

@ -111,34 +111,35 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
let expr_ty = self.resolve_type_vars_with_obligations(checked_ty);
let mut err = self.report_mismatched_types(&cause, expected, expr_ty, e);
// If the expected type is an enum with any variants whose sole
// field is of the found type, suggest such variants. See Issue
// #42764.
// If the expected type is an enum (Issue #55250) with any variants whose
// sole field is of the found type, suggest such variants. (Issue #42764)
if let ty::Adt(expected_adt, substs) = expected.sty {
let mut compatible_variants = expected_adt.variants
.iter()
.filter(|variant| variant.fields.len() == 1)
.filter_map(|variant| {
let sole_field = &variant.fields[0];
let sole_field_ty = sole_field.ty(self.tcx, substs);
if self.can_coerce(expr_ty, sole_field_ty) {
let variant_path = self.tcx.item_path_str(variant.did);
Some(variant_path.trim_left_matches("std::prelude::v1::").to_string())
} else {
None
}
}).peekable();
if expected_adt.is_enum() {
let mut compatible_variants = expected_adt.variants
.iter()
.filter(|variant| variant.fields.len() == 1)
.filter_map(|variant| {
let sole_field = &variant.fields[0];
let sole_field_ty = sole_field.ty(self.tcx, substs);
if self.can_coerce(expr_ty, sole_field_ty) {
let variant_path = self.tcx.item_path_str(variant.did);
Some(variant_path.trim_left_matches("std::prelude::v1::").to_string())
} else {
None
}
}).peekable();
if compatible_variants.peek().is_some() {
let expr_text = print::to_string(print::NO_ANN, |s| s.print_expr(expr));
let suggestions = compatible_variants.map(|v|
format!("{}({})", v, expr_text)).collect::<Vec<_>>();
err.span_suggestions_with_applicability(
expr.span,
"try using a variant of the expected type",
suggestions,
Applicability::MaybeIncorrect,
);
if compatible_variants.peek().is_some() {
let expr_text = print::to_string(print::NO_ANN, |s| s.print_expr(expr));
let suggestions = compatible_variants
.map(|v| format!("{}({})", v, expr_text)).collect::<Vec<_>>();
err.span_suggestions_with_applicability(
expr.span,
"try using a variant of the expected type",
suggestions,
Applicability::MaybeIncorrect,
);
}
}
}

View File

@ -5198,7 +5198,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
} else {
// If no type arguments were provided, we have to infer them.
// This case also occurs as a result of some malformed input, e.g.
// a lifetime argument being given instead of a type paramter.
// a lifetime argument being given instead of a type parameter.
// Using inference instead of `Error` gives better error messages.
self.var_for_def(span, param)
}

View File

@ -674,7 +674,7 @@ fn check_existential_types<'a, 'fcx, 'gcx, 'tcx>(
} // if may_define_existential_type
// now register the bounds on the parameters of the existential type
// so the parameters given by the function need to fulfil them
// so the parameters given by the function need to fulfill them
// ```rust
// existential type Foo<T: Bar>: 'static;
// fn foo<U>() -> Foo<U> { .. *}

View File

@ -269,7 +269,7 @@ pub fn coerce_unsized_info<'a, 'gcx>(gcx: TyCtxt<'a, 'gcx, 'gcx>,
// exactly one (non-phantom) field has changed its
// type, which we will expect to be the pointer that
// is becoming fat (we could probably generalize this
// to mutiple thin pointers of the same type becoming
// to multiple thin pointers of the same type becoming
// fat, but we don't). In this case:
//
// - `extra` has type `T` before and type `T` after

View File

@ -3632,7 +3632,7 @@ fn name_from_pat(p: &hir::Pat) -> String {
fields.iter().map(|&Spanned { node: ref fp, .. }|
format!("{}: {}", fp.ident, name_from_pat(&*fp.pat)))
.collect::<Vec<String>>().join(", "),
if etc { ", ..." } else { "" }
if etc { ", .." } else { "" }
)
}
PatKind::Tuple(ref elts, _) => format!("({})", elts.iter().map(|p| name_from_pat(&**p))

View File

@ -198,12 +198,12 @@ impl f32 {
}
}
/// Returns a number composed of the magnitude of one number and the sign of
/// another.
/// Returns a number composed of the magnitude of `self` and the sign of
/// `y`.
///
/// Equal to `self` if the sign of `self` and `y` are the same, otherwise
/// equal to `-y`. If `self` is a `NAN`, then a `NAN` with the sign of `y`
/// is returned.
/// equal to `-self`. If `self` is a `NAN`, then a `NAN` with the sign of
/// `y` is returned.
///
/// # Examples
///

View File

@ -176,12 +176,12 @@ impl f64 {
}
}
/// Returns a number composed of the magnitude of one number and the sign of
/// another.
/// Returns a number composed of the magnitude of `self` and the sign of
/// `y`.
///
/// Equal to `self` if the sign of `self` and `y` are the same, otherwise
/// equal to `-y`. If `self` is a `NAN`, then a `NAN` with the sign of `y`
/// is returned.
/// equal to `-self`. If `self` is a `NAN`, then a `NAN` with the sign of
/// `y` is returned.
///
/// # Examples
///

View File

@ -8,72 +8,713 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
#[doc(keyword = "fn")]
#[doc(keyword = "as")]
//
/// The `fn` keyword.
/// The keyword for casting a value to a type.
///
/// The `fn` keyword is used to declare a function.
///
/// Example:
/// `as` is most commonly used to turn primitive types into other primitive types, but it has other
/// uses that include turning pointers into addresses, addresses into pointers, and pointers into
/// other pointers.
///
/// ```rust
/// fn some_function() {
/// // code goes in here
/// let thing1: u8 = 89.0 as u8;
/// assert_eq!('B' as u32, 66);
/// assert_eq!(thing1 as char, 'Y');
/// let thing2: f32 = thing1 as f32 + 10.5;
/// assert_eq!(true as u8 + thing2 as u8, 100);
/// ```
///
/// In general, any cast that can be performed via ascribing the type can also be done using `as`,
/// so instead of writing `let x: u32 = 123`, you can write `let x = 123 as u32` (Note: `let x: u32
/// = 123` would be best in that situation). The same is not true in the other direction, however,
/// explicitly using `as` allows a few more coercions that aren't allowed implicitly, such as
/// changing the type of a raw pointer or turning closures into raw pointers.
///
/// Other places `as` is used include as extra syntax for [`crate`] and `use`, to change the name
/// something is imported as.
///
/// For more information on what `as` is capable of, see the [Reference]
///
/// [Reference]:
/// https://doc.rust-lang.org/reference/expressions/operator-expr.html#type-cast-expressions
/// [`crate`]: keyword.crate.html
mod as_keyword { }
#[doc(keyword = "const")]
//
/// The keyword for defining constants.
///
/// Sometimes a certain value is used many times throughout a program, and it can become
/// inconvenient to copy it over and over. What's more, it's not always possible or desirable to
/// make it a variable that gets carried around to each function that needs it. In these cases, the
/// `const` keyword provides a convenient alternative to code duplication.
///
/// ```rust
/// const THING: u32 = 0xABAD1DEA;
///
/// let foo = 123 + THING;
/// ```
///
/// Constants must be explicitly typed, unlike with `let` you can't ignore its type and let the
/// compiler figure it out. Any constant value can be defined in a const, which in practice happens
/// to be most things that would be reasonable to have a constant (barring `const fn`s, coming
/// soon). For example, you can't have a File as a `const`.
///
/// The only lifetime allowed in a constant is `'static`, which is the lifetime that encompasses
/// all others in a Rust program. For example, if you wanted to define a constant string, it would
/// look like this:
///
/// ```rust
/// const WORDS: &'static str = "hello rust!";
/// ```
///
/// Thanks to static lifetime elision, you usually don't have to explicitly use 'static:
///
/// ```rust
/// const WORDS: &str = "hello convenience!";
/// ```
///
/// `const` items looks remarkably similar to `static` items, which introduces some confusion as
/// to which one should be used at which times. To put it simply, constants are inlined wherever
/// they're used, making using them identical to simply replacing the name of the const with its
/// value. Static variables on the other hand point to a single location in memory, which all
/// accesses share. This means that, unlike with constants, they can't have destructors, and act as
/// a single value across the entire codebase.
///
/// Constants, as with statics, should always be in SCREAMING_SNAKE_CASE.
///
/// The `const` keyword is also used in raw pointers in combination with `mut`, as seen in `*const
/// T` and `*mut T`. More about that can be read at the [pointer] primitive part of the Rust docs.
///
/// For more detail on `const`, see the [Rust Book] or the [Reference]
///
/// [pointer]: primitive.pointer.html
/// [Rust Book]:
/// https://doc.rust-lang.org/stable/book/2018-edition/ch03-01-variables-and-mutability.html#differences-between-variables-and-constants
/// [Reference]: https://doc.rust-lang.org/reference/items/constant-items.html
mod const_keyword { }
#[doc(keyword = "crate")]
//
/// The `crate` keyword.
///
/// The primary use of the `crate` keyword is as a part of `extern crate` declarations, which are
/// used to specify a dependency on a crate external to the one it's declared in. Crates are the
/// fundamental compilation unit of Rust code, and can be seen as libraries or projects. More can
/// be read about crates in the [Reference].
///
/// ```rust ignore
/// extern crate rand;
/// extern crate my_crate as thing;
/// extern crate std; // implicitly added to the root of every Rust project
/// ```
///
/// The `as` keyword can be used to change what the crate is referred to as in your project. If a
/// crate name includes a dash, it is implicitly imported with the dashes replaced by underscores.
///
/// `crate` is also used as in conjunction with `pub` to signify that the item it's attached to
/// is public only to other members of the same crate it's in.
///
/// ```rust
/// # #[allow(unused_imports)]
/// pub(crate) use std::io::Error as IoError;
/// pub(crate) enum CoolMarkerType { }
/// pub struct PublicThing {
/// pub(crate) semi_secret_thing: bool,
/// }
/// ```
///
/// For more information about functions, take a look at the [Rust Book][book].
/// [Reference]: https://doc.rust-lang.org/reference/items/extern-crates.html
mod crate_keyword { }
#[doc(keyword = "enum")]
//
/// For defining enumerations.
///
/// [book]: https://doc.rust-lang.org/book/second-edition/ch03-03-how-functions-work.html
/// Enums in Rust are similar to those of other compiled languages like C, but have important
/// differences that make them considerably more powerful. What Rust calls enums are more commonly
/// known as [Algebraic Data Types] if you're coming from a functional programming background. The
/// important detail is that each enum variant can have data to go along with it.
///
/// ```rust
/// # struct Coord;
/// enum SimpleEnum {
/// FirstVariant,
/// SecondVariant,
/// ThirdVariant,
/// }
///
/// enum Location {
/// Unknown,
/// Anonymous,
/// Known(Coord),
/// }
///
/// enum ComplexEnum {
/// Nothing,
/// Something(u32),
/// LotsOfThings {
/// usual_struct_stuff: bool,
/// blah: String,
/// }
/// }
///
/// enum EmptyEnum { }
/// ```
///
/// The first enum shown is the usual kind of enum you'd find in a C-style language. The second
/// shows off a hypothetical example of something storing location data, with `Coord` being any
/// other type that's needed, for example a struct. The third example demonstrates the kind of
/// data a variant can store, ranging from nothing, to a tuple, to an anonymous struct.
///
/// Instantiating enum variants involves explicitly using the enum's name as its namespace,
/// followed by one of its variants. `SimpleEnum::SecondVariant` would be an example from above.
/// When data follows along with a variant, such as with rust's built-in [`Option`] type, the data
/// is added as the type describes, for example `Option::Some(123)`. The same follows with
/// struct-like variants, with things looking like `ComplexEnum::LotsOfThings { usual_struct_stuff:
/// true, blah: "hello!".to_string(), }`. Empty Enums are similar to () in that they cannot be
/// instantiated at all, and are used mainly to mess with the type system in interesting ways.
///
/// For more information, take a look at the [Rust Book] or the [Reference]
///
/// [Algebraic Data Types]: https://en.wikipedia.org/wiki/Algebraic_data_type
/// [`Option`]: option/enum.Option.html
/// [Rust Book]: https://doc.rust-lang.org/book/second-edition/ch06-01-defining-an-enum.html
/// [Reference]: https://doc.rust-lang.org/reference/items/enumerations.html
mod enum_keyword { }
#[doc(keyword = "extern")]
//
/// For external connections in Rust code.
///
/// The `extern` keyword is used in two places in Rust. One is in conjunction with the [`crate`]
/// keyword to make your Rust code aware of other Rust crates in your project, i.e. `extern crate
/// lazy_static;`. The other use is in foreign function interfaces (FFI).
///
/// `extern` is used in two different contexts within FFI. The first is in the form of external
/// blocks, for declaring function interfaces that Rust code can call foreign code by.
///
/// ```rust ignore
/// #[link(name = "my_c_library")]
/// extern "C" {
/// fn my_c_function(x: i32) -> bool;
/// }
/// ```
///
/// This code would attempt to link with `libmy_c_library.so` on unix-like systems and
/// `my_c_library.dll` on Windows at runtime, and panic if it can't find something to link to. Rust
/// code could then use `my_c_function` as if it were any other unsafe Rust function. Working with
/// non-Rust languages and FFI is inherently unsafe, so wrappers are usually built around C APIs.
///
/// The mirror use case of FFI is also done via the `extern` keyword:
///
/// ```rust
/// #[no_mangle]
/// pub extern fn callable_from_c(x: i32) -> bool {
/// x % 3 == 0
/// }
/// ```
///
/// If compiled as a dylib, the resulting .so could then be linked to from a C library, and the
/// function could be used as if it was from any other library.
///
/// For more information on FFI, check the [Rust book] or the [Reference].
///
/// [Rust book]:
/// https://doc.rust-lang.org/book/second-edition/ch19-01-unsafe-rust.html#using-extern-functions-to-call-external-code
/// [Reference]: https://doc.rust-lang.org/reference/items/external-blocks.html
mod extern_keyword { }
#[doc(keyword = "fn")]
//
/// The keyword for defining functions.
///
/// Functions are the primary way code is executed within Rust. Function blocks, usually just
/// called functions, can be defined in a variety of different places and be assigned many
/// different attributes and modifiers.
///
/// Standalone functions that just sit within a module not attached to anything else are common,
/// but most functions will end up being inside [`impl`] blocks, either on another type itself, or
/// as a trait impl for that type.
///
/// ```rust
/// fn standalone_function() {
/// // code
/// }
///
/// pub fn public_thing(argument: bool) -> String {
/// // code
/// # "".to_string()
/// }
///
/// struct Thing {
/// foo: i32,
/// }
///
/// impl Thing {
/// pub fn new() -> Self {
/// Self {
/// foo: 42,
/// }
/// }
/// }
/// ```
///
/// In addition to presenting fixed types in the form of `fn name(arg: type, ..) -> return_type`,
/// functions can also declare a list of type parameters along with trait bounds that they fall
/// into.
///
/// ```rust
/// fn generic_function<T: Clone>(x: T) -> (T, T, T) {
/// (x.clone(), x.clone(), x.clone())
/// }
///
/// fn generic_where<T>(x: T) -> T
/// where T: std::ops::Add<Output=T> + Copy
/// {
/// x + x + x
/// }
/// ```
///
/// Declaring trait bounds in the angle brackets is functionally identical to using a `where`
/// clause. It's up to the programmer to decide which works better in each situation, but `where`
/// tends to be better when things get longer than one line.
///
/// Along with being made public via `pub`, `fn` can also have an [`extern`] added for use in
/// FFI.
///
/// For more information on the various types of functions and how they're used, consult the [Rust
/// book] or the [Reference].
///
/// [`impl`]: keyword.impl.html
/// [`extern`]: keyword.extern.html
/// [Rust book]: https://doc.rust-lang.org/book/second-edition/ch03-03-how-functions-work.html
/// [Reference]: https://doc.rust-lang.org/reference/items/functions.html
mod fn_keyword { }
#[doc(keyword = "for")]
//
/// The `for` keyword.
///
/// `for` is primarily used in for-in-loops, but it has a few other pieces of syntactic uses such as
/// `impl Trait for Type` (see [`impl`] for more info on that). for-in-loops, or to be more
/// precise, iterator loops, are a simple syntactic sugar over an exceedingly common practice
/// within Rust, which is to loop over an iterator until that iterator returns None (or `break`
/// is called).
///
/// ```rust
/// for i in 0..5 {
/// println!("{}", i * 2);
/// }
///
/// for i in std::iter::repeat(5) {
/// println!("turns out {} never stops being 5", i);
/// break; // would loop forever otherwise
/// }
///
/// 'outer: for x in 5..50 {
/// for y in 0..10 {
/// if x == y {
/// break 'outer;
/// }
/// }
/// }
/// ```
///
/// As shown in the example above, `for` loops (along with all other loops) can be tagged, using
/// similar syntax to lifetimes (only visually similar, entirely distinct in practice). Giving the
/// same tag to `break` breaks the tagged loop, which is useful for inner loops. It is definitely
/// not a goto.
///
/// A `for` loop expands as shown:
///
/// ```rust
/// # fn code() { }
/// # let iterator = 0..2;
/// for loop_variable in iterator {
/// code()
/// }
/// ```
///
/// ```rust
/// # fn code() { }
/// # let iterator = 0..2;
/// {
/// let mut _iter = std::iter::IntoIterator::into_iter(iterator);
/// loop {
/// match _iter.next() {
/// Some(loop_variable) => {
/// code()
/// },
/// None => break,
/// }
/// }
/// }
/// ```
///
/// More details on the functionality shown can be seen at the [`IntoIterator`] docs.
///
/// For more information on for-loops, see the [Rust book] or the [Reference].
///
/// [`impl`]: keyword.impl.html
/// [`IntoIterator`]: iter/trait.IntoIterator.html
/// [Rust book]:
/// https://doc.rust-lang.org/book/2018-edition/ch03-05-control-flow.html#looping-through-a-collection-with-for
/// [Reference]: https://doc.rust-lang.org/reference/expressions/loop-expr.html#iterator-loops
mod for_keyword { }
#[doc(keyword = "if")]
//
/// If statements and expressions.
///
/// `if` is a familiar construct to most programmers, and is the main way you'll often do logic in
/// your code. However, unlike in most languages, `if` blocks can also act as expressions.
///
/// ```rust
/// # let rude = true;
/// if 1 == 2 {
/// println!("whoops, mathematics broke");
/// } else {
/// println!("everything's fine!");
/// }
///
/// let greeting = if rude {
/// "sup nerd."
/// } else {
/// "hello, friend!"
/// };
///
/// if let Ok(x) = "123".parse::<i32>() {
/// println!("{} double that and you get {}!", greeting, x * 2);
/// }
/// ```
///
/// Shown above are the three typical forms an `if` block comes in. First is the usual kind of
/// thing you'd see in many languages, with an optional `else` block. Second uses `if` as an
/// expression, which is only possible if all branches return the same type. An `if` expression can
/// be used everywhere you'd expect. The third kind of `if` block is an `if let` block, which
/// behaves similarly to using a `match` expression:
///
/// ```rust
/// if let Some(x) = Some(123) {
/// // code
/// # let _ = x;
/// } else {
/// // something else
/// }
///
/// match Some(123) {
/// Some(x) => {
/// // code
/// # let _ = x;
/// },
/// _ => {
/// // something else
/// },
/// }
/// ```
///
/// Each kind of `if` expression can be mixed and matched as needed.
///
/// ```rust
/// if true == false {
/// println!("oh no");
/// } else if "something" == "other thing" {
/// println!("oh dear");
/// } else if let Some(200) = "blarg".parse::<i32>().ok() {
/// println!("uh oh");
/// } else {
/// println!("phew, nothing's broken");
/// }
/// ```
///
/// The `if` keyword is used in one other place in Rust, namely as a part of pattern matching
/// itself, allowing patterns such as `Some(x) if x > 200` to be used.
///
/// For more information on `if` expressions, see the [Rust book] or the [Reference].
///
/// [Rust book]:
/// https://doc.rust-lang.org/stable/book/2018-edition/ch03-05-control-flow.html#if-expressions
/// [Reference]: https://doc.rust-lang.org/reference/expressions/if-expr.html
mod if_keyword { }
#[doc(keyword = "impl")]
//
/// The implementation-defining keyword.
///
/// The `impl` keyword is primarily used to define implementations on types. Inherent
/// implementations are standalone, while trait implementations are used to implement traits for
/// types, or other traits.
///
/// Functions and consts can both be defined in an implementation. A function defined in an
/// `impl` block can be standalone, meaning it would be called like `Foo::bar()`. If the function
/// takes `self`, `&self`, or `&mut self` as its first argument, it can also be called using
/// method-call syntax, a familiar feature to any object oriented programmer, like `foo.bar()`.
///
/// ```rust
/// struct Example {
/// number: i32,
/// }
///
/// impl Example {
/// fn boo() {
/// println!("boo! Example::boo() was called!");
/// }
///
/// fn answer(&mut self) {
/// self.number += 42;
/// }
///
/// fn get_number(&self) -> i32 {
/// self.number
/// }
/// }
///
/// trait Thingy {
/// fn do_thingy(&self);
/// }
///
/// impl Thingy for Example {
/// fn do_thingy(&self) {
/// println!("doing a thing! also, number is {}!", self.number);
/// }
/// }
/// ```
///
/// For more information on implementations, see the [Rust book][book1] or the [Reference].
///
/// The other use of the `impl` keyword is in `impl Trait` syntax, which can be seen as a shorthand
/// for "a concrete type that implements this trait". Its primary use is working with closures,
/// which have type definitions generated at compile time that can't be simply typed out.
///
/// ```rust
/// fn thing_returning_closure() -> impl Fn(i32) -> bool {
/// println!("here's a closure for you!");
/// |x: i32| x % 3 == 0
/// }
/// ```
///
/// For more information on `impl Trait` syntax, see the [Rust book][book2].
///
/// [book1]: https://doc.rust-lang.org/stable/book/2018-edition/ch05-03-method-syntax.html
/// [Reference]: https://doc.rust-lang.org/reference/items/implementations.html
/// [book2]:
/// https://doc.rust-lang.org/stable/book/2018-edition/ch10-02-traits.html#returning-traits
mod impl_keyword { }
#[doc(keyword = "let")]
//
/// The `let` keyword.
/// The variable binding keyword.
///
/// The `let` keyword is used to declare a variable.
///
/// Example:
/// The primary use for the `let` keyword is in `let` statements, which are used to introduce a new
/// set of variables into the current scope, as given by a pattern.
///
/// ```rust
/// # #![allow(unused_assignments)]
/// let x = 3; // We create a variable named `x` with the value `3`.
/// let thing1: i32 = 100;
/// let thing2 = 200 + thing1;
///
/// let mut changing_thing = true;
/// changing_thing = false;
///
/// let (part1, part2) = ("first", "second");
///
/// struct Example {
/// a: bool,
/// b: u64,
/// }
///
/// let Example { a, b: _ } = Example {
/// a: true,
/// b: 10004,
/// };
/// assert!(a);
/// ```
///
/// By default, all variables are **not** mutable. If you want a mutable variable,
/// you'll have to use the `mut` keyword.
/// The pattern is most commonly a single variable, which means no pattern matching is done and
/// the expression given is bound to the variable. Apart from that, patterns used in `let` bindings
/// can be as complicated as needed, given that the pattern is exhaustive. See the [Rust
/// book][book1] for more information on pattern matching. The type of the pattern is optionally
/// given afterwards, but if left blank is automatically inferred by the compiler if possible.
///
/// Example:
/// Variables in Rust are immutable by default, and require the `mut` keyword to be made mutable.
///
/// Multiple variables can be defined with the same name, known as shadowing. This doesn't affect
/// the original variable in any way beyond being unable to directly access it beyond the point of
/// shadowing. It continues to remain in scope, getting dropped only when it falls out of scope.
/// Shadowed variables don't need to have the same type as the variables shadowing them.
///
/// ```rust
/// # #![allow(unused_assignments)]
/// let mut x = 3; // We create a mutable variable named `x` with the value `3`.
///
/// x += 4; // `x` is now equal to `7`.
/// let shadowing_example = true;
/// let shadowing_example = 123.4;
/// let shadowing_example = shadowing_example as u32;
/// let mut shadowing_example = format!("cool! {}", shadowing_example);
/// shadowing_example += " something else!"; // not shadowing
/// ```
///
/// For more information about the `let` keyword, take a look at the [Rust Book][book].
/// Other places the `let` keyword is used include along with [`if`], in the form of `if let`
/// expressions. They're useful if the pattern being matched isn't exhaustive, such as with
/// enumerations. `while let` also exists, which runs a loop with a pattern matched value until
/// that pattern can't be matched.
///
/// [book]: https://doc.rust-lang.org/book/second-edition/ch03-01-variables-and-mutability.html
/// For more information on the `let` keyword, see the [Rust book] or the [Reference]
///
/// [book1]: https://doc.rust-lang.org/stable/book/2018-edition/ch06-02-match.html
/// [`if`]: keyword.if.html
/// [book2]:
/// https://doc.rust-lang.org/stable/book/2018-edition/ch18-01-all-the-places-for-patterns.html#let-statements
/// [Reference]: https://doc.rust-lang.org/reference/statements.html#let-statements
mod let_keyword { }
#[doc(keyword = "struct")]
#[doc(keyword = "loop")]
//
/// The `struct` keyword.
/// The loop-defining keyword.
///
/// The `struct` keyword is used to define a struct type.
/// `loop` is used to define the simplest kind of loop supported in Rust. It runs the code inside
/// it until the code uses `break` or the program exits.
///
/// Example:
/// ```rust
/// loop {
/// println!("hello world forever!");
/// # break;
/// }
///
/// ```
/// struct Foo {
/// field1: u32,
/// field2: String,
/// let mut i = 0;
/// loop {
/// println!("i is {}", i);
/// if i > 10 {
/// break;
/// }
/// i += 1;
/// }
/// ```
///
/// There are different kinds of structs. For more information, take a look at the
/// [Rust Book][book].
/// Unlike the other kinds of loops in Rust (`while`, `while let`, and `for`), loops can be used as
/// expressions that return values via `break`.
///
/// ```rust
/// let mut i = 1;
/// let something = loop {
/// i *= 2;
/// if i > 100 {
/// break i;
/// }
/// };
/// assert_eq!(something, 128);
/// ```
///
/// Every `break` in a loop has to have the same type. When it's not explicitly giving something,
/// `break;` returns `()`.
///
/// For more information on `loop` and loops in general, see the [Reference].
///
/// [Reference]: https://doc.rust-lang.org/reference/expressions/loop-expr.html
mod loop_keyword { }
#[doc(keyword = "struct")]
//
/// The keyword used to define structs.
///
/// Structs in Rust come in three flavours: Structs with named fields, tuple structs, and unit
/// structs.
///
/// ```rust
/// struct Regular {
/// field1: f32,
/// field2: String,
/// pub field3: bool
/// }
///
/// struct Tuple(u32, String);
///
/// struct Unit;
/// ```
///
/// Regular structs are the most commonly used. Each field defined within them has a name and a
/// type, and once defined can be accessed using `example_struct.field` syntax. The fields of a
/// struct share its mutability, so `foo.bar = 2;` would only be valid if `foo` was mutable. Adding
/// `pub` to a field makes it visible to code in other modules, as well as allowing it to be
/// directly accessed and modified.
///
/// Tuple structs are similar to regular structs, but its fields have no names. They are used like
/// tuples, with deconstruction possible via `let TupleStruct(x, y) = foo;` syntax. For accessing
/// individual variables, the same syntax is used as with regular tuples, namely `foo.0`, `foo.1`,
/// etc, starting at zero.
///
/// Unit structs are most commonly used as marker. They have a size of zero bytes, but unlike empty
/// enums they can be instantiated, making them isomorphic to the unit type `()`. Unit structs are
/// useful when you need to implement a trait on something, but don't need to store any data inside
/// it.
///
/// # Instantiation
///
/// Structs can be instantiated in different ways, all of which can be mixed and
/// matched as needed. The most common way to make a new struct is via a constructor method such as
/// `new()`, but when that isn't available (or you're writing the constructor itself), struct
/// literal syntax is used:
///
/// ```rust
/// # struct Foo { field1: f32, field2: String, etc: bool }
/// let example = Foo {
/// field1: 42.0,
/// field2: "blah".to_string(),
/// etc: true,
/// };
/// ```
///
/// It's only possible to directly instantiate a struct using struct literal syntax when all of its
/// fields are visible to you.
///
/// There are a handful of shortcuts provided to make writing constructors more convenient, most
/// common of which is the Field Init shorthand. When there is a variable and a field of the same
/// name, the assignment can be simplified from `field: field` into simply `field`. The following
/// example of a hypothetical constructor demonstrates this:
///
/// ```rust
/// struct User {
/// name: String,
/// admin: bool,
/// }
///
/// impl User {
/// pub fn new(name: String) -> Self {
/// Self {
/// name,
/// admin: false,
/// }
/// }
/// }
/// ```
///
/// Another shortcut for struct instantiation is available, used when you need to make a new
/// struct that has the same values as most of a previous struct of the same type, called struct
/// update syntax:
///
/// ```rust
/// # struct Foo { field1: String, field2: () }
/// # let thing = Foo { field1: "".to_string(), field2: () };
/// let updated_thing = Foo {
/// field1: "a new value".to_string(),
/// ..thing
/// };
/// ```
///
/// Tuple structs are instantiated in the same way as tuples themselves, except with the struct's
/// name as a prefix: `Foo(123, false, 0.1)`.
///
/// Empty structs are instantiated with just their name, and don't need anything else. `let thing =
/// EmptyStruct;`
///
/// # Style conventions
///
/// Structs are always written in CamelCase, with few exceptions. While the trailing comma on a
/// struct's list of fields can be omitted, it's usually kept for convenience in adding and
/// removing fields down the line.
///
/// For more information on structs, take a look at the [Rust Book][book] or the
/// [Reference][reference].
///
/// [`PhantomData`]: marker/struct.PhantomData.html
/// [book]: https://doc.rust-lang.org/book/second-edition/ch05-01-defining-structs.html
/// [reference]: https://doc.rust-lang.org/reference/items/structs.html
mod struct_keyword { }

View File

@ -43,12 +43,12 @@ use time::Duration;
/// use std::io::prelude::*;
/// use std::net::TcpStream;
///
/// {
/// let mut stream = TcpStream::connect("127.0.0.1:34254").unwrap();
/// fn main() -> std::io::Result<()> {
/// let mut stream = TcpStream::connect("127.0.0.1:34254")?;
///
/// // ignore the Result
/// let _ = stream.write(&[1]);
/// let _ = stream.read(&mut [0; 128]); // ignore here too
/// stream.write(&[1])?;
/// stream.read(&mut [0; 128])?;
/// Ok(())
/// } // the stream is closed here
/// ```
#[stable(feature = "rust1", since = "1.0.0")]

View File

@ -323,8 +323,8 @@ mod prim_never { }
/// let s = String::from("love: ❤️");
/// let v: Vec<char> = s.chars().collect();
///
/// assert_eq!(12, s.len() * std::mem::size_of::<u8>());
/// assert_eq!(32, v.len() * std::mem::size_of::<char>());
/// assert_eq!(12, std::mem::size_of_val(&s[..]));
/// assert_eq!(32, std::mem::size_of_val(&v[..]));
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
mod prim_char { }

View File

@ -1016,6 +1016,28 @@ impl fmt::Debug for Stdio {
#[stable(feature = "stdio_from", since = "1.20.0")]
impl From<ChildStdin> for Stdio {
/// Converts a `ChildStdin` into a `Stdio`
///
/// # Examples
///
/// `ChildStdin` will be converted to `Stdio` using `Stdio::from` under the hood.
///
/// ```rust
/// use std::process::{Command, Stdio};
///
/// let reverse = Command::new("rev")
/// .stdin(Stdio::piped())
/// .spawn()
/// .expect("failed reverse command");
///
/// let _echo = Command::new("echo")
/// .arg("Hello, world!")
/// .stdout(reverse.stdin.unwrap()) // Converted into a Stdio here
/// .output()
/// .expect("failed echo command");
///
/// // "!dlrow ,olleH" echoed to console
/// ```
fn from(child: ChildStdin) -> Stdio {
Stdio::from_inner(child.into_inner().into())
}
@ -1023,6 +1045,28 @@ impl From<ChildStdin> for Stdio {
#[stable(feature = "stdio_from", since = "1.20.0")]
impl From<ChildStdout> for Stdio {
/// Converts a `ChildStdout` into a `Stdio`
///
/// # Examples
///
/// `ChildStdout` will be converted to `Stdio` using `Stdio::from` under the hood.
///
/// ```rust
/// use std::process::{Command, Stdio};
///
/// let hello = Command::new("echo")
/// .arg("Hello, world!")
/// .stdout(Stdio::piped())
/// .spawn()
/// .expect("failed echo command");
///
/// let reverse = Command::new("rev")
/// .stdin(hello.stdout.unwrap()) // Converted into a Stdio here
/// .output()
/// .expect("failed reverse command");
///
/// assert_eq!(reverse.stdout, b"!dlrow ,olleH\n");
/// ```
fn from(child: ChildStdout) -> Stdio {
Stdio::from_inner(child.into_inner().into())
}
@ -1030,6 +1074,30 @@ impl From<ChildStdout> for Stdio {
#[stable(feature = "stdio_from", since = "1.20.0")]
impl From<ChildStderr> for Stdio {
/// Converts a `ChildStderr` into a `Stdio`
///
/// # Examples
///
/// ```rust,no_run
/// use std::process::{Command, Stdio};
///
/// let reverse = Command::new("rev")
/// .arg("non_existing_file.txt")
/// .stderr(Stdio::piped())
/// .spawn()
/// .expect("failed reverse command");
///
/// let cat = Command::new("cat")
/// .arg("-")
/// .stdin(reverse.stderr.unwrap()) // Converted into a Stdio here
/// .output()
/// .expect("failed echo command");
///
/// assert_eq!(
/// String::from_utf8_lossy(&cat.stdout),
/// "rev: cannot open non_existing_file.txt: No such file or directory\n"
/// );
/// ```
fn from(child: ChildStderr) -> Stdio {
Stdio::from_inner(child.into_inner().into())
}
@ -1037,6 +1105,26 @@ impl From<ChildStderr> for Stdio {
#[stable(feature = "stdio_from", since = "1.20.0")]
impl From<fs::File> for Stdio {
/// Converts a `File` into a `Stdio`
///
/// # Examples
///
/// `File` will be converted to `Stdio` using `Stdio::from` under the hood.
///
/// ```rust,no_run
/// use std::fs::File;
/// use std::process::Command;
///
/// // With the `foo.txt` file containing `Hello, world!"
/// let file = File::open("foo.txt").unwrap();
///
/// let reverse = Command::new("rev")
/// .stdin(file) // Implicit File convertion into a Stdio
/// .output()
/// .expect("failed reverse command");
///
/// assert_eq!(reverse.stdout, b"!dlrow ,olleH");
/// ```
fn from(file: fs::File) -> Stdio {
Stdio::from_inner(file.into_inner().into())
}

View File

@ -97,7 +97,7 @@
//! - A **multiprocessor** system executing multiple hardware threads
//! at the same time: In multi-threaded scenarios, you can use two
//! kinds of primitives to deal with synchronization:
//! - [memory fences] to ensure memory accesses are made visibile to
//! - [memory fences] to ensure memory accesses are made visible to
//! other CPUs in the right order.
//! - [atomic operations] to ensure simultaneous access to the same
//! memory location doesn't lead to undefined behavior.

View File

@ -290,8 +290,8 @@ impl Once {
}
/// Returns true if some `call_once` call has completed
/// successfuly. Specifically, `is_completed` will return false in
/// the following situtations:
/// successfully. Specifically, `is_completed` will return false in
/// the following situations:
/// * `call_once` was not called at all,
/// * `call_once` was called, but has not yet completed,
/// * the `Once` instance is poisoned

View File

@ -96,7 +96,7 @@ impl<'a> StripUnconfigured<'a> {
/// when the configuration predicate is true, or otherwise expand into an
/// empty list of attributes.
///
/// Gives a compiler warning when the `cfg_attr` contains no attribtes and
/// Gives a compiler warning when the `cfg_attr` contains no attributes and
/// is in the original source file. Gives a compiler error if the syntax of
/// the attribute is incorrect
fn process_cfg_attr(&mut self, attr: ast::Attribute) -> Vec<ast::Attribute> {
@ -138,7 +138,7 @@ impl<'a> StripUnconfigured<'a> {
};
// Check feature gate and lint on zero attributes in source. Even if the feature is gated,
// we still compute as if it wasn't, since the emitted error will stop compilation futher
// we still compute as if it wasn't, since the emitted error will stop compilation further
// along the compilation.
match (expanded_attrs.len(), gate_cfg_attr_multi) {
(0, false) => {

View File

@ -905,7 +905,8 @@ fn is_in_follow(tok: &quoted::TokenTree, frag: &str) -> Result<bool, (String, &'
"path" | "ty" => match *tok {
TokenTree::Token(_, ref tok) => match *tok {
OpenDelim(token::DelimToken::Brace) | OpenDelim(token::DelimToken::Bracket) |
Comma | FatArrow | Colon | Eq | Gt | Semi | BinOp(token::Or) => Ok(true),
Comma | FatArrow | Colon | Eq | Gt | BinOp(token::Shr) | Semi |
BinOp(token::Or) => Ok(true),
Ident(i, false) if i.name == "as" || i.name == "where" => Ok(true),
_ => Ok(false)
},

View File

@ -965,7 +965,7 @@ pub fn noop_fold_item_kind<T: Folder>(i: ItemKind, folder: &mut T) -> ItemKind {
polarity,
defaultness,
folder.fold_generics(generics),
ifce.map(|trait_ref| folder.fold_trait_ref(trait_ref.clone())),
ifce.map(|trait_ref| folder.fold_trait_ref(trait_ref)),
folder.fold_ty(ty),
impl_items.move_flat_map(|item| folder.fold_impl_item(item)),
),

@ -1 +1 @@
Subproject commit 307650500de5b44dc1047dc9d15e449e09d92b57
Subproject commit 431766a3fbcfb6dafb2d5a3866c1609bf44ee554

View File

@ -9,7 +9,7 @@
// except according to those terms.
// run-pass
// Test for issue #18804, #[linkage] does not propagate thorugh generic
// Test for issue #18804, #[linkage] does not propagate through generic
// functions. Failure results in a linker error.
// ignore-asmjs no weak symbol support

View File

@ -0,0 +1,16 @@
macro_rules! test {
(
fn fun() -> Option<Box<$t:ty>>;
) => {
fn fun(x: $t) -> Option<Box<$t>>
{ Some(Box::new(x)) }
}
}
test! {
fn fun() -> Option<Box<i32>>;
}
fn main() {
println!("{}", fun(0).unwrap());
}

View File

@ -15,6 +15,7 @@
// compile-flags:--test
// normalize-stdout-test: "src/test/rustdoc-ui" -> "$$DIR"
// failure-status: 101
// rustc-env:RUST_BACKTRACE=0
// doctest fails at runtime
/// ```

View File

@ -1,22 +1,22 @@
running 2 tests
test $DIR/failed-doctest-output.rs - OtherStruct (line 26) ... FAILED
test $DIR/failed-doctest-output.rs - SomeStruct (line 20) ... FAILED
test $DIR/failed-doctest-output.rs - OtherStruct (line 27) ... FAILED
test $DIR/failed-doctest-output.rs - SomeStruct (line 21) ... FAILED
failures:
---- $DIR/failed-doctest-output.rs - OtherStruct (line 26) stdout ----
---- $DIR/failed-doctest-output.rs - OtherStruct (line 27) stdout ----
error[E0425]: cannot find value `no` in this scope
--> $DIR/failed-doctest-output.rs:27:1
--> $DIR/failed-doctest-output.rs:28:1
|
3 | no
| ^^ not found in this scope
thread '$DIR/failed-doctest-output.rs - OtherStruct (line 26)' panicked at 'couldn't compile the test', librustdoc/test.rs:332:13
thread '$DIR/failed-doctest-output.rs - OtherStruct (line 27)' panicked at 'couldn't compile the test', librustdoc/test.rs:332:13
note: Run with `RUST_BACKTRACE=1` for a backtrace.
---- $DIR/failed-doctest-output.rs - SomeStruct (line 20) stdout ----
thread '$DIR/failed-doctest-output.rs - SomeStruct (line 20)' panicked at 'test executable failed:
---- $DIR/failed-doctest-output.rs - SomeStruct (line 21) stdout ----
thread '$DIR/failed-doctest-output.rs - SomeStruct (line 21)' panicked at 'test executable failed:
thread 'main' panicked at 'oh no', $DIR/failed-doctest-output.rs:3:1
note: Run with `RUST_BACKTRACE=1` for a backtrace.
@ -25,8 +25,8 @@ note: Run with `RUST_BACKTRACE=1` for a backtrace.
failures:
$DIR/failed-doctest-output.rs - OtherStruct (line 26)
$DIR/failed-doctest-output.rs - SomeStruct (line 20)
$DIR/failed-doctest-output.rs - OtherStruct (line 27)
$DIR/failed-doctest-output.rs - SomeStruct (line 21)
test result: FAILED. 0 passed; 2 failed; 0 ignored; 0 measured; 0 filtered out

View File

@ -0,0 +1,42 @@
// Issue #54478: regression test showing that we can demonstrate
// `#[global_allocator]` in code blocks built by `rustdoc`.
//
// ## Background
//
// Changes in lang-item visibility injected failures that were only
// exposed when compiling with `-C prefer-dynamic`. But `rustdoc` used
// `-C prefer-dynamic` (and had done so for years, for reasons we did
// not document at that time).
//
// Rather than try to revise the visbility semanics, we instead
// decided to change `rustdoc` to behave more like the compiler's
// default setting, by leaving off `-C prefer-dynamic`.
// compile-flags:--test
//! This is a doc comment
//!
//! ```rust
//! use std::alloc::*;
//!
//! #[global_allocator]
//! static ALLOC: A = A;
//!
//! static mut HIT: bool = false;
//!
//! struct A;
//!
//! unsafe impl GlobalAlloc for A {
//! unsafe fn alloc(&self, layout: Layout) -> *mut u8 {
//! HIT = true;
//! System.alloc(layout)
//! }
//! unsafe fn dealloc(&self, ptr: *mut u8, layout: Layout) {
//! System.dealloc(ptr, layout);
//! }
//! }
//!
//! fn main() {
//! assert!(unsafe { HIT });
//! }
//! ```

View File

@ -2,10 +2,9 @@ error[E0106]: missing lifetime specifier
--> $DIR/bound-lifetime-in-binding-only.rs:62:23
|
LL | fn elision<T: Fn() -> &i32>() {
| ^ expected lifetime parameter
| ^ help: consider giving it a 'static lifetime: `&'static`
|
= help: this function's return type contains a borrowed value, but there is no value for it to be borrowed from
= help: consider giving it a 'static lifetime
error: aborting due to previous error

View File

@ -2,10 +2,9 @@ error[E0106]: missing lifetime specifier
--> $DIR/bound-lifetime-in-return-only.rs:44:23
|
LL | fn elision(_: fn() -> &i32) {
| ^ expected lifetime parameter
| ^ help: consider giving it a 'static lifetime: `&'static`
|
= help: this function's return type contains a borrowed value, but there is no value for it to be borrowed from
= help: consider giving it a 'static lifetime
error: aborting due to previous error

View File

@ -8,7 +8,7 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
// Test that we do some basic error correcton in the tokeniser (and don't spew
// Test that we do some basic error correction in the tokeniser (and don't spew
// too many bogus errors).
fn foo() -> usize {

View File

@ -1,5 +1,5 @@
// Test that cfg_attr doesn't emit any attributes when the
// configuation variable is false. This mirrors `cfg-attr-multi-true.rs`
// configuration variable is false. This mirrors `cfg-attr-multi-true.rs`
// compile-pass

View File

@ -20,4 +20,20 @@ fn main() {
let n: usize = 42;
this_function_expects_a_double_option(n);
//~^ ERROR mismatched types
//~| HELP try using a variant of the expected type
}
// But don't issue the "try using a variant" help if the one-"variant" ADT is
// actually a one-field struct.
struct Payload;
struct Wrapper { payload: Payload }
struct Context { wrapper: Wrapper }
fn overton() {
let _c = Context { wrapper: Payload{} };
//~^ ERROR mismatched types
}

View File

@ -13,6 +13,15 @@ LL | this_function_expects_a_double_option(DoubleOption::FirstSome(n));
LL | this_function_expects_a_double_option(DoubleOption::AlternativeSome(n));
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: aborting due to previous error
error[E0308]: mismatched types
--> $DIR/issue-42764.rs:37:33
|
LL | let _c = Context { wrapper: Payload{} };
| ^^^^^^^^^ expected struct `Wrapper`, found struct `Payload`
|
= note: expected type `Wrapper`
found type `Payload`
error: aborting due to 2 previous errors
For more information about this error, try `rustc --explain E0308`.

View File

@ -0,0 +1,18 @@
// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
// run-rustfix
extern "C" {
pub fn g(_: &u8) -> &u8; // OK
pub fn f() -> &'static u8; //~ ERROR missing lifetime specifier
}
fn main() {}

View File

@ -8,9 +8,11 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
// run-rustfix
extern "C" {
fn g(_: &u8) -> &u8; // OK
fn f() -> &u8; //~ ERROR missing lifetime specifier
pub fn g(_: &u8) -> &u8; // OK
pub fn f() -> &u8; //~ ERROR missing lifetime specifier
}
fn main() {}

View File

@ -1,11 +1,10 @@
error[E0106]: missing lifetime specifier
--> $DIR/foreign-fn-return-lifetime.rs:13:15
--> $DIR/foreign-fn-return-lifetime.rs:15:19
|
LL | fn f() -> &u8; //~ ERROR missing lifetime specifier
| ^ expected lifetime parameter
LL | pub fn f() -> &u8; //~ ERROR missing lifetime specifier
| ^ help: consider giving it a 'static lifetime: `&'static`
|
= help: this function's return type contains a borrowed value, but there is no value for it to be borrowed from
= help: consider giving it a 'static lifetime
error: aborting due to previous error

View File

@ -2,10 +2,9 @@ error[E0106]: missing lifetime specifier
--> $DIR/issue-13497.rs:12:5
|
LL | &str //~ ERROR missing lifetime specifier
| ^ expected lifetime parameter
| ^ help: consider giving it a 'static lifetime: `&'static`
|
= help: this function's return type contains a borrowed value, but there is no value for it to be borrowed from
= help: consider giving it a 'static lifetime
error: aborting due to previous error

View File

@ -10,19 +10,17 @@ error[E0106]: missing lifetime specifier
--> $DIR/issue-26638.rs:14:40
|
LL | fn parse_type_2(iter: fn(&u8)->&u8) -> &str { iter() }
| ^ expected lifetime parameter
| ^ help: consider giving it an explicit bounded or 'static lifetime: `&'static`
|
= help: this function's return type contains a borrowed value with an elided lifetime, but the lifetime cannot be derived from the arguments
= help: consider giving it an explicit bounded or 'static lifetime
error[E0106]: missing lifetime specifier
--> $DIR/issue-26638.rs:17:22
|
LL | fn parse_type_3() -> &str { unimplemented!() }
| ^ expected lifetime parameter
| ^ help: consider giving it a 'static lifetime: `&'static`
|
= help: this function's return type contains a borrowed value, but there is no value for it to be borrowed from
= help: consider giving it a 'static lifetime
error: aborting due to 3 previous errors

View File

@ -2,10 +2,9 @@ error[E0106]: missing lifetime specifier
--> $DIR/lifetime-elision-return-type-requires-explicit-lifetime.rs:12:11
|
LL | fn f() -> &isize { //~ ERROR missing lifetime specifier
| ^ expected lifetime parameter
| ^ help: consider giving it a 'static lifetime: `&'static`
|
= help: this function's return type contains a borrowed value, but there is no value for it to be borrowed from
= help: consider giving it a 'static lifetime
error[E0106]: missing lifetime specifier
--> $DIR/lifetime-elision-return-type-requires-explicit-lifetime.rs:17:33
@ -27,28 +26,25 @@ error[E0106]: missing lifetime specifier
--> $DIR/lifetime-elision-return-type-requires-explicit-lifetime.rs:31:20
|
LL | fn i(_x: isize) -> &isize { //~ ERROR missing lifetime specifier
| ^ expected lifetime parameter
| ^ help: consider giving it an explicit bounded or 'static lifetime: `&'static`
|
= help: this function's return type contains a borrowed value with an elided lifetime, but the lifetime cannot be derived from the arguments
= help: consider giving it an explicit bounded or 'static lifetime
error[E0106]: missing lifetime specifier
--> $DIR/lifetime-elision-return-type-requires-explicit-lifetime.rs:44:24
|
LL | fn j(_x: StaticStr) -> &isize { //~ ERROR missing lifetime specifier
| ^ expected lifetime parameter
| ^ help: consider giving it an explicit bounded or 'static lifetime: `&'static`
|
= help: this function's return type contains a borrowed value with an elided lifetime, but the lifetime cannot be derived from the arguments
= help: consider giving it an explicit bounded or 'static lifetime
error[E0106]: missing lifetime specifier
--> $DIR/lifetime-elision-return-type-requires-explicit-lifetime.rs:50:49
|
LL | fn k<'a, T: WithLifetime<'a>>(_x: T::Output) -> &isize {
| ^ expected lifetime parameter
| ^ help: consider giving it an explicit bounded or 'static lifetime: `&'static`
|
= help: this function's return type contains a borrowed value with an elided lifetime, but the lifetime cannot be derived from the arguments
= help: consider giving it an explicit bounded or 'static lifetime
error: aborting due to 6 previous errors

View File

@ -0,0 +1,12 @@
trait Future {
type Item;
type Error;
}
use std::error::Error;
fn foo() -> impl Future<Item=(), Error=Box<Error>> {
Ok(())
}
fn main() {}

View File

@ -0,0 +1,11 @@
error[E0106]: missing lifetime specifier
--> $DIR/lifetime-elision-return-type-trait.rs:8:44
|
LL | fn foo() -> impl Future<Item=(), Error=Box<Error>> {
| ^^^^^ help: consider giving it a 'static lifetime: `Error + 'static`
|
= help: this function's return type contains a borrowed value, but there is no value for it to be borrowed from
error: aborting due to previous error
For more information about this error, try `rustc --explain E0106`.

View File

@ -56,7 +56,7 @@ fn main() {
while true {
//~^ WARN denote infinite loops
//~| HELP use `loop`
let mut a = (1);
let mut registry_no = (format!("NX-{}", 74205));
//~^ WARN does not need to be mutable
//~| HELP remove this `mut`
//~| WARN unnecessary parentheses
@ -72,6 +72,6 @@ fn main() {
//~^ WARN this pattern is redundant
//~| HELP remove this
}
println!("{} {}", a, b);
println!("{} {}", registry_no, b);
}
}

View File

@ -1,8 +1,8 @@
warning: unnecessary parentheses around assigned value
--> $DIR/suggestions.rs:59:21
--> $DIR/suggestions.rs:59:31
|
LL | let mut a = (1);
| ^^^ help: remove these parentheses
LL | let mut registry_no = (format!("NX-{}", 74205));
| ^^^^^^^^^^^^^^^^^^^^^^^^^ help: remove these parentheses
|
note: lint level defined here
--> $DIR/suggestions.rs:13:21
@ -21,8 +21,8 @@ LL | #[no_debug] // should suggest removal of deprecated attribute
warning: variable does not need to be mutable
--> $DIR/suggestions.rs:59:13
|
LL | let mut a = (1);
| ----^
LL | let mut registry_no = (format!("NX-{}", 74205));
| ----^^^^^^^^^^^
| |
| help: remove this `mut`
|

View File

@ -66,7 +66,7 @@ impl<F> R<F> { fn new(f: F) -> Self { R { w: 0, f } } }
// It got pretty monotonous writing the same code over and over, and I
// feared I would forget details. So I abstracted some desiderata into
// macros. But I left the initialization code inline, because that's
// where the errors for #54986 will be emited.
// where the errors for #54986 will be emitted.
macro_rules! use_fully {
(struct $s:expr) => { {

View File

@ -1,5 +1,5 @@
// rust-lang/rust#52059: Regardless of whether you are moving out of a
// Drop type or just introducing an inadvertant alias via a borrow of
// Drop type or just introducing an inadvertent alias via a borrow of
// one of its fields, it is useful to be reminded of the significance
// of the fact that the type implements Drop.

View File

@ -8,7 +8,7 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
// Test that we do some basic error correcton in the tokeniser (and don't ICE).
// Test that we do some basic error correction in the tokeniser (and don't ICE).
fn main() {
if foo {

View File

@ -10,7 +10,7 @@
// ignore-cloudabi no std::fs support
// Test that we do some basic error correcton in the tokeniser (and don't spew
// Test that we do some basic error correction in the tokeniser (and don't spew
// too many bogus errors).
pub mod raw {

View File

@ -8,7 +8,7 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
// Test that we do some basic error correcton in the tokeniser.
// Test that we do some basic error correction in the tokeniser.
fn main() {
foo(bar(;

View File

@ -19,22 +19,22 @@ fn main() {
use std::ops::Range;
if let Range { start: _, end: _ } = true..true && false { }
//~^ ERROR ambigious use of `&&`
//~^ ERROR ambiguous use of `&&`
if let Range { start: _, end: _ } = true..true || false { }
//~^ ERROR ambigious use of `||`
//~^ ERROR ambiguous use of `||`
while let Range { start: _, end: _ } = true..true && false { }
//~^ ERROR ambigious use of `&&`
//~^ ERROR ambiguous use of `&&`
while let Range { start: _, end: _ } = true..true || false { }
//~^ ERROR ambigious use of `||`
//~^ ERROR ambiguous use of `||`
if let true = false && false { }
//~^ ERROR ambigious use of `&&`
//~^ ERROR ambiguous use of `&&`
while let true = (1 == 2) && false { }
//~^ ERROR ambigious use of `&&`
//~^ ERROR ambiguous use of `&&`
// The following cases are not an error as parenthesis are used to
// clarify intent:

View File

@ -1,4 +1,4 @@
error: ambigious use of `&&`
error: ambiguous use of `&&`
--> $DIR/syntax-ambiguity-2015.rs:21:47
|
LL | if let Range { start: _, end: _ } = true..true && false { }
@ -7,7 +7,7 @@ LL | if let Range { start: _, end: _ } = true..true && false { }
= note: this will be a error until the `let_chains` feature is stabilized
= note: see rust-lang/rust#53668 for more information
error: ambigious use of `||`
error: ambiguous use of `||`
--> $DIR/syntax-ambiguity-2015.rs:24:47
|
LL | if let Range { start: _, end: _ } = true..true || false { }
@ -16,7 +16,7 @@ LL | if let Range { start: _, end: _ } = true..true || false { }
= note: this will be a error until the `let_chains` feature is stabilized
= note: see rust-lang/rust#53668 for more information
error: ambigious use of `&&`
error: ambiguous use of `&&`
--> $DIR/syntax-ambiguity-2015.rs:27:50
|
LL | while let Range { start: _, end: _ } = true..true && false { }
@ -25,7 +25,7 @@ LL | while let Range { start: _, end: _ } = true..true && false { }
= note: this will be a error until the `let_chains` feature is stabilized
= note: see rust-lang/rust#53668 for more information
error: ambigious use of `||`
error: ambiguous use of `||`
--> $DIR/syntax-ambiguity-2015.rs:30:50
|
LL | while let Range { start: _, end: _ } = true..true || false { }
@ -34,7 +34,7 @@ LL | while let Range { start: _, end: _ } = true..true || false { }
= note: this will be a error until the `let_chains` feature is stabilized
= note: see rust-lang/rust#53668 for more information
error: ambigious use of `&&`
error: ambiguous use of `&&`
--> $DIR/syntax-ambiguity-2015.rs:33:19
|
LL | if let true = false && false { }
@ -43,7 +43,7 @@ LL | if let true = false && false { }
= note: this will be a error until the `let_chains` feature is stabilized
= note: see rust-lang/rust#53668 for more information
error: ambigious use of `&&`
error: ambiguous use of `&&`
--> $DIR/syntax-ambiguity-2015.rs:36:22
|
LL | while let true = (1 == 2) && false { }

View File

@ -19,22 +19,22 @@ fn main() {
use std::ops::Range;
if let Range { start: _, end: _ } = true..true && false { }
//~^ ERROR ambigious use of `&&`
//~^ ERROR ambiguous use of `&&`
if let Range { start: _, end: _ } = true..true || false { }
//~^ ERROR ambigious use of `||`
//~^ ERROR ambiguous use of `||`
while let Range { start: _, end: _ } = true..true && false { }
//~^ ERROR ambigious use of `&&`
//~^ ERROR ambiguous use of `&&`
while let Range { start: _, end: _ } = true..true || false { }
//~^ ERROR ambigious use of `||`
//~^ ERROR ambiguous use of `||`
if let true = false && false { }
//~^ ERROR ambigious use of `&&`
//~^ ERROR ambiguous use of `&&`
while let true = (1 == 2) && false { }
//~^ ERROR ambigious use of `&&`
//~^ ERROR ambiguous use of `&&`
// The following cases are not an error as parenthesis are used to
// clarify intent:

View File

@ -1,4 +1,4 @@
error: ambigious use of `&&`
error: ambiguous use of `&&`
--> $DIR/syntax-ambiguity-2018.rs:21:47
|
LL | if let Range { start: _, end: _ } = true..true && false { }
@ -7,7 +7,7 @@ LL | if let Range { start: _, end: _ } = true..true && false { }
= note: this will be a error until the `let_chains` feature is stabilized
= note: see rust-lang/rust#53668 for more information
error: ambigious use of `||`
error: ambiguous use of `||`
--> $DIR/syntax-ambiguity-2018.rs:24:47
|
LL | if let Range { start: _, end: _ } = true..true || false { }
@ -16,7 +16,7 @@ LL | if let Range { start: _, end: _ } = true..true || false { }
= note: this will be a error until the `let_chains` feature is stabilized
= note: see rust-lang/rust#53668 for more information
error: ambigious use of `&&`
error: ambiguous use of `&&`
--> $DIR/syntax-ambiguity-2018.rs:27:50
|
LL | while let Range { start: _, end: _ } = true..true && false { }
@ -25,7 +25,7 @@ LL | while let Range { start: _, end: _ } = true..true && false { }
= note: this will be a error until the `let_chains` feature is stabilized
= note: see rust-lang/rust#53668 for more information
error: ambigious use of `||`
error: ambiguous use of `||`
--> $DIR/syntax-ambiguity-2018.rs:30:50
|
LL | while let Range { start: _, end: _ } = true..true || false { }
@ -34,7 +34,7 @@ LL | while let Range { start: _, end: _ } = true..true || false { }
= note: this will be a error until the `let_chains` feature is stabilized
= note: see rust-lang/rust#53668 for more information
error: ambigious use of `&&`
error: ambiguous use of `&&`
--> $DIR/syntax-ambiguity-2018.rs:33:19
|
LL | if let true = false && false { }
@ -43,7 +43,7 @@ LL | if let true = false && false { }
= note: this will be a error until the `let_chains` feature is stabilized
= note: see rust-lang/rust#53668 for more information
error: ambigious use of `&&`
error: ambiguous use of `&&`
--> $DIR/syntax-ambiguity-2018.rs:36:22
|
LL | while let true = (1 == 2) && false { }

View File

@ -24,7 +24,7 @@ use std::fmt::{Debug, Display};
// • one generic parameter (T) bound inline
// • one parameter (T) with a where clause
// • two parameters (T and U), both bound inline
// • two paramters (T and U), one bound inline, one with a where clause
// • two parameters (T and U), one bound inline, one with a where clause
// • two parameters (T and U), both with where clauses
//
// —and for every permutation of 0, 1, or 2 lifetimes to outlive and 0 or 1

View File

@ -24,7 +24,7 @@ use std::fmt::{Debug, Display};
// • one generic parameter (T) bound inline
// • one parameter (T) with a where clause
// • two parameters (T and U), both bound inline
// • two paramters (T and U), one bound inline, one with a where clause
// • two parameters (T and U), one bound inline, one with a where clause
// • two parameters (T and U), both with where clauses
//
// —and for every permutation of 0, 1, or 2 lifetimes to outlive and 0 or 1

View File

@ -12,7 +12,7 @@
// Regression test for #52050: when inserting the blanket impl `I`
// into the tree, we had to replace the child node for `Foo`, which
// led to the struture of the tree being messed up.
// led to the structure of the tree being messed up.
use std::iter::Iterator;

View File

@ -20,10 +20,9 @@ error[E0106]: missing lifetime specifier
--> $DIR/underscore-lifetime-binders.rs:20:29
|
LL | fn meh() -> Box<for<'_> Meh<'_>> //~ ERROR cannot be used here
| ^^ expected lifetime parameter
| ^^ help: consider giving it a 'static lifetime: `'static`
|
= help: this function's return type contains a borrowed value, but there is no value for it to be borrowed from
= help: consider giving it a 'static lifetime
error[E0106]: missing lifetime specifier
--> $DIR/underscore-lifetime-binders.rs:26:35

@ -1 +1 @@
Subproject commit 5afdf8b78507ddf015d192858aef56e72c17de16
Subproject commit b1d0343749bdc87e5cbbe7f1aeaa9d2a2c9dbc5b

View File

@ -163,7 +163,7 @@ fn check_cfgs(contents: &mut String, file: &Path,
fn find_test_mod(contents: &str) -> usize {
if let Some(mod_tests_idx) = contents.find("mod tests") {
// Also capture a previos line indicating "mod tests" in cfg-ed out
// Also capture a previous line indicating "mod tests" in cfg-ed out
let prev_newline_idx = contents[..mod_tests_idx].rfind('\n').unwrap_or(mod_tests_idx);
let prev_newline_idx = contents[..prev_newline_idx].rfind('\n');
if let Some(nl) = prev_newline_idx {