Skip to content

Store all generic arguments for method calls in AST/HIR #43115

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
Jul 9, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 7 additions & 7 deletions src/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 2 additions & 3 deletions src/librustc/hir/intravisit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
6 changes: 3 additions & 3 deletions src/librustc/hir/lowering.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1844,10 +1844,10 @@ impl<'a> LoweringContext<'a> {
let f = P(self.lower_expr(f));
hir::ExprCall(f, args.iter().map(|x| self.lower_expr(x)).collect())
}
ExprKind::MethodCall(i, ref tps, ref args) => {
let tps = tps.iter().map(|x| self.lower_ty(x)).collect();
ExprKind::MethodCall(ref seg, ref args) => {
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(i.span, self.lower_ident(i.node)), tps, args)
hir::ExprMethodCall(hir_seg, seg.span, args)
}
ExprKind::Binary(binop, ref lhs, ref rhs) => {
let binop = self.lower_binop(binop);
Expand Down
17 changes: 7 additions & 10 deletions src/librustc/hir/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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`)
Expand Down
17 changes: 8 additions & 9 deletions src/librustc/hir/print.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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)
}
Expand Down Expand Up @@ -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)?;
Expand Down
2 changes: 1 addition & 1 deletion src/librustc/ich/impls_hir.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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),
Expand Down
17 changes: 17 additions & 0 deletions src/librustc_passes/ast_validation.rs
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,23 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
ExprKind::Continue(Some(ident)) => {
self.check_label(ident.node, ident.span);
}
ExprKind::MethodCall(ref segment, ..) => {
if let Some(ref params) = segment.parameters {
match **params {
PathParameters::AngleBracketed(ref param_data) => {
if !param_data.bindings.is_empty() {
let binding_span = param_data.bindings[0].span;
self.err_handler().span_err(binding_span,
"type bindings cannot be used in method calls");
}
}
PathParameters::Parenthesized(..) => {
self.err_handler().span_err(expr.span,
"parenthesized parameters cannot be used on method calls");
}
}
}
}
_ => {}
}

Expand Down
4 changes: 2 additions & 2 deletions src/librustc_privacy/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
Expand Down
14 changes: 6 additions & 8 deletions src/librustc_resolve/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2467,9 +2467,9 @@ impl<'a> Resolver<'a> {
path_str, ident.node));
return err;
}
ExprKind::MethodCall(ident, ..) => {
ExprKind::MethodCall(ref segment, ..) => {
err.span_label(parent.span, format!("did you mean `{}::{}(...)`?",
path_str, ident.node));
path_str, segment.identifier));
return err;
}
_ => {}
Expand Down Expand Up @@ -3145,15 +3145,13 @@ impl<'a> Resolver<'a> {
ExprKind::Field(ref subexpression, _) => {
self.resolve_expr(subexpression, Some(expr));
}
ExprKind::MethodCall(_, ref types, ref arguments) => {
ExprKind::MethodCall(ref segment, ref arguments) => {
let mut arguments = arguments.iter();
self.resolve_expr(arguments.next().unwrap(), Some(expr));
for argument in arguments {
self.resolve_expr(argument, None);
}
for ty in types.iter() {
self.visit_ty(ty);
}
self.visit_path_segment(expr.span, segment);
}

ExprKind::Repeat(ref element, ref count) => {
Expand Down Expand Up @@ -3185,10 +3183,10 @@ impl<'a> Resolver<'a> {
let traits = self.get_traits_containing_item(name.node, ValueNS);
self.trait_map.insert(expr.id, traits);
}
ExprKind::MethodCall(name, ..) => {
ExprKind::MethodCall(ref segment, ..) => {
debug!("(recording candidate traits for expr) recording traits for {}",
expr.id);
let traits = self.get_traits_containing_item(name.node, ValueNS);
let traits = self.get_traits_containing_item(segment.identifier, ValueNS);
self.trait_map.insert(expr.id, traits);
}
_ => {
Expand Down
26 changes: 15 additions & 11 deletions src/librustc_typeck/check/method/confirm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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)
}
}

Expand All @@ -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);
Expand All @@ -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);

Expand Down Expand Up @@ -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.
Expand Down Expand Up @@ -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
Expand All @@ -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)
}
})
}
Expand Down
11 changes: 5 additions & 6 deletions src/librustc_typeck/check/method/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand All @@ -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.
Expand Down
Loading