]> git.lizzy.rs Git - rust.git/commitdiff
Rollup merge of #43287 - kennytm:travis-ci-adjustments, r=alexcrichton
authorMark Simulacrum <mark.simulacrum@gmail.com>
Tue, 18 Jul 2017 15:41:31 +0000 (09:41 -0600)
committerGitHub <noreply@github.com>
Tue, 18 Jul 2017 15:41:31 +0000 (09:41 -0600)
Change Travis CI job order.

Reorder the job matrix to take advantage of the order how Travis CI starts them in rust-lang/rust. Plus other refactoring of `.travis.yml`.

1. Move the `$ALLOW_PR` image to the top, so pull requests will start testing as immediately after the build is started. Previously the `$ALLOW_PR` image starts 6 minutes after the build was scheduled.

2. Move the slow macOS images near the top, so they share more time with the rest of the faster Linux builds, which should shorten total test time (actually not much, about 7 minutes at most if this change does work).

3. Merged the `install` section of both Linux and macOS to make the `env:` section a bit shorter, and enable change 4 below.

4. Do not download or install anything if `$SKIP_BUILD == true`, which further reduces chance of spurious failure in the PR-CI stage (avoid the red cross appearing even if CI passed).

(IMO `$SKIP_BUILD` should not even exist: those irrelevant jobs should not start at all, but that would require travis-ci/travis-ci#2778 which has been rejected)

23 files changed:
CONTRIBUTING.md
src/libcore/fmt/mod.rs
src/librustc/ich/impls_ty.rs
src/librustc/lint/builtin.rs
src/librustc/ty/mod.rs
src/librustc_lint/lib.rs
src/librustc_passes/ast_validation.rs
src/librustc_typeck/check/method/confirm.rs
src/librustc_typeck/check/mod.rs
src/librustc_typeck/collect.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/E0088.rs
src/test/compile-fail/constructor-lifetime-args.rs [new file with mode: 0644]
src/test/compile-fail/method-call-lifetime-args-lint.rs [new file with mode: 0644]
src/test/compile-fail/method-call-lifetime-args-subst-index.rs [new file with mode: 0644]
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
src/test/incremental/hashes/inherent_impls.rs
src/test/incremental/hashes/trait_defs.rs

index 370cf6c0b43867b4b14971c551a6837cde254b73..04b6fea75a78a87d962e33aa961635832fd7a404 100644 (file)
@@ -289,7 +289,7 @@ been approved. The PR then enters the [merge queue][merge-queue], where @bors
 will run all the tests on every platform we support. If it all works out,
 @bors will merge your code into `master` and close the pull request.
 
-[merge-queue]: https://buildbot.rust-lang.org/homu/queue/rust
+[merge-queue]: https://buildbot2.rust-lang.org/homu/queue/rust
 
 Speaking of tests, Rust has a comprehensive test suite. More information about
 it can be found
index 750e86114c4bb057446f1024dcaff0a22d7b066d..193c8b9f925fbf0011f00e73860d6c0636b14291 100644 (file)
@@ -81,6 +81,22 @@ pub mod rt {
 /// This type does not support transmission of an error other than that an error
 /// occurred. Any extra information must be arranged to be transmitted through
 /// some other means.
+///
+/// An important thing to remember is that the type `fmt::Error` should not be
+/// confused with `std::io::Error` or `std::error::Error`, which you may also
+/// have in scope.
+///
+/// # Examples
+///
+/// ```rust
+/// use std::fmt::{self, write};
+///
+/// let mut output = String::new();
+/// match write(&mut output, format_args!("Hello {}!", "world")) {
+///     Err(fmt::Error) => panic!("An error occurred"),
+///     _ => (),
+/// }
+/// ```
 #[stable(feature = "rust1", since = "1.0.0")]
 #[derive(Copy, Clone, Debug, Default, Eq, Hash, Ord, PartialEq, PartialOrd)]
 pub struct Error;
index a1dd2caf786c207951ab26e97024d7e13734be44..3e227872848efb36efcd10ac1cde8ef167f5787e 100644 (file)
@@ -346,6 +346,7 @@ fn hash_stable<W: StableHasherResult>(&self,
             // `def_id.index` (`def_id.krate` is the same as the item's).
             type_param_to_index: _, // Don't hash this
             has_self,
+            has_late_bound_regions,
         } = *self;
 
         parent.hash_stable(hcx, hasher);
@@ -354,6 +355,7 @@ fn hash_stable<W: StableHasherResult>(&self,
         regions.hash_stable(hcx, hasher);
         types.hash_stable(hcx, hasher);
         has_self.hash_stable(hcx, hasher);
+        has_late_bound_regions.hash_stable(hcx, hasher);
     }
 }
 
index 2d088c4f6d1727729aaccd4d065e33b28669f985..cbe642a9a76a65b3afca29288f97de502778745e 100644 (file)
     "detects parenthesized generic parameters in type and module names"
 }
 
+declare_lint! {
+    pub LATE_BOUND_LIFETIME_ARGUMENTS,
+    Warn,
+    "detects generic lifetime arguments in path segments with late bound lifetime parameters"
+}
+
 declare_lint! {
     pub DEPRECATED,
     Warn,
@@ -249,6 +255,7 @@ fn get_lints(&self) -> LintArray {
             LEGACY_CONSTRUCTOR_VISIBILITY,
             MISSING_FRAGMENT_SPECIFIER,
             PARENTHESIZED_PARAMS_IN_TYPES_AND_MODULES,
+            LATE_BOUND_LIFETIME_ARGUMENTS,
             DEPRECATED
         )
     }
index 5aaba526e265f8a40b5494f0a49cb7dc592de58d..1fee0dd98634ae3af07784b751bb122348240322 100644 (file)
@@ -719,6 +719,7 @@ pub struct Generics {
     pub type_param_to_index: BTreeMap<DefIndex, u32>,
 
     pub has_self: bool,
+    pub has_late_bound_regions: bool,
 }
 
 impl Generics {
index a03f12c3dfbca09dd054c2f732c4a6cda7bcd5f9..21dca7f6c61c413234671a38817e6aabba2c9231 100644 (file)
@@ -235,7 +235,11 @@ macro_rules! add_lint_group {
         FutureIncompatibleInfo {
             id: LintId::of(PARENTHESIZED_PARAMS_IN_TYPES_AND_MODULES),
             reference: "issue #42238 <https://github.com/rust-lang/rust/issues/42238>",
-        }
+        },
+        FutureIncompatibleInfo {
+            id: LintId::of(LATE_BOUND_LIFETIME_ARGUMENTS),
+            reference: "issue #42868 <https://github.com/rust-lang/rust/issues/42868>",
+        },
         ]);
 
     // Register renamed and removed lints
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..ad4ee5a9d6dcf2c7dea25f84cf8c0616edc94a9a 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;
@@ -280,62 +281,38 @@ fn extract_existential_trait_ref<R, F>(&mut self, self_ty: Ty<'tcx>, mut closure
     fn instantiate_method_substs(&mut self,
                                  pick: &probe::Pick<'tcx>,
                                  segment: &hir::PathSegment,
-                                 substs: &Substs<'tcx>)
+                                 parent_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, true);
 
         // 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),
+        };
+        assert_eq!(method_generics.parent_count(), parent_substs.len());
         Substs::for_item(self.tcx, pick.item.def_id, |def, _| {
             let i = def.index as usize;
-            if i < substs.len() {
-                substs.region_at(i)
+            if i < parent_substs.len() {
+                parent_substs.region_at(i)
+            } else if let Some(lifetime) =
+                    supplied_lifetimes.get(i - parent_substs.len()) {
+                AstConv::ast_region_to_region(self.fcx, lifetime, Some(def))
             } else {
                 self.region_var_for_def(self.span, def)
             }
         }, |def, cur_substs| {
             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) {
+            if i < parent_substs.len() {
+                parent_substs.type_at(i)
+            } else if let Some(ast_ty) =
+                    supplied_types.get(i - parent_substs.len() - method_generics.regions.len()) {
                 self.to_ty(ast_ty)
             } else {
                 self.type_var_for_def(self.span, def, cur_substs)
index cdbe5e14e90948fabb469189226f1d6465283578..af11cacb247b6b6b90bef620d7a28e58b0768893 100644 (file)
@@ -4491,8 +4491,8 @@ pub fn instantiate_value_path(&self,
         // variables. If the user provided some types, we may still need
         // to add defaults. If the user provided *too many* types, that's
         // a problem.
-        self.check_path_parameter_count(span, &mut type_segment);
-        self.check_path_parameter_count(span, &mut fn_segment);
+        self.check_path_parameter_count(span, &mut type_segment, false);
+        self.check_path_parameter_count(span, &mut fn_segment, false);
 
         let (fn_start, has_self) = match (type_segment, fn_segment) {
             (_, Some((_, generics))) => {
@@ -4618,7 +4618,8 @@ pub fn instantiate_value_path(&self,
     /// Report errors if the provided parameters are too few or too many.
     fn check_path_parameter_count(&self,
                                   span: Span,
-                                  segment: &mut Option<(&hir::PathSegment, &ty::Generics)>) {
+                                  segment: &mut Option<(&hir::PathSegment, &ty::Generics)>,
+                                  is_method_call: bool) {
         let (lifetimes, types, infer_types, bindings) = {
             match segment.map(|(s, _)| &s.parameters) {
                 Some(&hir::AngleBracketedParameters(ref data)) => {
@@ -4632,6 +4633,7 @@ fn check_path_parameter_count(&self,
                 None => (&[][..], &[][..], true, &[][..])
             }
         };
+        let infer_lifetimes = lifetimes.len() == 0;
 
         let count_lifetime_params = |n| {
             format!("{} lifetime parameter{}", n, if n == 1 { "" } else { "s" })
@@ -4640,32 +4642,6 @@ fn check_path_parameter_count(&self,
             format!("{} type parameter{}", n, if n == 1 { "" } else { "s" })
         };
 
-        // Check provided lifetime parameters.
-        let lifetime_defs = segment.map_or(&[][..], |(_, generics)| &generics.regions);
-        if lifetimes.len() > lifetime_defs.len() {
-            let expected_text = count_lifetime_params(lifetime_defs.len());
-            let actual_text = count_lifetime_params(lifetimes.len());
-            struct_span_err!(self.tcx.sess, span, E0088,
-                             "too many lifetime parameters provided: \
-                              expected at most {}, found {}",
-                             expected_text, actual_text)
-                .span_label(span, format!("expected {}", expected_text))
-                .emit();
-        } else if lifetimes.len() > 0 && lifetimes.len() < lifetime_defs.len() {
-            let expected_text = count_lifetime_params(lifetime_defs.len());
-            let actual_text = count_lifetime_params(lifetimes.len());
-            struct_span_err!(self.tcx.sess, span, E0090,
-                             "too few lifetime parameters provided: \
-                              expected {}, found {}",
-                             expected_text, actual_text)
-                .span_label(span, format!("expected {}", expected_text))
-                .emit();
-        }
-
-        // The case where there is not enough lifetime parameters is not checked,
-        // because this is not possible - a function never takes lifetime parameters.
-        // See discussion for Pull Request 36208.
-
         // Check provided type parameters.
         let type_defs = segment.map_or(&[][..], |(_, generics)| {
             if generics.parent.is_none() {
@@ -4690,7 +4666,7 @@ fn check_path_parameter_count(&self,
             // type parameters, we force instantiate_value_path to
             // use inference variables instead of the provided types.
             *segment = None;
-        } else if !infer_types && types.len() < required_len {
+        } else if types.len() < required_len && !infer_types {
             let expected_text = count_type_params(required_len);
             let actual_text = count_type_params(types.len());
             struct_span_err!(self.tcx.sess, span, E0089,
@@ -4706,6 +4682,51 @@ fn check_path_parameter_count(&self,
                       "unexpected binding of associated item in expression path \
                        (only allowed in type paths)");
         }
+
+        // Check provided lifetime parameters.
+        let lifetime_defs = segment.map_or(&[][..], |(_, generics)| &generics.regions);
+        let required_len = lifetime_defs.len();
+
+        // Prohibit explicit lifetime arguments if late bound lifetime parameters are present.
+        let has_late_bound_lifetime_defs =
+            segment.map_or(false, |(_, generics)| generics.has_late_bound_regions);
+        if has_late_bound_lifetime_defs && !lifetimes.is_empty() {
+            // Report this as a lint only if no error was reported previously.
+            if !is_method_call && (lifetimes.len() > lifetime_defs.len() ||
+                                   lifetimes.len() < required_len && !infer_lifetimes) {
+                self.tcx.sess.span_err(lifetimes[0].span,
+                                       "cannot specify lifetime arguments explicitly \
+                                        if late bound lifetime parameters are present");
+                *segment = None;
+            } else {
+                self.tcx.sess.add_lint(lint::builtin::LATE_BOUND_LIFETIME_ARGUMENTS,
+                                       lifetimes[0].id, lifetimes[0].span,
+                                       format!("cannot specify lifetime arguments explicitly \
+                                                if late bound lifetime parameters are present"));
+            }
+            return;
+        }
+
+        if lifetimes.len() > lifetime_defs.len() {
+            let span = lifetimes[lifetime_defs.len()].span;
+            let expected_text = count_lifetime_params(lifetime_defs.len());
+            let actual_text = count_lifetime_params(lifetimes.len());
+            struct_span_err!(self.tcx.sess, span, E0088,
+                             "too many lifetime parameters provided: \
+                              expected at most {}, found {}",
+                             expected_text, actual_text)
+                .span_label(span, format!("expected {}", expected_text))
+                .emit();
+        } else if lifetimes.len() < required_len && !infer_lifetimes {
+            let expected_text = count_lifetime_params(lifetime_defs.len());
+            let actual_text = count_lifetime_params(lifetimes.len());
+            struct_span_err!(self.tcx.sess, span, E0090,
+                             "too few lifetime parameters provided: \
+                              expected {}, found {}",
+                             expected_text, actual_text)
+                .span_label(span, format!("expected {}", expected_text))
+                .emit();
+        }
     }
 
     fn structurally_resolve_type_or_else<F>(&self, sp: Span, ty: Ty<'tcx>, f: F)
index 002a148c459a3be506f7196e64ee7b91b8ab3f1b..72bd084330dd3ca62d92373d351431533685dd09 100644 (file)
@@ -772,6 +772,95 @@ fn trait_def<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
     tcx.alloc_trait_def(def)
 }
 
+fn has_late_bound_regions<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
+                                    node: hir_map::Node<'tcx>)
+                                    -> bool {
+    struct LateBoundRegionsDetector<'a, 'tcx: 'a> {
+        tcx: TyCtxt<'a, 'tcx, 'tcx>,
+        binder_depth: u32,
+        has_late_bound_regions: bool,
+    }
+
+    impl<'a, 'tcx> Visitor<'tcx> for LateBoundRegionsDetector<'a, 'tcx> {
+        fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'tcx> {
+            NestedVisitorMap::None
+        }
+
+        fn visit_ty(&mut self, ty: &'tcx hir::Ty) {
+            if self.has_late_bound_regions { return }
+            match ty.node {
+                hir::TyBareFn(..) => {
+                    self.binder_depth += 1;
+                    intravisit::walk_ty(self, ty);
+                    self.binder_depth -= 1;
+                }
+                _ => intravisit::walk_ty(self, ty)
+            }
+        }
+
+        fn visit_poly_trait_ref(&mut self,
+                                tr: &'tcx hir::PolyTraitRef,
+                                m: hir::TraitBoundModifier) {
+            if self.has_late_bound_regions { return }
+            self.binder_depth += 1;
+            intravisit::walk_poly_trait_ref(self, tr, m);
+            self.binder_depth -= 1;
+        }
+
+        fn visit_lifetime(&mut self, lt: &'tcx hir::Lifetime) {
+            if self.has_late_bound_regions { return }
+
+            match self.tcx.named_region_map.defs.get(&lt.id).cloned() {
+                Some(rl::Region::Static) | Some(rl::Region::EarlyBound(..)) => {}
+                Some(rl::Region::LateBound(debruijn, _)) |
+                Some(rl::Region::LateBoundAnon(debruijn, _))
+                    if debruijn.depth < self.binder_depth => {}
+                _ => self.has_late_bound_regions = true,
+            }
+        }
+    }
+
+    fn has_late_bound_regions<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
+                                        generics: &'tcx hir::Generics,
+                                        decl: &'tcx hir::FnDecl)
+                                        -> bool {
+        let mut visitor = LateBoundRegionsDetector {
+            tcx, binder_depth: 1, has_late_bound_regions: false
+        };
+        for lifetime in &generics.lifetimes {
+            if tcx.named_region_map.late_bound.contains(&lifetime.lifetime.id) {
+                return true;
+            }
+        }
+        visitor.visit_fn_decl(decl);
+        visitor.has_late_bound_regions
+    }
+
+    match node {
+        hir_map::NodeTraitItem(item) => match item.node {
+            hir::TraitItemKind::Method(ref sig, _) =>
+                has_late_bound_regions(tcx, &sig.generics, &sig.decl),
+            _ => false,
+        },
+        hir_map::NodeImplItem(item) => match item.node {
+            hir::ImplItemKind::Method(ref sig, _) =>
+                has_late_bound_regions(tcx, &sig.generics, &sig.decl),
+            _ => false,
+        },
+        hir_map::NodeForeignItem(item) => match item.node {
+            hir::ForeignItemFn(ref fn_decl, _, ref generics) =>
+                has_late_bound_regions(tcx, generics, fn_decl),
+            _ => false,
+        },
+        hir_map::NodeItem(item) => match item.node {
+            hir::ItemFn(ref fn_decl, .., ref generics, _) =>
+                has_late_bound_regions(tcx, generics, fn_decl),
+            _ => false,
+        },
+        _ => false
+    }
+}
+
 fn generics_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                          def_id: DefId)
                          -> &'tcx ty::Generics {
@@ -959,7 +1048,8 @@ fn generics_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
         regions: regions,
         types: types,
         type_param_to_index: type_param_to_index,
-        has_self: has_self || parent_has_self
+        has_self: has_self || parent_has_self,
+        has_late_bound_regions: has_late_bound_regions(tcx, node),
     })
 }
 
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
-}
index de188677a1121ba4513916fa06d8313b6dd92902..db84a4edc487c98914f839dd8e9f92415f2d8a65 100644 (file)
@@ -9,14 +9,9 @@
 // except according to those terms.
 
 fn f() {}
-fn g<'a>() {}
+fn g<'a>() -> &'a u8 { loop {} }
 
 fn main() {
-    f::<'static>();
-    //~^ ERROR expected at most 0 lifetime parameters, found 1 lifetime parameter [E0088]
-    //~| NOTE expected 0 lifetime parameters
-
-    g::<'static, 'static>();
-    //~^ ERROR expected at most 0 lifetime parameters, found 2 lifetime parameters [E0088]
-    //~| NOTE expected 0 lifetime parameters
+    f::<'static>(); //~ ERROR E0088
+    g::<'static, 'static>(); //~ ERROR E0088
 }
diff --git a/src/test/compile-fail/constructor-lifetime-args.rs b/src/test/compile-fail/constructor-lifetime-args.rs
new file mode 100644 (file)
index 0000000..50db970
--- /dev/null
@@ -0,0 +1,36 @@
+// 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.
+
+// All lifetime parameters in struct constructors are currently considered early bound,
+// i.e. `S::<ARGS>` is interpreted kinda like an associated item `S::<ARGS>::ctor`.
+// This behavior is a bit weird, because if equivalent constructor were written manually
+// it would get late bound lifetime parameters.
+// Variant constructors behave in the same way, lifetime parameters are considered
+// belonging to the enum and being early bound.
+// https://github.com/rust-lang/rust/issues/30904
+
+struct S<'a, 'b>(&'a u8, &'b u8);
+enum E<'a, 'b> {
+    V(&'a u8),
+    U(&'b u8),
+}
+
+fn main() {
+    S(&0, &0); // OK
+    S::<'static>(&0, &0);
+    //~^ ERROR expected 2 lifetime parameters, found 1 lifetime parameter
+    S::<'static, 'static, 'static>(&0, &0);
+    //~^ ERROR expected at most 2 lifetime parameters, found 3 lifetime parameters
+    E::V(&0); // OK
+    E::V::<'static>(&0);
+    //~^ ERROR expected 2 lifetime parameters, found 1 lifetime parameter
+    E::V::<'static, 'static, 'static>(&0);
+    //~^ ERROR expected at most 2 lifetime parameters, found 3 lifetime parameters
+}
diff --git a/src/test/compile-fail/method-call-lifetime-args-lint.rs b/src/test/compile-fail/method-call-lifetime-args-lint.rs
new file mode 100644 (file)
index 0000000..b2a94e0
--- /dev/null
@@ -0,0 +1,97 @@
+// 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.
+
+#![deny(late_bound_lifetime_arguments)]
+#![allow(unused)]
+
+struct S;
+
+impl S {
+    fn late<'a, 'b>(self, _: &'a u8, _: &'b u8) {}
+    fn late_implicit(self, _: &u8, _: &u8) {}
+    fn late_early<'a, 'b>(self, _: &'a u8) -> &'b u8 { loop {} }
+    fn late_implicit_early<'b>(self, _: &u8) -> &'b u8 { loop {} }
+
+    // 'late lifetimes here belong to nested types not to the tested functions.
+    fn early_tricky_explicit<'a>(_: for<'late> fn(&'late u8),
+                                 _: Box<for<'late> Fn(&'late u8)>)
+                                 -> &'a u8 { loop {} }
+    fn early_tricky_implicit<'a>(_: fn(&u8),
+                                 _: Box<Fn(&u8)>)
+                                 -> &'a u8 { loop {} }
+}
+
+fn method_call() {
+    S.late(&0, &0); // OK
+    S.late::<'static>(&0, &0);
+    //~^ ERROR cannot specify lifetime arguments explicitly
+    //~| WARN this was previously accepted
+    S.late::<'static, 'static>(&0, &0);
+    //~^ ERROR cannot specify lifetime arguments explicitly
+    //~| WARN this was previously accepted
+    S.late::<'static, 'static, 'static>(&0, &0);
+    //~^ ERROR cannot specify lifetime arguments explicitly
+    //~| WARN this was previously accepted
+    S.late_early(&0); // OK
+    S.late_early::<'static>(&0);
+    //~^ ERROR cannot specify lifetime arguments explicitly
+    //~| WARN this was previously accepted
+    S.late_early::<'static, 'static>(&0);
+    //~^ ERROR cannot specify lifetime arguments explicitly
+    //~| WARN this was previously accepted
+    S.late_early::<'static, 'static, 'static>(&0);
+    //~^ ERROR cannot specify lifetime arguments explicitly
+    //~| WARN this was previously accepted
+
+    S.late_implicit(&0, &0); // OK
+    S.late_implicit::<'static>(&0, &0);
+    //~^ ERROR cannot specify lifetime arguments explicitly
+    //~| WARN this was previously accepted
+    S.late_implicit::<'static, 'static>(&0, &0);
+    //~^ ERROR cannot specify lifetime arguments explicitly
+    //~| WARN this was previously accepted
+    S.late_implicit::<'static, 'static, 'static>(&0, &0);
+    //~^ ERROR cannot specify lifetime arguments explicitly
+    //~| WARN this was previously accepted
+    S.late_implicit_early(&0); // OK
+    S.late_implicit_early::<'static>(&0);
+    //~^ ERROR cannot specify lifetime arguments explicitly
+    //~| WARN this was previously accepted
+    S.late_implicit_early::<'static, 'static>(&0);
+    //~^ ERROR cannot specify lifetime arguments explicitly
+    //~| WARN this was previously accepted
+    S.late_implicit_early::<'static, 'static, 'static>(&0);
+    //~^ ERROR cannot specify lifetime arguments explicitly
+    //~| WARN this was previously accepted
+
+    S::early_tricky_explicit::<'static>(loop {}, loop {}); // OK
+    S::early_tricky_implicit::<'static>(loop {}, loop {}); // OK
+}
+
+fn ufcs() {
+    S::late_early::<'static>(S, &0);
+    //~^ ERROR cannot specify lifetime arguments explicitly
+    //~| WARN this was previously accepted
+
+    S::late_implicit_early::<'static>(S, &0);
+    //~^ ERROR cannot specify lifetime arguments explicitly
+    //~| WARN this was previously accepted
+}
+
+fn lint_not_inference_error() {
+    fn f<'early, 'late, T: 'early>() {}
+
+    // Make sure `u8` is substituted and not replaced with an inference variable
+    f::<'static, u8>;
+    //~^ ERROR cannot specify lifetime arguments explicitly
+    //~| WARN this was previously accepted
+}
+
+fn main() {}
diff --git a/src/test/compile-fail/method-call-lifetime-args-subst-index.rs b/src/test/compile-fail/method-call-lifetime-args-subst-index.rs
new file mode 100644 (file)
index 0000000..a9505e4
--- /dev/null
@@ -0,0 +1,25 @@
+// 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.
+
+#![feature(rustc_attrs)]
+#![allow(unused)]
+
+struct S;
+
+impl S {
+    fn early_and_type<'a, T>(self) -> &'a T { loop {} }
+}
+
+fn test() {
+    S.early_and_type::<u16>();
+}
+
+#[rustc_error]
+fn main() {} //~ ERROR compilation successful
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..f0a87c7
--- /dev/null
@@ -0,0 +1,82 @@
+// 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 late_implicit(self, _: &u8, _: &u8) {}
+    fn early<'a, 'b>(self) -> (&'a u8, &'b u8) { loop {} }
+    fn late_early<'a, 'b>(self, _: &'a u8) -> &'b u8 { loop {} }
+    fn late_implicit_early<'b>(self, _: &u8) -> &'b u8 { loop {} }
+    fn late_implicit_self_early<'b>(&self) -> &'b u8 { loop {} }
+    fn late_unused_early<'a, 'b>(self) -> &'b u8 { loop {} }
+    fn life_and_type<'a, T>(self) -> &'a T { loop {} }
+}
+
+fn method_call() {
+    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>();
+}
+
+fn ufcs() {
+    S::late(S, &0, &0); // OK
+    S::late::<'static>(S, &0, &0);
+    //~^ ERROR cannot specify lifetime arguments explicitly
+    S::late::<'static, 'static>(S, &0, &0);
+    //~^ ERROR cannot specify lifetime arguments explicitly
+    S::late::<'static, 'static, 'static>(S, &0, &0);
+    //~^ ERROR cannot specify lifetime arguments explicitly
+    S::late_early(S, &0); // OK
+    S::late_early::<'static, 'static>(S, &0);
+    //~^ ERROR cannot specify lifetime arguments explicitly
+    S::late_early::<'static, 'static, 'static>(S, &0);
+    //~^ ERROR cannot specify lifetime arguments explicitly
+
+    S::late_implicit(S, &0, &0); // OK
+    S::late_implicit::<'static>(S, &0, &0);
+    //~^ ERROR cannot specify lifetime arguments explicitly
+    S::late_implicit::<'static, 'static>(S, &0, &0);
+    //~^ ERROR cannot specify lifetime arguments explicitly
+    S::late_implicit::<'static, 'static, 'static>(S, &0, &0);
+    //~^ ERROR cannot specify lifetime arguments explicitly
+    S::late_implicit_early(S, &0); // OK
+    S::late_implicit_early::<'static, 'static>(S, &0);
+    //~^ ERROR cannot specify lifetime arguments explicitly
+    S::late_implicit_early::<'static, 'static, 'static>(S, &0);
+    //~^ ERROR cannot specify lifetime arguments explicitly
+    S::late_implicit_self_early(&S); // OK
+    S::late_implicit_self_early::<'static, 'static>(&S);
+    //~^ ERROR cannot specify lifetime arguments explicitly
+    S::late_implicit_self_early::<'static, 'static, 'static>(&S);
+    //~^ ERROR cannot specify lifetime arguments explicitly
+    S::late_unused_early(S); // OK
+    S::late_unused_early::<'static, 'static>(S);
+    //~^ ERROR cannot specify lifetime arguments explicitly
+    S::late_unused_early::<'static, 'static, 'static>(S);
+    //~^ ERROR cannot specify lifetime arguments explicitly
+
+    S::early(S); // OK
+    S::early::<'static>(S);
+    //~^ ERROR expected 2 lifetime parameters, found 1 lifetime parameter
+    S::early::<'static, 'static, 'static>(S);
+    //~^ ERROR expected at most 2 lifetime parameters, found 3 lifetime parameters
+    let _: &u8 = S::life_and_type::<'static>(S);
+    S::life_and_type::<u8>(S);
+    S::life_and_type::<'static, u8>(S);
+}
+
+fn main() {}
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
index 899aefa24a033b0e3d4eeeb666b96c7e3b9c86d2..daddc0c9f5459a3af5c09c80158be76b96651db5 100644 (file)
@@ -369,7 +369,7 @@ pub fn add_lifetime_parameter_to_method(&self) { }
 impl Foo {
     #[rustc_dirty(label="Hir", cfg="cfail2")]
     #[rustc_clean(label="Hir", cfg="cfail3")]
-    #[rustc_metadata_clean(cfg="cfail2")] // Apparently unused lifetimes don't show up in the type.
+    #[rustc_metadata_clean(cfg="cfail2")]
     #[rustc_metadata_clean(cfg="cfail3")]
     pub fn add_lifetime_parameter_to_method<'a>(&self) { }
 }
index e47556a790b62652835cc525e652fb5e69536da2..44950ee8a601f90865698e22d955bc9a07344bf5 100644 (file)
@@ -448,7 +448,7 @@ trait TraitAddLifetimeParameterToMethod {
 trait TraitAddLifetimeParameterToMethod {
     #[rustc_dirty(label="Hir", cfg="cfail2")]
     #[rustc_clean(label="Hir", cfg="cfail3")]
-    #[rustc_metadata_clean(cfg="cfail2")] // Unused lifetimes don't seem to show up in type?
+    #[rustc_metadata_dirty(cfg="cfail2")]
     #[rustc_metadata_clean(cfg="cfail3")]
     fn method<'a>();
 }