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
/// };
}
/// Desugar `<expr>.await` into:
- /// ```rust
+ /// ```ignore (pseudo-rust)
/// match ::std::future::IntoFuture::into_future(<expr>) {
/// mut __awaitee => loop {
/// match unsafe { ::std::future::Future::poll(
}
/// Desugar `ExprForLoop` from: `[opt_ident]: for <pat> in <head> <body>` into:
- /// ```rust
+ /// ```ignore (pseudo-rust)
/// {
/// let result = match IntoIterator::into_iter(<head>) {
/// mut iter => {
}
/// Desugar `ExprKind::Try` from: `<expr>?` into:
- /// ```rust
+ /// ```ignore (pseudo-rust)
/// match Try::branch(<expr>) {
/// ControlFlow::Continue(val) => #[allow(unreachable_code)] val,,
/// ControlFlow::Break(residual) =>
/// Given an associated type constraint like one of these:
///
- /// ```
+ /// ```ignore (illustrative)
/// T: Iterator<Item: Debug>
/// ^^^^^^^^^^^
/// T: Iterator<Item = Debug>
//! 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,
/// 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 },
}
///
/// 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", "", "")
- ///
+ /// ```
+ /// ("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")
- ///
+ /// ```
+ /// ("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")
- ///
+ /// ```
+ /// ("x.u", "x.u.z", "x.u.y")
+ /// # ;
+ /// ```
/// This is used when creating error messages like below:
///
/// ```text
/// 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 }
/// ```
///
/// Suppose we are trying to give a name to the lifetime of the
/// reference `x`:
///
- /// ```
+ /// ```ignore (pseudo-rust)
/// fn foo(x: &u32) { .. }
/// ```
///
/// 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>`,
/// 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] {
///
/// 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(
/// minimum values.
///
/// For example:
- ///
- /// fn foo<'a, 'b>(..) where 'a: 'b
- ///
+ /// ```
+ /// fn foo<'a, 'b>( /* ... */ ) where 'a: 'b { /* ... */ }
+ /// ```
/// would initialize two variables like so:
- ///
- /// R0 = { CFG, R0 } // 'a
- /// R1 = { CFG, R0, R1 } // 'b
- ///
+ /// ```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
/// 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:
- ///
- /// fn foo<'a, 'b>(x: &'a u32) -> &'b u32 { x }
- ///
+ /// ```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
/// <https://smallcultfollowing.com/babysteps/blog/2019/01/17/polonius-and-region-errors/>
///
/// In the canonical example
- ///
- /// fn foo<'a, 'b>(x: &'a u32) -> &'b u32 { x }
- ///
+ /// ```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.
/// 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
///
/// 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
/// }
/// ```
///
//!
//! 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> {
//! 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)]
//!
//! would yield functions like:
//!
-//! ```
+//! ```ignore (old code)
//! # #[derive(RustcEncodable, RustcDecodable)]
//! # struct Span;
//! # struct Spanned<T> { node: T, span: Span }
/// }
/// }
/// }
- ///
- /// // 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 {
/// // 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
/// }
/// }
///
/// 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;
///
/// At a high level Thin LTO looks like:
///
-/// 1. Prepare a "summary" of each LLVM module in question which describes
-/// the values inside, cost of the values, etc.
-/// 2. Merge the summaries of all modules in question into one "index"
-/// 3. Perform some global analysis on this index
-/// 4. For each module, use the index and analysis calculated previously to
-/// perform local transformations on the module, for example inlining
-/// small functions from other modules.
-/// 5. Run thin-specific optimization passes over each module, and then code
-/// generate everything at the end.
+/// 1. Prepare a "summary" of each LLVM module in question which describes
+/// the values inside, cost of the values, etc.
+/// 2. Merge the summaries of all modules in question into one "index"
+/// 3. Perform some global analysis on this index
+/// 4. For each module, use the index and analysis calculated previously to
+/// perform local transformations on the module, for example inlining
+/// small functions from other modules.
+/// 5. Run thin-specific optimization passes over each module, and then code
+/// generate everything at the end.
///
/// The summary for each module is intended to be quite cheap, and the global
/// index is relatively quite cheap to create as well. As a result, the goal of
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.
will generate the following callstack with a naive DFS algorithm:
-```
+```ignore (illustrative)
describe(t = List)
describe(t = i32)
describe(t = Option<Box<List>>)
//! `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 {
/// with this node.
///
/// The non-`Error` state transitions are as follows.
-/// ```
+/// ```text
/// (Pre-creation)
/// |
/// | register_obligation_at() (called by process_obligations() and
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];
## 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.
## 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 {
## 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]);
## 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())
## 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() {
## 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() {
## 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() {
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() {
///
/// # 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));
///
/// # 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]));
///
/// # 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]));
///
/// # 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.
/// 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);
///
/// # 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));
///
/// # 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]));
///
/// # 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]));
///
/// # 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]));
///
/// # 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]));
///
/// # 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.
/// 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);
/// 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;
/// (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 ---+
/// `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")] },
///
/// or by replacing the entire span:
///
- /// ```
+ /// ```ignore (illustrative)
/// vec![
/// Substitution { parts: vec![(0..7, "a.b")] },
/// Substitution { parts: vec![(0..7, "x.y")] },
//!
//! ## Meta-variables must not be bound twice
//!
-//! ```
+//! ```compile_fail
//! macro_rules! foo { ($x:tt $x:tt) => { $x }; }
//! ```
//!
/// Kleene operators of its binder as a prefix.
///
/// Consider $i in the following example:
-///
-/// ( $( $i:ident = $($j:ident),+ );* ) => { $($( $i += $j; )+)* }
-///
+/// ```ignore (illustrative)
+/// ( $( $i:ident = $($j:ident),+ );* ) => { $($( $i += $j; )+)* }
+/// ```
/// It occurs under the Kleene stack ["*", "+"] and is bound under ["*"] only.
///
/// Arguments:
///
/// Then, the tree will have the following shape:
///
-/// ```rust
+/// ```ignore (private-internal)
+/// # use NamedMatch::*;
/// MatchedSeq([
/// MatchedSeq([
/// MatchedNonterminal(a),
/// 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>()]);
/// Synthetic name generated when user elided a lifetime in an impl header.
///
/// E.g., the lifetimes in cases like these:
- ///
- /// impl Foo for &u32
- /// impl Foo<'_> for u32
- ///
+ /// ```ignore (fragment)
+ /// impl Foo for &u32
+ /// impl Foo<'_> for u32
+ /// ```
/// in that case, we rewrite to
- ///
- /// impl<'f> Foo for &'f u32
- /// impl<'f> Foo<'f> for u32
- ///
+ /// ```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),
/// 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>]),
/// wouldn't it be better to make the `ty` field an enum like the
/// following?
///
-/// ```
+/// ```ignore (pseudo-rust)
/// enum TypeBindingKind {
/// Equals(...),
/// Binding(...),
//!
//! Example:
//!
-//! ```
+//! ```ignore (needs flags)
//! #[rustc_if_this_changed(Hir)]
//! fn foo() { }
//!
//! 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")]
//! ```
//! 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
//!
//!
//! 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
///
/// 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
- ///
- /// impl<T> Trait<'static> for T { .. }
- ///
+ /// ```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
///
/// 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] {
///
/// For the following code:
///
- /// ```no_run
+ /// ```ignore (illustrative)
/// let x: Foo<Bar<Qux>> = foo::<Bar<Qux>>();
/// ```
///
/// A possible error is to forget to add `.await` when using futures:
///
- /// ```
+ /// ```compile_fail,E0308
/// async fn make_u32() -> u32 {
/// 22
/// }
///
/// Consider a case where we have
///
- /// ```no_run
+ /// ```compile_fail,E0623
/// fn foo(x: &mut Vec<&u8>, y: &u8) {
/// x.push(y);
/// }
/// 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); }
/// ```
/// 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
/// 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`
/// 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 { /* ... */ }
/// }
/// ```
///
///
/// Example:
///
- /// ```
+ /// ```ignore (pseudo-rust)
/// fn foo<T>() {
/// callback(for<'a> |x: &'a T| {
/// // ^^^^^^^ not legal syntax, but probably should be
//! 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
//! }
//! ```
///
/// 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
/// {
/// Describes the things that some `GenericKind` value `G` is known to
/// outlive. Each variant of `VerifyBound` can be thought of as a
/// function:
-///
-/// fn(min: Region) -> bool { .. }
-///
+/// ```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:
-///
-/// fn(min: Region) -> bool {
-/// ('a: min) || ('b: min)
-/// }
-///
+/// ```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> {
/// 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)
///
/// So we would compile to a verify-bound like
///
- /// ```
+ /// ```ignore (illustrative)
/// IfEq(<T as Trait<'a>>::Item, AnyRegion('a))
/// ```
///
/// Given a region `R`, expands to the function:
///
- /// ```
+ /// ```ignore (pseudo-rust)
/// fn(min) -> bool {
/// R: min
/// }
/// Given a set of bounds `B`, expands to the function:
///
- /// ```rust
+ /// ```ignore (pseudo-rust)
/// fn(min) -> bool {
/// exists (b in B) { b(min) }
/// }
/// Given a set of bounds `B`, expands to the function:
///
- /// ```rust
+ /// ```ignore (pseudo-rust)
/// fn(min) -> bool {
/// forall (b in B) { b(min) }
/// }
/// table exists only to help with the occurs check. In particular,
/// we want to report constraints like these as an occurs check
/// violation:
- ///
- /// ?1 <: ?3
- /// Box<?3> <: ?1
- ///
+ /// ``` 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>`
/// 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:
- ///
- /// exists X. (a <: X || X <: a) && (b <: X || X <: b)
+ /// ```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)
}
///
/// ### Example
///
- /// ```rust,compile_fail
+ /// ```compile_fail
+ /// #![deny(unaligned_references)]
/// #[repr(packed)]
/// pub struct Foo {
/// field1: u64,
/// }
/// ```
///
- /// ```
+ /// ```compile_fail,E0308
/// fn foo(x: usize) -> bool {
/// loop {
/// true // If `get_return_block` gets passed the `id` corresponding
/// 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)]
///
/// 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:
- ///
- /// 00000000|00000000
- /// ^ ^ ^ ^
- /// index: 0 7 8 15
- ///
+ /// ```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,
/// 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:
- ///
- /// let mut x = &Some(0);
- /// match *x {
- /// None => (),
- /// Some(_) if { x = &None; false } => (),
- /// Some(_) => (),
- /// }
- ///
+ /// ```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`.
/// 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 y = || *x += 5;
- ///
+ /// ```
+ /// 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
- /// fn fn_ptr(env: &mut Env) { **env.x += 5; }
- ///
+ /// ```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
- /// fn fn_ptr(env: &mut Env) { **env.x += 5; }
- ///
+ /// ```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
/// ```
/// fn foo(x: &str) {
/// match {
- /// match x.parse().unwrap() {
+ /// match x.parse::<u32>().unwrap() {
/// y => y + 2
/// }
/// } {
/// Encodes a user's type ascription. These need to be preserved
/// intact so that NLL can respect them. For example:
- ///
- /// let a: T = y;
- ///
+ /// ```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:
///
/// 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 },
///
/// An example:
///
-/// ```rust
+/// ```ignore (illustrative)
/// struct S<'a>((i32, &'a str), String);
/// let S((_, w): (i32, &'static str), _): S = ...;
/// // ------ ^^^^^^^^^^^^^^^^^^^ (1)
///
/// 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>
/// ```
/// 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)
/// }
///
/// becomes
///
- /// ```
+ /// ```ignore (MIR)
/// BB0 {
/// Drop(P, goto BB1, unwind BB2)
/// }
//!
//! 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>) {
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:
- ///
- /// z = x.y;
- /// f(&x.y);
- ///
+ /// ```ignore (illustrative)
+ /// z = x.y;
+ /// f(&x.y);
+ /// ```
Projection,
}
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:
- ///
- /// x.y = ...;
- /// f(&mut x.y);
- ///
+ /// ```ignore (illustrative)
+ /// x.y = ...;
+ /// f(&mut x.y);
+ /// ```
Projection,
/// Retagging, a "Stacked Borrows" shadow state operation
Retag,
/// impl. Concretely, that means that the following example will
/// fail to compile:
///
- /// ```
+ /// ```compile_fail,E0308
+ /// #![feature(specialization)]
/// trait Assoc {
/// type Output;
/// }
/// }
///
/// fn main() {
- /// let <() as Assoc>::Output = true;
+ /// let x: <() as Assoc>::Output = true;
/// }
/// ```
UserFacing,
/// 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
/// Example:
///
/// ```
+ /// #![feature(specialization)]
/// trait Tr {
/// fn assoc(&self);
/// }
/// 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],
///
/// is essentially represented with [`Ty`] as the following pseudocode:
///
-/// ```
+/// ```ignore (illustrative)
/// struct S { x }
/// ```
///
/// let mut t = (0,1);
///
/// let c = || {
- /// println!("{t}"); // L1
+ /// println!("{t:?}"); // L1
/// t.1 = 4; // L2
/// };
/// ```
/// let x = 5;
///
/// let c = || {
- /// let _ = x
+ /// let _ = x;
/// };
/// ```
///
/// 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; }
/// ```
///
/// 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; }
/// ```
///
/// # 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
/// ```
///
///
/// The *liberated* form of this would be
///
- /// ```
+ /// ```ignore (illustrative)
/// fn(&'a u32) -> u32
/// ```
///
//!
//! 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
/// traversed. If we encounter a bound region bound by this
/// binder or one outer to it, it appears free. Example:
///
- /// ```
- /// 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`
+ /// ```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`
/// ```
///
/// You see that, initially, *any* bound value is free,
/// 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 {
/// }
///
/// mod c {
+ /// use super::Void;
/// pub struct AlsoSecretlyUninhabited {
/// _priv: Void,
/// }
/// contain `Foo`.
///
/// # Example
- /// ```rust
+ /// ```ignore (illustrative)
/// let foo_result: Result<T, Foo> = ... ;
/// let Ok(t) = foo_result;
/// ```
/// 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) { ... }
/// ```
///
/// their values.
///
/// Example:
-///
-/// struct Foo<T, U: Bar<T>> { ... }
-///
+/// ```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 `[[],
/// 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:
- ///
- /// Foo<'a, T> = ?C
- ///
+ /// ```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
///
/// 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) = ...;
/// corresponds to entering a `forall` quantifier. So, for
/// example, suppose we have this type in universe `U`:
///
- /// ```
+ /// ```ignore (illustrative)
/// for<'a> fn(&'a u32)
/// ```
///
/// 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 {}
/// 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>>>),
static_assert_size!(TyKind<'_>, 32);
/// A closure can be modeled as a struct that looks like:
-///
-/// struct Closure<'l0...'li, T0...Tj, CK, CS, U>(...U);
-///
+/// ```ignore (illustrative)
+/// struct Closure<'l0...'li, T0...Tj, CK, CS, U>(...U);
+/// ```
/// where:
///
/// - 'l0...'li and T0...Tj are the generic parameters
/// and the up-var has the type `Foo`, then that field of U will be `&Foo`).
///
/// So, for example, given this function:
-///
-/// fn foo<'a, T>(data: &'a mut T) {
-/// do(|| data.count += 1)
-/// }
-///
+/// ```ignore (illustrative)
+/// fn foo<'a, T>(data: &'a mut T) {
+/// do(|| data.count += 1)
+/// }
+/// ```
/// the type of the closure would be something like:
-///
-/// struct Closure<'a, T, U>(...U);
-///
+/// ```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:
-///
-/// impl<'b, 'a, T> FnMut() for Closure<'a, T, (&'b mut &'a mut T,)> {
-/// ...
-/// }
-///
+/// ```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.)
}
/// An inline const is modeled like
-///
-/// const InlineConst<'l0...'li, T0...Tj, R>: R;
-///
+/// ```ignore (illustrative)
+/// const InlineConst<'l0...'li, T0...Tj, R>: R;
+/// ```
/// where:
///
/// - 'l0...'li and T0...Tj are the generic parameters
/// A complete reference to a trait. These take numerous guises in syntax,
/// but perhaps the most recognizable form is in a where-clause:
-///
-/// T: Foo<U>
-///
+/// ```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.
/// An existential reference to a trait, where `Self` is erased.
/// For example, the trait object `Trait<'a, 'b, X, Y>` is:
-///
-/// exists T. T: Trait<'a, 'b, X, Y>
-///
+/// ```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)]
///
/// In general, the region lattice looks like
///
-/// ```
+/// ```text
/// static ----------+-----...------+ (greatest)
/// | | |
/// early-bound and | |
/// 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
/// {..}
/// }
/// ```
///
/// ```
/// 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
- ///
- /// for<'a> fn(fn(&'a i32))
- /// ^~ ^~ ^~~
- /// | | |
- /// | | DebruijnIndex of 2
- /// Binders
- ///
+ /// ```ignore (illustrative)
+ /// for<'a> fn(fn(&'a i32))
+ /// // ^~ ^~ ^~~
+ /// // | | |
+ /// // | | 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
///
/// ```
/// 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:
- ///
- /// for<'a> fn((&'a i32, fn(&'a i32)))
- /// ^~~ ^~~
- /// | |
- /// DebruijnIndex of 1 |
- /// DebruijnIndex of 2
- ///
+ /// ```ignore (illustrative)
+ /// for<'a> fn((&'a i32, fn(&'a i32)))
+ /// // ^~~ ^~~
+ /// // | |
+ /// // 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.
/// 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() { } }
/// ```
///
/// Examples:
///
- /// ```
+ /// ```ignore (illustrative)
/// impl<'a> Foo for &'a T {
/// // Legal declarations:
/// fn method1(self: &&'a T); // ExplicitSelf::ByReference
///
/// Example: Imagine you are walking `Foo<Bar<i32>, usize>`.
///
- /// ```
+ /// ```ignore (illustrative)
/// let mut iter: TypeWalker = ...;
/// iter.next(); // yields Foo
/// iter.next(); // yields Bar<i32>
/// 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)
/// ```
/// 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)
/// ```
///
///
/// Consider the following example
/// ```rust
- /// let t = (10, (10, (10, 10)));
+ /// let t = (((10, 10), 10), 10);
///
/// let c = || {
/// println!("{}", t.0.0.0);
/// ```
/// Here the THIR expression for `t.0.0.0` will be something like
///
- /// ```
+ /// ```ignore (illustrative)
/// * Field(0)
/// * Field(0)
/// * Field(0)
/// 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
///
/// For example, if we have something like this:
///
- /// ```rust
+ /// ```ignore (illustrative)
/// ...
/// Some(x) if cond1 => ...
/// Some(x) => ...
/// ```
/// # 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
/// with precisely the reachable arms being reachable - but that problem
/// is trivially NP-complete:
///
- /// ```rust
- /// match (var0, var1, var2, var3, ...) {
- /// (true, _, _, false, true, ...) => false,
- /// (_, true, true, false, _, ...) => false,
- /// (false, _, false, false, _, ...) => false,
- /// ...
- /// _ => true
- /// }
+ /// ```ignore (illustrative)
+ /// match (var0, var1, var2, var3, ...) {
+ /// (true , _ , _ , false, true, ...) => false,
+ /// (_ , true, true , false, _ , ...) => false,
+ /// (false, _ , false, false, _ , ...) => false,
+ /// ...
+ /// _ => true
+ /// }
/// ```
///
/// Here the last arm is reachable only if there is an assignment to
/// 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 => ...,
/// scope (which can be larger or smaller).
///
/// Consider:
- ///
- /// let x = foo(bar(X, Y));
- ///
+ /// ```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:
- ///
- /// foo(Box::new(2), panic!())
- ///
+ /// ```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.
///
/// Example: when compiling the call to `foo` here:
///
- /// ```rust
+ /// ```ignore (illustrative)
/// foo(bar(), ...)
/// ```
///
/// dropped). However, if no unwind occurs, then `_X` will be
/// unconditionally consumed by the `call`:
///
- /// ```
+ /// ```ignore (illustrative)
/// bb {
/// ...
/// _R = CALL(foo, _X, ...)
//! 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`
/// straddles the boundary of one of the inputs.
///
/// The following input:
-/// ```
+/// ```text
/// |-------------------------| // `self`
/// |------| |----------| |----|
/// |-------| |-------|
/// ```
/// would be iterated over as follows:
-/// ```
+/// ```text
/// ||---|--||-|---|---|---|--|
/// ```
#[derive(Debug, Clone)]
///
/// 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
/// [true, true, _, _, _ ] => {}
/// [_, _, _, false, false] => {}
/// [_, _, _, _, _ ] => {}
+/// # _ => {}
+/// # }}
/// ```
///
/// If we went above length 5, we would simply be inserting more columns full of wildcards in the
/// 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), ..] => {}
//! 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(_)` above
+//! 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
//! 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`.
//! 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_.
//! 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)]
//! - We return the concatenation of all the witnesses found, if any.
//!
//! Example:
-//! ```
+//! ```ignore (illustrative)
//! [Some(true)] // p_1
//! [None] // p_2
//! [Some(_)] // q
///
/// 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:
///
/// ```rust
/// struct S;
-/// fn foo(pred: bool) { // maybe-init:
-/// // {}
-/// let a = S; let b = S; let c; let d; // {a, b}
+/// fn foo(pred: bool) { // maybe-init:
+/// // {}
+/// let a = S; let mut b = S; let c; let d; // {a, b}
///
/// if pred {
-/// drop(a); // { b}
-/// b = S; // { b}
+/// drop(a); // { b}
+/// b = S; // { b}
///
/// } else {
-/// drop(b); // {a}
-/// d = S; // {a, d}
+/// drop(b); // {a}
+/// d = S; // {a, d}
///
-/// } // {a, b, d}
+/// } // {a, b, d}
///
-/// c = S; // {a, b, c, d}
+/// c = S; // {a, b, c, d}
/// }
/// ```
///
///
/// ```rust
/// struct S;
-/// fn foo(pred: bool) { // maybe-uninit:
-/// // {a, b, c, d}
-/// let a = S; let b = S; let c; let d; // { c, d}
+/// fn foo(pred: bool) { // maybe-uninit:
+/// // {a, b, c, d}
+/// let a = S; let mut b = S; let c; let d; // { c, d}
///
/// if pred {
-/// drop(a); // {a, c, d}
-/// b = S; // {a, c, d}
+/// drop(a); // {a, c, d}
+/// b = S; // {a, c, d}
///
/// } else {
-/// drop(b); // { b, c, d}
-/// d = S; // { b, c }
+/// drop(b); // { b, c, d}
+/// d = S; // { b, c }
///
-/// } // {a, b, c, d}
+/// } // {a, b, c, d}
///
-/// c = S; // {a, b, d}
+/// c = S; // {a, b, d}
/// }
/// ```
///
///
/// ```rust
/// struct S;
-/// fn foo(pred: bool) { // definite-init:
-/// // { }
-/// let a = S; let b = S; let c; let d; // {a, b }
+/// fn foo(pred: bool) { // definite-init:
+/// // { }
+/// let a = S; let mut b = S; let c; let d; // {a, b }
///
/// if pred {
-/// drop(a); // { b, }
-/// b = S; // { b, }
+/// drop(a); // { b, }
+/// b = S; // { b, }
///
/// } else {
-/// drop(b); // {a, }
-/// d = S; // {a, d}
+/// drop(b); // {a, }
+/// d = S; // {a, d}
///
-/// } // { }
+/// } // { }
///
-/// c = S; // { c }
+/// c = S; // { c }
/// }
/// ```
///
///
/// ```rust
/// struct S;
-/// fn foo(pred: bool) { // ever-init:
-/// // { }
-/// let a = S; let b = S; let c; let d; // {a, b }
+/// fn foo(pred: bool) { // ever-init:
+/// // { }
+/// let a = S; let mut b = S; let c; let d; // {a, b }
///
/// if pred {
-/// drop(a); // {a, b, }
-/// b = S; // {a, b, }
+/// drop(a); // {a, b, }
+/// b = S; // {a, b, }
///
/// } else {
-/// drop(b); // {a, b, }
-/// d = S; // {a, b, d }
+/// drop(b); // {a, b, }
+/// d = S; // {a, b, d }
///
-/// } // {a, b, d }
+/// } // {a, b, d }
///
-/// c = S; // {a, b, c, d }
+/// c = S; // {a, b, c, d }
/// }
/// ```
pub struct EverInitializedPlaces<'a, 'tcx> {
//! 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
///
/// For example:
///
-/// ```rust
+/// ```ignore (MIR)
/// bb0: {
/// switchInt(move _3) -> [42_isize: bb1, otherwise: bb2];
/// }
///
/// into:
///
-/// ```rust
+/// ```ignore (MIR)
/// bb0: {
/// _2 = Eq(move _3, const 42_isize);
/// goto -> bb3;
/// 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];
///
/// into:
///
-/// ```
+/// ```ignore (MIR)
/// switchInt(_4) -> [43i32: bb3, otherwise: bb2];
/// ```
pub struct SimplifyComparisonIntegral;
//! 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`.
///
/// 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;
///
/// into:
///
-/// ```rust
+/// ```ignore (MIR)
/// _LOCAL_0 = move _LOCAL_1
/// ```
pub struct SimplifyArmIdentity;
}
/// Match on:
-/// ```rust
+/// ```ignore (MIR)
/// _LOCAL_INTO = ((_LOCAL_FROM as Variant).FIELD: TY);
/// ```
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>)> {
}
/// Match on:
-/// ```rust
+/// ```ignore (MIR)
/// discriminant(_LOCAL_TO_SET) = VAR_IDX;
/// ```
fn match_set_discr(stmt: &Statement<'_>) -> Option<(Local, VariantIdx)> {
///
/// 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
/// ```
//! 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);
//! }
//!
}
/// Matches the following grammar (per RFC 1559).
- ///
- /// meta_item : PATH ( '=' UNSUFFIXED_LIT | '(' meta_item_inner? ')' )? ;
- /// meta_item_inner : (meta_item | UNSUFFIXED_LIT) (',' meta_item_inner)? ;
+ /// ```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 {
/// 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 */ }
/// ```
///
/// 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 "}"
/// ```
}
/// Parses a `type` alias with the following grammar:
- /// ```
+ /// ```ebnf
/// TypeAlias = "type" Ident Generics {":" GenericBounds}? {"=" Ty}? ";" ;
/// ```
/// The `"type"` has already been eaten.
///
/// # Examples
///
- /// ```
+ /// ```ignore (illustrative)
/// extern crate foo;
/// extern crate bar as foo;
/// ```
/// 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 ;
/// 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 }
/// ```
}
/// Parses a function pointer type (`TyKind::BareFn`).
- /// ```
- /// [unsafe] [extern "ABI"] fn (S) -> T
- /// ^~~~~^ ^~~~^ ^~^ ^
- /// | | | |
- /// | | | Return type
- /// Function Style ABI Parameter types
+ /// ```ignore (illustrative)
+ /// [unsafe] [extern "ABI"] fn (S) -> T
+ /// // ^~~~~^ ^~~~^ ^~^ ^
+ /// // | | | |
+ /// // | | | 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(
}
/// Parses a bound according to the grammar:
- /// ```
+ /// ```ebnf
/// BOUND = TY_BOUND | LT_BOUND
/// ```
fn parse_generic_bound(&mut self) -> PResult<'a, Result<GenericBound, Span>> {
}
/// Parses a lifetime ("outlives") bound, e.g. `'a`, according to:
- /// ```
+ /// ```ebnf
/// LT_BOUND = LIFETIME
/// ```
fn parse_generic_lt_bound(
///
/// 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> {
}
/// 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
/// ```
/// A dep-node filter goes from a user-defined string to a query over
/// nodes. Right now the format is like this:
-///
-/// x & y & z
-///
+/// ```ignore (illustrative)
+/// x & y & z
+/// ```
/// where the format-string of the dep-node must contain `x`, `y`, and
/// `z`.
#[derive(Debug)]
/// 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,
/// 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();
/// 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,
/// 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;
/// }
/// 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;
/// }
/// 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 {
/// ...
/// 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) {
/// 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 {
/// 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));
/// }
/// 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
- /// mac!();
- /// ^^^^^^ input
+ /// ```ignore (illustrative)
+ /// // v output
+ /// mac!();
+ /// // ^^^^^^ 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)?));
/// (*), 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
- /// fn foo<'a, 'b>(..) -> (Foo1<'a>, Foo2<'b>) { .. }
- ///
+ /// ```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.
/// `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:
- ///
- /// impl<T> Send for Foo<T> where T: IntoIterator
- ///
+ /// ```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`.
///
/// 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:
- ///
- /// T as MyTrait<'a>
- /// T as MyTrait<'static>
- ///
+ /// ```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.
///
/// 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
/// ```
/// - 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]>
/// ```
///
/// 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:
-///
-/// forall (U: Trait + ?Sized) {
-/// if (Self: Unsize<U>) {
-/// Receiver: DispatchFromDyn<Receiver[Self => U]>
-/// }
+/// ```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>>>`
}
/// Evaluates constraints of the form:
-///
-/// for<...> <T as Trait>::U == V
-///
+/// ```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.
///
}
/// Evaluates constraints of the form:
-///
-/// <T as Trait>::U == V
-///
+/// ```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.
/// 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>
/// }
/// 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:
- ///
- /// impl Fn(i32) for Closure { ... }
- ///
+ /// ```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.
///
/// 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]
///
/// 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
/// 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
/// ```
/// 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 { }
/// 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:
- ///
- /// for<'a> fn(for<'b> fn(&'b isize, &'a isize), &'a char)
- /// ^ ^ | | |
- /// | | | | |
- /// | +------------+ 0 | |
- /// | | |
- /// +----------------------------------+ 1 |
- /// | |
- /// +----------------------------------------------+ 0
- ///
+ /// ```ignore (illustrative)
+ /// for<'a> fn(for<'b> fn(&'b isize, &'a isize), &'a char)
+ /// // ^ ^ | | |
+ /// // | | | | |
+ /// // | +------------+ 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
/// 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 ^^
/// ```
/// variance with which the argument appears.
///
/// Example 1:
- ///
- /// *mut Vec<i32>
- ///
+ /// ```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
/// (again) in `Invariant`.
///
/// Example 2:
- ///
- /// fn(*const Vec<i32>, *mut Vec<i32)
- ///
+ /// ```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
///
/// Example:
///
- /// ```
- /// T: std::ops::Index<usize, Output = u32>
- /// ^1 ^^^^^^^^^^^^^^2 ^^^^3 ^^^^^^^^^^^4
+ /// ```ignore (illustrative)
+ /// T: std::ops::Index<usize, Output = u32>
+ /// // ^1 ^^^^^^^^^^^^^^2 ^^^^3 ^^^^^^^^^^^4
/// ```
///
/// 1. The `self_ty` here would refer to the type `T`.
///
/// For (generic) associated types
///
- /// ```
+ /// ```ignore (illustrative)
/// <Vec<u8> as Iterable<u8>>::Iter::<'a>
/// ```
///
///
/// Example:
///
- /// ```
+ /// ```ignore (illustrative)
/// poly_trait_ref = Iterator<Item = u32>
/// self_ty = Foo
/// ```
///
/// 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
///
/// # Examples
///
- /// ```
+ /// ```ignore (illustrative)
/// fn with_closure<F>(_: F)
/// where F: Fn(&u32) -> &u32 { .. }
///
//! 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) {
//! // ...
//! }
///
/// Example:
///
-/// ```
+/// ```ignore (illustrative)
/// let mut coerce = CoerceMany::new(expected_ty);
/// for expr in exprs {
/// let expr_ty = fcx.check_expr_with_expectation(expr, expected);
/// 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);
/// 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)> {
/// 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();
/// 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 `!`
/// fallback to use based on whether there is a coercion pattern
/// like this:
///
- /// ```
+ /// ```ignore (not-rust)
/// ?Diverging -> ?V
/// ?NonDiverging -> ?V
/// ?V != ?NonDiverging
/// A common error is to add an extra semicolon:
///
- /// ```
+ /// ```compile_fail,E0308
/// fn foo() -> usize {
/// 22;
/// }
/// 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)`
/// ```
/// 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()
/// }
/// 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()
/// }
/// 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
/// }
/// ```
///
/// Rule 3:
-/// ```rust
+/// ```compile_fail,E0382
/// let mut a = (vec![0], vec![0]);
/// drop(a);
/// a.1 = vec![1];
use std::ops::Deref;
/// Closures defined within the function. For example:
-///
-/// fn foo() {
-/// bar(move|| { ... })
-/// }
-///
+/// ```ignore (illustrative)
+/// fn foo() {
+/// bar(move|| { ... })
+/// }
+/// ```
/// Here, the function `foo()` and the closure passed to
/// `bar()` will each have their own `FnCtxt`, but they will
/// share the inherited fields.
pub import_ids: SmallVec<[LocalDefId; 1]>,
/// Indicates that the source expression should be autoderef'd N times
- ///
- /// A = expr | *expr | **expr | ...
+ /// ```ignore (not-rust)
+ /// A = expr | *expr | **expr | ...
+ /// ```
pub autoderefs: usize,
/// Indicates that we want to add an autoref (and maybe also unsize it), or if the receiver is
///
/// Example (`src/test/ui/method-two-trait-defer-resolution-1.rs`):
///
- /// ```
+ /// ```ignore (illustrative)
/// trait Foo { ... }
/// impl Foo for Vec<i32> { ... }
/// impl Foo for Vec<usize> { ... }
/// Tupling means that all call-side arguments are packed into a tuple and
/// passed as a single parameter. For example, if tupling is enabled, this
/// function:
-///
-/// fn f(x: (isize, isize))
-///
+/// ```
+/// fn f(x: (isize, isize)) {}
+/// ```
/// Can be called as:
-///
-/// f(1, 2);
-///
+/// ```ignore UNSOLVED (can this be done in user code?)
+/// # fn f(x: (isize, isize)) {}
+/// f(1, 2);
+/// ```
/// Instead of:
-///
-/// f((1, 2));
+/// ```
+/// # fn f(x: (isize, isize)) {}
+/// f((1, 2));
+/// ```
#[derive(Clone, Eq, PartialEq)]
enum TupleArgumentsFlag {
DontTupleArguments,
///
/// Syntactically, these look like `[pat_0, ..., pat_n]`.
/// Semantically, we are type checking a pattern with structure:
- /// ```
+ /// ```ignore (not-rust)
/// [before_0, ..., before_n, (slice, after_0, ... after_n)?]
/// ```
/// The type of `slice`, if it is present, depends on the `expected` type.
///
/// Consider this silly example:
///
- /// ```
+ /// ```ignore UNSOLVED (does replacing @i32 with Box<i32> preserve the desired semantics for the example?)
/// fn borrow(x: &i32) -> &i32 {x}
/// fn foo(x: @i32) -> i32 { // block: B
/// let b = borrow(x); // region: <R0>
//! immutable "borrow kind" (see `ty::BorrowKind` for details) and then
//! "escalating" the kind as needed. The borrow kind proceeds according to
//! the following lattice:
-//!
-//! ty::ImmBorrow -> ty::UniqueImmBorrow -> ty::MutBorrow
-//!
+//! ```ignore (not-rust)
+//! ty::ImmBorrow -> ty::UniqueImmBorrow -> ty::MutBorrow
+//! ```
//! So, for example, if we see an assignment `x = 5` to an upvar `x`, we
//! will promote its borrow kind to mutable borrow. If we see an `&mut x`
//! we'll do the same. Naturally, this applies not just to the upvar, but
/// the existing min_capture map that is stored in TypeckResults.
///
/// Eg:
- /// ```rust,no_run
+ /// ```
+ /// #[derive(Debug)]
/// struct Point { x: i32, y: i32 }
///
- /// let s: String; // hir_id_s
- /// let mut p: Point; // his_id_p
+ /// let s = String::from("s"); // hir_id_s
+ /// let mut p = Point { x: 2, y: -2 }; // his_id_p
/// let c = || {
- /// println!("{s}"); // L1
+ /// println!("{s:?}"); // L1
/// p.x += 10; // L2
/// println!("{}" , p.y); // L3
- /// println!("{p}"); // L4
+ /// println!("{p:?}"); // L4
/// drop(s); // L5
/// };
/// ```
///
/// InferBorrowKind results in a structure like this:
///
- /// ```text
+ /// ```ignore (illustrative)
/// {
/// Place(base: hir_id_s, projections: [], ....) -> {
/// capture_kind_expr: hir_id_L5,
/// ```
///
/// After the min capture analysis, we get:
- /// ```text
+ /// ```ignore (illustrative)
/// {
/// hir_id_s -> [
/// Place(base: hir_id_s, projections: [], ....) -> {
/// - Ty(place): Type of place
/// - `(a, b)`: Represents the function parameters `base_path_ty` and `captured_by_move_projs`
/// respectively.
- /// ```
+ /// ```ignore (illustrative)
/// (Ty(w), [ &[p, x], &[c] ])
- /// |
- /// ----------------------------
- /// | |
- /// v v
+ /// // |
+ /// // ----------------------------
+ /// // | |
+ /// // v v
/// (Ty(w.p), [ &[x] ]) (Ty(w.c), [ &[] ]) // I(1)
- /// | |
- /// v v
+ /// // | |
+ /// // v v
/// (Ty(w.p), [ &[x] ]) false
- /// |
- /// |
- /// -------------------------------
- /// | |
- /// v v
+ /// // |
+ /// // |
+ /// // -------------------------------
+ /// // | |
+ /// // v v
/// (Ty((w.p).x), [ &[] ]) (Ty((w.p).y), []) // IMP 2
- /// | |
- /// v v
+ /// // | |
+ /// // v v
/// false NeedsSignificantDrop(Ty(w.p.y))
- /// |
- /// v
+ /// // |
+ /// // v
/// true
/// ```
///
///
/// Consider another example:
///
- /// ```rust
+ /// ```ignore (pseudo-rust)
/// struct X;
/// impl Drop for X {}
///
/// s.str2 via a MutableBorrow
///
/// ```rust,no_run
- /// struct SomeStruct { str1: String, str2: String }
+ /// struct SomeStruct { str1: String, str2: String };
///
/// // Assume that the HirId for the variable definition is `V1`
- /// let mut s = SomeStruct { str1: format!("s1"), str2: format!("s2") }
+ /// let mut s = SomeStruct { str1: format!("s1"), str2: format!("s2") };
///
/// let fix_s = |new_s2| {
/// // Assume that the HirId for the expression `s.str1` is `E1`
- /// println!("Updating SomeStruct with str1=", s.str1);
+ /// println!("Updating SomeStruct with str1={0}", s.str1);
/// // Assume that the HirId for the expression `*s.str2` is `E2`
/// s.str2 = new_s2;
/// };
///
/// For closure `fix_s`, (at a high level) the map contains
///
- /// ```
+ /// ```ignore (illustrative)
/// Place { V1, [ProjectionKind::Field(Index=0, Variant=0)] } : CaptureKind { E1, ImmutableBorrow }
/// Place { V1, [ProjectionKind::Field(Index=1, Variant=0)] } : CaptureKind { E2, MutableBorrow }
/// ```
/// Consider the following example
/// ```rust,no_run
/// struct Point { x: i32, y: i32 }
-/// let mut p: Point { x: 10, y: 10 };
+/// let mut p = Point { x: 10, y: 10 };
///
/// let c = || {
/// p.x += 10;
///
/// Reason we only drop the last deref is because of the following edge case:
///
-/// ```rust
+/// ```
+/// # struct A { field_of_a: Box<i32> }
+/// # struct B {}
+/// # struct C<'a>(&'a i32);
/// struct MyStruct<'a> {
/// a: &'static A,
/// b: B,
/// }
///
/// fn foo<'a, 'b>(m: &'a MyStruct<'b>) -> impl FnMut() + 'static {
-/// let c = || drop(&*m.a.field_of_a);
+/// || drop(&*m.a.field_of_a)
/// // Here we really do want to capture `*m.a` because that outlives `'static`
///
/// // If we capture `m`, then the closure no longer outlives `'static'
/// Helper type of a temporary returned by `.for_item(...)`.
/// This is necessary because we can't write the following bound:
///
-/// ```rust
+/// ```ignore (illustrative)
/// F: for<'b, 'tcx> where 'tcx FnOnce(FnCtxt<'b, 'tcx>)
/// ```
struct CheckWfFcxBuilder<'tcx> {
/// In particular, definitions of opaque types can only use other generics as arguments,
/// and they cannot repeat an argument. Example:
///
-/// ```rust
+/// ```ignore (illustrative)
/// type Foo<A, B> = impl Bar<A, B>;
///
/// // Okay -- `Foo` is applied to two distinct, generic types.
/// constrained before it is used, if that is possible, and add the
/// parameters so constrained to `input_parameters`. For example,
/// imagine the following impl:
-///
-/// impl<T: Debug, U: Iterator<Item = T>> Trait for U
-///
+/// ```ignore (illustrative)
+/// impl<T: Debug, U: Iterator<Item = T>> Trait for U
+/// ```
/// The impl's predicates are collected from left to right. Ignoring
/// the implicit `Sized` bounds, these are
/// * T: Debug
/// In the following example the closures `c` only captures `p.x` even though `incr`
/// is a capture of the nested closure
///
- /// ```rust,ignore(cannot-test-this-because-pseudo-code)
- /// let p = ..;
+ /// ```
+ /// struct P { x: i32 }
+ /// let mut p = P { x: 4 };
/// let c = || {
/// let incr = 10;
/// let nested = || p.x += incr;
- /// }
+ /// };
/// ```
///
/// - When reporting the Place back to the Delegate, ensure that the UpvarId uses the enclosing
//!
//! Suppose we have the following always applicable impl:
//!
-//! ```rust
+//! ```ignore (illustrative)
//! impl<T> SpecExtend<T> for std::vec::IntoIter<T> { /* specialized impl */ }
//! impl<T, I: Iterator<Item=T>> SpecExtend<T> for I { /* default impl */ }
//! ```
//! expressions of the following forms (the actual enum has many more
//! possibilities, naturally, but they are all variants of these base
//! forms):
-//!
-//! E = rvalue // some computed rvalue
-//! | x // address of a local variable or argument
-//! | *E // deref of a ptr
-//! | E.comp // access to an interior component
-//!
+//! ```ignore (not-rust)
+//! E = rvalue // some computed rvalue
+//! | x // address of a local variable or argument
+//! | *E // deref of a ptr
+//! | E.comp // access to an interior component
+//! ```
//! Imagine a routine ToAddr(Expr) that evaluates an expression and returns an
//! address where the result is to be found. If Expr is a place, then this
//! is the address of the place. If `Expr` is an rvalue, this is the address of
/// We also have to check the explicit predicates
/// declared on the type.
+/// ```ignore (illustrative)
+/// struct Foo<'a, T> {
+/// field1: Bar<T>
+/// }
///
-/// struct Foo<'a, T> {
-/// field1: Bar<T>
-/// }
-///
-/// struct Bar<U> where U: 'static, U: Foo {
-/// ...
-/// }
-///
+/// struct Bar<U> where U: 'static, U: Foo {
+/// ...
+/// }
+/// ```
/// Here, we should fetch the explicit predicates, which
/// will give us `U: 'static` and `U: Foo`. The latter we
/// can ignore, but we will want to process `U: 'static`,
/// calling that fn, and hence the *callee* can assume that its
/// argument types are well-formed. This may imply certain relationships
/// between generic parameters. For example:
- ///
- /// fn foo<'a,T>(x: &'a T)
- ///
+ /// ```
+ /// fn foo<'a,T>(x: &'a T) {}
+ /// ```
/// can only be called with a `'a` and `T` such that `&'a T` is WF.
/// For `&'a T` to be WF, `T: 'a` must hold. So we can assume `T: 'a`.
///
/// To build constraints, we visit one item (type, trait) at a time
/// and look at its contents. So e.g., if we have
-///
-/// struct Foo<T> {
-/// b: Bar<T>
-/// }
-///
+/// ```ignore (illustrative)
+/// struct Foo<T> {
+/// b: Bar<T>
+/// }
+/// ```
/// then while we are visiting `Bar<T>`, the `CurrentItem` would have
/// the `DefId` and the start of `Foo`'s inferreds.
pub struct CurrentItem {