about summary refs log tree commit diff
diff options
context:
space:
mode:
authorAlexander Regueiro <alexreg@me.com>2018-11-01 21:52:56 +0000
committerAlexander Regueiro <alexreg@me.com>2018-11-03 04:28:29 +0000
commit417168587beda80b97e9de83b61cbb8517a61dbc (patch)
tree13b8a1b1fff49905f2abd8a5dabffd5b100f2506
parentc04559fe9eb14e59cfe35c2676cd5d93a5eab326 (diff)
downloadrust-417168587beda80b97e9de83b61cbb8517a61dbc.tar.gz
rust-417168587beda80b97e9de83b61cbb8517a61dbc.zip
Fixed bug with Self type param coming before lifetimes.
-rw-r--r--src/librustc/middle/resolve_lifetime.rs19
-rw-r--r--src/librustc_typeck/collect.rs10
-rw-r--r--src/test/run-pass/traits/trait-alias-bounds.rs21
-rw-r--r--src/test/run-pass/traits/trait-alias-syntax.rs32
4 files changed, 52 insertions, 30 deletions
diff --git a/src/librustc/middle/resolve_lifetime.rs b/src/librustc/middle/resolve_lifetime.rs
index 361abb16896..a387765085a 100644
--- a/src/librustc/middle/resolve_lifetime.rs
+++ b/src/librustc/middle/resolve_lifetime.rs
@@ -447,6 +447,17 @@ fn krate<'tcx>(tcx: TyCtxt<'_, 'tcx, 'tcx>) -> NamedRegionMap {
     map
 }
 
+/// In traits, there is an implicit `Self` type parameter which comes before the generics.
+/// We have to account for this when computing the index of the other generic parameters.
+/// This function returns whether there is such an implicit parameter defined on the given item.
+fn sub_items_have_self_param(node: &hir::ItemKind) -> bool {
+    match *node {
+        hir::ItemKind::Trait(..) |
+        hir::ItemKind::TraitAlias(..) => true,
+        _ => false,
+    }
+}
+
 impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
     fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'tcx> {
         NestedVisitorMap::All(&self.tcx.hir)
@@ -522,8 +533,8 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
                     hir::ItemKind::Impl(..) => true,
                     _ => false,
                 };
-                // These kinds of items have only early bound lifetime parameters.
-                let mut index = if let hir::ItemKind::Trait(..) = item.node {
+                // These kinds of items have only early-bound lifetime parameters.
+                let mut index = if sub_items_have_self_param(&item.node) {
                     1 // Self comes before lifetimes
                 } else {
                     0
@@ -1602,8 +1613,8 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
         let mut index = 0;
         if let Some(parent_id) = parent_id {
             let parent = self.tcx.hir.expect_item(parent_id);
-            if let hir::ItemKind::Trait(..) = parent.node {
-                index += 1; // Self comes first.
+            if sub_items_have_self_param(&parent.node) {
+                index += 1; // Self comes before lifetimes
             }
             match parent.node {
                 hir::ItemKind::Trait(_, _, ref generics, ..)
diff --git a/src/librustc_typeck/collect.rs b/src/librustc_typeck/collect.rs
index 917fb887e0b..c136d76e358 100644
--- a/src/librustc_typeck/collect.rs
+++ b/src/librustc_typeck/collect.rs
@@ -357,14 +357,12 @@ impl<'a, 'tcx> ItemCtxt<'a, 'tcx> {
             .flat_map(|bp| {
                 let bt = if is_param(self.tcx, &bp.bounded_ty, param_id) {
                     Some(ty)
-                } else if only_self_bounds.0 {
-                    None
-                } else {
+                } else if !only_self_bounds.0 {
                     Some(self.to_ty(&bp.bounded_ty))
+                } else {
+                    None
                 };
-                bp.bounds.iter().filter_map(move |b| {
-                    if let Some(bt) = bt { Some((bt, b)) } else { None }
-                })
+                bp.bounds.iter().filter_map(move |b| bt.map(|bt| (bt, b)))
             })
             .flat_map(|(bt, b)| predicates_from_bound(self, bt, b));
 
diff --git a/src/test/run-pass/traits/trait-alias-bounds.rs b/src/test/run-pass/traits/trait-alias-bounds.rs
index c1c3989107b..d8ac1a8c634 100644
--- a/src/test/run-pass/traits/trait-alias-bounds.rs
+++ b/src/test/run-pass/traits/trait-alias-bounds.rs
@@ -1,4 +1,4 @@
-// Copyright 2017-2018 The Rust Project Developers. See the COPYRIGHT
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
 // file at the top-level directory of this distribution and at
 // http://rust-lang.org/COPYRIGHT.
 //
@@ -12,25 +12,6 @@
 
 use std::marker::PhantomData;
 
-trait SimpleAlias = Default;
-trait GenericAlias<T> = Iterator<Item = T>;
-trait Partial<T> = IntoIterator<Item = T>;
-trait SpecificAlias = GenericAlias<i32>;
-trait PartialEqRef<'a, T> = PartialEq<&'a T>;
-trait StaticAlias = 'static;
-
-trait Things<T> {}
-trait Romeo {}
-#[allow(dead_code)]
-struct The<T>(T);
-#[allow(dead_code)]
-struct Fore<T>(T);
-impl<T, U> Things<T> for The<U> {}
-impl<T> Romeo for Fore<T> {}
-
-trait WithWhere<Art, Thou> = Romeo + Romeo where Fore<(Art, Thou)>: Romeo;
-trait BareWhere<Wild, Are> = where The<Wild>: Things<Are>;
-
 trait Empty {}
 trait EmptyAlias = Empty;
 trait CloneDefault = Clone + Default;
diff --git a/src/test/run-pass/traits/trait-alias-syntax.rs b/src/test/run-pass/traits/trait-alias-syntax.rs
new file mode 100644
index 00000000000..a9b7afb0ea3
--- /dev/null
+++ b/src/test/run-pass/traits/trait-alias-syntax.rs
@@ -0,0 +1,32 @@
+// Copyright 2018 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(trait_alias)]
+
+trait SimpleAlias = Default;
+trait GenericAlias<T> = Iterator<Item = T>;
+trait Partial<T> = IntoIterator<Item = T>;
+trait SpecificAlias = GenericAlias<i32>;
+trait PartialEqRef<'a, T: 'a> = PartialEq<&'a T>;
+trait StaticAlias = 'static;
+
+trait Things<T> {}
+trait Romeo {}
+#[allow(dead_code)]
+struct The<T>(T);
+#[allow(dead_code)]
+struct Fore<T>(T);
+impl<T, U> Things<T> for The<U> {}
+impl<T> Romeo for Fore<T> {}
+
+trait WithWhere<Art, Thou> = Romeo + Romeo where Fore<(Art, Thou)>: Romeo;
+trait BareWhere<Wild, Are> = where The<Wild>: Things<Are>;
+
+fn main() {}