fix most compiler/ doctests
This commit is contained in:
parent
bf611439e3
commit
7907385999
116 changed files with 666 additions and 609 deletions
|
@ -573,7 +573,7 @@ pub struct Block {
|
|||
pub span: Span,
|
||||
pub tokens: Option<LazyTokenStream>,
|
||||
/// The following *isn't* a parse error, but will cause multiple errors in following stages.
|
||||
/// ```
|
||||
/// ```compile_fail
|
||||
/// let x = {
|
||||
/// foo: var
|
||||
/// };
|
||||
|
|
|
@ -615,7 +615,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||
}
|
||||
|
||||
/// Desugar `<expr>.await` into:
|
||||
/// ```rust
|
||||
/// ```ignore (pseudo-rust)
|
||||
/// match ::std::future::IntoFuture::into_future(<expr>) {
|
||||
/// mut __awaitee => loop {
|
||||
/// match unsafe { ::std::future::Future::poll(
|
||||
|
@ -1325,7 +1325,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||
}
|
||||
|
||||
/// Desugar `ExprForLoop` from: `[opt_ident]: for <pat> in <head> <body>` into:
|
||||
/// ```rust
|
||||
/// ```ignore (pseudo-rust)
|
||||
/// {
|
||||
/// let result = match IntoIterator::into_iter(<head>) {
|
||||
/// mut iter => {
|
||||
|
@ -1436,7 +1436,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||
}
|
||||
|
||||
/// Desugar `ExprKind::Try` from: `<expr>?` into:
|
||||
/// ```rust
|
||||
/// ```ignore (pseudo-rust)
|
||||
/// match Try::branch(<expr>) {
|
||||
/// ControlFlow::Continue(val) => #[allow(unreachable_code)] val,,
|
||||
/// ControlFlow::Break(residual) =>
|
||||
|
|
|
@ -934,7 +934,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
|||
|
||||
/// Given an associated type constraint like one of these:
|
||||
///
|
||||
/// ```
|
||||
/// ```ignore (illustrative)
|
||||
/// T: Iterator<Item: Debug>
|
||||
/// ^^^^^^^^^^^
|
||||
/// T: Iterator<Item = Debug>
|
||||
|
|
|
@ -68,20 +68,20 @@
|
|||
//! will be made to flow subsequent breaks together onto lines. Inconsistent
|
||||
//! is the opposite. Inconsistent breaking example would be, say:
|
||||
//!
|
||||
//! ```
|
||||
//! ```ignore (illustrative)
|
||||
//! foo(hello, there, good, friends)
|
||||
//! ```
|
||||
//!
|
||||
//! breaking inconsistently to become
|
||||
//!
|
||||
//! ```
|
||||
//! ```ignore (illustrative)
|
||||
//! foo(hello, there,
|
||||
//! good, friends);
|
||||
//! ```
|
||||
//!
|
||||
//! whereas a consistent breaking would yield:
|
||||
//!
|
||||
//! ```
|
||||
//! ```ignore (illustrative)
|
||||
//! foo(hello,
|
||||
//! there,
|
||||
//! good,
|
||||
|
@ -153,14 +153,14 @@ enum IndentStyle {
|
|||
/// Vertically aligned under whatever column this block begins at.
|
||||
///
|
||||
/// fn demo(arg1: usize,
|
||||
/// arg2: usize);
|
||||
/// arg2: usize) {}
|
||||
Visual,
|
||||
/// Indented relative to the indentation level of the previous line.
|
||||
///
|
||||
/// fn demo(
|
||||
/// arg1: usize,
|
||||
/// arg2: usize,
|
||||
/// );
|
||||
/// ) {}
|
||||
Block { offset: isize },
|
||||
}
|
||||
|
||||
|
|
|
@ -896,20 +896,23 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
|||
///
|
||||
/// In the simplest case, where there are no unions involved, if a mutable borrow of `x` is
|
||||
/// attempted while a shared borrow is live, then this function will return:
|
||||
///
|
||||
/// ```
|
||||
/// ("x", "", "")
|
||||
///
|
||||
/// # ;
|
||||
/// ```
|
||||
/// In the simple union case, if a mutable borrow of a union field `x.z` is attempted while
|
||||
/// a shared borrow of another field `x.y`, then this function will return:
|
||||
///
|
||||
/// ```
|
||||
/// ("x", "x.z", "x.y")
|
||||
///
|
||||
/// # ;
|
||||
/// ```
|
||||
/// In the more complex union case, where the union is a field of a struct, then if a mutable
|
||||
/// borrow of a union field in a struct `x.u.z` is attempted while a shared borrow of
|
||||
/// another field `x.u.y`, then this function will return:
|
||||
///
|
||||
/// ```
|
||||
/// ("x.u", "x.u.z", "x.u.y")
|
||||
///
|
||||
/// # ;
|
||||
/// ```
|
||||
/// This is used when creating error messages like below:
|
||||
///
|
||||
/// ```text
|
||||
|
|
|
@ -259,7 +259,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
|
|||
/// Report an error because the universal region `fr` was required to outlive
|
||||
/// `outlived_fr` but it is not known to do so. For example:
|
||||
///
|
||||
/// ```
|
||||
/// ```compile_fail,E0312
|
||||
/// fn foo<'a, 'b>(x: &'a u32) -> &'b u32 { x }
|
||||
/// ```
|
||||
///
|
||||
|
|
|
@ -210,7 +210,7 @@ impl<'tcx> MirBorrowckCtxt<'_, 'tcx> {
|
|||
/// Suppose we are trying to give a name to the lifetime of the
|
||||
/// reference `x`:
|
||||
///
|
||||
/// ```
|
||||
/// ```ignore (pseudo-rust)
|
||||
/// fn foo(x: &u32) { .. }
|
||||
/// ```
|
||||
///
|
||||
|
@ -746,7 +746,7 @@ impl<'tcx> MirBorrowckCtxt<'_, 'tcx> {
|
|||
/// e.g. given the function:
|
||||
///
|
||||
/// ```
|
||||
/// async fn foo() -> i32 {}
|
||||
/// async fn foo() -> i32 { 2 }
|
||||
/// ```
|
||||
///
|
||||
/// this function, given the lowered return type of `foo`, an [`OpaqueDef`] that implements `Future<Output=i32>`,
|
||||
|
|
|
@ -169,7 +169,7 @@ where
|
|||
/// Returns the "choice regions" for a given member
|
||||
/// constraint. This is the `R1..Rn` from a constraint like:
|
||||
///
|
||||
/// ```
|
||||
/// ```text
|
||||
/// R0 member of [R1..Rn]
|
||||
/// ```
|
||||
crate fn choice_regions(&self, pci: NllMemberConstraintIndex) -> &[ty::RegionVid] {
|
||||
|
@ -195,14 +195,14 @@ where
|
|||
///
|
||||
/// Before:
|
||||
///
|
||||
/// ```
|
||||
/// ```text
|
||||
/// target_list: A -> B -> C -> (None)
|
||||
/// source_list: D -> E -> F -> (None)
|
||||
/// ```
|
||||
///
|
||||
/// After:
|
||||
///
|
||||
/// ```
|
||||
/// ```text
|
||||
/// target_list: A -> B -> C -> D -> E -> F -> (None)
|
||||
/// ```
|
||||
fn append_list(
|
||||
|
|
|
@ -436,14 +436,14 @@ impl<'tcx> RegionInferenceContext<'tcx> {
|
|||
/// minimum values.
|
||||
///
|
||||
/// For example:
|
||||
///
|
||||
/// fn foo<'a, 'b>(..) where 'a: 'b
|
||||
///
|
||||
/// ```
|
||||
/// fn foo<'a, 'b>( /* ... */ ) where 'a: 'b { /* ... */ }
|
||||
/// ```
|
||||
/// would initialize two variables like so:
|
||||
///
|
||||
/// ```ignore (illustrative)
|
||||
/// R0 = { CFG, R0 } // 'a
|
||||
/// R1 = { CFG, R0, R1 } // 'b
|
||||
///
|
||||
/// ```
|
||||
/// Here, R0 represents `'a`, and it contains (a) the entire CFG
|
||||
/// and (b) any universally quantified regions that it outlives,
|
||||
/// which in this case is just itself. R1 (`'b`) in contrast also
|
||||
|
@ -1310,9 +1310,9 @@ impl<'tcx> RegionInferenceContext<'tcx> {
|
|||
/// whether any of the constraints were too strong. In particular,
|
||||
/// we want to check for a case where a universally quantified
|
||||
/// region exceeded its bounds. Consider:
|
||||
///
|
||||
/// ```compile_fail,E0312
|
||||
/// fn foo<'a, 'b>(x: &'a u32) -> &'b u32 { x }
|
||||
///
|
||||
/// ```
|
||||
/// In this case, returning `x` requires `&'a u32 <: &'b u32`
|
||||
/// and hence we establish (transitively) a constraint that
|
||||
/// `'a: 'b`. The `propagate_constraints` code above will
|
||||
|
@ -1366,9 +1366,9 @@ impl<'tcx> RegionInferenceContext<'tcx> {
|
|||
/// <https://smallcultfollowing.com/babysteps/blog/2019/01/17/polonius-and-region-errors/>
|
||||
///
|
||||
/// In the canonical example
|
||||
///
|
||||
/// ```compile_fail,E0312
|
||||
/// fn foo<'a, 'b>(x: &'a u32) -> &'b u32 { x }
|
||||
///
|
||||
/// ```
|
||||
/// returning `x` requires `&'a u32 <: &'b u32` and hence we establish (transitively) a
|
||||
/// constraint that `'a: 'b`. It is an error that we have no evidence that this
|
||||
/// constraint holds.
|
||||
|
|
|
@ -971,7 +971,7 @@ pub enum Locations {
|
|||
/// things like the type of the return slot. Consider this
|
||||
/// example:
|
||||
///
|
||||
/// ```
|
||||
/// ```compile_fail,E0515
|
||||
/// fn foo<'a>(x: &'a u32) -> &'a u32 {
|
||||
/// let y = 22;
|
||||
/// return &y; // error
|
||||
|
|
|
@ -187,12 +187,12 @@ pub enum RegionClassification {
|
|||
///
|
||||
/// Consider this example:
|
||||
///
|
||||
/// ```
|
||||
/// ```ignore (pseudo-rust)
|
||||
/// fn foo<'a, 'b>(a: &'a u32, b: &'b u32, c: &'static u32) {
|
||||
/// let closure = for<'x> |x: &'x u32| { .. };
|
||||
/// ^^^^^^^ pretend this were legal syntax
|
||||
/// for declaring a late-bound region in
|
||||
/// a closure signature
|
||||
/// // ^^^^^^^ pretend this were legal syntax
|
||||
/// // for declaring a late-bound region in
|
||||
/// // a closure signature
|
||||
/// }
|
||||
/// ```
|
||||
///
|
||||
|
|
|
@ -5,14 +5,14 @@
|
|||
//!
|
||||
//! For example, a type like:
|
||||
//!
|
||||
//! ```
|
||||
//! ```ignore (old code)
|
||||
//! #[derive(RustcEncodable, RustcDecodable)]
|
||||
//! struct Node { id: usize }
|
||||
//! ```
|
||||
//!
|
||||
//! would generate two implementations like:
|
||||
//!
|
||||
//! ```
|
||||
//! ```ignore (old code)
|
||||
//! # struct Node { id: usize }
|
||||
//! impl<S: Encoder<E>, E> Encodable<S, E> for Node {
|
||||
//! fn encode(&self, s: &mut S) -> Result<(), E> {
|
||||
|
@ -40,7 +40,7 @@
|
|||
//! Other interesting scenarios are when the item has type parameters or
|
||||
//! references other non-built-in types. A type definition like:
|
||||
//!
|
||||
//! ```
|
||||
//! ```ignore (old code)
|
||||
//! # #[derive(RustcEncodable, RustcDecodable)]
|
||||
//! # struct Span;
|
||||
//! #[derive(RustcEncodable, RustcDecodable)]
|
||||
|
@ -49,7 +49,7 @@
|
|||
//!
|
||||
//! would yield functions like:
|
||||
//!
|
||||
//! ```
|
||||
//! ```ignore (old code)
|
||||
//! # #[derive(RustcEncodable, RustcDecodable)]
|
||||
//! # struct Span;
|
||||
//! # struct Spanned<T> { node: T, span: Span }
|
||||
|
|
|
@ -1006,9 +1006,11 @@ impl<'a> MethodDef<'a> {
|
|||
/// }
|
||||
/// }
|
||||
/// }
|
||||
///
|
||||
/// // or if A is repr(packed) - note fields are matched by-value
|
||||
/// // instead of by-reference.
|
||||
/// ```
|
||||
/// or if A is repr(packed) - note fields are matched by-value
|
||||
/// instead of by-reference.
|
||||
/// ```
|
||||
/// # struct A { x: i32, y: i32 }
|
||||
/// impl PartialEq for A {
|
||||
/// fn eq(&self, other: &A) -> bool {
|
||||
/// match *self {
|
||||
|
@ -1126,14 +1128,15 @@ impl<'a> MethodDef<'a> {
|
|||
/// // is equivalent to
|
||||
///
|
||||
/// impl PartialEq for A {
|
||||
/// fn eq(&self, other: &A) -> ::bool {
|
||||
/// fn eq(&self, other: &A) -> bool {
|
||||
/// use A::*;
|
||||
/// match (&*self, &*other) {
|
||||
/// (&A1, &A1) => true,
|
||||
/// (&A2(ref self_0),
|
||||
/// &A2(ref __arg_1_0)) => (*self_0).eq(&(*__arg_1_0)),
|
||||
/// _ => {
|
||||
/// let __self_vi = match *self { A1(..) => 0, A2(..) => 1 };
|
||||
/// let __arg_1_vi = match *other { A1(..) => 0, A2(..) => 1 };
|
||||
/// let __self_vi = match *self { A1 => 0, A2(..) => 1 };
|
||||
/// let __arg_1_vi = match *other { A1 => 0, A2(..) => 1 };
|
||||
/// false
|
||||
/// }
|
||||
/// }
|
||||
|
|
|
@ -249,7 +249,7 @@ fn generate_test_harness(
|
|||
///
|
||||
/// By default this expands to
|
||||
///
|
||||
/// ```
|
||||
/// ```ignore UNSOLVED (I think I still need guidance for this one. Is it correct? Do we try to make it run? How do we nicely fill it out?)
|
||||
/// #[rustc_main]
|
||||
/// pub fn main() {
|
||||
/// extern crate test;
|
||||
|
|
|
@ -27,9 +27,9 @@ The module is thus driven from an outside client with functions like
|
|||
Internally the module will try to reuse already created metadata by
|
||||
utilizing a cache. The way to get a shared metadata node when needed is
|
||||
thus to just call the corresponding function in this module:
|
||||
|
||||
let file_metadata = file_metadata(cx, file);
|
||||
|
||||
```ignore (illustrative)
|
||||
let file_metadata = file_metadata(cx, file);
|
||||
```
|
||||
The function will take care of probing the cache for an existing node for
|
||||
that exact file path.
|
||||
|
||||
|
@ -63,7 +63,7 @@ struct List {
|
|||
|
||||
will generate the following callstack with a naive DFS algorithm:
|
||||
|
||||
```
|
||||
```ignore (illustrative)
|
||||
describe(t = List)
|
||||
describe(t = i32)
|
||||
describe(t = Option<Box<List>>)
|
||||
|
|
|
@ -23,7 +23,8 @@
|
|||
//! `computed` does not change accidentally (e.g. somebody might accidentally call
|
||||
//! `foo.computed.mutate()`). This is what `Frozen` is for. We can do the following:
|
||||
//!
|
||||
//! ```rust
|
||||
//! ```
|
||||
//! # struct Bar {}
|
||||
//! use rustc_data_structures::frozen::Frozen;
|
||||
//!
|
||||
//! struct Foo {
|
||||
|
|
|
@ -202,7 +202,7 @@ impl<O> Node<O> {
|
|||
/// with this node.
|
||||
///
|
||||
/// The non-`Error` state transitions are as follows.
|
||||
/// ```
|
||||
/// ```text
|
||||
/// (Pre-creation)
|
||||
/// |
|
||||
/// | register_obligation_at() (called by process_obligations() and
|
||||
|
|
|
@ -25,9 +25,8 @@ of the reference because the backing allocation of the vector does not change.
|
|||
This library enables this safe usage by keeping the owner and the reference
|
||||
bundled together in a wrapper type that ensure that lifetime constraint:
|
||||
|
||||
```rust
|
||||
# extern crate owning_ref;
|
||||
# use owning_ref::OwningRef;
|
||||
```
|
||||
# use rustc_data_structures::owning_ref::OwningRef;
|
||||
# fn main() {
|
||||
fn return_owned_and_referenced() -> OwningRef<Vec<u8>, [u8]> {
|
||||
let v = vec![1, 2, 3, 4];
|
||||
|
@ -56,8 +55,7 @@ See the documentation around `OwningHandle` for more details.
|
|||
## Basics
|
||||
|
||||
```
|
||||
extern crate owning_ref;
|
||||
use owning_ref::BoxRef;
|
||||
use rustc_data_structures::owning_ref::BoxRef;
|
||||
|
||||
fn main() {
|
||||
// Create an array owned by a Box.
|
||||
|
@ -78,8 +76,7 @@ fn main() {
|
|||
## Caching a reference to a struct field
|
||||
|
||||
```
|
||||
extern crate owning_ref;
|
||||
use owning_ref::BoxRef;
|
||||
use rustc_data_structures::owning_ref::BoxRef;
|
||||
|
||||
fn main() {
|
||||
struct Foo {
|
||||
|
@ -106,8 +103,7 @@ fn main() {
|
|||
## Caching a reference to an entry in a vector
|
||||
|
||||
```
|
||||
extern crate owning_ref;
|
||||
use owning_ref::VecRef;
|
||||
use rustc_data_structures::owning_ref::VecRef;
|
||||
|
||||
fn main() {
|
||||
let v = VecRef::new(vec![1, 2, 3, 4, 5]).map(|v| &v[3]);
|
||||
|
@ -118,8 +114,7 @@ fn main() {
|
|||
## Caching a subslice of a String
|
||||
|
||||
```
|
||||
extern crate owning_ref;
|
||||
use owning_ref::StringRef;
|
||||
use rustc_data_structures::owning_ref::StringRef;
|
||||
|
||||
fn main() {
|
||||
let s = StringRef::new("hello world".to_owned())
|
||||
|
@ -132,8 +127,7 @@ fn main() {
|
|||
## Reference counted slices that share ownership of the backing storage
|
||||
|
||||
```
|
||||
extern crate owning_ref;
|
||||
use owning_ref::RcRef;
|
||||
use rustc_data_structures::owning_ref::RcRef;
|
||||
use std::rc::Rc;
|
||||
|
||||
fn main() {
|
||||
|
@ -155,8 +149,7 @@ fn main() {
|
|||
## Atomic reference counted slices that share ownership of the backing storage
|
||||
|
||||
```
|
||||
extern crate owning_ref;
|
||||
use owning_ref::ArcRef;
|
||||
use rustc_data_structures::owning_ref::ArcRef;
|
||||
use std::sync::Arc;
|
||||
|
||||
fn main() {
|
||||
|
@ -188,8 +181,7 @@ fn main() {
|
|||
## References into RAII locks
|
||||
|
||||
```
|
||||
extern crate owning_ref;
|
||||
use owning_ref::RefRef;
|
||||
use rustc_data_structures::owning_ref::RefRef;
|
||||
use std::cell::{RefCell, Ref};
|
||||
|
||||
fn main() {
|
||||
|
@ -219,8 +211,7 @@ When the owned container implements `DerefMut`, it is also possible to make
|
|||
a _mutable owning reference_. (e.g., with `Box`, `RefMut`, `MutexGuard`)
|
||||
|
||||
```
|
||||
extern crate owning_ref;
|
||||
use owning_ref::RefMutRefMut;
|
||||
use rustc_data_structures::owning_ref::RefMutRefMut;
|
||||
use std::cell::{RefCell, RefMut};
|
||||
|
||||
fn main() {
|
||||
|
@ -326,8 +317,7 @@ impl<O, T: ?Sized> OwningRef<O, T> {
|
|||
///
|
||||
/// # Example
|
||||
/// ```
|
||||
/// extern crate owning_ref;
|
||||
/// use owning_ref::OwningRef;
|
||||
/// use rustc_data_structures::owning_ref::OwningRef;
|
||||
///
|
||||
/// fn main() {
|
||||
/// let owning_ref = OwningRef::new(Box::new(42));
|
||||
|
@ -362,8 +352,7 @@ impl<O, T: ?Sized> OwningRef<O, T> {
|
|||
///
|
||||
/// # Example
|
||||
/// ```
|
||||
/// extern crate owning_ref;
|
||||
/// use owning_ref::OwningRef;
|
||||
/// use rustc_data_structures::owning_ref::OwningRef;
|
||||
///
|
||||
/// fn main() {
|
||||
/// let owning_ref = OwningRef::new(Box::new([1, 2, 3, 4]));
|
||||
|
@ -390,8 +379,7 @@ impl<O, T: ?Sized> OwningRef<O, T> {
|
|||
///
|
||||
/// # Example
|
||||
/// ```
|
||||
/// extern crate owning_ref;
|
||||
/// use owning_ref::OwningRef;
|
||||
/// use rustc_data_structures::owning_ref::OwningRef;
|
||||
///
|
||||
/// fn main() {
|
||||
/// let owning_ref = OwningRef::new(Box::new([1, 2, 3, 4]));
|
||||
|
@ -441,8 +429,7 @@ impl<O, T: ?Sized> OwningRef<O, T> {
|
|||
///
|
||||
/// # Example
|
||||
/// ```
|
||||
/// extern crate owning_ref;
|
||||
/// use owning_ref::{OwningRef, Erased};
|
||||
/// use rustc_data_structures::owning_ref::{OwningRef, Erased};
|
||||
///
|
||||
/// fn main() {
|
||||
/// // N.B., using the concrete types here for explicitness.
|
||||
|
@ -460,7 +447,7 @@ impl<O, T: ?Sized> OwningRef<O, T> {
|
|||
/// let owning_ref_b: OwningRef<Box<Vec<(i32, bool)>>, i32>
|
||||
/// = owning_ref_b.map(|a| &a[1].0);
|
||||
///
|
||||
/// let owning_refs: [OwningRef<Box<Erased>, i32>; 2]
|
||||
/// let owning_refs: [OwningRef<Box<dyn Erased>, i32>; 2]
|
||||
/// = [owning_ref_a.erase_owner(), owning_ref_b.erase_owner()];
|
||||
///
|
||||
/// assert_eq!(*owning_refs[0], 1);
|
||||
|
@ -516,8 +503,7 @@ impl<O, T: ?Sized> OwningRefMut<O, T> {
|
|||
///
|
||||
/// # Example
|
||||
/// ```
|
||||
/// extern crate owning_ref;
|
||||
/// use owning_ref::OwningRefMut;
|
||||
/// use rustc_data_structures::owning_ref::OwningRefMut;
|
||||
///
|
||||
/// fn main() {
|
||||
/// let owning_ref_mut = OwningRefMut::new(Box::new(42));
|
||||
|
@ -552,8 +538,7 @@ impl<O, T: ?Sized> OwningRefMut<O, T> {
|
|||
///
|
||||
/// # Example
|
||||
/// ```
|
||||
/// extern crate owning_ref;
|
||||
/// use owning_ref::OwningRefMut;
|
||||
/// use rustc_data_structures::owning_ref::OwningRefMut;
|
||||
///
|
||||
/// fn main() {
|
||||
/// let owning_ref_mut = OwningRefMut::new(Box::new([1, 2, 3, 4]));
|
||||
|
@ -580,8 +565,7 @@ impl<O, T: ?Sized> OwningRefMut<O, T> {
|
|||
///
|
||||
/// # Example
|
||||
/// ```
|
||||
/// extern crate owning_ref;
|
||||
/// use owning_ref::OwningRefMut;
|
||||
/// use rustc_data_structures::owning_ref::OwningRefMut;
|
||||
///
|
||||
/// fn main() {
|
||||
/// let owning_ref_mut = OwningRefMut::new(Box::new([1, 2, 3, 4]));
|
||||
|
@ -608,8 +592,7 @@ impl<O, T: ?Sized> OwningRefMut<O, T> {
|
|||
///
|
||||
/// # Example
|
||||
/// ```
|
||||
/// extern crate owning_ref;
|
||||
/// use owning_ref::OwningRefMut;
|
||||
/// use rustc_data_structures::owning_ref::OwningRefMut;
|
||||
///
|
||||
/// fn main() {
|
||||
/// let owning_ref_mut = OwningRefMut::new(Box::new([1, 2, 3, 4]));
|
||||
|
@ -638,8 +621,7 @@ impl<O, T: ?Sized> OwningRefMut<O, T> {
|
|||
///
|
||||
/// # Example
|
||||
/// ```
|
||||
/// extern crate owning_ref;
|
||||
/// use owning_ref::OwningRefMut;
|
||||
/// use rustc_data_structures::owning_ref::OwningRefMut;
|
||||
///
|
||||
/// fn main() {
|
||||
/// let owning_ref_mut = OwningRefMut::new(Box::new([1, 2, 3, 4]));
|
||||
|
@ -689,8 +671,7 @@ impl<O, T: ?Sized> OwningRefMut<O, T> {
|
|||
///
|
||||
/// # Example
|
||||
/// ```
|
||||
/// extern crate owning_ref;
|
||||
/// use owning_ref::{OwningRefMut, Erased};
|
||||
/// use rustc_data_structures::owning_ref::{OwningRefMut, Erased};
|
||||
///
|
||||
/// fn main() {
|
||||
/// // N.B., using the concrete types here for explicitness.
|
||||
|
@ -708,7 +689,7 @@ impl<O, T: ?Sized> OwningRefMut<O, T> {
|
|||
/// let owning_ref_mut_b: OwningRefMut<Box<Vec<(i32, bool)>>, i32>
|
||||
/// = owning_ref_mut_b.map_mut(|a| &mut a[1].0);
|
||||
///
|
||||
/// let owning_refs_mut: [OwningRefMut<Box<Erased>, i32>; 2]
|
||||
/// let owning_refs_mut: [OwningRefMut<Box<dyn Erased>, i32>; 2]
|
||||
/// = [owning_ref_mut_a.erase_owner(), owning_ref_mut_b.erase_owner()];
|
||||
///
|
||||
/// assert_eq!(*owning_refs_mut[0], 1);
|
||||
|
|
|
@ -45,7 +45,8 @@ pub unsafe trait Pointer: Deref {
|
|||
/// case you'll need to manually figure out what the right type to pass to
|
||||
/// align_of is.
|
||||
///
|
||||
/// ```rust
|
||||
/// ```ignore UNSOLVED (what to do about the Self)
|
||||
/// # use std::ops::Deref;
|
||||
/// std::mem::align_of::<<Self as Deref>::Target>().trailing_zeros() as usize;
|
||||
/// ```
|
||||
const BITS: usize;
|
||||
|
|
|
@ -282,7 +282,7 @@ impl<T: Eq + Hash + Copy> TransitiveRelation<T> {
|
|||
/// (where the relation is encoding the `<=` relation for the lattice).
|
||||
/// So e.g., if the relation is `->` and we have
|
||||
///
|
||||
/// ```
|
||||
/// ```text
|
||||
/// a -> b -> d -> f
|
||||
/// | ^
|
||||
/// +--> c -> e ---+
|
||||
|
|
|
@ -100,7 +100,7 @@ pub struct CodeSuggestion {
|
|||
/// `foo.bar` might be replaced with `a.b` or `x.y` by replacing
|
||||
/// `foo` and `bar` on their own:
|
||||
///
|
||||
/// ```
|
||||
/// ```ignore (illustrative)
|
||||
/// vec![
|
||||
/// Substitution { parts: vec![(0..3, "a"), (4..7, "b")] },
|
||||
/// Substitution { parts: vec![(0..3, "x"), (4..7, "y")] },
|
||||
|
@ -109,7 +109,7 @@ pub struct CodeSuggestion {
|
|||
///
|
||||
/// or by replacing the entire span:
|
||||
///
|
||||
/// ```
|
||||
/// ```ignore (illustrative)
|
||||
/// vec![
|
||||
/// Substitution { parts: vec![(0..7, "a.b")] },
|
||||
/// Substitution { parts: vec![(0..7, "x.y")] },
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
//!
|
||||
//! ## Meta-variables must not be bound twice
|
||||
//!
|
||||
//! ```
|
||||
//! ```compile_fail
|
||||
//! macro_rules! foo { ($x:tt $x:tt) => { $x }; }
|
||||
//! ```
|
||||
//!
|
||||
|
@ -604,9 +604,9 @@ fn check_ops_is_prefix(
|
|||
/// Kleene operators of its binder as a prefix.
|
||||
///
|
||||
/// Consider $i in the following example:
|
||||
///
|
||||
/// ```ignore (illustrative)
|
||||
/// ( $( $i:ident = $($j:ident),+ );* ) => { $($( $i += $j; )+)* }
|
||||
///
|
||||
/// ```
|
||||
/// It occurs under the Kleene stack ["*", "+"] and is bound under ["*"] only.
|
||||
///
|
||||
/// Arguments:
|
||||
|
|
|
@ -320,7 +320,8 @@ pub(super) fn count_metavar_decls(matcher: &[TokenTree]) -> usize {
|
|||
///
|
||||
/// Then, the tree will have the following shape:
|
||||
///
|
||||
/// ```rust
|
||||
/// ```ignore (private-internal)
|
||||
/// # use NamedMatch::*;
|
||||
/// MatchedSeq([
|
||||
/// MatchedSeq([
|
||||
/// MatchedNonterminal(a),
|
||||
|
|
|
@ -312,6 +312,7 @@ pub enum Res<Id = hir::HirId> {
|
|||
/// HACK(min_const_generics): self types also have an optional requirement to **not** mention
|
||||
/// any generic parameters to allow the following with `min_const_generics`:
|
||||
/// ```
|
||||
/// # struct Foo;
|
||||
/// impl Foo { fn test() -> [u8; std::mem::size_of::<Self>()] { todo!() } }
|
||||
///
|
||||
/// struct Bar([u8; baz::<Self>()]);
|
||||
|
|
|
@ -49,15 +49,15 @@ pub enum ParamName {
|
|||
/// Synthetic name generated when user elided a lifetime in an impl header.
|
||||
///
|
||||
/// E.g., the lifetimes in cases like these:
|
||||
///
|
||||
/// ```ignore (fragment)
|
||||
/// impl Foo for &u32
|
||||
/// impl Foo<'_> for u32
|
||||
///
|
||||
/// ```
|
||||
/// in that case, we rewrite to
|
||||
///
|
||||
/// ```ignore (fragment)
|
||||
/// impl<'f> Foo for &'f u32
|
||||
/// impl<'f> Foo<'f> for u32
|
||||
///
|
||||
/// ```
|
||||
/// where `'f` is something like `Fresh(0)`. The indices are
|
||||
/// unique per impl, but not necessarily continuous.
|
||||
Fresh(LocalDefId),
|
||||
|
@ -1082,7 +1082,7 @@ pub enum PatKind<'hir> {
|
|||
/// If `slice` exists, then `after` can be non-empty.
|
||||
///
|
||||
/// The representation for e.g., `[a, b, .., c, d]` is:
|
||||
/// ```
|
||||
/// ```ignore (illustrative)
|
||||
/// PatKind::Slice([Binding(a), Binding(b)], Some(Wild), [Binding(c), Binding(d)])
|
||||
/// ```
|
||||
Slice(&'hir [Pat<'hir>], Option<&'hir Pat<'hir>>, &'hir [Pat<'hir>]),
|
||||
|
@ -2247,7 +2247,7 @@ pub const FN_OUTPUT_NAME: Symbol = sym::Output;
|
|||
/// wouldn't it be better to make the `ty` field an enum like the
|
||||
/// following?
|
||||
///
|
||||
/// ```
|
||||
/// ```ignore (pseudo-rust)
|
||||
/// enum TypeBindingKind {
|
||||
/// Equals(...),
|
||||
/// Binding(...),
|
||||
|
|
|
@ -22,7 +22,7 @@
|
|||
//!
|
||||
//! Example:
|
||||
//!
|
||||
//! ```
|
||||
//! ```ignore (needs flags)
|
||||
//! #[rustc_if_this_changed(Hir)]
|
||||
//! fn foo() { }
|
||||
//!
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
//! The user adds annotations to the crate of the following form:
|
||||
//!
|
||||
//! ```
|
||||
//! # #![feature(rustc_attrs)]
|
||||
//! #![rustc_partition_reused(module="spike", cfg="rpass2")]
|
||||
//! #![rustc_partition_codegened(module="spike-x", cfg="rpass2")]
|
||||
//! ```
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
//! is always the "expected" output from the POV of diagnostics.
|
||||
//!
|
||||
//! Examples:
|
||||
//!
|
||||
//! ```ignore (fragment)
|
||||
//! infcx.at(cause, param_env).sub(a, b)
|
||||
//! // requires that `a <: b`, with `a` considered the "expected" type
|
||||
//!
|
||||
|
@ -15,11 +15,11 @@
|
|||
//!
|
||||
//! infcx.at(cause, param_env).eq(a, b)
|
||||
//! // requires that `a == b`, with `a` considered the "expected" type
|
||||
//!
|
||||
//! ```
|
||||
//! For finer-grained control, you can also do use `trace`:
|
||||
//!
|
||||
//! ```ignore (fragment)
|
||||
//! infcx.at(...).trace(a, b).sub(&c, &d)
|
||||
//!
|
||||
//! ```
|
||||
//! This will set `a` and `b` as the "root" values for
|
||||
//! error-reporting, but actually operate on `c` and `d`. This is
|
||||
//! sometimes useful when the types of `c` and `d` are not traceable
|
||||
|
|
|
@ -87,9 +87,9 @@ impl<'cx, 'tcx> InferCtxt<'cx, 'tcx> {
|
|||
///
|
||||
/// with a mapping M that maps `'?0` to `'static`. But if we found that there
|
||||
/// exists only one possible impl of `Trait`, and it looks like
|
||||
///
|
||||
/// ```ignore (illustrative)
|
||||
/// impl<T> Trait<'static> for T { .. }
|
||||
///
|
||||
/// ```
|
||||
/// then we would prepare a query result R that (among other
|
||||
/// things) includes a mapping to `'?0 := 'static`. When
|
||||
/// canonicalizing this query result R, we would leave this
|
||||
|
|
|
@ -202,7 +202,7 @@ impl<'infcx, 'tcx> InferCtxt<'infcx, 'tcx> {
|
|||
///
|
||||
/// A good example of this is the following:
|
||||
///
|
||||
/// ```rust
|
||||
/// ```compile_fail,E0308
|
||||
/// #![feature(generic_const_exprs)]
|
||||
///
|
||||
/// fn bind<const N: usize>(value: [u8; N]) -> [u8; 3 + 4] {
|
||||
|
|
|
@ -889,7 +889,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
|
|||
///
|
||||
/// For the following code:
|
||||
///
|
||||
/// ```no_run
|
||||
/// ```ignore (illustrative)
|
||||
/// let x: Foo<Bar<Qux>> = foo::<Bar<Qux>>();
|
||||
/// ```
|
||||
///
|
||||
|
@ -1872,7 +1872,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
|
|||
|
||||
/// A possible error is to forget to add `.await` when using futures:
|
||||
///
|
||||
/// ```
|
||||
/// ```compile_fail,E0308
|
||||
/// async fn make_u32() -> u32 {
|
||||
/// 22
|
||||
/// }
|
||||
|
|
|
@ -18,7 +18,7 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
|
|||
///
|
||||
/// Consider a case where we have
|
||||
///
|
||||
/// ```no_run
|
||||
/// ```compile_fail,E0623
|
||||
/// fn foo(x: &mut Vec<&u8>, y: &u8) {
|
||||
/// x.push(y);
|
||||
/// }
|
||||
|
|
|
@ -14,7 +14,7 @@ use rustc_middle::ty::{self, Region, TyCtxt};
|
|||
/// br - the bound region corresponding to the above region which is of type `BrAnon(_)`
|
||||
///
|
||||
/// # Example
|
||||
/// ```
|
||||
/// ```compile_fail,E0623
|
||||
/// fn foo(x: &mut Vec<&u8>, y: &u8)
|
||||
/// { x.push(y); }
|
||||
/// ```
|
||||
|
|
|
@ -159,9 +159,9 @@ pub struct InferCtxtInner<'tcx> {
|
|||
/// outlive the lifetime 'a". These constraints derive from
|
||||
/// instantiated type parameters. So if you had a struct defined
|
||||
/// like
|
||||
///
|
||||
/// ```ignore (illustrative)
|
||||
/// struct Foo<T:'static> { ... }
|
||||
///
|
||||
/// ```
|
||||
/// then in some expression `let x = Foo { ... }` it will
|
||||
/// instantiate the type parameter `T` with a fresh type `$0`. At
|
||||
/// the same time, it will record a region obligation of
|
||||
|
|
|
@ -309,14 +309,22 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
|
|||
/// the same as generating an outlives constraint on `Tc` itself.
|
||||
/// For example, if we had a function like this:
|
||||
///
|
||||
/// ```rust
|
||||
/// ```
|
||||
/// # #![feature(type_alias_impl_trait)]
|
||||
/// # fn main() {}
|
||||
/// # trait Foo<'a> {}
|
||||
/// # impl<'a, T> Foo<'a> for (&'a u32, T) {}
|
||||
/// fn foo<'a, T>(x: &'a u32, y: T) -> impl Foo<'a> {
|
||||
/// (x, y)
|
||||
/// }
|
||||
///
|
||||
/// // Equivalent to:
|
||||
/// # mod dummy { use super::*;
|
||||
/// type FooReturn<'a, T> = impl Foo<'a>;
|
||||
/// fn foo<'a, T>(..) -> FooReturn<'a, T> { .. }
|
||||
/// fn foo<'a, T>(x: &'a u32, y: T) -> FooReturn<'a, T> {
|
||||
/// (x, y)
|
||||
/// }
|
||||
/// # }
|
||||
/// ```
|
||||
///
|
||||
/// then the hidden type `Tc` would be `(&'0 u32, T)` (where `'0`
|
||||
|
@ -602,17 +610,17 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
|
|||
/// Returns `true` if `opaque_hir_id` is a sibling or a child of a sibling of `def_id`.
|
||||
///
|
||||
/// Example:
|
||||
/// ```rust
|
||||
/// ```ignore UNSOLVED (is this a bug?)
|
||||
/// # #![feature(type_alias_impl_trait)]
|
||||
/// pub mod foo {
|
||||
/// pub mod bar {
|
||||
/// pub trait Bar { .. }
|
||||
///
|
||||
/// pub trait Bar { /* ... */ }
|
||||
/// pub type Baz = impl Bar;
|
||||
///
|
||||
/// fn f1() -> Baz { .. }
|
||||
/// # impl Bar for () {}
|
||||
/// fn f1() -> Baz { /* ... */ }
|
||||
/// }
|
||||
///
|
||||
/// fn f2() -> bar::Baz { .. }
|
||||
/// fn f2() -> bar::Baz { /* ... */ }
|
||||
/// }
|
||||
/// ```
|
||||
///
|
||||
|
|
|
@ -103,7 +103,7 @@ impl<'a, 'tcx> OutlivesEnvironment<'tcx> {
|
|||
///
|
||||
/// Example:
|
||||
///
|
||||
/// ```
|
||||
/// ```ignore (pseudo-rust)
|
||||
/// fn foo<T>() {
|
||||
/// callback(for<'a> |x: &'a T| {
|
||||
/// // ^^^^^^^ not legal syntax, but probably should be
|
||||
|
|
|
@ -33,9 +33,9 @@
|
|||
//! Consider:
|
||||
//!
|
||||
//! ```
|
||||
//! fn bar<T>(a: T, b: impl for<'a> Fn(&'a T));
|
||||
//! fn bar<T>(a: T, b: impl for<'a> Fn(&'a T)) {}
|
||||
//! fn foo<T>(x: T) {
|
||||
//! bar(x, |y| { ... })
|
||||
//! bar(x, |y| { /* ... */})
|
||||
//! // ^ closure arg
|
||||
//! }
|
||||
//! ```
|
||||
|
|
|
@ -313,7 +313,7 @@ impl<'cx, 'tcx> VerifyBoundCx<'cx, 'tcx> {
|
|||
///
|
||||
/// It will not, however, work for higher-ranked bounds like:
|
||||
///
|
||||
/// ```rust
|
||||
/// ```compile_fail,E0311
|
||||
/// trait Foo<'a, 'b>
|
||||
/// where for<'x> <Self as Foo<'x, 'b>>::Bar: 'x
|
||||
/// {
|
||||
|
|
|
@ -174,19 +174,19 @@ pub enum GenericKind<'tcx> {
|
|||
/// Describes the things that some `GenericKind` value `G` is known to
|
||||
/// outlive. Each variant of `VerifyBound` can be thought of as a
|
||||
/// function:
|
||||
///
|
||||
/// ```ignore (pseudo-rust)
|
||||
/// fn(min: Region) -> bool { .. }
|
||||
///
|
||||
/// ```
|
||||
/// where `true` means that the region `min` meets that `G: min`.
|
||||
/// (False means nothing.)
|
||||
///
|
||||
/// So, for example, if we have the type `T` and we have in scope that
|
||||
/// `T: 'a` and `T: 'b`, then the verify bound might be:
|
||||
///
|
||||
/// ```ignore (pseudo-rust)
|
||||
/// fn(min: Region) -> bool {
|
||||
/// ('a: min) || ('b: min)
|
||||
/// }
|
||||
///
|
||||
/// ```
|
||||
/// This is described with an `AnyRegion('a, 'b)` node.
|
||||
#[derive(Debug, Clone)]
|
||||
pub enum VerifyBound<'tcx> {
|
||||
|
@ -194,7 +194,7 @@ pub enum VerifyBound<'tcx> {
|
|||
/// following, where `G` is the generic for which this verify
|
||||
/// bound was created:
|
||||
///
|
||||
/// ```rust
|
||||
/// ```ignore (pseudo-rust)
|
||||
/// fn(min) -> bool {
|
||||
/// if G == K {
|
||||
/// B(min)
|
||||
|
@ -218,7 +218,7 @@ pub enum VerifyBound<'tcx> {
|
|||
///
|
||||
/// So we would compile to a verify-bound like
|
||||
///
|
||||
/// ```
|
||||
/// ```ignore (illustrative)
|
||||
/// IfEq(<T as Trait<'a>>::Item, AnyRegion('a))
|
||||
/// ```
|
||||
///
|
||||
|
@ -228,7 +228,7 @@ pub enum VerifyBound<'tcx> {
|
|||
|
||||
/// Given a region `R`, expands to the function:
|
||||
///
|
||||
/// ```
|
||||
/// ```ignore (pseudo-rust)
|
||||
/// fn(min) -> bool {
|
||||
/// R: min
|
||||
/// }
|
||||
|
@ -243,7 +243,7 @@ pub enum VerifyBound<'tcx> {
|
|||
|
||||
/// Given a set of bounds `B`, expands to the function:
|
||||
///
|
||||
/// ```rust
|
||||
/// ```ignore (pseudo-rust)
|
||||
/// fn(min) -> bool {
|
||||
/// exists (b in B) { b(min) }
|
||||
/// }
|
||||
|
@ -255,7 +255,7 @@ pub enum VerifyBound<'tcx> {
|
|||
|
||||
/// Given a set of bounds `B`, expands to the function:
|
||||
///
|
||||
/// ```rust
|
||||
/// ```ignore (pseudo-rust)
|
||||
/// fn(min) -> bool {
|
||||
/// forall (b in B) { b(min) }
|
||||
/// }
|
||||
|
|
|
@ -73,10 +73,10 @@ pub struct TypeVariableStorage<'tcx> {
|
|||
/// table exists only to help with the occurs check. In particular,
|
||||
/// we want to report constraints like these as an occurs check
|
||||
/// violation:
|
||||
///
|
||||
/// ``` text
|
||||
/// ?1 <: ?3
|
||||
/// Box<?3> <: ?1
|
||||
///
|
||||
/// ```
|
||||
/// Without this second table, what would happen in a case like
|
||||
/// this is that we would instantiate `?1` with a generalized
|
||||
/// type like `Box<?6>`. We would then relate `Box<?3> <: Box<?6>`
|
||||
|
@ -287,8 +287,9 @@ impl<'tcx> TypeVariableTable<'_, 'tcx> {
|
|||
/// related via equality or subtyping will yield the same root
|
||||
/// variable (per the union-find algorithm), so `sub_root_var(a)
|
||||
/// == sub_root_var(b)` implies that:
|
||||
///
|
||||
/// ```text
|
||||
/// exists X. (a <: X || X <: a) && (b <: X || X <: b)
|
||||
/// ```
|
||||
pub fn sub_root_var(&mut self, vid: ty::TyVid) -> ty::TyVid {
|
||||
self.sub_relations().find(vid)
|
||||
}
|
||||
|
|
|
@ -1109,7 +1109,8 @@ declare_lint! {
|
|||
///
|
||||
/// ### Example
|
||||
///
|
||||
/// ```rust,compile_fail
|
||||
/// ```compile_fail
|
||||
/// #![deny(unaligned_references)]
|
||||
/// #[repr(packed)]
|
||||
/// pub struct Foo {
|
||||
/// field1: u64,
|
||||
|
|
|
@ -742,7 +742,7 @@ impl<'hir> Map<'hir> {
|
|||
/// }
|
||||
/// ```
|
||||
///
|
||||
/// ```
|
||||
/// ```compile_fail,E0308
|
||||
/// fn foo(x: usize) -> bool {
|
||||
/// loop {
|
||||
/// true // If `get_return_block` gets passed the `id` corresponding
|
||||
|
|
|
@ -10,7 +10,7 @@ use rustc_span::Span;
|
|||
/// Requires that `region` must be equal to one of the regions in `choice_regions`.
|
||||
/// We often denote this using the syntax:
|
||||
///
|
||||
/// ```
|
||||
/// ```text
|
||||
/// R0 member of [O1..On]
|
||||
/// ```
|
||||
#[derive(Debug, Clone, HashStable, TypeFoldable, Lift)]
|
||||
|
|
|
@ -770,11 +770,11 @@ impl InitMask {
|
|||
///
|
||||
/// Note that all examples below are written with 8 (instead of 64) bit blocks for simplicity,
|
||||
/// and with the least significant bit (and lowest block) first:
|
||||
///
|
||||
/// ```text
|
||||
/// 00000000|00000000
|
||||
/// ^ ^ ^ ^
|
||||
/// index: 0 7 8 15
|
||||
///
|
||||
/// ```
|
||||
/// Also, if not stated, assume that `is_init = true`, that is, we are searching for the first 1 bit.
|
||||
fn find_bit_fast(
|
||||
init_mask: &InitMask,
|
||||
|
|
|
@ -737,14 +737,14 @@ pub enum BorrowKind {
|
|||
/// This is used when lowering matches: when matching on a place we want to
|
||||
/// ensure that place have the same value from the start of the match until
|
||||
/// an arm is selected. This prevents this code from compiling:
|
||||
///
|
||||
/// ```compile_fail,E0510
|
||||
/// let mut x = &Some(0);
|
||||
/// match *x {
|
||||
/// None => (),
|
||||
/// Some(_) if { x = &None; false } => (),
|
||||
/// Some(_) => (),
|
||||
/// }
|
||||
///
|
||||
/// ```
|
||||
/// This can't be a shared borrow because mutably borrowing (*x as Some).0
|
||||
/// should not prevent `if let None = x { ... }`, for example, because the
|
||||
/// mutating `(*x as Some).0` can't affect the discriminant of `x`.
|
||||
|
@ -755,27 +755,30 @@ pub enum BorrowKind {
|
|||
/// cannot currently be expressed by the user and is used only in
|
||||
/// implicit closure bindings. It is needed when the closure is
|
||||
/// borrowing or mutating a mutable referent, e.g.:
|
||||
///
|
||||
/// let x: &mut isize = ...;
|
||||
/// ```
|
||||
/// let mut z = 3;
|
||||
/// let x: &mut isize = &mut z;
|
||||
/// let y = || *x += 5;
|
||||
///
|
||||
/// ```
|
||||
/// If we were to try to translate this closure into a more explicit
|
||||
/// form, we'd encounter an error with the code as written:
|
||||
///
|
||||
/// struct Env { x: & &mut isize }
|
||||
/// let x: &mut isize = ...;
|
||||
/// let y = (&mut Env { &x }, fn_ptr); // Closure is pair of env and fn
|
||||
/// ```compile_fail,E0594
|
||||
/// struct Env<'a> { x: &'a &'a mut isize }
|
||||
/// let mut z = 3;
|
||||
/// let x: &mut isize = &mut z;
|
||||
/// let y = (&mut Env { x: &x }, fn_ptr); // Closure is pair of env and fn
|
||||
/// fn fn_ptr(env: &mut Env) { **env.x += 5; }
|
||||
///
|
||||
/// ```
|
||||
/// This is then illegal because you cannot mutate an `&mut` found
|
||||
/// in an aliasable location. To solve, you'd have to translate with
|
||||
/// an `&mut` borrow:
|
||||
///
|
||||
/// struct Env { x: &mut &mut isize }
|
||||
/// let x: &mut isize = ...;
|
||||
/// let y = (&mut Env { &mut x }, fn_ptr); // changed from &x to &mut x
|
||||
/// ```compile_fail,E0596
|
||||
/// struct Env<'a> { x: &'a mut &'a mut isize }
|
||||
/// let mut z = 3;
|
||||
/// let x: &mut isize = &mut z;
|
||||
/// let y = (&mut Env { x: &mut x }, fn_ptr); // changed from &x to &mut x
|
||||
/// fn fn_ptr(env: &mut Env) { **env.x += 5; }
|
||||
///
|
||||
/// ```
|
||||
/// Now the assignment to `**env.x` is legal, but creating a
|
||||
/// mutable pointer to `x` is not because `x` is not mutable. We
|
||||
/// could fix this by declaring `x` as `let mut x`. This is ok in
|
||||
|
@ -1016,7 +1019,7 @@ pub struct LocalDecl<'tcx> {
|
|||
/// ```
|
||||
/// fn foo(x: &str) {
|
||||
/// match {
|
||||
/// match x.parse().unwrap() {
|
||||
/// match x.parse::<u32>().unwrap() {
|
||||
/// y => y + 2
|
||||
/// }
|
||||
/// } {
|
||||
|
@ -1690,9 +1693,9 @@ pub enum StatementKind<'tcx> {
|
|||
|
||||
/// Encodes a user's type ascription. These need to be preserved
|
||||
/// intact so that NLL can respect them. For example:
|
||||
///
|
||||
/// ```ignore (illustrative)
|
||||
/// let a: T = y;
|
||||
///
|
||||
/// ```
|
||||
/// The effect of this annotation is to relate the type `T_y` of the place `y`
|
||||
/// to the user-given type `T`. The effect depends on the specified variance:
|
||||
///
|
||||
|
@ -1985,7 +1988,7 @@ pub enum ProjectionElem<V, T> {
|
|||
/// These indices are generated by slice patterns. Easiest to explain
|
||||
/// by example:
|
||||
///
|
||||
/// ```
|
||||
/// ```ignore (illustrative)
|
||||
/// [X, _, .._, _, _] => { offset: 0, min_length: 4, from_end: false },
|
||||
/// [_, X, .._, _, _] => { offset: 1, min_length: 4, from_end: false },
|
||||
/// [_, _, .._, X, _] => { offset: 2, min_length: 4, from_end: true },
|
||||
|
@ -3179,7 +3182,7 @@ impl<'tcx> ConstantKind<'tcx> {
|
|||
///
|
||||
/// An example:
|
||||
///
|
||||
/// ```rust
|
||||
/// ```ignore (illustrative)
|
||||
/// struct S<'a>((i32, &'a str), String);
|
||||
/// let S((_, w): (i32, &'static str), _): S = ...;
|
||||
/// // ------ ^^^^^^^^^^^^^^^^^^^ (1)
|
||||
|
|
|
@ -438,7 +438,7 @@ impl<'tcx> CodegenUnitNameBuilder<'tcx> {
|
|||
///
|
||||
/// This function will build CGU names of the form:
|
||||
///
|
||||
/// ```
|
||||
/// ```text
|
||||
/// <crate-name>.<crate-disambiguator>[-in-<local-crate-id>](-<component>)*[.<special-suffix>]
|
||||
/// <local-crate-id> = <local-crate-name>.<local-crate-disambiguator>
|
||||
/// ```
|
||||
|
|
|
@ -202,7 +202,7 @@ pub enum TerminatorKind<'tcx> {
|
|||
/// This assignment occurs both in the unwind and the regular code paths. The semantics are best
|
||||
/// explained by the elaboration:
|
||||
///
|
||||
/// ```
|
||||
/// ```ignore (MIR)
|
||||
/// BB0 {
|
||||
/// DropAndReplace(P <- V, goto BB1, unwind BB2)
|
||||
/// }
|
||||
|
@ -210,7 +210,7 @@ pub enum TerminatorKind<'tcx> {
|
|||
///
|
||||
/// becomes
|
||||
///
|
||||
/// ```
|
||||
/// ```ignore (MIR)
|
||||
/// BB0 {
|
||||
/// Drop(P, goto BB1, unwind BB2)
|
||||
/// }
|
||||
|
|
|
@ -29,7 +29,7 @@
|
|||
//!
|
||||
//! For example, the `super_basic_block_data` method begins like this:
|
||||
//!
|
||||
//! ```rust
|
||||
//! ```ignore (pseudo-rust)
|
||||
//! fn super_basic_block_data(&mut self,
|
||||
//! block: BasicBlock,
|
||||
//! data: & $($mutability)? BasicBlockData<'tcx>) {
|
||||
|
@ -1170,10 +1170,10 @@ pub enum NonMutatingUseContext {
|
|||
AddressOf,
|
||||
/// Used as base for another place, e.g., `x` in `x.y`. Will not mutate the place.
|
||||
/// For example, the projection `x.y` is not marked as a mutation in these cases:
|
||||
///
|
||||
/// ```ignore (illustrative)
|
||||
/// z = x.y;
|
||||
/// f(&x.y);
|
||||
///
|
||||
/// ```
|
||||
Projection,
|
||||
}
|
||||
|
||||
|
@ -1199,10 +1199,10 @@ pub enum MutatingUseContext {
|
|||
AddressOf,
|
||||
/// Used as base for another place, e.g., `x` in `x.y`. Could potentially mutate the place.
|
||||
/// For example, the projection `x.y` is marked as a mutation in these cases:
|
||||
///
|
||||
/// ```ignore (illustrative)
|
||||
/// x.y = ...;
|
||||
/// f(&mut x.y);
|
||||
///
|
||||
/// ```
|
||||
Projection,
|
||||
/// Retagging, a "Stacked Borrows" shadow state operation
|
||||
Retag,
|
||||
|
|
|
@ -47,7 +47,8 @@ pub enum Reveal {
|
|||
/// impl. Concretely, that means that the following example will
|
||||
/// fail to compile:
|
||||
///
|
||||
/// ```
|
||||
/// ```compile_fail,E0308
|
||||
/// #![feature(specialization)]
|
||||
/// trait Assoc {
|
||||
/// type Output;
|
||||
/// }
|
||||
|
@ -57,7 +58,7 @@ pub enum Reveal {
|
|||
/// }
|
||||
///
|
||||
/// fn main() {
|
||||
/// let <() as Assoc>::Output = true;
|
||||
/// let x: <() as Assoc>::Output = true;
|
||||
/// }
|
||||
/// ```
|
||||
UserFacing,
|
||||
|
@ -515,7 +516,7 @@ pub type SelectionResult<'tcx, T> = Result<Option<T>, SelectionError<'tcx>>;
|
|||
/// For example, the obligation may be satisfied by a specific impl (case A),
|
||||
/// or it may be relative to some bound that is in scope (case B).
|
||||
///
|
||||
/// ```
|
||||
/// ```ignore (illustrative)
|
||||
/// impl<T:Clone> Clone<T> for Option<T> { ... } // Impl_1
|
||||
/// impl<T:Clone> Clone<T> for Box<T> { ... } // Impl_2
|
||||
/// impl Clone for i32 { ... } // Impl_3
|
||||
|
|
|
@ -180,6 +180,7 @@ pub struct LeafDef {
|
|||
/// Example:
|
||||
///
|
||||
/// ```
|
||||
/// #![feature(specialization)]
|
||||
/// trait Tr {
|
||||
/// fn assoc(&self);
|
||||
/// }
|
||||
|
|
|
@ -59,7 +59,7 @@ pub enum PointerCast {
|
|||
/// sized struct to a dynamically sized one. E.g., `&[i32; 4]` -> `&[i32]` is
|
||||
/// represented by:
|
||||
///
|
||||
/// ```
|
||||
/// ```ignore (illustrative)
|
||||
/// Deref(None) -> [i32; 4],
|
||||
/// Borrow(AutoBorrow::Ref) -> &[i32; 4],
|
||||
/// Unsize -> &[i32],
|
||||
|
|
|
@ -82,7 +82,7 @@ bitflags! {
|
|||
///
|
||||
/// is essentially represented with [`Ty`] as the following pseudocode:
|
||||
///
|
||||
/// ```
|
||||
/// ```ignore (illustrative)
|
||||
/// struct S { x }
|
||||
/// ```
|
||||
///
|
||||
|
|
|
@ -293,7 +293,7 @@ pub struct CaptureInfo {
|
|||
/// let mut t = (0,1);
|
||||
///
|
||||
/// let c = || {
|
||||
/// println!("{t}"); // L1
|
||||
/// println!("{t:?}"); // L1
|
||||
/// t.1 = 4; // L2
|
||||
/// };
|
||||
/// ```
|
||||
|
@ -309,7 +309,7 @@ pub struct CaptureInfo {
|
|||
/// let x = 5;
|
||||
///
|
||||
/// let c = || {
|
||||
/// let _ = x
|
||||
/// let _ = x;
|
||||
/// };
|
||||
/// ```
|
||||
///
|
||||
|
@ -373,17 +373,19 @@ pub enum BorrowKind {
|
|||
/// is borrowing or mutating a mutable referent, e.g.:
|
||||
///
|
||||
/// ```
|
||||
/// let x: &mut isize = ...;
|
||||
/// let mut z = 3;
|
||||
/// let x: &mut isize = &mut z;
|
||||
/// let y = || *x += 5;
|
||||
/// ```
|
||||
///
|
||||
/// If we were to try to translate this closure into a more explicit
|
||||
/// form, we'd encounter an error with the code as written:
|
||||
///
|
||||
/// ```
|
||||
/// struct Env { x: & &mut isize }
|
||||
/// let x: &mut isize = ...;
|
||||
/// let y = (&mut Env { &x }, fn_ptr); // Closure is pair of env and fn
|
||||
/// ```compile_fail,E0594
|
||||
/// struct Env<'a> { x: &'a &'a mut isize }
|
||||
/// let mut z = 3;
|
||||
/// let x: &mut isize = &mut z;
|
||||
/// let y = (&mut Env { x: &x }, fn_ptr); // Closure is pair of env and fn
|
||||
/// fn fn_ptr(env: &mut Env) { **env.x += 5; }
|
||||
/// ```
|
||||
///
|
||||
|
@ -391,10 +393,11 @@ pub enum BorrowKind {
|
|||
/// in an aliasable location. To solve, you'd have to translate with
|
||||
/// an `&mut` borrow:
|
||||
///
|
||||
/// ```
|
||||
/// struct Env { x: &mut &mut isize }
|
||||
/// let x: &mut isize = ...;
|
||||
/// let y = (&mut Env { &mut x }, fn_ptr); // changed from &x to &mut x
|
||||
/// ```compile_fail,E0596
|
||||
/// struct Env<'a> { x: &'a mut &'a mut isize }
|
||||
/// let mut z = 3;
|
||||
/// let x: &mut isize = &mut z;
|
||||
/// let y = (&mut Env { x: &mut x }, fn_ptr); // changed from &x to &mut x
|
||||
/// fn fn_ptr(env: &mut Env) { **env.x += 5; }
|
||||
/// ```
|
||||
///
|
||||
|
|
|
@ -455,12 +455,13 @@ pub struct TypeckResults<'tcx> {
|
|||
/// # Example
|
||||
///
|
||||
/// ```rust
|
||||
/// # use std::fmt::Debug;
|
||||
/// fn foo(x: &u32) -> impl Debug { *x }
|
||||
/// ```
|
||||
///
|
||||
/// The function signature here would be:
|
||||
///
|
||||
/// ```
|
||||
/// ```ignore (illustrative)
|
||||
/// for<'a> fn(&'a u32) -> Foo
|
||||
/// ```
|
||||
///
|
||||
|
@ -469,7 +470,7 @@ pub struct TypeckResults<'tcx> {
|
|||
///
|
||||
/// The *liberated* form of this would be
|
||||
///
|
||||
/// ```
|
||||
/// ```ignore (illustrative)
|
||||
/// fn(&'a u32) -> u32
|
||||
/// ```
|
||||
///
|
||||
|
|
|
@ -41,7 +41,7 @@
|
|||
//!
|
||||
//! For example, if you have `struct S(Ty, U)` where `S: TypeFoldable` and `U:
|
||||
//! TypeFoldable`, and an instance `S(ty, u)`, it would be visited like so:
|
||||
//! ```
|
||||
//! ```text
|
||||
//! s.visit_with(visitor) calls
|
||||
//! - s.super_visit_with(visitor) calls
|
||||
//! - ty.visit_with(visitor) calls
|
||||
|
@ -486,13 +486,13 @@ impl<'tcx> TyCtxt<'tcx> {
|
|||
/// traversed. If we encounter a bound region bound by this
|
||||
/// binder or one outer to it, it appears free. Example:
|
||||
///
|
||||
/// ```
|
||||
/// ```ignore (illustrative)
|
||||
/// for<'a> fn(for<'b> fn(), T)
|
||||
/// ^ ^ ^ ^
|
||||
/// | | | | here, would be shifted in 1
|
||||
/// | | | here, would be shifted in 2
|
||||
/// | | here, would be `INNERMOST` shifted in by 1
|
||||
/// | here, initially, binder would be `INNERMOST`
|
||||
/// // ^ ^ ^ ^
|
||||
/// // | | | | here, would be shifted in 1
|
||||
/// // | | | here, would be shifted in 2
|
||||
/// // | | here, would be `INNERMOST` shifted in by 1
|
||||
/// // | here, initially, binder would be `INNERMOST`
|
||||
/// ```
|
||||
///
|
||||
/// You see that, initially, *any* bound value is free,
|
||||
|
|
|
@ -56,7 +56,9 @@ impl<'tcx> TyCtxt<'tcx> {
|
|||
/// Checks whether a type is visibly uninhabited from a particular module.
|
||||
///
|
||||
/// # Example
|
||||
/// ```rust
|
||||
/// ```
|
||||
/// #![feature(never_type)]
|
||||
/// # fn main() {}
|
||||
/// enum Void {}
|
||||
/// mod a {
|
||||
/// pub mod b {
|
||||
|
@ -67,6 +69,7 @@ impl<'tcx> TyCtxt<'tcx> {
|
|||
/// }
|
||||
///
|
||||
/// mod c {
|
||||
/// use super::Void;
|
||||
/// pub struct AlsoSecretlyUninhabited {
|
||||
/// _priv: Void,
|
||||
/// }
|
||||
|
@ -84,7 +87,7 @@ impl<'tcx> TyCtxt<'tcx> {
|
|||
/// contain `Foo`.
|
||||
///
|
||||
/// # Example
|
||||
/// ```rust
|
||||
/// ```ignore (illustrative)
|
||||
/// let foo_result: Result<T, Foo> = ... ;
|
||||
/// let Ok(t) = foo_result;
|
||||
/// ```
|
||||
|
|
|
@ -337,7 +337,7 @@ impl<'tcx> Instance<'tcx> {
|
|||
/// Returns `Ok(None)` if we cannot resolve `Instance` to a specific instance.
|
||||
/// For example, in a context like this,
|
||||
///
|
||||
/// ```
|
||||
/// ```ignore (illustrative)
|
||||
/// fn foo<T: Debug>(t: T) { ... }
|
||||
/// ```
|
||||
///
|
||||
|
|
|
@ -1012,9 +1012,9 @@ impl<'tcx> Predicate<'tcx> {
|
|||
/// their values.
|
||||
///
|
||||
/// Example:
|
||||
///
|
||||
/// ```ignore (illustrative)
|
||||
/// struct Foo<T, U: Bar<T>> { ... }
|
||||
///
|
||||
/// ```
|
||||
/// Here, the `GenericPredicates` for `Foo` would contain a list of bounds like
|
||||
/// `[[], [U:Bar<T>]]`. Now if there were some particular reference
|
||||
/// like `Foo<isize,usize>`, then the `InstantiatedPredicates` would be `[[],
|
||||
|
@ -1072,9 +1072,9 @@ pub struct OpaqueHiddenType<'tcx> {
|
|||
/// The type variable that represents the value of the opaque type
|
||||
/// that we require. In other words, after we compile this function,
|
||||
/// we will be created a constraint like:
|
||||
///
|
||||
/// ```ignore (pseudo-rust)
|
||||
/// Foo<'a, T> = ?C
|
||||
///
|
||||
/// ```
|
||||
/// where `?C` is the value of this type variable. =) It may
|
||||
/// naturally refer to the type and lifetime parameters in scope
|
||||
/// in this function, though ultimately it should only reference
|
||||
|
@ -1115,7 +1115,7 @@ rustc_index::newtype_index! {
|
|||
///
|
||||
/// To make this more concrete, consider this program:
|
||||
///
|
||||
/// ```
|
||||
/// ```ignore (illustrative)
|
||||
/// struct Foo { }
|
||||
/// fn bar<T>(x: T) {
|
||||
/// let y: for<'a> fn(&'a u8, Foo) = ...;
|
||||
|
@ -1154,7 +1154,7 @@ impl UniverseIndex {
|
|||
/// corresponds to entering a `forall` quantifier. So, for
|
||||
/// example, suppose we have this type in universe `U`:
|
||||
///
|
||||
/// ```
|
||||
/// ```ignore (illustrative)
|
||||
/// for<'a> fn(&'a u32)
|
||||
/// ```
|
||||
///
|
||||
|
@ -1941,7 +1941,7 @@ pub enum ImplOverlapKind {
|
|||
/// The widely-used version 0.1.0 of the crate `traitobject` had accidentally relied
|
||||
/// that difference, making what reduces to the following set of impls:
|
||||
///
|
||||
/// ```
|
||||
/// ```compile_fail,(E0119)
|
||||
/// trait Trait {}
|
||||
/// impl Trait for dyn Send + Sync {}
|
||||
/// impl Trait for dyn Sync + Send {}
|
||||
|
|
|
@ -187,12 +187,14 @@ pub enum TyKind<'tcx> {
|
|||
/// Looking at the following example, the witness for this generator
|
||||
/// may end up as something like `for<'a> [Vec<i32>, &'a Vec<i32>]`:
|
||||
///
|
||||
/// ```rust
|
||||
/// ```ignore UNSOLVED (ask @compiler-errors, should this error? can we just swap the yields?)
|
||||
/// #![feature(generators)]
|
||||
/// |a| {
|
||||
/// let x = &vec![3];
|
||||
/// yield a;
|
||||
/// yield x[0];
|
||||
/// }
|
||||
/// # ;
|
||||
/// ```
|
||||
GeneratorWitness(Binder<'tcx, &'tcx List<Ty<'tcx>>>),
|
||||
|
||||
|
@ -276,9 +278,9 @@ impl<'tcx> TyKind<'tcx> {
|
|||
static_assert_size!(TyKind<'_>, 32);
|
||||
|
||||
/// A closure can be modeled as a struct that looks like:
|
||||
///
|
||||
/// ```ignore (illustrative)
|
||||
/// struct Closure<'l0...'li, T0...Tj, CK, CS, U>(...U);
|
||||
///
|
||||
/// ```
|
||||
/// where:
|
||||
///
|
||||
/// - 'l0...'li and T0...Tj are the generic parameters
|
||||
|
@ -295,25 +297,25 @@ static_assert_size!(TyKind<'_>, 32);
|
|||
/// and the up-var has the type `Foo`, then that field of U will be `&Foo`).
|
||||
///
|
||||
/// So, for example, given this function:
|
||||
///
|
||||
/// ```ignore (illustrative)
|
||||
/// fn foo<'a, T>(data: &'a mut T) {
|
||||
/// do(|| data.count += 1)
|
||||
/// }
|
||||
///
|
||||
/// ```
|
||||
/// the type of the closure would be something like:
|
||||
///
|
||||
/// ```ignore (illustrative)
|
||||
/// struct Closure<'a, T, U>(...U);
|
||||
///
|
||||
/// ```
|
||||
/// Note that the type of the upvar is not specified in the struct.
|
||||
/// You may wonder how the impl would then be able to use the upvar,
|
||||
/// if it doesn't know it's type? The answer is that the impl is
|
||||
/// (conceptually) not fully generic over Closure but rather tied to
|
||||
/// instances with the expected upvar types:
|
||||
///
|
||||
/// ```ignore (illustrative)
|
||||
/// impl<'b, 'a, T> FnMut() for Closure<'a, T, (&'b mut &'a mut T,)> {
|
||||
/// ...
|
||||
/// }
|
||||
///
|
||||
/// ```
|
||||
/// You can see that the *impl* fully specified the type of the upvar
|
||||
/// and thus knows full well that `data` has type `&'b mut &'a mut T`.
|
||||
/// (Here, I am assuming that `data` is mut-borrowed.)
|
||||
|
@ -760,9 +762,9 @@ impl<'tcx> UpvarSubsts<'tcx> {
|
|||
}
|
||||
|
||||
/// An inline const is modeled like
|
||||
///
|
||||
/// ```ignore (illustrative)
|
||||
/// const InlineConst<'l0...'li, T0...Tj, R>: R;
|
||||
///
|
||||
/// ```
|
||||
/// where:
|
||||
///
|
||||
/// - 'l0...'li and T0...Tj are the generic parameters
|
||||
|
@ -936,9 +938,9 @@ impl<'tcx> List<ty::Binder<'tcx, ExistentialPredicate<'tcx>>> {
|
|||
|
||||
/// A complete reference to a trait. These take numerous guises in syntax,
|
||||
/// but perhaps the most recognizable form is in a where-clause:
|
||||
///
|
||||
/// ```ignore (illustrative)
|
||||
/// T: Foo<U>
|
||||
///
|
||||
/// ```
|
||||
/// This would be represented by a trait-reference where the `DefId` is the
|
||||
/// `DefId` for the trait `Foo` and the substs define `T` as parameter 0,
|
||||
/// and `U` as parameter 1.
|
||||
|
@ -1012,9 +1014,9 @@ impl<'tcx> PolyTraitRef<'tcx> {
|
|||
|
||||
/// An existential reference to a trait, where `Self` is erased.
|
||||
/// For example, the trait object `Trait<'a, 'b, X, Y>` is:
|
||||
///
|
||||
/// ```ignore (illustrative)
|
||||
/// exists T. T: Trait<'a, 'b, X, Y>
|
||||
///
|
||||
/// ```
|
||||
/// The substitutions don't include the erased `Self`, only trait
|
||||
/// type and lifetime parameters (`[X, Y]` and `['a, 'b]` above).
|
||||
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, TyEncodable, TyDecodable)]
|
||||
|
@ -1434,7 +1436,7 @@ impl<'tcx> fmt::Debug for Region<'tcx> {
|
|||
///
|
||||
/// In general, the region lattice looks like
|
||||
///
|
||||
/// ```
|
||||
/// ```text
|
||||
/// static ----------+-----...------+ (greatest)
|
||||
/// | | |
|
||||
/// early-bound and | |
|
||||
|
@ -1780,14 +1782,14 @@ impl<'tcx> Region<'tcx> {
|
|||
/// Given an early-bound or free region, returns the `DefId` where it was bound.
|
||||
/// For example, consider the regions in this snippet of code:
|
||||
///
|
||||
/// ```
|
||||
/// ```ignore (illustrative)
|
||||
/// impl<'a> Foo {
|
||||
/// ^^ -- early bound, declared on an impl
|
||||
/// // ^^ -- early bound, declared on an impl
|
||||
///
|
||||
/// fn bar<'b, 'c>(x: &self, y: &'b u32, z: &'c u64) where 'static: 'c
|
||||
/// ^^ ^^ ^ anonymous, late-bound
|
||||
/// | early-bound, appears in where-clauses
|
||||
/// late-bound, appears only in fn args
|
||||
/// // ^^ ^^ ^ anonymous, late-bound
|
||||
/// // | early-bound, appears in where-clauses
|
||||
/// // late-bound, appears only in fn args
|
||||
/// {..}
|
||||
/// }
|
||||
/// ```
|
||||
|
|
|
@ -687,17 +687,17 @@ impl<'a, 'tcx> SubstFolder<'a, 'tcx> {
|
|||
///
|
||||
/// ```
|
||||
/// type Func<A> = fn(A);
|
||||
/// type MetaFunc = for<'a> fn(Func<&'a i32>)
|
||||
/// type MetaFunc = for<'a> fn(Func<&'a i32>);
|
||||
/// ```
|
||||
///
|
||||
/// The type `MetaFunc`, when fully expanded, will be
|
||||
///
|
||||
/// ```ignore (illustrative)
|
||||
/// for<'a> fn(fn(&'a i32))
|
||||
/// ^~ ^~ ^~~
|
||||
/// | | |
|
||||
/// | | DebruijnIndex of 2
|
||||
/// Binders
|
||||
///
|
||||
/// // ^~ ^~ ^~~
|
||||
/// // | | |
|
||||
/// // | | DebruijnIndex of 2
|
||||
/// // Binders
|
||||
/// ```
|
||||
/// Here the `'a` lifetime is bound in the outer function, but appears as an argument of the
|
||||
/// inner one. Therefore, that appearance will have a DebruijnIndex of 2, because we must skip
|
||||
/// over the inner binder (remember that we count De Bruijn indices from 1). However, in the
|
||||
|
@ -709,17 +709,17 @@ impl<'a, 'tcx> SubstFolder<'a, 'tcx> {
|
|||
///
|
||||
/// ```
|
||||
/// type FuncTuple<A> = (A,fn(A));
|
||||
/// type MetaFuncTuple = for<'a> fn(FuncTuple<&'a i32>)
|
||||
/// type MetaFuncTuple = for<'a> fn(FuncTuple<&'a i32>);
|
||||
/// ```
|
||||
///
|
||||
/// Here the final type will be:
|
||||
///
|
||||
/// ```ignore (illustrative)
|
||||
/// for<'a> fn((&'a i32, fn(&'a i32)))
|
||||
/// ^~~ ^~~
|
||||
/// | |
|
||||
/// DebruijnIndex of 1 |
|
||||
/// DebruijnIndex of 2
|
||||
///
|
||||
/// // ^~~ ^~~
|
||||
/// // | |
|
||||
/// // DebruijnIndex of 1 |
|
||||
/// // DebruijnIndex of 2
|
||||
/// ```
|
||||
/// As indicated in the diagram, here the same type `&'a i32` is substituted once, but in the
|
||||
/// first case we do not increase the De Bruijn index and in the second case we do. The reason
|
||||
/// is that only in the second case have we passed through a fn binder.
|
||||
|
@ -767,7 +767,7 @@ pub struct UserSubsts<'tcx> {
|
|||
/// sometimes needed to constrain the type parameters on the impl. For
|
||||
/// example, in this code:
|
||||
///
|
||||
/// ```
|
||||
/// ```ignore (illustrative)
|
||||
/// struct Foo<T> { }
|
||||
/// impl<A> Foo<A> { fn method() { } }
|
||||
/// ```
|
||||
|
|
|
@ -975,7 +975,7 @@ impl<'tcx> ExplicitSelf<'tcx> {
|
|||
///
|
||||
/// Examples:
|
||||
///
|
||||
/// ```
|
||||
/// ```ignore (illustrative)
|
||||
/// impl<'a> Foo for &'a T {
|
||||
/// // Legal declarations:
|
||||
/// fn method1(self: &&'a T); // ExplicitSelf::ByReference
|
||||
|
|
|
@ -34,7 +34,7 @@ impl<'tcx> TypeWalker<'tcx> {
|
|||
///
|
||||
/// Example: Imagine you are walking `Foo<Bar<i32>, usize>`.
|
||||
///
|
||||
/// ```
|
||||
/// ```ignore (illustrative)
|
||||
/// let mut iter: TypeWalker = ...;
|
||||
/// iter.next(); // yields Foo
|
||||
/// iter.next(); // yields Bar<i32>
|
||||
|
|
|
@ -42,15 +42,17 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
|||
/// We tweak the handling of parameters of unsized type slightly to avoid the need to create a
|
||||
/// local variable of unsized type. For example, consider this program:
|
||||
///
|
||||
/// ```rust
|
||||
/// fn foo(p: dyn Debug) { ... }
|
||||
/// ```
|
||||
/// #![feature(unsized_locals, unsized_fn_params)]
|
||||
/// # use core::fmt::Debug;
|
||||
/// fn foo(p: dyn Debug) { dbg!(p); }
|
||||
///
|
||||
/// fn bar(box_p: Box<dyn Debug>) { foo(*p); }
|
||||
/// fn bar(box_p: Box<dyn Debug>) { foo(*box_p); }
|
||||
/// ```
|
||||
///
|
||||
/// Ordinarily, for sized types, we would compile the call `foo(*p)` like so:
|
||||
///
|
||||
/// ```rust
|
||||
/// ```ignore (illustrative)
|
||||
/// let tmp0 = *box_p; // tmp0 would be the operand returned by this function call
|
||||
/// foo(tmp0)
|
||||
/// ```
|
||||
|
@ -60,7 +62,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
|||
/// that we create *stores the entire box*, and the parameter to the call itself will be
|
||||
/// `*tmp0`:
|
||||
///
|
||||
/// ```rust
|
||||
/// ```ignore (illustrative)
|
||||
/// let tmp0 = box_p; call foo(*tmp0)
|
||||
/// ```
|
||||
///
|
||||
|
|
|
@ -37,7 +37,7 @@ crate enum PlaceBase {
|
|||
///
|
||||
/// Consider the following example
|
||||
/// ```rust
|
||||
/// let t = (10, (10, (10, 10)));
|
||||
/// let t = (((10, 10), 10), 10);
|
||||
///
|
||||
/// let c = || {
|
||||
/// println!("{}", t.0.0.0);
|
||||
|
@ -45,7 +45,7 @@ crate enum PlaceBase {
|
|||
/// ```
|
||||
/// Here the THIR expression for `t.0.0.0` will be something like
|
||||
///
|
||||
/// ```
|
||||
/// ```ignore (illustrative)
|
||||
/// * Field(0)
|
||||
/// * Field(0)
|
||||
/// * Field(0)
|
||||
|
|
|
@ -1032,11 +1032,13 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
|||
/// exhaustive match, consider:
|
||||
///
|
||||
/// ```
|
||||
/// # fn foo(x: (bool, bool)) {
|
||||
/// match x {
|
||||
/// (true, true) => (),
|
||||
/// (_, false) => (),
|
||||
/// (false, true) => (),
|
||||
/// }
|
||||
/// # }
|
||||
/// ```
|
||||
///
|
||||
/// For this match, we check if `x.0` matches `true` (for the first
|
||||
|
@ -1157,7 +1159,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
|||
///
|
||||
/// For example, if we have something like this:
|
||||
///
|
||||
/// ```rust
|
||||
/// ```ignore (illustrative)
|
||||
/// ...
|
||||
/// Some(x) if cond1 => ...
|
||||
/// Some(x) => ...
|
||||
|
@ -1481,11 +1483,12 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
|||
/// ```
|
||||
/// # let (x, y, z) = (true, true, true);
|
||||
/// match (x, y, z) {
|
||||
/// (true, _, true) => true, // (0)
|
||||
/// (_, true, _) => true, // (1)
|
||||
/// (false, false, _) => false, // (2)
|
||||
/// (true, _, false) => false, // (3)
|
||||
/// (true , _ , true ) => true, // (0)
|
||||
/// (_ , true , _ ) => true, // (1)
|
||||
/// (false, false, _ ) => false, // (2)
|
||||
/// (true , _ , false) => false, // (3)
|
||||
/// }
|
||||
/// # ;
|
||||
/// ```
|
||||
///
|
||||
/// In that case, after we test on `x`, there are 2 overlapping candidate
|
||||
|
@ -1502,11 +1505,11 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
|||
/// with precisely the reachable arms being reachable - but that problem
|
||||
/// is trivially NP-complete:
|
||||
///
|
||||
/// ```rust
|
||||
/// ```ignore (illustrative)
|
||||
/// match (var0, var1, var2, var3, ...) {
|
||||
/// (true, _, _, false, true, ...) => false,
|
||||
/// (_, true, true, false, _, ...) => false,
|
||||
/// (false, _, false, false, _, ...) => false,
|
||||
/// (true , _ , _ , false, true, ...) => false,
|
||||
/// (_ , true, true , false, _ , ...) => false,
|
||||
/// (false, _ , false, false, _ , ...) => false,
|
||||
/// ...
|
||||
/// _ => true
|
||||
/// }
|
||||
|
@ -1520,7 +1523,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
|||
/// our simplistic treatment of constants and guards would make it occur
|
||||
/// in very common situations - for example [#29740]:
|
||||
///
|
||||
/// ```rust
|
||||
/// ```ignore (illustrative)
|
||||
/// match x {
|
||||
/// "foo" if foo_guard => ...,
|
||||
/// "bar" if bar_guard => ...,
|
||||
|
|
|
@ -803,16 +803,16 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
|||
/// scope (which can be larger or smaller).
|
||||
///
|
||||
/// Consider:
|
||||
///
|
||||
/// ```ignore (illustrative)
|
||||
/// let x = foo(bar(X, Y));
|
||||
///
|
||||
/// ```
|
||||
/// We wish to pop the storage for X and Y after `bar()` is
|
||||
/// called, not after the whole `let` is completed.
|
||||
///
|
||||
/// As another example, if the second argument diverges:
|
||||
///
|
||||
/// ```ignore (illustrative)
|
||||
/// foo(Box::new(2), panic!())
|
||||
///
|
||||
/// ```
|
||||
/// We would allocate the box but then free it on the unwinding
|
||||
/// path; we would also emit a free on the 'success' path from
|
||||
/// panic, but that will turn out to be removed as dead-code.
|
||||
|
@ -944,7 +944,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
|||
///
|
||||
/// Example: when compiling the call to `foo` here:
|
||||
///
|
||||
/// ```rust
|
||||
/// ```ignore (illustrative)
|
||||
/// foo(bar(), ...)
|
||||
/// ```
|
||||
///
|
||||
|
@ -955,7 +955,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
|||
/// dropped). However, if no unwind occurs, then `_X` will be
|
||||
/// unconditionally consumed by the `call`:
|
||||
///
|
||||
/// ```
|
||||
/// ```ignore (illustrative)
|
||||
/// bb {
|
||||
/// ...
|
||||
/// _R = CALL(foo, _X, ...)
|
||||
|
|
|
@ -13,7 +13,7 @@
|
|||
//! Instead of listing all those constructors (which is intractable), we group those value
|
||||
//! constructors together as much as possible. Example:
|
||||
//!
|
||||
//! ```
|
||||
//! ```compile_fail,E0004
|
||||
//! match (0, false) {
|
||||
//! (0 ..=100, true) => {} // `p_1`
|
||||
//! (50..=150, false) => {} // `p_2`
|
||||
|
@ -344,13 +344,13 @@ enum IntBorder {
|
|||
/// straddles the boundary of one of the inputs.
|
||||
///
|
||||
/// The following input:
|
||||
/// ```
|
||||
/// ```text
|
||||
/// |-------------------------| // `self`
|
||||
/// |------| |----------| |----|
|
||||
/// |-------| |-------|
|
||||
/// ```
|
||||
/// would be iterated over as follows:
|
||||
/// ```
|
||||
/// ```text
|
||||
/// ||---|--||-|---|---|---|--|
|
||||
/// ```
|
||||
#[derive(Debug, Clone)]
|
||||
|
@ -492,14 +492,17 @@ impl Slice {
|
|||
///
|
||||
/// Let's look at an example, where we are trying to split the last pattern:
|
||||
/// ```
|
||||
/// # fn foo(x: &[bool]) {
|
||||
/// match x {
|
||||
/// [true, true, ..] => {}
|
||||
/// [.., false, false] => {}
|
||||
/// [..] => {}
|
||||
/// }
|
||||
/// # }
|
||||
/// ```
|
||||
/// Here are the results of specialization for the first few lengths:
|
||||
/// ```
|
||||
/// # fn foo(x: &[bool]) { match x {
|
||||
/// // length 0
|
||||
/// [] => {}
|
||||
/// // length 1
|
||||
|
@ -520,6 +523,8 @@ impl Slice {
|
|||
/// [true, true, _, _, _ ] => {}
|
||||
/// [_, _, _, false, false] => {}
|
||||
/// [_, _, _, _, _ ] => {}
|
||||
/// # _ => {}
|
||||
/// # }}
|
||||
/// ```
|
||||
///
|
||||
/// If we went above length 5, we would simply be inserting more columns full of wildcards in the
|
||||
|
@ -1128,7 +1133,8 @@ impl<'tcx> SplitWildcard<'tcx> {
|
|||
/// In the following example `Fields::wildcards` returns `[_, _, _, _]`. Then in
|
||||
/// `extract_pattern_arguments` we fill some of the entries, and the result is
|
||||
/// `[Some(0), _, _, _]`.
|
||||
/// ```rust
|
||||
/// ```compile_fail,E0004
|
||||
/// # fn foo() -> [Option<u8>; 4] { [None; 4] }
|
||||
/// let x: [Option<u8>; 4] = foo();
|
||||
/// match x {
|
||||
/// [Some(0), ..] => {}
|
||||
|
|
|
@ -35,23 +35,27 @@
|
|||
//! This is enough to compute reachability: a pattern in a `match` expression is reachable iff it
|
||||
//! is useful w.r.t. the patterns above it:
|
||||
//! ```rust
|
||||
//! # fn foo(x: Option<i32>) {
|
||||
//! match x {
|
||||
//! Some(_) => ...,
|
||||
//! None => ..., // reachable: `None` is matched by this but not the branch above
|
||||
//! Some(0) => ..., // unreachable: all the values this matches are already matched by
|
||||
//! Some(_) => {},
|
||||
//! None => {}, // reachable: `None` is matched by this but not the branch above
|
||||
//! Some(0) => {}, // unreachable: all the values this matches are already matched by
|
||||
//! // `Some(_)` above
|
||||
//! }
|
||||
//! # }
|
||||
//! ```
|
||||
//!
|
||||
//! This is also enough to compute exhaustiveness: a match is exhaustive iff the wildcard `_`
|
||||
//! pattern is _not_ useful w.r.t. the patterns in the match. The values returned by `usefulness`
|
||||
//! are used to tell the user which values are missing.
|
||||
//! ```rust
|
||||
//! ```compile_fail,E0004
|
||||
//! # fn foo(x: Option<i32>) {
|
||||
//! match x {
|
||||
//! Some(0) => ...,
|
||||
//! None => ...,
|
||||
//! Some(0) => {},
|
||||
//! None => {},
|
||||
//! // not exhaustive: `_` is useful because it matches `Some(1)`
|
||||
//! }
|
||||
//! # }
|
||||
//! ```
|
||||
//!
|
||||
//! The entrypoint of this file is the [`compute_match_usefulness`] function, which computes
|
||||
|
@ -120,12 +124,15 @@
|
|||
//! say from knowing only the first constructor of our candidate value.
|
||||
//!
|
||||
//! Let's take the following example:
|
||||
//! ```
|
||||
//! ```compile_fail,E0004
|
||||
//! # enum Enum { Variant1(()), Variant2(Option<bool>, u32)}
|
||||
//! # fn foo(x: Enum) {
|
||||
//! match x {
|
||||
//! Enum::Variant1(_) => {} // `p1`
|
||||
//! Enum::Variant2(None, 0) => {} // `p2`
|
||||
//! Enum::Variant2(Some(_), 0) => {} // `q`
|
||||
//! }
|
||||
//! # }
|
||||
//! ```
|
||||
//!
|
||||
//! We can easily see that if our candidate value `v` starts with `Variant1` it will not match `q`.
|
||||
|
@ -133,11 +140,13 @@
|
|||
//! and `v1`. In fact, such a `v` will be a witness of usefulness of `q` exactly when the tuple
|
||||
//! `(v0, v1)` is a witness of usefulness of `q'` in the following reduced match:
|
||||
//!
|
||||
//! ```
|
||||
//! ```compile_fail,E0004
|
||||
//! # fn foo(x: (Option<bool>, u32)) {
|
||||
//! match x {
|
||||
//! (None, 0) => {} // `p2'`
|
||||
//! (Some(_), 0) => {} // `q'`
|
||||
//! }
|
||||
//! # }
|
||||
//! ```
|
||||
//!
|
||||
//! This motivates a new step in computing usefulness, that we call _specialization_.
|
||||
|
@ -150,7 +159,7 @@
|
|||
//! like a stack. We note a pattern-stack simply with `[p_1 ... p_n]`.
|
||||
//! Here's a sequence of specializations of a list of pattern-stacks, to illustrate what's
|
||||
//! happening:
|
||||
//! ```
|
||||
//! ```ignore (illustrative)
|
||||
//! [Enum::Variant1(_)]
|
||||
//! [Enum::Variant2(None, 0)]
|
||||
//! [Enum::Variant2(Some(_), 0)]
|
||||
|
@ -234,7 +243,7 @@
|
|||
//! - We return the concatenation of all the witnesses found, if any.
|
||||
//!
|
||||
//! Example:
|
||||
//! ```
|
||||
//! ```ignore (illustrative)
|
||||
//! [Some(true)] // p_1
|
||||
//! [None] // p_2
|
||||
//! [Some(_)] // q
|
||||
|
@ -659,13 +668,15 @@ enum ArmType {
|
|||
///
|
||||
/// For example, if we are constructing a witness for the match against
|
||||
///
|
||||
/// ```
|
||||
/// ```compile_fail,E0004
|
||||
/// # #![feature(type_ascription)]
|
||||
/// struct Pair(Option<(u32, u32)>, bool);
|
||||
///
|
||||
/// # fn foo(p: Pair) {
|
||||
/// match (p: Pair) {
|
||||
/// Pair(None, _) => {}
|
||||
/// Pair(_, false) => {}
|
||||
/// }
|
||||
/// # }
|
||||
/// ```
|
||||
///
|
||||
/// We'll perform the following steps:
|
||||
|
|
|
@ -39,7 +39,7 @@ pub use self::storage_liveness::{MaybeRequiresStorage, MaybeStorageLive};
|
|||
/// struct S;
|
||||
/// fn foo(pred: bool) { // maybe-init:
|
||||
/// // {}
|
||||
/// let a = S; let b = S; let c; let d; // {a, b}
|
||||
/// let a = S; let mut b = S; let c; let d; // {a, b}
|
||||
///
|
||||
/// if pred {
|
||||
/// drop(a); // { b}
|
||||
|
@ -92,7 +92,7 @@ impl<'a, 'tcx> HasMoveData<'tcx> for MaybeInitializedPlaces<'a, 'tcx> {
|
|||
/// struct S;
|
||||
/// fn foo(pred: bool) { // maybe-uninit:
|
||||
/// // {a, b, c, d}
|
||||
/// let a = S; let b = S; let c; let d; // { c, d}
|
||||
/// let a = S; let mut b = S; let c; let d; // { c, d}
|
||||
///
|
||||
/// if pred {
|
||||
/// drop(a); // {a, c, d}
|
||||
|
@ -157,7 +157,7 @@ impl<'a, 'tcx> HasMoveData<'tcx> for MaybeUninitializedPlaces<'a, 'tcx> {
|
|||
/// struct S;
|
||||
/// fn foo(pred: bool) { // definite-init:
|
||||
/// // { }
|
||||
/// let a = S; let b = S; let c; let d; // {a, b }
|
||||
/// let a = S; let mut b = S; let c; let d; // {a, b }
|
||||
///
|
||||
/// if pred {
|
||||
/// drop(a); // { b, }
|
||||
|
@ -212,7 +212,7 @@ impl<'a, 'tcx> HasMoveData<'tcx> for DefinitelyInitializedPlaces<'a, 'tcx> {
|
|||
/// struct S;
|
||||
/// fn foo(pred: bool) { // ever-init:
|
||||
/// // { }
|
||||
/// let a = S; let b = S; let c; let d; // {a, b }
|
||||
/// let a = S; let mut b = S; let c; let d; // {a, b }
|
||||
///
|
||||
/// if pred {
|
||||
/// drop(a); // {a, b, }
|
||||
|
|
|
@ -18,13 +18,13 @@
|
|||
//! First upvars are stored
|
||||
//! It is followed by the generator state field.
|
||||
//! Then finally the MIR locals which are live across a suspension point are stored.
|
||||
//!
|
||||
//! ```ignore (illustrative)
|
||||
//! struct Generator {
|
||||
//! upvars...,
|
||||
//! state: u32,
|
||||
//! mir_locals...,
|
||||
//! }
|
||||
//!
|
||||
//! ```
|
||||
//! This pass computes the meaning of the state field and the MIR locals which are live
|
||||
//! across a suspension point. There are however three hardcoded generator states:
|
||||
//! 0 - Generator have not been resumed yet
|
||||
|
|
|
@ -14,7 +14,7 @@ pub struct MatchBranchSimplification;
|
|||
///
|
||||
/// For example:
|
||||
///
|
||||
/// ```rust
|
||||
/// ```ignore (MIR)
|
||||
/// bb0: {
|
||||
/// switchInt(move _3) -> [42_isize: bb1, otherwise: bb2];
|
||||
/// }
|
||||
|
@ -32,7 +32,7 @@ pub struct MatchBranchSimplification;
|
|||
///
|
||||
/// into:
|
||||
///
|
||||
/// ```rust
|
||||
/// ```ignore (MIR)
|
||||
/// bb0: {
|
||||
/// _2 = Eq(move _3, const 42_isize);
|
||||
/// goto -> bb3;
|
||||
|
|
|
@ -12,7 +12,7 @@ use rustc_middle::{
|
|||
/// Pass to convert `if` conditions on integrals into switches on the integral.
|
||||
/// For an example, it turns something like
|
||||
///
|
||||
/// ```
|
||||
/// ```ignore (MIR)
|
||||
/// _3 = Eq(move _4, const 43i32);
|
||||
/// StorageDead(_4);
|
||||
/// switchInt(_3) -> [false: bb2, otherwise: bb3];
|
||||
|
@ -20,7 +20,7 @@ use rustc_middle::{
|
|||
///
|
||||
/// into:
|
||||
///
|
||||
/// ```
|
||||
/// ```ignore (MIR)
|
||||
/// switchInt(_4) -> [43i32: bb3, otherwise: bb2];
|
||||
/// ```
|
||||
pub struct SimplifyComparisonIntegral;
|
||||
|
|
|
@ -1,10 +1,12 @@
|
|||
//! The general point of the optimizations provided here is to simplify something like:
|
||||
//!
|
||||
//! ```rust
|
||||
//! # fn foo<T, E>(x: Result<T, E>) -> Result<T, E> {
|
||||
//! match x {
|
||||
//! Ok(x) => Ok(x),
|
||||
//! Err(x) => Err(x)
|
||||
//! }
|
||||
//! # }
|
||||
//! ```
|
||||
//!
|
||||
//! into just `x`.
|
||||
|
@ -23,7 +25,7 @@ use std::slice::Iter;
|
|||
///
|
||||
/// This is done by transforming basic blocks where the statements match:
|
||||
///
|
||||
/// ```rust
|
||||
/// ```ignore (MIR)
|
||||
/// _LOCAL_TMP = ((_LOCAL_1 as Variant ).FIELD: TY );
|
||||
/// _TMP_2 = _LOCAL_TMP;
|
||||
/// ((_LOCAL_0 as Variant).FIELD: TY) = move _TMP_2;
|
||||
|
@ -32,7 +34,7 @@ use std::slice::Iter;
|
|||
///
|
||||
/// into:
|
||||
///
|
||||
/// ```rust
|
||||
/// ```ignore (MIR)
|
||||
/// _LOCAL_0 = move _LOCAL_1
|
||||
/// ```
|
||||
pub struct SimplifyArmIdentity;
|
||||
|
@ -472,7 +474,7 @@ impl Visitor<'_> for LocalUseCounter {
|
|||
}
|
||||
|
||||
/// Match on:
|
||||
/// ```rust
|
||||
/// ```ignore (MIR)
|
||||
/// _LOCAL_INTO = ((_LOCAL_FROM as Variant).FIELD: TY);
|
||||
/// ```
|
||||
fn match_get_variant_field<'tcx>(
|
||||
|
@ -492,7 +494,7 @@ fn match_get_variant_field<'tcx>(
|
|||
}
|
||||
|
||||
/// Match on:
|
||||
/// ```rust
|
||||
/// ```ignore (MIR)
|
||||
/// ((_LOCAL_FROM as Variant).FIELD: TY) = move _LOCAL_INTO;
|
||||
/// ```
|
||||
fn match_set_variant_field<'tcx>(stmt: &Statement<'tcx>) -> Option<(Local, Local, VarField<'tcx>)> {
|
||||
|
@ -507,7 +509,7 @@ fn match_set_variant_field<'tcx>(stmt: &Statement<'tcx>) -> Option<(Local, Local
|
|||
}
|
||||
|
||||
/// Match on:
|
||||
/// ```rust
|
||||
/// ```ignore (MIR)
|
||||
/// discriminant(_LOCAL_TO_SET) = VAR_IDX;
|
||||
/// ```
|
||||
fn match_set_discr(stmt: &Statement<'_>) -> Option<(Local, VariantIdx)> {
|
||||
|
@ -690,7 +692,7 @@ impl<'tcx> SimplifyBranchSameOptimizationFinder<'_, 'tcx> {
|
|||
///
|
||||
/// Statements can be trivially equal if the kinds match.
|
||||
/// But they can also be considered equal in the following case A:
|
||||
/// ```
|
||||
/// ```ignore (MIR)
|
||||
/// discriminant(_0) = 0; // bb1
|
||||
/// _0 = move _1; // bb2
|
||||
/// ```
|
||||
|
|
|
@ -91,12 +91,13 @@
|
|||
//! another function. It suffices to just take a reference in order to introduce
|
||||
//! an edge. Consider the following example:
|
||||
//!
|
||||
//! ```rust
|
||||
//! ```
|
||||
//! # use core::fmt::Display;
|
||||
//! fn print_val<T: Display>(x: T) {
|
||||
//! println!("{}", x);
|
||||
//! }
|
||||
//!
|
||||
//! fn call_fn(f: &Fn(i32), x: i32) {
|
||||
//! fn call_fn(f: &dyn Fn(i32), x: i32) {
|
||||
//! f(x);
|
||||
//! }
|
||||
//!
|
||||
|
|
|
@ -371,9 +371,10 @@ impl<'a> Parser<'a> {
|
|||
}
|
||||
|
||||
/// Matches the following grammar (per RFC 1559).
|
||||
///
|
||||
/// ```ebnf
|
||||
/// meta_item : PATH ( '=' UNSUFFIXED_LIT | '(' meta_item_inner? ')' )? ;
|
||||
/// meta_item_inner : (meta_item | UNSUFFIXED_LIT) (',' meta_item_inner)? ;
|
||||
/// ```
|
||||
pub fn parse_meta_item(&mut self) -> PResult<'a, ast::MetaItem> {
|
||||
let nt_meta = match self.token.kind {
|
||||
token::Interpolated(ref nt) => match **nt {
|
||||
|
|
|
@ -485,7 +485,7 @@ impl<'a> Parser<'a> {
|
|||
|
||||
/// Parses an implementation item.
|
||||
///
|
||||
/// ```
|
||||
/// ```ignore (illustrative)
|
||||
/// impl<'a, T> TYPE { /* impl items */ }
|
||||
/// impl<'a, T> TRAIT for TYPE { /* impl items */ }
|
||||
/// impl<'a, T> !TRAIT for TYPE { /* impl items */ }
|
||||
|
@ -493,7 +493,7 @@ impl<'a> Parser<'a> {
|
|||
/// ```
|
||||
///
|
||||
/// We actually parse slightly more relaxed grammar for better error reporting and recovery.
|
||||
/// ```
|
||||
/// ```ebnf
|
||||
/// "impl" GENERICS "const"? "!"? TYPE "for"? (TYPE | "..") ("where" PREDICATES)? "{" BODY "}"
|
||||
/// "impl" GENERICS "const"? "!"? TYPE ("where" PREDICATES)? "{" BODY "}"
|
||||
/// ```
|
||||
|
@ -806,7 +806,7 @@ impl<'a> Parser<'a> {
|
|||
}
|
||||
|
||||
/// Parses a `type` alias with the following grammar:
|
||||
/// ```
|
||||
/// ```ebnf
|
||||
/// TypeAlias = "type" Ident Generics {":" GenericBounds}? {"=" Ty}? ";" ;
|
||||
/// ```
|
||||
/// The `"type"` has already been eaten.
|
||||
|
@ -930,7 +930,7 @@ impl<'a> Parser<'a> {
|
|||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// ```ignore (illustrative)
|
||||
/// extern crate foo;
|
||||
/// extern crate bar as foo;
|
||||
/// ```
|
||||
|
@ -1630,7 +1630,7 @@ impl<'a> Parser<'a> {
|
|||
|
||||
/// Parses a declarative macro 2.0 definition.
|
||||
/// The `macro` keyword has already been parsed.
|
||||
/// ```
|
||||
/// ```ebnf
|
||||
/// MacBody = "{" TOKEN_STREAM "}" ;
|
||||
/// MacParams = "(" TOKEN_STREAM ")" ;
|
||||
/// DeclMac = "macro" Ident MacParams? MacBody ;
|
||||
|
|
|
@ -52,7 +52,7 @@ pub(super) enum RecoverQuestionMark {
|
|||
/// Signals whether parsing a type should recover `->`.
|
||||
///
|
||||
/// More specifically, when parsing a function like:
|
||||
/// ```rust
|
||||
/// ```compile_fail
|
||||
/// fn foo() => u8 { 0 }
|
||||
/// fn bar(): u8 { 0 }
|
||||
/// ```
|
||||
|
@ -499,12 +499,12 @@ impl<'a> Parser<'a> {
|
|||
}
|
||||
|
||||
/// Parses a function pointer type (`TyKind::BareFn`).
|
||||
/// ```
|
||||
/// ```ignore (illustrative)
|
||||
/// [unsafe] [extern "ABI"] fn (S) -> T
|
||||
/// ^~~~~^ ^~~~^ ^~^ ^
|
||||
/// | | | |
|
||||
/// | | | Return type
|
||||
/// Function Style ABI Parameter types
|
||||
/// // ^~~~~^ ^~~~^ ^~^ ^
|
||||
/// // | | | |
|
||||
/// // | | | Return type
|
||||
/// // Function Style ABI Parameter types
|
||||
/// ```
|
||||
/// We actually parse `FnHeader FnDecl`, but we error on `const` and `async` qualifiers.
|
||||
fn parse_ty_bare_fn(
|
||||
|
@ -707,7 +707,7 @@ impl<'a> Parser<'a> {
|
|||
}
|
||||
|
||||
/// Parses a bound according to the grammar:
|
||||
/// ```
|
||||
/// ```ebnf
|
||||
/// BOUND = TY_BOUND | LT_BOUND
|
||||
/// ```
|
||||
fn parse_generic_bound(&mut self) -> PResult<'a, Result<GenericBound, Span>> {
|
||||
|
@ -729,7 +729,7 @@ impl<'a> Parser<'a> {
|
|||
}
|
||||
|
||||
/// Parses a lifetime ("outlives") bound, e.g. `'a`, according to:
|
||||
/// ```
|
||||
/// ```ebnf
|
||||
/// LT_BOUND = LIFETIME
|
||||
/// ```
|
||||
fn parse_generic_lt_bound(
|
||||
|
@ -787,7 +787,7 @@ impl<'a> Parser<'a> {
|
|||
///
|
||||
/// If no modifiers are present, this does not consume any tokens.
|
||||
///
|
||||
/// ```
|
||||
/// ```ebnf
|
||||
/// TY_BOUND_MODIFIERS = ["~const"] ["?"]
|
||||
/// ```
|
||||
fn parse_ty_bound_modifiers(&mut self) -> PResult<'a, BoundModifiers> {
|
||||
|
@ -807,7 +807,7 @@ impl<'a> Parser<'a> {
|
|||
}
|
||||
|
||||
/// Parses a type bound according to:
|
||||
/// ```
|
||||
/// ```ebnf
|
||||
/// TY_BOUND = TY_BOUND_NOPAREN | (TY_BOUND_NOPAREN)
|
||||
/// TY_BOUND_NOPAREN = [TY_BOUND_MODIFIERS] [for<LT_PARAM_DEFS>] SIMPLE_PATH
|
||||
/// ```
|
||||
|
|
|
@ -7,9 +7,9 @@ use std::error::Error;
|
|||
|
||||
/// A dep-node filter goes from a user-defined string to a query over
|
||||
/// nodes. Right now the format is like this:
|
||||
///
|
||||
/// ```ignore (illustrative)
|
||||
/// x & y & z
|
||||
///
|
||||
/// ```
|
||||
/// where the format-string of the dep-node must contain `x`, `y`, and
|
||||
/// `z`.
|
||||
#[derive(Debug)]
|
||||
|
|
|
@ -2273,16 +2273,16 @@ impl<'a, 'b> ImportResolver<'a, 'b> {
|
|||
|
||||
/// Given a `binding_span` of a binding within a use statement:
|
||||
///
|
||||
/// ```
|
||||
/// ```ignore (illustrative)
|
||||
/// use foo::{a, b, c};
|
||||
/// ^
|
||||
/// // ^
|
||||
/// ```
|
||||
///
|
||||
/// then return the span until the next binding or the end of the statement:
|
||||
///
|
||||
/// ```
|
||||
/// ```ignore (illustrative)
|
||||
/// use foo::{a, b, c};
|
||||
/// ^^^
|
||||
/// // ^^^
|
||||
/// ```
|
||||
fn find_span_of_binding_until_next_binding(
|
||||
sess: &Session,
|
||||
|
@ -2326,14 +2326,14 @@ fn find_span_of_binding_until_next_binding(
|
|||
/// Given a `binding_span`, return the span through to the comma or opening brace of the previous
|
||||
/// binding.
|
||||
///
|
||||
/// ```
|
||||
/// ```ignore (illustrative)
|
||||
/// use foo::a::{a, b, c};
|
||||
/// ^^--- binding span
|
||||
/// |
|
||||
/// returned span
|
||||
/// // ^^--- binding span
|
||||
/// // |
|
||||
/// // returned span
|
||||
///
|
||||
/// use foo::{a, b, c};
|
||||
/// --- binding span
|
||||
/// // --- binding span
|
||||
/// ```
|
||||
fn extend_span_to_previous_binding(sess: &Session, binding_span: Span) -> Option<Span> {
|
||||
let source_map = sess.source_map();
|
||||
|
@ -2369,15 +2369,15 @@ fn extend_span_to_previous_binding(sess: &Session, binding_span: Span) -> Option
|
|||
/// Given a `use_span` of a binding within a use statement, returns the highlighted span and if
|
||||
/// it is a nested use tree.
|
||||
///
|
||||
/// ```
|
||||
/// ```ignore (illustrative)
|
||||
/// use foo::a::{b, c};
|
||||
/// ^^^^^^^^^^ // false
|
||||
/// // ^^^^^^^^^^ -- false
|
||||
///
|
||||
/// use foo::{a, b, c};
|
||||
/// ^^^^^^^^^^ // true
|
||||
/// // ^^^^^^^^^^ -- true
|
||||
///
|
||||
/// use foo::{a, b::{c, d}};
|
||||
/// ^^^^^^^^^^^^^^^ // true
|
||||
/// // ^^^^^^^^^^^^^^^ -- true
|
||||
/// ```
|
||||
fn find_span_immediately_after_crate_name(
|
||||
sess: &Session,
|
||||
|
|
|
@ -401,7 +401,7 @@ pub fn provide(providers: &mut ty::query::Providers) {
|
|||
/// The reason for this separate call is to resolve what would otherwise
|
||||
/// be a cycle. Consider this example:
|
||||
///
|
||||
/// ```rust
|
||||
/// ```ignore UNSOLVED (maybe @jackh726 knows what lifetime parameter to give Sub)
|
||||
/// trait Base<'a> {
|
||||
/// type BaseItem;
|
||||
/// }
|
||||
|
@ -2552,7 +2552,7 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
|
|||
/// Returns all the late-bound vars that come into scope from supertrait HRTBs, based on the
|
||||
/// associated type name and starting trait.
|
||||
/// For example, imagine we have
|
||||
/// ```rust
|
||||
/// ```ignore (illustrative)
|
||||
/// trait Foo<'a, 'b> {
|
||||
/// type As;
|
||||
/// }
|
||||
|
|
|
@ -686,7 +686,7 @@ impl SyntaxContext {
|
|||
/// context up one macro definition level. That is, if we have a nested macro
|
||||
/// definition as follows:
|
||||
///
|
||||
/// ```rust
|
||||
/// ```ignore (illustrative)
|
||||
/// macro_rules! f {
|
||||
/// macro_rules! g {
|
||||
/// ...
|
||||
|
@ -710,6 +710,7 @@ impl SyntaxContext {
|
|||
/// For example, consider the following three resolutions of `f`:
|
||||
///
|
||||
/// ```rust
|
||||
/// #![feature(decl_macro)]
|
||||
/// mod foo { pub fn f() {} } // `f`'s `SyntaxContext` is empty.
|
||||
/// m!(f);
|
||||
/// macro m($f:ident) {
|
||||
|
@ -746,7 +747,8 @@ impl SyntaxContext {
|
|||
/// via a glob import with the given `SyntaxContext`.
|
||||
/// For example:
|
||||
///
|
||||
/// ```rust
|
||||
/// ```compile_fail,E0425
|
||||
/// #![feature(decl_macro)]
|
||||
/// m!(f);
|
||||
/// macro m($i:ident) {
|
||||
/// mod foo {
|
||||
|
@ -786,7 +788,7 @@ impl SyntaxContext {
|
|||
|
||||
/// Undo `glob_adjust` if possible:
|
||||
///
|
||||
/// ```rust
|
||||
/// ```ignore (illustrative)
|
||||
/// if let Some(privacy_checking_scope) = self.reverse_glob_adjust(expansion, glob_ctxt) {
|
||||
/// assert!(self.glob_adjust(expansion, glob_ctxt) == Some(privacy_checking_scope));
|
||||
/// }
|
||||
|
|
|
@ -1058,10 +1058,11 @@ impl SourceMap {
|
|||
|
||||
/// Tries to find the span of the semicolon of a macro call statement.
|
||||
/// The input must be the *call site* span of a statement from macro expansion.
|
||||
///
|
||||
/// v output
|
||||
/// ```ignore (illustrative)
|
||||
/// // v output
|
||||
/// mac!();
|
||||
/// ^^^^^^ input
|
||||
/// // ^^^^^^ input
|
||||
/// ```
|
||||
pub fn mac_call_stmt_semi_span(&self, mac_call: Span) -> Option<Span> {
|
||||
let span = self.span_extend_while(mac_call, char::is_whitespace).ok()?;
|
||||
let span = span.shrink_to_hi().with_hi(BytePos(span.hi().0.checked_add(1)?));
|
||||
|
|
|
@ -22,11 +22,11 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
|
|||
/// (*), computes the "definition type" for an opaque type
|
||||
/// definition -- that is, the inferred value of `Foo1<'x>` or
|
||||
/// `Foo2<'x>` that we would conceptually use in its definition:
|
||||
///
|
||||
/// type Foo1<'x> = impl Bar<'x> = AAA; <-- this type AAA
|
||||
/// type Foo2<'x> = impl Bar<'x> = BBB; <-- or this type BBB
|
||||
/// ```ignore (illustrative)
|
||||
/// type Foo1<'x> = impl Bar<'x> = AAA; // <-- this type AAA
|
||||
/// type Foo2<'x> = impl Bar<'x> = BBB; // <-- or this type BBB
|
||||
/// fn foo<'a, 'b>(..) -> (Foo1<'a>, Foo2<'b>) { .. }
|
||||
///
|
||||
/// ```
|
||||
/// Note that these values are defined in terms of a distinct set of
|
||||
/// generic parameters (`'x` instead of `'a`) from C1 or C2. The main
|
||||
/// purpose of this function is to do that translation.
|
||||
|
|
|
@ -255,9 +255,9 @@ impl<'tcx> AutoTraitFinder<'tcx> {
|
|||
/// `FulfillmentContext` will drive `SelectionContext` to consider that impl before giving up.
|
||||
/// If we were to rely on `FulfillmentContext`s decision, we might end up synthesizing an impl
|
||||
/// like this:
|
||||
///
|
||||
/// ```ignore (illustrative)
|
||||
/// impl<T> Send for Foo<T> where T: IntoIterator
|
||||
///
|
||||
/// ```
|
||||
/// While it might be technically true that Foo implements Send where `T: IntoIterator`,
|
||||
/// the bound is overly restrictive - it's really only necessary that `T: Iterator`.
|
||||
///
|
||||
|
@ -420,10 +420,10 @@ impl<'tcx> AutoTraitFinder<'tcx> {
|
|||
/// two trait predicates that differ only in their region parameters:
|
||||
/// one containing a HRTB lifetime parameter, and one containing a 'normal'
|
||||
/// lifetime parameter. For example:
|
||||
///
|
||||
/// ```ignore (illustrative)
|
||||
/// T as MyTrait<'a>
|
||||
/// T as MyTrait<'static>
|
||||
///
|
||||
/// ```
|
||||
/// If we put both of these predicates in our computed `ParamEnv`, we'll
|
||||
/// confuse `SelectionContext`, since it will (correctly) view both as being applicable.
|
||||
///
|
||||
|
|
|
@ -547,7 +547,7 @@ pub fn orphan_check(tcx: TyCtxt<'_>, impl_def_id: DefId) -> Result<(), OrphanChe
|
|||
/// 2. They ground negative reasoning for coherence. If a user wants to
|
||||
/// write both a conditional blanket impl and a specific impl, we need to
|
||||
/// make sure they do not overlap. For example, if we write
|
||||
/// ```
|
||||
/// ```ignore (illustrative)
|
||||
/// impl<T> IntoIterator for Vec<T>
|
||||
/// impl<T: Iterator> IntoIterator for T
|
||||
/// ```
|
||||
|
|
|
@ -595,7 +595,7 @@ fn object_ty_for_trait<'tcx>(
|
|||
/// - let `Receiver` be the type of the `self` argument, i.e `Self`, `&Self`, `Rc<Self>`,
|
||||
/// - require the following bound:
|
||||
///
|
||||
/// ```
|
||||
/// ```ignore (not-rust)
|
||||
/// Receiver[Self => T]: DispatchFromDyn<Receiver[Self => dyn Trait]>
|
||||
/// ```
|
||||
///
|
||||
|
@ -621,13 +621,13 @@ fn object_ty_for_trait<'tcx>(
|
|||
/// Instead, we fudge a little by introducing a new type parameter `U` such that
|
||||
/// `Self: Unsize<U>` and `U: Trait + ?Sized`, and use `U` in place of `dyn Trait`.
|
||||
/// Written as a chalk-style query:
|
||||
///
|
||||
/// ```ignore (not-rust)
|
||||
/// forall (U: Trait + ?Sized) {
|
||||
/// if (Self: Unsize<U>) {
|
||||
/// Receiver: DispatchFromDyn<Receiver[Self => U]>
|
||||
/// }
|
||||
/// }
|
||||
///
|
||||
/// ```
|
||||
/// for `self: &'a mut Self`, this means `&'a mut Self: DispatchFromDyn<&'a mut U>`
|
||||
/// for `self: Rc<Self>`, this means `Rc<Self>: DispatchFromDyn<Rc<U>>`
|
||||
/// for `self: Pin<Box<Self>>`, this means `Pin<Box<Self>>: DispatchFromDyn<Pin<Box<U>>>`
|
||||
|
|
|
@ -158,9 +158,9 @@ pub(super) enum ProjectAndUnifyResult<'tcx> {
|
|||
}
|
||||
|
||||
/// Evaluates constraints of the form:
|
||||
///
|
||||
/// ```ignore (not-rust)
|
||||
/// for<...> <T as Trait>::U == V
|
||||
///
|
||||
/// ```
|
||||
/// If successful, this may result in additional obligations. Also returns
|
||||
/// the projection cache key used to track these additional obligations.
|
||||
///
|
||||
|
@ -224,9 +224,9 @@ pub(super) fn poly_project_and_unify_type<'cx, 'tcx>(
|
|||
}
|
||||
|
||||
/// Evaluates constraints of the form:
|
||||
///
|
||||
/// ```ignore (not-rust)
|
||||
/// <T as Trait>::U == V
|
||||
///
|
||||
/// ```
|
||||
/// If successful, this may result in additional obligations.
|
||||
///
|
||||
/// See [poly_project_and_unify_type] for an explanation of the return value.
|
||||
|
@ -1258,7 +1258,7 @@ fn assemble_candidates_from_param_env<'cx, 'tcx>(
|
|||
/// In the case of a nested projection like <<A as Foo>::FooT as Bar>::BarT, we may find
|
||||
/// that the definition of `Foo` has some clues:
|
||||
///
|
||||
/// ```
|
||||
/// ```ignore (illustrative)
|
||||
/// trait Foo {
|
||||
/// type FooT : Bar<BarT=i32>
|
||||
/// }
|
||||
|
|
|
@ -712,9 +712,9 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
|||
/// and we desugared it so that the type of the expression is
|
||||
/// `Closure`, and `Closure` expects `i32` as argument. Then it
|
||||
/// is "as if" the compiler generated this impl:
|
||||
///
|
||||
/// ```ignore (illustrative)
|
||||
/// impl Fn(i32) for Closure { ... }
|
||||
///
|
||||
/// ```
|
||||
/// Now imagine our obligation is `Closure: Fn(usize)`. So far
|
||||
/// we have matched the self type `Closure`. At this point we'll
|
||||
/// compare the `i32` to `usize` and generate an error.
|
||||
|
|
|
@ -1933,7 +1933,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
|||
///
|
||||
/// Here are some (simple) examples:
|
||||
///
|
||||
/// ```
|
||||
/// ```ignore (illustrative)
|
||||
/// (i32, u32) -> [i32, u32]
|
||||
/// Foo where struct Foo { x: i32, y: u32 } -> [i32, u32]
|
||||
/// Bar<i32> where struct Bar<T> { x: T, y: u32 } -> [i32, u32]
|
||||
|
|
|
@ -52,7 +52,7 @@ pub struct OverlapError {
|
|||
///
|
||||
/// For example, consider the following scenario:
|
||||
///
|
||||
/// ```rust
|
||||
/// ```ignore (illustrative)
|
||||
/// trait Foo { ... }
|
||||
/// impl<T, U> Foo for (T, U) { ... } // target impl
|
||||
/// impl<V> Foo for (V, V) { ... } // source impl
|
||||
|
@ -64,7 +64,7 @@ pub struct OverlapError {
|
|||
/// where-clauses add some trickiness here, because they can be used to "define"
|
||||
/// an argument indirectly:
|
||||
///
|
||||
/// ```rust
|
||||
/// ```ignore (illustrative)
|
||||
/// impl<'a, I, T: 'a> Iterator for Cloned<I>
|
||||
/// where I: Iterator<Item = &'a T>, T: Clone
|
||||
/// ```
|
||||
|
|
|
@ -170,7 +170,7 @@ struct WfPredicates<'a, 'tcx> {
|
|||
/// predicates. This is a kind of hack to address #43784. The
|
||||
/// underlying problem in that issue was a trait structure like:
|
||||
///
|
||||
/// ```
|
||||
/// ```ignore (illustrative)
|
||||
/// trait Foo: Copy { }
|
||||
/// trait Bar: Foo { }
|
||||
/// impl<T: Bar> Foo for T { }
|
||||
|
|
|
@ -122,16 +122,16 @@ rustc_index::newtype_index! {
|
|||
/// A [De Bruijn index][dbi] is a standard means of representing
|
||||
/// regions (and perhaps later types) in a higher-ranked setting. In
|
||||
/// particular, imagine a type like this:
|
||||
///
|
||||
/// ```ignore (illustrative)
|
||||
/// for<'a> fn(for<'b> fn(&'b isize, &'a isize), &'a char)
|
||||
/// ^ ^ | | |
|
||||
/// | | | | |
|
||||
/// | +------------+ 0 | |
|
||||
/// | | |
|
||||
/// +----------------------------------+ 1 |
|
||||
/// | |
|
||||
/// +----------------------------------------------+ 0
|
||||
///
|
||||
/// // ^ ^ | | |
|
||||
/// // | | | | |
|
||||
/// // | +------------+ 0 | |
|
||||
/// // | | |
|
||||
/// // +----------------------------------+ 1 |
|
||||
/// // | |
|
||||
/// // +----------------------------------------------+ 0
|
||||
/// ```
|
||||
/// In this type, there are two binders (the outer fn and the inner
|
||||
/// fn). We need to be able to determine, for any given region, which
|
||||
/// fn type it is bound by, the inner or the outer one. There are
|
||||
|
@ -203,7 +203,7 @@ impl DebruijnIndex {
|
|||
/// it will now be bound at INNERMOST. This is an appropriate thing to do
|
||||
/// when moving a region out from inside binders:
|
||||
///
|
||||
/// ```
|
||||
/// ```ignore (illustrative)
|
||||
/// for<'a> fn(for<'b> for<'c> fn(&'a u32), _)
|
||||
/// // Binder: D3 D2 D1 ^^
|
||||
/// ```
|
||||
|
@ -471,9 +471,9 @@ impl Variance {
|
|||
/// variance with which the argument appears.
|
||||
///
|
||||
/// Example 1:
|
||||
///
|
||||
/// ```ignore (illustrative)
|
||||
/// *mut Vec<i32>
|
||||
///
|
||||
/// ```
|
||||
/// Here, the "ambient" variance starts as covariant. `*mut T` is
|
||||
/// invariant with respect to `T`, so the variance in which the
|
||||
/// `Vec<i32>` appears is `Covariant.xform(Invariant)`, which
|
||||
|
@ -483,9 +483,9 @@ impl Variance {
|
|||
/// (again) in `Invariant`.
|
||||
///
|
||||
/// Example 2:
|
||||
///
|
||||
/// ```ignore (illustrative)
|
||||
/// fn(*const Vec<i32>, *mut Vec<i32)
|
||||
///
|
||||
/// ```
|
||||
/// The ambient variance is covariant. A `fn` type is
|
||||
/// contravariant with respect to its parameters, so the variance
|
||||
/// within which both pointer types appear is
|
||||
|
|
|
@ -294,9 +294,9 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
|
|||
///
|
||||
/// Example:
|
||||
///
|
||||
/// ```
|
||||
/// ```ignore (illustrative)
|
||||
/// T: std::ops::Index<usize, Output = u32>
|
||||
/// ^1 ^^^^^^^^^^^^^^2 ^^^^3 ^^^^^^^^^^^4
|
||||
/// // ^1 ^^^^^^^^^^^^^^2 ^^^^3 ^^^^^^^^^^^4
|
||||
/// ```
|
||||
///
|
||||
/// 1. The `self_ty` here would refer to the type `T`.
|
||||
|
@ -310,7 +310,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
|
|||
///
|
||||
/// For (generic) associated types
|
||||
///
|
||||
/// ```
|
||||
/// ```ignore (illustrative)
|
||||
/// <Vec<u8> as Iterable<u8>>::Iter::<'a>
|
||||
/// ```
|
||||
///
|
||||
|
@ -756,7 +756,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
|
|||
///
|
||||
/// Example:
|
||||
///
|
||||
/// ```
|
||||
/// ```ignore (illustrative)
|
||||
/// poly_trait_ref = Iterator<Item = u32>
|
||||
/// self_ty = Foo
|
||||
/// ```
|
||||
|
@ -1021,10 +1021,10 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
|
|||
///
|
||||
/// Example:
|
||||
///
|
||||
/// ```
|
||||
/// ```ignore (illustrative)
|
||||
/// fn foo<T: Bar + Baz>() { }
|
||||
/// ^ ^^^^^^^^^ ast_bounds
|
||||
/// param_ty
|
||||
/// // ^ ^^^^^^^^^ ast_bounds
|
||||
/// // param_ty
|
||||
/// ```
|
||||
///
|
||||
/// The `sized_by_default` parameter indicates if, in this context, the `param_ty` should be
|
||||
|
|
|
@ -371,7 +371,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// ```ignore (illustrative)
|
||||
/// fn with_closure<F>(_: F)
|
||||
/// where F: Fn(&u32) -> &u32 { .. }
|
||||
///
|
||||
|
|
|
@ -21,7 +21,7 @@
|
|||
//! When inferring the generic arguments of functions, the argument
|
||||
//! order is relevant, which can lead to the following edge case:
|
||||
//!
|
||||
//! ```rust
|
||||
//! ```ignore (illustrative)
|
||||
//! fn foo<T>(a: T, b: T) {
|
||||
//! // ...
|
||||
//! }
|
||||
|
@ -1210,7 +1210,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
///
|
||||
/// Example:
|
||||
///
|
||||
/// ```
|
||||
/// ```ignore (illustrative)
|
||||
/// let mut coerce = CoerceMany::new(expected_ty);
|
||||
/// for expr in exprs {
|
||||
/// let expr_ty = fcx.check_expr_with_expectation(expr, expected);
|
||||
|
|
|
@ -439,7 +439,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
/// Identify some cases where `as_ref()` would be appropriate and suggest it.
|
||||
///
|
||||
/// Given the following code:
|
||||
/// ```
|
||||
/// ```compile_fail,E0308
|
||||
/// struct Foo;
|
||||
/// fn takes_ref(_: &Foo) {}
|
||||
/// let ref opt = Some(Foo);
|
||||
|
@ -449,7 +449,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
/// Suggest using `opt.as_ref().map(|param| takes_ref(param));` instead.
|
||||
///
|
||||
/// It only checks for `Option` and `Result` and won't work with
|
||||
/// ```
|
||||
/// ```ignore (illustrative)
|
||||
/// opt.map(|param| { takes_ref(param) });
|
||||
/// ```
|
||||
fn can_use_as_ref(&self, expr: &hir::Expr<'_>) -> Option<(Span, &'static str, String)> {
|
||||
|
@ -566,7 +566,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
/// This function is used to determine potential "simple" improvements or users' errors and
|
||||
/// provide them useful help. For example:
|
||||
///
|
||||
/// ```
|
||||
/// ```compile_fail,E0308
|
||||
/// fn some_fn(s: &str) {}
|
||||
///
|
||||
/// let x = "hey!".to_owned();
|
||||
|
|
|
@ -144,6 +144,7 @@ impl<'tcx> FnCtxt<'_, 'tcx> {
|
|||
/// code. The most common case is something like this:
|
||||
///
|
||||
/// ```rust
|
||||
/// # fn foo() -> i32 { 4 }
|
||||
/// match foo() {
|
||||
/// 22 => Default::default(), // call this type `?D`
|
||||
/// _ => return, // return has type `!`
|
||||
|
@ -168,7 +169,7 @@ impl<'tcx> FnCtxt<'_, 'tcx> {
|
|||
/// fallback to use based on whether there is a coercion pattern
|
||||
/// like this:
|
||||
///
|
||||
/// ```
|
||||
/// ```ignore (not-rust)
|
||||
/// ?Diverging -> ?V
|
||||
/// ?NonDiverging -> ?V
|
||||
/// ?V != ?NonDiverging
|
||||
|
|
|
@ -1467,7 +1467,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
|
||||
/// A common error is to add an extra semicolon:
|
||||
///
|
||||
/// ```
|
||||
/// ```compile_fail,E0308
|
||||
/// fn foo() -> usize {
|
||||
/// 22;
|
||||
/// }
|
||||
|
|
|
@ -72,7 +72,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
|
||||
/// When encountering an fn-like ctor that needs to unify with a value, check whether calling
|
||||
/// the ctor would successfully solve the type mismatch and if so, suggest it:
|
||||
/// ```
|
||||
/// ```compile_fail,E0308
|
||||
/// fn foo(x: usize) -> usize { x }
|
||||
/// let x: usize = foo; // suggest calling the `foo` function: `foo(42)`
|
||||
/// ```
|
||||
|
@ -463,7 +463,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
|
||||
/// A common error is to forget to add a semicolon at the end of a block, e.g.,
|
||||
///
|
||||
/// ```
|
||||
/// ```compile_fail,E0308
|
||||
/// # fn bar_that_returns_u32() -> u32 { 4 }
|
||||
/// fn foo() {
|
||||
/// bar_that_returns_u32()
|
||||
/// }
|
||||
|
@ -504,7 +505,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
|
||||
/// A possible error is to forget to add a return type that is needed:
|
||||
///
|
||||
/// ```
|
||||
/// ```compile_fail,E0308
|
||||
/// # fn bar_that_returns_u32() -> u32 { 4 }
|
||||
/// fn foo() {
|
||||
/// bar_that_returns_u32()
|
||||
/// }
|
||||
|
@ -569,7 +571,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
/// check whether the return type is a generic type with a trait bound
|
||||
/// only suggest this if the generic param is not present in the arguments
|
||||
/// if this is true, hint them towards changing the return type to `impl Trait`
|
||||
/// ```
|
||||
/// ```compile_fail,E0308
|
||||
/// fn cant_name_it<T: Fn() -> u32>() -> T {
|
||||
/// || 3
|
||||
/// }
|
||||
|
|
|
@ -71,7 +71,7 @@ pub(super) fn build_control_flow_graph<'tcx>(
|
|||
/// ```
|
||||
///
|
||||
/// Rule 3:
|
||||
/// ```rust
|
||||
/// ```compile_fail,E0382
|
||||
/// let mut a = (vec![0], vec![0]);
|
||||
/// drop(a);
|
||||
/// a.1 = vec![1];
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Reference in a new issue