mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-25 16:24:46 +00:00
Store all generic arguments for method calls in HIR
This commit is contained in:
parent
287de2595a
commit
8c44a9dca7
@ -944,10 +944,9 @@ pub fn walk_expr<'v, V: Visitor<'v>>(visitor: &mut V, expression: &'v Expr) {
|
||||
walk_list!(visitor, visit_expr, arguments);
|
||||
visitor.visit_expr(callee_expression)
|
||||
}
|
||||
ExprMethodCall(ref name, ref types, ref arguments) => {
|
||||
visitor.visit_name(name.span, name.node);
|
||||
ExprMethodCall(ref segment, _, ref arguments) => {
|
||||
visitor.visit_path_segment(expression.span, segment);
|
||||
walk_list!(visitor, visit_expr, arguments);
|
||||
walk_list!(visitor, visit_ty, types);
|
||||
}
|
||||
ExprBinary(_, ref left_expression, ref right_expression) => {
|
||||
visitor.visit_expr(left_expression);
|
||||
|
@ -1845,16 +1845,9 @@ impl<'a> LoweringContext<'a> {
|
||||
hir::ExprCall(f, args.iter().map(|x| self.lower_expr(x)).collect())
|
||||
}
|
||||
ExprKind::MethodCall(ref seg, ref args) => {
|
||||
let tps = match seg.parameters {
|
||||
Some(ref params) => match **params {
|
||||
PathParameters::AngleBracketed(ref param_data) => ¶m_data.types[..],
|
||||
_ => &[],
|
||||
},
|
||||
_ => &[],
|
||||
};
|
||||
let tps = tps.iter().map(|x| self.lower_ty(x)).collect();
|
||||
let hir_seg = self.lower_path_segment(e.span, seg, ParamMode::Optional, 0);
|
||||
let args = args.iter().map(|x| self.lower_expr(x)).collect();
|
||||
hir::ExprMethodCall(respan(seg.span, self.lower_ident(seg.identifier)), tps, args)
|
||||
hir::ExprMethodCall(hir_seg, seg.span, args)
|
||||
}
|
||||
ExprKind::Binary(binop, ref lhs, ref rhs) => {
|
||||
let binop = self.lower_binop(binop);
|
||||
|
@ -972,19 +972,16 @@ pub enum Expr_ {
|
||||
/// The first field resolves to the function itself (usually an `ExprPath`),
|
||||
/// and the second field is the list of arguments
|
||||
ExprCall(P<Expr>, HirVec<Expr>),
|
||||
/// A method call (`x.foo::<Bar, Baz>(a, b, c, d)`)
|
||||
/// A method call (`x.foo::<'static, Bar, Baz>(a, b, c, d)`)
|
||||
///
|
||||
/// The `Spanned<Name>` is the identifier for the method name.
|
||||
/// The vector of `Ty`s are the ascripted type parameters for the method
|
||||
/// The `PathSegment`/`Span` represent the method name and its generic arguments
|
||||
/// (within the angle brackets).
|
||||
///
|
||||
/// The first element of the vector of `Expr`s is the expression that
|
||||
/// evaluates to the object on which the method is being called on (the
|
||||
/// receiver), and the remaining elements are the rest of the arguments.
|
||||
///
|
||||
/// The first element of the vector of `Expr`s is the expression that evaluates
|
||||
/// to the object on which the method is being called on (the receiver),
|
||||
/// and the remaining elements are the rest of the arguments.
|
||||
/// Thus, `x.foo::<Bar, Baz>(a, b, c, d)` is represented as
|
||||
/// `ExprMethodCall(foo, [Bar, Baz], [x, a, b, c, d])`.
|
||||
ExprMethodCall(Spanned<Name>, HirVec<P<Ty>>, HirVec<Expr>),
|
||||
/// `ExprKind::MethodCall(PathSegment { foo, [Bar, Baz] }, [x, a, b, c, d])`.
|
||||
ExprMethodCall(PathSegment, Span, HirVec<Expr>),
|
||||
/// A tuple (`(a, b, c ,d)`)
|
||||
ExprTup(HirVec<Expr>),
|
||||
/// A binary operation (For example: `a + b`, `a * b`)
|
||||
|
@ -1188,18 +1188,17 @@ impl<'a> State<'a> {
|
||||
}
|
||||
|
||||
fn print_expr_method_call(&mut self,
|
||||
name: Spanned<ast::Name>,
|
||||
tys: &[P<hir::Ty>],
|
||||
segment: &hir::PathSegment,
|
||||
args: &[hir::Expr])
|
||||
-> io::Result<()> {
|
||||
let base_args = &args[1..];
|
||||
self.print_expr(&args[0])?;
|
||||
word(&mut self.s, ".")?;
|
||||
self.print_name(name.node)?;
|
||||
if !tys.is_empty() {
|
||||
word(&mut self.s, "::<")?;
|
||||
self.commasep(Inconsistent, tys, |s, ty| s.print_type(&ty))?;
|
||||
word(&mut self.s, ">")?;
|
||||
self.print_name(segment.name)?;
|
||||
if !segment.parameters.lifetimes().is_empty() ||
|
||||
!segment.parameters.types().is_empty() ||
|
||||
!segment.parameters.bindings().is_empty() {
|
||||
self.print_path_parameters(&segment.parameters, true)?;
|
||||
}
|
||||
self.print_call_post(base_args)
|
||||
}
|
||||
@ -1254,8 +1253,8 @@ impl<'a> State<'a> {
|
||||
hir::ExprCall(ref func, ref args) => {
|
||||
self.print_expr_call(&func, args)?;
|
||||
}
|
||||
hir::ExprMethodCall(name, ref tys, ref args) => {
|
||||
self.print_expr_method_call(name, &tys[..], args)?;
|
||||
hir::ExprMethodCall(ref segment, _, ref args) => {
|
||||
self.print_expr_method_call(segment, args)?;
|
||||
}
|
||||
hir::ExprBinary(op, ref lhs, ref rhs) => {
|
||||
self.print_expr_binary(op, &lhs, &rhs)?;
|
||||
|
@ -626,7 +626,7 @@ impl_stable_hash_for!(enum hir::Expr_ {
|
||||
ExprBox(sub),
|
||||
ExprArray(subs),
|
||||
ExprCall(callee, args),
|
||||
ExprMethodCall(name, ts, args),
|
||||
ExprMethodCall(segment, span, args),
|
||||
ExprTup(fields),
|
||||
ExprBinary(op, lhs, rhs),
|
||||
ExprUnary(op, operand),
|
||||
|
@ -670,10 +670,10 @@ impl<'a, 'tcx> Visitor<'tcx> for TypePrivacyVisitor<'a, 'tcx> {
|
||||
return;
|
||||
}
|
||||
}
|
||||
hir::ExprMethodCall(name, ..) => {
|
||||
hir::ExprMethodCall(_, span, _) => {
|
||||
// Method calls have to be checked specially.
|
||||
let def_id = self.tables.type_dependent_defs[&expr.id].def_id();
|
||||
self.span = name.span;
|
||||
self.span = span;
|
||||
if self.tcx.type_of(def_id).visit_with(self) {
|
||||
return;
|
||||
}
|
||||
|
@ -44,15 +44,15 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
||||
call_expr: &'gcx hir::Expr,
|
||||
unadjusted_self_ty: Ty<'tcx>,
|
||||
pick: probe::Pick<'tcx>,
|
||||
supplied_method_types: Vec<Ty<'tcx>>)
|
||||
segment: &hir::PathSegment)
|
||||
-> MethodCallee<'tcx> {
|
||||
debug!("confirm(unadjusted_self_ty={:?}, pick={:?}, supplied_method_types={:?})",
|
||||
debug!("confirm(unadjusted_self_ty={:?}, pick={:?}, generic_args={:?})",
|
||||
unadjusted_self_ty,
|
||||
pick,
|
||||
supplied_method_types);
|
||||
segment.parameters);
|
||||
|
||||
let mut confirm_cx = ConfirmContext::new(self, span, self_expr, call_expr);
|
||||
confirm_cx.confirm(unadjusted_self_ty, pick, supplied_method_types)
|
||||
confirm_cx.confirm(unadjusted_self_ty, pick, segment)
|
||||
}
|
||||
}
|
||||
|
||||
@ -73,7 +73,7 @@ impl<'a, 'gcx, 'tcx> ConfirmContext<'a, 'gcx, 'tcx> {
|
||||
fn confirm(&mut self,
|
||||
unadjusted_self_ty: Ty<'tcx>,
|
||||
pick: probe::Pick<'tcx>,
|
||||
supplied_method_types: Vec<Ty<'tcx>>)
|
||||
segment: &hir::PathSegment)
|
||||
-> MethodCallee<'tcx> {
|
||||
// Adjust the self expression the user provided and obtain the adjusted type.
|
||||
let self_ty = self.adjust_self_ty(unadjusted_self_ty, &pick);
|
||||
@ -83,7 +83,7 @@ impl<'a, 'gcx, 'tcx> ConfirmContext<'a, 'gcx, 'tcx> {
|
||||
|
||||
// Create substitutions for the method's type parameters.
|
||||
let rcvr_substs = self.fresh_receiver_substs(self_ty, &pick);
|
||||
let all_substs = self.instantiate_method_substs(&pick, supplied_method_types, rcvr_substs);
|
||||
let all_substs = self.instantiate_method_substs(&pick, segment, rcvr_substs);
|
||||
|
||||
debug!("all_substs={:?}", all_substs);
|
||||
|
||||
@ -279,9 +279,14 @@ impl<'a, 'gcx, 'tcx> ConfirmContext<'a, 'gcx, 'tcx> {
|
||||
|
||||
fn instantiate_method_substs(&mut self,
|
||||
pick: &probe::Pick<'tcx>,
|
||||
mut supplied_method_types: Vec<Ty<'tcx>>,
|
||||
segment: &hir::PathSegment,
|
||||
substs: &Substs<'tcx>)
|
||||
-> &'tcx Substs<'tcx> {
|
||||
let supplied_method_types = match segment.parameters {
|
||||
hir::AngleBracketedParameters(ref data) => &data.types,
|
||||
_ => bug!("unexpected generic arguments: {:?}", segment.parameters),
|
||||
};
|
||||
|
||||
// Determine the values for the generic parameters of the method.
|
||||
// If they were not explicitly supplied, just construct fresh
|
||||
// variables.
|
||||
@ -312,7 +317,6 @@ impl<'a, 'gcx, 'tcx> ConfirmContext<'a, 'gcx, 'tcx> {
|
||||
num_method_types))
|
||||
.emit();
|
||||
}
|
||||
supplied_method_types = vec![self.tcx.types.err; num_method_types];
|
||||
}
|
||||
|
||||
// Create subst for early-bound lifetime parameters, combining
|
||||
@ -331,10 +335,10 @@ impl<'a, 'gcx, 'tcx> ConfirmContext<'a, 'gcx, 'tcx> {
|
||||
let i = def.index as usize;
|
||||
if i < substs.len() {
|
||||
substs.type_at(i)
|
||||
} else if supplied_method_types.is_empty() {
|
||||
self.type_var_for_def(self.span, def, cur_substs)
|
||||
} else if let Some(ast_ty) = supplied_method_types.get(i - supplied_start) {
|
||||
self.to_ty(ast_ty)
|
||||
} else {
|
||||
supplied_method_types[i - supplied_start]
|
||||
self.type_var_for_def(self.span, def, cur_substs)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
@ -130,22 +130,21 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
||||
/// * `supplied_method_types`: the explicit method type parameters, if any (`T1..Tn`)
|
||||
/// * `self_expr`: the self expression (`foo`)
|
||||
pub fn lookup_method(&self,
|
||||
span: Span,
|
||||
method_name: ast::Name,
|
||||
self_ty: ty::Ty<'tcx>,
|
||||
supplied_method_types: Vec<ty::Ty<'tcx>>,
|
||||
segment: &hir::PathSegment,
|
||||
span: Span,
|
||||
call_expr: &'gcx hir::Expr,
|
||||
self_expr: &'gcx hir::Expr)
|
||||
-> Result<MethodCallee<'tcx>, MethodError<'tcx>> {
|
||||
debug!("lookup(method_name={}, self_ty={:?}, call_expr={:?}, self_expr={:?})",
|
||||
method_name,
|
||||
segment.name,
|
||||
self_ty,
|
||||
call_expr,
|
||||
self_expr);
|
||||
|
||||
let mode = probe::Mode::MethodCall;
|
||||
let self_ty = self.resolve_type_vars_if_possible(&self_ty);
|
||||
let pick = self.probe_for_name(span, mode, method_name, IsSuggestion(false),
|
||||
let pick = self.probe_for_name(span, mode, segment.name, IsSuggestion(false),
|
||||
self_ty, call_expr.id)?;
|
||||
|
||||
if let Some(import_id) = pick.import_id {
|
||||
@ -161,7 +160,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
||||
call_expr,
|
||||
self_ty,
|
||||
pick,
|
||||
supplied_method_types))
|
||||
segment))
|
||||
}
|
||||
|
||||
/// `lookup_method_in_trait` is used for overloaded operators.
|
||||
|
@ -2771,22 +2771,19 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
||||
// Checks a method call.
|
||||
fn check_method_call(&self,
|
||||
expr: &'gcx hir::Expr,
|
||||
method_name: Spanned<ast::Name>,
|
||||
segment: &hir::PathSegment,
|
||||
span: Span,
|
||||
args: &'gcx [hir::Expr],
|
||||
tps: &[P<hir::Ty>],
|
||||
expected: Expectation<'tcx>,
|
||||
lvalue_pref: LvaluePreference) -> Ty<'tcx> {
|
||||
let rcvr = &args[0];
|
||||
let rcvr_t = self.check_expr_with_lvalue_pref(&rcvr, lvalue_pref);
|
||||
|
||||
// no need to check for bot/err -- callee does that
|
||||
let expr_t = self.structurally_resolved_type(expr.span, rcvr_t);
|
||||
let rcvr_t = self.structurally_resolved_type(expr.span, rcvr_t);
|
||||
|
||||
let tps = tps.iter().map(|ast_ty| self.to_ty(&ast_ty)).collect::<Vec<_>>();
|
||||
let method = match self.lookup_method(method_name.span,
|
||||
method_name.node,
|
||||
expr_t,
|
||||
tps,
|
||||
let method = match self.lookup_method(rcvr_t,
|
||||
segment,
|
||||
span,
|
||||
expr,
|
||||
rcvr) {
|
||||
Ok(method) => {
|
||||
@ -2794,10 +2791,10 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
||||
Ok(method)
|
||||
}
|
||||
Err(error) => {
|
||||
if method_name.node != keywords::Invalid.name() {
|
||||
self.report_method_error(method_name.span,
|
||||
expr_t,
|
||||
method_name.node,
|
||||
if segment.name != keywords::Invalid.name() {
|
||||
self.report_method_error(span,
|
||||
rcvr_t,
|
||||
segment.name,
|
||||
Some(rcvr),
|
||||
error,
|
||||
Some(args));
|
||||
@ -2807,7 +2804,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
||||
};
|
||||
|
||||
// Call the generic checker.
|
||||
self.check_method_argument_types(method_name.span, method,
|
||||
self.check_method_argument_types(span, method,
|
||||
&args[1..],
|
||||
DontTupleArguments,
|
||||
expected)
|
||||
@ -3735,8 +3732,8 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
||||
hir::ExprCall(ref callee, ref args) => {
|
||||
self.check_call(expr, &callee, args, expected)
|
||||
}
|
||||
hir::ExprMethodCall(name, ref tps, ref args) => {
|
||||
self.check_method_call(expr, name, args, &tps[..], expected, lvalue_pref)
|
||||
hir::ExprMethodCall(ref segment, span, ref args) => {
|
||||
self.check_method_call(expr, segment, span, args, expected, lvalue_pref)
|
||||
}
|
||||
hir::ExprCast(ref e, ref t) => {
|
||||
// Find the type of `e`. Supply hints based on the type we are casting to,
|
||||
|
Loading…
Reference in New Issue
Block a user