Skip to content

Commit b24030f

Browse files
authored
Rollup merge of rust-lang#72292 - ldm0:derefsteps, r=estebank
Replace obligation construction with deref_steps() 1. Use `probe()` to avoid unwanted binding committing during `deref_steps()`. 2. Fixes rust-lang#59819 again by using `deref_steps()`, make the code cleaner. And if we want to suggest multiple dereferences (like: `consider dereferencing the borrow: "****a"`) in the future, this change will make it easier to achieve.
2 parents 75b0a68 + 407958a commit b24030f

File tree

2 files changed

+27
-47
lines changed

2 files changed

+27
-47
lines changed

src/librustc_typeck/check/coercion.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -887,7 +887,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
887887
let coerce = Coerce::new(self, cause, AllowTwoPhase::No);
888888
coerce
889889
.autoderef(rustc_span::DUMMY_SP, expr_ty)
890-
.find_map(|(ty, steps)| coerce.unify(ty, target).ok().map(|_| steps))
890+
.find_map(|(ty, steps)| self.probe(|_| coerce.unify(ty, target)).ok().map(|_| steps))
891891
}
892892

893893
/// Given some expressions, their known unified type and another expression,

src/librustc_typeck/check/demand.rs

+26-46
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,15 @@
11
use crate::check::FnCtxt;
22
use rustc_infer::infer::InferOk;
33
use rustc_trait_selection::infer::InferCtxtExt as _;
4-
use rustc_trait_selection::traits::query::evaluate_obligation::InferCtxtExt as _;
5-
use rustc_trait_selection::traits::{self, ObligationCause};
4+
use rustc_trait_selection::traits::ObligationCause;
65

76
use rustc_ast::util::parser::PREC_POSTFIX;
87
use rustc_errors::{Applicability, DiagnosticBuilder};
98
use rustc_hir as hir;
10-
use rustc_hir::lang_items::{CloneTraitLangItem, DerefTraitLangItem};
9+
use rustc_hir::lang_items::CloneTraitLangItem;
1110
use rustc_hir::{is_range_literal, Node};
1211
use rustc_middle::ty::adjustment::AllowTwoPhase;
13-
use rustc_middle::ty::{self, AssocItem, ToPredicate, Ty, TypeAndMut};
12+
use rustc_middle::ty::{self, AssocItem, Ty, TypeAndMut};
1413
use rustc_span::symbol::sym;
1514
use rustc_span::Span;
1615

@@ -633,48 +632,29 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
633632
}
634633
}
635634
_ if sp == expr.span && !is_macro => {
636-
// Check for `Deref` implementations by constructing a predicate to
637-
// prove: `<T as Deref>::Output == U`
638-
let deref_trait = self.tcx.require_lang_item(DerefTraitLangItem, Some(sp));
639-
let item_def_id = self
640-
.tcx
641-
.associated_items(deref_trait)
642-
.in_definition_order()
643-
.find(|item| item.kind == ty::AssocKind::Type)
644-
.unwrap()
645-
.def_id;
646-
let predicate =
647-
ty::PredicateKind::Projection(ty::Binder::bind(ty::ProjectionPredicate {
648-
// `<T as Deref>::Output`
649-
projection_ty: ty::ProjectionTy {
650-
// `T`
651-
substs: self.tcx.intern_substs(&[checked_ty.into()]),
652-
// `Deref::Output`
653-
item_def_id,
654-
},
655-
// `U`
656-
ty: expected,
657-
}))
658-
.to_predicate(self.tcx);
659-
let obligation = traits::Obligation::new(self.misc(sp), self.param_env, predicate);
660-
let impls_deref = self.infcx.predicate_may_hold(&obligation);
661-
662-
// For a suggestion to make sense, the type would need to be `Copy`.
663-
let is_copy = self.infcx.type_is_copy_modulo_regions(self.param_env, expected, sp);
664-
665-
if is_copy && impls_deref {
666-
if let Ok(code) = sm.span_to_snippet(sp) {
667-
let message = if checked_ty.is_region_ptr() {
668-
"consider dereferencing the borrow"
669-
} else {
670-
"consider dereferencing the type"
671-
};
672-
let suggestion = if is_struct_pat_shorthand_field {
673-
format!("{}: *{}", code, code)
674-
} else {
675-
format!("*{}", code)
676-
};
677-
return Some((sp, message, suggestion, Applicability::MachineApplicable));
635+
if let Some(steps) = self.deref_steps(checked_ty, expected) {
636+
if steps == 1 {
637+
// For a suggestion to make sense, the type would need to be `Copy`.
638+
if self.infcx.type_is_copy_modulo_regions(self.param_env, expected, sp) {
639+
if let Ok(code) = sm.span_to_snippet(sp) {
640+
let message = if checked_ty.is_region_ptr() {
641+
"consider dereferencing the borrow"
642+
} else {
643+
"consider dereferencing the type"
644+
};
645+
let suggestion = if is_struct_pat_shorthand_field {
646+
format!("{}: *{}", code, code)
647+
} else {
648+
format!("*{}", code)
649+
};
650+
return Some((
651+
sp,
652+
message,
653+
suggestion,
654+
Applicability::MachineApplicable,
655+
));
656+
}
657+
}
678658
}
679659
}
680660
}

0 commit comments

Comments
 (0)