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)
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
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, ..)
.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));
-// 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.
//
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;
--- /dev/null
+// 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() {}