err: &mut Diagnostic,
trait_pred: ty::PolyTraitPredicate<'tcx>,
);
- fn function_argument_obligation(
+ fn note_function_argument_obligation(
&self,
arg_hir_id: HirId,
err: &mut Diagnostic,
self.note_conflicting_closure_bounds(cause, &mut err);
if let Some(found_node) = found_node {
- hint_missing_borrow(span, found_span, found, expected, found_node, &mut err);
+ hint_missing_borrow(span, found, expected, found_node, &mut err);
}
err
}
}
GeneratorInteriorOrUpvar::Upvar(upvar_span) => {
- // `Some(ref_ty)` if `target_ty` is `&T` and `T` fails to impl `Sync`
- let refers_to_non_sync = match target_ty.kind() {
- ty::Ref(_, ref_ty, _) => match self.evaluate_obligation(&obligation) {
- Ok(eval) if !eval.may_apply() => Some(ref_ty),
+ // `Some((ref_ty, is_mut))` if `target_ty` is `&T` or `&mut T` and fails to impl `Send`
+ let non_send = match target_ty.kind() {
+ ty::Ref(_, ref_ty, mutability) => match self.evaluate_obligation(&obligation) {
+ Ok(eval) if !eval.may_apply() => Some((ref_ty, mutability.is_mut())),
_ => None,
},
_ => None,
};
- let (span_label, span_note) = match refers_to_non_sync {
- // if `target_ty` is `&T` and `T` fails to impl `Sync`,
- // include suggestions to make `T: Sync` so that `&T: Send`
- Some(ref_ty) => (
- format!(
- "has type `{}` which {}, because `{}` is not `Sync`",
- target_ty, trait_explanation, ref_ty
- ),
- format!(
- "captured value {} because `&` references cannot be sent unless their referent is `Sync`",
- trait_explanation
- ),
- ),
+ let (span_label, span_note) = match non_send {
+ // if `target_ty` is `&T` or `&mut T` and fails to impl `Send`,
+ // include suggestions to make `T: Sync` so that `&T: Send`,
+ // or to make `T: Send` so that `&mut T: Send`
+ Some((ref_ty, is_mut)) => {
+ let ref_ty_trait = if is_mut { "Send" } else { "Sync" };
+ let ref_kind = if is_mut { "&mut" } else { "&" };
+ (
+ format!(
+ "has type `{}` which {}, because `{}` is not `{}`",
+ target_ty, trait_explanation, ref_ty, ref_ty_trait
+ ),
+ format!(
+ "captured value {} because `{}` references cannot be sent unless their referent is `{}`",
+ trait_explanation, ref_kind, ref_ty_trait
+ ),
+ )
+ }
None => (
format!("has type `{}` which {}", target_ty, trait_explanation),
format!("captured value {}", trait_explanation),
}
ty::Closure(def_id, _) => err.span_note(
self.tcx.def_span(def_id),
- &format!("required because it's used within this closure"),
+ "required because it's used within this closure",
),
_ => err.note(&msg),
};
ref parent_code,
..
} => {
- self.function_argument_obligation(
+ self.note_function_argument_obligation(
arg_hir_id,
err,
parent_code,
);
}
}
- fn function_argument_obligation(
+ fn note_function_argument_obligation(
&self,
arg_hir_id: HirId,
err: &mut Diagnostic,
parent_code: &ObligationCauseCode<'tcx>,
param_env: ty::ParamEnv<'tcx>,
- predicate: ty::Predicate<'tcx>,
+ failed_pred: ty::Predicate<'tcx>,
call_hir_id: HirId,
) {
let tcx = self.tcx;
let hir = tcx.hir();
- if let Some(Node::Expr(expr)) = hir.find(arg_hir_id) {
- let parent_id = hir.get_parent_item(arg_hir_id);
- let typeck_results: &TypeckResults<'tcx> = match &self.typeck_results {
- Some(t) if t.hir_owner == parent_id => t,
- _ => self.tcx.typeck(parent_id.def_id),
- };
+ if let Some(Node::Expr(expr)) = hir.find(arg_hir_id)
+ && let Some(typeck_results) = &self.typeck_results
+ {
if let hir::Expr { kind: hir::ExprKind::Block(..), .. } = expr {
let expr = expr.peel_blocks();
let ty = typeck_results.expr_ty_adjusted_opt(expr).unwrap_or(tcx.ty_error());
let mut type_diffs = vec![];
if let ObligationCauseCode::ExprBindingObligation(def_id, _, _, idx) = parent_code.deref()
- && let predicates = self.tcx.predicates_of(def_id).instantiate_identity(self.tcx)
- && let Some(pred) = predicates.predicates.get(*idx)
+ && let Some(node_substs) = typeck_results.node_substs_opt(call_hir_id)
+ && let where_clauses = self.tcx.predicates_of(def_id).instantiate(self.tcx, node_substs)
+ && let Some(where_pred) = where_clauses.predicates.get(*idx)
{
- if let Ok(trait_pred) = pred.kind().try_map_bound(|pred| match pred {
- ty::PredicateKind::Clause(ty::Clause::Trait(trait_pred)) => Ok(trait_pred),
- _ => Err(()),
- })
- && let Ok(trait_predicate) = predicate.kind().try_map_bound(|pred| match pred {
- ty::PredicateKind::Clause(ty::Clause::Trait(trait_pred)) => Ok(trait_pred),
- _ => Err(()),
- })
+ if let Some(where_pred) = where_pred.to_opt_poly_trait_pred()
+ && let Some(failed_pred) = failed_pred.to_opt_poly_trait_pred()
{
let mut c = CollectAllMismatches {
infcx: self.infcx,
param_env,
errors: vec![],
};
- if let Ok(_) = c.relate(trait_pred, trait_predicate) {
+ if let Ok(_) = c.relate(where_pred, failed_pred) {
type_diffs = c.errors;
}
- } else if let ty::PredicateKind::Clause(
- ty::Clause::Projection(proj)
- ) = pred.kind().skip_binder()
- && let ty::PredicateKind::Clause(
- ty::Clause::Projection(projection)
- ) = predicate.kind().skip_binder()
+ } else if let Some(where_pred) = where_pred.to_opt_poly_projection_pred()
+ && let Some(failed_pred) = failed_pred.to_opt_poly_projection_pred()
+ && let Some(found) = failed_pred.skip_binder().term.ty()
{
type_diffs = vec![
Sorts(ty::error::ExpectedFound {
- expected: self.tcx.mk_ty(ty::Alias(ty::Projection, proj.projection_ty)),
- found: projection.term.ty().unwrap(),
+ expected: self.tcx.mk_ty(ty::Alias(ty::Projection, where_pred.skip_binder().projection_ty)),
+ found,
}),
];
}
// If the expression we're calling on is a binding, we want to point at the
// `let` when talking about the type. Otherwise we'll point at every part
// of the method chain with the type.
- self.point_at_chain(binding_expr, typeck_results, type_diffs, param_env, err);
+ self.point_at_chain(binding_expr, &typeck_results, type_diffs, param_env, err);
} else {
- self.point_at_chain(expr, typeck_results, type_diffs, param_env, err);
+ self.point_at_chain(expr, &typeck_results, type_diffs, param_env, err);
}
}
let call_node = hir.find(call_hir_id);
}
err.span_note(
multi_span,
- format!("the method call chain might not have had the expected associated types"),
+ "the method call chain might not have had the expected associated types",
);
}
}
/// Add a hint to add a missing borrow or remove an unnecessary one.
fn hint_missing_borrow<'tcx>(
span: Span,
- found_span: Span,
found: Ty<'tcx>,
expected: Ty<'tcx>,
found_node: Node<'_>,
}
};
- let fn_decl = found_node
- .fn_decl()
- .unwrap_or_else(|| span_bug!(found_span, "found node must be a function"));
+ // This could be a variant constructor, for example.
+ let Some(fn_decl) = found_node.fn_decl() else { return; };
let arg_spans = fn_decl.inputs.iter().map(|ty| ty.span);
- fn get_deref_type_and_refs<'tcx>(mut ty: Ty<'tcx>) -> (Ty<'tcx>, usize) {
+ fn get_deref_type_and_refs(mut ty: Ty<'_>) -> (Ty<'_>, usize) {
let mut refs = 0;
while let ty::Ref(_, new_ty, _) = ty.kind() {