Skip to content

Commit 000dc07

Browse files
committed
Store a method-from-trait's impl in some cases when it is known.
This allows one to look at an `ExprMethodCall` `foo.bar()` where `bar` is a method in some trait and (sometimes) extract the `impl` that `bar` is defined in, e.g. trait Foo { fn bar(&self); } impl Foo for uint { // <A> fn bar(&self) {} } fn main() { 1u.bar(); // impl_def_id == Some(<A>) } This definitely doesn't handle all cases, but is correct when it is known, meaning it should only be used for certain linting/heuristic purposes; no safety analysis.
1 parent 4be79d6 commit 000dc07

File tree

6 files changed

+40
-7
lines changed

6 files changed

+40
-7
lines changed

src/librustc/middle/astencode.rs

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -627,6 +627,7 @@ impl<'tcx> tr for MethodOrigin<'tcx> {
627627
// def-id is already translated when we read it out
628628
trait_ref: mp.trait_ref.clone(),
629629
method_num: mp.method_num,
630+
impl_def_id: mp.impl_def_id.tr(dcx),
630631
}
631632
)
632633
}
@@ -879,6 +880,16 @@ impl<'a, 'tcx> rbml_writer_helpers<'tcx> for Encoder<'a> {
879880
try!(this.emit_struct_field("method_num", 0, |this| {
880881
this.emit_uint(p.method_num)
881882
}));
883+
try!(this.emit_struct_field("impl_def_id", 0, |this| {
884+
this.emit_option(|this| {
885+
match p.impl_def_id {
886+
None => this.emit_option_none(),
887+
Some(did) => this.emit_option_some(|this| {
888+
Ok(this.emit_def_id(did))
889+
})
890+
}
891+
})
892+
}));
882893
Ok(())
883894
})
884895
})
@@ -1452,6 +1463,17 @@ impl<'a, 'tcx> rbml_decoder_decoder_helpers<'tcx> for reader::Decoder<'a> {
14521463
this.read_struct_field("method_num", 1, |this| {
14531464
this.read_uint()
14541465
}).unwrap()
1466+
},
1467+
impl_def_id: {
1468+
this.read_struct_field("impl_def_id", 2, |this| {
1469+
this.read_option(|this, b| {
1470+
if b {
1471+
Ok(Some(this.read_def_id(dcx)))
1472+
} else {
1473+
Ok(None)
1474+
}
1475+
})
1476+
}).unwrap()
14551477
}
14561478
}))
14571479
}).unwrap()

src/librustc/middle/ty.rs

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -453,9 +453,14 @@ pub struct MethodParam<'tcx> {
453453
// never contains bound regions; those regions should have been
454454
// instantiated with fresh variables at this point.
455455
pub trait_ref: Rc<ty::TraitRef<'tcx>>,
456-
457456
// index of uint in the list of methods for the trait
458457
pub method_num: uint,
458+
459+
/// The impl for the trait from which the method comes. This
460+
/// should only be used for certain linting/heuristic purposes
461+
/// since there is no guarantee that this is Some in every
462+
/// situation that it could/should be.
463+
pub impl_def_id: Option<ast::DefId>,
459464
}
460465

461466
// details for a method invoked with a receiver whose type is an object

src/librustc/middle/ty_fold.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -310,7 +310,8 @@ impl<'tcx> TypeFoldable<'tcx> for ty::MethodOrigin<'tcx> {
310310
ty::MethodTypeParam(ref param) => {
311311
ty::MethodTypeParam(ty::MethodParam {
312312
trait_ref: param.trait_ref.fold_with(folder),
313-
method_num: param.method_num
313+
method_num: param.method_num,
314+
impl_def_id: param.impl_def_id,
314315
})
315316
}
316317
ty::MethodTraitObject(ref object) => {

src/librustc_trans/trans/meth.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -132,7 +132,8 @@ pub fn trans_method_callee<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
132132

133133
ty::MethodTypeParam(ty::MethodParam {
134134
ref trait_ref,
135-
method_num
135+
method_num,
136+
impl_def_id: _
136137
}) => {
137138
let trait_ref = ty::Binder(bcx.monomorphize(trait_ref));
138139
let span = bcx.tcx().map.span(method_call.expr_id);

src/librustc_typeck/check/method/confirm.rs

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -256,7 +256,8 @@ impl<'a,'tcx> ConfirmContext<'a,'tcx> {
256256
&impl_polytype.substs,
257257
&ty::impl_trait_ref(self.tcx(), impl_def_id).unwrap());
258258
let origin = MethodTypeParam(MethodParam { trait_ref: impl_trait_ref.clone(),
259-
method_num: method_num });
259+
method_num: method_num,
260+
impl_def_id: Some(impl_def_id) });
260261
(impl_trait_ref.substs.clone(), origin)
261262
}
262263

@@ -275,7 +276,8 @@ impl<'a,'tcx> ConfirmContext<'a,'tcx> {
275276
let trait_ref =
276277
Rc::new(ty::TraitRef::new(trait_def_id, self.tcx().mk_substs(substs.clone())));
277278
let origin = MethodTypeParam(MethodParam { trait_ref: trait_ref,
278-
method_num: method_num });
279+
method_num: method_num,
280+
impl_def_id: None });
279281
(substs, origin)
280282
}
281283

@@ -285,7 +287,8 @@ impl<'a,'tcx> ConfirmContext<'a,'tcx> {
285287
let trait_ref = self.replace_late_bound_regions_with_fresh_var(&*poly_trait_ref);
286288
let substs = trait_ref.substs.clone();
287289
let origin = MethodTypeParam(MethodParam { trait_ref: trait_ref,
288-
method_num: method_num });
290+
method_num: method_num,
291+
impl_def_id: None });
289292
(substs, origin)
290293
}
291294
}

src/librustc_typeck/check/method/mod.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -287,7 +287,8 @@ pub fn lookup_in_trait_adjusted<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
287287

288288
let callee = MethodCallee {
289289
origin: MethodTypeParam(MethodParam{trait_ref: trait_ref.clone(),
290-
method_num: method_num}),
290+
method_num: method_num,
291+
impl_def_id: None}),
291292
ty: fty,
292293
substs: trait_ref.substs.clone()
293294
};

0 commit comments

Comments
 (0)