about summary refs log tree commit diff
diff options
context:
space:
mode:
authorMara Bos <m-ou.se@m-ou.se>2021-02-05 12:25:50 +0100
committerGitHub <noreply@github.com>2021-02-05 12:25:50 +0100
commitdeec6a96d428d20250bfad2317c00fc67e4b70f0 (patch)
treeddccb276fd47d1190b34019bd505e5f9bcc2ecaf
parent9e5d58fb420a487ae30f38141eccdc8d79fb8d58 (diff)
parent12d411febb37d4ddfd423415554714265609cb72 (diff)
downloadrust-deec6a96d428d20250bfad2317c00fc67e4b70f0.tar.gz
rust-deec6a96d428d20250bfad2317c00fc67e4b70f0.zip
Rollup merge of #79554 - b-naber:generic-associated-types-in-trait-paths, r=jackh726
Generic associated types in trait paths

This is the second part of https://github.com/rust-lang/rust/pull/78978

This should fix:

Fixes #67510
Fixes #68648
Fixes #68649
Fixes #68650
Fixes #68652
Fixes #74684
Fixes #76535
Fixes #79422
Fixes #80433

and implement the remaining functionality needed for https://github.com/rust-lang/rust/issues/44265

r? ``@matthewjasper``
-rw-r--r--compiler/rustc_ast_lowering/src/lib.rs39
-rw-r--r--compiler/rustc_ast_lowering/src/path.rs7
-rw-r--r--compiler/rustc_hir/src/hir.rs1
-rw-r--r--compiler/rustc_hir/src/intravisit.rs1
-rw-r--r--compiler/rustc_hir_pretty/src/lib.rs1
-rw-r--r--compiler/rustc_middle/src/ty/sty.rs10
-rw-r--r--compiler/rustc_trait_selection/src/traits/object_safety.rs4
-rw-r--r--compiler/rustc_typeck/src/astconv/mod.rs166
-rw-r--r--src/test/ui/generic-associated-types/gat-in-trait-path-undeclared-lifetime.rs12
-rw-r--r--src/test/ui/generic-associated-types/gat-in-trait-path-undeclared-lifetime.stderr29
-rw-r--r--src/test/ui/generic-associated-types/gat-in-trait-path.rs30
-rw-r--r--src/test/ui/generic-associated-types/gat-in-trait-path.stderr11
-rw-r--r--src/test/ui/generic-associated-types/gat-trait-path-generic-type-arg.rs16
-rw-r--r--src/test/ui/generic-associated-types/gat-trait-path-generic-type-arg.stderr32
-rw-r--r--src/test/ui/generic-associated-types/gat-trait-path-missing-lifetime.rs18
-rw-r--r--src/test/ui/generic-associated-types/gat-trait-path-missing-lifetime.stderr44
-rw-r--r--src/test/ui/generic-associated-types/gat-trait-path-parenthesised-args.rs15
-rw-r--r--src/test/ui/generic-associated-types/gat-trait-path-parenthesised-args.stderr68
-rw-r--r--src/test/ui/generic-associated-types/issue-67510-pass.rs12
-rw-r--r--src/test/ui/generic-associated-types/issue-67510-pass.stderr11
-rw-r--r--src/test/ui/generic-associated-types/issue-67510.rs13
-rw-r--r--src/test/ui/generic-associated-types/issue-67510.stderr32
-rw-r--r--src/test/ui/generic-associated-types/issue-68648-1.rs26
-rw-r--r--src/test/ui/generic-associated-types/issue-68648-1.stderr11
-rw-r--r--src/test/ui/generic-associated-types/issue-68648-2.rs24
-rw-r--r--src/test/ui/generic-associated-types/issue-68648-2.stderr23
-rw-r--r--src/test/ui/generic-associated-types/issue-68649-pass.rs25
-rw-r--r--src/test/ui/generic-associated-types/issue-68649-pass.stderr11
-rw-r--r--src/test/ui/generic-associated-types/issue-74684-1.rs26
-rw-r--r--src/test/ui/generic-associated-types/issue-74684-1.stderr27
-rw-r--r--src/test/ui/generic-associated-types/issue-74684-2.rs26
-rw-r--r--src/test/ui/generic-associated-types/issue-74684-2.stderr21
-rw-r--r--src/test/ui/generic-associated-types/issue-76535.rs41
-rw-r--r--src/test/ui/generic-associated-types/issue-76535.stderr63
-rw-r--r--src/test/ui/generic-associated-types/issue-79422.rs47
-rw-r--r--src/test/ui/generic-associated-types/issue-79422.stderr54
-rw-r--r--src/test/ui/generic-associated-types/issue-80433-reduced.rs24
-rw-r--r--src/test/ui/generic-associated-types/issue-80433.rs35
-rw-r--r--src/test/ui/generic-associated-types/issue-80433.stderr19
-rw-r--r--src/test/ui/generic-associated-types/parse/trait-path-type-error-once-implemented.rs6
-rw-r--r--src/test/ui/generic-associated-types/parse/trait-path-type-error-once-implemented.stderr51
-rw-r--r--src/test/ui/generic-associated-types/parse/trait-path-unimplemented.rs17
-rw-r--r--src/test/ui/generic-associated-types/parse/trait-path-unimplemented.stderr14
43 files changed, 1051 insertions, 112 deletions
diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs
index b7f227da73e..f076dca5cf5 100644
--- a/compiler/rustc_ast_lowering/src/lib.rs
+++ b/compiler/rustc_ast_lowering/src/lib.rs
@@ -1076,16 +1076,40 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
     fn lower_assoc_ty_constraint(
         &mut self,
         constraint: &AssocTyConstraint,
-        itctx: ImplTraitContext<'_, 'hir>,
+        mut itctx: ImplTraitContext<'_, 'hir>,
     ) -> hir::TypeBinding<'hir> {
         debug!("lower_assoc_ty_constraint(constraint={:?}, itctx={:?})", constraint, itctx);
 
-        if let Some(ref gen_args) = constraint.gen_args {
-            self.sess.span_fatal(
-                gen_args.span(),
-                "generic associated types in trait paths are currently not implemented",
-            );
-        }
+        // lower generic arguments of identifier in constraint
+        let gen_args = if let Some(ref gen_args) = constraint.gen_args {
+            let gen_args_ctor = match gen_args {
+                GenericArgs::AngleBracketed(ref data) => {
+                    self.lower_angle_bracketed_parameter_data(
+                        data,
+                        ParamMode::Explicit,
+                        itctx.reborrow(),
+                    )
+                    .0
+                }
+                GenericArgs::Parenthesized(ref data) => {
+                    let mut err = self.sess.struct_span_err(
+                        gen_args.span(),
+                        "parenthesized generic arguments cannot be used in associated type constraints"
+                    );
+                    // FIXME: try to write a suggestion here
+                    err.emit();
+                    self.lower_angle_bracketed_parameter_data(
+                        &data.as_angle_bracketed_args(),
+                        ParamMode::Explicit,
+                        itctx.reborrow(),
+                    )
+                    .0
+                }
+            };
+            self.arena.alloc(gen_args_ctor.into_generic_args(&self.arena))
+        } else {
+            self.arena.alloc(hir::GenericArgs::none())
+        };
 
         let kind = match constraint.kind {
             AssocTyConstraintKind::Equality { ref ty } => {
@@ -1182,6 +1206,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
         hir::TypeBinding {
             hir_id: self.lower_node_id(constraint.id),
             ident: constraint.ident,
+            gen_args,
             kind,
             span: constraint.span,
         }
diff --git a/compiler/rustc_ast_lowering/src/path.rs b/compiler/rustc_ast_lowering/src/path.rs
index 9079e26eb50..cb4d5ea6ee6 100644
--- a/compiler/rustc_ast_lowering/src/path.rs
+++ b/compiler/rustc_ast_lowering/src/path.rs
@@ -362,7 +362,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
         }
     }
 
-    fn lower_angle_bracketed_parameter_data(
+    pub(crate) fn lower_angle_bracketed_parameter_data(
         &mut self,
         data: &AngleBracketedArgs,
         param_mode: ParamMode,
@@ -426,6 +426,9 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
     ) -> hir::TypeBinding<'hir> {
         let ident = Ident::with_dummy_span(hir::FN_OUTPUT_NAME);
         let kind = hir::TypeBindingKind::Equality { ty };
-        hir::TypeBinding { hir_id: self.next_id(), span, ident, kind }
+        let args = arena_vec![self;];
+        let bindings = arena_vec![self;];
+        let gen_args = self.arena.alloc(hir::GenericArgs { args, bindings, parenthesized: false });
+        hir::TypeBinding { hir_id: self.next_id(), gen_args, span, ident, kind }
     }
 }
diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs
index 6487b23a6a6..67a15418ea4 100644
--- a/compiler/rustc_hir/src/hir.rs
+++ b/compiler/rustc_hir/src/hir.rs
@@ -2015,6 +2015,7 @@ pub struct TypeBinding<'hir> {
     pub hir_id: HirId,
     #[stable_hasher(project(name))]
     pub ident: Ident,
+    pub gen_args: &'hir GenericArgs<'hir>,
     pub kind: TypeBindingKind<'hir>,
     pub span: Span,
 }
diff --git a/compiler/rustc_hir/src/intravisit.rs b/compiler/rustc_hir/src/intravisit.rs
index 6c1bee2335a..f8b3f0d9b6e 100644
--- a/compiler/rustc_hir/src/intravisit.rs
+++ b/compiler/rustc_hir/src/intravisit.rs
@@ -781,6 +781,7 @@ pub fn walk_assoc_type_binding<'v, V: Visitor<'v>>(
 ) {
     visitor.visit_id(type_binding.hir_id);
     visitor.visit_ident(type_binding.ident);
+    visitor.visit_generic_args(type_binding.span, type_binding.gen_args);
     match type_binding.kind {
         TypeBindingKind::Equality { ref ty } => {
             visitor.visit_ty(ty);
diff --git a/compiler/rustc_hir_pretty/src/lib.rs b/compiler/rustc_hir_pretty/src/lib.rs
index f1c2a6b7e6e..4595855309f 100644
--- a/compiler/rustc_hir_pretty/src/lib.rs
+++ b/compiler/rustc_hir_pretty/src/lib.rs
@@ -1840,6 +1840,7 @@ impl<'a> State<'a> {
             for binding in generic_args.bindings.iter() {
                 start_or_comma(self);
                 self.print_ident(binding.ident);
+                self.print_generic_args(binding.gen_args, false, false);
                 self.s.space();
                 match generic_args.bindings[0].kind {
                     hir::TypeBindingKind::Equality { ref ty } => {
diff --git a/compiler/rustc_middle/src/ty/sty.rs b/compiler/rustc_middle/src/ty/sty.rs
index 6b4f08d9f93..c1fa84dcb25 100644
--- a/compiler/rustc_middle/src/ty/sty.rs
+++ b/compiler/rustc_middle/src/ty/sty.rs
@@ -1132,8 +1132,16 @@ impl<'tcx> ProjectionTy<'tcx> {
     /// For example, if this is a projection of `<T as Iterator>::Item`,
     /// then this function would return a `T: Iterator` trait reference.
     pub fn trait_ref(&self, tcx: TyCtxt<'tcx>) -> ty::TraitRef<'tcx> {
+        // FIXME: This method probably shouldn't exist at all, since it's not
+        // clear what this method really intends to do. Be careful when
+        // using this method since the resulting TraitRef additionally
+        // contains the substs for the assoc_item, which strictly speaking
+        // is not correct
         let def_id = tcx.associated_item(self.item_def_id).container.id();
-        ty::TraitRef { def_id, substs: self.substs.truncate_to(tcx, tcx.generics_of(def_id)) }
+        // Include substitutions for generic arguments of associated types
+        let assoc_item = tcx.associated_item(self.item_def_id);
+        let substs_assoc_item = self.substs.truncate_to(tcx, tcx.generics_of(assoc_item.def_id));
+        ty::TraitRef { def_id, substs: substs_assoc_item }
     }
 
     pub fn self_ty(&self) -> Ty<'tcx> {
diff --git a/compiler/rustc_trait_selection/src/traits/object_safety.rs b/compiler/rustc_trait_selection/src/traits/object_safety.rs
index 3852005ee3f..e155f0366e1 100644
--- a/compiler/rustc_trait_selection/src/traits/object_safety.rs
+++ b/compiler/rustc_trait_selection/src/traits/object_safety.rs
@@ -257,13 +257,11 @@ fn predicates_reference_self(
 }
 
 fn bounds_reference_self(tcx: TyCtxt<'_>, trait_def_id: DefId) -> SmallVec<[Span; 1]> {
-    let trait_ref = ty::Binder::dummy(ty::TraitRef::identity(tcx, trait_def_id));
     tcx.associated_items(trait_def_id)
         .in_definition_order()
         .filter(|item| item.kind == ty::AssocKind::Type)
         .flat_map(|item| tcx.explicit_item_bounds(item.def_id))
-        .map(|&(predicate, sp)| (predicate.subst_supertrait(tcx, &trait_ref), sp))
-        .filter_map(|predicate| predicate_references_self(tcx, predicate))
+        .filter_map(|pred_span| predicate_references_self(tcx, *pred_span))
         .collect()
 }
 
diff --git a/compiler/rustc_typeck/src/astconv/mod.rs b/compiler/rustc_typeck/src/astconv/mod.rs
index 437813ea41b..5659345f0ff 100644
--- a/compiler/rustc_typeck/src/astconv/mod.rs
+++ b/compiler/rustc_typeck/src/astconv/mod.rs
@@ -112,12 +112,15 @@ pub enum SizedByDefault {
     No,
 }
 
+#[derive(Debug)]
 struct ConvertedBinding<'a, 'tcx> {
     item_name: Ident,
     kind: ConvertedBindingKind<'a, 'tcx>,
+    gen_args: &'a GenericArgs<'a>,
     span: Span,
 }
 
+#[derive(Debug)]
 enum ConvertedBindingKind<'a, 'tcx> {
     Equality(Ty<'tcx>),
     Constraint(&'a [hir::GenericBound<'a>]),
@@ -323,6 +326,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
 
         let tcx = self.tcx();
         let generics = tcx.generics_of(def_id);
+        debug!("generics: {:?}", generics);
 
         if generics.has_self {
             if generics.parent.is_some() {
@@ -557,7 +561,12 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
                         ConvertedBindingKind::Constraint(bounds)
                     }
                 };
-                ConvertedBinding { item_name: binding.ident, kind, span: binding.span }
+                ConvertedBinding {
+                    item_name: binding.ident,
+                    kind,
+                    gen_args: binding.gen_args,
+                    span: binding.span,
+                }
             })
             .collect();
 
@@ -918,60 +927,27 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
         dup_bindings: &mut FxHashMap<DefId, Span>,
         path_span: Span,
     ) -> Result<(), ErrorReported> {
-        let tcx = self.tcx();
-
-        if !speculative {
-            // Given something like `U: SomeTrait<T = X>`, we want to produce a
-            // predicate like `<U as SomeTrait>::T = X`. This is somewhat
-            // subtle in the event that `T` is defined in a supertrait of
-            // `SomeTrait`, because in that case we need to upcast.
-            //
-            // That is, consider this case:
-            //
-            // ```
-            // trait SubTrait: SuperTrait<i32> { }
-            // trait SuperTrait<A> { type T; }
-            //
-            // ... B: SubTrait<T = foo> ...
-            // ```
-            //
-            // We want to produce `<B as SuperTrait<i32>>::T == foo`.
-
-            // Find any late-bound regions declared in `ty` that are not
-            // declared in the trait-ref. These are not well-formed.
-            //
-            // Example:
-            //
-            //     for<'a> <T as Iterator>::Item = &'a str // <-- 'a is bad
-            //     for<'a> <T as FnMut<(&'a u32,)>>::Output = &'a str // <-- 'a is ok
-            if let ConvertedBindingKind::Equality(ty) = binding.kind {
-                let late_bound_in_trait_ref =
-                    tcx.collect_constrained_late_bound_regions(&trait_ref);
-                let late_bound_in_ty =
-                    tcx.collect_referenced_late_bound_regions(&ty::Binder::bind(ty));
-                debug!("late_bound_in_trait_ref = {:?}", late_bound_in_trait_ref);
-                debug!("late_bound_in_ty = {:?}", late_bound_in_ty);
+        // Given something like `U: SomeTrait<T = X>`, we want to produce a
+        // predicate like `<U as SomeTrait>::T = X`. This is somewhat
+        // subtle in the event that `T` is defined in a supertrait of
+        // `SomeTrait`, because in that case we need to upcast.
+        //
+        // That is, consider this case:
+        //
+        // ```
+        // trait SubTrait: SuperTrait<i32> { }
+        // trait SuperTrait<A> { type T; }
+        //
+        // ... B: SubTrait<T = foo> ...
+        // ```
+        //
+        // We want to produce `<B as SuperTrait<i32>>::T == foo`.
 
-                // FIXME: point at the type params that don't have appropriate lifetimes:
-                // struct S1<F: for<'a> Fn(&i32, &i32) -> &'a i32>(F);
-                //                         ----  ----     ^^^^^^^
-                self.validate_late_bound_regions(
-                    late_bound_in_trait_ref,
-                    late_bound_in_ty,
-                    |br_name| {
-                        struct_span_err!(
-                            tcx.sess,
-                            binding.span,
-                            E0582,
-                            "binding for associated type `{}` references {}, \
-                             which does not appear in the trait input types",
-                            binding.item_name,
-                            br_name
-                        )
-                    },
-                );
-            }
-        }
+        debug!(
+            "add_predicates_for_ast_type_binding(hir_ref_id {:?}, trait_ref {:?}, binding {:?}, bounds {:?}",
+            hir_ref_id, trait_ref, binding, bounds
+        );
+        let tcx = self.tcx();
 
         let candidate =
             if self.trait_defines_associated_type_named(trait_ref.def_id(), binding.item_name) {
@@ -1030,6 +1006,72 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
                 .or_insert(binding.span);
         }
 
+        // Include substitutions for generic parameters of associated types
+        let projection_ty = candidate.map_bound(|trait_ref| {
+            let item_segment = hir::PathSegment {
+                ident: assoc_ty.ident,
+                hir_id: None,
+                res: None,
+                args: Some(binding.gen_args),
+                infer_args: false,
+            };
+
+            let substs_trait_ref_and_assoc_item = self.create_substs_for_associated_item(
+                tcx,
+                path_span,
+                assoc_ty.def_id,
+                &item_segment,
+                trait_ref.substs,
+            );
+
+            debug!(
+                "add_predicates_for_ast_type_binding: substs for trait-ref and assoc_item: {:?}",
+                substs_trait_ref_and_assoc_item
+            );
+
+            ty::ProjectionTy {
+                item_def_id: assoc_ty.def_id,
+                substs: substs_trait_ref_and_assoc_item,
+            }
+        });
+
+        if !speculative {
+            // Find any late-bound regions declared in `ty` that are not
+            // declared in the trait-ref or assoc_ty. These are not well-formed.
+            //
+            // Example:
+            //
+            //     for<'a> <T as Iterator>::Item = &'a str // <-- 'a is bad
+            //     for<'a> <T as FnMut<(&'a u32,)>>::Output = &'a str // <-- 'a is ok
+            if let ConvertedBindingKind::Equality(ty) = binding.kind {
+                let late_bound_in_trait_ref =
+                    tcx.collect_constrained_late_bound_regions(&projection_ty);
+                let late_bound_in_ty =
+                    tcx.collect_referenced_late_bound_regions(&ty::Binder::bind(ty));
+                debug!("late_bound_in_trait_ref = {:?}", late_bound_in_trait_ref);
+                debug!("late_bound_in_ty = {:?}", late_bound_in_ty);
+
+                // FIXME: point at the type params that don't have appropriate lifetimes:
+                // struct S1<F: for<'a> Fn(&i32, &i32) -> &'a i32>(F);
+                //                         ----  ----     ^^^^^^^
+                self.validate_late_bound_regions(
+                    late_bound_in_trait_ref,
+                    late_bound_in_ty,
+                    |br_name| {
+                        struct_span_err!(
+                            tcx.sess,
+                            binding.span,
+                            E0582,
+                            "binding for associated type `{}` references {}, \
+                             which does not appear in the trait input types",
+                            binding.item_name,
+                            br_name
+                        )
+                    },
+                );
+            }
+        }
+
         match binding.kind {
             ConvertedBindingKind::Equality(ref ty) => {
                 // "Desugar" a constraint like `T: Iterator<Item = u32>` this to
@@ -1037,13 +1079,12 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
                 //
                 // `<T as Iterator>::Item = u32`
                 bounds.projection_bounds.push((
-                    candidate.map_bound(|trait_ref| ty::ProjectionPredicate {
-                        projection_ty: ty::ProjectionTy::from_ref_and_name(
-                            tcx,
-                            trait_ref,
-                            binding.item_name,
-                        ),
-                        ty,
+                    projection_ty.map_bound(|projection_ty| {
+                        debug!(
+                            "add_predicates_for_ast_type_binding: projection_ty {:?}, substs: {:?}",
+                            projection_ty, projection_ty.substs
+                        );
+                        ty::ProjectionPredicate { projection_ty, ty }
                     }),
                     binding.span,
                 ));
@@ -1055,7 +1096,8 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
                 //
                 // Calling `skip_binder` is okay, because `add_bounds` expects the `param_ty`
                 // parameter to have a skipped binder.
-                let param_ty = tcx.mk_projection(assoc_ty.def_id, candidate.skip_binder().substs);
+                let param_ty =
+                    tcx.mk_projection(assoc_ty.def_id, projection_ty.skip_binder().substs);
                 self.add_bounds(param_ty, ast_bounds, bounds);
             }
         }
diff --git a/src/test/ui/generic-associated-types/gat-in-trait-path-undeclared-lifetime.rs b/src/test/ui/generic-associated-types/gat-in-trait-path-undeclared-lifetime.rs
new file mode 100644
index 00000000000..2c543455b6e
--- /dev/null
+++ b/src/test/ui/generic-associated-types/gat-in-trait-path-undeclared-lifetime.rs
@@ -0,0 +1,12 @@
+#![feature(generic_associated_types)]
+  //~^ WARNING: the feature `generic_associated_types` is incomplete
+
+trait X {
+  type Y<'x>;
+}
+
+fn main() {
+  fn _f(arg : Box<dyn for<'a> X<Y<'x> = &'a [u32]>>) {}
+    //~^ ERROR: use of undeclared lifetime name `'x`
+    //~| ERROR: binding for associated type `Y` references lifetime
+}
diff --git a/src/test/ui/generic-associated-types/gat-in-trait-path-undeclared-lifetime.stderr b/src/test/ui/generic-associated-types/gat-in-trait-path-undeclared-lifetime.stderr
new file mode 100644
index 00000000000..1c7c107d783
--- /dev/null
+++ b/src/test/ui/generic-associated-types/gat-in-trait-path-undeclared-lifetime.stderr
@@ -0,0 +1,29 @@
+warning: the feature `generic_associated_types` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/gat-in-trait-path-undeclared-lifetime.rs:1:12
+   |
+LL | #![feature(generic_associated_types)]
+   |            ^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: `#[warn(incomplete_features)]` on by default
+   = note: see issue #44265 <https://github.com/rust-lang/rust/issues/44265> for more information
+
+error[E0261]: use of undeclared lifetime name `'x`
+  --> $DIR/gat-in-trait-path-undeclared-lifetime.rs:9:35
+   |
+LL |   fn _f(arg : Box<dyn for<'a> X<Y<'x> = &'a [u32]>>) {}
+   |        -                          ^^ undeclared lifetime
+   |        |
+   |        help: consider introducing lifetime `'x` here: `<'x>`
+   |
+   = help: if you want to experiment with in-band lifetime bindings, add `#![feature(in_band_lifetimes)]` to the crate attributes
+
+error[E0582]: binding for associated type `Y` references lifetime `'a`, which does not appear in the trait input types
+  --> $DIR/gat-in-trait-path-undeclared-lifetime.rs:9:33
+   |
+LL |   fn _f(arg : Box<dyn for<'a> X<Y<'x> = &'a [u32]>>) {}
+   |                                 ^^^^^^^^^^^^^^^^^
+
+error: aborting due to 2 previous errors; 1 warning emitted
+
+Some errors have detailed explanations: E0261, E0582.
+For more information about an error, try `rustc --explain E0261`.
diff --git a/src/test/ui/generic-associated-types/gat-in-trait-path.rs b/src/test/ui/generic-associated-types/gat-in-trait-path.rs
new file mode 100644
index 00000000000..2dbd1840dec
--- /dev/null
+++ b/src/test/ui/generic-associated-types/gat-in-trait-path.rs
@@ -0,0 +1,30 @@
+// check-pass
+
+#![feature(generic_associated_types)]
+  //~^ WARNING: the feature `generic_associated_types` is incomplete
+#![feature(associated_type_defaults)]
+
+trait Foo {
+    type A<'a> where Self: 'a;
+}
+
+struct Fooy;
+
+impl Foo for Fooy {
+    type A<'a> = &'a ();
+}
+
+#[derive(Clone)]
+struct Fooer<T>(T);
+
+impl<T> Foo for Fooer<T> {
+    type A<'x> where T: 'x = &'x ();
+}
+
+fn f(_arg : Box<dyn for<'a> Foo<A<'a> = &'a ()>>) {}
+
+
+fn main() {
+  let foo = Fooer(5);
+  f(Box::new(foo));
+}
diff --git a/src/test/ui/generic-associated-types/gat-in-trait-path.stderr b/src/test/ui/generic-associated-types/gat-in-trait-path.stderr
new file mode 100644
index 00000000000..f3769827f04
--- /dev/null
+++ b/src/test/ui/generic-associated-types/gat-in-trait-path.stderr
@@ -0,0 +1,11 @@
+warning: the feature `generic_associated_types` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/gat-in-trait-path.rs:3:12
+   |
+LL | #![feature(generic_associated_types)]
+   |            ^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: `#[warn(incomplete_features)]` on by default
+   = note: see issue #44265 <https://github.com/rust-lang/rust/issues/44265> for more information
+
+warning: 1 warning emitted
+
diff --git a/src/test/ui/generic-associated-types/gat-trait-path-generic-type-arg.rs b/src/test/ui/generic-associated-types/gat-trait-path-generic-type-arg.rs
new file mode 100644
index 00000000000..cff5a21052f
--- /dev/null
+++ b/src/test/ui/generic-associated-types/gat-trait-path-generic-type-arg.rs
@@ -0,0 +1,16 @@
+#![feature(generic_associated_types)]
+  //~^ WARNING: the feature `generic_associated_types` is incomplete
+
+trait Foo {
+    type F<'a>;
+
+    fn identity<'a>(t: &'a Self::F<'a>) -> &'a Self::F<'a> { t }
+}
+
+impl <T, T1> Foo for T {
+    type F<T1> = &[u8];
+      //~^ ERROR: the name `T1` is already used for
+      //~| ERROR: missing lifetime specifier
+}
+
+fn main() {}
diff --git a/src/test/ui/generic-associated-types/gat-trait-path-generic-type-arg.stderr b/src/test/ui/generic-associated-types/gat-trait-path-generic-type-arg.stderr
new file mode 100644
index 00000000000..e83af1d0c73
--- /dev/null
+++ b/src/test/ui/generic-associated-types/gat-trait-path-generic-type-arg.stderr
@@ -0,0 +1,32 @@
+error[E0403]: the name `T1` is already used for a generic parameter in this item's generic parameters
+  --> $DIR/gat-trait-path-generic-type-arg.rs:11:12
+   |
+LL | impl <T, T1> Foo for T {
+   |          -- first use of `T1`
+LL |     type F<T1> = &[u8];
+   |            ^^ already used
+
+warning: the feature `generic_associated_types` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/gat-trait-path-generic-type-arg.rs:1:12
+   |
+LL | #![feature(generic_associated_types)]
+   |            ^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: `#[warn(incomplete_features)]` on by default
+   = note: see issue #44265 <https://github.com/rust-lang/rust/issues/44265> for more information
+
+error[E0106]: missing lifetime specifier
+  --> $DIR/gat-trait-path-generic-type-arg.rs:11:18
+   |
+LL |     type F<T1> = &[u8];
+   |                  ^ expected named lifetime parameter
+   |
+help: consider introducing a named lifetime parameter
+   |
+LL |     type F<'a, T1> = &'a [u8];
+   |            ^^^       ^^^
+
+error: aborting due to 2 previous errors; 1 warning emitted
+
+Some errors have detailed explanations: E0106, E0403.
+For more information about an error, try `rustc --explain E0106`.
diff --git a/src/test/ui/generic-associated-types/gat-trait-path-missing-lifetime.rs b/src/test/ui/generic-associated-types/gat-trait-path-missing-lifetime.rs
new file mode 100644
index 00000000000..e69e355ba48
--- /dev/null
+++ b/src/test/ui/generic-associated-types/gat-trait-path-missing-lifetime.rs
@@ -0,0 +1,18 @@
+#![feature(generic_associated_types)]
+  //~^ WARNING: the feature `generic_associated_types` is incomplete
+
+trait X {
+  type Y<'a>;
+    //~^ ERROR missing generics for
+    //~| ERROR missing generics for
+
+  fn foo<'a>(t : Self::Y<'a>) -> Self::Y<'a> { t }
+}
+
+impl<T> X for T {
+  fn foo<'a, T1: X<Y = T1>>(t : T1) -> T1::Y<'a> {
+    t
+  }
+}
+
+fn main() {}
diff --git a/src/test/ui/generic-associated-types/gat-trait-path-missing-lifetime.stderr b/src/test/ui/generic-associated-types/gat-trait-path-missing-lifetime.stderr
new file mode 100644
index 00000000000..9c6e2ce3e17
--- /dev/null
+++ b/src/test/ui/generic-associated-types/gat-trait-path-missing-lifetime.stderr
@@ -0,0 +1,44 @@
+warning: the feature `generic_associated_types` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/gat-trait-path-missing-lifetime.rs:1:12
+   |
+LL | #![feature(generic_associated_types)]
+   |            ^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: `#[warn(incomplete_features)]` on by default
+   = note: see issue #44265 <https://github.com/rust-lang/rust/issues/44265> for more information
+
+error[E0107]: missing generics for associated type `X::Y`
+  --> $DIR/gat-trait-path-missing-lifetime.rs:5:8
+   |
+LL |   type Y<'a>;
+   |        ^ expected 1 lifetime argument
+   |
+note: associated type defined here, with 1 lifetime parameter: `'a`
+  --> $DIR/gat-trait-path-missing-lifetime.rs:5:8
+   |
+LL |   type Y<'a>;
+   |        ^ --
+help: use angle brackets to add missing lifetime argument
+   |
+LL |   type Y<'a><'a>;
+   |         ^^^^
+
+error[E0107]: missing generics for associated type `X::Y`
+  --> $DIR/gat-trait-path-missing-lifetime.rs:5:8
+   |
+LL |   type Y<'a>;
+   |        ^ expected 1 lifetime argument
+   |
+note: associated type defined here, with 1 lifetime parameter: `'a`
+  --> $DIR/gat-trait-path-missing-lifetime.rs:5:8
+   |
+LL |   type Y<'a>;
+   |        ^ --
+help: use angle brackets to add missing lifetime argument
+   |
+LL |   type Y<'a><'a>;
+   |         ^^^^
+
+error: aborting due to 2 previous errors; 1 warning emitted
+
+For more information about this error, try `rustc --explain E0107`.
diff --git a/src/test/ui/generic-associated-types/gat-trait-path-parenthesised-args.rs b/src/test/ui/generic-associated-types/gat-trait-path-parenthesised-args.rs
new file mode 100644
index 00000000000..bb1f27a17ca
--- /dev/null
+++ b/src/test/ui/generic-associated-types/gat-trait-path-parenthesised-args.rs
@@ -0,0 +1,15 @@
+#![feature(generic_associated_types)]
+  //~^ WARNING: the feature `generic_associated_types` is incomplete
+
+trait X {
+  type Y<'a>;
+    //~^ ERROR this associated type
+    //~| ERROR this associated type
+}
+
+fn foo<'a>(arg: Box<dyn X<Y('a) = &'a ()>>) {}
+  //~^ ERROR: lifetime in trait object type must be followed by `+`
+  //~| ERROR: parenthesized generic arguments cannot be used
+  //~| WARNING: trait objects without an explicit `dyn` are deprecated
+
+fn main() {}
diff --git a/src/test/ui/generic-associated-types/gat-trait-path-parenthesised-args.stderr b/src/test/ui/generic-associated-types/gat-trait-path-parenthesised-args.stderr
new file mode 100644
index 00000000000..20cb6d88287
--- /dev/null
+++ b/src/test/ui/generic-associated-types/gat-trait-path-parenthesised-args.stderr
@@ -0,0 +1,68 @@
+error: lifetime in trait object type must be followed by `+`
+  --> $DIR/gat-trait-path-parenthesised-args.rs:10:29
+   |
+LL | fn foo<'a>(arg: Box<dyn X<Y('a) = &'a ()>>) {}
+   |                             ^^
+
+error: parenthesized generic arguments cannot be used in associated type constraints
+  --> $DIR/gat-trait-path-parenthesised-args.rs:10:27
+   |
+LL | fn foo<'a>(arg: Box<dyn X<Y('a) = &'a ()>>) {}
+   |                           ^^^^^
+
+warning: the feature `generic_associated_types` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/gat-trait-path-parenthesised-args.rs:1:12
+   |
+LL | #![feature(generic_associated_types)]
+   |            ^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: `#[warn(incomplete_features)]` on by default
+   = note: see issue #44265 <https://github.com/rust-lang/rust/issues/44265> for more information
+
+warning: trait objects without an explicit `dyn` are deprecated
+  --> $DIR/gat-trait-path-parenthesised-args.rs:10:29
+   |
+LL | fn foo<'a>(arg: Box<dyn X<Y('a) = &'a ()>>) {}
+   |                             ^^ help: use `dyn`: `dyn 'a`
+   |
+   = note: `#[warn(bare_trait_objects)]` on by default
+
+error[E0107]: this associated type takes 1 lifetime argument but 0 lifetime arguments were supplied
+  --> $DIR/gat-trait-path-parenthesised-args.rs:5:8
+   |
+LL |   type Y<'a>;
+   |        ^ expected 1 lifetime argument
+   |
+note: associated type defined here, with 1 lifetime parameter: `'a`
+  --> $DIR/gat-trait-path-parenthesised-args.rs:5:8
+   |
+LL |   type Y<'a>;
+   |        ^ --
+help: add missing lifetime argument
+   |
+LL | fn foo<'a>(arg: Box<dyn X<Y('a'a) = &'a ()>>) {}
+   |                             ^^
+
+error[E0107]: this associated type takes 0 type arguments but 1 type argument was supplied
+  --> $DIR/gat-trait-path-parenthesised-args.rs:5:8
+   |
+LL |     type Y<'a>;
+   |  ________^-
+   | |        |
+   | |        expected 0 type arguments
+LL | |
+LL | |
+LL | | }
+LL | |
+LL | | fn foo<'a>(arg: Box<dyn X<Y('a) = &'a ()>>) {}
+   | |_________________________________________- help: remove these generics
+   |
+note: associated type defined here, with 0 type parameters
+  --> $DIR/gat-trait-path-parenthesised-args.rs:5:8
+   |
+LL |   type Y<'a>;
+   |        ^
+
+error: aborting due to 4 previous errors; 2 warnings emitted
+
+For more information about this error, try `rustc --explain E0107`.
diff --git a/src/test/ui/generic-associated-types/issue-67510-pass.rs b/src/test/ui/generic-associated-types/issue-67510-pass.rs
new file mode 100644
index 00000000000..ff38b3e93eb
--- /dev/null
+++ b/src/test/ui/generic-associated-types/issue-67510-pass.rs
@@ -0,0 +1,12 @@
+// check-pass
+
+#![feature(generic_associated_types)]
+  //~^ WARNING: the feature `generic_associated_types` is incomplete
+
+trait X {
+    type Y<'a>;
+}
+
+fn _func1<'a>(_x: Box<dyn X<Y<'a>=&'a ()>>) {}
+
+fn main() {}
diff --git a/src/test/ui/generic-associated-types/issue-67510-pass.stderr b/src/test/ui/generic-associated-types/issue-67510-pass.stderr
new file mode 100644
index 00000000000..0fbf704df76
--- /dev/null
+++ b/src/test/ui/generic-associated-types/issue-67510-pass.stderr
@@ -0,0 +1,11 @@
+warning: the feature `generic_associated_types` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/issue-67510-pass.rs:3:12
+   |
+LL | #![feature(generic_associated_types)]
+   |            ^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: `#[warn(incomplete_features)]` on by default
+   = note: see issue #44265 <https://github.com/rust-lang/rust/issues/44265> for more information
+
+warning: 1 warning emitted
+
diff --git a/src/test/ui/generic-associated-types/issue-67510.rs b/src/test/ui/generic-associated-types/issue-67510.rs
new file mode 100644
index 00000000000..62b22089f91
--- /dev/null
+++ b/src/test/ui/generic-associated-types/issue-67510.rs
@@ -0,0 +1,13 @@
+#![feature(generic_associated_types)]
+  //~^ WARNING: the feature `generic_associated_types` is incomplete
+
+trait X {
+    type Y<'a>;
+}
+
+fn f(x: Box<dyn X<Y<'a>=&'a ()>>) {}
+  //~^ ERROR: use of undeclared lifetime name `'a`
+  //~| ERROR: use of undeclared lifetime name `'a`
+
+
+fn main() {}
diff --git a/src/test/ui/generic-associated-types/issue-67510.stderr b/src/test/ui/generic-associated-types/issue-67510.stderr
new file mode 100644
index 00000000000..12755c56974
--- /dev/null
+++ b/src/test/ui/generic-associated-types/issue-67510.stderr
@@ -0,0 +1,32 @@
+warning: the feature `generic_associated_types` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/issue-67510.rs:1:12
+   |
+LL | #![feature(generic_associated_types)]
+   |            ^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: `#[warn(incomplete_features)]` on by default
+   = note: see issue #44265 <https://github.com/rust-lang/rust/issues/44265> for more information
+
+error[E0261]: use of undeclared lifetime name `'a`
+  --> $DIR/issue-67510.rs:8:21
+   |
+LL | fn f(x: Box<dyn X<Y<'a>=&'a ()>>) {}
+   |     -               ^^ undeclared lifetime
+   |     |
+   |     help: consider introducing lifetime `'a` here: `<'a>`
+   |
+   = help: if you want to experiment with in-band lifetime bindings, add `#![feature(in_band_lifetimes)]` to the crate attributes
+
+error[E0261]: use of undeclared lifetime name `'a`
+  --> $DIR/issue-67510.rs:8:26
+   |
+LL | fn f(x: Box<dyn X<Y<'a>=&'a ()>>) {}
+   |     -                    ^^ undeclared lifetime
+   |     |
+   |     help: consider introducing lifetime `'a` here: `<'a>`
+   |
+   = help: if you want to experiment with in-band lifetime bindings, add `#![feature(in_band_lifetimes)]` to the crate attributes
+
+error: aborting due to 2 previous errors; 1 warning emitted
+
+For more information about this error, try `rustc --explain E0261`.
diff --git a/src/test/ui/generic-associated-types/issue-68648-1.rs b/src/test/ui/generic-associated-types/issue-68648-1.rs
new file mode 100644
index 00000000000..f294b22f73c
--- /dev/null
+++ b/src/test/ui/generic-associated-types/issue-68648-1.rs
@@ -0,0 +1,26 @@
+// check-pass
+
+#![feature(generic_associated_types)]
+  //~^ WARNING: the feature `generic_associated_types` is incomplete
+
+
+trait Fun {
+    type F<'a>;
+
+    fn identity<'a>(t: Self::F<'a>) -> Self::F<'a> { t }
+}
+
+impl <T> Fun for T {
+    type F<'a> = Self;
+}
+
+fn bug<'a, T: for<'b> Fun<F<'b> = T>>(t: T) -> T::F<'a> {
+    T::identity(t)
+}
+
+
+fn main() {
+    let x = 10;
+
+    bug(x);
+}
diff --git a/src/test/ui/generic-associated-types/issue-68648-1.stderr b/src/test/ui/generic-associated-types/issue-68648-1.stderr
new file mode 100644
index 00000000000..322a8f9e13f
--- /dev/null
+++ b/src/test/ui/generic-associated-types/issue-68648-1.stderr
@@ -0,0 +1,11 @@
+warning: the feature `generic_associated_types` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/issue-68648-1.rs:3:12
+   |
+LL | #![feature(generic_associated_types)]
+   |            ^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: `#[warn(incomplete_features)]` on by default
+   = note: see issue #44265 <https://github.com/rust-lang/rust/issues/44265> for more information
+
+warning: 1 warning emitted
+
diff --git a/src/test/ui/generic-associated-types/issue-68648-2.rs b/src/test/ui/generic-associated-types/issue-68648-2.rs
new file mode 100644
index 00000000000..e55bfcd4ba2
--- /dev/null
+++ b/src/test/ui/generic-associated-types/issue-68648-2.rs
@@ -0,0 +1,24 @@
+#![feature(generic_associated_types)]
+  //~^ WARNING: the feature `generic_associated_types` is incomplete
+
+trait Fun {
+    type F<'a>;
+
+    fn identity<'a>(t: Self::F<'a>) -> Self::F<'a> { t }
+}
+
+impl <T> Fun for T {
+    type F<'a> = Self;
+}
+
+fn bug<'a, T: Fun<F<'a> = T>>(t: T) -> T::F<'a> {
+    T::identity(())
+      //~^ ERROR: mismatched types
+}
+
+
+fn main() {
+    let x = 10;
+
+    bug(x);
+}
diff --git a/src/test/ui/generic-associated-types/issue-68648-2.stderr b/src/test/ui/generic-associated-types/issue-68648-2.stderr
new file mode 100644
index 00000000000..b51e0bca9f7
--- /dev/null
+++ b/src/test/ui/generic-associated-types/issue-68648-2.stderr
@@ -0,0 +1,23 @@
+warning: the feature `generic_associated_types` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/issue-68648-2.rs:1:12
+   |
+LL | #![feature(generic_associated_types)]
+   |            ^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: `#[warn(incomplete_features)]` on by default
+   = note: see issue #44265 <https://github.com/rust-lang/rust/issues/44265> for more information
+
+error[E0308]: mismatched types
+  --> $DIR/issue-68648-2.rs:15:17
+   |
+LL | fn bug<'a, T: Fun<F<'a> = T>>(t: T) -> T::F<'a> {
+   |            - this type parameter
+LL |     T::identity(())
+   |                 ^^ expected type parameter `T`, found `()`
+   |
+   = note: expected type parameter `T`
+                   found unit type `()`
+
+error: aborting due to previous error; 1 warning emitted
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/generic-associated-types/issue-68649-pass.rs b/src/test/ui/generic-associated-types/issue-68649-pass.rs
new file mode 100644
index 00000000000..396315302f7
--- /dev/null
+++ b/src/test/ui/generic-associated-types/issue-68649-pass.rs
@@ -0,0 +1,25 @@
+// check-pass
+
+#![feature(generic_associated_types)]
+  //~^ WARNING: the feature `generic_associated_types` is incomplete
+
+trait Fun {
+    type F<'a>;
+
+    fn identity<'a>(t: Self::F<'a>) -> Self::F<'a> { t }
+}
+
+impl <T> Fun for T {
+    type F<'a> = Self;
+}
+
+fn bug<'a, T: Fun<F<'a> = T>>(t: T) -> T::F<'a> {
+    T::identity(t)
+}
+
+
+fn main() {
+    let x = 10;
+
+    bug(x);
+}
diff --git a/src/test/ui/generic-associated-types/issue-68649-pass.stderr b/src/test/ui/generic-associated-types/issue-68649-pass.stderr
new file mode 100644
index 00000000000..e4a2f8d2a64
--- /dev/null
+++ b/src/test/ui/generic-associated-types/issue-68649-pass.stderr
@@ -0,0 +1,11 @@
+warning: the feature `generic_associated_types` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/issue-68649-pass.rs:3:12
+   |
+LL | #![feature(generic_associated_types)]
+   |            ^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: `#[warn(incomplete_features)]` on by default
+   = note: see issue #44265 <https://github.com/rust-lang/rust/issues/44265> for more information
+
+warning: 1 warning emitted
+
diff --git a/src/test/ui/generic-associated-types/issue-74684-1.rs b/src/test/ui/generic-associated-types/issue-74684-1.rs
new file mode 100644
index 00000000000..a483da863ff
--- /dev/null
+++ b/src/test/ui/generic-associated-types/issue-74684-1.rs
@@ -0,0 +1,26 @@
+#![feature(generic_associated_types)]
+  //~^ WARNING: the feature `generic_associated_types` is incomplete
+
+trait Fun {
+    type F<'a>: ?Sized;
+
+    fn identity<'a>(t: &'a Self::F<'a>) -> &'a Self::F<'a> { t }
+}
+
+impl <T> Fun for T {
+    type F<'a> = [u8];
+}
+
+fn bug<'a, T: ?Sized + Fun<F<'a> = [u8]>>(_ : Box<T>) -> &'static T::F<'a> {
+    let a = [0; 1];
+    let _x = T::identity(&a);
+      //~^ ERROR: `a` does not live long enough
+    todo!()
+}
+
+
+fn main() {
+    let x = 10;
+
+    bug(Box::new(x));
+}
diff --git a/src/test/ui/generic-associated-types/issue-74684-1.stderr b/src/test/ui/generic-associated-types/issue-74684-1.stderr
new file mode 100644
index 00000000000..651da696827
--- /dev/null
+++ b/src/test/ui/generic-associated-types/issue-74684-1.stderr
@@ -0,0 +1,27 @@
+warning: the feature `generic_associated_types` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/issue-74684-1.rs:1:12
+   |
+LL | #![feature(generic_associated_types)]
+   |            ^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: `#[warn(incomplete_features)]` on by default
+   = note: see issue #44265 <https://github.com/rust-lang/rust/issues/44265> for more information
+
+error[E0597]: `a` does not live long enough
+  --> $DIR/issue-74684-1.rs:16:26
+   |
+LL | fn bug<'a, T: ?Sized + Fun<F<'a> = [u8]>>(_ : Box<T>) -> &'static T::F<'a> {
+   |        -- lifetime `'a` defined here
+LL |     let a = [0; 1];
+LL |     let _x = T::identity(&a);
+   |              ------------^^-
+   |              |           |
+   |              |           borrowed value does not live long enough
+   |              argument requires that `a` is borrowed for `'a`
+...
+LL | }
+   | - `a` dropped here while still borrowed
+
+error: aborting due to previous error; 1 warning emitted
+
+For more information about this error, try `rustc --explain E0597`.
diff --git a/src/test/ui/generic-associated-types/issue-74684-2.rs b/src/test/ui/generic-associated-types/issue-74684-2.rs
new file mode 100644
index 00000000000..0caf19cb030
--- /dev/null
+++ b/src/test/ui/generic-associated-types/issue-74684-2.rs
@@ -0,0 +1,26 @@
+#![feature(generic_associated_types)]
+  //~^ WARNING: the feature `generic_associated_types` is incomplete
+
+trait Fun {
+    type F<'a>: ?Sized;
+
+    fn identity<'a>(t: &'a Self::F<'a>) -> &'a Self::F<'a> { t }
+}
+
+impl <T> Fun for T {
+    type F<'a> = i32;
+}
+
+fn bug<'a, T: ?Sized + Fun<F<'a> = [u8]>>(t: Box<T>) -> &'static T::F<'a> {
+    let a = [0; 1];
+    let x = T::identity(&a);
+    todo!()
+}
+
+
+fn main() {
+    let x = 10;
+
+    bug(Box::new(x));
+      //~^ ERROR: type mismatch resolving `<{integer} as Fun>::F<'_> == [u8]`
+}
diff --git a/src/test/ui/generic-associated-types/issue-74684-2.stderr b/src/test/ui/generic-associated-types/issue-74684-2.stderr
new file mode 100644
index 00000000000..8c3484f9a73
--- /dev/null
+++ b/src/test/ui/generic-associated-types/issue-74684-2.stderr
@@ -0,0 +1,21 @@
+warning: the feature `generic_associated_types` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/issue-74684-2.rs:1:12
+   |
+LL | #![feature(generic_associated_types)]
+   |            ^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: `#[warn(incomplete_features)]` on by default
+   = note: see issue #44265 <https://github.com/rust-lang/rust/issues/44265> for more information
+
+error[E0271]: type mismatch resolving `<{integer} as Fun>::F<'_> == [u8]`
+  --> $DIR/issue-74684-2.rs:24:5
+   |
+LL | fn bug<'a, T: ?Sized + Fun<F<'a> = [u8]>>(t: Box<T>) -> &'static T::F<'a> {
+   |                            ------------ required by this bound in `bug`
+...
+LL |     bug(Box::new(x));
+   |     ^^^ expected slice `[u8]`, found `i32`
+
+error: aborting due to previous error; 1 warning emitted
+
+For more information about this error, try `rustc --explain E0271`.
diff --git a/src/test/ui/generic-associated-types/issue-76535.rs b/src/test/ui/generic-associated-types/issue-76535.rs
new file mode 100644
index 00000000000..2b4757d8d15
--- /dev/null
+++ b/src/test/ui/generic-associated-types/issue-76535.rs
@@ -0,0 +1,41 @@
+#![feature(generic_associated_types)]
+ //~^ WARNING the feature
+
+pub trait SubTrait {}
+
+pub trait SuperTrait {
+    type SubType<'a>: SubTrait;
+      //~^ ERROR missing generics for associated
+
+    fn get_sub<'a>(&'a mut self) -> Self::SubType<'a>;
+}
+
+pub struct SubStruct<'a> {
+    sup: &'a mut SuperStruct,
+}
+
+impl<'a> SubTrait for SubStruct<'a> {}
+
+pub struct SuperStruct {
+    value: u8,
+}
+
+impl SuperStruct {
+    pub fn new(value: u8) -> SuperStruct {
+        SuperStruct { value }
+    }
+}
+
+impl SuperTrait for SuperStruct {
+    type SubType<'a> = SubStruct<'a>;
+
+    fn get_sub<'a>(&'a mut self) -> Self::SubType<'a> {
+        SubStruct { sup: self }
+    }
+}
+
+fn main() {
+    let sub: Box<dyn SuperTrait<SubType = SubStruct>> = Box::new(SuperStruct::new(0));
+      //~^ ERROR the trait
+      //~| ERROR the trait
+}
diff --git a/src/test/ui/generic-associated-types/issue-76535.stderr b/src/test/ui/generic-associated-types/issue-76535.stderr
new file mode 100644
index 00000000000..ce4875af9c0
--- /dev/null
+++ b/src/test/ui/generic-associated-types/issue-76535.stderr
@@ -0,0 +1,63 @@
+warning: the feature `generic_associated_types` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/issue-76535.rs:1:12
+   |
+LL | #![feature(generic_associated_types)]
+   |            ^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: `#[warn(incomplete_features)]` on by default
+   = note: see issue #44265 <https://github.com/rust-lang/rust/issues/44265> for more information
+
+error[E0107]: missing generics for associated type `SuperTrait::SubType`
+  --> $DIR/issue-76535.rs:7:10
+   |
+LL |     type SubType<'a>: SubTrait;
+   |          ^^^^^^^ expected 1 lifetime argument
+   |
+note: associated type defined here, with 1 lifetime parameter: `'a`
+  --> $DIR/issue-76535.rs:7:10
+   |
+LL |     type SubType<'a>: SubTrait;
+   |          ^^^^^^^ --
+help: use angle brackets to add missing lifetime argument
+   |
+LL |     type SubType<'a><'a>: SubTrait;
+   |                 ^^^^
+
+error[E0038]: the trait `SuperTrait` cannot be made into an object
+  --> $DIR/issue-76535.rs:38:14
+   |
+LL |     let sub: Box<dyn SuperTrait<SubType = SubStruct>> = Box::new(SuperStruct::new(0));
+   |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `SuperTrait` cannot be made into an object
+   |
+   = help: consider moving `get_sub` to another trait
+note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
+  --> $DIR/issue-76535.rs:10:37
+   |
+LL | pub trait SuperTrait {
+   |           ---------- this trait cannot be made into an object...
+...
+LL |     fn get_sub<'a>(&'a mut self) -> Self::SubType<'a>;
+   |                                     ^^^^^^^^^^^^^^^^^ ...because method `get_sub` references the `Self` type in its return type
+
+error[E0038]: the trait `SuperTrait` cannot be made into an object
+  --> $DIR/issue-76535.rs:38:57
+   |
+LL |     let sub: Box<dyn SuperTrait<SubType = SubStruct>> = Box::new(SuperStruct::new(0));
+   |                                                         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `SuperTrait` cannot be made into an object
+   |
+   = help: consider moving `get_sub` to another trait
+note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
+  --> $DIR/issue-76535.rs:10:37
+   |
+LL | pub trait SuperTrait {
+   |           ---------- this trait cannot be made into an object...
+...
+LL |     fn get_sub<'a>(&'a mut self) -> Self::SubType<'a>;
+   |                                     ^^^^^^^^^^^^^^^^^ ...because method `get_sub` references the `Self` type in its return type
+   = note: required because of the requirements on the impl of `CoerceUnsized<Box<dyn SuperTrait<SubType = SubStruct<'_>>>>` for `Box<SuperStruct>`
+   = note: required by cast to type `Box<dyn SuperTrait<SubType = SubStruct<'_>>>`
+
+error: aborting due to 3 previous errors; 1 warning emitted
+
+Some errors have detailed explanations: E0038, E0107.
+For more information about an error, try `rustc --explain E0038`.
diff --git a/src/test/ui/generic-associated-types/issue-79422.rs b/src/test/ui/generic-associated-types/issue-79422.rs
new file mode 100644
index 00000000000..26b38430dd9
--- /dev/null
+++ b/src/test/ui/generic-associated-types/issue-79422.rs
@@ -0,0 +1,47 @@
+#![allow(incomplete_features)]
+#![feature(generic_associated_types)]
+
+trait RefCont<'a, T> {
+    fn t(&'a self) -> &'a T;
+}
+
+impl<'a, T> RefCont<'a, T> for &'a T {
+    fn t(&'a self) -> &'a T {
+        self
+    }
+}
+
+impl<'a, T> RefCont<'a, T> for Box<T> {
+    fn t(&'a self) -> &'a T {
+        self.as_ref()
+    }
+}
+
+trait MapLike<K, V> {
+    type VRefCont<'a>: RefCont<'a, V>;
+      //~^ ERROR missing generics
+    fn get<'a>(&'a self, key: &K) -> Option<Self::VRefCont<'a>>;
+}
+
+impl<K: Ord, V: 'static> MapLike<K, V> for std::collections::BTreeMap<K, V> {
+    type VRefCont<'a> = &'a V;
+    fn get<'a>(&'a self, key: &K) -> Option<&'a V> {
+        std::collections::BTreeMap::get(self, key)
+    }
+}
+
+struct Source;
+
+impl<K, V: Default> MapLike<K, V> for Source {
+    type VRefCont<'a> = Box<V>;
+    fn get<'a>(&self, _: &K) -> Option<Box<V>> {
+        Some(Box::new(V::default()))
+    }
+}
+
+fn main() {
+    let m = Box::new(std::collections::BTreeMap::<u8, u8>::new())
+        as Box<dyn MapLike<u8, u8, VRefCont = dyn RefCont<'_, u8>>>;
+      //~^ ERROR the trait
+      //~^^^ ERROR the trait
+}
diff --git a/src/test/ui/generic-associated-types/issue-79422.stderr b/src/test/ui/generic-associated-types/issue-79422.stderr
new file mode 100644
index 00000000000..d2e12962715
--- /dev/null
+++ b/src/test/ui/generic-associated-types/issue-79422.stderr
@@ -0,0 +1,54 @@
+error[E0107]: missing generics for associated type `MapLike::VRefCont`
+  --> $DIR/issue-79422.rs:21:10
+   |
+LL |     type VRefCont<'a>: RefCont<'a, V>;
+   |          ^^^^^^^^ expected 1 lifetime argument
+   |
+note: associated type defined here, with 1 lifetime parameter: `'a`
+  --> $DIR/issue-79422.rs:21:10
+   |
+LL |     type VRefCont<'a>: RefCont<'a, V>;
+   |          ^^^^^^^^ --
+help: use angle brackets to add missing lifetime argument
+   |
+LL |     type VRefCont<'a><'a>: RefCont<'a, V>;
+   |                  ^^^^
+
+error[E0038]: the trait `MapLike` cannot be made into an object
+  --> $DIR/issue-79422.rs:44:12
+   |
+LL |         as Box<dyn MapLike<u8, u8, VRefCont = dyn RefCont<'_, u8>>>;
+   |            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `MapLike` cannot be made into an object
+   |
+   = help: consider moving `get` to another trait
+note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
+  --> $DIR/issue-79422.rs:23:38
+   |
+LL | trait MapLike<K, V> {
+   |       ------- this trait cannot be made into an object...
+...
+LL |     fn get<'a>(&'a self, key: &K) -> Option<Self::VRefCont<'a>>;
+   |                                      ^^^^^^^^^^^^^^^^^^^^^^^^^^ ...because method `get` references the `Self` type in its return type
+
+error[E0038]: the trait `MapLike` cannot be made into an object
+  --> $DIR/issue-79422.rs:43:13
+   |
+LL |     let m = Box::new(std::collections::BTreeMap::<u8, u8>::new())
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `MapLike` cannot be made into an object
+   |
+   = help: consider moving `get` to another trait
+note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
+  --> $DIR/issue-79422.rs:23:38
+   |
+LL | trait MapLike<K, V> {
+   |       ------- this trait cannot be made into an object...
+...
+LL |     fn get<'a>(&'a self, key: &K) -> Option<Self::VRefCont<'a>>;
+   |                                      ^^^^^^^^^^^^^^^^^^^^^^^^^^ ...because method `get` references the `Self` type in its return type
+   = note: required because of the requirements on the impl of `CoerceUnsized<Box<dyn MapLike<u8, u8, VRefCont = (dyn RefCont<'_, u8> + 'static)>>>` for `Box<BTreeMap<u8, u8>>`
+   = note: required by cast to type `Box<dyn MapLike<u8, u8, VRefCont = (dyn RefCont<'_, u8> + 'static)>>`
+
+error: aborting due to 3 previous errors
+
+Some errors have detailed explanations: E0038, E0107.
+For more information about an error, try `rustc --explain E0038`.
diff --git a/src/test/ui/generic-associated-types/issue-80433-reduced.rs b/src/test/ui/generic-associated-types/issue-80433-reduced.rs
new file mode 100644
index 00000000000..7c1673edc51
--- /dev/null
+++ b/src/test/ui/generic-associated-types/issue-80433-reduced.rs
@@ -0,0 +1,24 @@
+// check-pass
+
+#![allow(incomplete_features)]
+#![feature(generic_associated_types)]
+
+struct E {}
+
+trait TestMut {
+    type Output<'a>;
+    fn test_mut(&mut self) -> Self::Output<'static>;
+}
+
+impl TestMut for E {
+    type Output<'a> = usize;
+    fn test_mut(&mut self) -> Self::Output<'static> {
+        todo!()
+    }
+}
+
+fn test_simpler<'a>(_: impl TestMut<Output<'a> = usize>) {}
+
+fn main() {
+    test_simpler(E {});
+}
diff --git a/src/test/ui/generic-associated-types/issue-80433.rs b/src/test/ui/generic-associated-types/issue-80433.rs
new file mode 100644
index 00000000000..ea65f05de23
--- /dev/null
+++ b/src/test/ui/generic-associated-types/issue-80433.rs
@@ -0,0 +1,35 @@
+#![feature(generic_associated_types)]
+#![allow(incomplete_features)]
+
+#[derive(Default)]
+struct E<T> {
+    data: T,
+}
+
+trait TestMut {
+    type Output<'a>;
+      //~^ ERROR missing generics
+    fn test_mut<'a>(&'a mut self) -> Self::Output<'a>;
+}
+
+impl<T> TestMut for E<T>
+where
+    T: 'static,
+{
+    type Output<'a> = &'a mut T;
+    fn test_mut<'a>(&'a mut self) -> Self::Output<'a> {
+        &mut self.data
+    }
+}
+
+fn test_simpler<'a>(dst: &'a mut impl TestMut<Output = &'a mut f32>)
+{
+    for n in 0i16..100 {
+        *dst.test_mut() = n.into();
+    }
+}
+
+fn main() {
+    let mut t1: E<f32> = Default::default();
+    test_simpler(&mut t1);
+}
diff --git a/src/test/ui/generic-associated-types/issue-80433.stderr b/src/test/ui/generic-associated-types/issue-80433.stderr
new file mode 100644
index 00000000000..5398920fafd
--- /dev/null
+++ b/src/test/ui/generic-associated-types/issue-80433.stderr
@@ -0,0 +1,19 @@
+error[E0107]: missing generics for associated type `TestMut::Output`
+  --> $DIR/issue-80433.rs:10:10
+   |
+LL |     type Output<'a>;
+   |          ^^^^^^ expected 1 lifetime argument
+   |
+note: associated type defined here, with 1 lifetime parameter: `'a`
+  --> $DIR/issue-80433.rs:10:10
+   |
+LL |     type Output<'a>;
+   |          ^^^^^^ --
+help: use angle brackets to add missing lifetime argument
+   |
+LL |     type Output<'a><'a>;
+   |                ^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0107`.
diff --git a/src/test/ui/generic-associated-types/parse/trait-path-type-error-once-implemented.rs b/src/test/ui/generic-associated-types/parse/trait-path-type-error-once-implemented.rs
index e203a5e0d2d..2d38770bcdf 100644
--- a/src/test/ui/generic-associated-types/parse/trait-path-type-error-once-implemented.rs
+++ b/src/test/ui/generic-associated-types/parse/trait-path-type-error-once-implemented.rs
@@ -1,10 +1,14 @@
 #![feature(generic_associated_types)]
+  //~^ the feature `generic_associated_types` is incomplete
 
 trait X {
     type Y<'a>;
+      //~^ ERROR this associated type
+      //~| ERROR this associated type
 }
 
 const _: () = {
   fn f2<'a>(arg : Box<dyn X<Y<1> = &'a ()>>) {}
-      //~^  ERROR: generic associated types in trait paths are currently not implemented
 };
+
+fn main() {}
diff --git a/src/test/ui/generic-associated-types/parse/trait-path-type-error-once-implemented.stderr b/src/test/ui/generic-associated-types/parse/trait-path-type-error-once-implemented.stderr
index e59a72a99ee..60b8fb9bcaa 100644
--- a/src/test/ui/generic-associated-types/parse/trait-path-type-error-once-implemented.stderr
+++ b/src/test/ui/generic-associated-types/parse/trait-path-type-error-once-implemented.stderr
@@ -1,8 +1,49 @@
-error: generic associated types in trait paths are currently not implemented
-  --> $DIR/trait-path-type-error-once-implemented.rs:8:30
+warning: the feature `generic_associated_types` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/trait-path-type-error-once-implemented.rs:1:12
    |
-LL |   fn f2<'a>(arg : Box<dyn X<Y<1> = &'a ()>>) {}
-   |                              ^^^
+LL | #![feature(generic_associated_types)]
+   |            ^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: `#[warn(incomplete_features)]` on by default
+   = note: see issue #44265 <https://github.com/rust-lang/rust/issues/44265> for more information
+
+error[E0107]: this associated type takes 1 lifetime argument but 0 lifetime arguments were supplied
+  --> $DIR/trait-path-type-error-once-implemented.rs:5:10
+   |
+LL |     type Y<'a>;
+   |          ^ expected 1 lifetime argument
+   |
+note: associated type defined here, with 1 lifetime parameter: `'a`
+  --> $DIR/trait-path-type-error-once-implemented.rs:5:10
+   |
+LL |     type Y<'a>;
+   |          ^ --
+help: add missing lifetime argument
+   |
+LL |   fn f2<'a>(arg : Box<dyn X<Y<'a1> = &'a ()>>) {}
+   |                               ^^
+
+error[E0107]: this associated type takes 0 const arguments but 1 const argument was supplied
+  --> $DIR/trait-path-type-error-once-implemented.rs:5:10
+   |
+LL |       type Y<'a>;
+   |  __________^-
+   | |          |
+   | |          expected 0 const arguments
+LL | |
+LL | |
+LL | | }
+LL | |
+LL | | const _: () = {
+LL | |   fn f2<'a>(arg : Box<dyn X<Y<1> = &'a ()>>) {}
+   | |________________________________- help: remove these generics
+   |
+note: associated type defined here, with 0 const parameters
+  --> $DIR/trait-path-type-error-once-implemented.rs:5:10
+   |
+LL |     type Y<'a>;
+   |          ^
 
-error: aborting due to previous error
+error: aborting due to 2 previous errors; 1 warning emitted
 
+For more information about this error, try `rustc --explain E0107`.
diff --git a/src/test/ui/generic-associated-types/parse/trait-path-unimplemented.rs b/src/test/ui/generic-associated-types/parse/trait-path-unimplemented.rs
deleted file mode 100644
index 02d53d5faee..00000000000
--- a/src/test/ui/generic-associated-types/parse/trait-path-unimplemented.rs
+++ /dev/null
@@ -1,17 +0,0 @@
-#![feature(generic_associated_types)]
-
-trait X {
-    type Y<'a>;
-}
-
-const _: () = {
-  fn f1<'a>(arg : Box<dyn X<Y<'a> = &'a ()>>) {}
-      //~^  ERROR: generic associated types in trait paths are currently not implemented
-};
-
-const _: () = {
-  fn f1<'a>(arg : Box<dyn X<Y('a) = &'a ()>>) {}
-      //~^  ERROR: lifetime in trait object type must be followed by `+`
-};
-
-fn main() {}
diff --git a/src/test/ui/generic-associated-types/parse/trait-path-unimplemented.stderr b/src/test/ui/generic-associated-types/parse/trait-path-unimplemented.stderr
deleted file mode 100644
index 1fba9cebd24..00000000000
--- a/src/test/ui/generic-associated-types/parse/trait-path-unimplemented.stderr
+++ /dev/null
@@ -1,14 +0,0 @@
-error: lifetime in trait object type must be followed by `+`
-  --> $DIR/trait-path-unimplemented.rs:13:31
-   |
-LL |   fn f1<'a>(arg : Box<dyn X<Y('a) = &'a ()>>) {}
-   |                               ^^
-
-error: generic associated types in trait paths are currently not implemented
-  --> $DIR/trait-path-unimplemented.rs:8:30
-   |
-LL |   fn f1<'a>(arg : Box<dyn X<Y<'a> = &'a ()>>) {}
-   |                              ^^^^
-
-error: aborting due to 2 previous errors
-