Skip to content

Commit

Permalink
Rollup merge of rust-lang#72292 - ldm0:derefsteps, r=estebank
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
Dylan-DPC authored May 23, 2020
2 parents 75b0a68 + 407958a commit bd8f68d
Show file tree
Hide file tree
Showing 2 changed files with 27 additions and 47 deletions.
2 changes: 1 addition & 1 deletion src/librustc_typeck/check/coercion.rs
Original file line number Diff line number Diff line change
Expand Up @@ -887,7 +887,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
let coerce = Coerce::new(self, cause, AllowTwoPhase::No);
coerce
.autoderef(rustc_span::DUMMY_SP, expr_ty)
.find_map(|(ty, steps)| coerce.unify(ty, target).ok().map(|_| steps))
.find_map(|(ty, steps)| self.probe(|_| coerce.unify(ty, target)).ok().map(|_| steps))
}

/// Given some expressions, their known unified type and another expression,
Expand Down
72 changes: 26 additions & 46 deletions src/librustc_typeck/check/demand.rs
Original file line number Diff line number Diff line change
@@ -1,16 +1,15 @@
use crate::check::FnCtxt;
use rustc_infer::infer::InferOk;
use rustc_trait_selection::infer::InferCtxtExt as _;
use rustc_trait_selection::traits::query::evaluate_obligation::InferCtxtExt as _;
use rustc_trait_selection::traits::{self, ObligationCause};
use rustc_trait_selection::traits::ObligationCause;

use rustc_ast::util::parser::PREC_POSTFIX;
use rustc_errors::{Applicability, DiagnosticBuilder};
use rustc_hir as hir;
use rustc_hir::lang_items::{CloneTraitLangItem, DerefTraitLangItem};
use rustc_hir::lang_items::CloneTraitLangItem;
use rustc_hir::{is_range_literal, Node};
use rustc_middle::ty::adjustment::AllowTwoPhase;
use rustc_middle::ty::{self, AssocItem, ToPredicate, Ty, TypeAndMut};
use rustc_middle::ty::{self, AssocItem, Ty, TypeAndMut};
use rustc_span::symbol::sym;
use rustc_span::Span;

Expand Down Expand Up @@ -633,48 +632,29 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
}
}
_ if sp == expr.span && !is_macro => {
// Check for `Deref` implementations by constructing a predicate to
// prove: `<T as Deref>::Output == U`
let deref_trait = self.tcx.require_lang_item(DerefTraitLangItem, Some(sp));
let item_def_id = self
.tcx
.associated_items(deref_trait)
.in_definition_order()
.find(|item| item.kind == ty::AssocKind::Type)
.unwrap()
.def_id;
let predicate =
ty::PredicateKind::Projection(ty::Binder::bind(ty::ProjectionPredicate {
// `<T as Deref>::Output`
projection_ty: ty::ProjectionTy {
// `T`
substs: self.tcx.intern_substs(&[checked_ty.into()]),
// `Deref::Output`
item_def_id,
},
// `U`
ty: expected,
}))
.to_predicate(self.tcx);
let obligation = traits::Obligation::new(self.misc(sp), self.param_env, predicate);
let impls_deref = self.infcx.predicate_may_hold(&obligation);

// For a suggestion to make sense, the type would need to be `Copy`.
let is_copy = self.infcx.type_is_copy_modulo_regions(self.param_env, expected, sp);

if is_copy && impls_deref {
if let Ok(code) = sm.span_to_snippet(sp) {
let message = if checked_ty.is_region_ptr() {
"consider dereferencing the borrow"
} else {
"consider dereferencing the type"
};
let suggestion = if is_struct_pat_shorthand_field {
format!("{}: *{}", code, code)
} else {
format!("*{}", code)
};
return Some((sp, message, suggestion, Applicability::MachineApplicable));
if let Some(steps) = self.deref_steps(checked_ty, expected) {
if steps == 1 {
// For a suggestion to make sense, the type would need to be `Copy`.
if self.infcx.type_is_copy_modulo_regions(self.param_env, expected, sp) {
if let Ok(code) = sm.span_to_snippet(sp) {
let message = if checked_ty.is_region_ptr() {
"consider dereferencing the borrow"
} else {
"consider dereferencing the type"
};
let suggestion = if is_struct_pat_shorthand_field {
format!("{}: *{}", code, code)
} else {
format!("*{}", code)
};
return Some((
sp,
message,
suggestion,
Applicability::MachineApplicable,
));
}
}
}
}
}
Expand Down

0 comments on commit bd8f68d

Please sign in to comment.