rustc: replace method_map with Def::Method and node_substs entries.
This commit is contained in:
parent
9eae6ba7fa
commit
552ab37a10
20 changed files with 120 additions and 119 deletions
|
@ -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())
|
||||
}
|
||||
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
};
|
||||
|
|
|
@ -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>> {
|
||||
|
|
|
@ -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`.
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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)),
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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))
|
||||
}
|
||||
|
||||
|
|
|
@ -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())
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue