]> git.lizzy.rs Git - rust.git/commitdiff
Fix incorrect subst index
authorVadim Petrochenkov <vadim.petrochenkov@gmail.com>
Tue, 11 Jul 2017 20:12:06 +0000 (23:12 +0300)
committerVadim Petrochenkov <vadim.petrochenkov@gmail.com>
Mon, 17 Jul 2017 21:12:48 +0000 (00:12 +0300)
Fix treatment of lifetimes defined in nested types during detection of late bound regions in signatures.
Do not replace substs with inference variables when "cannot specify lifetime arguments explicitly..." is reported as a lint.

src/librustc_typeck/check/method/confirm.rs
src/librustc_typeck/check/mod.rs
src/librustc_typeck/collect.rs
src/test/compile-fail/method-call-lifetime-args-lint.rs
src/test/compile-fail/method-call-lifetime-args-subst-index.rs [new file with mode: 0644]
src/test/compile-fail/method-call-lifetime-args.rs

index c28ddf876b3cda242b37a13ac25e5b8fe935c334..ad4ee5a9d6dcf2c7dea25f84cf8c0616edc94a9a 100644 (file)
@@ -281,7 +281,7 @@ 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> {
         // Determine the values for the generic parameters of the method.
         // If they were not explicitly supplied, just construct fresh
@@ -296,20 +296,23 @@ fn instantiate_method_substs(&mut self,
             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)
-            } else if let Some(lifetime) = supplied_lifetimes.get(i - substs.len()) {
+            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_types.get(i - substs.len()) {
+            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 917bffbc22f00ae8271fcc254d821966125ac51e..af11cacb247b6b6b90bef620d7a28e58b0768893 100644 (file)
@@ -4697,13 +4697,13 @@ fn check_path_parameter_count(&self,
                 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"));
             }
-            *segment = None;
             return;
         }
 
index 32ccfc511fc4bc38c572a1a52edd1db7f62028f0..72bd084330dd3ca62d92373d351431533685dd09 100644 (file)
@@ -777,7 +777,7 @@ fn has_late_bound_regions<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                                     -> bool {
     struct LateBoundRegionsDetector<'a, 'tcx: 'a> {
         tcx: TyCtxt<'a, 'tcx, 'tcx>,
-        binder_depth: usize,
+        binder_depth: u32,
         has_late_bound_regions: bool,
     }
 
@@ -812,7 +812,10 @@ fn visit_lifetime(&mut self, lt: &'tcx hir::Lifetime) {
 
             match self.tcx.named_region_map.defs.get(&lt.id).cloned() {
                 Some(rl::Region::Static) | Some(rl::Region::EarlyBound(..)) => {}
-                _ => self.has_late_bound_regions = true
+                Some(rl::Region::LateBound(debruijn, _)) |
+                Some(rl::Region::LateBoundAnon(debruijn, _))
+                    if debruijn.depth < self.binder_depth => {}
+                _ => self.has_late_bound_regions = true,
             }
         }
     }
@@ -822,7 +825,7 @@ fn has_late_bound_regions<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                                         decl: &'tcx hir::FnDecl)
                                         -> bool {
         let mut visitor = LateBoundRegionsDetector {
-            tcx, binder_depth: 0, has_late_bound_regions: false
+            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) {
index 9bf34de92fe8d33d6780500c63eb1dce98aebb5f..b206924e538f36d0521a281e917040b37688aa1f 100644 (file)
@@ -17,6 +17,14 @@ 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() {
@@ -61,6 +69,9 @@ fn method_call() {
     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() {
@@ -73,4 +84,13 @@ fn ufcs() {
     //~| 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
index c29701804a741b56cb7df3d3325d126c4c7e1fc0..f0a87c7470386b3f3500e2bead3446e0d3ef7ce7 100644 (file)
@@ -19,14 +19,6 @@ 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 {} }
-
-    // '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() {
@@ -85,9 +77,6 @@ fn ufcs() {
     let _: &u8 = S::life_and_type::<'static>(S);
     S::life_and_type::<u8>(S);
     S::life_and_type::<'static, u8>(S);
-
-    S::early_tricky_explicit::<'static>(loop {}, loop {}); // OK
-    S::early_tricky_implicit::<'static>(loop {}, loop {}); // OK
 }
 
 fn main() {}