|
1 | 1 | use super::{
|
2 |
| - DerivedObligationCause, EvaluationResult, ImplDerivedObligationCause, Obligation, |
3 |
| - ObligationCause, ObligationCauseCode, PredicateObligation, SelectionContext, |
| 2 | + EvaluationResult, Obligation, ObligationCause, ObligationCauseCode, PredicateObligation, |
| 3 | + SelectionContext, |
4 | 4 | };
|
5 | 5 |
|
6 | 6 | use crate::autoderef::Autoderef;
|
@@ -504,78 +504,50 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
|
504 | 504 | trait_pred: ty::PolyTraitPredicate<'tcx>,
|
505 | 505 | ) -> bool {
|
506 | 506 | // It only make sense when suggesting dereferences for arguments
|
507 |
| - let ObligationCauseCode::FunctionArgumentObligation { .. } = obligation.cause.code() else { |
| 507 | + let code = if let ObligationCauseCode::FunctionArgumentObligation { parent_code, .. } = |
| 508 | + obligation.cause.code() |
| 509 | + { |
| 510 | + parent_code.clone() |
| 511 | + } else { |
508 | 512 | return false;
|
509 | 513 | };
|
510 | 514 | let param_env = obligation.param_env;
|
511 | 515 | let body_id = obligation.cause.body_id;
|
512 | 516 | let span = obligation.cause.span;
|
513 |
| - let mut real_trait_pred = trait_pred; |
514 |
| - let mut code = obligation.cause.code(); |
515 |
| - loop { |
516 |
| - match &code { |
517 |
| - ObligationCauseCode::FunctionArgumentObligation { parent_code, .. } => { |
518 |
| - code = &parent_code; |
519 |
| - } |
520 |
| - ObligationCauseCode::ImplDerivedObligation(box ImplDerivedObligationCause { |
521 |
| - derived: DerivedObligationCause { parent_code, parent_trait_pred }, |
522 |
| - .. |
523 |
| - }) |
524 |
| - | ObligationCauseCode::BuiltinDerivedObligation(DerivedObligationCause { |
525 |
| - parent_code, |
526 |
| - parent_trait_pred, |
527 |
| - }) |
528 |
| - | ObligationCauseCode::DerivedObligation(DerivedObligationCause { |
529 |
| - parent_code, |
530 |
| - parent_trait_pred, |
531 |
| - }) => { |
532 |
| - code = &parent_code; |
533 |
| - real_trait_pred = *parent_trait_pred; |
534 |
| - } |
535 |
| - _ => break, |
536 |
| - }; |
537 |
| - let Some(real_ty) = real_trait_pred.self_ty().no_bound_vars() else { |
538 |
| - continue; |
539 |
| - }; |
| 517 | + let real_trait_pred = match &*code { |
| 518 | + ObligationCauseCode::ImplDerivedObligation(cause) => cause.derived.parent_trait_pred, |
| 519 | + ObligationCauseCode::DerivedObligation(cause) |
| 520 | + | ObligationCauseCode::BuiltinDerivedObligation(cause) => cause.parent_trait_pred, |
| 521 | + _ => trait_pred, |
| 522 | + }; |
| 523 | + let Some(real_ty) = real_trait_pred.self_ty().no_bound_vars() else { |
| 524 | + return false; |
| 525 | + }; |
540 | 526 |
|
541 |
| - if let ty::Ref(region, base_ty, mutbl) = *real_ty.kind() { |
542 |
| - let mut autoderef = Autoderef::new(self, param_env, body_id, span, base_ty, span); |
543 |
| - if let Some(steps) = autoderef.find_map(|(ty, steps)| { |
544 |
| - // Re-add the `&` |
545 |
| - let ty = self.tcx.mk_ref(region, TypeAndMut { ty, mutbl }); |
546 |
| - let obligation = |
547 |
| - self.mk_trait_obligation_with_new_self_ty(param_env, real_trait_pred, ty); |
548 |
| - Some(steps).filter(|_| self.predicate_may_hold(&obligation)) |
549 |
| - }) { |
550 |
| - if steps > 0 { |
551 |
| - if let Ok(src) = self.tcx.sess.source_map().span_to_snippet(span) { |
552 |
| - // Don't care about `&mut` because `DerefMut` is used less |
553 |
| - // often and user will not expect autoderef happens. |
554 |
| - if src.starts_with('&') && !src.starts_with("&mut ") { |
555 |
| - let derefs = "*".repeat(steps); |
556 |
| - err.span_suggestion( |
557 |
| - span, |
558 |
| - "consider dereferencing here", |
559 |
| - format!("&{}{}", derefs, &src[1..]), |
560 |
| - Applicability::MachineApplicable, |
561 |
| - ); |
562 |
| - return true; |
563 |
| - } |
| 527 | + if let ty::Ref(region, base_ty, mutbl) = *real_ty.kind() { |
| 528 | + let mut autoderef = Autoderef::new(self, param_env, body_id, span, base_ty, span); |
| 529 | + if let Some(steps) = autoderef.find_map(|(ty, steps)| { |
| 530 | + // Re-add the `&` |
| 531 | + let ty = self.tcx.mk_ref(region, TypeAndMut { ty, mutbl }); |
| 532 | + let obligation = |
| 533 | + self.mk_trait_obligation_with_new_self_ty(param_env, real_trait_pred, ty); |
| 534 | + Some(steps).filter(|_| self.predicate_may_hold(&obligation)) |
| 535 | + }) { |
| 536 | + if steps > 0 { |
| 537 | + if let Ok(src) = self.tcx.sess.source_map().span_to_snippet(span) { |
| 538 | + // Don't care about `&mut` because `DerefMut` is used less |
| 539 | + // often and user will not expect autoderef happens. |
| 540 | + if src.starts_with('&') && !src.starts_with("&mut ") { |
| 541 | + let derefs = "*".repeat(steps); |
| 542 | + err.span_suggestion( |
| 543 | + span, |
| 544 | + "consider adding dereference here", |
| 545 | + format!("&{}{}", derefs, &src[1..]), |
| 546 | + Applicability::MachineApplicable, |
| 547 | + ); |
| 548 | + return true; |
564 | 549 | }
|
565 | 550 | }
|
566 |
| - } else if real_trait_pred != trait_pred { |
567 |
| - // This branch addresses #87437. |
568 |
| - let obligation = |
569 |
| - self.mk_trait_obligation_with_new_self_ty(param_env, real_trait_pred, base_ty); |
570 |
| - if self.predicate_may_hold(&obligation) { |
571 |
| - err.span_suggestion_verbose( |
572 |
| - span.shrink_to_lo(), |
573 |
| - "consider dereferencing here", |
574 |
| - "*".to_string(), |
575 |
| - Applicability::MachineApplicable, |
576 |
| - ); |
577 |
| - return true; |
578 |
| - } |
579 | 551 | }
|
580 | 552 | }
|
581 | 553 | }
|
|
0 commit comments