summaryrefslogtreecommitdiffstats
path: root/src/test/ui/associated-type-bounds
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-17 12:02:58 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-17 12:02:58 +0000
commit698f8c2f01ea549d77d7dc3338a12e04c11057b9 (patch)
tree173a775858bd501c378080a10dca74132f05bc50 /src/test/ui/associated-type-bounds
parentInitial commit. (diff)
downloadrustc-698f8c2f01ea549d77d7dc3338a12e04c11057b9.tar.xz
rustc-698f8c2f01ea549d77d7dc3338a12e04c11057b9.zip
Adding upstream version 1.64.0+dfsg1.upstream/1.64.0+dfsg1
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'src/test/ui/associated-type-bounds')
-rw-r--r--src/test/ui/associated-type-bounds/ambiguous-associated-type.rs12
-rw-r--r--src/test/ui/associated-type-bounds/ambiguous-associated-type2.rs10
-rw-r--r--src/test/ui/associated-type-bounds/ambiguous-associated-type2.stderr16
-rw-r--r--src/test/ui/associated-type-bounds/assoc-type-bound-through-where-clause.rs16
-rw-r--r--src/test/ui/associated-type-bounds/assoc-type-eq-with-dyn-atb-fail.rs36
-rw-r--r--src/test/ui/associated-type-bounds/assoc-type-eq-with-dyn-atb-fail.stderr9
-rw-r--r--src/test/ui/associated-type-bounds/associated-item-through-where-clause.rs21
-rw-r--r--src/test/ui/associated-type-bounds/auxiliary/fn-aux.rs177
-rw-r--r--src/test/ui/associated-type-bounds/auxiliary/fn-dyn-aux.rs182
-rw-r--r--src/test/ui/associated-type-bounds/bad-bounds-on-assoc-in-trait.rs67
-rw-r--r--src/test/ui/associated-type-bounds/bad-bounds-on-assoc-in-trait.stderr39
-rw-r--r--src/test/ui/associated-type-bounds/binder-on-bound.rs11
-rw-r--r--src/test/ui/associated-type-bounds/binder-on-bound.stderr8
-rw-r--r--src/test/ui/associated-type-bounds/bounds-on-assoc-in-trait.rs54
-rw-r--r--src/test/ui/associated-type-bounds/bounds-on-assoc-in-trait.stderr26
-rw-r--r--src/test/ui/associated-type-bounds/duplicate.rs256
-rw-r--r--src/test/ui/associated-type-bounds/duplicate.stderr483
-rw-r--r--src/test/ui/associated-type-bounds/dyn-impl-trait-type.rs66
-rw-r--r--src/test/ui/associated-type-bounds/dyn-rpit-and-let.rs73
-rw-r--r--src/test/ui/associated-type-bounds/elision.rs9
-rw-r--r--src/test/ui/associated-type-bounds/elision.stderr28
-rw-r--r--src/test/ui/associated-type-bounds/entails-sized-object-safety.rs26
-rw-r--r--src/test/ui/associated-type-bounds/enum-bounds.rs123
-rw-r--r--src/test/ui/associated-type-bounds/fn-apit.rs59
-rw-r--r--src/test/ui/associated-type-bounds/fn-aux.rs12
-rw-r--r--src/test/ui/associated-type-bounds/fn-dyn-apit.rs61
-rw-r--r--src/test/ui/associated-type-bounds/fn-inline.rs63
-rw-r--r--src/test/ui/associated-type-bounds/fn-where.rs79
-rw-r--r--src/test/ui/associated-type-bounds/fn-wrap-apit.rs65
-rw-r--r--src/test/ui/associated-type-bounds/handle-predicates-that-can-define-assoc-type.rs10
-rw-r--r--src/test/ui/associated-type-bounds/hrtb.rs65
-rw-r--r--src/test/ui/associated-type-bounds/implied-region-constraints.rs45
-rw-r--r--src/test/ui/associated-type-bounds/implied-region-constraints.stderr28
-rw-r--r--src/test/ui/associated-type-bounds/inside-adt.rs30
-rw-r--r--src/test/ui/associated-type-bounds/inside-adt.stderr131
-rw-r--r--src/test/ui/associated-type-bounds/issue-61752.rs24
-rw-r--r--src/test/ui/associated-type-bounds/issue-70292.rs21
-rw-r--r--src/test/ui/associated-type-bounds/issue-71443-1.rs9
-rw-r--r--src/test/ui/associated-type-bounds/issue-71443-1.stderr11
-rw-r--r--src/test/ui/associated-type-bounds/issue-71443-2.rs11
-rw-r--r--src/test/ui/associated-type-bounds/issue-73818.rs25
-rw-r--r--src/test/ui/associated-type-bounds/issue-79949.rs26
-rw-r--r--src/test/ui/associated-type-bounds/issue-81193.rs15
-rw-r--r--src/test/ui/associated-type-bounds/issue-83017.rs39
-rw-r--r--src/test/ui/associated-type-bounds/issue-99828.rs11
-rw-r--r--src/test/ui/associated-type-bounds/issue-99828.stderr24
-rw-r--r--src/test/ui/associated-type-bounds/missing-trait-bound-for-assoc-fails.rs10
-rw-r--r--src/test/ui/associated-type-bounds/missing-trait-bound-for-assoc-fails.stderr16
-rw-r--r--src/test/ui/associated-type-bounds/order-dependent-bounds-issue-54121.rs47
-rw-r--r--src/test/ui/associated-type-bounds/rpit.rs64
-rw-r--r--src/test/ui/associated-type-bounds/struct-bounds.rs116
-rw-r--r--src/test/ui/associated-type-bounds/supertrait-referencing-self.rs12
-rw-r--r--src/test/ui/associated-type-bounds/supertrait-referencing.rs19
-rw-r--r--src/test/ui/associated-type-bounds/supertrait-where-referencing-self.rs27
-rw-r--r--src/test/ui/associated-type-bounds/trait-alias-impl-trait.rs96
-rw-r--r--src/test/ui/associated-type-bounds/trait-params.rs116
-rw-r--r--src/test/ui/associated-type-bounds/traits-assoc-anonymized.rs33
-rw-r--r--src/test/ui/associated-type-bounds/traits-assoc-type-macros.rs43
-rw-r--r--src/test/ui/associated-type-bounds/type-alias.rs19
-rw-r--r--src/test/ui/associated-type-bounds/type-alias.stderr147
-rw-r--r--src/test/ui/associated-type-bounds/union-bounds.rs123
61 files changed, 3500 insertions, 0 deletions
diff --git a/src/test/ui/associated-type-bounds/ambiguous-associated-type.rs b/src/test/ui/associated-type-bounds/ambiguous-associated-type.rs
new file mode 100644
index 000000000..9c47a003d
--- /dev/null
+++ b/src/test/ui/associated-type-bounds/ambiguous-associated-type.rs
@@ -0,0 +1,12 @@
+// check-pass
+
+#![feature(associated_type_bounds)]
+
+pub struct Flatten<I>
+where
+ I: Iterator<Item: IntoIterator>,
+{
+ inner: <I::Item as IntoIterator>::IntoIter,
+}
+
+fn main() {}
diff --git a/src/test/ui/associated-type-bounds/ambiguous-associated-type2.rs b/src/test/ui/associated-type-bounds/ambiguous-associated-type2.rs
new file mode 100644
index 000000000..48de59334
--- /dev/null
+++ b/src/test/ui/associated-type-bounds/ambiguous-associated-type2.rs
@@ -0,0 +1,10 @@
+trait Foo {
+ type Item;
+}
+trait Bar<T> {
+ type Item;
+}
+trait Baz: Foo + Bar<Self::Item> {}
+//~^ ERROR cycle detected when computing the super traits of `Baz` with associated type name `Item` [E0391]
+
+fn main() {}
diff --git a/src/test/ui/associated-type-bounds/ambiguous-associated-type2.stderr b/src/test/ui/associated-type-bounds/ambiguous-associated-type2.stderr
new file mode 100644
index 000000000..4162cdaa8
--- /dev/null
+++ b/src/test/ui/associated-type-bounds/ambiguous-associated-type2.stderr
@@ -0,0 +1,16 @@
+error[E0391]: cycle detected when computing the super traits of `Baz` with associated type name `Item`
+ --> $DIR/ambiguous-associated-type2.rs:7:1
+ |
+LL | trait Baz: Foo + Bar<Self::Item> {}
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+ = note: ...which immediately requires computing the super traits of `Baz` with associated type name `Item` again
+note: cycle used when computing the super traits of `Baz`
+ --> $DIR/ambiguous-associated-type2.rs:7:1
+ |
+LL | trait Baz: Foo + Bar<Self::Item> {}
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0391`.
diff --git a/src/test/ui/associated-type-bounds/assoc-type-bound-through-where-clause.rs b/src/test/ui/associated-type-bounds/assoc-type-bound-through-where-clause.rs
new file mode 100644
index 000000000..49f111407
--- /dev/null
+++ b/src/test/ui/associated-type-bounds/assoc-type-bound-through-where-clause.rs
@@ -0,0 +1,16 @@
+// Check that `where Self::Output: Copy` is turned into a bound on `Op::Output`.
+
+//check-pass
+
+trait Op
+where
+ Self::Output: Copy,
+{
+ type Output;
+}
+
+fn duplicate<T: Op>(x: T::Output) -> (T::Output, T::Output) {
+ (x, x)
+}
+
+fn main() {}
diff --git a/src/test/ui/associated-type-bounds/assoc-type-eq-with-dyn-atb-fail.rs b/src/test/ui/associated-type-bounds/assoc-type-eq-with-dyn-atb-fail.rs
new file mode 100644
index 000000000..4c36289f4
--- /dev/null
+++ b/src/test/ui/associated-type-bounds/assoc-type-eq-with-dyn-atb-fail.rs
@@ -0,0 +1,36 @@
+// This test documents that `type Out = Box<dyn Bar<Assoc: Copy>>;`
+// is allowed and will correctly reject an opaque `type Out` which
+// does not satisfy the bound `<TheType as Bar>::Assoc: Copy`.
+//
+// FIXME(rust-lang/lang): I think this behavior is logical if we want to allow
+// `dyn Trait<Assoc: Bound>` but we should decide if we want that. // Centril
+//
+// Additionally, as reported in https://github.com/rust-lang/rust/issues/63594,
+// we check that the spans for the error message are sane here.
+
+#![feature(associated_type_bounds)]
+
+fn main() {}
+
+trait Bar {
+ type Assoc;
+}
+
+trait Thing {
+ type Out;
+ fn func() -> Self::Out;
+}
+
+struct AssocNoCopy;
+impl Bar for AssocNoCopy {
+ type Assoc = String;
+}
+
+impl Thing for AssocNoCopy {
+ type Out = Box<dyn Bar<Assoc: Copy>>;
+
+ fn func() -> Self::Out {
+ //~^ ERROR the trait bound `String: Copy` is not satisfied
+ Box::new(AssocNoCopy)
+ }
+}
diff --git a/src/test/ui/associated-type-bounds/assoc-type-eq-with-dyn-atb-fail.stderr b/src/test/ui/associated-type-bounds/assoc-type-eq-with-dyn-atb-fail.stderr
new file mode 100644
index 000000000..a32ab4531
--- /dev/null
+++ b/src/test/ui/associated-type-bounds/assoc-type-eq-with-dyn-atb-fail.stderr
@@ -0,0 +1,9 @@
+error[E0277]: the trait bound `String: Copy` is not satisfied
+ --> $DIR/assoc-type-eq-with-dyn-atb-fail.rs:32:18
+ |
+LL | fn func() -> Self::Out {
+ | ^^^^^^^^^ the trait `Copy` is not implemented for `String`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/associated-type-bounds/associated-item-through-where-clause.rs b/src/test/ui/associated-type-bounds/associated-item-through-where-clause.rs
new file mode 100644
index 000000000..3eb50ab55
--- /dev/null
+++ b/src/test/ui/associated-type-bounds/associated-item-through-where-clause.rs
@@ -0,0 +1,21 @@
+// check-pass
+
+trait Foo {
+ type Item;
+}
+
+trait Bar
+where
+ Self: Foo,
+{
+}
+
+#[allow(dead_code)]
+fn foo<M>(_m: M)
+where
+ M: Bar,
+ M::Item: Send,
+{
+}
+
+fn main() {}
diff --git a/src/test/ui/associated-type-bounds/auxiliary/fn-aux.rs b/src/test/ui/associated-type-bounds/auxiliary/fn-aux.rs
new file mode 100644
index 000000000..0ea23ad1d
--- /dev/null
+++ b/src/test/ui/associated-type-bounds/auxiliary/fn-aux.rs
@@ -0,0 +1,177 @@
+// Traits:
+
+pub trait Alpha {
+ fn alpha(self) -> usize;
+}
+
+pub trait Beta {
+ type Gamma;
+ fn gamma(self) -> Self::Gamma;
+}
+
+pub trait Delta {
+ fn delta(self) -> usize;
+}
+
+pub trait Epsilon<'a> {
+ type Zeta;
+ fn zeta(&'a self) -> Self::Zeta;
+
+ fn epsilon(&'a self) -> usize;
+}
+
+pub trait Eta {
+ fn eta(self) -> usize;
+}
+
+// Assertions:
+
+pub fn assert_alpha<T: Alpha>(x: T) -> usize { x.alpha() }
+pub fn assert_static<T: 'static>(_: T) -> usize { 24 }
+pub fn assert_delta<T: Delta>(x: T) -> usize { x.delta() }
+pub fn assert_epsilon_specific<'a, T: 'a + Epsilon<'a>>(x: &'a T) -> usize { x.epsilon() }
+pub fn assert_epsilon_forall<T: for<'a> Epsilon<'a>>() {}
+pub fn assert_forall_epsilon_zeta_satisfies_eta<T>(x: T) -> usize
+where
+ T: for<'a> Epsilon<'a>,
+ for<'a> <T as Epsilon<'a>>::Zeta: Eta,
+{
+ x.epsilon() + x.zeta().eta()
+}
+
+// Implementations and types:
+
+#[derive(Copy, Clone)]
+pub struct BetaType;
+
+#[derive(Copy, Clone)]
+pub struct GammaType;
+
+#[derive(Copy, Clone)]
+pub struct ZetaType;
+
+impl Beta for BetaType {
+ type Gamma = GammaType;
+ fn gamma(self) -> Self::Gamma { GammaType }
+}
+
+impl<'a> Beta for &'a BetaType {
+ type Gamma = GammaType;
+ fn gamma(self) -> Self::Gamma { GammaType }
+}
+
+impl Beta for GammaType {
+ type Gamma = Self;
+ fn gamma(self) -> Self::Gamma { self }
+}
+
+impl Alpha for GammaType {
+ fn alpha(self) -> usize { 42 }
+}
+
+impl Delta for GammaType {
+ fn delta(self) -> usize { 1337 }
+}
+
+impl<'a> Epsilon<'a> for GammaType {
+ type Zeta = ZetaType;
+ fn zeta(&'a self) -> Self::Zeta { ZetaType }
+
+ fn epsilon(&'a self) -> usize { 7331 }
+}
+
+impl Eta for ZetaType {
+ fn eta(self) -> usize { 7 }
+}
+
+// Desugared forms to check against:
+
+pub fn desugared_bound<B>(beta: B) -> usize
+where
+ B: Beta,
+ B::Gamma: Alpha
+{
+ let gamma: B::Gamma = beta.gamma();
+ assert_alpha::<B::Gamma>(gamma)
+}
+
+pub fn desugared_bound_region<B>(beta: B) -> usize
+where
+ B: Beta,
+ B::Gamma: 'static,
+{
+ assert_static::<B::Gamma>(beta.gamma())
+}
+
+pub fn desugared_bound_multi<B>(beta: B) -> usize
+where
+ B: Copy + Beta,
+ B::Gamma: Alpha + 'static + Delta,
+{
+ assert_alpha::<B::Gamma>(beta.gamma()) +
+ assert_static::<B::Gamma>(beta.gamma()) +
+ assert_delta::<B::Gamma>(beta.gamma())
+}
+
+pub fn desugared_bound_region_specific<'a, B>(gamma: &'a B::Gamma) -> usize
+where
+ B: Beta,
+ B::Gamma: 'a + Epsilon<'a>,
+{
+ assert_epsilon_specific::<B::Gamma>(gamma)
+}
+
+pub fn desugared_bound_region_forall<B>(beta: B) -> usize
+where
+ B: Beta,
+ B::Gamma: Copy + for<'a> Epsilon<'a>,
+{
+ assert_epsilon_forall::<B::Gamma>();
+ let g1: B::Gamma = beta.gamma();
+ let g2: B::Gamma = g1;
+ assert_epsilon_specific::<B::Gamma>(&g1) +
+ assert_epsilon_specific::<B::Gamma>(&g2)
+}
+
+pub fn desugared_bound_region_forall2<B>(beta: B) -> usize
+where
+ B: Beta,
+ B::Gamma: Copy + for<'a> Epsilon<'a>,
+ for<'a> <B::Gamma as Epsilon<'a>>::Zeta: Eta,
+{
+ let gamma = beta.gamma();
+ assert_forall_epsilon_zeta_satisfies_eta::<B::Gamma>(gamma)
+}
+
+pub fn desugared_contraint_region_forall<B>(beta: B) -> usize
+where
+ for<'a> &'a B: Beta,
+ for<'a> <&'a B as Beta>::Gamma: Alpha,
+{
+ let g1 = beta.gamma();
+ let g2 = beta.gamma();
+ assert_alpha(g1) + assert_alpha(g2)
+}
+
+pub fn desugared_bound_nested<B>(beta: B) -> usize
+where
+ B: Beta,
+ B::Gamma: Copy + Alpha + Beta,
+ <B::Gamma as Beta>::Gamma: Delta,
+{
+ let go = beta.gamma();
+ let gi = go.gamma();
+ go.alpha() + gi.delta()
+}
+
+pub fn desugared() {
+ let beta = BetaType;
+ let gamma = beta.gamma();
+
+ assert_eq!(42, desugared_bound(beta));
+ assert_eq!(24, desugared_bound_region(beta));
+ assert_eq!(42 + 24 + 1337, desugared_bound_multi(beta));
+ assert_eq!(7331, desugared_bound_region_specific::<BetaType>(&gamma));
+ assert_eq!(7331 * 2, desugared_bound_region_forall(beta));
+ assert_eq!(42 + 1337, desugared_bound_nested(beta));
+}
diff --git a/src/test/ui/associated-type-bounds/auxiliary/fn-dyn-aux.rs b/src/test/ui/associated-type-bounds/auxiliary/fn-dyn-aux.rs
new file mode 100644
index 000000000..85d6c5aaf
--- /dev/null
+++ b/src/test/ui/associated-type-bounds/auxiliary/fn-dyn-aux.rs
@@ -0,0 +1,182 @@
+// Traits:
+
+pub trait Alpha {
+ fn alpha(self) -> usize;
+}
+
+pub trait Beta {
+ type Gamma;
+ fn gamma(&self) -> Self::Gamma;
+}
+
+pub trait Delta {
+ fn delta(self) -> usize;
+}
+
+pub trait Epsilon<'a> {
+ type Zeta;
+ fn zeta(&'a self) -> Self::Zeta;
+
+ fn epsilon(&'a self) -> usize;
+}
+
+pub trait Eta {
+ fn eta(self) -> usize;
+}
+
+// Assertions:
+
+pub fn assert_alpha<T: Alpha>(x: T) -> usize { x.alpha() }
+pub fn assert_static<T: 'static>(_: T) -> usize { 24 }
+pub fn assert_delta<T: Delta>(x: T) -> usize { x.delta() }
+pub fn assert_epsilon_specific<'a, T: 'a + Epsilon<'a>>(x: &'a T) -> usize { x.epsilon() }
+pub fn assert_epsilon_forall<T: for<'a> Epsilon<'a>>() {}
+pub fn assert_forall_epsilon_zeta_satisfies_eta<T>(x: T) -> usize
+where
+ T: for<'a> Epsilon<'a>,
+ for<'a> <T as Epsilon<'a>>::Zeta: Eta,
+{
+ x.epsilon() + x.zeta().eta()
+}
+
+// Implementations and types:
+
+#[derive(Copy, Clone)]
+pub struct BetaType;
+
+#[derive(Copy, Clone)]
+pub struct GammaType;
+
+#[derive(Copy, Clone)]
+pub struct ZetaType;
+
+impl<T> Beta for &(dyn Beta<Gamma = T> + Send) {
+ type Gamma = T;
+ fn gamma(&self) -> Self::Gamma { (*self).gamma() }
+}
+
+impl Beta for BetaType {
+ type Gamma = GammaType;
+ fn gamma(&self) -> Self::Gamma { GammaType }
+}
+
+impl<'a> Beta for &'a BetaType {
+ type Gamma = GammaType;
+ fn gamma(&self) -> Self::Gamma { GammaType }
+}
+
+impl Beta for GammaType {
+ type Gamma = Self;
+ fn gamma(&self) -> Self::Gamma { Self }
+}
+
+impl Alpha for GammaType {
+ fn alpha(self) -> usize { 42 }
+}
+
+impl Delta for GammaType {
+ fn delta(self) -> usize { 1337 }
+}
+
+impl<'a> Epsilon<'a> for GammaType {
+ type Zeta = ZetaType;
+ fn zeta(&'a self) -> Self::Zeta { ZetaType }
+
+ fn epsilon(&'a self) -> usize { 7331 }
+}
+
+impl Eta for ZetaType {
+ fn eta(self) -> usize { 7 }
+}
+
+// Desugared forms to check against:
+
+pub fn desugared_bound<B: ?Sized>(beta: &B) -> usize
+where
+ B: Beta,
+ B::Gamma: Alpha
+{
+ let gamma: B::Gamma = beta.gamma();
+ assert_alpha::<B::Gamma>(gamma)
+}
+
+pub fn desugared_bound_region<B: ?Sized>(beta: &B) -> usize
+where
+ B: Beta,
+ B::Gamma: 'static,
+{
+ assert_static::<B::Gamma>(beta.gamma())
+}
+
+pub fn desugared_bound_multi<B: ?Sized>(beta: B) -> usize
+where
+ B: Copy + Beta,
+ B::Gamma: Alpha + 'static + Delta,
+{
+ assert_alpha::<B::Gamma>(beta.gamma()) +
+ assert_static::<B::Gamma>(beta.gamma()) +
+ assert_delta::<B::Gamma>(beta.gamma())
+}
+
+pub fn desugared_bound_region_specific<'a, B: ?Sized>(gamma: &'a B::Gamma) -> usize
+where
+ B: Beta,
+ B::Gamma: 'a + Epsilon<'a>,
+{
+ assert_epsilon_specific::<B::Gamma>(gamma)
+}
+
+pub fn desugared_bound_region_forall<B: ?Sized>(beta: &B) -> usize
+where
+ B: Beta,
+ B::Gamma: Copy + for<'a> Epsilon<'a>,
+{
+ assert_epsilon_forall::<B::Gamma>();
+ let g1: B::Gamma = beta.gamma();
+ let g2: B::Gamma = g1;
+ assert_epsilon_specific::<B::Gamma>(&g1) +
+ assert_epsilon_specific::<B::Gamma>(&g2)
+}
+
+pub fn desugared_bound_region_forall2<B: ?Sized>(beta: &B) -> usize
+where
+ B: Beta,
+ B::Gamma: Copy + for<'a> Epsilon<'a>,
+ for<'a> <B::Gamma as Epsilon<'a>>::Zeta: Eta,
+{
+ let gamma = beta.gamma();
+ assert_forall_epsilon_zeta_satisfies_eta::<B::Gamma>(gamma)
+}
+
+pub fn desugared_contraint_region_forall<B: ?Sized>(beta: &B) -> usize
+where
+ for<'a> &'a B: Beta,
+ for<'a> <&'a B as Beta>::Gamma: Alpha,
+{
+ let g1 = beta.gamma();
+ let g2 = beta.gamma();
+ assert_alpha(g1) + assert_alpha(g2)
+}
+
+pub fn desugared_bound_nested<B: ?Sized>(beta: &B) -> usize
+where
+ B: Beta,
+ B::Gamma: Copy + Alpha + Beta,
+ <B::Gamma as Beta>::Gamma: Delta,
+{
+ let go = beta.gamma();
+ let gi = go.gamma();
+ go.alpha() + gi.delta()
+}
+
+pub fn desugared() {
+ let beta = BetaType;
+ let gamma = beta.gamma();
+
+ assert_eq!(42, desugared_bound(&beta));
+ assert_eq!(24, desugared_bound_region(&beta));
+ assert_eq!(42 + 24 + 1337, desugared_bound_multi(beta));
+ assert_eq!(7331, desugared_bound_region_specific::<BetaType>(&gamma));
+ assert_eq!(7331 * 2, desugared_bound_region_forall(&beta));
+ assert_eq!(42 + 1337, desugared_bound_nested(&beta));
+}
diff --git a/src/test/ui/associated-type-bounds/bad-bounds-on-assoc-in-trait.rs b/src/test/ui/associated-type-bounds/bad-bounds-on-assoc-in-trait.rs
new file mode 100644
index 000000000..d180de9be
--- /dev/null
+++ b/src/test/ui/associated-type-bounds/bad-bounds-on-assoc-in-trait.rs
@@ -0,0 +1,67 @@
+// NOTE: rustc cannot currently handle bounds of the form `for<'a> <Foo as Bar<'a>>::Assoc: Baz`.
+// This should hopefully be fixed with Chalk.
+
+#![feature(associated_type_bounds)]
+
+use std::fmt::Debug;
+use std::iter::Once;
+
+trait Lam<Binder> {
+ type App;
+}
+
+#[derive(Clone)]
+struct L1;
+impl<'a> Lam<&'a u8> for L1 {
+ type App = u8;
+}
+
+#[derive(Clone)]
+struct L2;
+impl<'a, 'b> Lam<&'a &'b u8> for L2 {
+ type App = u8;
+}
+
+trait Case1 {
+ type C: Clone + Iterator<Item: Send + Iterator<Item: for<'a> Lam<&'a u8, App: Debug>> + Sync>;
+ //~^ ERROR `<<Self as Case1>::C as Iterator>::Item` is not an iterator
+ //~| ERROR `<<Self as Case1>::C as Iterator>::Item` cannot be sent between threads safely
+ //~| ERROR `<<Self as Case1>::C as Iterator>::Item` cannot be shared between threads safely
+}
+
+pub struct S1;
+impl Case1 for S1 {
+ type C = Once<Once<L1>>;
+}
+
+fn assume_case1<T: Case1>() {
+ fn assert_a<_0, A>()
+ where
+ A: Iterator<Item = _0>,
+ _0: Debug,
+ {
+ }
+ assert_a::<_, T::A>();
+
+ fn assert_b<_0, B>()
+ where
+ B: Iterator<Item = _0>,
+ _0: 'static,
+ {
+ }
+ assert_b::<_, T::B>();
+
+ fn assert_c<_0, _1, _2, C>()
+ where
+ C: Clone + Iterator<Item = _2>,
+ _2: Send + Iterator<Item = _1>,
+ _1: for<'a> Lam<&'a u8, App = _0>,
+ _0: Debug,
+ {
+ }
+ assert_c::<_, _, _, T::C>();
+}
+
+fn main() {
+ assume_case1(S1);
+}
diff --git a/src/test/ui/associated-type-bounds/bad-bounds-on-assoc-in-trait.stderr b/src/test/ui/associated-type-bounds/bad-bounds-on-assoc-in-trait.stderr
new file mode 100644
index 000000000..c23e54594
--- /dev/null
+++ b/src/test/ui/associated-type-bounds/bad-bounds-on-assoc-in-trait.stderr
@@ -0,0 +1,39 @@
+error[E0277]: `<<Self as Case1>::C as Iterator>::Item` cannot be sent between threads safely
+ --> $DIR/bad-bounds-on-assoc-in-trait.rs:26:36
+ |
+LL | type C: Clone + Iterator<Item: Send + Iterator<Item: for<'a> Lam<&'a u8, App: Debug>> + Sync>;
+ | ^^^^ `<<Self as Case1>::C as Iterator>::Item` cannot be sent between threads safely
+ |
+ = help: the trait `Send` is not implemented for `<<Self as Case1>::C as Iterator>::Item`
+help: consider further restricting the associated type
+ |
+LL | trait Case1 where <<Self as Case1>::C as Iterator>::Item: Send {
+ | ++++++++++++++++++++++++++++++++++++++++++++++++++
+
+error[E0277]: `<<Self as Case1>::C as Iterator>::Item` is not an iterator
+ --> $DIR/bad-bounds-on-assoc-in-trait.rs:26:43
+ |
+LL | type C: Clone + Iterator<Item: Send + Iterator<Item: for<'a> Lam<&'a u8, App: Debug>> + Sync>;
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `<<Self as Case1>::C as Iterator>::Item` is not an iterator
+ |
+ = help: the trait `Iterator` is not implemented for `<<Self as Case1>::C as Iterator>::Item`
+help: consider further restricting the associated type
+ |
+LL | trait Case1 where <<Self as Case1>::C as Iterator>::Item: Iterator {
+ | ++++++++++++++++++++++++++++++++++++++++++++++++++++++
+
+error[E0277]: `<<Self as Case1>::C as Iterator>::Item` cannot be shared between threads safely
+ --> $DIR/bad-bounds-on-assoc-in-trait.rs:26:93
+ |
+LL | type C: Clone + Iterator<Item: Send + Iterator<Item: for<'a> Lam<&'a u8, App: Debug>> + Sync>;
+ | ^^^^ `<<Self as Case1>::C as Iterator>::Item` cannot be shared between threads safely
+ |
+ = help: the trait `Sync` is not implemented for `<<Self as Case1>::C as Iterator>::Item`
+help: consider further restricting the associated type
+ |
+LL | trait Case1 where <<Self as Case1>::C as Iterator>::Item: Sync {
+ | ++++++++++++++++++++++++++++++++++++++++++++++++++
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/associated-type-bounds/binder-on-bound.rs b/src/test/ui/associated-type-bounds/binder-on-bound.rs
new file mode 100644
index 000000000..0b4b24b98
--- /dev/null
+++ b/src/test/ui/associated-type-bounds/binder-on-bound.rs
@@ -0,0 +1,11 @@
+#![feature(generic_associated_types)]
+
+trait Trait {
+ type Bound<'a>;
+}
+
+fn foo() where Trait<for<'a> Bound<'a> = &'a ()> {
+ //~^ ERROR `for<...>` is not allowed on associated type bounds
+}
+
+fn main() {}
diff --git a/src/test/ui/associated-type-bounds/binder-on-bound.stderr b/src/test/ui/associated-type-bounds/binder-on-bound.stderr
new file mode 100644
index 000000000..3432672e0
--- /dev/null
+++ b/src/test/ui/associated-type-bounds/binder-on-bound.stderr
@@ -0,0 +1,8 @@
+error: `for<...>` is not allowed on associated type bounds
+ --> $DIR/binder-on-bound.rs:7:22
+ |
+LL | fn foo() where Trait<for<'a> Bound<'a> = &'a ()> {
+ | ^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/associated-type-bounds/bounds-on-assoc-in-trait.rs b/src/test/ui/associated-type-bounds/bounds-on-assoc-in-trait.rs
new file mode 100644
index 000000000..23be73501
--- /dev/null
+++ b/src/test/ui/associated-type-bounds/bounds-on-assoc-in-trait.rs
@@ -0,0 +1,54 @@
+#![feature(associated_type_bounds)]
+
+use std::fmt::Debug;
+use std::iter::Empty;
+use std::ops::Range;
+
+trait Lam<Binder> { type App; }
+
+#[derive(Clone)]
+struct L1;
+impl<'a> Lam<&'a u8> for L1 { type App = u8; }
+
+#[derive(Clone)]
+struct L2;
+impl<'a, 'b> Lam<&'a &'b u8> for L2 { type App = u8; }
+
+trait Case1 {
+ type A: Iterator<Item: Debug>;
+ //~^ ERROR `<<Self as Case1>::A as Iterator>::Item` doesn't implement `Debug`
+
+ type B: Iterator<Item: 'static>;
+}
+
+pub struct S1;
+impl Case1 for S1 {
+ type A = Empty<String>;
+ type B = Range<u16>;
+}
+
+// Ensure we don't have opaque `impl Trait` desugaring:
+
+// What is this supposed to mean? Rustc currently lowers `: Default` in the
+// bounds of `Out`, but trait selection can't find the bound since it applies
+// to a type other than `Self::Out`.
+pub trait Foo { type Out: Baz<Assoc: Default>; }
+//~^ ERROR trait bound `<<Self as Foo>::Out as Baz>::Assoc: Default` is not satisfied
+pub trait Baz { type Assoc; }
+
+#[derive(Default)]
+struct S2;
+#[derive(Default)]
+struct S3;
+struct S4;
+struct S5;
+struct S6;
+struct S7;
+
+impl Foo for S6 { type Out = S4; }
+impl Foo for S7 { type Out = S5; }
+
+impl Baz for S4 { type Assoc = S2; }
+impl Baz for S5 { type Assoc = S3; }
+
+fn main() {}
diff --git a/src/test/ui/associated-type-bounds/bounds-on-assoc-in-trait.stderr b/src/test/ui/associated-type-bounds/bounds-on-assoc-in-trait.stderr
new file mode 100644
index 000000000..4e2313bd4
--- /dev/null
+++ b/src/test/ui/associated-type-bounds/bounds-on-assoc-in-trait.stderr
@@ -0,0 +1,26 @@
+error[E0277]: `<<Self as Case1>::A as Iterator>::Item` doesn't implement `Debug`
+ --> $DIR/bounds-on-assoc-in-trait.rs:18:28
+ |
+LL | type A: Iterator<Item: Debug>;
+ | ^^^^^ `<<Self as Case1>::A as Iterator>::Item` cannot be formatted using `{:?}` because it doesn't implement `Debug`
+ |
+ = help: the trait `Debug` is not implemented for `<<Self as Case1>::A as Iterator>::Item`
+help: consider further restricting the associated type
+ |
+LL | trait Case1 where <<Self as Case1>::A as Iterator>::Item: Debug {
+ | +++++++++++++++++++++++++++++++++++++++++++++++++++
+
+error[E0277]: the trait bound `<<Self as Foo>::Out as Baz>::Assoc: Default` is not satisfied
+ --> $DIR/bounds-on-assoc-in-trait.rs:35:38
+ |
+LL | pub trait Foo { type Out: Baz<Assoc: Default>; }
+ | ^^^^^^^ the trait `Default` is not implemented for `<<Self as Foo>::Out as Baz>::Assoc`
+ |
+help: consider further restricting the associated type
+ |
+LL | pub trait Foo where <<Self as Foo>::Out as Baz>::Assoc: Default { type Out: Baz<Assoc: Default>; }
+ | +++++++++++++++++++++++++++++++++++++++++++++++++
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/associated-type-bounds/duplicate.rs b/src/test/ui/associated-type-bounds/duplicate.rs
new file mode 100644
index 000000000..6e464f695
--- /dev/null
+++ b/src/test/ui/associated-type-bounds/duplicate.rs
@@ -0,0 +1,256 @@
+#![feature(associated_type_bounds)]
+#![feature(type_alias_impl_trait)]
+
+use std::iter;
+use std::mem::ManuallyDrop;
+
+struct SI1<T: Iterator<Item: Copy, Item: Send>> {
+ //~^ ERROR the value of the associated type `Item` (from trait `Iterator`) is already specified [E0719]
+ f: T,
+}
+struct SI2<T: Iterator<Item: Copy, Item: Copy>> {
+ //~^ ERROR the value of the associated type `Item` (from trait `Iterator`) is already specified [E0719]
+ f: T,
+}
+struct SI3<T: Iterator<Item: 'static, Item: 'static>> {
+ //~^ ERROR the value of the associated type `Item` (from trait `Iterator`) is already specified [E0719]
+ f: T,
+}
+struct SW1<T>
+where
+ T: Iterator<Item: Copy, Item: Send>,
+ //~^ ERROR the value of the associated type `Item` (from trait `Iterator`) is already specified [E0719]
+{
+ f: T,
+}
+struct SW2<T>
+where
+ T: Iterator<Item: Copy, Item: Copy>,
+ //~^ ERROR the value of the associated type `Item` (from trait `Iterator`) is already specified [E0719]
+{
+ f: T,
+}
+struct SW3<T>
+where
+ T: Iterator<Item: 'static, Item: 'static>,
+ //~^ ERROR the value of the associated type `Item` (from trait `Iterator`) is already specified [E0719]
+{
+ f: T,
+}
+
+enum EI1<T: Iterator<Item: Copy, Item: Send>> {
+ //~^ ERROR the value of the associated type `Item` (from trait `Iterator`) is already specified [E0719]
+ V(T),
+}
+enum EI2<T: Iterator<Item: Copy, Item: Copy>> {
+ //~^ ERROR the value of the associated type `Item` (from trait `Iterator`) is already specified [E0719]
+ V(T),
+}
+enum EI3<T: Iterator<Item: 'static, Item: 'static>> {
+ //~^ ERROR the value of the associated type `Item` (from trait `Iterator`) is already specified [E0719]
+ V(T),
+}
+enum EW1<T>
+where
+ T: Iterator<Item: Copy, Item: Send>,
+ //~^ ERROR the value of the associated type `Item` (from trait `Iterator`) is already specified [E0719]
+{
+ V(T),
+}
+enum EW2<T>
+where
+ T: Iterator<Item: Copy, Item: Copy>,
+ //~^ ERROR the value of the associated type `Item` (from trait `Iterator`) is already specified [E0719]
+{
+ V(T),
+}
+enum EW3<T>
+where
+ T: Iterator<Item: 'static, Item: 'static>,
+ //~^ ERROR the value of the associated type `Item` (from trait `Iterator`) is already specified [E0719]
+{
+ V(T),
+}
+
+union UI1<T: Iterator<Item: Copy, Item: Send>> {
+ //~^ ERROR the value of the associated type `Item` (from trait `Iterator`) is already specified [E0719]
+ f: ManuallyDrop<T>,
+}
+union UI2<T: Iterator<Item: Copy, Item: Copy>> {
+ //~^ ERROR the value of the associated type `Item` (from trait `Iterator`) is already specified [E0719]
+ f: ManuallyDrop<T>,
+}
+union UI3<T: Iterator<Item: 'static, Item: 'static>> {
+ //~^ ERROR the value of the associated type `Item` (from trait `Iterator`) is already specified [E0719]
+ f: ManuallyDrop<T>,
+}
+union UW1<T>
+where
+ T: Iterator<Item: Copy, Item: Send>,
+ //~^ ERROR the value of the associated type `Item` (from trait `Iterator`) is already specified [E0719]
+{
+ f: ManuallyDrop<T>,
+}
+union UW2<T>
+where
+ T: Iterator<Item: Copy, Item: Copy>,
+ //~^ ERROR the value of the associated type `Item` (from trait `Iterator`) is already specified [E0719]
+{
+ f: ManuallyDrop<T>,
+}
+union UW3<T>
+where
+ T: Iterator<Item: 'static, Item: 'static>,
+ //~^ ERROR the value of the associated type `Item` (from trait `Iterator`) is already specified [E0719]
+{
+ f: ManuallyDrop<T>,
+}
+
+fn FI1<T: Iterator<Item: Copy, Item: Send>>() {}
+//~^ ERROR the value of the associated type `Item` (from trait `Iterator`) is already specified [E0719]
+fn FI2<T: Iterator<Item: Copy, Item: Copy>>() {}
+//~^ ERROR the value of the associated type `Item` (from trait `Iterator`) is already specified [E0719]
+fn FI3<T: Iterator<Item: 'static, Item: 'static>>() {}
+//~^ ERROR the value of the associated type `Item` (from trait `Iterator`) is already specified [E0719]
+fn FW1<T>()
+where
+ T: Iterator<Item: Copy, Item: Send>,
+ //~^ ERROR the value of the associated type `Item` (from trait `Iterator`) is already specified [E0719]
+{
+}
+fn FW2<T>()
+where
+ T: Iterator<Item: Copy, Item: Copy>,
+ //~^ ERROR the value of the associated type `Item` (from trait `Iterator`) is already specified [E0719]
+{
+}
+fn FW3<T>()
+where
+ T: Iterator<Item: 'static, Item: 'static>,
+ //~^ ERROR the value of the associated type `Item` (from trait `Iterator`) is already specified [E0719]
+{
+}
+
+fn FRPIT1() -> impl Iterator<Item: Copy, Item: Send> {
+ iter::empty()
+}
+fn FRPIT2() -> impl Iterator<Item: Copy, Item: Copy> {
+ iter::empty()
+}
+fn FRPIT3() -> impl Iterator<Item: 'static, Item: 'static> {
+ iter::empty()
+}
+fn FAPIT1(_: impl Iterator<Item: Copy, Item: Send>) {}
+//~^ ERROR the value of the associated type `Item` (from trait `Iterator`) is already specified [E0719]
+fn FAPIT2(_: impl Iterator<Item: Copy, Item: Copy>) {}
+//~^ ERROR the value of the associated type `Item` (from trait `Iterator`) is already specified [E0719]
+fn FAPIT3(_: impl Iterator<Item: 'static, Item: 'static>) {}
+//~^ ERROR the value of the associated type `Item` (from trait `Iterator`) is already specified [E0719]
+
+type TAI1<T: Iterator<Item: Copy, Item: Send>> = T;
+//~^ ERROR the value of the associated type `Item` (from trait `Iterator`) is already specified [E0719]
+type TAI2<T: Iterator<Item: Copy, Item: Copy>> = T;
+//~^ ERROR the value of the associated type `Item` (from trait `Iterator`) is already specified [E0719]
+type TAI3<T: Iterator<Item: 'static, Item: 'static>> = T;
+//~^ ERROR the value of the associated type `Item` (from trait `Iterator`) is already specified [E0719]
+type TAW1<T>
+where
+ T: Iterator<Item: Copy, Item: Send>,
+//~^ ERROR the value of the associated type `Item` (from trait `Iterator`) is already specified [E0719]
+= T;
+type TAW2<T>
+where
+ T: Iterator<Item: Copy, Item: Copy>,
+//~^ ERROR the value of the associated type `Item` (from trait `Iterator`) is already specified [E0719]
+= T;
+type TAW3<T>
+where
+ T: Iterator<Item: 'static, Item: 'static>,
+//~^ ERROR the value of the associated type `Item` (from trait `Iterator`) is already specified [E0719]
+= T;
+
+type ETAI1<T: Iterator<Item: Copy, Item: Send>> = impl Copy;
+//~^ ERROR the value of the associated type `Item` (from trait `Iterator`) is already specified [E0719]
+type ETAI2<T: Iterator<Item: Copy, Item: Copy>> = impl Copy;
+//~^ ERROR the value of the associated type `Item` (from trait `Iterator`) is already specified [E0719]
+type ETAI3<T: Iterator<Item: 'static, Item: 'static>> = impl Copy;
+//~^ ERROR the value of the associated type `Item` (from trait `Iterator`) is already specified [E0719]
+type ETAI4 = impl Iterator<Item: Copy, Item: Send>;
+//~^ ERROR the value of the associated type `Item` (from trait `Iterator`) is already specified [E0719]
+type ETAI5 = impl Iterator<Item: Copy, Item: Copy>;
+//~^ ERROR the value of the associated type `Item` (from trait `Iterator`) is already specified [E0719]
+type ETAI6 = impl Iterator<Item: 'static, Item: 'static>;
+//~^ ERROR the value of the associated type `Item` (from trait `Iterator`) is already specified [E0719]
+
+trait TRI1<T: Iterator<Item: Copy, Item: Send>> {}
+//~^ ERROR the value of the associated type `Item` (from trait `Iterator`) is already specified [E0719]
+trait TRI2<T: Iterator<Item: Copy, Item: Copy>> {}
+//~^ ERROR the value of the associated type `Item` (from trait `Iterator`) is already specified [E0719]
+trait TRI3<T: Iterator<Item: 'static, Item: 'static>> {}
+//~^ ERROR the value of the associated type `Item` (from trait `Iterator`) is already specified [E0719]
+trait TRS1: Iterator<Item: Copy, Item: Send> {}
+//~^ ERROR the value of the associated type `Item` (from trait `Iterator`) is already specified [E0719]
+trait TRS2: Iterator<Item: Copy, Item: Copy> {}
+//~^ ERROR the value of the associated type `Item` (from trait `Iterator`) is already specified [E0719]
+trait TRS3: Iterator<Item: 'static, Item: 'static> {}
+//~^ ERROR the value of the associated type `Item` (from trait `Iterator`) is already specified [E0719]
+trait TRW1<T>
+where
+ T: Iterator<Item: Copy, Item: Send>,
+ //~^ ERROR the value of the associated type `Item` (from trait `Iterator`) is already specified [E0719]
+{
+}
+trait TRW2<T>
+where
+ T: Iterator<Item: Copy, Item: Copy>,
+ //~^ ERROR the value of the associated type `Item` (from trait `Iterator`) is already specified [E0719]
+{
+}
+trait TRW3<T>
+where
+ T: Iterator<Item: 'static, Item: 'static>,
+ //~^ ERROR the value of the associated type `Item` (from trait `Iterator`) is already specified [E0719]
+{
+}
+trait TRSW1
+where
+ Self: Iterator<Item: Copy, Item: Send>,
+ //~^ ERROR the value of the associated type `Item` (from trait `Iterator`) is already specified [E0719]
+ //~| ERROR the value of the associated type `Item` (from trait `Iterator`) is already specified [E0719]
+{
+}
+trait TRSW2
+where
+ Self: Iterator<Item: Copy, Item: Copy>,
+ //~^ ERROR the value of the associated type `Item` (from trait `Iterator`) is already specified [E0719]
+ //~| ERROR the value of the associated type `Item` (from trait `Iterator`) is already specified [E0719]
+{
+}
+trait TRSW3
+where
+ Self: Iterator<Item: 'static, Item: 'static>,
+ //~^ ERROR the value of the associated type `Item` (from trait `Iterator`) is already specified [E0719]
+ //~| ERROR the value of the associated type `Item` (from trait `Iterator`) is already specified [E0719]
+{
+}
+trait TRA1 {
+ type A: Iterator<Item: Copy, Item: Send>;
+ //~^ ERROR the value of the associated type `Item` (from trait `Iterator`) is already specified [E0719]
+}
+trait TRA2 {
+ type A: Iterator<Item: Copy, Item: Copy>;
+ //~^ ERROR the value of the associated type `Item` (from trait `Iterator`) is already specified [E0719]
+}
+trait TRA3 {
+ type A: Iterator<Item: 'static, Item: 'static>;
+ //~^ ERROR the value of the associated type `Item` (from trait `Iterator`) is already specified [E0719]
+}
+
+type TADyn1 = dyn Iterator<Item: Copy, Item: Send>;
+//~^ ERROR the value of the associated type `Item` (from trait `Iterator`) is already specified [E0719]
+type TADyn2 = Box<dyn Iterator<Item: Copy, Item: Copy>>;
+//~^ ERROR the value of the associated type `Item` (from trait `Iterator`) is already specified [E0719]
+type TADyn3 = dyn Iterator<Item: 'static, Item: 'static>;
+//~^ ERROR the value of the associated type `Item` (from trait `Iterator`) is already specified [E0719]
+
+fn main() {}
diff --git a/src/test/ui/associated-type-bounds/duplicate.stderr b/src/test/ui/associated-type-bounds/duplicate.stderr
new file mode 100644
index 000000000..e4f4836f7
--- /dev/null
+++ b/src/test/ui/associated-type-bounds/duplicate.stderr
@@ -0,0 +1,483 @@
+error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified
+ --> $DIR/duplicate.rs:7:36
+ |
+LL | struct SI1<T: Iterator<Item: Copy, Item: Send>> {
+ | ---------- ^^^^^^^^^^ re-bound here
+ | |
+ | `Item` bound here first
+
+error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified
+ --> $DIR/duplicate.rs:11:36
+ |
+LL | struct SI2<T: Iterator<Item: Copy, Item: Copy>> {
+ | ---------- ^^^^^^^^^^ re-bound here
+ | |
+ | `Item` bound here first
+
+error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified
+ --> $DIR/duplicate.rs:15:39
+ |
+LL | struct SI3<T: Iterator<Item: 'static, Item: 'static>> {
+ | ------------- ^^^^^^^^^^^^^ re-bound here
+ | |
+ | `Item` bound here first
+
+error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified
+ --> $DIR/duplicate.rs:21:29
+ |
+LL | T: Iterator<Item: Copy, Item: Send>,
+ | ---------- ^^^^^^^^^^ re-bound here
+ | |
+ | `Item` bound here first
+
+error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified
+ --> $DIR/duplicate.rs:28:29
+ |
+LL | T: Iterator<Item: Copy, Item: Copy>,
+ | ---------- ^^^^^^^^^^ re-bound here
+ | |
+ | `Item` bound here first
+
+error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified
+ --> $DIR/duplicate.rs:35:32
+ |
+LL | T: Iterator<Item: 'static, Item: 'static>,
+ | ------------- ^^^^^^^^^^^^^ re-bound here
+ | |
+ | `Item` bound here first
+
+error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified
+ --> $DIR/duplicate.rs:41:34
+ |
+LL | enum EI1<T: Iterator<Item: Copy, Item: Send>> {
+ | ---------- ^^^^^^^^^^ re-bound here
+ | |
+ | `Item` bound here first
+
+error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified
+ --> $DIR/duplicate.rs:45:34
+ |
+LL | enum EI2<T: Iterator<Item: Copy, Item: Copy>> {
+ | ---------- ^^^^^^^^^^ re-bound here
+ | |
+ | `Item` bound here first
+
+error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified
+ --> $DIR/duplicate.rs:49:37
+ |
+LL | enum EI3<T: Iterator<Item: 'static, Item: 'static>> {
+ | ------------- ^^^^^^^^^^^^^ re-bound here
+ | |
+ | `Item` bound here first
+
+error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified
+ --> $DIR/duplicate.rs:55:29
+ |
+LL | T: Iterator<Item: Copy, Item: Send>,
+ | ---------- ^^^^^^^^^^ re-bound here
+ | |
+ | `Item` bound here first
+
+error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified
+ --> $DIR/duplicate.rs:62:29
+ |
+LL | T: Iterator<Item: Copy, Item: Copy>,
+ | ---------- ^^^^^^^^^^ re-bound here
+ | |
+ | `Item` bound here first
+
+error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified
+ --> $DIR/duplicate.rs:69:32
+ |
+LL | T: Iterator<Item: 'static, Item: 'static>,
+ | ------------- ^^^^^^^^^^^^^ re-bound here
+ | |
+ | `Item` bound here first
+
+error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified
+ --> $DIR/duplicate.rs:75:35
+ |
+LL | union UI1<T: Iterator<Item: Copy, Item: Send>> {
+ | ---------- ^^^^^^^^^^ re-bound here
+ | |
+ | `Item` bound here first
+
+error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified
+ --> $DIR/duplicate.rs:79:35
+ |
+LL | union UI2<T: Iterator<Item: Copy, Item: Copy>> {
+ | ---------- ^^^^^^^^^^ re-bound here
+ | |
+ | `Item` bound here first
+
+error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified
+ --> $DIR/duplicate.rs:83:38
+ |
+LL | union UI3<T: Iterator<Item: 'static, Item: 'static>> {
+ | ------------- ^^^^^^^^^^^^^ re-bound here
+ | |
+ | `Item` bound here first
+
+error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified
+ --> $DIR/duplicate.rs:89:29
+ |
+LL | T: Iterator<Item: Copy, Item: Send>,
+ | ---------- ^^^^^^^^^^ re-bound here
+ | |
+ | `Item` bound here first
+
+error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified
+ --> $DIR/duplicate.rs:96:29
+ |
+LL | T: Iterator<Item: Copy, Item: Copy>,
+ | ---------- ^^^^^^^^^^ re-bound here
+ | |
+ | `Item` bound here first
+
+error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified
+ --> $DIR/duplicate.rs:103:32
+ |
+LL | T: Iterator<Item: 'static, Item: 'static>,
+ | ------------- ^^^^^^^^^^^^^ re-bound here
+ | |
+ | `Item` bound here first
+
+error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified
+ --> $DIR/duplicate.rs:109:32
+ |
+LL | fn FI1<T: Iterator<Item: Copy, Item: Send>>() {}
+ | ---------- ^^^^^^^^^^ re-bound here
+ | |
+ | `Item` bound here first
+
+error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified
+ --> $DIR/duplicate.rs:111:32
+ |
+LL | fn FI2<T: Iterator<Item: Copy, Item: Copy>>() {}
+ | ---------- ^^^^^^^^^^ re-bound here
+ | |
+ | `Item` bound here first
+
+error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified
+ --> $DIR/duplicate.rs:113:35
+ |
+LL | fn FI3<T: Iterator<Item: 'static, Item: 'static>>() {}
+ | ------------- ^^^^^^^^^^^^^ re-bound here
+ | |
+ | `Item` bound here first
+
+error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified
+ --> $DIR/duplicate.rs:117:29
+ |
+LL | T: Iterator<Item: Copy, Item: Send>,
+ | ---------- ^^^^^^^^^^ re-bound here
+ | |
+ | `Item` bound here first
+
+error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified
+ --> $DIR/duplicate.rs:123:29
+ |
+LL | T: Iterator<Item: Copy, Item: Copy>,
+ | ---------- ^^^^^^^^^^ re-bound here
+ | |
+ | `Item` bound here first
+
+error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified
+ --> $DIR/duplicate.rs:129:32
+ |
+LL | T: Iterator<Item: 'static, Item: 'static>,
+ | ------------- ^^^^^^^^^^^^^ re-bound here
+ | |
+ | `Item` bound here first
+
+error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified
+ --> $DIR/duplicate.rs:143:40
+ |
+LL | fn FAPIT1(_: impl Iterator<Item: Copy, Item: Send>) {}
+ | ---------- ^^^^^^^^^^ re-bound here
+ | |
+ | `Item` bound here first
+
+error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified
+ --> $DIR/duplicate.rs:145:40
+ |
+LL | fn FAPIT2(_: impl Iterator<Item: Copy, Item: Copy>) {}
+ | ---------- ^^^^^^^^^^ re-bound here
+ | |
+ | `Item` bound here first
+
+error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified
+ --> $DIR/duplicate.rs:147:43
+ |
+LL | fn FAPIT3(_: impl Iterator<Item: 'static, Item: 'static>) {}
+ | ------------- ^^^^^^^^^^^^^ re-bound here
+ | |
+ | `Item` bound here first
+
+error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified
+ --> $DIR/duplicate.rs:150:35
+ |
+LL | type TAI1<T: Iterator<Item: Copy, Item: Send>> = T;
+ | ---------- ^^^^^^^^^^ re-bound here
+ | |
+ | `Item` bound here first
+
+error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified
+ --> $DIR/duplicate.rs:152:35
+ |
+LL | type TAI2<T: Iterator<Item: Copy, Item: Copy>> = T;
+ | ---------- ^^^^^^^^^^ re-bound here
+ | |
+ | `Item` bound here first
+
+error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified
+ --> $DIR/duplicate.rs:154:38
+ |
+LL | type TAI3<T: Iterator<Item: 'static, Item: 'static>> = T;
+ | ------------- ^^^^^^^^^^^^^ re-bound here
+ | |
+ | `Item` bound here first
+
+error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified
+ --> $DIR/duplicate.rs:158:29
+ |
+LL | T: Iterator<Item: Copy, Item: Send>,
+ | ---------- ^^^^^^^^^^ re-bound here
+ | |
+ | `Item` bound here first
+
+error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified
+ --> $DIR/duplicate.rs:163:29
+ |
+LL | T: Iterator<Item: Copy, Item: Copy>,
+ | ---------- ^^^^^^^^^^ re-bound here
+ | |
+ | `Item` bound here first
+
+error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified
+ --> $DIR/duplicate.rs:168:32
+ |
+LL | T: Iterator<Item: 'static, Item: 'static>,
+ | ------------- ^^^^^^^^^^^^^ re-bound here
+ | |
+ | `Item` bound here first
+
+error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified
+ --> $DIR/duplicate.rs:172:36
+ |
+LL | type ETAI1<T: Iterator<Item: Copy, Item: Send>> = impl Copy;
+ | ---------- ^^^^^^^^^^ re-bound here
+ | |
+ | `Item` bound here first
+
+error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified
+ --> $DIR/duplicate.rs:174:36
+ |
+LL | type ETAI2<T: Iterator<Item: Copy, Item: Copy>> = impl Copy;
+ | ---------- ^^^^^^^^^^ re-bound here
+ | |
+ | `Item` bound here first
+
+error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified
+ --> $DIR/duplicate.rs:176:39
+ |
+LL | type ETAI3<T: Iterator<Item: 'static, Item: 'static>> = impl Copy;
+ | ------------- ^^^^^^^^^^^^^ re-bound here
+ | |
+ | `Item` bound here first
+
+error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified
+ --> $DIR/duplicate.rs:178:40
+ |
+LL | type ETAI4 = impl Iterator<Item: Copy, Item: Send>;
+ | ---------- ^^^^^^^^^^ re-bound here
+ | |
+ | `Item` bound here first
+
+error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified
+ --> $DIR/duplicate.rs:180:40
+ |
+LL | type ETAI5 = impl Iterator<Item: Copy, Item: Copy>;
+ | ---------- ^^^^^^^^^^ re-bound here
+ | |
+ | `Item` bound here first
+
+error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified
+ --> $DIR/duplicate.rs:182:43
+ |
+LL | type ETAI6 = impl Iterator<Item: 'static, Item: 'static>;
+ | ------------- ^^^^^^^^^^^^^ re-bound here
+ | |
+ | `Item` bound here first
+
+error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified
+ --> $DIR/duplicate.rs:185:36
+ |
+LL | trait TRI1<T: Iterator<Item: Copy, Item: Send>> {}
+ | ---------- ^^^^^^^^^^ re-bound here
+ | |
+ | `Item` bound here first
+
+error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified
+ --> $DIR/duplicate.rs:187:36
+ |
+LL | trait TRI2<T: Iterator<Item: Copy, Item: Copy>> {}
+ | ---------- ^^^^^^^^^^ re-bound here
+ | |
+ | `Item` bound here first
+
+error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified
+ --> $DIR/duplicate.rs:189:39
+ |
+LL | trait TRI3<T: Iterator<Item: 'static, Item: 'static>> {}
+ | ------------- ^^^^^^^^^^^^^ re-bound here
+ | |
+ | `Item` bound here first
+
+error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified
+ --> $DIR/duplicate.rs:191:34
+ |
+LL | trait TRS1: Iterator<Item: Copy, Item: Send> {}
+ | ---------- ^^^^^^^^^^ re-bound here
+ | |
+ | `Item` bound here first
+
+error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified
+ --> $DIR/duplicate.rs:193:34
+ |
+LL | trait TRS2: Iterator<Item: Copy, Item: Copy> {}
+ | ---------- ^^^^^^^^^^ re-bound here
+ | |
+ | `Item` bound here first
+
+error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified
+ --> $DIR/duplicate.rs:195:37
+ |
+LL | trait TRS3: Iterator<Item: 'static, Item: 'static> {}
+ | ------------- ^^^^^^^^^^^^^ re-bound here
+ | |
+ | `Item` bound here first
+
+error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified
+ --> $DIR/duplicate.rs:199:29
+ |
+LL | T: Iterator<Item: Copy, Item: Send>,
+ | ---------- ^^^^^^^^^^ re-bound here
+ | |
+ | `Item` bound here first
+
+error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified
+ --> $DIR/duplicate.rs:205:29
+ |
+LL | T: Iterator<Item: Copy, Item: Copy>,
+ | ---------- ^^^^^^^^^^ re-bound here
+ | |
+ | `Item` bound here first
+
+error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified
+ --> $DIR/duplicate.rs:211:32
+ |
+LL | T: Iterator<Item: 'static, Item: 'static>,
+ | ------------- ^^^^^^^^^^^^^ re-bound here
+ | |
+ | `Item` bound here first
+
+error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified
+ --> $DIR/duplicate.rs:217:32
+ |
+LL | Self: Iterator<Item: Copy, Item: Send>,
+ | ---------- ^^^^^^^^^^ re-bound here
+ | |
+ | `Item` bound here first
+
+error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified
+ --> $DIR/duplicate.rs:217:32
+ |
+LL | Self: Iterator<Item: Copy, Item: Send>,
+ | ---------- ^^^^^^^^^^ re-bound here
+ | |
+ | `Item` bound here first
+
+error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified
+ --> $DIR/duplicate.rs:224:32
+ |
+LL | Self: Iterator<Item: Copy, Item: Copy>,
+ | ---------- ^^^^^^^^^^ re-bound here
+ | |
+ | `Item` bound here first
+
+error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified
+ --> $DIR/duplicate.rs:224:32
+ |
+LL | Self: Iterator<Item: Copy, Item: Copy>,
+ | ---------- ^^^^^^^^^^ re-bound here
+ | |
+ | `Item` bound here first
+
+error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified
+ --> $DIR/duplicate.rs:231:35
+ |
+LL | Self: Iterator<Item: 'static, Item: 'static>,
+ | ------------- ^^^^^^^^^^^^^ re-bound here
+ | |
+ | `Item` bound here first
+
+error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified
+ --> $DIR/duplicate.rs:231:35
+ |
+LL | Self: Iterator<Item: 'static, Item: 'static>,
+ | ------------- ^^^^^^^^^^^^^ re-bound here
+ | |
+ | `Item` bound here first
+
+error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified
+ --> $DIR/duplicate.rs:249:40
+ |
+LL | type TADyn1 = dyn Iterator<Item: Copy, Item: Send>;
+ | ---------- ^^^^^^^^^^ re-bound here
+ | |
+ | `Item` bound here first
+
+error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified
+ --> $DIR/duplicate.rs:251:44
+ |
+LL | type TADyn2 = Box<dyn Iterator<Item: Copy, Item: Copy>>;
+ | ---------- ^^^^^^^^^^ re-bound here
+ | |
+ | `Item` bound here first
+
+error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified
+ --> $DIR/duplicate.rs:253:43
+ |
+LL | type TADyn3 = dyn Iterator<Item: 'static, Item: 'static>;
+ | ------------- ^^^^^^^^^^^^^ re-bound here
+ | |
+ | `Item` bound here first
+
+error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified
+ --> $DIR/duplicate.rs:237:34
+ |
+LL | type A: Iterator<Item: Copy, Item: Send>;
+ | ---------- ^^^^^^^^^^ re-bound here
+ | |
+ | `Item` bound here first
+
+error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified
+ --> $DIR/duplicate.rs:241:34
+ |
+LL | type A: Iterator<Item: Copy, Item: Copy>;
+ | ---------- ^^^^^^^^^^ re-bound here
+ | |
+ | `Item` bound here first
+
+error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified
+ --> $DIR/duplicate.rs:245:37
+ |
+LL | type A: Iterator<Item: 'static, Item: 'static>;
+ | ------------- ^^^^^^^^^^^^^ re-bound here
+ | |
+ | `Item` bound here first
+
+error: aborting due to 60 previous errors
+
+For more information about this error, try `rustc --explain E0719`.
diff --git a/src/test/ui/associated-type-bounds/dyn-impl-trait-type.rs b/src/test/ui/associated-type-bounds/dyn-impl-trait-type.rs
new file mode 100644
index 000000000..a8d00803a
--- /dev/null
+++ b/src/test/ui/associated-type-bounds/dyn-impl-trait-type.rs
@@ -0,0 +1,66 @@
+// run-pass
+
+#![feature(associated_type_bounds)]
+
+use std::ops::Add;
+
+trait Tr1 { type As1; fn mk(&self) -> Self::As1; }
+trait Tr2<'a> { fn tr2(self) -> &'a Self; }
+
+fn assert_copy<T: Copy>(x: T) { let _x = x; let _x = x; }
+fn assert_static<T: 'static>(_: T) {}
+fn assert_forall_tr2<T: for<'a> Tr2<'a>>(_: T) {}
+
+struct S1;
+#[derive(Copy, Clone)]
+struct S2;
+impl Tr1 for S1 { type As1 = S2; fn mk(&self) -> Self::As1 { S2 } }
+
+type Et1 = Box<dyn Tr1<As1: Copy>>;
+fn def_et1() -> Et1 { Box::new(S1) }
+pub fn use_et1() { assert_copy(def_et1().mk()); }
+
+type Et2 = Box<dyn Tr1<As1: 'static>>;
+fn def_et2() -> Et2 { Box::new(S1) }
+pub fn use_et2() { assert_static(def_et2().mk()); }
+
+type Et3 = Box<dyn Tr1<As1: Clone + Iterator<Item: Add<u8, Output: Into<u8>>>>>;
+fn def_et3() -> Et3 {
+ struct A;
+ impl Tr1 for A {
+ type As1 = core::ops::Range<u8>;
+ fn mk(&self) -> Self::As1 { 0..10 }
+ }
+ Box::new(A)
+}
+pub fn use_et3() {
+ let _0 = def_et3().mk().clone();
+ let mut s = 0u8;
+ for _1 in _0 {
+ let _2 = _1 + 1u8;
+ s += _2.into();
+ }
+ assert_eq!(s, (0..10).map(|x| x + 1).sum());
+}
+
+type Et4 = Box<dyn Tr1<As1: for<'a> Tr2<'a>>>;
+fn def_et4() -> Et4 {
+ #[derive(Copy, Clone)]
+ struct A;
+ impl Tr1 for A {
+ type As1 = A;
+ fn mk(&self) -> A { A }
+ }
+ impl<'a> Tr2<'a> for A {
+ fn tr2(self) -> &'a Self { &A }
+ }
+ Box::new(A)
+}
+pub fn use_et4() { assert_forall_tr2(def_et4().mk()); }
+
+fn main() {
+ let _ = use_et1();
+ let _ = use_et2();
+ let _ = use_et3();
+ let _ = use_et4();
+}
diff --git a/src/test/ui/associated-type-bounds/dyn-rpit-and-let.rs b/src/test/ui/associated-type-bounds/dyn-rpit-and-let.rs
new file mode 100644
index 000000000..08f965452
--- /dev/null
+++ b/src/test/ui/associated-type-bounds/dyn-rpit-and-let.rs
@@ -0,0 +1,73 @@
+// run-pass
+
+// FIXME: uncomment let binding types below when `impl_trait_in_bindings` feature is fixed.
+
+#![feature(associated_type_bounds)]
+
+use std::ops::Add;
+
+trait Tr1 { type As1; fn mk(&self) -> Self::As1; }
+trait Tr2<'a> { fn tr2(self) -> &'a Self; }
+
+fn assert_copy<T: Copy>(x: T) { let _x = x; let _x = x; }
+fn assert_static<T: 'static>(_: T) {}
+fn assert_forall_tr2<T: for<'a> Tr2<'a>>(_: T) {}
+
+struct S1;
+#[derive(Copy, Clone)]
+struct S2;
+impl Tr1 for S1 { type As1 = S2; fn mk(&self) -> Self::As1 { S2 } }
+
+fn def_et1() -> Box<dyn Tr1<As1: Copy>> {
+ let x /* : Box<dyn Tr1<As1: Copy>> */ = Box::new(S1);
+ x
+}
+pub fn use_et1() { assert_copy(def_et1().mk()); }
+
+fn def_et2() -> Box<dyn Tr1<As1: Send + 'static>> {
+ let x /* : Box<dyn Tr1<As1: Send + 'static>> */ = Box::new(S1);
+ x
+}
+pub fn use_et2() { assert_static(def_et2().mk()); }
+
+fn def_et3() -> Box<dyn Tr1<As1: Clone + Iterator<Item: Add<u8, Output: Into<u8>>>>> {
+ struct A;
+ impl Tr1 for A {
+ type As1 = core::ops::Range<u8>;
+ fn mk(&self) -> Self::As1 { 0..10 }
+ }
+ let x /* : Box<dyn Tr1<As1: Clone + Iterator<Item: Add<u8, Output: Into<u8>>>>> */
+ = Box::new(A);
+ x
+}
+pub fn use_et3() {
+ let _0 = def_et3().mk().clone();
+ let mut s = 0u8;
+ for _1 in _0 {
+ let _2 = _1 + 1u8;
+ s += _2.into();
+ }
+ assert_eq!(s, (0..10).map(|x| x + 1).sum());
+}
+
+fn def_et4() -> Box<dyn Tr1<As1: for<'a> Tr2<'a>>> {
+ #[derive(Copy, Clone)]
+ struct A;
+ impl Tr1 for A {
+ type As1 = A;
+ fn mk(&self) -> A { A }
+ }
+ impl<'a> Tr2<'a> for A {
+ fn tr2(self) -> &'a Self { &A }
+ }
+ let x /* : Box<dyn Tr1<As1: for<'a> Tr2<'a>>> */ = Box::new(A);
+ x
+}
+pub fn use_et4() { assert_forall_tr2(def_et4().mk()); }
+
+fn main() {
+ let _ = use_et1();
+ let _ = use_et2();
+ let _ = use_et3();
+ let _ = use_et4();
+}
diff --git a/src/test/ui/associated-type-bounds/elision.rs b/src/test/ui/associated-type-bounds/elision.rs
new file mode 100644
index 000000000..4a5339399
--- /dev/null
+++ b/src/test/ui/associated-type-bounds/elision.rs
@@ -0,0 +1,9 @@
+#![feature(associated_type_bounds)]
+#![feature(anonymous_lifetime_in_impl_trait)]
+
+// The same thing should happen for constaints in dyn trait.
+fn f(x: &mut dyn Iterator<Item: Iterator<Item = &'_ ()>>) -> Option<&'_ ()> { x.next() }
+//~^ ERROR missing lifetime specifier
+//~| ERROR mismatched types
+
+fn main() {}
diff --git a/src/test/ui/associated-type-bounds/elision.stderr b/src/test/ui/associated-type-bounds/elision.stderr
new file mode 100644
index 000000000..ea3024627
--- /dev/null
+++ b/src/test/ui/associated-type-bounds/elision.stderr
@@ -0,0 +1,28 @@
+error[E0106]: missing lifetime specifier
+ --> $DIR/elision.rs:5:70
+ |
+LL | fn f(x: &mut dyn Iterator<Item: Iterator<Item = &'_ ()>>) -> Option<&'_ ()> { x.next() }
+ | ------------------------------------------------ ^^ expected named lifetime parameter
+ |
+ = help: this function's return type contains a borrowed value, but the signature does not say which one of `x`'s 2 lifetimes it is borrowed from
+help: consider introducing a named lifetime parameter
+ |
+LL | fn f<'a>(x: &'a mut dyn Iterator<Item: Iterator<Item = &'a ()>>) -> Option<&'a ()> { x.next() }
+ | ++++ ++ ~~ ~~
+
+error[E0308]: mismatched types
+ --> $DIR/elision.rs:5:79
+ |
+LL | fn f(x: &mut dyn Iterator<Item: Iterator<Item = &'_ ()>>) -> Option<&'_ ()> { x.next() }
+ | ----------------------------- -------------- ^^^^^^^^ expected `&()`, found type parameter `impl Iterator<Item = &'_ ()>`
+ | | |
+ | | expected `Option<&'static ()>` because of return type
+ | this type parameter
+ |
+ = note: expected enum `Option<&'static ()>`
+ found enum `Option<impl Iterator<Item = &'_ ()>>`
+
+error: aborting due to 2 previous errors
+
+Some errors have detailed explanations: E0106, E0308.
+For more information about an error, try `rustc --explain E0106`.
diff --git a/src/test/ui/associated-type-bounds/entails-sized-object-safety.rs b/src/test/ui/associated-type-bounds/entails-sized-object-safety.rs
new file mode 100644
index 000000000..f5a9bac6e
--- /dev/null
+++ b/src/test/ui/associated-type-bounds/entails-sized-object-safety.rs
@@ -0,0 +1,26 @@
+// build-pass (FIXME(62277): could be check-pass?)
+
+#![feature(associated_type_bounds)]
+
+trait Tr1: Sized { type As1; }
+trait Tr2<'a>: Sized { type As2; }
+
+trait ObjTr1 { fn foo() -> Self where Self: Tr1<As1: Copy>; }
+fn _assert_obj_safe_1(_: Box<dyn ObjTr1>) {}
+
+trait ObjTr2 { fn foo() -> Self where Self: Tr1<As1: 'static>; }
+fn _assert_obj_safe_2(_: Box<dyn ObjTr2>) {}
+
+trait ObjTr3 { fn foo() -> Self where Self: Tr1<As1: Into<u8> + 'static + Copy>; }
+fn _assert_obj_safe_3(_: Box<dyn ObjTr3>) {}
+
+trait ObjTr4 { fn foo() -> Self where Self: Tr1<As1: for<'a> Tr2<'a>>; }
+fn _assert_obj_safe_4(_: Box<dyn ObjTr4>) {}
+
+trait ObjTr5 { fn foo() -> Self where for<'a> Self: Tr1<As1: Tr2<'a>>; }
+fn _assert_obj_safe_5(_: Box<dyn ObjTr5>) {}
+
+trait ObjTr6 { fn foo() -> Self where Self: for<'a> Tr1<As1: Tr2<'a, As2: for<'b> Tr2<'b>>>; }
+fn _assert_obj_safe_6(_: Box<dyn ObjTr6>) {}
+
+fn main() {}
diff --git a/src/test/ui/associated-type-bounds/enum-bounds.rs b/src/test/ui/associated-type-bounds/enum-bounds.rs
new file mode 100644
index 000000000..193f2efe1
--- /dev/null
+++ b/src/test/ui/associated-type-bounds/enum-bounds.rs
@@ -0,0 +1,123 @@
+// run-pass
+
+#![feature(associated_type_bounds)]
+#![allow(dead_code)]
+
+trait Tr1 { type As1; }
+trait Tr2 { type As2; }
+trait Tr3 { type As3; }
+trait Tr4<'a> { type As4; }
+trait Tr5 { type As5; }
+
+impl Tr1 for &str { type As1 = bool; }
+impl Tr2 for bool { type As2 = u8; }
+impl Tr3 for u8 { type As3 = fn() -> u8; }
+impl Tr1 for () { type As1 = (usize,); }
+impl<'a> Tr4<'a> for (usize,) { type As4 = u8; }
+impl Tr5 for bool { type As5 = u16; }
+
+enum En1<T: Tr1<As1: Tr2>> {
+ Outest(T),
+ Outer(T::As1),
+ Inner(<T::As1 as Tr2>::As2),
+}
+
+fn wrap_en1_1<T>(x: T) -> En1<T> where T: Tr1, T::As1: Tr2 {
+ En1::Outest(x)
+}
+
+fn wrap_en1_2<T>(x: T::As1) -> En1<T> where T: Tr1, T::As1: Tr2 {
+ En1::Outer(x)
+}
+
+fn wrap_en1_3<T>(x: <T::As1 as Tr2>::As2) -> En1<T> where T: Tr1, T::As1: Tr2 {
+ En1::Inner(x)
+}
+
+enum En2<T: Tr1<As1: Tr2<As2: Tr3>>> {
+ V0(T),
+ V1(T::As1),
+ V2(<T::As1 as Tr2>::As2),
+ V3(<<T::As1 as Tr2>::As2 as Tr3>::As3),
+}
+
+enum En3<T: Tr1<As1: 'static>> {
+ V0(T),
+ V1(&'static T::As1),
+}
+
+enum En4<'x1, 'x2, T: Tr1<As1: for<'l> Tr4<'l>>> {
+ V0(&'x1 <T::As1 as Tr4<'x1>>::As4),
+ V1(&'x2 <T::As1 as Tr4<'x2>>::As4),
+}
+
+enum _En5<'x1, 'x2, T: Tr1<As1: for<'l> Tr4<'l, As4: Copy>>> {
+ _V0(&'x1 <T::As1 as Tr4<'x1>>::As4),
+ _V1(&'x2 <T::As1 as Tr4<'x2>>::As4),
+}
+
+enum En6<T>
+where
+ T: Tr1<As1: Tr2 + 'static + Tr5>,
+{
+ V0(T),
+ V1(<T::As1 as Tr2>::As2),
+ V2(&'static T::As1),
+ V3(<T::As1 as Tr5>::As5),
+}
+
+enum _En7<'a, 'b, T> // `<T::As1 as Tr2>::As2: 'a` is implied.
+where
+ T: Tr1<As1: Tr2>,
+{
+ V0(&'a T),
+ V1(&'b <T::As1 as Tr2>::As2),
+}
+
+fn _make_en7<'a, 'b, T>(x: _En7<'a, 'b, T>)
+where
+ T: Tr1<As1: Tr2>,
+{
+ match x {
+ _En7::V0(x) => {
+ let _: &'a T = &x;
+ },
+ _En7::V1(_) => {},
+ }
+}
+
+enum EnSelf<T> where Self: Tr1<As1: Tr2> {
+ V0(T),
+ V1(<Self as Tr1>::As1),
+ V2(<<Self as Tr1>::As1 as Tr2>::As2),
+}
+
+impl Tr1 for EnSelf<&'static str> { type As1 = bool; }
+
+fn main() {
+ if let En1::Outest("foo") = wrap_en1_1::<_>("foo") {} else { panic!() };
+ if let En1::Outer(true) = wrap_en1_2::<&str>(true) {} else { panic!() };
+ if let En1::Inner(24u8) = wrap_en1_3::<&str>(24u8) {} else { panic!() };
+
+ let _ = En2::<_>::V0("151571");
+ let _ = En2::<&str>::V1(false);
+ let _ = En2::<&str>::V2(42u8);
+ let _ = En2::<&str>::V3(|| 12u8);
+
+ let _ = En3::<_>::V0("deadbeef");
+ let _ = En3::<&str>::V1(&true);
+
+ let f1 = (1,);
+ let f2 = (2,);
+ let _ = En4::<()>::V0(&f1.0);
+ let _ = En4::<()>::V1(&f2.0);
+
+ let _ = En6::<_>::V0("bar");
+ let _ = En6::<&str>::V1(24u8);
+ let _ = En6::<&str>::V2(&false);
+ let _ = En6::<&str>::V3(12u16);
+
+ let _ = EnSelf::<_>::V0("foo");
+ let _ = EnSelf::<&'static str>::V1(true);
+ let _ = EnSelf::<&'static str>::V2(24u8);
+}
diff --git a/src/test/ui/associated-type-bounds/fn-apit.rs b/src/test/ui/associated-type-bounds/fn-apit.rs
new file mode 100644
index 000000000..3c9f51133
--- /dev/null
+++ b/src/test/ui/associated-type-bounds/fn-apit.rs
@@ -0,0 +1,59 @@
+// run-pass
+// aux-build:fn-aux.rs
+
+#![allow(unused)]
+#![feature(associated_type_bounds)]
+
+extern crate fn_aux;
+
+use fn_aux::*;
+
+fn apit_bound(beta: impl Beta<Gamma: Alpha>) -> usize {
+ desugared_bound(beta)
+}
+
+fn apit_bound_region(beta: impl Beta<Gamma: 'static>) -> usize {
+ desugared_bound_region(beta)
+}
+
+fn apit_bound_multi(
+ beta: impl Copy + Beta<Gamma: Alpha + 'static + Delta>
+) -> usize {
+ desugared_bound_multi(beta)
+}
+
+fn apit_bound_region_forall(
+ beta: impl Beta<Gamma: Copy + for<'a> Epsilon<'a>>
+) -> usize {
+ desugared_bound_region_forall(beta)
+}
+
+fn apit_bound_region_forall2(
+ beta: impl Beta<Gamma: Copy + for<'a> Epsilon<'a, Zeta: Eta>>
+) -> usize {
+ desugared_bound_region_forall2(beta)
+}
+
+fn apit_bound_nested(
+ beta: impl Beta<Gamma: Copy + Alpha + Beta<Gamma: Delta>>
+) -> usize {
+ desugared_bound_nested(beta)
+}
+
+fn apit_bound_nested2(
+ beta: impl Beta<Gamma = impl Copy + Alpha + Beta<Gamma: Delta>>
+) -> usize {
+ desugared_bound_nested(beta)
+}
+
+fn main() {
+ let beta = BetaType;
+ let _gamma = beta.gamma();
+
+ assert_eq!(42, apit_bound(beta));
+ assert_eq!(24, apit_bound_region(beta));
+ assert_eq!(42 + 24 + 1337, apit_bound_multi(beta));
+ assert_eq!(7331 * 2, apit_bound_region_forall(beta));
+ assert_eq!(42 + 1337, apit_bound_nested(beta));
+ assert_eq!(42 + 1337, apit_bound_nested2(beta));
+}
diff --git a/src/test/ui/associated-type-bounds/fn-aux.rs b/src/test/ui/associated-type-bounds/fn-aux.rs
new file mode 100644
index 000000000..434bdbe99
--- /dev/null
+++ b/src/test/ui/associated-type-bounds/fn-aux.rs
@@ -0,0 +1,12 @@
+// run-pass
+// aux-build:fn-aux.rs
+
+#![feature(associated_type_bounds)]
+
+extern crate fn_aux;
+
+use fn_aux::*;
+
+fn main() {
+ desugared();
+}
diff --git a/src/test/ui/associated-type-bounds/fn-dyn-apit.rs b/src/test/ui/associated-type-bounds/fn-dyn-apit.rs
new file mode 100644
index 000000000..c4e8092c2
--- /dev/null
+++ b/src/test/ui/associated-type-bounds/fn-dyn-apit.rs
@@ -0,0 +1,61 @@
+// run-pass
+// aux-build:fn-dyn-aux.rs
+
+#![allow(unused)]
+#![feature(associated_type_bounds)]
+
+extern crate fn_dyn_aux;
+
+use fn_dyn_aux::*;
+
+// ATB, APIT (dyn trait):
+
+fn dyn_apit_bound(beta: &dyn Beta<Gamma: Alpha>) -> usize {
+ desugared_bound(beta)
+}
+
+fn dyn_apit_bound_region(beta: &dyn Beta<Gamma: 'static>) -> usize {
+ desugared_bound_region(beta)
+}
+
+fn dyn_apit_bound_multi(
+ beta: &(dyn Beta<Gamma: Alpha + 'static + Delta> + Send)
+) -> usize {
+ desugared_bound_multi(beta)
+}
+
+fn dyn_apit_bound_region_forall(
+ beta: &dyn Beta<Gamma: Copy + for<'a> Epsilon<'a>>
+) -> usize {
+ desugared_bound_region_forall(beta)
+}
+
+fn dyn_apit_bound_region_forall2(
+ beta: &dyn Beta<Gamma: Copy + for<'a> Epsilon<'a, Zeta: Eta>>
+) -> usize {
+ desugared_bound_region_forall2(beta)
+}
+
+fn dyn_apit_bound_nested(
+ beta: &dyn Beta<Gamma: Copy + Alpha + Beta<Gamma: Delta>>
+) -> usize {
+ desugared_bound_nested(beta)
+}
+
+fn dyn_apit_bound_nested2(
+ beta: &dyn Beta<Gamma = impl Copy + Alpha + Beta<Gamma: Delta>>
+) -> usize {
+ desugared_bound_nested(beta)
+}
+
+fn main() {
+ let beta = BetaType;
+ let _gamma = beta.gamma();
+
+ assert_eq!(42, dyn_apit_bound(&beta));
+ assert_eq!(24, dyn_apit_bound_region(&beta));
+ assert_eq!(42 + 24 + 1337, dyn_apit_bound_multi(&beta));
+ assert_eq!(7331 * 2, dyn_apit_bound_region_forall(&beta));
+ assert_eq!(42 + 1337, dyn_apit_bound_nested(&beta));
+ assert_eq!(42 + 1337, dyn_apit_bound_nested2(&beta));
+}
diff --git a/src/test/ui/associated-type-bounds/fn-inline.rs b/src/test/ui/associated-type-bounds/fn-inline.rs
new file mode 100644
index 000000000..8fa7212d6
--- /dev/null
+++ b/src/test/ui/associated-type-bounds/fn-inline.rs
@@ -0,0 +1,63 @@
+// run-pass
+// aux-build:fn-aux.rs
+
+#![allow(unused)]
+#![feature(associated_type_bounds)]
+
+extern crate fn_aux;
+
+use fn_aux::*;
+
+// ATB, Type parameters, Inline bounds:
+
+fn inline_bound<B: Beta<Gamma: Alpha>>(beta: B) -> usize {
+ desugared_bound(beta)
+}
+
+fn inline_bound_region<B: Beta<Gamma: 'static>>(beta: B) -> usize {
+ desugared_bound_region(beta)
+}
+
+fn inline_bound_multi<B: Copy + Beta<Gamma: Alpha + 'static + Delta>>(
+ beta: B
+) -> usize {
+ desugared_bound_multi(beta)
+}
+
+fn inline_bound_region_specific<'a, B: Beta<Gamma: 'a + Epsilon<'a>>>(
+ gamma: &'a B::Gamma
+) -> usize {
+ desugared_bound_region_specific::<B>(gamma)
+}
+
+fn inline_bound_region_forall<B: Beta<Gamma: Copy + for<'a> Epsilon<'a>>>(
+ beta: B
+) -> usize {
+ desugared_bound_region_forall(beta)
+}
+
+fn inline_bound_region_forall2<B: Beta<Gamma: Copy + for<'a> Epsilon<'a, Zeta: Eta>>>(
+ beta: B
+) -> usize {
+ desugared_bound_region_forall2(beta)
+}
+
+fn inline_bound_nested<B: Beta<Gamma: Copy + Alpha + Beta<Gamma: Delta>>>(
+ beta: B
+) -> usize {
+ desugared_bound_nested(beta)
+}
+
+fn main() {
+ let beta = BetaType;
+ let gamma = beta.gamma();
+
+ assert_eq!(42, inline_bound(beta));
+ assert_eq!(24, inline_bound_region(beta));
+ assert_eq!(42 + 24 + 1337, inline_bound_multi(beta));
+ assert_eq!(7331, inline_bound_region_specific::<BetaType>(&gamma));
+ assert_eq!(7331 * 2, inline_bound_region_forall(beta));
+ // FIXME: requires lazy normalization.
+ // assert_eq!(7331 * 2, inline_bound_region_forall2(beta));
+ assert_eq!(42 + 1337, inline_bound_nested(beta));
+}
diff --git a/src/test/ui/associated-type-bounds/fn-where.rs b/src/test/ui/associated-type-bounds/fn-where.rs
new file mode 100644
index 000000000..9c4f82ac9
--- /dev/null
+++ b/src/test/ui/associated-type-bounds/fn-where.rs
@@ -0,0 +1,79 @@
+// run-pass
+// aux-build:fn-aux.rs
+
+#![allow(unused)]
+#![feature(associated_type_bounds)]
+
+extern crate fn_aux;
+
+use fn_aux::*;
+
+// ATB, Type parameters, Where-clauses:
+
+fn where_bound<B>(beta: B) -> usize
+where
+ B: Beta<Gamma: Alpha>
+{
+ desugared_bound(beta)
+}
+
+fn where_bound_region<B>(beta: B) -> usize
+where
+ B: Beta<Gamma: 'static>
+{
+ desugared_bound_region(beta)
+}
+
+fn where_bound_multi<B>(beta: B) -> usize
+where
+ B: Copy + Beta<Gamma: Alpha + 'static + Delta>,
+{
+ desugared_bound_multi(beta)
+}
+
+fn where_bound_region_specific<'a, B>(gamma: &'a B::Gamma) -> usize
+where
+ B: Beta<Gamma: 'a + Epsilon<'a>>,
+{
+ desugared_bound_region_specific::<B>(gamma)
+}
+
+fn where_bound_region_forall<B>(beta: B) -> usize
+where
+ B: Beta<Gamma: Copy + for<'a> Epsilon<'a>>,
+{
+ desugared_bound_region_forall(beta)
+}
+
+fn where_bound_region_forall2<B>(beta: B) -> usize
+where
+ B: Beta<Gamma: Copy + for<'a> Epsilon<'a, Zeta: Eta>>,
+{
+ desugared_bound_region_forall2(beta)
+}
+
+fn where_contraint_region_forall<B>(beta: B) -> usize
+where
+ for<'a> &'a B: Beta<Gamma: Alpha>,
+{
+ desugared_contraint_region_forall(beta)
+}
+
+fn where_bound_nested<B>(beta: B) -> usize
+where
+ B: Beta<Gamma: Copy + Alpha + Beta<Gamma: Delta>>,
+{
+ desugared_bound_nested(beta)
+}
+
+fn main() {
+ let beta = BetaType;
+ let gamma = beta.gamma();
+
+ assert_eq!(42, where_bound(beta));
+ assert_eq!(24, where_bound_region(beta));
+ assert_eq!(42 + 24 + 1337, where_bound_multi(beta));
+ assert_eq!(7331, where_bound_region_specific::<BetaType>(&gamma));
+ assert_eq!(7331 * 2, where_bound_region_forall::<BetaType>(beta));
+ assert_eq!(42 + 1337, where_bound_nested::<BetaType>(beta));
+}
diff --git a/src/test/ui/associated-type-bounds/fn-wrap-apit.rs b/src/test/ui/associated-type-bounds/fn-wrap-apit.rs
new file mode 100644
index 000000000..96df13e37
--- /dev/null
+++ b/src/test/ui/associated-type-bounds/fn-wrap-apit.rs
@@ -0,0 +1,65 @@
+// run-pass
+// aux-build:fn-aux.rs
+
+#![feature(associated_type_bounds)]
+#![allow(dead_code)]
+
+extern crate fn_aux;
+
+use fn_aux::*;
+
+// ATB, APIT + Wrap:
+
+struct Wrap<T>(T);
+
+fn wrap_apit_bound(beta: Wrap<impl Beta<Gamma: Alpha>>) -> usize {
+ desugared_bound(beta.0)
+}
+
+fn wrap_apit_bound_region(beta: Wrap<impl Beta<Gamma: 'static>>) -> usize {
+ desugared_bound_region(beta.0)
+}
+
+fn wrap_apit_bound_multi(
+ beta: Wrap<impl Copy + Beta<Gamma: Alpha + 'static + Delta>>
+) -> usize {
+ desugared_bound_multi(beta.0)
+}
+
+fn wrap_apit_bound_region_forall(
+ beta: Wrap<impl Beta<Gamma: Copy + for<'a> Epsilon<'a>>>
+) -> usize {
+ desugared_bound_region_forall(beta.0)
+}
+
+fn wrap_apit_bound_region_forall2(
+ beta: Wrap<impl Beta<Gamma: Copy + for<'a> Epsilon<'a, Zeta: Eta>>>
+) -> usize {
+ desugared_bound_region_forall2(beta.0)
+}
+
+fn wrap_apit_bound_nested(
+ beta: Wrap<impl Beta<Gamma: Copy + Alpha + Beta<Gamma: Delta>>>
+) -> usize {
+ desugared_bound_nested(beta.0)
+}
+
+fn wrap_apit_bound_nested2(
+ beta: Wrap<impl Beta<Gamma = impl Copy + Alpha + Beta<Gamma: Delta>>>
+) -> usize {
+ desugared_bound_nested(beta.0)
+}
+
+fn main() {
+ let beta = BetaType;
+ let _gamma = beta.gamma();
+
+ assert_eq!(42, wrap_apit_bound(Wrap(beta)));
+ assert_eq!(24, wrap_apit_bound_region(Wrap(beta)));
+ assert_eq!(42 + 24 + 1337, wrap_apit_bound_multi(Wrap(beta)));
+ assert_eq!(7331 * 2, wrap_apit_bound_region_forall(Wrap(beta)));
+ // FIXME: requires lazy normalization.
+ // assert_eq!(7331 * 2, wrap_apit_bound_region_forall2(Wrap(beta)));
+ assert_eq!(42 + 1337, wrap_apit_bound_nested(Wrap(beta)));
+ assert_eq!(42 + 1337, wrap_apit_bound_nested2(Wrap(beta)));
+}
diff --git a/src/test/ui/associated-type-bounds/handle-predicates-that-can-define-assoc-type.rs b/src/test/ui/associated-type-bounds/handle-predicates-that-can-define-assoc-type.rs
new file mode 100644
index 000000000..b1e54ec04
--- /dev/null
+++ b/src/test/ui/associated-type-bounds/handle-predicates-that-can-define-assoc-type.rs
@@ -0,0 +1,10 @@
+// check-pass
+
+trait Foo<T> {}
+trait Bar {
+ type A;
+ type B;
+}
+trait Baz: Bar<B = u32> + Foo<Self::A> {}
+
+fn main() {}
diff --git a/src/test/ui/associated-type-bounds/hrtb.rs b/src/test/ui/associated-type-bounds/hrtb.rs
new file mode 100644
index 000000000..7ab383649
--- /dev/null
+++ b/src/test/ui/associated-type-bounds/hrtb.rs
@@ -0,0 +1,65 @@
+// check-pass
+
+#![feature(associated_type_bounds)]
+
+trait A<'a> {}
+trait B<'b> {}
+fn foo<T>()
+where
+ for<'a> T: A<'a> + 'a,
+{
+}
+trait C<'c>: for<'a> A<'a> + for<'b> B<'b> {
+ type As;
+}
+struct D<T>
+where
+ T: for<'c> C<'c, As: A<'c>>,
+{
+ t: std::marker::PhantomData<T>,
+}
+
+trait E<'e> {
+ type As;
+}
+trait F<'f>: for<'a> A<'a> + for<'e> E<'e> {}
+struct G<T>
+where
+ for<'f> T: F<'f, As: E<'f>> + 'f,
+{
+ t: std::marker::PhantomData<T>,
+}
+
+trait I<'a, 'b, 'c> {
+ type As;
+}
+trait H<'d, 'e>: for<'f> I<'d, 'f, 'e> + 'd {}
+fn foo2<T>()
+where
+ T: for<'g> H<'g, 'g, As: for<'h> H<'h, 'g> + 'g>,
+{
+}
+
+fn foo3<T>()
+where
+ T: for<'i> H<'i, 'i, As: for<'j> H<'j, 'i, As: for<'k> I<'i, 'k, 'j> + 'j> + 'i>,
+{
+}
+fn foo4<T>()
+where
+ T: for<'l, 'i> H<'l, 'i, As: for<'j> H<'j, 'i, As: for<'k> I<'l, 'k, 'j> + 'j> + 'i>,
+{
+}
+
+struct X<'x, 'y> {
+ x: std::marker::PhantomData<&'x ()>,
+ y: std::marker::PhantomData<&'y ()>,
+}
+
+fn foo5<T>()
+where
+ T: for<'l, 'i> H<'l, 'i, As: for<'j> H<'j, 'i, As: for<'k> H<'j, 'k, As = X<'j, 'k>> + 'j> + 'i>
+{
+}
+
+fn main() {}
diff --git a/src/test/ui/associated-type-bounds/implied-region-constraints.rs b/src/test/ui/associated-type-bounds/implied-region-constraints.rs
new file mode 100644
index 000000000..38219da61
--- /dev/null
+++ b/src/test/ui/associated-type-bounds/implied-region-constraints.rs
@@ -0,0 +1,45 @@
+#![feature(associated_type_bounds)]
+
+trait Tr1 { type As1; }
+trait Tr2 { type As2; }
+
+struct St<'a, 'b, T: Tr1<As1: Tr2>> { // `T: 'b` is *not* implied!
+ f0: &'a T, // `T: 'a` is implied.
+ f1: &'b <T::As1 as Tr2>::As2, // `<T::As1 as Tr2>::As2: 'a` is implied.
+}
+
+fn _bad_st<'a, 'b, T>(x: St<'a, 'b, T>)
+where
+ T: Tr1,
+ T::As1: Tr2,
+{
+ // This should fail because `T: 'b` is not implied from `WF(St<'a, 'b, T>)`.
+ let _failure_proves_not_implied_outlives_region_b: &'b T = &x.f0;
+ //~^ ERROR lifetime may not live long enough
+}
+
+enum En7<'a, 'b, T> // `<T::As1 as Tr2>::As2: 'a` is implied.
+where
+ T: Tr1,
+ T::As1: Tr2,
+{
+ V0(&'a T),
+ V1(&'b <T::As1 as Tr2>::As2),
+}
+
+fn _bad_en7<'a, 'b, T>(x: En7<'a, 'b, T>)
+where
+ T: Tr1,
+ T::As1: Tr2,
+{
+ match x {
+ En7::V0(x) => {
+ // Also fails for the same reason as above:
+ let _failure_proves_not_implied_outlives_region_b: &'b T = &x;
+ //~^ ERROR lifetime may not live long enough
+ },
+ En7::V1(_) => {},
+ }
+}
+
+fn main() {}
diff --git a/src/test/ui/associated-type-bounds/implied-region-constraints.stderr b/src/test/ui/associated-type-bounds/implied-region-constraints.stderr
new file mode 100644
index 000000000..cddce8777
--- /dev/null
+++ b/src/test/ui/associated-type-bounds/implied-region-constraints.stderr
@@ -0,0 +1,28 @@
+error: lifetime may not live long enough
+ --> $DIR/implied-region-constraints.rs:17:56
+ |
+LL | fn _bad_st<'a, 'b, T>(x: St<'a, 'b, T>)
+ | -- -- lifetime `'b` defined here
+ | |
+ | lifetime `'a` defined here
+...
+LL | let _failure_proves_not_implied_outlives_region_b: &'b T = &x.f0;
+ | ^^^^^ type annotation requires that `'a` must outlive `'b`
+ |
+ = help: consider adding the following bound: `'a: 'b`
+
+error: lifetime may not live long enough
+ --> $DIR/implied-region-constraints.rs:38:64
+ |
+LL | fn _bad_en7<'a, 'b, T>(x: En7<'a, 'b, T>)
+ | -- -- lifetime `'b` defined here
+ | |
+ | lifetime `'a` defined here
+...
+LL | let _failure_proves_not_implied_outlives_region_b: &'b T = &x;
+ | ^^^^^ type annotation requires that `'a` must outlive `'b`
+ |
+ = help: consider adding the following bound: `'a: 'b`
+
+error: aborting due to 2 previous errors
+
diff --git a/src/test/ui/associated-type-bounds/inside-adt.rs b/src/test/ui/associated-type-bounds/inside-adt.rs
new file mode 100644
index 000000000..f26037f07
--- /dev/null
+++ b/src/test/ui/associated-type-bounds/inside-adt.rs
@@ -0,0 +1,30 @@
+#![feature(associated_type_bounds)]
+
+use std::mem::ManuallyDrop;
+
+struct S1 { f: dyn Iterator<Item: Copy> }
+//~^ ERROR associated type bounds are not allowed within structs, enums, or unions
+struct S2 { f: Box<dyn Iterator<Item: Copy>> }
+//~^ ERROR associated type bounds are not allowed within structs, enums, or unions
+struct S3 { f: dyn Iterator<Item: 'static> }
+//~^ ERROR associated type bounds are not allowed within structs, enums, or unions
+
+enum E1 { V(dyn Iterator<Item: Copy>) }
+//~^ ERROR associated type bounds are not allowed within structs, enums, or unions
+//~| ERROR the size for values of type `(dyn Iterator<Item = impl Copy> + 'static)`
+enum E2 { V(Box<dyn Iterator<Item: Copy>>) }
+//~^ ERROR associated type bounds are not allowed within structs, enums, or unions
+enum E3 { V(dyn Iterator<Item: 'static>) }
+//~^ ERROR associated type bounds are not allowed within structs, enums, or unions
+//~| ERROR the size for values of type `(dyn Iterator<Item = impl Sized> + 'static)`
+
+union U1 { f: ManuallyDrop<dyn Iterator<Item: Copy>> }
+//~^ ERROR associated type bounds are not allowed within structs, enums, or unions
+//~| ERROR the size for values of type `(dyn Iterator<Item = impl Copy> + 'static)`
+union U2 { f: ManuallyDrop<Box<dyn Iterator<Item: Copy>>> }
+//~^ ERROR associated type bounds are not allowed within structs, enums, or unions
+union U3 { f: ManuallyDrop<dyn Iterator<Item: 'static>> }
+//~^ ERROR associated type bounds are not allowed within structs, enums, or unions
+//~| ERROR the size for values of type `(dyn Iterator<Item = impl Sized> + 'static)`
+
+fn main() {}
diff --git a/src/test/ui/associated-type-bounds/inside-adt.stderr b/src/test/ui/associated-type-bounds/inside-adt.stderr
new file mode 100644
index 000000000..978390fa7
--- /dev/null
+++ b/src/test/ui/associated-type-bounds/inside-adt.stderr
@@ -0,0 +1,131 @@
+error: associated type bounds are not allowed within structs, enums, or unions
+ --> $DIR/inside-adt.rs:5:29
+ |
+LL | struct S1 { f: dyn Iterator<Item: Copy> }
+ | ^^^^^^^^^^
+
+error: associated type bounds are not allowed within structs, enums, or unions
+ --> $DIR/inside-adt.rs:7:33
+ |
+LL | struct S2 { f: Box<dyn Iterator<Item: Copy>> }
+ | ^^^^^^^^^^
+
+error: associated type bounds are not allowed within structs, enums, or unions
+ --> $DIR/inside-adt.rs:9:29
+ |
+LL | struct S3 { f: dyn Iterator<Item: 'static> }
+ | ^^^^^^^^^^^^^
+
+error: associated type bounds are not allowed within structs, enums, or unions
+ --> $DIR/inside-adt.rs:12:26
+ |
+LL | enum E1 { V(dyn Iterator<Item: Copy>) }
+ | ^^^^^^^^^^
+
+error: associated type bounds are not allowed within structs, enums, or unions
+ --> $DIR/inside-adt.rs:15:30
+ |
+LL | enum E2 { V(Box<dyn Iterator<Item: Copy>>) }
+ | ^^^^^^^^^^
+
+error: associated type bounds are not allowed within structs, enums, or unions
+ --> $DIR/inside-adt.rs:17:26
+ |
+LL | enum E3 { V(dyn Iterator<Item: 'static>) }
+ | ^^^^^^^^^^^^^
+
+error: associated type bounds are not allowed within structs, enums, or unions
+ --> $DIR/inside-adt.rs:21:41
+ |
+LL | union U1 { f: ManuallyDrop<dyn Iterator<Item: Copy>> }
+ | ^^^^^^^^^^
+
+error: associated type bounds are not allowed within structs, enums, or unions
+ --> $DIR/inside-adt.rs:24:45
+ |
+LL | union U2 { f: ManuallyDrop<Box<dyn Iterator<Item: Copy>>> }
+ | ^^^^^^^^^^
+
+error: associated type bounds are not allowed within structs, enums, or unions
+ --> $DIR/inside-adt.rs:26:41
+ |
+LL | union U3 { f: ManuallyDrop<dyn Iterator<Item: 'static>> }
+ | ^^^^^^^^^^^^^
+
+error[E0277]: the size for values of type `(dyn Iterator<Item = impl Copy> + 'static)` cannot be known at compilation time
+ --> $DIR/inside-adt.rs:12:13
+ |
+LL | enum E1 { V(dyn Iterator<Item: Copy>) }
+ | ^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
+ |
+ = help: the trait `Sized` is not implemented for `(dyn Iterator<Item = impl Copy> + 'static)`
+ = note: no field of an enum variant may have a dynamically sized type
+ = help: change the field's type to have a statically known size
+help: borrowed types always have a statically known size
+ |
+LL | enum E1 { V(&dyn Iterator<Item: Copy>) }
+ | +
+help: the `Box` type always has a statically known size and allocates its contents in the heap
+ |
+LL | enum E1 { V(Box<dyn Iterator<Item: Copy>>) }
+ | ++++ +
+
+error[E0277]: the size for values of type `(dyn Iterator<Item = impl Sized> + 'static)` cannot be known at compilation time
+ --> $DIR/inside-adt.rs:17:13
+ |
+LL | enum E3 { V(dyn Iterator<Item: 'static>) }
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
+ |
+ = help: the trait `Sized` is not implemented for `(dyn Iterator<Item = impl Sized> + 'static)`
+ = note: no field of an enum variant may have a dynamically sized type
+ = help: change the field's type to have a statically known size
+help: borrowed types always have a statically known size
+ |
+LL | enum E3 { V(&dyn Iterator<Item: 'static>) }
+ | +
+help: the `Box` type always has a statically known size and allocates its contents in the heap
+ |
+LL | enum E3 { V(Box<dyn Iterator<Item: 'static>>) }
+ | ++++ +
+
+error[E0277]: the size for values of type `(dyn Iterator<Item = impl Copy> + 'static)` cannot be known at compilation time
+ --> $DIR/inside-adt.rs:21:15
+ |
+LL | union U1 { f: ManuallyDrop<dyn Iterator<Item: Copy>> }
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
+ |
+ = help: within `ManuallyDrop<(dyn Iterator<Item = impl Copy> + 'static)>`, the trait `Sized` is not implemented for `(dyn Iterator<Item = impl Copy> + 'static)`
+ = note: required because it appears within the type `ManuallyDrop<(dyn Iterator<Item = impl Copy> + 'static)>`
+ = note: no field of a union may have a dynamically sized type
+ = help: change the field's type to have a statically known size
+help: borrowed types always have a statically known size
+ |
+LL | union U1 { f: &ManuallyDrop<dyn Iterator<Item: Copy>> }
+ | +
+help: the `Box` type always has a statically known size and allocates its contents in the heap
+ |
+LL | union U1 { f: Box<ManuallyDrop<dyn Iterator<Item: Copy>>> }
+ | ++++ +
+
+error[E0277]: the size for values of type `(dyn Iterator<Item = impl Sized> + 'static)` cannot be known at compilation time
+ --> $DIR/inside-adt.rs:26:15
+ |
+LL | union U3 { f: ManuallyDrop<dyn Iterator<Item: 'static>> }
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
+ |
+ = help: within `ManuallyDrop<(dyn Iterator<Item = impl Sized> + 'static)>`, the trait `Sized` is not implemented for `(dyn Iterator<Item = impl Sized> + 'static)`
+ = note: required because it appears within the type `ManuallyDrop<(dyn Iterator<Item = impl Sized> + 'static)>`
+ = note: no field of a union may have a dynamically sized type
+ = help: change the field's type to have a statically known size
+help: borrowed types always have a statically known size
+ |
+LL | union U3 { f: &ManuallyDrop<dyn Iterator<Item: 'static>> }
+ | +
+help: the `Box` type always has a statically known size and allocates its contents in the heap
+ |
+LL | union U3 { f: Box<ManuallyDrop<dyn Iterator<Item: 'static>>> }
+ | ++++ +
+
+error: aborting due to 13 previous errors
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/associated-type-bounds/issue-61752.rs b/src/test/ui/associated-type-bounds/issue-61752.rs
new file mode 100644
index 000000000..f38ec640e
--- /dev/null
+++ b/src/test/ui/associated-type-bounds/issue-61752.rs
@@ -0,0 +1,24 @@
+// check-pass
+
+#![feature(associated_type_bounds)]
+
+trait Foo {
+ type Bar;
+}
+
+impl Foo for () {
+ type Bar = ();
+}
+
+fn a<F: Foo>() where F::Bar: Copy {}
+
+fn b<F: Foo>() where <F as Foo>::Bar: Copy {}
+
+// This used to complain about ambiguous associated types.
+fn c<F: Foo<Bar: Foo>>() where F::Bar: Copy {}
+
+fn main() {
+ a::<()>();
+ b::<()>();
+ c::<()>();
+}
diff --git a/src/test/ui/associated-type-bounds/issue-70292.rs b/src/test/ui/associated-type-bounds/issue-70292.rs
new file mode 100644
index 000000000..945d7688c
--- /dev/null
+++ b/src/test/ui/associated-type-bounds/issue-70292.rs
@@ -0,0 +1,21 @@
+// check-pass
+
+#![feature(associated_type_bounds)]
+
+fn foo<F>(_: F)
+where
+ F: for<'a> Trait<Output: 'a>,
+{
+}
+
+trait Trait {
+ type Output;
+}
+
+impl<T> Trait for T {
+ type Output = ();
+}
+
+fn main() {
+ foo(());
+}
diff --git a/src/test/ui/associated-type-bounds/issue-71443-1.rs b/src/test/ui/associated-type-bounds/issue-71443-1.rs
new file mode 100644
index 000000000..5d2a3e6cb
--- /dev/null
+++ b/src/test/ui/associated-type-bounds/issue-71443-1.rs
@@ -0,0 +1,9 @@
+#![feature(associated_type_bounds)]
+
+struct Incorrect;
+
+fn hello<F: for<'a> Iterator<Item: 'a>>() {
+ Incorrect //~ERROR: mismatched types
+}
+
+fn main() {}
diff --git a/src/test/ui/associated-type-bounds/issue-71443-1.stderr b/src/test/ui/associated-type-bounds/issue-71443-1.stderr
new file mode 100644
index 000000000..a9459ee74
--- /dev/null
+++ b/src/test/ui/associated-type-bounds/issue-71443-1.stderr
@@ -0,0 +1,11 @@
+error[E0308]: mismatched types
+ --> $DIR/issue-71443-1.rs:6:5
+ |
+LL | fn hello<F: for<'a> Iterator<Item: 'a>>() {
+ | - help: try adding a return type: `-> Incorrect`
+LL | Incorrect
+ | ^^^^^^^^^ expected `()`, found struct `Incorrect`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/associated-type-bounds/issue-71443-2.rs b/src/test/ui/associated-type-bounds/issue-71443-2.rs
new file mode 100644
index 000000000..813dcd60a
--- /dev/null
+++ b/src/test/ui/associated-type-bounds/issue-71443-2.rs
@@ -0,0 +1,11 @@
+// check-pass
+
+#![feature(associated_type_bounds)]
+
+fn hello<'b, F>()
+where
+ for<'a> F: Iterator<Item: 'a> + 'b,
+{
+}
+
+fn main() {}
diff --git a/src/test/ui/associated-type-bounds/issue-73818.rs b/src/test/ui/associated-type-bounds/issue-73818.rs
new file mode 100644
index 000000000..bb890f72a
--- /dev/null
+++ b/src/test/ui/associated-type-bounds/issue-73818.rs
@@ -0,0 +1,25 @@
+// Test that associated type bounds are correctly normalized when checking
+// default associated type values.
+// check-pass
+
+#![allow(incomplete_features)]
+#![feature(specialization)]
+
+#[derive(PartialEq)]
+enum Never {}
+trait Foo {
+ type Assoc: PartialEq; // PartialEq<<Self as Foo>::Assoc>
+}
+impl<T> Foo for T {
+ default type Assoc = Never;
+}
+
+trait Trait1 {
+ type Selection: PartialEq;
+}
+trait Trait2: PartialEq<Self> {}
+impl<T: Trait2> Trait1 for T {
+ default type Selection = T;
+}
+
+fn main() {}
diff --git a/src/test/ui/associated-type-bounds/issue-79949.rs b/src/test/ui/associated-type-bounds/issue-79949.rs
new file mode 100644
index 000000000..9f924f1fd
--- /dev/null
+++ b/src/test/ui/associated-type-bounds/issue-79949.rs
@@ -0,0 +1,26 @@
+// check-pass
+
+#![allow(incomplete_features)]
+#![feature(associated_type_bounds)]
+#![feature(generic_associated_types)]
+
+trait MP {
+ type T<'a>;
+}
+struct S(String);
+impl MP for S {
+ type T<'a> = &'a str;
+}
+
+trait SR: MP {
+ fn sr<IM>(&self) -> i32
+ where
+ for<'a> IM: T<T: U<<Self as MP>::T<'a>>>;
+}
+
+trait T {
+ type T;
+}
+trait U<X> {}
+
+fn main() {}
diff --git a/src/test/ui/associated-type-bounds/issue-81193.rs b/src/test/ui/associated-type-bounds/issue-81193.rs
new file mode 100644
index 000000000..d2aa54ab9
--- /dev/null
+++ b/src/test/ui/associated-type-bounds/issue-81193.rs
@@ -0,0 +1,15 @@
+// check-pass
+
+#![feature(associated_type_bounds)]
+
+trait A<'a, 'b> {}
+
+trait B<'a, 'b, 'c> {}
+
+fn err<'u, 'a, F>()
+where
+ for<'b> F: Iterator<Item: for<'c> B<'a, 'b, 'c> + for<'c> A<'a, 'c>>,
+{
+}
+
+fn main() {}
diff --git a/src/test/ui/associated-type-bounds/issue-83017.rs b/src/test/ui/associated-type-bounds/issue-83017.rs
new file mode 100644
index 000000000..a02208661
--- /dev/null
+++ b/src/test/ui/associated-type-bounds/issue-83017.rs
@@ -0,0 +1,39 @@
+// check-pass
+
+#![feature(associated_type_bounds)]
+
+trait TraitA<'a> {
+ type AsA;
+}
+
+trait TraitB<'a, 'b> {
+ type AsB;
+}
+
+trait TraitC<'a, 'b, 'c> {}
+
+struct X;
+
+impl<'a, 'b, 'c> TraitC<'a, 'b, 'c> for X {}
+
+struct Y;
+
+impl<'a, 'b> TraitB<'a, 'b> for Y {
+ type AsB = X;
+}
+
+struct Z;
+
+impl<'a> TraitA<'a> for Z {
+ type AsA = Y;
+}
+
+fn foo<T>()
+where
+ for<'a> T: TraitA<'a, AsA: for<'b> TraitB<'a, 'b, AsB: for<'c> TraitC<'a, 'b, 'c>>>,
+{
+}
+
+fn main() {
+ foo::<Z>();
+}
diff --git a/src/test/ui/associated-type-bounds/issue-99828.rs b/src/test/ui/associated-type-bounds/issue-99828.rs
new file mode 100644
index 000000000..7b711283f
--- /dev/null
+++ b/src/test/ui/associated-type-bounds/issue-99828.rs
@@ -0,0 +1,11 @@
+fn get_iter(vec: &[i32]) -> impl Iterator<Item = {}> + '_ {
+ //~^ ERROR expected associated type bound, found constant
+ //~| ERROR associated const equality is incomplete
+ vec.iter()
+}
+
+fn main() {
+ let vec = Vec::new();
+ let mut iter = get_iter(&vec);
+ iter.next();
+}
diff --git a/src/test/ui/associated-type-bounds/issue-99828.stderr b/src/test/ui/associated-type-bounds/issue-99828.stderr
new file mode 100644
index 000000000..1c20ead05
--- /dev/null
+++ b/src/test/ui/associated-type-bounds/issue-99828.stderr
@@ -0,0 +1,24 @@
+error[E0658]: associated const equality is incomplete
+ --> $DIR/issue-99828.rs:1:43
+ |
+LL | fn get_iter(vec: &[i32]) -> impl Iterator<Item = {}> + '_ {
+ | ^^^^^^^^^
+ |
+ = note: see issue #92827 <https://github.com/rust-lang/rust/issues/92827> for more information
+ = help: add `#![feature(associated_const_equality)]` to the crate attributes to enable
+
+error: expected associated type bound, found constant
+ --> $DIR/issue-99828.rs:1:43
+ |
+LL | fn get_iter(vec: &[i32]) -> impl Iterator<Item = {}> + '_ {
+ | ^^^^^^^^^
+ |
+note: associated type defined here
+ --> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL
+ |
+LL | type Item;
+ | ^^^^^^^^^
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0658`.
diff --git a/src/test/ui/associated-type-bounds/missing-trait-bound-for-assoc-fails.rs b/src/test/ui/associated-type-bounds/missing-trait-bound-for-assoc-fails.rs
new file mode 100644
index 000000000..07d0f8f87
--- /dev/null
+++ b/src/test/ui/associated-type-bounds/missing-trait-bound-for-assoc-fails.rs
@@ -0,0 +1,10 @@
+#[allow(dead_code)]
+fn foo<M>(_m: M)
+where
+ M::Item: Temp,
+ //~^ ERROR cannot find trait `Temp` in this scope [E0405]
+ //~| ERROR associated type `Item` not found for `M` [E0220]
+{
+}
+
+fn main() {}
diff --git a/src/test/ui/associated-type-bounds/missing-trait-bound-for-assoc-fails.stderr b/src/test/ui/associated-type-bounds/missing-trait-bound-for-assoc-fails.stderr
new file mode 100644
index 000000000..bc2807b03
--- /dev/null
+++ b/src/test/ui/associated-type-bounds/missing-trait-bound-for-assoc-fails.stderr
@@ -0,0 +1,16 @@
+error[E0405]: cannot find trait `Temp` in this scope
+ --> $DIR/missing-trait-bound-for-assoc-fails.rs:4:14
+ |
+LL | M::Item: Temp,
+ | ^^^^ not found in this scope
+
+error[E0220]: associated type `Item` not found for `M`
+ --> $DIR/missing-trait-bound-for-assoc-fails.rs:4:8
+ |
+LL | M::Item: Temp,
+ | ^^^^ associated type `Item` not found
+
+error: aborting due to 2 previous errors
+
+Some errors have detailed explanations: E0220, E0405.
+For more information about an error, try `rustc --explain E0220`.
diff --git a/src/test/ui/associated-type-bounds/order-dependent-bounds-issue-54121.rs b/src/test/ui/associated-type-bounds/order-dependent-bounds-issue-54121.rs
new file mode 100644
index 000000000..77e4bd4d6
--- /dev/null
+++ b/src/test/ui/associated-type-bounds/order-dependent-bounds-issue-54121.rs
@@ -0,0 +1,47 @@
+// check-pass
+
+// From https://github.com/rust-lang/rust/issues/54121/
+//
+// Whether the code compiled depended on the order of the trait bounds in
+// `type T: Tr<u8, u8> + Tr<u16, u16>`
+// But both should compile as order shouldn't matter.
+
+trait Tr<A, B> {
+ fn exec(a: A, b: B);
+}
+
+trait P {
+ // This compiled successfully
+ type T: Tr<u16, u16> + Tr<u8, u8>;
+}
+
+trait Q {
+ // This didn't compile
+ type T: Tr<u8, u8> + Tr<u16, u16>;
+}
+
+#[allow(dead_code)]
+fn f<S: P>() {
+ <S as P>::T::exec(0u8, 0u8)
+}
+
+#[allow(dead_code)]
+fn g<S: Q>() {
+ // A mismatched types error was emitted on this line.
+ <S as Q>::T::exec(0u8, 0u8)
+}
+
+// Another reproduction of the same issue
+trait Trait {
+ type Type: Into<Self::Type1> + Into<Self::Type2> + Copy;
+ type Type1;
+ type Type2;
+}
+
+#[allow(dead_code)]
+fn foo<T: Trait>(x: T::Type) {
+ let _1: T::Type1 = x.into();
+ let _2: T::Type2 = x.into();
+}
+
+fn main() { }
diff --git a/src/test/ui/associated-type-bounds/rpit.rs b/src/test/ui/associated-type-bounds/rpit.rs
new file mode 100644
index 000000000..47cadf331
--- /dev/null
+++ b/src/test/ui/associated-type-bounds/rpit.rs
@@ -0,0 +1,64 @@
+// run-pass
+
+#![feature(associated_type_bounds)]
+
+use std::ops::Add;
+
+trait Tr1 { type As1; fn mk(self) -> Self::As1; }
+trait Tr2<'a> { fn tr2(self) -> &'a Self; }
+
+fn assert_copy<T: Copy>(x: T) { let _x = x; let _x = x; }
+fn assert_static<T: 'static>(_: T) {}
+fn assert_forall_tr2<T: for<'a> Tr2<'a>>(_: T) {}
+
+struct S1;
+#[derive(Copy, Clone)]
+struct S2;
+impl Tr1 for S1 { type As1 = S2; fn mk(self) -> Self::As1 { S2 } }
+
+fn def_et1() -> impl Tr1<As1: Copy> { S1 }
+pub fn use_et1() { assert_copy(def_et1().mk()); }
+
+fn def_et2() -> impl Tr1<As1: 'static> { S1 }
+pub fn use_et2() { assert_static(def_et2().mk()); }
+
+fn def_et3() -> impl Tr1<As1: Clone + Iterator<Item: Add<u8, Output: Into<u8>>>> {
+ struct A;
+ impl Tr1 for A {
+ type As1 = core::ops::Range<u8>;
+ fn mk(self) -> Self::As1 { 0..10 }
+ }
+ A
+}
+
+pub fn use_et3() {
+ let _0 = def_et3().mk().clone();
+ let mut s = 0u8;
+ for _1 in _0 {
+ let _2 = _1 + 1u8;
+ s += _2.into();
+ }
+ assert_eq!(s, (0..10).map(|x| x + 1).sum());
+}
+
+fn def_et4() -> impl Tr1<As1: for<'a> Tr2<'a>> {
+ #[derive(Copy, Clone)]
+ struct A;
+ impl Tr1 for A {
+ type As1 = A;
+ fn mk(self) -> A { A }
+ }
+ impl<'a> Tr2<'a> for A {
+ fn tr2(self) -> &'a Self { &A }
+ }
+ A
+}
+
+pub fn use_et4() { assert_forall_tr2(def_et4().mk()); }
+
+fn main() {
+ let _ = use_et1();
+ let _ = use_et2();
+ let _ = use_et3();
+ let _ = use_et4();
+}
diff --git a/src/test/ui/associated-type-bounds/struct-bounds.rs b/src/test/ui/associated-type-bounds/struct-bounds.rs
new file mode 100644
index 000000000..2c1ce1c37
--- /dev/null
+++ b/src/test/ui/associated-type-bounds/struct-bounds.rs
@@ -0,0 +1,116 @@
+// run-pass
+
+#![allow(unused)]
+#![feature(associated_type_bounds)]
+
+trait Tr1 { type As1; }
+trait Tr2 { type As2; }
+trait Tr3 {}
+trait Tr4<'a> { type As4; }
+trait Tr5 { type As5; }
+
+impl Tr1 for &str { type As1 = bool; }
+impl Tr2 for bool { type As2 = u8; }
+impl Tr3 for u8 {}
+impl Tr1 for () { type As1 = (usize,); }
+impl<'a> Tr4<'a> for (usize,) { type As4 = u8; }
+impl Tr5 for bool { type As5 = u16; }
+
+struct St1<T: Tr1<As1: Tr2>> {
+ outest: T,
+ outer: T::As1,
+ inner: <T::As1 as Tr2>::As2,
+}
+
+fn unwrap_1_st1<T: Tr1<As1: Tr2>>(x: St1<T>) -> (T, T::As1, <T::As1 as Tr2>::As2) {
+ (x.outest, x.outer, x.inner)
+}
+
+fn unwrap_2_st1<T>(x: St1<T>) -> (T, T::As1, <T::As1 as Tr2>::As2)
+where
+ T: Tr1,
+ T::As1: Tr2,
+{
+ unwrap_1_st1(x)
+}
+
+struct St2<T: Tr1<As1: Tr2<As2: Tr3>>> {
+ outest: T,
+ outer: T::As1,
+ inner: <T::As1 as Tr2>::As2,
+}
+
+struct St3<T: Tr1<As1: 'static>> {
+ outest: T,
+ outer: &'static T::As1,
+}
+
+struct St4<'x1, 'x2, T: Tr1<As1: for<'l> Tr4<'l>>> {
+ f1: &'x1 <T::As1 as Tr4<'x1>>::As4,
+ f2: &'x2 <T::As1 as Tr4<'x2>>::As4,
+}
+
+struct St5<'x1, 'x2, T: Tr1<As1: for<'l> Tr4<'l, As4: Copy>>> {
+ f1: &'x1 <T::As1 as Tr4<'x1>>::As4,
+ f2: &'x2 <T::As1 as Tr4<'x2>>::As4,
+}
+
+struct St6<T>
+where
+ T: Tr1<As1: Tr2 + 'static + Tr5>,
+{
+ f0: T,
+ f1: <T::As1 as Tr2>::As2,
+ f2: &'static T::As1,
+ f3: <T::As1 as Tr5>::As5,
+}
+
+struct St7<'a, 'b, T> // `<T::As1 as Tr2>::As2: 'a` is implied.
+where
+ T: Tr1<As1: Tr2>,
+{
+ f0: &'a T,
+ f1: &'b <T::As1 as Tr2>::As2,
+}
+
+fn _use_st7<'a, 'b, T>(x: St7<'a, 'b, T>)
+where
+ T: Tr1,
+ T::As1: Tr2,
+{
+ let _: &'a T = &x.f0;
+}
+
+struct StSelf<T> where Self: Tr1<As1: Tr2> {
+ f2: <<Self as Tr1>::As1 as Tr2>::As2,
+}
+
+impl Tr1 for StSelf<&'static str> { type As1 = bool; }
+
+fn main() {
+ let st1 = St1 { outest: "foo", outer: true, inner: 42u8 };
+ assert_eq!(("foo", true, 42), unwrap_1_st1(st1));
+
+ let _ = St2 { outest: "foo", outer: true, inner: 42u8 };
+
+ let _ = St3 { outest: "foo", outer: &true };
+
+ let f1 = (1,);
+ let f2 = (2,);
+ let st4 = St4::<()> { f1: &f1.0, f2: &f2.0, };
+ assert_eq!((&1, &2), (st4.f1, st4.f2));
+
+ // FIXME: requires lazy normalization.
+ /*
+ let f1 = (1,);
+ let f2 = (2,);
+ let st5 = St5::<()> { f1: &f1.0, f2: &f2.0, };
+ assert_eq!((&1, &2), (st5.f1, st5.f2));
+ */
+
+ let st6 = St6 { f0: "bar", f1: 24u8, f2: &true, f3: 12u16, };
+ assert_eq!(("bar", 24, &true, 12), (st6.f0, st6.f1, st6.f2, st6.f3));
+
+ let stself = StSelf::<&'static str> { f2: 42u8 };
+ assert_eq!(stself.f2, 42u8);
+}
diff --git a/src/test/ui/associated-type-bounds/supertrait-referencing-self.rs b/src/test/ui/associated-type-bounds/supertrait-referencing-self.rs
new file mode 100644
index 000000000..c82ec01f4
--- /dev/null
+++ b/src/test/ui/associated-type-bounds/supertrait-referencing-self.rs
@@ -0,0 +1,12 @@
+// check-pass
+trait Foo {
+ type Bar;
+}
+trait Qux: Foo + AsRef<Self::Bar> {}
+trait Foo2 {}
+
+trait Qux2: Foo2 + AsRef<Self::Bar> {
+ type Bar;
+}
+
+fn main() {}
diff --git a/src/test/ui/associated-type-bounds/supertrait-referencing.rs b/src/test/ui/associated-type-bounds/supertrait-referencing.rs
new file mode 100644
index 000000000..2e9753515
--- /dev/null
+++ b/src/test/ui/associated-type-bounds/supertrait-referencing.rs
@@ -0,0 +1,19 @@
+// check-pass
+
+// The goal of this test is to ensure that T: Bar<T::Item>
+// in the where clause does not cycle
+
+trait Foo {
+ type Item;
+}
+
+trait Bar<T> {}
+
+fn baz<T>()
+where
+ T: Foo,
+ T: Bar<T::Item>,
+{
+}
+
+fn main() {}
diff --git a/src/test/ui/associated-type-bounds/supertrait-where-referencing-self.rs b/src/test/ui/associated-type-bounds/supertrait-where-referencing-self.rs
new file mode 100644
index 000000000..72a6be9ff
--- /dev/null
+++ b/src/test/ui/associated-type-bounds/supertrait-where-referencing-self.rs
@@ -0,0 +1,27 @@
+// check-pass
+
+// Test that we do not get a cycle due to
+// resolving `Self::Bar` in the where clauses
+// on a trait definition (in particular, in
+// a where clause that is defining a superpredicate).
+
+trait Foo {
+ type Bar;
+}
+trait Qux
+where
+ Self: Foo,
+ Self: AsRef<Self::Bar>,
+{
+}
+trait Foo2 {}
+
+trait Qux2
+where
+ Self: Foo2,
+ Self: AsRef<Self::Bar>,
+{
+ type Bar;
+}
+
+fn main() {}
diff --git a/src/test/ui/associated-type-bounds/trait-alias-impl-trait.rs b/src/test/ui/associated-type-bounds/trait-alias-impl-trait.rs
new file mode 100644
index 000000000..e223a8957
--- /dev/null
+++ b/src/test/ui/associated-type-bounds/trait-alias-impl-trait.rs
@@ -0,0 +1,96 @@
+// run-pass
+
+#![feature(associated_type_bounds)]
+#![feature(type_alias_impl_trait)]
+
+use std::ops::Add;
+
+trait Tr1 {
+ type As1;
+ fn mk(self) -> Self::As1;
+}
+trait Tr2<'a> {
+ fn tr2(self) -> &'a Self;
+}
+
+fn assert_copy<T: Copy>(x: T) {
+ let _x = x;
+ let _x = x;
+}
+fn assert_static<T: 'static>(_: T) {}
+fn assert_forall_tr2<T: for<'a> Tr2<'a>>(_: T) {}
+
+struct S1;
+#[derive(Copy, Clone)]
+struct S2;
+impl Tr1 for S1 {
+ type As1 = S2;
+ fn mk(self) -> Self::As1 {
+ S2
+ }
+}
+
+type Et1 = impl Tr1<As1: Copy>;
+fn def_et1() -> Et1 {
+ S1
+}
+pub fn use_et1() {
+ assert_copy(def_et1().mk());
+}
+
+type Et2 = impl Tr1<As1: 'static>;
+fn def_et2() -> Et2 {
+ S1
+}
+pub fn use_et2() {
+ assert_static(def_et2().mk());
+}
+
+type Et3 = impl Tr1<As1: Clone + Iterator<Item: Add<u8, Output: Into<u8>>>>;
+fn def_et3() -> Et3 {
+ struct A;
+ impl Tr1 for A {
+ type As1 = core::ops::Range<u8>;
+ fn mk(self) -> Self::As1 {
+ 0..10
+ }
+ }
+ A
+}
+pub fn use_et3() {
+ let _0 = def_et3().mk().clone();
+ let mut s = 0u8;
+ for _1 in _0 {
+ let _2 = _1 + 1u8;
+ s += _2.into();
+ }
+ assert_eq!(s, (0..10).map(|x| x + 1).sum());
+}
+
+type Et4 = impl Tr1<As1: for<'a> Tr2<'a>>;
+fn def_et4() -> Et4 {
+ #[derive(Copy, Clone)]
+ struct A;
+ impl Tr1 for A {
+ type As1 = A;
+ fn mk(self) -> A {
+ A
+ }
+ }
+ impl<'a> Tr2<'a> for A {
+ fn tr2(self) -> &'a Self {
+ &A
+ }
+ }
+ A
+}
+pub fn use_et4() {
+ assert_forall_tr2(def_et4().mk());
+}
+
+fn main() {
+ let _ = use_et1();
+ let _ = use_et2();
+ let _ = use_et3();
+ let _ = use_et4();
+}
diff --git a/src/test/ui/associated-type-bounds/trait-params.rs b/src/test/ui/associated-type-bounds/trait-params.rs
new file mode 100644
index 000000000..b0703a4ee
--- /dev/null
+++ b/src/test/ui/associated-type-bounds/trait-params.rs
@@ -0,0 +1,116 @@
+// build-pass (FIXME(62277): could be check-pass?)
+
+#![feature(associated_type_bounds)]
+
+use std::iter::Once;
+use std::ops::Range;
+
+pub trait Three { type A; type B; type C; }
+pub fn assert_three<T: ?Sized + Three>() {}
+pub fn assert_iterator<T: Iterator>() {}
+pub fn assert_copy<T: Copy>() {}
+pub fn assert_static<T: 'static>() {}
+pub fn assert_send<T: Send>() {}
+pub fn assert_forall_into<T: for<'a> Into<&'a u8>>() {}
+
+struct A; struct B;
+impl<'a> Into<&'a u8> for A { fn into(self) -> &'a u8 { &0 } }
+impl Three for B { type A = Range<u8>; type B = Range<u8>; type C = Range<u8>; }
+
+trait Case1<A, B, C, D, E>
+where
+ A: Iterator<Item: Copy>,
+ B: Iterator<Item: 'static>,
+ C: Iterator<Item: 'static + Copy + Send>,
+ D: Iterator<Item: for<'a> Into<&'a u8>>,
+ E: Three<A: Iterator<Item: Copy>, B: Iterator<Item: Copy>, C: Iterator<Item: Copy>>,
+ Self: Three<A: 'static, B: Copy, C: Send>,
+{
+ fn _a() {
+ assert_iterator::<A>();
+ assert_copy::<A::Item>();
+ }
+ fn _b() {
+ assert_iterator::<B>();
+ assert_static::<B::Item>();
+ }
+ fn _c() {
+ assert_iterator::<C>();
+ assert_copy::<C::Item>();
+ assert_static::<C::Item>();
+ assert_send::<C::Item>();
+ }
+ fn _d() {
+ assert_iterator::<D>();
+ assert_forall_into::<D::Item>();
+ }
+ fn _e() {
+ assert_three::<E>();
+ assert_iterator::<E::A>();
+ assert_iterator::<E::B>();
+ assert_iterator::<E::C>();
+ assert_copy::<<E::A as Iterator>::Item>();
+ assert_copy::<<E::B as Iterator>::Item>();
+ assert_copy::<<E::C as Iterator>::Item>();
+ }
+ fn _self() {
+ assert_three::<Self>();
+ assert_copy::<Self::B>();
+ assert_static::<Self::A>();
+ assert_send::<Self::C>();
+ }
+}
+
+struct DataCase1;
+impl Three for DataCase1 { type A = u8; type B = u8; type C = u8; }
+impl Case1<Range<u8>, Range<u8>, Range<u8>, Once<A>, B> for DataCase1 {}
+
+trait Case2<
+ A: Iterator<Item: Copy>,
+ B: Iterator<Item: 'static>,
+ C: Iterator<Item: 'static + Copy + Send>,
+ D: Iterator<Item: for<'a> Into<&'a u8>>,
+ E: Three<A: Iterator<Item: Copy>, B: Iterator<Item: Copy>, C: Iterator<Item: Copy>>,
+>:
+ Three<A: 'static, B: Copy, C: Send>
+{
+ fn _a() {
+ assert_iterator::<A>();
+ assert_copy::<A::Item>();
+ }
+ fn _b() {
+ assert_iterator::<B>();
+ assert_static::<B::Item>();
+ }
+ fn _c() {
+ assert_iterator::<C>();
+ assert_copy::<C::Item>();
+ assert_static::<C::Item>();
+ assert_send::<C::Item>();
+ }
+ fn _d() {
+ assert_iterator::<D>();
+ assert_forall_into::<D::Item>();
+ }
+ fn _e() {
+ assert_three::<E>();
+ assert_iterator::<E::A>();
+ assert_iterator::<E::B>();
+ assert_iterator::<E::C>();
+ assert_copy::<<E::A as Iterator>::Item>();
+ assert_copy::<<E::B as Iterator>::Item>();
+ assert_copy::<<E::C as Iterator>::Item>();
+ }
+ fn _self() {
+ assert_three::<Self>();
+ assert_copy::<Self::B>();
+ assert_static::<Self::A>();
+ assert_send::<Self::C>();
+ }
+}
+
+struct DataCase2;
+impl Three for DataCase2 { type A = u8; type B = u8; type C = u8; }
+impl Case2<Range<u8>, Range<u8>, Range<u8>, Once<A>, B> for DataCase2 {}
+
+fn main() {}
diff --git a/src/test/ui/associated-type-bounds/traits-assoc-anonymized.rs b/src/test/ui/associated-type-bounds/traits-assoc-anonymized.rs
new file mode 100644
index 000000000..a9d6eed81
--- /dev/null
+++ b/src/test/ui/associated-type-bounds/traits-assoc-anonymized.rs
@@ -0,0 +1,33 @@
+// check-pass
+
+pub struct LookupInternedStorage;
+
+impl<Q> QueryStorageOps<Q> for LookupInternedStorage
+where
+ Q: Query,
+ for<'d> Q: QueryDb<'d>,
+{
+ fn fmt_index(&self, db: &<Q as QueryDb<'_>>::DynDb) {
+ <<Q as QueryDb<'_>>::DynDb as HasQueryGroup<Q::Group>>::group_storage(db);
+ }
+}
+
+pub trait HasQueryGroup<G> {
+ fn group_storage(&self);
+}
+
+pub trait QueryStorageOps<Q>
+where
+ Q: Query,
+{
+ fn fmt_index(&self, db: &<Q as QueryDb<'_>>::DynDb);
+}
+
+pub trait QueryDb<'d> {
+ type DynDb: HasQueryGroup<Self::Group> + 'd;
+ type Group;
+}
+
+pub trait Query: for<'d> QueryDb<'d> {}
+
+fn main() {}
diff --git a/src/test/ui/associated-type-bounds/traits-assoc-type-macros.rs b/src/test/ui/associated-type-bounds/traits-assoc-type-macros.rs
new file mode 100644
index 000000000..d854dce38
--- /dev/null
+++ b/src/test/ui/associated-type-bounds/traits-assoc-type-macros.rs
@@ -0,0 +1,43 @@
+// check-pass
+// incremental
+
+// This test case makes sure that we can compile with incremental compilation
+// enabled when there are macros, traits, inheritance and associated types involved.
+
+trait Deserializer {
+ type Error;
+}
+
+trait Deserialize {
+ fn deserialize<D>(_: D) -> D::Error
+ where
+ D: Deserializer;
+}
+
+macro_rules! impl_deserialize {
+ ($name:ident) => {
+ impl Deserialize for $name {
+ fn deserialize<D>(_: D) -> D::Error
+ where
+ D: Deserializer,
+ {
+ loop {}
+ }
+ }
+ };
+}
+
+macro_rules! formats {
+ {
+ $($name:ident,)*
+ } => {
+ $(
+ pub struct $name;
+
+ impl_deserialize!($name);
+ )*
+ }
+}
+formats! { Foo, Bar, }
+
+fn main() {}
diff --git a/src/test/ui/associated-type-bounds/type-alias.rs b/src/test/ui/associated-type-bounds/type-alias.rs
new file mode 100644
index 000000000..f74c5ff1e
--- /dev/null
+++ b/src/test/ui/associated-type-bounds/type-alias.rs
@@ -0,0 +1,19 @@
+// check-pass
+
+#![feature(associated_type_bounds)]
+
+type _TaWhere1<T> where T: Iterator<Item: Copy> = T; //~ WARNING type_alias_bounds
+type _TaWhere2<T> where T: Iterator<Item: 'static> = T; //~ WARNING type_alias_bounds
+type _TaWhere3<T> where T: Iterator<Item: 'static> = T; //~ WARNING type_alias_bounds
+type _TaWhere4<T> where T: Iterator<Item: 'static + Copy + Send> = T; //~ WARNING type_alias_bounds
+type _TaWhere5<T> where T: Iterator<Item: for<'a> Into<&'a u8>> = T; //~ WARNING type_alias_bounds
+type _TaWhere6<T> where T: Iterator<Item: Iterator<Item: Copy>> = T; //~ WARNING type_alias_bounds
+
+type _TaInline1<T: Iterator<Item: Copy>> = T; //~ WARNING type_alias_bounds
+type _TaInline2<T: Iterator<Item: 'static>> = T; //~ WARNING type_alias_bounds
+type _TaInline3<T: Iterator<Item: 'static>> = T; //~ WARNING type_alias_bounds
+type _TaInline4<T: Iterator<Item: 'static + Copy + Send>> = T; //~ WARNING type_alias_bounds
+type _TaInline5<T: Iterator<Item: for<'a> Into<&'a u8>>> = T; //~ WARNING type_alias_bounds
+type _TaInline6<T: Iterator<Item: Iterator<Item: Copy>>> = T; //~ WARNING type_alias_bounds
+
+fn main() {}
diff --git a/src/test/ui/associated-type-bounds/type-alias.stderr b/src/test/ui/associated-type-bounds/type-alias.stderr
new file mode 100644
index 000000000..c22b80b88
--- /dev/null
+++ b/src/test/ui/associated-type-bounds/type-alias.stderr
@@ -0,0 +1,147 @@
+warning: where clauses are not enforced in type aliases
+ --> $DIR/type-alias.rs:5:25
+ |
+LL | type _TaWhere1<T> where T: Iterator<Item: Copy> = T;
+ | ^^^^^^^^^^^^^^^^^^^^^^^
+ |
+ = note: `#[warn(type_alias_bounds)]` on by default
+help: the clause will not be checked when the type alias is used, and should be removed
+ |
+LL - type _TaWhere1<T> where T: Iterator<Item: Copy> = T;
+LL + type _TaWhere1<T> = T;
+ |
+
+warning: where clauses are not enforced in type aliases
+ --> $DIR/type-alias.rs:6:25
+ |
+LL | type _TaWhere2<T> where T: Iterator<Item: 'static> = T;
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+help: the clause will not be checked when the type alias is used, and should be removed
+ |
+LL - type _TaWhere2<T> where T: Iterator<Item: 'static> = T;
+LL + type _TaWhere2<T> = T;
+ |
+
+warning: where clauses are not enforced in type aliases
+ --> $DIR/type-alias.rs:7:25
+ |
+LL | type _TaWhere3<T> where T: Iterator<Item: 'static> = T;
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+help: the clause will not be checked when the type alias is used, and should be removed
+ |
+LL - type _TaWhere3<T> where T: Iterator<Item: 'static> = T;
+LL + type _TaWhere3<T> = T;
+ |
+
+warning: where clauses are not enforced in type aliases
+ --> $DIR/type-alias.rs:8:25
+ |
+LL | type _TaWhere4<T> where T: Iterator<Item: 'static + Copy + Send> = T;
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+help: the clause will not be checked when the type alias is used, and should be removed
+ |
+LL - type _TaWhere4<T> where T: Iterator<Item: 'static + Copy + Send> = T;
+LL + type _TaWhere4<T> = T;
+ |
+
+warning: where clauses are not enforced in type aliases
+ --> $DIR/type-alias.rs:9:25
+ |
+LL | type _TaWhere5<T> where T: Iterator<Item: for<'a> Into<&'a u8>> = T;
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+help: the clause will not be checked when the type alias is used, and should be removed
+ |
+LL - type _TaWhere5<T> where T: Iterator<Item: for<'a> Into<&'a u8>> = T;
+LL + type _TaWhere5<T> = T;
+ |
+
+warning: where clauses are not enforced in type aliases
+ --> $DIR/type-alias.rs:10:25
+ |
+LL | type _TaWhere6<T> where T: Iterator<Item: Iterator<Item: Copy>> = T;
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+help: the clause will not be checked when the type alias is used, and should be removed
+ |
+LL - type _TaWhere6<T> where T: Iterator<Item: Iterator<Item: Copy>> = T;
+LL + type _TaWhere6<T> = T;
+ |
+
+warning: bounds on generic parameters are not enforced in type aliases
+ --> $DIR/type-alias.rs:12:20
+ |
+LL | type _TaInline1<T: Iterator<Item: Copy>> = T;
+ | ^^^^^^^^^^^^^^^^^^^^
+ |
+help: the bound will not be checked when the type alias is used, and should be removed
+ |
+LL - type _TaInline1<T: Iterator<Item: Copy>> = T;
+LL + type _TaInline1<T> = T;
+ |
+
+warning: bounds on generic parameters are not enforced in type aliases
+ --> $DIR/type-alias.rs:13:20
+ |
+LL | type _TaInline2<T: Iterator<Item: 'static>> = T;
+ | ^^^^^^^^^^^^^^^^^^^^^^^
+ |
+help: the bound will not be checked when the type alias is used, and should be removed
+ |
+LL - type _TaInline2<T: Iterator<Item: 'static>> = T;
+LL + type _TaInline2<T> = T;
+ |
+
+warning: bounds on generic parameters are not enforced in type aliases
+ --> $DIR/type-alias.rs:14:20
+ |
+LL | type _TaInline3<T: Iterator<Item: 'static>> = T;
+ | ^^^^^^^^^^^^^^^^^^^^^^^
+ |
+help: the bound will not be checked when the type alias is used, and should be removed
+ |
+LL - type _TaInline3<T: Iterator<Item: 'static>> = T;
+LL + type _TaInline3<T> = T;
+ |
+
+warning: bounds on generic parameters are not enforced in type aliases
+ --> $DIR/type-alias.rs:15:20
+ |
+LL | type _TaInline4<T: Iterator<Item: 'static + Copy + Send>> = T;
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+help: the bound will not be checked when the type alias is used, and should be removed
+ |
+LL - type _TaInline4<T: Iterator<Item: 'static + Copy + Send>> = T;
+LL + type _TaInline4<T> = T;
+ |
+
+warning: bounds on generic parameters are not enforced in type aliases
+ --> $DIR/type-alias.rs:16:20
+ |
+LL | type _TaInline5<T: Iterator<Item: for<'a> Into<&'a u8>>> = T;
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+help: the bound will not be checked when the type alias is used, and should be removed
+ |
+LL - type _TaInline5<T: Iterator<Item: for<'a> Into<&'a u8>>> = T;
+LL + type _TaInline5<T> = T;
+ |
+
+warning: bounds on generic parameters are not enforced in type aliases
+ --> $DIR/type-alias.rs:17:20
+ |
+LL | type _TaInline6<T: Iterator<Item: Iterator<Item: Copy>>> = T;
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+help: the bound will not be checked when the type alias is used, and should be removed
+ |
+LL - type _TaInline6<T: Iterator<Item: Iterator<Item: Copy>>> = T;
+LL + type _TaInline6<T> = T;
+ |
+
+warning: 12 warnings emitted
+
diff --git a/src/test/ui/associated-type-bounds/union-bounds.rs b/src/test/ui/associated-type-bounds/union-bounds.rs
new file mode 100644
index 000000000..46e5aef04
--- /dev/null
+++ b/src/test/ui/associated-type-bounds/union-bounds.rs
@@ -0,0 +1,123 @@
+// run-pass
+
+#![feature(associated_type_bounds)]
+
+#![allow(unused_assignments)]
+
+trait Tr1: Copy { type As1: Copy; }
+trait Tr2: Copy { type As2: Copy; }
+trait Tr3: Copy { type As3: Copy; }
+trait Tr4<'a>: Copy { type As4: Copy; }
+trait Tr5: Copy { type As5: Copy; }
+
+impl Tr1 for &str { type As1 = bool; }
+impl Tr2 for bool { type As2 = u8; }
+impl Tr3 for u8 { type As3 = fn() -> u8; }
+impl Tr1 for () { type As1 = (usize,); }
+impl<'a> Tr4<'a> for (usize,) { type As4 = u8; }
+impl Tr5 for bool { type As5 = u16; }
+
+union Un1<T: Tr1<As1: Tr2>> {
+ outest: T,
+ outer: T::As1,
+ inner: <T::As1 as Tr2>::As2,
+}
+
+union Un2<T: Tr1<As1: Tr2<As2: Tr3>>> {
+ outest: T,
+ outer: T::As1,
+ inner: <T::As1 as Tr2>::As2,
+}
+
+union Un3<T: Tr1<As1: 'static>> {
+ outest: T,
+ outer: &'static T::As1,
+}
+
+union Un4<'x1, 'x2, T: Tr1<As1: for<'l> Tr4<'l>>> {
+ f1: &'x1 <T::As1 as Tr4<'x1>>::As4,
+ f2: &'x2 <T::As1 as Tr4<'x2>>::As4,
+}
+
+union _Un5<'x1, 'x2, T: Tr1<As1: for<'l> Tr4<'l, As4: Copy>>> {
+ f1: &'x1 <T::As1 as Tr4<'x1>>::As4,
+ f2: &'x2 <T::As1 as Tr4<'x2>>::As4,
+}
+
+union Un6<T>
+where
+ T: Tr1<As1: Tr2 + 'static + Tr5>,
+{
+ f0: T,
+ f1: <T::As1 as Tr2>::As2,
+ f2: &'static T::As1,
+ f3: <T::As1 as Tr5>::As5,
+}
+
+union _Un7<'a, 'b, T> // `<T::As1 as Tr2>::As2: 'a` is implied.
+where
+ T: Tr1<As1: Tr2>,
+{
+ f0: &'a T,
+ f1: &'b <T::As1 as Tr2>::As2,
+}
+
+unsafe fn _use_un7<'a, 'b, T>(x: _Un7<'a, 'b, T>)
+where
+ T: Tr1,
+ T::As1: Tr2,
+{
+ let _: &'a T = &x.f0;
+}
+
+#[derive(Copy, Clone)]
+union UnSelf<T> where Self: Tr1<As1: Tr2>, T: Copy {
+ f0: T,
+ f1: <Self as Tr1>::As1,
+ f2: <<Self as Tr1>::As1 as Tr2>::As2,
+}
+
+impl Tr1 for UnSelf<&'static str> { type As1 = bool; }
+
+fn main() {
+ let mut un1 = Un1 { outest: "foo" };
+ un1 = Un1 { outer: true };
+ assert_eq!(unsafe { un1.outer }, true);
+ un1 = Un1 { inner: 42u8 };
+ assert_eq!(unsafe { un1.inner }, 42u8);
+
+ let mut un2 = Un2 { outest: "bar" };
+ assert_eq!(unsafe { un2.outest }, "bar");
+ un2 = Un2 { outer: true };
+ assert_eq!(unsafe { un2.outer }, true);
+ un2 = Un2 { inner: 42u8 };
+ assert_eq!(unsafe { un2.inner }, 42u8);
+
+ let mut un3 = Un3 { outest: "baz" };
+ assert_eq!(unsafe { un3.outest }, "baz");
+ un3 = Un3 { outer: &true };
+ assert_eq!(unsafe { *un3.outer }, true);
+
+ let f1 = (1,);
+ let f2 = (2,);
+ let mut un4 = Un4::<()> { f1: &f1.0 };
+ assert_eq!(1, unsafe { *un4.f1 });
+ un4 = Un4 { f2: &f2.0 };
+ assert_eq!(2, unsafe { *un4.f2 });
+
+ let mut un6 = Un6 { f0: "bar" };
+ assert_eq!(unsafe { un6.f0 }, "bar");
+ un6 = Un6 { f1: 24u8 };
+ assert_eq!(unsafe { un6.f1 }, 24u8);
+ un6 = Un6 { f2: &true };
+ assert_eq!(unsafe { un6.f2 }, &true);
+ un6 = Un6 { f3: 12u16 };
+ assert_eq!(unsafe { un6.f3 }, 12u16);
+
+ let mut unself = UnSelf::<_> { f0: "selfish" };
+ assert_eq!(unsafe { unself.f0 }, "selfish");
+ unself = UnSelf { f1: true };
+ assert_eq!(unsafe { unself.f1 }, true);
+ unself = UnSelf { f2: 24u8 };
+ assert_eq!(unsafe { unself.f2 }, 24u8);
+}