]> git.lizzy.rs Git - rust.git/commitdiff
Support generic lifetime arguments in method calls
authorVadim Petrochenkov <vadim.petrochenkov@gmail.com>
Tue, 6 Jun 2017 21:17:14 +0000 (00:17 +0300)
committerVadim Petrochenkov <vadim.petrochenkov@gmail.com>
Mon, 17 Jul 2017 21:12:48 +0000 (00:12 +0300)
src/librustc_passes/ast_validation.rs
src/librustc_typeck/check/method/confirm.rs
src/librustc_typeck/diagnostics.rs
src/test/compile-fail/E0035.rs [deleted file]
src/test/compile-fail/E0036.rs [deleted file]
src/test/compile-fail/method-call-lifetime-args-unresolved.rs [new file with mode: 0644]
src/test/compile-fail/method-call-lifetime-args.rs [new file with mode: 0644]
src/test/compile-fail/method-call-type-binding.rs
src/test/compile-fail/trait-test-2.rs

index 72c7b92fe6e309e149eed66844ccb2f526a51c4f..99a49dbd7d732122c8a458ef8cac9804d5488005 100644 (file)
@@ -127,18 +127,9 @@ fn visit_expr(&mut self, expr: &'a Expr) {
             }
             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");
-                        }
+                    if let PathParameters::Parenthesized(..) = **params {
+                        self.err_handler().span_err(expr.span,
+                            "parenthesized parameters cannot be used on method calls");
                     }
                 }
             }
index 0829951e12debfdaaed9d6d6d15f6aa5c89fc109..a647a8bf6f86c9aee24d33b1ea85af4bb7eddeab 100644 (file)
@@ -10,6 +10,7 @@
 
 use super::{probe, MethodCallee};
 
+use astconv::AstConv;
 use check::{FnCtxt, LvalueOp, callee};
 use hir::def_id::DefId;
 use rustc::ty::subst::Substs;
@@ -282,52 +283,25 @@ fn instantiate_method_substs(&mut self,
                                  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.
-        let num_supplied_types = supplied_method_types.len();
         let method_generics = self.tcx.generics_of(pick.item.def_id);
-        let num_method_types = method_generics.types.len();
-
-        if num_supplied_types > 0 && num_supplied_types != num_method_types {
-            if num_method_types == 0 {
-                struct_span_err!(self.tcx.sess,
-                                 self.span,
-                                 E0035,
-                                 "does not take type parameters")
-                    .span_label(self.span, "called with unneeded type parameters")
-                    .emit();
-            } else {
-                struct_span_err!(self.tcx.sess,
-                                 self.span,
-                                 E0036,
-                                 "incorrect number of type parameters given for this method: \
-                                  expected {}, found {}",
-                                 num_method_types,
-                                 num_supplied_types)
-                    .span_label(self.span,
-                                format!("Passed {} type argument{}, expected {}",
-                                         num_supplied_types,
-                                         if num_supplied_types != 1 { "s" } else { "" },
-                                         num_method_types))
-                    .emit();
-            }
-        }
+        let mut fn_segment = Some((segment, method_generics));
+        self.fcx.check_path_parameter_count(self.span, &mut fn_segment);
 
         // Create subst for early-bound lifetime parameters, combining
         // parameters from the type and those from the method.
-        //
-        // FIXME -- permit users to manually specify lifetimes
-        let supplied_start = substs.len() + method_generics.regions.len();
+        let (supplied_types, supplied_lifetimes) = match segment.parameters {
+            hir::AngleBracketedParameters(ref data) => (&data.types, &data.lifetimes),
+            _ => bug!("unexpected generic arguments: {:?}", segment.parameters),
+        };
         Substs::for_item(self.tcx, pick.item.def_id, |def, _| {
             let i = def.index as usize;
             if i < substs.len() {
                 substs.region_at(i)
+            } else if let Some(lifetime) = supplied_lifetimes.get(i - substs.len()) {
+                AstConv::ast_region_to_region(self.fcx, lifetime, Some(def))
             } else {
                 self.region_var_for_def(self.span, def)
             }
@@ -335,7 +309,7 @@ fn instantiate_method_substs(&mut self,
             let i = def.index as usize;
             if i < substs.len() {
                 substs.type_at(i)
-            } else if let Some(ast_ty) = supplied_method_types.get(i - supplied_start) {
+            } else if let Some(ast_ty) = supplied_types.get(i - substs.len()) {
                 self.to_ty(ast_ty)
             } else {
                 self.type_var_for_def(self.span, def, cur_substs)
index 87e59683fd2a8d49a40593051312a84bad1f7211..1e26a734e7640d8e90765077522e6dba4ffade1d 100644 (file)
@@ -332,92 +332,6 @@ fn main() {
 ```
 "##,
 
-E0035: r##"
-You tried to give a type parameter where it wasn't needed. Erroneous code
-example:
-
-```compile_fail,E0035
-struct Test;
-
-impl Test {
-    fn method(&self) {}
-}
-
-fn main() {
-    let x = Test;
-
-    x.method::<i32>(); // Error: Test::method doesn't need type parameter!
-}
-```
-
-To fix this error, just remove the type parameter:
-
-```
-struct Test;
-
-impl Test {
-    fn method(&self) {}
-}
-
-fn main() {
-    let x = Test;
-
-    x.method(); // OK, we're good!
-}
-```
-"##,
-
-E0036: r##"
-This error occurrs when you pass too many or not enough type parameters to
-a method. Erroneous code example:
-
-```compile_fail,E0036
-struct Test;
-
-impl Test {
-    fn method<T>(&self, v: &[T]) -> usize {
-        v.len()
-    }
-}
-
-fn main() {
-    let x = Test;
-    let v = &[0];
-
-    x.method::<i32, i32>(v); // error: only one type parameter is expected!
-}
-```
-
-To fix it, just specify a correct number of type parameters:
-
-```
-struct Test;
-
-impl Test {
-    fn method<T>(&self, v: &[T]) -> usize {
-        v.len()
-    }
-}
-
-fn main() {
-    let x = Test;
-    let v = &[0];
-
-    x.method::<i32>(v); // OK, we're good!
-}
-```
-
-Please note on the last example that we could have called `method` like this:
-
-```
-# struct Test;
-# impl Test { fn method<T>(&self, v: &[T]) -> usize { v.len() } }
-# let x = Test;
-# let v = &[0];
-x.method(v);
-```
-"##,
-
 E0040: r##"
 It is not allowed to manually call destructors in Rust. It is also not
 necessary to do this since `drop` is called automatically whenever a value goes
@@ -4681,6 +4595,8 @@ fn i_am_a_function() {}
 }
 
 register_diagnostics! {
+//  E0035, merged into E0087/E0089
+//  E0036, merged into E0087/E0089
 //  E0068,
 //  E0085,
 //  E0086,
diff --git a/src/test/compile-fail/E0035.rs b/src/test/compile-fail/E0035.rs
deleted file mode 100644 (file)
index 9322d21..0000000
+++ /dev/null
@@ -1,21 +0,0 @@
-// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-struct Test;
-
-impl Test {
-    fn method(&self) {}
-}
-
-fn main() {
-    let x = Test;
-    x.method::<i32>(); //~ ERROR E0035
-                       //~| NOTE called with unneeded type parameters
-}
diff --git a/src/test/compile-fail/E0036.rs b/src/test/compile-fail/E0036.rs
deleted file mode 100644 (file)
index ecb6dac..0000000
+++ /dev/null
@@ -1,24 +0,0 @@
-// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-struct Test;
-
-impl Test {
-    fn method<T>(&self, v: &[T]) -> usize {
-        v.len()
-    }
-}
-
-fn main() {
-    let x = Test;
-    let v = &[0];
-    x.method::<i32, i32>(v); //~ ERROR E0036
-                             //~| NOTE Passed 2 type arguments, expected 1
-}
diff --git a/src/test/compile-fail/method-call-lifetime-args-unresolved.rs b/src/test/compile-fail/method-call-lifetime-args-unresolved.rs
new file mode 100644 (file)
index 0000000..4910bfa
--- /dev/null
@@ -0,0 +1,13 @@
+// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+fn main() {
+    0.clone::<'a>(); //~ ERROR use of undeclared lifetime name `'a`
+}
diff --git a/src/test/compile-fail/method-call-lifetime-args.rs b/src/test/compile-fail/method-call-lifetime-args.rs
new file mode 100644 (file)
index 0000000..75c469e
--- /dev/null
@@ -0,0 +1,33 @@
+// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+struct S;
+
+impl S {
+    fn late<'a, 'b>(self, _: &'a u8, _: &'b u8) {}
+    fn early<'a, 'b>(self) -> (&'a u8, &'b u8) { loop {} }
+    fn life_and_type<'a, T>(&self) -> &'a T { loop {} }
+}
+
+fn main() {
+    S.late(&0, &0); // OK
+    S.late::<'static>(&0, &0);
+    //~^ ERROR expected at most 0 lifetime parameters, found 1 lifetime parameter
+    S.late::<'static, 'static, 'static>(&0, &0);
+    //~^ ERROR expected at most 0 lifetime parameters, found 3 lifetime parameter
+    S.early(); // OK
+    S.early::<'static>();
+    //~^ ERROR expected 2 lifetime parameters, found 1 lifetime parameter
+    S.early::<'static, 'static, 'static>();
+    //~^ ERROR expected at most 2 lifetime parameters, found 3 lifetime parameters
+    let _: &u8 = S.life_and_type::<'static>();
+    S.life_and_type::<u8>();
+    S.life_and_type::<'static, u8>();
+}
index acffb06ebecf2cc4cbfdef6441e2cd8cf9d1190a..3ae878ed1cbc0659929d47885f8daaa90ce154ab 100644 (file)
@@ -9,5 +9,5 @@
 // except according to those terms.
 
 fn main() {
-    0.clone::<T = u8>(); //~ ERROR type bindings cannot be used in method calls
+    0.clone::<T = u8>(); //~ ERROR unexpected binding of associated item
 }
index 2d4df77f960452a126928ce40ee05fb108324012..b08aab6da852a71c6dfd3db0dce616c0d737a18b 100644 (file)
@@ -15,9 +15,8 @@ impl bar for i32 { fn dup(&self) -> i32 { *self } fn blah<X>(&self) {} }
 impl bar for u32 { fn dup(&self) -> u32 { *self } fn blah<X>(&self) {} }
 
 fn main() {
-    10.dup::<i32>(); //~ ERROR does not take type parameters
-    10.blah::<i32, i32>();
-    //~^ ERROR incorrect number of type parameters given for this method: expected 1, found 2
+    10.dup::<i32>(); //~ ERROR expected at most 0 type parameters, found 1 type parameter
+    10.blah::<i32, i32>(); //~ ERROR expected at most 1 type parameter, found 2 type parameters
     (box 10 as Box<bar>).dup();
     //~^ ERROR E0038
     //~| ERROR E0038