diff options
| author | Alexander Regueiro <alexreg@me.com> | 2018-11-01 21:52:56 +0000 |
|---|---|---|
| committer | Alexander Regueiro <alexreg@me.com> | 2018-11-03 04:28:29 +0000 |
| commit | 417168587beda80b97e9de83b61cbb8517a61dbc (patch) | |
| tree | 13b8a1b1fff49905f2abd8a5dabffd5b100f2506 | |
| parent | c04559fe9eb14e59cfe35c2676cd5d93a5eab326 (diff) | |
| download | rust-417168587beda80b97e9de83b61cbb8517a61dbc.tar.gz rust-417168587beda80b97e9de83b61cbb8517a61dbc.zip | |
Fixed bug with Self type param coming before lifetimes.
| -rw-r--r-- | src/librustc/middle/resolve_lifetime.rs | 19 | ||||
| -rw-r--r-- | src/librustc_typeck/collect.rs | 10 | ||||
| -rw-r--r-- | src/test/run-pass/traits/trait-alias-bounds.rs | 21 | ||||
| -rw-r--r-- | src/test/run-pass/traits/trait-alias-syntax.rs | 32 |
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() {} |
