]> git.lizzy.rs Git - rust.git/commitdiff
Substitute type/lifetimeInstatiate method type/early-bound lifetime parameters too...
authorNiko Matsakis <niko@alum.mit.edu>
Thu, 6 Nov 2014 20:51:29 +0000 (15:51 -0500)
committerNiko Matsakis <niko@alum.mit.edu>
Mon, 17 Nov 2014 19:25:11 +0000 (14:25 -0500)
Fixes #18208.

src/librustc/middle/typeck/check/method/probe.rs
src/test/run-pass/method-early-bound-lifetimes-on-self.rs [new file with mode: 0644]

index 63f017e8041b1f8911689dd9f73af54e3218b15d..c07c6ebfc47c17ee4590e3f3dedc73cfc0204dc7 100644 (file)
@@ -827,6 +827,32 @@ fn xform_self_ty(&self, method: &Rc<ty::Method>, substs: &subst::Substs) -> ty::
                method.fty.sig.inputs[0].repr(self.tcx()),
                substs.repr(self.tcx()));
 
+        // It is possible for type parameters or early-bound lifetimes
+        // to appear in the signature of `self`. The substitutions we
+        // are given do not include type/lifetime parameters for the
+        // method yet. So create fresh variables here for those too,
+        // if there are any.
+        assert_eq!(substs.types.len(subst::FnSpace), 0);
+        assert_eq!(substs.regions().len(subst::FnSpace), 0);
+        let mut substs = substs;
+        let placeholder;
+        if
+            !method.generics.types.is_empty_in(subst::FnSpace) ||
+            !method.generics.regions.is_empty_in(subst::FnSpace)
+        {
+            let method_types =
+                self.infcx().next_ty_vars(
+                    method.generics.types.len(subst::FnSpace));
+
+            let method_regions =
+                self.infcx().region_vars_for_defs(
+                    self.span,
+                    method.generics.regions.get_slice(subst::FnSpace));
+
+            placeholder = (*substs).clone().with_method(method_types, method_regions);
+            substs = &placeholder;
+        }
+
         let xform_self_ty = method.fty.sig.inputs[0].subst(self.tcx(), substs);
         self.infcx().replace_late_bound_regions_with_fresh_var(method.fty.sig.binder_id,
                                                                self.span,
diff --git a/src/test/run-pass/method-early-bound-lifetimes-on-self.rs b/src/test/run-pass/method-early-bound-lifetimes-on-self.rs
new file mode 100644 (file)
index 0000000..25ce0d7
--- /dev/null
@@ -0,0 +1,34 @@
+// Copyright 2012 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.
+
+// Check that we successfully handle methods where the `self` type has
+// an early-bound lifetime. Issue #18208.
+
+#![allow(dead_code)]
+
+struct Cursor<'a>;
+
+trait CursorNavigator {
+    fn init_cursor<'a, 'b:'a>(&'a self, cursor: &mut Cursor<'b>) -> bool;
+}
+
+struct SimpleNavigator;
+
+impl CursorNavigator for SimpleNavigator {
+    fn init_cursor<'a, 'b: 'a>(&'a self, _cursor: &mut Cursor<'b>) -> bool {
+        false
+    }
+}
+
+fn main() {
+    let mut c = Cursor;
+    let n = SimpleNavigator;
+    n.init_cursor(&mut c);
+}