Re-format let-else per rustfmt update
This commit is contained in:
parent
67b0cfc761
commit
cc907f80b9
162 changed files with 1404 additions and 947 deletions
|
@ -160,8 +160,8 @@ pub(super) trait GoalKind<'tcx>:
|
|||
Self::probe_and_match_goal_against_assumption(ecx, goal, assumption, |ecx| {
|
||||
let tcx = ecx.tcx();
|
||||
let ty::Dynamic(bounds, _, _) = *goal.predicate.self_ty().kind() else {
|
||||
bug!("expected object type in `consider_object_bound_candidate`");
|
||||
};
|
||||
bug!("expected object type in `consider_object_bound_candidate`");
|
||||
};
|
||||
ecx.add_goals(
|
||||
structural_traits::predicates_for_object_candidate(
|
||||
&ecx,
|
||||
|
@ -352,9 +352,7 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
|
|||
candidates: &mut Vec<Candidate<'tcx>>,
|
||||
) {
|
||||
let tcx = self.tcx();
|
||||
let &ty::Alias(_, projection_ty) = goal.predicate.self_ty().kind() else {
|
||||
return
|
||||
};
|
||||
let &ty::Alias(_, projection_ty) = goal.predicate.self_ty().kind() else { return };
|
||||
|
||||
let normalized_self_candidates: Result<_, NoSolution> =
|
||||
self.probe(|_| CandidateKind::NormalizedSelfTyAssembly).enter(|ecx| {
|
||||
|
|
|
@ -221,10 +221,7 @@ fn rematch_object<'tcx>(
|
|||
mut nested: Vec<PredicateObligation<'tcx>>,
|
||||
) -> SelectionResult<'tcx, Selection<'tcx>> {
|
||||
let self_ty = goal.predicate.self_ty();
|
||||
let ty::Dynamic(data, _, source_kind) = *self_ty.kind()
|
||||
else {
|
||||
bug!()
|
||||
};
|
||||
let ty::Dynamic(data, _, source_kind) = *self_ty.kind() else { bug!() };
|
||||
let source_trait_ref = data.principal().unwrap().with_self_ty(infcx.tcx, self_ty);
|
||||
|
||||
let (is_upcasting, target_trait_ref_unnormalized) = if Some(goal.predicate.def_id())
|
||||
|
|
|
@ -266,12 +266,11 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
|
|||
return Err(NoSolution);
|
||||
}
|
||||
|
||||
let Certainty::Maybe(maybe_cause) = responses.iter().fold(
|
||||
Certainty::AMBIGUOUS,
|
||||
|certainty, response| {
|
||||
let Certainty::Maybe(maybe_cause) =
|
||||
responses.iter().fold(Certainty::AMBIGUOUS, |certainty, response| {
|
||||
certainty.unify_with(response.value.certainty)
|
||||
},
|
||||
) else {
|
||||
})
|
||||
else {
|
||||
bug!("expected flounder response to be ambiguous")
|
||||
};
|
||||
|
||||
|
|
|
@ -146,89 +146,88 @@ impl<'tcx> assembly::GoalKind<'tcx> for ProjectionPredicate<'tcx> {
|
|||
return Err(NoSolution);
|
||||
}
|
||||
|
||||
ecx.probe(
|
||||
|r| CandidateKind::Candidate { name: "impl".into(), result: *r }).enter(
|
||||
|ecx| {
|
||||
let impl_substs = ecx.fresh_substs_for_item(impl_def_id);
|
||||
let impl_trait_ref = impl_trait_ref.subst(tcx, impl_substs);
|
||||
ecx.probe(|r| CandidateKind::Candidate { name: "impl".into(), result: *r }).enter(|ecx| {
|
||||
let impl_substs = ecx.fresh_substs_for_item(impl_def_id);
|
||||
let impl_trait_ref = impl_trait_ref.subst(tcx, impl_substs);
|
||||
|
||||
ecx.eq(goal.param_env, goal_trait_ref, impl_trait_ref)?;
|
||||
ecx.eq(goal.param_env, goal_trait_ref, impl_trait_ref)?;
|
||||
|
||||
let where_clause_bounds = tcx
|
||||
.predicates_of(impl_def_id)
|
||||
.instantiate(tcx, impl_substs)
|
||||
.predicates
|
||||
.into_iter()
|
||||
.map(|pred| goal.with(tcx, pred));
|
||||
ecx.add_goals(where_clause_bounds);
|
||||
let where_clause_bounds = tcx
|
||||
.predicates_of(impl_def_id)
|
||||
.instantiate(tcx, impl_substs)
|
||||
.predicates
|
||||
.into_iter()
|
||||
.map(|pred| goal.with(tcx, pred));
|
||||
ecx.add_goals(where_clause_bounds);
|
||||
|
||||
// In case the associated item is hidden due to specialization, we have to
|
||||
// return ambiguity this would otherwise be incomplete, resulting in
|
||||
// unsoundness during coherence (#105782).
|
||||
let Some(assoc_def) = fetch_eligible_assoc_item_def(
|
||||
ecx,
|
||||
goal.param_env,
|
||||
goal_trait_ref,
|
||||
goal.predicate.def_id(),
|
||||
impl_def_id
|
||||
)? else {
|
||||
return ecx.evaluate_added_goals_and_make_canonical_response(Certainty::AMBIGUOUS);
|
||||
};
|
||||
// In case the associated item is hidden due to specialization, we have to
|
||||
// return ambiguity this would otherwise be incomplete, resulting in
|
||||
// unsoundness during coherence (#105782).
|
||||
let Some(assoc_def) = fetch_eligible_assoc_item_def(
|
||||
ecx,
|
||||
goal.param_env,
|
||||
goal_trait_ref,
|
||||
goal.predicate.def_id(),
|
||||
impl_def_id,
|
||||
)?
|
||||
else {
|
||||
return ecx.evaluate_added_goals_and_make_canonical_response(Certainty::AMBIGUOUS);
|
||||
};
|
||||
|
||||
if !assoc_def.item.defaultness(tcx).has_value() {
|
||||
let guar = tcx.sess.delay_span_bug(
|
||||
tcx.def_span(assoc_def.item.def_id),
|
||||
"missing value for assoc item in impl",
|
||||
);
|
||||
let error_term = match assoc_def.item.kind {
|
||||
ty::AssocKind::Const => ty::Const::new_error(tcx,
|
||||
guar,
|
||||
tcx.type_of(goal.predicate.def_id())
|
||||
.subst(tcx, goal.predicate.projection_ty.substs),
|
||||
)
|
||||
.into(),
|
||||
ty::AssocKind::Type => Ty::new_error(tcx,guar).into(),
|
||||
ty::AssocKind::Fn => unreachable!(),
|
||||
};
|
||||
ecx.eq(goal.param_env, goal.predicate.term, error_term)
|
||||
.expect("expected goal term to be fully unconstrained");
|
||||
return ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes);
|
||||
}
|
||||
|
||||
// Getting the right substitutions here is complex, e.g. given:
|
||||
// - a goal `<Vec<u32> as Trait<i32>>::Assoc<u64>`
|
||||
// - the applicable impl `impl<T> Trait<i32> for Vec<T>`
|
||||
// - and the impl which defines `Assoc` being `impl<T, U> Trait<U> for Vec<T>`
|
||||
//
|
||||
// We first rebase the goal substs onto the impl, going from `[Vec<u32>, i32, u64]`
|
||||
// to `[u32, u64]`.
|
||||
//
|
||||
// And then map these substs to the substs of the defining impl of `Assoc`, going
|
||||
// from `[u32, u64]` to `[u32, i32, u64]`.
|
||||
let impl_substs_with_gat = goal.predicate.projection_ty.substs.rebase_onto(
|
||||
tcx,
|
||||
goal_trait_ref.def_id,
|
||||
impl_substs,
|
||||
if !assoc_def.item.defaultness(tcx).has_value() {
|
||||
let guar = tcx.sess.delay_span_bug(
|
||||
tcx.def_span(assoc_def.item.def_id),
|
||||
"missing value for assoc item in impl",
|
||||
);
|
||||
let substs = ecx.translate_substs(
|
||||
goal.param_env,
|
||||
impl_def_id,
|
||||
impl_substs_with_gat,
|
||||
assoc_def.defining_node,
|
||||
);
|
||||
|
||||
// Finally we construct the actual value of the associated type.
|
||||
let term = match assoc_def.item.kind {
|
||||
ty::AssocKind::Type => tcx.type_of(assoc_def.item.def_id).map_bound(|ty| ty.into()),
|
||||
ty::AssocKind::Const => bug!("associated const projection is not supported yet"),
|
||||
ty::AssocKind::Fn => unreachable!("we should never project to a fn"),
|
||||
let error_term = match assoc_def.item.kind {
|
||||
ty::AssocKind::Const => ty::Const::new_error(
|
||||
tcx,
|
||||
guar,
|
||||
tcx.type_of(goal.predicate.def_id())
|
||||
.subst(tcx, goal.predicate.projection_ty.substs),
|
||||
)
|
||||
.into(),
|
||||
ty::AssocKind::Type => Ty::new_error(tcx, guar).into(),
|
||||
ty::AssocKind::Fn => unreachable!(),
|
||||
};
|
||||
|
||||
ecx.eq(goal.param_env, goal.predicate.term, term.subst(tcx, substs))
|
||||
ecx.eq(goal.param_env, goal.predicate.term, error_term)
|
||||
.expect("expected goal term to be fully unconstrained");
|
||||
ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
|
||||
},
|
||||
)
|
||||
return ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes);
|
||||
}
|
||||
|
||||
// Getting the right substitutions here is complex, e.g. given:
|
||||
// - a goal `<Vec<u32> as Trait<i32>>::Assoc<u64>`
|
||||
// - the applicable impl `impl<T> Trait<i32> for Vec<T>`
|
||||
// - and the impl which defines `Assoc` being `impl<T, U> Trait<U> for Vec<T>`
|
||||
//
|
||||
// We first rebase the goal substs onto the impl, going from `[Vec<u32>, i32, u64]`
|
||||
// to `[u32, u64]`.
|
||||
//
|
||||
// And then map these substs to the substs of the defining impl of `Assoc`, going
|
||||
// from `[u32, u64]` to `[u32, i32, u64]`.
|
||||
let impl_substs_with_gat = goal.predicate.projection_ty.substs.rebase_onto(
|
||||
tcx,
|
||||
goal_trait_ref.def_id,
|
||||
impl_substs,
|
||||
);
|
||||
let substs = ecx.translate_substs(
|
||||
goal.param_env,
|
||||
impl_def_id,
|
||||
impl_substs_with_gat,
|
||||
assoc_def.defining_node,
|
||||
);
|
||||
|
||||
// Finally we construct the actual value of the associated type.
|
||||
let term = match assoc_def.item.kind {
|
||||
ty::AssocKind::Type => tcx.type_of(assoc_def.item.def_id).map_bound(|ty| ty.into()),
|
||||
ty::AssocKind::Const => bug!("associated const projection is not supported yet"),
|
||||
ty::AssocKind::Fn => unreachable!("we should never project to a fn"),
|
||||
};
|
||||
|
||||
ecx.eq(goal.param_env, goal.predicate.term, term.subst(tcx, substs))
|
||||
.expect("expected goal term to be fully unconstrained");
|
||||
ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
|
||||
})
|
||||
}
|
||||
|
||||
fn consider_auto_trait_candidate(
|
||||
|
|
|
@ -600,11 +600,9 @@ impl<'tcx> assembly::GoalKind<'tcx> for TraitPredicate<'tcx> {
|
|||
// which will ICE for region vars.
|
||||
let substs = ecx.tcx().erase_regions(goal.predicate.trait_ref.substs);
|
||||
|
||||
let Some(assume) = rustc_transmute::Assume::from_const(
|
||||
ecx.tcx(),
|
||||
goal.param_env,
|
||||
substs.const_at(3),
|
||||
) else {
|
||||
let Some(assume) =
|
||||
rustc_transmute::Assume::from_const(ecx.tcx(), goal.param_env, substs.const_at(3))
|
||||
else {
|
||||
return Err(NoSolution);
|
||||
};
|
||||
|
||||
|
|
|
@ -152,14 +152,9 @@ impl<'tcx> AutoTraitFinder<'tcx> {
|
|||
// traits::project will see that 'T: SomeTrait' is in our ParamEnv, allowing
|
||||
// SelectionContext to return it back to us.
|
||||
|
||||
let Some((new_env, user_env)) = self.evaluate_predicates(
|
||||
&infcx,
|
||||
trait_did,
|
||||
ty,
|
||||
orig_env,
|
||||
orig_env,
|
||||
&mut fresh_preds,
|
||||
) else {
|
||||
let Some((new_env, user_env)) =
|
||||
self.evaluate_predicates(&infcx, trait_did, ty, orig_env, orig_env, &mut fresh_preds)
|
||||
else {
|
||||
return AutoTraitResult::NegativeImpl;
|
||||
};
|
||||
|
||||
|
|
|
@ -376,7 +376,7 @@ fn impl_intersection_has_negative_obligation(
|
|||
// do the impls unify? If not, then it's not currently possible to prove any
|
||||
// obligations about their intersection.
|
||||
let Ok(InferOk { obligations: equate_obligations, .. }) =
|
||||
infcx.at(&ObligationCause::dummy(), impl_env).eq(DefineOpaqueTypes::No,subject1, subject2)
|
||||
infcx.at(&ObligationCause::dummy(), impl_env).eq(DefineOpaqueTypes::No, subject1, subject2)
|
||||
else {
|
||||
debug!("explicit_disjoint: {:?} does not unify with {:?}", subject1, subject2);
|
||||
return false;
|
||||
|
@ -437,8 +437,7 @@ fn prove_negated_obligation<'tcx>(
|
|||
let body_def_id = body_def_id.as_local().unwrap_or(CRATE_DEF_ID);
|
||||
|
||||
let ocx = ObligationCtxt::new(&infcx);
|
||||
let Ok(wf_tys) = ocx.assumed_wf_types(param_env, body_def_id)
|
||||
else {
|
||||
let Ok(wf_tys) = ocx.assumed_wf_types(param_env, body_def_id) else {
|
||||
return false;
|
||||
};
|
||||
|
||||
|
|
|
@ -2708,10 +2708,17 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
|
|||
err: &mut Diagnostic,
|
||||
obligation: &PredicateObligation<'tcx>,
|
||||
) {
|
||||
let ty::PredicateKind::Clause(ty::ClauseKind::Trait(pred)) = obligation.predicate.kind().skip_binder() else { return; };
|
||||
let ty::PredicateKind::Clause(ty::ClauseKind::Trait(pred)) =
|
||||
obligation.predicate.kind().skip_binder()
|
||||
else {
|
||||
return;
|
||||
};
|
||||
let (ObligationCauseCode::BindingObligation(item_def_id, span)
|
||||
| ObligationCauseCode::ExprBindingObligation(item_def_id, span, ..))
|
||||
= *obligation.cause.code().peel_derives() else { return; };
|
||||
| ObligationCauseCode::ExprBindingObligation(item_def_id, span, ..)) =
|
||||
*obligation.cause.code().peel_derives()
|
||||
else {
|
||||
return;
|
||||
};
|
||||
debug!(?pred, ?item_def_id, ?span);
|
||||
|
||||
let (Some(node), true) = (
|
||||
|
@ -2880,10 +2887,16 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
|
|||
src: trait_ref.substs.type_at(1),
|
||||
};
|
||||
let scope = trait_ref.substs.type_at(2);
|
||||
let Some(assume) =
|
||||
rustc_transmute::Assume::from_const(self.infcx.tcx, obligation.param_env, trait_ref.substs.const_at(3)) else {
|
||||
span_bug!(span, "Unable to construct rustc_transmute::Assume where it was previously possible");
|
||||
};
|
||||
let Some(assume) = rustc_transmute::Assume::from_const(
|
||||
self.infcx.tcx,
|
||||
obligation.param_env,
|
||||
trait_ref.substs.const_at(3),
|
||||
) else {
|
||||
span_bug!(
|
||||
span,
|
||||
"Unable to construct rustc_transmute::Assume where it was previously possible"
|
||||
);
|
||||
};
|
||||
|
||||
match rustc_transmute::TransmuteTypeEnv::new(self.infcx).is_transmutable(
|
||||
obligation.cause,
|
||||
|
|
|
@ -752,14 +752,20 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
|
|||
trait_pred: ty::PolyTraitPredicate<'tcx>,
|
||||
) -> bool {
|
||||
// It only make sense when suggesting dereferences for arguments
|
||||
let ObligationCauseCode::FunctionArgumentObligation { arg_hir_id, call_hir_id, .. } = obligation.cause.code()
|
||||
else { return false; };
|
||||
let Some(typeck_results) = &self.typeck_results
|
||||
else { return false; };
|
||||
let hir::Node::Expr(expr) = self.tcx.hir().get(*arg_hir_id)
|
||||
else { return false; };
|
||||
let Some(arg_ty) = typeck_results.expr_ty_adjusted_opt(expr)
|
||||
else { return false; };
|
||||
let ObligationCauseCode::FunctionArgumentObligation { arg_hir_id, call_hir_id, .. } =
|
||||
obligation.cause.code()
|
||||
else {
|
||||
return false;
|
||||
};
|
||||
let Some(typeck_results) = &self.typeck_results else {
|
||||
return false;
|
||||
};
|
||||
let hir::Node::Expr(expr) = self.tcx.hir().get(*arg_hir_id) else {
|
||||
return false;
|
||||
};
|
||||
let Some(arg_ty) = typeck_results.expr_ty_adjusted_opt(expr) else {
|
||||
return false;
|
||||
};
|
||||
|
||||
let span = obligation.cause.span;
|
||||
let mut real_trait_pred = trait_pred;
|
||||
|
@ -933,11 +939,11 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
|
|||
trait_pred.self_ty(),
|
||||
);
|
||||
|
||||
let Some((def_id_or_name, output, inputs)) = self.extract_callable_info(
|
||||
obligation.cause.body_id,
|
||||
obligation.param_env,
|
||||
self_ty,
|
||||
) else { return false; };
|
||||
let Some((def_id_or_name, output, inputs)) =
|
||||
self.extract_callable_info(obligation.cause.body_id, obligation.param_env, self_ty)
|
||||
else {
|
||||
return false;
|
||||
};
|
||||
|
||||
// Remapping bound vars here
|
||||
let trait_pred_and_self = trait_pred.map_bound(|trait_pred| (trait_pred, output));
|
||||
|
@ -1035,26 +1041,40 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
|
|||
span.remove_mark();
|
||||
}
|
||||
let mut expr_finder = FindExprBySpan::new(span);
|
||||
let Some(body_id) = self.tcx.hir().maybe_body_owned_by(obligation.cause.body_id) else { return; };
|
||||
let Some(body_id) = self.tcx.hir().maybe_body_owned_by(obligation.cause.body_id) else {
|
||||
return;
|
||||
};
|
||||
let body = self.tcx.hir().body(body_id);
|
||||
expr_finder.visit_expr(body.value);
|
||||
let Some(expr) = expr_finder.result else { return; };
|
||||
let Some(typeck) = &self.typeck_results else { return; };
|
||||
let Some(ty) = typeck.expr_ty_adjusted_opt(expr) else { return; };
|
||||
let Some(expr) = expr_finder.result else {
|
||||
return;
|
||||
};
|
||||
let Some(typeck) = &self.typeck_results else {
|
||||
return;
|
||||
};
|
||||
let Some(ty) = typeck.expr_ty_adjusted_opt(expr) else {
|
||||
return;
|
||||
};
|
||||
if !ty.is_unit() {
|
||||
return;
|
||||
};
|
||||
let hir::ExprKind::Path(hir::QPath::Resolved(None, path)) = expr.kind else { return; };
|
||||
let hir::def::Res::Local(hir_id) = path.res else { return; };
|
||||
let hir::ExprKind::Path(hir::QPath::Resolved(None, path)) = expr.kind else {
|
||||
return;
|
||||
};
|
||||
let hir::def::Res::Local(hir_id) = path.res else {
|
||||
return;
|
||||
};
|
||||
let Some(hir::Node::Pat(pat)) = self.tcx.hir().find(hir_id) else {
|
||||
return;
|
||||
};
|
||||
let Some(hir::Node::Local(hir::Local {
|
||||
ty: None,
|
||||
init: Some(init),
|
||||
..
|
||||
})) = self.tcx.hir().find_parent(pat.hir_id) else { return; };
|
||||
let hir::ExprKind::Block(block, None) = init.kind else { return; };
|
||||
let Some(hir::Node::Local(hir::Local { ty: None, init: Some(init), .. })) =
|
||||
self.tcx.hir().find_parent(pat.hir_id)
|
||||
else {
|
||||
return;
|
||||
};
|
||||
let hir::ExprKind::Block(block, None) = init.kind else {
|
||||
return;
|
||||
};
|
||||
if block.expr.is_some() {
|
||||
return;
|
||||
}
|
||||
|
@ -1062,7 +1082,9 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
|
|||
err.span_label(block.span, "this empty block is missing a tail expression");
|
||||
return;
|
||||
};
|
||||
let hir::StmtKind::Semi(tail_expr) = stmt.kind else { return; };
|
||||
let hir::StmtKind::Semi(tail_expr) = stmt.kind else {
|
||||
return;
|
||||
};
|
||||
let Some(ty) = typeck.expr_ty_opt(tail_expr) else {
|
||||
err.span_label(block.span, "this block is missing a tail expression");
|
||||
return;
|
||||
|
@ -1092,12 +1114,18 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
|
|||
) -> bool {
|
||||
let self_ty = self.resolve_vars_if_possible(trait_pred.self_ty());
|
||||
let ty = self.instantiate_binder_with_placeholders(self_ty);
|
||||
let Some(generics) = self.tcx.hir().get_generics(obligation.cause.body_id) else { return false };
|
||||
let Some(generics) = self.tcx.hir().get_generics(obligation.cause.body_id) else {
|
||||
return false;
|
||||
};
|
||||
let ty::Ref(_, inner_ty, hir::Mutability::Not) = ty.kind() else { return false };
|
||||
let ty::Param(param) = inner_ty.kind() else { return false };
|
||||
let ObligationCauseCode::FunctionArgumentObligation { arg_hir_id, .. } = obligation.cause.code() else { return false };
|
||||
let ObligationCauseCode::FunctionArgumentObligation { arg_hir_id, .. } =
|
||||
obligation.cause.code()
|
||||
else {
|
||||
return false;
|
||||
};
|
||||
let arg_node = self.tcx.hir().get(*arg_hir_id);
|
||||
let Node::Expr(Expr { kind: hir::ExprKind::Path(_), ..}) = arg_node else { return false };
|
||||
let Node::Expr(Expr { kind: hir::ExprKind::Path(_), .. }) = arg_node else { return false };
|
||||
|
||||
let clone_trait = self.tcx.require_lang_item(LangItem::Clone, None);
|
||||
let has_clone = |ty| {
|
||||
|
@ -1143,21 +1171,30 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
|
|||
found: Ty<'tcx>,
|
||||
) -> Option<(DefIdOrName, Ty<'tcx>, Vec<Ty<'tcx>>)> {
|
||||
// Autoderef is useful here because sometimes we box callables, etc.
|
||||
let Some((def_id_or_name, output, inputs)) = (self.autoderef_steps)(found).into_iter().find_map(|(found, _)| {
|
||||
match *found.kind() {
|
||||
ty::FnPtr(fn_sig) =>
|
||||
Some((DefIdOrName::Name("function pointer"), fn_sig.output(), fn_sig.inputs())),
|
||||
ty::FnDef(def_id, _) => {
|
||||
let fn_sig = found.fn_sig(self.tcx);
|
||||
Some((DefIdOrName::DefId(def_id), fn_sig.output(), fn_sig.inputs()))
|
||||
}
|
||||
ty::Closure(def_id, substs) => {
|
||||
let fn_sig = substs.as_closure().sig();
|
||||
Some((DefIdOrName::DefId(def_id), fn_sig.output(), fn_sig.inputs().map_bound(|inputs| &inputs[1..])))
|
||||
}
|
||||
ty::Alias(ty::Opaque, ty::AliasTy { def_id, substs, .. }) => {
|
||||
self.tcx.item_bounds(def_id).subst(self.tcx, substs).iter().find_map(|pred| {
|
||||
if let ty::ClauseKind::Projection(proj) = pred.kind().skip_binder()
|
||||
let Some((def_id_or_name, output, inputs)) =
|
||||
(self.autoderef_steps)(found).into_iter().find_map(|(found, _)| {
|
||||
match *found.kind() {
|
||||
ty::FnPtr(fn_sig) => Some((
|
||||
DefIdOrName::Name("function pointer"),
|
||||
fn_sig.output(),
|
||||
fn_sig.inputs(),
|
||||
)),
|
||||
ty::FnDef(def_id, _) => {
|
||||
let fn_sig = found.fn_sig(self.tcx);
|
||||
Some((DefIdOrName::DefId(def_id), fn_sig.output(), fn_sig.inputs()))
|
||||
}
|
||||
ty::Closure(def_id, substs) => {
|
||||
let fn_sig = substs.as_closure().sig();
|
||||
Some((
|
||||
DefIdOrName::DefId(def_id),
|
||||
fn_sig.output(),
|
||||
fn_sig.inputs().map_bound(|inputs| &inputs[1..]),
|
||||
))
|
||||
}
|
||||
ty::Alias(ty::Opaque, ty::AliasTy { def_id, substs, .. }) => {
|
||||
self.tcx.item_bounds(def_id).subst(self.tcx, substs).iter().find_map(
|
||||
|pred| {
|
||||
if let ty::ClauseKind::Projection(proj) = pred.kind().skip_binder()
|
||||
&& Some(proj.projection_ty.def_id) == self.tcx.lang_items().fn_once_output()
|
||||
// args tuple will always be substs[1]
|
||||
&& let ty::Tuple(args) = proj.projection_ty.substs.type_at(1).kind()
|
||||
|
@ -1170,11 +1207,12 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
|
|||
} else {
|
||||
None
|
||||
}
|
||||
})
|
||||
}
|
||||
ty::Dynamic(data, _, ty::Dyn) => {
|
||||
data.iter().find_map(|pred| {
|
||||
if let ty::ExistentialPredicate::Projection(proj) = pred.skip_binder()
|
||||
},
|
||||
)
|
||||
}
|
||||
ty::Dynamic(data, _, ty::Dyn) => {
|
||||
data.iter().find_map(|pred| {
|
||||
if let ty::ExistentialPredicate::Projection(proj) = pred.skip_binder()
|
||||
&& Some(proj.def_id) == self.tcx.lang_items().fn_once_output()
|
||||
// for existential projection, substs are shifted over by 1
|
||||
&& let ty::Tuple(args) = proj.substs.type_at(0).kind()
|
||||
|
@ -1187,11 +1225,11 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
|
|||
} else {
|
||||
None
|
||||
}
|
||||
})
|
||||
}
|
||||
ty::Param(param) => {
|
||||
let generics = self.tcx.generics_of(body_id);
|
||||
let name = if generics.count() > param.index as usize
|
||||
})
|
||||
}
|
||||
ty::Param(param) => {
|
||||
let generics = self.tcx.generics_of(body_id);
|
||||
let name = if generics.count() > param.index as usize
|
||||
&& let def = generics.param_at(param.index as usize, self.tcx)
|
||||
&& matches!(def.kind, ty::GenericParamDefKind::Type { .. })
|
||||
&& def.name == param.name
|
||||
|
@ -1200,8 +1238,8 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
|
|||
} else {
|
||||
DefIdOrName::Name("type parameter")
|
||||
};
|
||||
param_env.caller_bounds().iter().find_map(|pred| {
|
||||
if let ty::ClauseKind::Projection(proj) = pred.kind().skip_binder()
|
||||
param_env.caller_bounds().iter().find_map(|pred| {
|
||||
if let ty::ClauseKind::Projection(proj) = pred.kind().skip_binder()
|
||||
&& Some(proj.projection_ty.def_id) == self.tcx.lang_items().fn_once_output()
|
||||
&& proj.projection_ty.self_ty() == found
|
||||
// args tuple will always be substs[1]
|
||||
|
@ -1215,11 +1253,14 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
|
|||
} else {
|
||||
None
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
||||
_ => None,
|
||||
}
|
||||
_ => None,
|
||||
}
|
||||
}) else { return None; };
|
||||
})
|
||||
else {
|
||||
return None;
|
||||
};
|
||||
|
||||
let output = self.instantiate_binder_with_fresh_vars(
|
||||
DUMMY_SP,
|
||||
|
@ -1408,11 +1449,17 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
|
|||
// Issue #104961, we need to add parentheses properly for compound expressions
|
||||
// for example, `x.starts_with("hi".to_string() + "you")`
|
||||
// should be `x.starts_with(&("hi".to_string() + "you"))`
|
||||
let Some(body_id) = self.tcx.hir().maybe_body_owned_by(obligation.cause.body_id) else { return false; };
|
||||
let Some(body_id) =
|
||||
self.tcx.hir().maybe_body_owned_by(obligation.cause.body_id)
|
||||
else {
|
||||
return false;
|
||||
};
|
||||
let body = self.tcx.hir().body(body_id);
|
||||
let mut expr_finder = FindExprBySpan::new(span);
|
||||
expr_finder.visit_expr(body.value);
|
||||
let Some(expr) = expr_finder.result else { return false; };
|
||||
let Some(expr) = expr_finder.result else {
|
||||
return false;
|
||||
};
|
||||
let needs_parens = match expr.kind {
|
||||
// parenthesize if needed (Issue #46756)
|
||||
hir::ExprKind::Cast(_, _) | hir::ExprKind::Binary(_, _, _) => true,
|
||||
|
@ -1463,8 +1510,12 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
|
|||
self_ty: Ty<'tcx>,
|
||||
target_ty: Ty<'tcx>,
|
||||
) {
|
||||
let ty::Ref(_, object_ty, hir::Mutability::Not) = target_ty.kind() else { return; };
|
||||
let ty::Dynamic(predicates, _, ty::Dyn) = object_ty.kind() else { return; };
|
||||
let ty::Ref(_, object_ty, hir::Mutability::Not) = target_ty.kind() else {
|
||||
return;
|
||||
};
|
||||
let ty::Dynamic(predicates, _, ty::Dyn) = object_ty.kind() else {
|
||||
return;
|
||||
};
|
||||
let self_ref_ty = Ty::new_imm_ref(self.tcx, self.tcx.lifetimes.re_erased, self_ty);
|
||||
|
||||
for predicate in predicates.iter() {
|
||||
|
@ -1566,7 +1617,9 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
|
|||
}
|
||||
|
||||
// Maybe suggest removal of borrows from expressions, like in `for i in &&&foo {}`.
|
||||
let Some(mut expr) = expr_finder.result else { return false; };
|
||||
let Some(mut expr) = expr_finder.result else {
|
||||
return false;
|
||||
};
|
||||
let mut count = 0;
|
||||
let mut suggestions = vec![];
|
||||
// Skipping binder here, remapping below
|
||||
|
@ -1798,7 +1851,9 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
|
|||
|
||||
fn return_type_span(&self, obligation: &PredicateObligation<'tcx>) -> Option<Span> {
|
||||
let hir = self.tcx.hir();
|
||||
let Some(hir::Node::Item(hir::Item { kind: hir::ItemKind::Fn(sig, ..), .. })) = hir.find_by_def_id(obligation.cause.body_id) else {
|
||||
let Some(hir::Node::Item(hir::Item { kind: hir::ItemKind::Fn(sig, ..), .. })) =
|
||||
hir.find_by_def_id(obligation.cause.body_id)
|
||||
else {
|
||||
return None;
|
||||
};
|
||||
|
||||
|
@ -2222,7 +2277,9 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
|
|||
|
||||
// Only continue if a generator was found.
|
||||
debug!(?generator, ?trait_ref, ?target_ty);
|
||||
let (Some(generator_did), Some(trait_ref), Some(target_ty)) = (generator, trait_ref, target_ty) else {
|
||||
let (Some(generator_did), Some(trait_ref), Some(target_ty)) =
|
||||
(generator, trait_ref, target_ty)
|
||||
else {
|
||||
return false;
|
||||
};
|
||||
|
||||
|
@ -3617,7 +3674,9 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
|
|||
let Some(typeck_results) = self.typeck_results.as_ref() else { return };
|
||||
|
||||
// Make sure we're dealing with the `Option` type.
|
||||
let Some(option_ty_adt) = typeck_results.expr_ty_adjusted(expr).ty_adt_def() else { return };
|
||||
let Some(option_ty_adt) = typeck_results.expr_ty_adjusted(expr).ty_adt_def() else {
|
||||
return;
|
||||
};
|
||||
if !tcx.is_diagnostic_item(sym::Option, option_ty_adt.did()) {
|
||||
return;
|
||||
}
|
||||
|
@ -3749,11 +3808,17 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
|
|||
while let Some(assocs_in_method) = assocs.next() {
|
||||
let Some(prev_assoc_in_method) = assocs.peek() else {
|
||||
for entry in assocs_in_method {
|
||||
let Some((span, (assoc, ty))) = entry else { continue; };
|
||||
if primary_spans.is_empty() || type_diffs.iter().any(|diff| {
|
||||
let Sorts(expected_found) = diff else { return false; };
|
||||
self.can_eq(param_env, expected_found.found, ty)
|
||||
}) {
|
||||
let Some((span, (assoc, ty))) = entry else {
|
||||
continue;
|
||||
};
|
||||
if primary_spans.is_empty()
|
||||
|| type_diffs.iter().any(|diff| {
|
||||
let Sorts(expected_found) = diff else {
|
||||
return false;
|
||||
};
|
||||
self.can_eq(param_env, expected_found.found, ty)
|
||||
})
|
||||
{
|
||||
// FIXME: this doesn't quite work for `Iterator::collect`
|
||||
// because we have `Vec<i32>` and `()`, but we'd want `i32`
|
||||
// to point at the `.into_iter()` call, but as long as we
|
||||
|
@ -3781,7 +3846,9 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
|
|||
let assoc = with_forced_trimmed_paths!(self.tcx.def_path_str(assoc));
|
||||
if !self.can_eq(param_env, ty, *prev_ty) {
|
||||
if type_diffs.iter().any(|diff| {
|
||||
let Sorts(expected_found) = diff else { return false; };
|
||||
let Sorts(expected_found) = diff else {
|
||||
return false;
|
||||
};
|
||||
self.can_eq(param_env, expected_found.found, ty)
|
||||
}) {
|
||||
primary_spans.push(span);
|
||||
|
@ -3829,8 +3896,12 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
|
|||
let ocx = ObligationCtxt::new(self.infcx);
|
||||
let mut assocs_in_this_method = Vec::with_capacity(type_diffs.len());
|
||||
for diff in type_diffs {
|
||||
let Sorts(expected_found) = diff else { continue; };
|
||||
let ty::Alias(ty::Projection, proj) = expected_found.expected.kind() else { continue; };
|
||||
let Sorts(expected_found) = diff else {
|
||||
continue;
|
||||
};
|
||||
let ty::Alias(ty::Projection, proj) = expected_found.expected.kind() else {
|
||||
continue;
|
||||
};
|
||||
|
||||
let origin = TypeVariableOrigin { kind: TypeVariableOriginKind::TypeInference, span };
|
||||
let trait_def_id = proj.trait_def_id(self.tcx);
|
||||
|
@ -3974,7 +4045,9 @@ fn hint_missing_borrow<'tcx>(
|
|||
};
|
||||
|
||||
// This could be a variant constructor, for example.
|
||||
let Some(fn_decl) = found_node.fn_decl() else { return; };
|
||||
let Some(fn_decl) = found_node.fn_decl() else {
|
||||
return;
|
||||
};
|
||||
|
||||
let args = fn_decl.inputs.iter();
|
||||
|
||||
|
|
|
@ -362,12 +362,9 @@ pub fn normalize_param_env_or_error<'tcx>(
|
|||
"normalize_param_env_or_error: predicates=(non-outlives={:?}, outlives={:?})",
|
||||
predicates, outlives_predicates
|
||||
);
|
||||
let Ok(non_outlives_predicates) = do_normalize_predicates(
|
||||
tcx,
|
||||
cause.clone(),
|
||||
elaborated_env,
|
||||
predicates,
|
||||
) else {
|
||||
let Ok(non_outlives_predicates) =
|
||||
do_normalize_predicates(tcx, cause.clone(), elaborated_env, predicates)
|
||||
else {
|
||||
// An unnormalized env is better than nothing.
|
||||
debug!("normalize_param_env_or_error: errored resolving non-outlives predicates");
|
||||
return elaborated_env;
|
||||
|
@ -384,12 +381,9 @@ pub fn normalize_param_env_or_error<'tcx>(
|
|||
unnormalized_env.reveal(),
|
||||
unnormalized_env.constness(),
|
||||
);
|
||||
let Ok(outlives_predicates) = do_normalize_predicates(
|
||||
tcx,
|
||||
cause,
|
||||
outlives_env,
|
||||
outlives_predicates,
|
||||
) else {
|
||||
let Ok(outlives_predicates) =
|
||||
do_normalize_predicates(tcx, cause, outlives_env, outlives_predicates)
|
||||
else {
|
||||
// An unnormalized env is better than nothing.
|
||||
debug!("normalize_param_env_or_error: errored resolving outlives predicates");
|
||||
return elaborated_env;
|
||||
|
|
|
@ -83,7 +83,8 @@ impl<'a, 'tcx: 'a> InferCtxtExt<'a, 'tcx> for InferCtxt<'tcx> {
|
|||
&canonical_var_values,
|
||||
canonical_result,
|
||||
&mut constraints,
|
||||
) else {
|
||||
)
|
||||
else {
|
||||
return vec![];
|
||||
};
|
||||
assert_eq!(&obligations, &[]);
|
||||
|
|
|
@ -402,8 +402,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
|||
};
|
||||
|
||||
for &(predicate, _) in self.tcx().predicates_of(impl_def_id).predicates {
|
||||
let ty::ClauseKind::Trait(pred)
|
||||
= predicate.kind().skip_binder() else { continue };
|
||||
let ty::ClauseKind::Trait(pred) = predicate.kind().skip_binder() else { continue };
|
||||
if fn_ptr_trait != pred.trait_ref.def_id {
|
||||
continue;
|
||||
}
|
||||
|
|
|
@ -342,7 +342,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
|||
let Some(assume) = rustc_transmute::Assume::from_const(
|
||||
self.infcx.tcx,
|
||||
obligation.param_env,
|
||||
predicate.trait_ref.substs.const_at(3)
|
||||
predicate.trait_ref.substs.const_at(3),
|
||||
) else {
|
||||
return Err(Unimplemented);
|
||||
};
|
||||
|
@ -662,10 +662,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
|||
|
||||
let tcx = self.tcx();
|
||||
|
||||
let Some(self_ty) = self
|
||||
.infcx
|
||||
.shallow_resolve(obligation.self_ty().no_bound_vars()) else
|
||||
{
|
||||
let Some(self_ty) = self.infcx.shallow_resolve(obligation.self_ty().no_bound_vars()) else {
|
||||
// FIXME: Ideally we'd support `for<'a> fn(&'a ()): Fn(&'a ())`,
|
||||
// but we do not currently. Luckily, such a bound is not
|
||||
// particularly useful, so we don't expect users to write
|
||||
|
|
|
@ -226,13 +226,11 @@ fn fulfill_implication<'tcx>(
|
|||
util::impl_subject_and_oblig(selcx, param_env, target_impl, target_substs, error_cause);
|
||||
|
||||
// do the impls unify? If not, no specialization.
|
||||
let Ok(InferOk { obligations: more_obligations, .. }) =
|
||||
infcx.at(&ObligationCause::dummy(), param_env).eq(DefineOpaqueTypes::No, source_trait, target_trait)
|
||||
let Ok(InferOk { obligations: more_obligations, .. }) = infcx
|
||||
.at(&ObligationCause::dummy(), param_env)
|
||||
.eq(DefineOpaqueTypes::No, source_trait, target_trait)
|
||||
else {
|
||||
debug!(
|
||||
"fulfill_implication: {:?} does not unify with {:?}",
|
||||
source_trait, target_trait
|
||||
);
|
||||
debug!("fulfill_implication: {:?} does not unify with {:?}", source_trait, target_trait);
|
||||
return Err(());
|
||||
};
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue