rustc: replace method_map with Def::Method and node_substs entries.

This commit is contained in:
Eduard-Mihai Burtescu 2017-05-20 16:11:07 +03:00
parent 9eae6ba7fa
commit 552ab37a10
20 changed files with 120 additions and 119 deletions

View file

@ -355,11 +355,11 @@ impl<'a, 'tcx> CFGBuilder<'a, 'tcx> {
}
hir::ExprIndex(ref l, ref r) |
hir::ExprBinary(_, ref l, ref r) if self.tables.is_method_call(expr.id) => {
hir::ExprBinary(_, ref l, ref r) if self.tables.is_method_call(expr) => {
self.call(expr, pred, &l, Some(&**r).into_iter())
}
hir::ExprUnary(_, ref e) if self.tables.is_method_call(expr.id) => {
hir::ExprUnary(_, ref e) if self.tables.is_method_call(expr) => {
self.call(expr, pred, &e, None::<hir::Expr>.iter())
}

View file

@ -598,11 +598,10 @@ impl<'a, 'tcx> HashStable<StableHashingContext<'a, 'tcx>> for ty::TypeckTables<'
hcx: &mut StableHashingContext<'a, 'tcx>,
hasher: &mut StableHasher<W>) {
let ty::TypeckTables {
ref type_relative_path_defs,
ref type_dependent_defs,
ref node_types,
ref node_substs,
ref adjustments,
ref method_map,
ref upvar_capture_map,
ref closure_tys,
ref closure_kinds,
@ -619,11 +618,10 @@ impl<'a, 'tcx> HashStable<StableHashingContext<'a, 'tcx>> for ty::TypeckTables<'
} = *self;
hcx.with_node_id_hashing_mode(NodeIdHashingMode::HashDefPath, |hcx| {
ich::hash_stable_nodemap(hcx, hasher, type_relative_path_defs);
ich::hash_stable_nodemap(hcx, hasher, type_dependent_defs);
ich::hash_stable_nodemap(hcx, hasher, node_types);
ich::hash_stable_nodemap(hcx, hasher, node_substs);
ich::hash_stable_nodemap(hcx, hasher, adjustments);
ich::hash_stable_nodemap(hcx, hasher, method_map);
ich::hash_stable_hashmap(hcx, hasher, upvar_capture_map, |hcx, up_var_id| {
let ty::UpvarId {
var_id,

View file

@ -95,7 +95,7 @@ impl<'a, 'tcx> MarkSymbolVisitor<'a, 'tcx> {
}
fn lookup_and_handle_method(&mut self, id: ast::NodeId) {
self.check_def_id(self.tables.method_map[&id].def_id);
self.check_def_id(self.tables.type_dependent_defs[&id].def_id());
}
fn handle_field_access(&mut self, lhs: &hir::Expr, name: ast::Name) {

View file

@ -173,8 +173,8 @@ impl<'a, 'tcx> Visitor<'tcx> for EffectCheckVisitor<'a, 'tcx> {
fn visit_expr(&mut self, expr: &'tcx hir::Expr) {
match expr.node {
hir::ExprMethodCall(..) => {
let method = self.tables.method_map[&expr.id];
let base_type = self.tcx.type_of(method.def_id);
let def_id = self.tables.type_dependent_defs[&expr.id].def_id();
let base_type = self.tcx.type_of(def_id);
debug!("effect: method call case, base type is {:?}",
base_type);
if type_is_unsafe_function(base_type) {

View file

@ -563,8 +563,8 @@ impl<'a, 'gcx, 'tcx> ExprUseVisitor<'a, 'gcx, 'tcx> {
}
ty::TyError => { }
_ => {
let method = self.mc.infcx.tables.borrow().method_map[&call.id];
match OverloadedCallType::from_method_id(self.tcx(), method.def_id) {
let def_id = self.mc.infcx.tables.borrow().type_dependent_defs[&call.id].def_id();
match OverloadedCallType::from_method_id(self.tcx(), def_id) {
FnMutOverloadedCall => {
let call_scope_r = self.tcx().node_scope_region(call.id);
self.borrow_expr(callee,
@ -849,7 +849,7 @@ impl<'a, 'gcx, 'tcx> ExprUseVisitor<'a, 'gcx, 'tcx> {
pass_args: PassArgs)
-> bool
{
if !self.mc.infcx.tables.borrow().is_method_call(expr.id) {
if !self.mc.infcx.tables.borrow().is_method_call(expr) {
return false;
}

View file

@ -1045,7 +1045,7 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> {
hir::ExprAssignOp(_, ref l, ref r) => {
// an overloaded assign op is like a method call
if self.tables.is_method_call(expr.id) {
if self.tables.is_method_call(expr) {
let succ = self.propagate_through_expr(&l, succ);
self.propagate_through_expr(&r, succ)
} else {
@ -1366,7 +1366,7 @@ fn check_expr<'a, 'tcx>(this: &mut Liveness<'a, 'tcx>, expr: &'tcx Expr) {
}
hir::ExprAssignOp(_, ref l, _) => {
if !this.tables.is_method_call(expr.id) {
if !this.tables.is_method_call(expr) {
this.check_lvalue(&l);
}

View file

@ -515,7 +515,7 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> {
let expr_ty = self.expr_ty(expr)?;
match expr.node {
hir::ExprUnary(hir::UnDeref, ref e_base) => {
if self.infcx.tables.borrow().is_method_call(expr.id) {
if self.infcx.tables.borrow().is_method_call(expr) {
self.cat_overloaded_lvalue(expr, e_base, false)
} else {
let base_cmt = self.cat_expr(&e_base)?;
@ -538,7 +538,7 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> {
}
hir::ExprIndex(ref base, _) => {
if self.infcx.tables.borrow().is_method_call(expr.id()) {
if self.infcx.tables.borrow().is_method_call(expr) {
// If this is an index implemented by a method call, then it
// will include an implicit deref of the result.
// The call to index() returns a `&T` value, which

View file

@ -110,8 +110,7 @@ impl<'a, 'tcx> Visitor<'tcx> for ReachableContext<'a, 'tcx> {
Some(self.tables.qpath_def(qpath, expr.id))
}
hir::ExprMethodCall(..) => {
let def_id = self.tables.method_map[&expr.id].def_id;
Some(Def::Method(def_id))
Some(self.tables.type_dependent_defs[&expr.id])
}
_ => None
};

View file

@ -206,8 +206,9 @@ pub struct CommonTypes<'tcx> {
#[derive(RustcEncodable, RustcDecodable)]
pub struct TypeckTables<'tcx> {
/// Resolved definitions for `<T>::X` associated paths.
pub type_relative_path_defs: NodeMap<Def>,
/// Resolved definitions for `<T>::X` associated paths and
/// method calls, including those of overloaded operators.
pub type_dependent_defs: NodeMap<Def>,
/// Stores the types for various nodes in the AST. Note that this table
/// is not guaranteed to be populated until after typeck. See
@ -222,8 +223,6 @@ pub struct TypeckTables<'tcx> {
pub adjustments: NodeMap<ty::adjustment::Adjustment<'tcx>>,
pub method_map: NodeMap<ty::MethodCallee<'tcx>>,
/// Borrows
pub upvar_capture_map: ty::UpvarCaptureMap<'tcx>,
@ -271,11 +270,10 @@ pub struct TypeckTables<'tcx> {
impl<'tcx> TypeckTables<'tcx> {
pub fn empty() -> TypeckTables<'tcx> {
TypeckTables {
type_relative_path_defs: NodeMap(),
type_dependent_defs: NodeMap(),
node_types: FxHashMap(),
node_substs: NodeMap(),
adjustments: NodeMap(),
method_map: FxHashMap(),
upvar_capture_map: FxHashMap(),
closure_tys: NodeMap(),
closure_kinds: NodeMap(),
@ -294,7 +292,7 @@ impl<'tcx> TypeckTables<'tcx> {
match *qpath {
hir::QPath::Resolved(_, ref path) => path.def,
hir::QPath::TypeRelative(..) => {
self.type_relative_path_defs.get(&id).cloned().unwrap_or(Def::Err)
self.type_dependent_defs.get(&id).cloned().unwrap_or(Def::Err)
}
}
}
@ -357,8 +355,17 @@ impl<'tcx> TypeckTables<'tcx> {
.map(|adj| adj.target).or_else(|| self.expr_ty_opt(expr))
}
pub fn is_method_call(&self, expr_id: NodeId) -> bool {
self.method_map.contains_key(&expr_id)
pub fn is_method_call(&self, expr: &hir::Expr) -> bool {
// Only paths and method calls/overloaded operators have
// entries in type_dependent_defs, ignore the former here.
if let hir::ExprPath(_) = expr.node {
return false;
}
match self.type_dependent_defs.get(&expr.id) {
Some(&Def::Method(_)) => true,
_ => false
}
}
pub fn upvar_capture(&self, upvar_id: ty::UpvarId) -> Option<ty::UpvarCapture<'tcx>> {

View file

@ -141,8 +141,6 @@ pub enum TypeVariants<'tcx> {
TyFnDef(DefId, &'tcx Substs<'tcx>, PolyFnSig<'tcx>),
/// A pointer to a function. Written as `fn() -> i32`.
/// FIXME: This is currently also used to represent the callee of a method;
/// see ty::MethodCallee etc.
TyFnPtr(PolyFnSig<'tcx>),
/// A trait, defined with `trait`.

View file

@ -881,17 +881,17 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnconditionalRecursion {
-> bool {
use rustc::ty::adjustment::*;
// Check for method calls and overloaded operators.
if let Some(m) = cx.tables.method_map.get(&id).cloned() {
if method_call_refers_to_method(cx.tcx, method, m.def_id, m.substs, id) {
return true;
}
}
// Ignore non-expressions.
let expr = if let hir_map::NodeExpr(e) = cx.tcx.hir.get(id) {
e
} else {
return false;
};
// Check for overloaded autoderef method calls.
if let Some(Adjustment {
if let Some(&Adjustment {
kind: Adjust::DerefRef { ref autoderefs, .. }, ..
}) = cx.tables.adjustments.get(&id).cloned() {
}) = cx.tables.adjustments.get(&id) {
for &overloaded in autoderefs {
if let Some(m) = overloaded {
if method_call_refers_to_method(cx.tcx, method, m.def_id, m.substs, id) {
@ -901,9 +901,18 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnconditionalRecursion {
}
}
// Check for method calls and overloaded operators.
if cx.tables.is_method_call(expr) {
let def_id = cx.tables.type_dependent_defs[&id].def_id();
let substs = cx.tables.node_substs(id);
if method_call_refers_to_method(cx.tcx, method, def_id, substs, id) {
return true;
}
}
// Check for calls to methods via explicit paths (e.g. `T::method()`).
match cx.tcx.hir.get(id) {
hir_map::NodeExpr(&hir::Expr { node: hir::ExprCall(ref callee, _), .. }) => {
match expr.node {
hir::ExprCall(ref callee, _) => {
let def = if let hir::ExprPath(ref qpath) = callee.node {
cx.tables.qpath_def(qpath, callee.id)
} else {

View file

@ -118,7 +118,7 @@ impl<'tcx> Mirror<'tcx> for &'tcx hir::Expr {
overloaded_lvalue(cx,
self,
mt.ty,
method,
Some(method),
PassArgs::ByRef,
expr.to_ref(),
vec![])
@ -244,8 +244,7 @@ fn make_mirror_unadjusted<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
// Here comes the interesting stuff:
hir::ExprMethodCall(.., ref args) => {
// Rewrite a.b(c) into UFCS form like Trait::b(a, c)
let method = cx.tables().method_map[&expr.id];
let expr = method_callee(cx, expr, method);
let expr = method_callee(cx, expr, None);
let args = args.iter()
.map(|e| e.to_ref())
.collect();
@ -257,7 +256,7 @@ fn make_mirror_unadjusted<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
}
hir::ExprCall(ref fun, ref args) => {
if let Some(&method) = cx.tables().method_map.get(&expr.id) {
if cx.tables().is_method_call(expr) {
// The callee is something implementing Fn, FnMut, or FnOnce.
// Find the actual method implementation being called and
// build the appropriate UFCS call expression with the
@ -265,7 +264,7 @@ fn make_mirror_unadjusted<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
// rewrite f(u, v) into FnOnce::call_once(f, (u, v))
let method = method_callee(cx, expr, method);
let method = method_callee(cx, expr, None);
let arg_tys = args.iter().map(|e| cx.tables().expr_ty_adjusted(e));
let tupled_args = Expr {
@ -346,7 +345,7 @@ fn make_mirror_unadjusted<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
}
hir::ExprAssignOp(op, ref lhs, ref rhs) => {
if let Some(&method) = cx.tables().method_map.get(&expr.id) {
if cx.tables().is_method_call(expr) {
let pass_args = if op.node.is_by_value() {
PassArgs::ByValue
} else {
@ -354,7 +353,7 @@ fn make_mirror_unadjusted<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
};
overloaded_operator(cx,
expr,
method,
None,
pass_args,
lhs.to_ref(),
vec![rhs])
@ -370,7 +369,7 @@ fn make_mirror_unadjusted<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
hir::ExprLit(..) => ExprKind::Literal { literal: cx.const_eval_literal(expr) },
hir::ExprBinary(op, ref lhs, ref rhs) => {
if let Some(&method) = cx.tables().method_map.get(&expr.id) {
if cx.tables().is_method_call(expr) {
let pass_args = if op.node.is_by_value() {
PassArgs::ByValue
} else {
@ -378,7 +377,7 @@ fn make_mirror_unadjusted<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
};
overloaded_operator(cx,
expr,
method,
None,
pass_args,
lhs.to_ref(),
vec![rhs])
@ -430,11 +429,11 @@ fn make_mirror_unadjusted<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
}
hir::ExprIndex(ref lhs, ref index) => {
if let Some(&method) = cx.tables().method_map.get(&expr.id) {
if cx.tables().is_method_call(expr) {
overloaded_lvalue(cx,
expr,
expr_ty,
method,
None,
PassArgs::ByValue,
lhs.to_ref(),
vec![index])
@ -447,11 +446,11 @@ fn make_mirror_unadjusted<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
}
hir::ExprUnary(hir::UnOp::UnDeref, ref arg) => {
if let Some(&method) = cx.tables().method_map.get(&expr.id) {
if cx.tables().is_method_call(expr) {
overloaded_lvalue(cx,
expr,
expr_ty,
method,
None,
PassArgs::ByValue,
arg.to_ref(),
vec![])
@ -461,10 +460,10 @@ fn make_mirror_unadjusted<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
}
hir::ExprUnary(hir::UnOp::UnNot, ref arg) => {
if let Some(&method) = cx.tables().method_map.get(&expr.id) {
if cx.tables().is_method_call(expr) {
overloaded_operator(cx,
expr,
method,
None,
PassArgs::ByValue,
arg.to_ref(),
vec![])
@ -477,10 +476,10 @@ fn make_mirror_unadjusted<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
}
hir::ExprUnary(hir::UnOp::UnNeg, ref arg) => {
if let Some(&method) = cx.tables().method_map.get(&expr.id) {
if cx.tables().is_method_call(expr) {
overloaded_operator(cx,
expr,
method,
None,
PassArgs::ByValue,
arg.to_ref(),
vec![])
@ -699,17 +698,21 @@ fn make_mirror_unadjusted<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
fn method_callee<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
expr: &hir::Expr,
callee: ty::MethodCallee<'tcx>)
custom_callee: Option<ty::MethodCallee<'tcx>>)
-> Expr<'tcx> {
let (temp_lifetime, was_shrunk) = cx.region_maps.temporary_scope2(expr.id);
let (def_id, substs) = custom_callee.map(|m| (m.def_id, m.substs)).unwrap_or_else(|| {
(cx.tables().type_dependent_defs[&expr.id].def_id(),
cx.tables().node_substs(expr.id))
});
Expr {
temp_lifetime: temp_lifetime,
temp_lifetime_was_shrunk: was_shrunk,
ty: cx.tcx.type_of(callee.def_id).subst(cx.tcx, callee.substs),
ty: cx.tcx.type_of(def_id).subst(cx.tcx, substs),
span: expr.span,
kind: ExprKind::Literal {
literal: Literal::Value {
value: ConstVal::Function(callee.def_id, callee.substs),
value: ConstVal::Function(def_id, substs),
},
},
}
@ -942,7 +945,7 @@ enum PassArgs {
fn overloaded_operator<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
expr: &'tcx hir::Expr,
method: ty::MethodCallee<'tcx>,
custom_callee: Option<ty::MethodCallee<'tcx>>,
pass_args: PassArgs,
receiver: ExprRef<'tcx>,
args: Vec<&'tcx P<hir::Expr>>)
@ -985,7 +988,7 @@ fn overloaded_operator<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
}
// now create the call itself
let fun = method_callee(cx, expr, method);
let fun = method_callee(cx, expr, custom_callee);
ExprKind::Call {
ty: fun.ty,
fun: fun.to_ref(),
@ -996,7 +999,7 @@ fn overloaded_operator<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
fn overloaded_lvalue<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
expr: &'tcx hir::Expr,
lvalue_ty: Ty<'tcx>,
method: ty::MethodCallee<'tcx>,
custom_callee: Option<ty::MethodCallee<'tcx>>,
pass_args: PassArgs,
receiver: ExprRef<'tcx>,
args: Vec<&'tcx P<hir::Expr>>)
@ -1025,7 +1028,7 @@ fn overloaded_lvalue<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
// construct the complete expression `foo()` for the overloaded call,
// which will yield the &T type
let (temp_lifetime, was_shrunk) = cx.region_maps.temporary_scope2(expr.id);
let ref_kind = overloaded_operator(cx, expr, method, pass_args, receiver, args);
let ref_kind = overloaded_operator(cx, expr, custom_callee, pass_args, receiver, args);
let ref_expr = Expr {
temp_lifetime: temp_lifetime,
temp_lifetime_was_shrunk: was_shrunk,

View file

@ -283,7 +283,7 @@ fn check_expr<'a, 'tcx>(v: &mut CheckCrateVisitor<'a, 'tcx>, e: &hir::Expr, node
match e.node {
hir::ExprUnary(..) |
hir::ExprBinary(..) |
hir::ExprIndex(..) if v.tables.method_map.contains_key(&e.id) => {
hir::ExprIndex(..) if v.tables.is_method_call(e) => {
v.promotable = false;
}
hir::ExprBox(_) => {
@ -380,9 +380,9 @@ fn check_expr<'a, 'tcx>(v: &mut CheckCrateVisitor<'a, 'tcx>, e: &hir::Expr, node
}
}
hir::ExprMethodCall(..) => {
let method = v.tables.method_map[&e.id];
match v.tcx.associated_item(method.def_id).container {
ty::ImplContainer(_) => v.handle_const_fn_call(method.def_id, node_ty),
let def_id = v.tables.type_dependent_defs[&e.id].def_id();
match v.tcx.associated_item(def_id).container {
ty::ImplContainer(_) => v.handle_const_fn_call(def_id, node_ty),
ty::TraitContainer(_) => v.promotable = false
}
}

View file

@ -564,7 +564,7 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> {
}
}
ast::ExprKind::MethodCall(..) => {
let method_id = self.tables.method_map[&expr.id].def_id;
let method_id = self.tables.type_dependent_defs[&expr.id].def_id();
let (def_id, decl_id) = match self.tcx.associated_item(method_id).container {
ty::ImplContainer(_) => (Some(method_id), None),
ty::TraitContainer(_) => (None, Some(method_id)),

View file

@ -308,7 +308,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
TupleArgumentsFlag::TupleArguments,
expected);
self.tables.borrow_mut().method_map.insert(call_expr.id, method_callee);
self.write_method_call(call_expr.id, method_callee);
output_type
}
}
@ -363,7 +363,7 @@ impl<'a, 'gcx, 'tcx> DeferredCallResolution<'gcx, 'tcx> {
target: method_sig.inputs()[0]
});
fcx.tables.borrow_mut().method_map.insert(self.call_expr.id, method_callee);
fcx.write_method_call(self.call_expr.id, method_callee);
}
None => {
span_bug!(self.call_expr.span,

View file

@ -475,7 +475,7 @@ impl<'a, 'gcx, 'tcx> ConfirmContext<'a, 'gcx, 'tcx> {
{
debug!("convert_lvalue_op_to_mutable({:?}, {:?}, {:?}, {:?})",
op, expr, base_expr, arg_tys);
if !self.tables.borrow().method_map.contains_key(&expr.id) {
if !self.tables.borrow().is_method_call(expr) {
debug!("convert_lvalue_op_to_mutable - builtin, nothing to do");
return
}
@ -497,7 +497,7 @@ impl<'a, 'gcx, 'tcx> ConfirmContext<'a, 'gcx, 'tcx> {
};
let (_, method) = self.register_infer_ok_obligations(ok);
debug!("convert_lvalue_op_to_mutable: method={:?}", method);
self.tables.borrow_mut().method_map.insert(expr.id, method);
self.write_method_call(expr.id, method);
// Convert the autoref in the base expr to mutable with the correct
// region and mutability.

View file

@ -1758,6 +1758,11 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
}
}
pub fn write_method_call(&self, node_id: ast::NodeId, method: ty::MethodCallee<'tcx>) {
self.tables.borrow_mut().type_dependent_defs.insert(node_id, Def::Method(method.def_id));
self.write_substs(node_id, method.substs);
}
pub fn write_substs(&self, node_id: ast::NodeId, substs: &'tcx Substs<'tcx>) {
if !substs.is_noop() {
debug!("write_substs({}, {:?}) in fcx {}",
@ -2238,7 +2243,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
target: method.sig.inputs()[0]
});
self.tables.borrow_mut().method_map.insert(expr.id, method);
self.write_method_call(expr.id, method);
(input_ty, self.make_overloaded_lvalue_return_type(method).ty)
});
if result.is_some() {
@ -2777,7 +2782,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
expr,
rcvr) {
Ok(method) => {
self.tables.borrow_mut().method_map.insert(expr.id, method);
self.write_method_call(expr.id, method);
Ok(method)
}
Err(error) => {
@ -3453,7 +3458,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
target: method.sig.inputs()[0]
});
oprnd_t = self.make_overloaded_lvalue_return_type(method).ty;
self.tables.borrow_mut().method_map.insert(expr.id, method);
self.write_method_call(expr.id, method);
} else {
self.type_error_message(expr.span, |actual| {
format!("type `{}` cannot be \
@ -3918,7 +3923,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
}
// Finish resolving a path in a struct expression or pattern `S::A { .. }` if necessary.
// The newly resolved definition is written into `type_relative_path_defs`.
// The newly resolved definition is written into `type_dependent_defs`.
fn finish_resolving_struct_path(&self,
qpath: &hir::QPath,
path_span: Span,
@ -3943,7 +3948,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
ty, def, segment);
// Write back the new resolution.
self.tables.borrow_mut().type_relative_path_defs.insert(node_id, def);
self.tables.borrow_mut().type_dependent_defs.insert(node_id, def);
(def, ty)
}
@ -3951,7 +3956,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
}
// Resolve associated value path into a base type and associated constant or method definition.
// The newly resolved definition is written into `type_relative_path_defs`.
// The newly resolved definition is written into `type_dependent_defs`.
pub fn resolve_ty_and_def_ufcs<'b>(&self,
qpath: &'b hir::QPath,
node_id: ast::NodeId,
@ -3984,7 +3989,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
};
// Write back the new resolution.
self.tables.borrow_mut().type_relative_path_defs.insert(node_id, def);
self.tables.borrow_mut().type_dependent_defs.insert(node_id, def);
(def, Some(ty), slice::ref_slice(&**item_segment))
}

View file

@ -421,7 +421,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
},
target: method.sig.inputs()[0]
});
self.tables.borrow_mut().method_map.insert(expr.id, method);
self.write_method_call(expr.id, method);
Ok(method.sig.output())
}

View file

@ -520,14 +520,13 @@ impl<'a, 'gcx, 'tcx> Visitor<'gcx> for RegionCtxt<'a, 'gcx, 'tcx> {
self.type_must_outlive(infer::ExprTypeIsNotInScope(expr_ty, expr.span),
expr_ty, expr_region);
let opt_method_callee = self.tables.borrow().method_map.get(&expr.id).cloned();
let has_method_map = opt_method_callee.is_some();
let is_method_call = self.tables.borrow().is_method_call(expr);
// If we are calling a method (either explicitly or via an
// overloaded operator), check that all of the types provided as
// arguments for its type parameters are well-formed, and all the regions
// provided as arguments outlive the call.
if let Some(callee) = opt_method_callee {
if is_method_call {
let origin = match expr.node {
hir::ExprMethodCall(..) =>
infer::ParameterOrigin::MethodCall,
@ -537,7 +536,8 @@ impl<'a, 'gcx, 'tcx> Visitor<'gcx> for RegionCtxt<'a, 'gcx, 'tcx> {
infer::ParameterOrigin::OverloadedOperator
};
self.substs_wf_in_scope(origin, &callee.substs, expr.span, expr_region);
let substs = self.tables.borrow().node_substs(expr.id);
self.substs_wf_in_scope(origin, substs, expr.span, expr_region);
// Arguments (sub-expressions) are checked via `constrain_call`, below.
}
@ -614,7 +614,7 @@ impl<'a, 'gcx, 'tcx> Visitor<'gcx> for RegionCtxt<'a, 'gcx, 'tcx> {
}
hir::ExprCall(ref callee, ref args) => {
if has_method_map {
if is_method_call {
self.constrain_call(expr, Some(&callee),
args.iter().map(|e| &*e), false);
} else {
@ -634,7 +634,7 @@ impl<'a, 'gcx, 'tcx> Visitor<'gcx> for RegionCtxt<'a, 'gcx, 'tcx> {
}
hir::ExprAssignOp(_, ref lhs, ref rhs) => {
if has_method_map {
if is_method_call {
self.constrain_call(expr, Some(&lhs),
Some(&**rhs).into_iter(), false);
}
@ -642,14 +642,14 @@ impl<'a, 'gcx, 'tcx> Visitor<'gcx> for RegionCtxt<'a, 'gcx, 'tcx> {
intravisit::walk_expr(self, expr);
}
hir::ExprIndex(ref lhs, ref rhs) if has_method_map => {
hir::ExprIndex(ref lhs, ref rhs) if is_method_call => {
self.constrain_call(expr, Some(&lhs),
Some(&**rhs).into_iter(), true);
intravisit::walk_expr(self, expr);
},
hir::ExprBinary(op, ref lhs, ref rhs) if has_method_map => {
hir::ExprBinary(op, ref lhs, ref rhs) if is_method_call => {
let implicitly_ref_args = !op.node.is_by_value();
// As `expr_method_call`, but the call is via an
@ -674,7 +674,7 @@ impl<'a, 'gcx, 'tcx> Visitor<'gcx> for RegionCtxt<'a, 'gcx, 'tcx> {
intravisit::walk_expr(self, expr);
}
hir::ExprUnary(op, ref lhs) if has_method_map => {
hir::ExprUnary(op, ref lhs) if is_method_call => {
let implicitly_ref_args = !op.is_by_value();
// As above.
@ -686,7 +686,7 @@ impl<'a, 'gcx, 'tcx> Visitor<'gcx> for RegionCtxt<'a, 'gcx, 'tcx> {
hir::ExprUnary(hir::UnDeref, ref base) => {
// For *a, the lifetime of a must enclose the deref
if self.tables.borrow().is_method_call(expr.id) {
if self.tables.borrow().is_method_call(expr) {
self.constrain_call(expr, Some(base),
None::<hir::Expr>.iter(), true);
}

View file

@ -106,7 +106,9 @@ impl<'cx, 'gcx, 'tcx> WritebackCx<'cx, 'gcx, 'tcx> {
let inner_ty = self.fcx.resolve_type_vars_if_possible(&inner_ty);
if inner_ty.is_scalar() {
self.fcx.tables.borrow_mut().method_map.remove(&e.id);
let mut tables = self.fcx.tables.borrow_mut();
tables.type_dependent_defs.remove(&e.id);
tables.node_substs.remove(&e.id);
}
}
hir::ExprBinary(ref op, ref lhs, ref rhs) |
@ -118,7 +120,9 @@ impl<'cx, 'gcx, 'tcx> WritebackCx<'cx, 'gcx, 'tcx> {
let rhs_ty = self.fcx.resolve_type_vars_if_possible(&rhs_ty);
if lhs_ty.is_scalar() && rhs_ty.is_scalar() {
self.fcx.tables.borrow_mut().method_map.remove(&e.id);
let mut tables = self.fcx.tables.borrow_mut();
tables.type_dependent_defs.remove(&e.id);
tables.node_substs.remove(&e.id);
// weird but true: the by-ref binops put an
// adjustment on the lhs but not the rhs; the
@ -127,11 +131,11 @@ impl<'cx, 'gcx, 'tcx> WritebackCx<'cx, 'gcx, 'tcx> {
match e.node {
hir::ExprBinary(..) => {
if !op.node.is_by_value() {
self.fcx.tables.borrow_mut().adjustments.remove(&lhs.id);
tables.adjustments.remove(&lhs.id);
}
},
hir::ExprAssignOp(..) => {
self.fcx.tables.borrow_mut().adjustments.remove(&lhs.id);
tables.adjustments.remove(&lhs.id);
},
_ => {},
}
@ -164,7 +168,6 @@ impl<'cx, 'gcx, 'tcx> Visitor<'gcx> for WritebackCx<'cx, 'gcx, 'tcx> {
self.fix_scalar_builtin_expr(e);
self.visit_node_id(e.span, e.id);
self.visit_method_map_entry(e.span, e.id);
if let hir::ExprClosure(_, _, body, _) = e.node {
let body = self.fcx.tcx.hir.body(body);
@ -280,9 +283,9 @@ impl<'cx, 'gcx, 'tcx> WritebackCx<'cx, 'gcx, 'tcx> {
}
fn visit_node_id(&mut self, span: Span, node_id: ast::NodeId) {
// Export associated path extensions.
if let Some(def) = self.fcx.tables.borrow_mut().type_relative_path_defs.remove(&node_id) {
self.tables.type_relative_path_defs.insert(node_id, def);
// Export associated path extensions and method resultions.
if let Some(def) = self.fcx.tables.borrow_mut().type_dependent_defs.remove(&node_id) {
self.tables.type_dependent_defs.insert(node_id, def);
}
// Resolve any borrowings for the node with id `node_id`
@ -358,27 +361,6 @@ impl<'cx, 'gcx, 'tcx> WritebackCx<'cx, 'gcx, 'tcx> {
}
}
fn visit_method_map_entry(&mut self,
method_span: Span,
node_id: ast::NodeId) {
// Resolve any method map entry
let new_method = match self.fcx.tables.borrow_mut().method_map.remove(&node_id) {
Some(method) => {
Some(MethodCallee {
def_id: method.def_id,
substs: self.resolve(&method.substs, &method_span),
sig: self.resolve(&method.sig, &method_span),
})
}
None => None
};
//NB(jroesch): We need to match twice to avoid a double borrow which would cause an ICE
if let Some(method) = new_method {
self.tables.method_map.insert(node_id, method);
}
}
fn visit_liberated_fn_sigs(&mut self) {
for (&node_id, fn_sig) in self.fcx.tables.borrow().liberated_fn_sigs.iter() {
let fn_sig = self.resolve(fn_sig, &node_id);