Skip to content

Commit 4a754f2

Browse files
committed
rustc: replace autoderefs' use of MethodCallee with OverloadedDeref.
1 parent c0e8fff commit 4a754f2

File tree

15 files changed

+261
-164
lines changed

15 files changed

+261
-164
lines changed

src/librustc/ich/impls_ty.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -110,7 +110,7 @@ impl<'a, 'tcx> HashStable<StableHashingContext<'a, 'tcx>> for ty::adjustment::Ad
110110
}
111111

112112
impl_stable_hash_for!(struct ty::adjustment::Adjustment<'tcx> { kind, target });
113-
impl_stable_hash_for!(struct ty::MethodCallee<'tcx> { def_id, substs, sig });
113+
impl_stable_hash_for!(struct ty::adjustment::OverloadedDeref<'tcx> { region, mutbl, target });
114114
impl_stable_hash_for!(struct ty::UpvarId { var_id, closure_expr_id });
115115
impl_stable_hash_for!(struct ty::UpvarBorrow<'tcx> { kind, region });
116116

src/librustc/middle/expr_use_visitor.rs

Lines changed: 5 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -745,23 +745,16 @@ impl<'a, 'gcx, 'tcx> ExprUseVisitor<'a, 'gcx, 'tcx> {
745745
fn walk_autoderefs(&mut self,
746746
expr: &hir::Expr,
747747
mut cmt: mc::cmt<'tcx>,
748-
autoderefs: &[Option<ty::MethodCallee<'tcx>>])
748+
autoderefs: &[Option<adjustment::OverloadedDeref<'tcx>>])
749749
-> mc::McResult<mc::cmt<'tcx>> {
750750
debug!("walk_autoderefs expr={:?} autoderefs={:?}", expr, autoderefs);
751751

752752
for &overloaded in autoderefs {
753-
if let Some(method) = overloaded {
754-
let self_ty = method.sig.inputs()[0];
755-
let self_ty = self.mc.infcx.resolve_type_vars_if_possible(&self_ty);
756-
757-
let (m, r) = match self_ty.sty {
758-
ty::TyRef(r, ref m) => (m.mutbl, r),
759-
_ => span_bug!(expr.span, "bad overloaded deref type {:?}", self_ty)
760-
};
761-
let bk = ty::BorrowKind::from_mutbl(m);
753+
if let Some(deref) = overloaded {
754+
let bk = ty::BorrowKind::from_mutbl(deref.mutbl);
762755
self.delegate.borrow(expr.id, expr.span, cmt.clone(),
763-
r, bk, AutoRef);
764-
cmt = self.mc.cat_overloaded_autoderef(expr, method)?;
756+
deref.region, bk, AutoRef);
757+
cmt = self.mc.cat_overloaded_autoderef(expr, deref)?;
765758
} else {
766759
cmt = self.mc.cat_deref(expr, cmt, false)?;
767760
}

src/librustc/middle/mem_categorization.rs

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -485,8 +485,8 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> {
485485
debug!("cat_expr: autoderefs={:?}, cmt={:?}",
486486
autoderefs, cmt);
487487
for &overloaded in autoderefs {
488-
if let Some(method) = overloaded {
489-
cmt = self.cat_overloaded_autoderef(expr, method)?;
488+
if let Some(deref) = overloaded {
489+
cmt = self.cat_overloaded_autoderef(expr, deref)?;
490490
} else {
491491
cmt = self.cat_deref(expr, cmt, false)?;
492492
}
@@ -936,12 +936,15 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> {
936936

937937
pub fn cat_overloaded_autoderef(&self,
938938
expr: &hir::Expr,
939-
method: ty::MethodCallee<'tcx>)
939+
deref: adjustment::OverloadedDeref<'tcx>)
940940
-> McResult<cmt<'tcx>> {
941-
debug!("cat_overloaded_autoderef: method={:?}", method);
941+
debug!("cat_overloaded_autoderef: deref={:?}", deref);
942942

943-
let ref_ty = method.sig.output();
944-
let ref_ty = self.infcx.resolve_type_vars_if_possible(&ref_ty);
943+
let target = self.infcx.resolve_type_vars_if_possible(&deref.target);
944+
let ref_ty = self.tcx().mk_ref(deref.region, ty::TypeAndMut {
945+
ty: target,
946+
mutbl: deref.mutbl,
947+
});
945948
let base_cmt = self.cat_rvalue_node(expr.id, expr.span, ref_ty);
946949
self.cat_deref(expr, base_cmt, false)
947950
}

src/librustc/ty/adjustment.rs

Lines changed: 28 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,10 @@
88
// option. This file may not be copied, modified, or distributed
99
// except according to those terms.
1010

11-
use ty::{self, Ty, TyCtxt, TypeAndMut};
12-
1311
use hir;
12+
use hir::def_id::DefId;
13+
use ty::{self, Ty, TyCtxt, TypeAndMut};
14+
use ty::subst::Substs;
1415

1516
#[derive(Clone, RustcEncodable, RustcDecodable)]
1617
pub struct Adjustment<'tcx> {
@@ -105,7 +106,7 @@ pub enum Adjust<'tcx> {
105106
/// ```
106107
DerefRef {
107108
/// Step 1. Apply a number of dereferences, producing an lvalue.
108-
autoderefs: Vec<Option<ty::MethodCallee<'tcx>>>,
109+
autoderefs: Vec<Option<OverloadedDeref<'tcx>>>,
109110

110111
/// Step 2. Optionally produce a pointer/reference from the value.
111112
autoref: Option<AutoBorrow<'tcx>>,
@@ -136,6 +137,30 @@ impl<'tcx> Adjustment<'tcx> {
136137
}
137138
}
138139

140+
/// An overloaded autoderef step, representing a `Deref(Mut)::deref(_mut)`
141+
/// call, with the signature `&'a T -> &'a U` or `&'a mut T -> &'a mut U`.
142+
/// The target type is `U` in both cases, with the region and mutability
143+
/// being those shared by both the receiver and the returned reference.
144+
#[derive(Copy, Clone, PartialEq, Debug, RustcEncodable, RustcDecodable)]
145+
pub struct OverloadedDeref<'tcx> {
146+
pub region: ty::Region<'tcx>,
147+
pub mutbl: hir::Mutability,
148+
pub target: Ty<'tcx>,
149+
}
150+
151+
impl<'a, 'gcx, 'tcx> OverloadedDeref<'tcx> {
152+
pub fn method_call(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>, source: Ty<'tcx>)
153+
-> (DefId, &'tcx Substs<'tcx>) {
154+
let trait_def_id = match self.mutbl {
155+
hir::MutImmutable => tcx.lang_items.deref_trait(),
156+
hir::MutMutable => tcx.lang_items.deref_mut_trait()
157+
};
158+
let method_def_id = tcx.associated_items(trait_def_id.unwrap())
159+
.find(|m| m.kind == ty::AssociatedKind::Method).unwrap().def_id;
160+
(method_def_id, tcx.mk_substs_trait(source, &[]))
161+
}
162+
}
163+
139164
#[derive(Copy, Clone, PartialEq, Debug, RustcEncodable, RustcDecodable)]
140165
pub enum AutoBorrow<'tcx> {
141166
/// Convert from T to &T.

src/librustc/ty/mod.rs

Lines changed: 0 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -390,18 +390,6 @@ impl Variance {
390390
}
391391
}
392392

393-
#[derive(Clone, Copy, Debug, RustcDecodable, RustcEncodable)]
394-
pub struct MethodCallee<'tcx> {
395-
/// Impl method ID, for inherent methods, or trait method ID, otherwise.
396-
pub def_id: DefId,
397-
pub substs: &'tcx Substs<'tcx>,
398-
399-
/// Instantiated method signature, i.e. it has been substituted,
400-
/// normalized, and has had late-bound lifetimes replaced
401-
/// (with inference variables, during type-checking).
402-
pub sig: FnSig<'tcx>,
403-
}
404-
405393
// Contains information needed to resolve types and (in the future) look up
406394
// the types of AST nodes.
407395
#[derive(Copy, Clone, PartialEq, Eq, Hash)]

src/librustc/ty/structural_impls.rs

Lines changed: 108 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -220,6 +220,55 @@ impl<'a, 'tcx> Lift<'tcx> for ty::ClosureSubsts<'a> {
220220
}
221221
}
222222

223+
impl<'a, 'tcx> Lift<'tcx> for ty::adjustment::Adjustment<'a> {
224+
type Lifted = ty::adjustment::Adjustment<'tcx>;
225+
fn lift_to_tcx<'b, 'gcx>(&self, tcx: TyCtxt<'b, 'gcx, 'tcx>) -> Option<Self::Lifted> {
226+
tcx.lift(&self.kind).and_then(|kind| {
227+
tcx.lift(&self.target).map(|target| {
228+
ty::adjustment::Adjustment { kind, target }
229+
})
230+
})
231+
}
232+
}
233+
234+
impl<'a, 'tcx> Lift<'tcx> for ty::adjustment::Adjust<'a> {
235+
type Lifted = ty::adjustment::Adjust<'tcx>;
236+
fn lift_to_tcx<'b, 'gcx>(&self, tcx: TyCtxt<'b, 'gcx, 'tcx>) -> Option<Self::Lifted> {
237+
match *self {
238+
ty::adjustment::Adjust::NeverToAny =>
239+
Some(ty::adjustment::Adjust::NeverToAny),
240+
ty::adjustment::Adjust::ReifyFnPointer =>
241+
Some(ty::adjustment::Adjust::ReifyFnPointer),
242+
ty::adjustment::Adjust::UnsafeFnPointer =>
243+
Some(ty::adjustment::Adjust::UnsafeFnPointer),
244+
ty::adjustment::Adjust::ClosureFnPointer =>
245+
Some(ty::adjustment::Adjust::ClosureFnPointer),
246+
ty::adjustment::Adjust::MutToConstPointer =>
247+
Some(ty::adjustment::Adjust::MutToConstPointer),
248+
ty::adjustment::Adjust::DerefRef { ref autoderefs, ref autoref, unsize } => {
249+
tcx.lift(autoderefs).and_then(|autoderefs| {
250+
tcx.lift(autoref).map(|autoref| {
251+
ty::adjustment::Adjust::DerefRef { autoderefs, autoref, unsize }
252+
})
253+
})
254+
}
255+
}
256+
}
257+
}
258+
259+
impl<'a, 'tcx> Lift<'tcx> for ty::adjustment::OverloadedDeref<'a> {
260+
type Lifted = ty::adjustment::OverloadedDeref<'tcx>;
261+
fn lift_to_tcx<'b, 'gcx>(&self, tcx: TyCtxt<'b, 'gcx, 'tcx>) -> Option<Self::Lifted> {
262+
tcx.lift(&(self.region, self.target)).map(|(region, target)| {
263+
ty::adjustment::OverloadedDeref {
264+
region,
265+
mutbl: self.mutbl,
266+
target,
267+
}
268+
})
269+
}
270+
}
271+
223272
impl<'a, 'tcx> Lift<'tcx> for ty::adjustment::AutoBorrow<'a> {
224273
type Lifted = ty::adjustment::AutoBorrow<'tcx>;
225274
fn lift_to_tcx<'b, 'gcx>(&self, tcx: TyCtxt<'b, 'gcx, 'tcx>) -> Option<Self::Lifted> {
@@ -631,6 +680,65 @@ impl<'tcx> TypeFoldable<'tcx> for ty::ClosureSubsts<'tcx> {
631680
}
632681
}
633682

683+
impl<'tcx> TypeFoldable<'tcx> for ty::adjustment::Adjustment<'tcx> {
684+
fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) -> Self {
685+
ty::adjustment::Adjustment {
686+
kind: self.kind.fold_with(folder),
687+
target: self.target.fold_with(folder),
688+
}
689+
}
690+
691+
fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> bool {
692+
self.kind.visit_with(visitor) || self.target.visit_with(visitor)
693+
}
694+
}
695+
696+
impl<'tcx> TypeFoldable<'tcx> for ty::adjustment::Adjust<'tcx> {
697+
fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) -> Self {
698+
match *self {
699+
ty::adjustment::Adjust::NeverToAny |
700+
ty::adjustment::Adjust::ReifyFnPointer |
701+
ty::adjustment::Adjust::UnsafeFnPointer |
702+
ty::adjustment::Adjust::ClosureFnPointer |
703+
ty::adjustment::Adjust::MutToConstPointer => self.clone(),
704+
ty::adjustment::Adjust::DerefRef { ref autoderefs, ref autoref, unsize } => {
705+
ty::adjustment::Adjust::DerefRef {
706+
autoderefs: autoderefs.fold_with(folder),
707+
autoref: autoref.fold_with(folder),
708+
unsize,
709+
}
710+
}
711+
}
712+
}
713+
714+
fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> bool {
715+
match *self {
716+
ty::adjustment::Adjust::NeverToAny |
717+
ty::adjustment::Adjust::ReifyFnPointer |
718+
ty::adjustment::Adjust::UnsafeFnPointer |
719+
ty::adjustment::Adjust::ClosureFnPointer |
720+
ty::adjustment::Adjust::MutToConstPointer => false,
721+
ty::adjustment::Adjust::DerefRef { ref autoderefs, ref autoref, unsize: _ } => {
722+
autoderefs.visit_with(visitor) || autoref.visit_with(visitor)
723+
}
724+
}
725+
}
726+
}
727+
728+
impl<'tcx> TypeFoldable<'tcx> for ty::adjustment::OverloadedDeref<'tcx> {
729+
fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) -> Self {
730+
ty::adjustment::OverloadedDeref {
731+
region: self.region.fold_with(folder),
732+
mutbl: self.mutbl,
733+
target: self.target.fold_with(folder),
734+
}
735+
}
736+
737+
fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> bool {
738+
self.region.visit_with(visitor) || self.target.visit_with(visitor)
739+
}
740+
}
741+
634742
impl<'tcx> TypeFoldable<'tcx> for ty::adjustment::AutoBorrow<'tcx> {
635743
fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) -> Self {
636744
match *self {

src/librustc_lint/builtin.rs

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -892,11 +892,17 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnconditionalRecursion {
892892
if let Some(&Adjustment {
893893
kind: Adjust::DerefRef { ref autoderefs, .. }, ..
894894
}) = cx.tables.adjustments.get(&id) {
895+
let mut source = cx.tables.expr_ty(expr);
895896
for &overloaded in autoderefs {
896-
if let Some(m) = overloaded {
897-
if method_call_refers_to_method(cx.tcx, method, m.def_id, m.substs, id) {
897+
if let Some(deref) = overloaded {
898+
let (def_id, substs) = deref.method_call(cx.tcx, source);
899+
if method_call_refers_to_method(cx.tcx, method, def_id, substs, id) {
898900
return true;
899901
}
902+
source = deref.target;
903+
} else {
904+
source = source.builtin_deref(true,
905+
ty::LvaluePreference::NoPreference).unwrap().ty;
900906
}
901907
}
902908
}

0 commit comments

Comments
 (0)