fn maybe_note_obligation_cause_for_async_await(
        &self,
        err: &mut DiagnosticBuilder<'_>,
        obligation: &PredicateObligation<'tcx>,
    ) -> bool {
        debug!("maybe_note_obligation_cause_for_async_await: obligation.predicate={:?} \
                obligation.cause.span={:?}", obligation.predicate, obligation.cause.span);
        let source_map = self.tcx.sess.source_map();

        // Attempt to detect an async-await error by looking at the obligation causes, looking
        // for a generator to be present.
        //
        // When a future does not implement a trait because of a captured type in one of the
        // generators somewhere in the call stack, then the result is a chain of obligations.
        //
        // Given a `async fn` A that calls a `async fn` B which captures a non-send type and that
        // future is passed as an argument to a function C which requires a `Send` type, then the
        // chain looks something like this:
        //
        // - `BuiltinDerivedObligation` with a generator witness (B)
        // - `BuiltinDerivedObligation` with a generator (B)
        // - `BuiltinDerivedObligation` with `std::future::GenFuture` (B)
        // - `BuiltinDerivedObligation` with `impl std::future::Future` (B)
        // - `BuiltinDerivedObligation` with `impl std::future::Future` (B)
        // - `BuiltinDerivedObligation` with a generator witness (A)
        // - `BuiltinDerivedObligation` with a generator (A)
        // - `BuiltinDerivedObligation` with `std::future::GenFuture` (A)
        // - `BuiltinDerivedObligation` with `impl std::future::Future` (A)
        // - `BuiltinDerivedObligation` with `impl std::future::Future` (A)
        // - `BindingObligation` with `impl_send (Send requirement)
        //
        // The first obligation in the chain is the most useful and has the generator that captured
        // the type. The last generator has information about where the bound was introduced. At
        // least one generator should be present for this diagnostic to be modified.
        let (mut trait_ref, mut target_ty) = match obligation.predicate {
            ty::Predicate::Trait(p) =>
                (Some(p.skip_binder().trait_ref), Some(p.skip_binder().self_ty())),
            _ => (None, None),
        };
        let mut generator = None;
        let mut last_generator = None;
        let mut next_code = Some(&obligation.cause.code);
        while let Some(code) = next_code {
            debug!("maybe_note_obligation_cause_for_async_await: code={:?}", code);
            match code {
                ObligationCauseCode::BuiltinDerivedObligation(derived_obligation) |
                ObligationCauseCode::ImplDerivedObligation(derived_obligation) => {
                    let ty = derived_obligation.parent_trait_ref.self_ty();
                    debug!("maybe_note_obligation_cause_for_async_await: \
                            parent_trait_ref={:?} self_ty.kind={:?}",
                           derived_obligation.parent_trait_ref, ty.kind);

                    match ty.kind {
                        ty::Generator(did, ..) => {
                            generator = generator.or(Some(did));
                            last_generator = Some(did);
                        },
                        ty::GeneratorWitness(..) => {},
                        _ if generator.is_none() => {
                            trait_ref = Some(*derived_obligation.parent_trait_ref.skip_binder());
                            target_ty = Some(ty);
                        },
                        _ => {},
                    }

                    next_code = Some(derived_obligation.parent_code.as_ref());
                },
                _ => break,
            }
        }

        // Only continue if a generator was found.
        debug!("maybe_note_obligation_cause_for_async_await: generator={:?} trait_ref={:?} \
                target_ty={:?}", generator, trait_ref, target_ty);
        let (generator_did, trait_ref, target_ty) = match (generator, trait_ref, target_ty) {
            (Some(generator_did), Some(trait_ref), Some(target_ty)) =>
                (generator_did, trait_ref, target_ty),
            _ => return false,
        };

        let span = self.tcx.def_span(generator_did);

        // Do not ICE on closure typeck (#66868).
        if let None = self.tcx.hir().as_local_hir_id(generator_did) {
            return false;
        }

        // Get the tables from the infcx if the generator is the function we are
        // currently type-checking; otherwise, get them by performing a query.
        // This is needed to avoid cycles.
        let in_progress_tables = self.in_progress_tables.map(|t| t.borrow());
        let generator_did_root = self.tcx.closure_base_def_id(generator_did);
        debug!("maybe_note_obligation_cause_for_async_await: generator_did={:?} \
             generator_did_root={:?} in_progress_tables.local_id_root={:?} span={:?}",
            generator_did, generator_did_root,
            in_progress_tables.as_ref().map(|t| t.local_id_root), span);
        let query_tables;
        let tables: &TypeckTables<'tcx> = match &in_progress_tables {
            Some(t) if t.local_id_root == Some(generator_did_root) => t,
            _ => {
                query_tables = self.tcx.typeck_tables_of(generator_did);
                &query_tables
            }
        };

        // Look for a type inside the generator interior that matches the target type to get
        // a span.
        let target_ty_erased = self.tcx.erase_regions(&target_ty);
        let target_span = tables.generator_interior_types.iter()
            .find(|ty::GeneratorInteriorTypeCause { ty, .. }| {
                // Careful: the regions for types that appear in the
                // generator interior are not generally known, so we
                // want to erase them when comparing (and anyway,
                // `Send` and other bounds are generally unaffected by
                // the choice of region).  When erasing regions, we
                // also have to erase late-bound regions. This is
                // because the types that appear in the generator
                // interior generally contain "bound regions" to
                // represent regions that are part of the suspended
                // generator frame. Bound regions are preserved by
                // `erase_regions` and so we must also call
                // `erase_late_bound_regions`.
                let ty_erased = self.tcx.erase_late_bound_regions(&ty::Binder::bind(*ty));
                let ty_erased = self.tcx.erase_regions(&ty_erased);
                let eq = ty::TyS::same_type(ty_erased, target_ty_erased);
                debug!("maybe_note_obligation_cause_for_async_await: ty_erased={:?} \
                        target_ty_erased={:?} eq={:?}", ty_erased, target_ty_erased, eq);
                eq
            })
            .map(|ty::GeneratorInteriorTypeCause { span, scope_span, .. }|
                 (span, source_map.span_to_snippet(*span), scope_span));
        debug!("maybe_note_obligation_cause_for_async_await: target_ty={:?} \
                generator_interior_types={:?} target_span={:?}",
                target_ty, tables.generator_interior_types, target_span);
        if let Some((target_span, Ok(snippet), scope_span)) = target_span {
            self.note_obligation_cause_for_async_await(
                err, *target_span, scope_span, snippet, generator_did, last_generator,
                trait_ref, target_ty, tables, obligation, next_code,
            );
            true
        } else {
            false
        }
    }
/// Adds an async-await specific note to the diagnostic when the future does not implement
/// an auto trait because of a captured type.
///
/// ```ignore (diagnostic)
/// note: future does not implement `Qux` as this value is used across an await
///   --> $DIR/issue-64130-3-other.rs:17:5
///    |
/// LL |     let x = Foo;
///    |         - has type `Foo`
/// LL |     baz().await;
///    |     ^^^^^^^^^^^ await occurs here, with `x` maybe used later
/// LL | }
///    | - `x` is later dropped here
/// ```
///
/// When the diagnostic does not implement `Send` or `Sync` specifically, then the diagnostic
/// is "replaced" with a different message and a more specific error.
///
/// ```ignore (diagnostic)
/// error: future cannot be sent between threads safely
///   --> $DIR/issue-64130-2-send.rs:21:5
///    |
/// LL | fn is_send<T: Send>(t: T) { }
///    |    -------    ---- required by this bound in `is_send`
/// ...
/// LL |     is_send(bar());
///    |     ^^^^^^^ future returned by `bar` is not send
///    |
///    = help: within `impl std::future::Future`, the trait `std::marker::Send` is not
///            implemented for `Foo`
/// note: future is not send as this value is used across an await
///   --> $DIR/issue-64130-2-send.rs:15:5
///    |
/// LL |     let x = Foo;
///    |         - has type `Foo`
/// LL |     baz().await;
///    |     ^^^^^^^^^^^ await occurs here, with `x` maybe used later
/// LL | }
///    | - `x` is later dropped here
/// ```
///
/// Returns `true` if an async-await specific note was added to the diagnostic.
Adds an async-await specific note to the diagnostic when the future does not implement
an auto trait because of a captured type.



When the diagnostic does not implement `Send` or `Sync` specifically, then the diagnostic
is "replaced" with a different message and a more specific error.



Returns `true` if an async-await specific note was added to the diagnostic.
Adds an async - await specific note to the diagnostic when the future does not implement an auto trait because of a captured type . When the diagnostic does not implement ` Send ` or ` Sync ` specifically then the diagnostic is " replaced " with a different message and a more specific error . Returns ` true ` if an async - await specific note was added to the diagnostic .
fn maybe_note_obligation_cause_for_async_await(
        &self,
        err: &mut DiagnosticBuilder<'_>,
        obligation: &PredicateObligation<'tcx>,
    ) -> bool {
        debug!("maybe_note_obligation_cause_for_async_await: obligation.predicate={:?} \
                obligation.cause.span={:?}", obligation.predicate, obligation.cause.span);
        let source_map = self.tcx.sess.source_map();
        // Attempt to detect an async-await error by looking at the obligation causes, looking
        // for a generator to be present.
        //
        // When a future does not implement a trait because of a captured type in one of the
        // generators somewhere in the call stack, then the result is a chain of obligations.
        //
        // Given a `async fn` A that calls a `async fn` B which captures a non-send type and that
        // future is passed as an argument to a function C which requires a `Send` type, then the
        // chain looks something like this:
        //
        // - `BuiltinDerivedObligation` with a generator witness (B)
        // - `BuiltinDerivedObligation` with a generator (B)
        // - `BuiltinDerivedObligation` with `std::future::GenFuture` (B)
        // - `BuiltinDerivedObligation` with `impl std::future::Future` (B)
        // - `BuiltinDerivedObligation` with `impl std::future::Future` (B)
        // - `BuiltinDerivedObligation` with a generator witness (A)
        // - `BuiltinDerivedObligation` with a generator (A)
        // - `BuiltinDerivedObligation` with `std::future::GenFuture` (A)
        // - `BuiltinDerivedObligation` with `impl std::future::Future` (A)
        // - `BuiltinDerivedObligation` with `impl std::future::Future` (A)
        // - `BindingObligation` with `impl_send (Send requirement)
        //
        // The first obligation in the chain is the most useful and has the generator that captured
        // the type. The last generator has information about where the bound was introduced. At
        // least one generator should be present for this diagnostic to be modified.
        let (mut trait_ref, mut target_ty) = match obligation.predicate {
            ty::Predicate::Trait(p) =>
                (Some(p.skip_binder().trait_ref), Some(p.skip_binder().self_ty())),
            _ => (None, None),
        };
        let mut generator = None;
        let mut last_generator = None;
        let mut next_code = Some(&obligation.cause.code);
        while let Some(code) = next_code {
            debug!("maybe_note_obligation_cause_for_async_await: code={:?}", code);
            match code {
                ObligationCauseCode::BuiltinDerivedObligation(derived_obligation) |
                ObligationCauseCode::ImplDerivedObligation(derived_obligation) => {
                    let ty = derived_obligation.parent_trait_ref.self_ty();
                    debug!("maybe_note_obligation_cause_for_async_await: \
                            parent_trait_ref={:?} self_ty.kind={:?}",
                           derived_obligation.parent_trait_ref, ty.kind);
                    match ty.kind {
                        ty::Generator(did, ..) => {
                            generator = generator.or(Some(did));
                            last_generator = Some(did);
                        },
                        ty::GeneratorWitness(..) => {},
                        _ if generator.is_none() => {
                            trait_ref = Some(*derived_obligation.parent_trait_ref.skip_binder());
                            target_ty = Some(ty);
                        },
                        _ => {},
                    }
                    next_code = Some(derived_obligation.parent_code.as_ref());
                },
                _ => break,
            }
        }
        // Only continue if a generator was found.
        debug!("maybe_note_obligation_cause_for_async_await: generator={:?} trait_ref={:?} \
                target_ty={:?}", generator, trait_ref, target_ty);
        let (generator_did, trait_ref, target_ty) = match (generator, trait_ref, target_ty) {
            (Some(generator_did), Some(trait_ref), Some(target_ty)) =>
                (generator_did, trait_ref, target_ty),
            _ => return false,
        };
        let span = self.tcx.def_span(generator_did);
        // Do not ICE on closure typeck (#66868).
        if let None = self.tcx.hir().as_local_hir_id(generator_did) {
            return false;
        }
        // Get the tables from the infcx if the generator is the function we are
        // currently type-checking; otherwise, get them by performing a query.
        // This is needed to avoid cycles.
        let in_progress_tables = self.in_progress_tables.map(|t| t.borrow());
        let generator_did_root = self.tcx.closure_base_def_id(generator_did);
        debug!("maybe_note_obligation_cause_for_async_await: generator_did={:?} \
             generator_did_root={:?} in_progress_tables.local_id_root={:?} span={:?}",
            generator_did, generator_did_root,
            in_progress_tables.as_ref().map(|t| t.local_id_root), span);
        let query_tables;
        let tables: &TypeckTables<'tcx> = match &in_progress_tables {
            Some(t) if t.local_id_root == Some(generator_did_root) => t,
            _ => {
                query_tables = self.tcx.typeck_tables_of(generator_did);
                &query_tables
            }
        };
        // Look for a type inside the generator interior that matches the target type to get
        // a span.
        let target_ty_erased = self.tcx.erase_regions(&target_ty);
        let target_span = tables.generator_interior_types.iter()
            .find(|ty::GeneratorInteriorTypeCause { ty, .. }| {
                // Careful: the regions for types that appear in the
                // generator interior are not generally known, so we
                // want to erase them when comparing (and anyway,
                // `Send` and other bounds are generally unaffected by
                // the choice of region).  When erasing regions, we
                // also have to erase late-bound regions. This is
                // because the types that appear in the generator
                // interior generally contain "bound regions" to
                // represent regions that are part of the suspended
                // generator frame. Bound regions are preserved by
                // `erase_regions` and so we must also call
                // `erase_late_bound_regions`.
                let ty_erased = self.tcx.erase_late_bound_regions(&ty::Binder::bind(*ty));
                let ty_erased = self.tcx.erase_regions(&ty_erased);
                let eq = ty::TyS::same_type(ty_erased, target_ty_erased);
                debug!("maybe_note_obligation_cause_for_async_await: ty_erased={:?} \
                        target_ty_erased={:?} eq={:?}", ty_erased, target_ty_erased, eq);
                eq
            })
            .map(|ty::GeneratorInteriorTypeCause { span, scope_span, .. }|
                 (span, source_map.span_to_snippet(*span), scope_span));
        debug!("maybe_note_obligation_cause_for_async_await: target_ty={:?} \
                generator_interior_types={:?} target_span={:?}",
                target_ty, tables.generator_interior_types, target_span);
        if let Some((target_span, Ok(snippet), scope_span)) = target_span {
            self.note_obligation_cause_for_async_await(
                err, *target_span, scope_span, snippet, generator_did, last_generator,
                trait_ref, target_ty, tables, obligation, next_code,
            );
            true
        } else {
            false
        }
    }
fn maybe_note_obligation_cause_for_async_await ( & self , err : & mut DiagnosticBuilder < ' _ > , obligation : & PredicateObligation < ' tcx > , ) -> bool { debug ! ( " \
 " obligation predicate obligation cause span ) ; let source_map = self . tcx . sess . source_map ( ) ; // Attempt to detect an async-await error by looking at the obligation causes, looking // for a generator to be present. // // When a future does not implement a trait because of a captured type in one of the // generators somewhere in the call stack, then the result is a chain of obligations. // // Given a `async fn` A that calls a `async fn` B which captures a non-send type and that // future is passed as an argument to a function C which requires a `Send` type, then the // chain looks something like this: // // - `BuiltinDerivedObligation` with a generator witness (B) // - `BuiltinDerivedObligation` with a generator (B) // - `BuiltinDerivedObligation` with `std::future::GenFuture` (B) // - `BuiltinDerivedObligation` with `impl std::future::Future` (B) // - `BuiltinDerivedObligation` with `impl std::future::Future` (B) // - `BuiltinDerivedObligation` with a generator witness (A) // - `BuiltinDerivedObligation` with a generator (A) // - `BuiltinDerivedObligation` with `std::future::GenFuture` (A) // - `BuiltinDerivedObligation` with `impl std::future::Future` (A) // - `BuiltinDerivedObligation` with `impl std::future::Future` (A) // - `BindingObligation` with `impl_send (Send requirement) // // The first obligation in the chain is the most useful and has the generator that captured // the type. The last generator has information about where the bound was introduced. At // least one generator should be present for this diagnostic to be modified. let ( mut trait_ref , mut target_ty ) = match obligation . predicate { ty :: Predicate :: Trait ( p ) => ( Some ( p . skip_binder ( ) . trait_ref ) , Some ( p . skip_binder ( ) . self_ty ( ) ) ) , _ => ( None , None ) , } ; let mut generator = None ; let mut last_generator = None ; let mut next_code = Some ( & obligation . cause . code ) ; while let Some ( code ) = next_code { debug ! ( " " code ) ; match code { ObligationCauseCode :: BuiltinDerivedObligation ( derived_obligation ) | ObligationCauseCode :: ImplDerivedObligation ( derived_obligation ) => { let ty = derived_obligation . parent_trait_ref . self_ty ( ) ; debug ! ( " \
 " derived_obligation parent_trait_ref ty kind ) ; match ty . kind { ty :: Generator ( did , .. ) => { generator = generator . or ( Some ( did ) ) ; last_generator = Some ( did ) ; } , ty :: GeneratorWitness ( .. ) => { } , _ if generator . is_none ( ) => { trait_ref = Some ( * derived_obligation . parent_trait_ref . skip_binder ( ) ) ; target_ty = Some ( ty ) ; } , _ => { } , } next_code = Some ( derived_obligation . parent_code . as_ref ( ) ) ; } , _ => break , } } // Only continue if a generator was found. debug ! ( " \
 " generator trait_ref target_ty ) ; let ( generator_did , trait_ref , target_ty ) = match ( generator , trait_ref , target_ty ) { ( Some ( generator_did ) , Some ( trait_ref ) , Some ( target_ty ) ) => ( generator_did , trait_ref , target_ty ) , _ => return false , } ; let span = self . tcx . def_span ( generator_did ) ; // Do not ICE on closure typeck (#66868). if let None = self . tcx . hir ( ) . as_local_hir_id ( generator_did ) { return false ; } // Get the tables from the infcx if the generator is the function we are // currently type-checking; otherwise, get them by performing a query. // This is needed to avoid cycles. let in_progress_tables = self . in_progress_tables . map ( | t | t . borrow ( ) ) ; let generator_did_root = self . tcx . closure_base_def_id ( generator_did ) ; debug ! ( " \
 " generator_did generator_did_root in_progress_tables as_ref ( ) map ( t t local_id_root ) span ) ; let query_tables ; let tables : & TypeckTables < ' tcx > = match & in_progress_tables { Some ( t ) if t . local_id_root == Some ( generator_did_root ) => t , _ => { query_tables = self . tcx . typeck_tables_of ( generator_did ) ; & query_tables } } ; // Look for a type inside the generator interior that matches the target type to get // a span. let target_ty_erased = self . tcx . erase_regions ( & target_ty ) ; let target_span = tables . generator_interior_types . iter ( ) . find ( | ty :: GeneratorInteriorTypeCause { ty , .. } | { // Careful: the regions for types that appear in the // generator interior are not generally known, so we // want to erase them when comparing (and anyway, // `Send` and other bounds are generally unaffected by // the choice of region).  When erasing regions, we // also have to erase late-bound regions. This is // because the types that appear in the generator // interior generally contain "bound regions" to // represent regions that are part of the suspended // generator frame. Bound regions are preserved by // `erase_regions` and so we must also call // `erase_late_bound_regions`. let ty_erased = self . tcx . erase_late_bound_regions ( & ty :: Binder :: bind ( * ty ) ) ; let ty_erased = self . tcx . erase_regions ( & ty_erased ) ; let eq = ty :: TyS :: same_type ( ty_erased , target_ty_erased ) ; debug ! ( " \
 " ty_erased target_ty_erased eq ) ; eq } ) . map ( | ty :: GeneratorInteriorTypeCause { span , scope_span , .. } | ( span , source_map . span_to_snippet ( * span ) , scope_span ) ) ; debug ! ( " \
 " target_ty tables generator_interior_types target_span ) ; if let Some ( ( target_span , Ok ( snippet ) , scope_span ) ) = target_span { self . note_obligation_cause_for_async_await ( err , * target_span , scope_span , snippet , generator_did , last_generator , trait_ref , target_ty , tables , obligation , next_code , ) ; true } else { false } }
Adds an async-await specific note to the diagnostic when the future does not implement
an auto trait because of a captured type.
Adds an async - await specific note to the diagnostic when the future does not implement an auto trait because of a captured type .
&self
err
&mut DiagnosticBuilder<'_>
obligation
&PredicateObligation<'tcx>