Skip to content

Commit 7deb57c

Browse files
committed
---
yaml --- r: 217850 b: refs/heads/master c: 5620a58 h: refs/heads/master v: v3
1 parent 8539790 commit 7deb57c

File tree

9 files changed

+93
-145
lines changed

9 files changed

+93
-145
lines changed

[refs]

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
---
2-
refs/heads/master: a2fe59afd66f032bea04f55fdb8beb00b53b65d7
2+
refs/heads/master: 5620a5879178dab2b929557208e19827eab9bda0
33
refs/heads/snap-stage3: ba0e1cd8147d452c356aacb29fb87568ca26f111
44
refs/heads/try: b53c0f93eedcdedd4fd89bccc5a3a09d1c5cd23e
55
refs/tags/release-0.1: 1f5c5126e96c79d22cb7862f75304136e204f105

trunk/src/librustc/middle/astencode.rs

Lines changed: 5 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -617,7 +617,7 @@ fn encode_method_callee<'a, 'tcx>(ecx: &e::EncodeContext<'a, 'tcx>,
617617
Ok(rbml_w.emit_def_id(method.def_id))
618618
});
619619
rbml_w.emit_struct_field("origin", 2, |rbml_w| {
620-
Ok(rbml_w.emit_method_origin(method.origin))
620+
method.origin.encode(rbml_w)
621621
});
622622
rbml_w.emit_struct_field("ty", 3, |rbml_w| {
623623
Ok(rbml_w.emit_ty(ecx, method.ty))
@@ -633,16 +633,14 @@ impl<'a, 'tcx> read_method_callee_helper<'tcx> for reader::Decoder<'a> {
633633
-> (u32, ty::MethodCallee<'tcx>) {
634634

635635
self.read_struct("MethodCallee", 5, |this| {
636-
let autoderef = this.read_struct_field("autoderef", 0, |this| {
637-
Decodable::decode(this)
638-
}).unwrap();
636+
let autoderef = this.read_struct_field("autoderef", 0,
637+
Decodable::decode).unwrap();
639638
Ok((autoderef, ty::MethodCallee {
640639
def_id: this.read_struct_field("def_id", 1, |this| {
641640
Ok(this.read_def_id(dcx))
642641
}).unwrap(),
643-
origin: this.read_struct_field("origin", 2, |this| {
644-
Ok(this.read_method_origin(dcx))
645-
}).unwrap(),
642+
origin: this.read_struct_field("origin", 2,
643+
Decodable::decode).unwrap(),
646644
ty: this.read_struct_field("ty", 3, |this| {
647645
Ok(this.read_ty(dcx))
648646
}).unwrap(),
@@ -713,7 +711,6 @@ impl<'a, 'tcx> get_ty_str_ctxt<'tcx> for e::EncodeContext<'a, 'tcx> {
713711
trait rbml_writer_helpers<'tcx> {
714712
fn emit_closure_type<'a>(&mut self, ecx: &e::EncodeContext<'a, 'tcx>,
715713
closure_type: &ty::ClosureTy<'tcx>);
716-
fn emit_method_origin(&mut self, method_origin: ty::MethodOrigin);
717714
fn emit_ty<'a>(&mut self, ecx: &e::EncodeContext<'a, 'tcx>, ty: Ty<'tcx>);
718715
fn emit_tys<'a>(&mut self, ecx: &e::EncodeContext<'a, 'tcx>, tys: &[Ty<'tcx>]);
719716
fn emit_type_param_def<'a>(&mut self, ecx: &e::EncodeContext<'a, 'tcx>,
@@ -745,37 +742,6 @@ impl<'a, 'tcx> rbml_writer_helpers<'tcx> for Encoder<'a> {
745742
});
746743
}
747744

748-
fn emit_method_origin(&mut self, method_origin: ty::MethodOrigin) {
749-
use serialize::Encoder;
750-
751-
self.emit_enum("MethodOrigin", |this| {
752-
match method_origin {
753-
ty::MethodOrigin::Inherent => {
754-
this.emit_enum_variant("Inherent", 0, 0, |_| Ok(()))
755-
}
756-
757-
ty::MethodOrigin::Trait(impl_def_id) => {
758-
this.emit_enum_variant("Trait", 1, 1, |this| {
759-
this.emit_option(|this| {
760-
match impl_def_id {
761-
None => this.emit_option_none(),
762-
Some(did) => this.emit_option_some(|this| {
763-
Ok(this.emit_def_id(did))
764-
})
765-
}
766-
})
767-
})
768-
}
769-
770-
ty::MethodOrigin::Object(vtable_index) => {
771-
this.emit_enum_variant("Object", 2, 1, |this| {
772-
this.emit_uint(vtable_index)
773-
})
774-
}
775-
}
776-
});
777-
}
778-
779745
fn emit_ty<'b>(&mut self, ecx: &e::EncodeContext<'b, 'tcx>, ty: Ty<'tcx>) {
780746
self.emit_opaque(|this| Ok(e::write_type(ecx, this, ty)));
781747
}
@@ -1118,7 +1084,6 @@ impl<'a> doc_decoder_helpers for rbml::Doc<'a> {
11181084
}
11191085

11201086
trait rbml_decoder_decoder_helpers<'tcx> {
1121-
fn read_method_origin(&mut self, dcx: &DecodeContext) -> ty::MethodOrigin;
11221087
fn read_ty<'a, 'b>(&mut self, dcx: &DecodeContext<'a, 'b, 'tcx>) -> Ty<'tcx>;
11231088
fn read_tys<'a, 'b>(&mut self, dcx: &DecodeContext<'a, 'b, 'tcx>) -> Vec<Ty<'tcx>>;
11241089
fn read_trait_ref<'a, 'b>(&mut self, dcx: &DecodeContext<'a, 'b, 'tcx>)
@@ -1202,30 +1167,6 @@ impl<'a, 'tcx> rbml_decoder_decoder_helpers<'tcx> for reader::Decoder<'a> {
12021167
}).unwrap()
12031168
}
12041169

1205-
fn read_method_origin(&mut self, dcx: &DecodeContext) -> ty::MethodOrigin {
1206-
self.read_enum("MethodOrigin", |this| {
1207-
let variants = &["Inherent", "Trait", "Object"];
1208-
this.read_enum_variant(variants, |this, i| {
1209-
match i {
1210-
0 => Ok(ty::MethodOrigin::Inherent),
1211-
1212-
1 => this.read_option(|this, b| {
1213-
Ok(ty::MethodOrigin::Trait(if b {
1214-
Some(this.read_def_id(dcx))
1215-
} else {
1216-
None
1217-
}))
1218-
}),
1219-
1220-
2 => this.read_uint().map(|idx| ty::MethodOrigin::Object(idx)),
1221-
1222-
_ => panic!("..")
1223-
}
1224-
})
1225-
}).unwrap()
1226-
}
1227-
1228-
12291170
fn read_ty<'b, 'c>(&mut self, dcx: &DecodeContext<'b, 'c, 'tcx>) -> Ty<'tcx> {
12301171
// Note: regions types embed local node ids. In principle, we
12311172
// should translate these node ids into the new decode

trunk/src/librustc/middle/ty.rs

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -625,17 +625,13 @@ pub enum CustomCoerceUnsized {
625625
Struct(usize)
626626
}
627627

628-
#[derive(Clone, Copy, Debug)]
628+
#[derive(Clone, Copy, RustcEncodable, RustcDecodable, Debug)]
629629
pub enum MethodOrigin {
630630
/// Inherent impl method call.
631631
Inherent,
632632

633633
/// Statically dispatched trait method call.
634-
/// The DefId is the impl for the trait from which the method comes.
635-
/// This should only be used for certain linting/heuristic purposes
636-
/// since there is no guarantee that this is Some in every situation
637-
/// that it could/should be.
638-
Trait(Option<ast::DefId>),
634+
Trait,
639635

640636
/// Dynamically dispatched trait method call.
641637
/// The usize is the index into the actual runtime vtable.

trunk/src/librustc_lint/builtin.rs

Lines changed: 78 additions & 66 deletions
Original file line numberDiff line numberDiff line change
@@ -33,8 +33,10 @@
3333

3434
use metadata::{csearch, decoder};
3535
use middle::def::*;
36+
use middle::infer;
3637
use middle::subst::Substs;
3738
use middle::ty::{self, Ty};
39+
use middle::traits;
3840
use middle::{def, pat_util, stability};
3941
use middle::const_eval::{eval_const_expr_partial, ConstVal};
4042
use middle::cfg;
@@ -1863,24 +1865,18 @@ impl LintPass for UnconditionalRecursion {
18631865

18641866
fn check_fn(&mut self, cx: &Context, fn_kind: visit::FnKind, _: &ast::FnDecl,
18651867
blk: &ast::Block, sp: Span, id: ast::NodeId) {
1866-
// FIXME(#23542) Replace with type ascription.
1867-
#![allow(trivial_casts)]
1868-
18691868
type F = for<'tcx> fn(&ty::ctxt<'tcx>,
18701869
ast::NodeId, ast::NodeId, ast::Ident, ast::NodeId) -> bool;
18711870

1872-
let (name, checker) = match fn_kind {
1873-
visit::FkItemFn(name, _, _, _, _, _) => (name, id_refers_to_this_fn as F),
1874-
visit::FkMethod(name, _, _) => (name, id_refers_to_this_method as F),
1871+
let method = match fn_kind {
1872+
visit::FkItemFn(..) => None,
1873+
visit::FkMethod(..) => {
1874+
cx.tcx.impl_or_trait_item(local_def(id)).as_opt_method()
1875+
}
18751876
// closures can't recur, so they don't matter.
18761877
visit::FkFnBlock => return
18771878
};
18781879

1879-
let impl_def_id = cx.tcx.impl_of_method(local_def(id))
1880-
.unwrap_or(local_def(ast::DUMMY_NODE_ID));
1881-
assert!(ast_util::is_local(impl_def_id));
1882-
let impl_node_id = impl_def_id.node;
1883-
18841880
// Walk through this function (say `f`) looking to see if
18851881
// every possible path references itself, i.e. the function is
18861882
// called recursively unconditionally. This is done by trying
@@ -1931,7 +1927,17 @@ impl LintPass for UnconditionalRecursion {
19311927
let node_id = cfg.graph.node_data(idx).id();
19321928

19331929
// is this a recursive call?
1934-
if node_id != ast::DUMMY_NODE_ID && checker(cx.tcx, impl_node_id, id, name, node_id) {
1930+
let self_recursive = if node_id != ast::DUMMY_NODE_ID {
1931+
match method {
1932+
Some(ref method) => {
1933+
expr_refers_to_this_method(cx.tcx, method, node_id)
1934+
}
1935+
None => expr_refers_to_this_fn(cx.tcx, id, node_id)
1936+
}
1937+
} else {
1938+
false
1939+
};
1940+
if self_recursive {
19351941
self_call_spans.push(cx.tcx.map.span(node_id));
19361942
// this is a self call, so we shouldn't explore past
19371943
// this node in the CFG.
@@ -1970,15 +1976,12 @@ impl LintPass for UnconditionalRecursion {
19701976
// all done
19711977
return;
19721978

1973-
// Functions for identifying if the given NodeId `id`
1974-
// represents a call to the function `fn_id`/method
1975-
// `method_id`.
1979+
// Functions for identifying if the given Expr NodeId `id`
1980+
// represents a call to the function `fn_id`/method `method`.
19761981

1977-
fn id_refers_to_this_fn<'tcx>(tcx: &ty::ctxt<'tcx>,
1978-
_: ast::NodeId,
1979-
fn_id: ast::NodeId,
1980-
_: ast::Ident,
1981-
id: ast::NodeId) -> bool {
1982+
fn expr_refers_to_this_fn(tcx: &ty::ctxt,
1983+
fn_id: ast::NodeId,
1984+
id: ast::NodeId) -> bool {
19821985
match tcx.map.get(id) {
19831986
ast_map::NodeExpr(&ast::Expr { node: ast::ExprCall(ref callee, _), .. }) => {
19841987
tcx.def_map.borrow().get(&callee.id)
@@ -1988,59 +1991,68 @@ impl LintPass for UnconditionalRecursion {
19881991
}
19891992
}
19901993

1991-
// check if the method call `id` refers to method `method_id`
1992-
// (with name `method_name` contained in impl `impl_id`).
1993-
fn id_refers_to_this_method<'tcx>(tcx: &ty::ctxt<'tcx>,
1994-
impl_id: ast::NodeId,
1995-
method_id: ast::NodeId,
1996-
method_name: ast::Ident,
1997-
id: ast::NodeId) -> bool {
1998-
let did = match tcx.tables.borrow().method_map.get(&ty::MethodCall::expr(id)) {
1999-
None => return false,
2000-
Some(m) => match m.origin {
2001-
// There's no way to know if a method call via a
2002-
// vtable is recursion, so we assume it's not.
2003-
ty::MethodOrigin::Object(_) => return false,
2004-
2005-
// This `did` refers directly to the method definition.
2006-
ty::MethodOrigin::Inherent => m.def_id,
2007-
2008-
// The `impl ... for ...` of this method call
2009-
// isn't known, e.g. it might be a default method
2010-
// in a trait, so we get the def-id of the trait
2011-
// method instead.
2012-
ty::MethodOrigin::Trait(None) => {
2013-
let on_self = m.substs.self_ty().map_or(false, |t| t.is_self());
2014-
if !on_self {
2015-
// we can only be recurring in a default
1994+
// Check if the method call `id` refers to method `method`.
1995+
fn expr_refers_to_this_method(tcx: &ty::ctxt,
1996+
method: &ty::Method,
1997+
id: ast::NodeId) -> bool {
1998+
let tables = tcx.tables.borrow();
1999+
let callee = match tables.method_map.get(&ty::MethodCall::expr(id)) {
2000+
Some(m) => m,
2001+
None => return false
2002+
};
2003+
let callee_item = tcx.impl_or_trait_item(callee.def_id);
2004+
2005+
match callee_item.container() {
2006+
// This is an inherent method, so the `def_id` refers
2007+
// directly to the method definition.
2008+
ty::ImplContainer(_) => {
2009+
callee.def_id == method.def_id
2010+
}
2011+
2012+
// A trait method, from any number of possible sources.
2013+
// Attempt to select a concrete impl before checking.
2014+
ty::TraitContainer(trait_def_id) => {
2015+
let trait_substs = callee.substs.clone().method_to_trait();
2016+
let trait_substs = tcx.mk_substs(trait_substs);
2017+
let trait_ref = ty::TraitRef::new(trait_def_id, trait_substs);
2018+
let trait_ref = ty::Binder(trait_ref);
2019+
let span = tcx.map.span(id);
2020+
let obligation =
2021+
traits::Obligation::new(traits::ObligationCause::misc(span, id),
2022+
trait_ref.to_poly_trait_predicate());
2023+
2024+
let param_env = ty::ParameterEnvironment::for_item(tcx, method.def_id.node);
2025+
let infcx = infer::new_infer_ctxt(tcx, &tcx.tables, Some(param_env), false);
2026+
let mut selcx = traits::SelectionContext::new(&infcx);
2027+
match selcx.select(&obligation) {
2028+
// The method comes from a `T: Trait` bound.
2029+
// If `T` is `Self`, then this call is inside
2030+
// a default method definition.
2031+
Ok(Some(traits::VtableParam(_))) => {
2032+
let self_ty = callee.substs.self_ty();
2033+
let on_self = self_ty.map_or(false, |t| t.is_self());
2034+
// We can only be recurring in a default
20162035
// method if we're being called literally
20172036
// on the `Self` type.
2018-
return false
2037+
on_self && callee.def_id == method.def_id
20192038
}
2020-
m.def_id
2021-
}
2022-
20232039

2024-
// The `impl` is known, so we check that with a
2025-
// special case:
2026-
ty::MethodOrigin::Trait(Some(impl_def_id)) => {
2040+
// The `impl` is known, so we check that with a
2041+
// special case:
2042+
Ok(Some(traits::VtableImpl(vtable_impl))) => {
2043+
let container = ty::ImplContainer(vtable_impl.impl_def_id);
2044+
// It matches if it comes from the same impl,
2045+
// and has the same method name.
2046+
container == method.container
2047+
&& callee_item.name() == method.name
2048+
}
20272049

2028-
let name = match tcx.map.expect_expr(id).node {
2029-
ast::ExprMethodCall(ref sp_ident, _, _) => sp_ident.node,
2030-
_ => tcx.sess.span_bug(
2031-
tcx.map.span(id),
2032-
"non-method call expr behaving like a method call?")
2033-
};
2034-
// It matches if it comes from the same impl,
2035-
// and has the same method name.
2036-
return ast_util::is_local(impl_def_id)
2037-
&& impl_def_id.node == impl_id
2038-
&& method_name.name == name.name
2050+
// There's no way to know if this call is
2051+
// recursive, so we assume it's not.
2052+
_ => return false
20392053
}
20402054
}
2041-
};
2042-
2043-
ast_util::is_local(did) && did.node == method_id
2055+
}
20442056
}
20452057
}
20462058
}

trunk/src/librustc_privacy/lib.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -852,7 +852,7 @@ impl<'a, 'tcx> PrivacyVisitor<'a, 'tcx> {
852852
}
853853
// Trait methods are always all public. The only controlling factor
854854
// is whether the trait itself is accessible or not.
855-
ty::MethodOrigin::Trait(_) | ty::MethodOrigin::Object(_) => {
855+
ty::MethodOrigin::Trait | ty::MethodOrigin::Object(_) => {
856856
let method = self.tcx.impl_or_trait_item(callee.def_id);
857857
self.report_error(self.ensure_public(span, method.container().id(),
858858
None, "source trait"));

trunk/src/librustc_trans/save/dump_csv.rs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -892,8 +892,7 @@ impl <'l, 'tcx> DumpCsvVisitor<'l, 'tcx> {
892892
ty::MethodOrigin::Inherent => {
893893
(Some(method_callee.def_id), None)
894894
}
895-
ty::MethodOrigin::Trait(_) |
896-
ty::MethodOrigin::Object(_) => {
895+
ty::MethodOrigin::Trait | ty::MethodOrigin::Object(_) => {
897896
(None, Some(method_callee.def_id))
898897
}
899898
};

trunk/src/librustc_trans/trans/meth.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -128,7 +128,7 @@ pub fn trans_method_callee<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
128128
}
129129
}
130130

131-
ty::MethodOrigin::Trait(_) => {
131+
ty::MethodOrigin::Trait => {
132132
let method_item = bcx.tcx().impl_or_trait_item(method_id);
133133
let trait_def_id = method_item.container().id();
134134

trunk/src/librustc_typeck/check/method/confirm.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -255,7 +255,7 @@ impl<'a,'tcx> ConfirmContext<'a,'tcx> {
255255
&impl_polytype.substs,
256256
&self.tcx().impl_trait_ref(impl_def_id).unwrap());
257257
let substs = impl_trait_ref.substs.clone();
258-
(substs, ty::MethodOrigin::Trait(Some(impl_def_id)))
258+
(substs, ty::MethodOrigin::Trait)
259259
}
260260

261261
probe::TraitPick => {
@@ -271,15 +271,15 @@ impl<'a,'tcx> ConfirmContext<'a,'tcx> {
271271
&trait_def.generics,
272272
self.infcx().next_ty_var());
273273

274-
(substs, ty::MethodOrigin::Trait(None))
274+
(substs, ty::MethodOrigin::Trait)
275275
}
276276

277277
probe::WhereClausePick(ref poly_trait_ref) => {
278278
// Where clauses can have bound regions in them. We need to instantiate
279279
// those to convert from a poly-trait-ref to a trait-ref.
280280
let trait_ref = self.replace_late_bound_regions_with_fresh_var(&*poly_trait_ref);
281281
let substs = trait_ref.substs.clone();
282-
(substs, ty::MethodOrigin::Trait(None))
282+
(substs, ty::MethodOrigin::Trait)
283283
}
284284
}
285285
}

0 commit comments

Comments
 (0)