Skip to content

Commit

Permalink
Store a method-from-trait's impl in some cases when it is known.
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
huonw committed Jan 24, 2015
1 parent 4be79d6 commit 000dc07
Show file tree
Hide file tree
Showing 6 changed files with 40 additions and 7 deletions.
22 changes: 22 additions & 0 deletions src/librustc/middle/astencode.rs
Expand Up @@ -627,6 +627,7 @@ impl<'tcx> tr for MethodOrigin<'tcx> {
// def-id is already translated when we read it out
trait_ref: mp.trait_ref.clone(),
method_num: mp.method_num,
impl_def_id: mp.impl_def_id.tr(dcx),
}
)
}
Expand Down Expand Up @@ -879,6 +880,16 @@ impl<'a, 'tcx> rbml_writer_helpers<'tcx> for Encoder<'a> {
try!(this.emit_struct_field("method_num", 0, |this| {
this.emit_uint(p.method_num)
}));
try!(this.emit_struct_field("impl_def_id", 0, |this| {
this.emit_option(|this| {
match p.impl_def_id {
None => this.emit_option_none(),
Some(did) => this.emit_option_some(|this| {
Ok(this.emit_def_id(did))
})
}
})
}));
Ok(())
})
})
Expand Down Expand Up @@ -1452,6 +1463,17 @@ impl<'a, 'tcx> rbml_decoder_decoder_helpers<'tcx> for reader::Decoder<'a> {
this.read_struct_field("method_num", 1, |this| {
this.read_uint()
}).unwrap()
},
impl_def_id: {
this.read_struct_field("impl_def_id", 2, |this| {
this.read_option(|this, b| {
if b {
Ok(Some(this.read_def_id(dcx)))
} else {
Ok(None)
}
})
}).unwrap()
}
}))
}).unwrap()
Expand Down
7 changes: 6 additions & 1 deletion src/librustc/middle/ty.rs
Expand Up @@ -453,9 +453,14 @@ pub struct MethodParam<'tcx> {
// never contains bound regions; those regions should have been
// instantiated with fresh variables at this point.
pub trait_ref: Rc<ty::TraitRef<'tcx>>,

// index of uint in the list of methods for the trait
pub method_num: uint,

/// The impl for the trait from which the method comes. This
/// should only be used for certain linting/heuristic purposes
/// since there is no guarantee that this is Some in every
/// situation that it could/should be.
pub impl_def_id: Option<ast::DefId>,
}

// details for a method invoked with a receiver whose type is an object
Expand Down
3 changes: 2 additions & 1 deletion src/librustc/middle/ty_fold.rs
Expand Up @@ -310,7 +310,8 @@ impl<'tcx> TypeFoldable<'tcx> for ty::MethodOrigin<'tcx> {
ty::MethodTypeParam(ref param) => {
ty::MethodTypeParam(ty::MethodParam {
trait_ref: param.trait_ref.fold_with(folder),
method_num: param.method_num
method_num: param.method_num,
impl_def_id: param.impl_def_id,
})
}
ty::MethodTraitObject(ref object) => {
Expand Down
3 changes: 2 additions & 1 deletion src/librustc_trans/trans/meth.rs
Expand Up @@ -132,7 +132,8 @@ pub fn trans_method_callee<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,

ty::MethodTypeParam(ty::MethodParam {
ref trait_ref,
method_num
method_num,
impl_def_id: _
}) => {
let trait_ref = ty::Binder(bcx.monomorphize(trait_ref));
let span = bcx.tcx().map.span(method_call.expr_id);
Expand Down
9 changes: 6 additions & 3 deletions src/librustc_typeck/check/method/confirm.rs
Expand Up @@ -256,7 +256,8 @@ impl<'a,'tcx> ConfirmContext<'a,'tcx> {
&impl_polytype.substs,
&ty::impl_trait_ref(self.tcx(), impl_def_id).unwrap());
let origin = MethodTypeParam(MethodParam { trait_ref: impl_trait_ref.clone(),
method_num: method_num });
method_num: method_num,
impl_def_id: Some(impl_def_id) });
(impl_trait_ref.substs.clone(), origin)
}

Expand All @@ -275,7 +276,8 @@ impl<'a,'tcx> ConfirmContext<'a,'tcx> {
let trait_ref =
Rc::new(ty::TraitRef::new(trait_def_id, self.tcx().mk_substs(substs.clone())));
let origin = MethodTypeParam(MethodParam { trait_ref: trait_ref,
method_num: method_num });
method_num: method_num,
impl_def_id: None });
(substs, origin)
}

Expand All @@ -285,7 +287,8 @@ impl<'a,'tcx> ConfirmContext<'a,'tcx> {
let trait_ref = self.replace_late_bound_regions_with_fresh_var(&*poly_trait_ref);
let substs = trait_ref.substs.clone();
let origin = MethodTypeParam(MethodParam { trait_ref: trait_ref,
method_num: method_num });
method_num: method_num,
impl_def_id: None });
(substs, origin)
}
}
Expand Down
3 changes: 2 additions & 1 deletion src/librustc_typeck/check/method/mod.rs
Expand Up @@ -287,7 +287,8 @@ pub fn lookup_in_trait_adjusted<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,

let callee = MethodCallee {
origin: MethodTypeParam(MethodParam{trait_ref: trait_ref.clone(),
method_num: method_num}),
method_num: method_num,
impl_def_id: None}),
ty: fty,
substs: trait_ref.substs.clone()
};
Expand Down

0 comments on commit 000dc07

Please sign in to comment.