Change:
I tried this code: I expected to see this happen: It not work correctly as if you remove it shouts at you saying its unsupported and will be a hard error one day. Instead, this happened: defaults on GATs seem to function perfectly fine version from playground: cc this is probably should either be allowed or a hard error before stabilisation?
one issue is that we ignore defaults on the gat in impls
WG-prioritization assigning priority (). label -I-prioritize +P-medium

Discussion:
_ => None, }; <ins> enum Defaults { Allowed, // See #36887 FutureCompatDisallowed, Deny, } </ins> let no_generics = hir::Generics::empty(); let ast_generics = node.generics().unwrap_or(&no_generics); let (opt_self, allow_defaults) = match node {

}, }); <del> (opt_self, true) </del> <ins> (opt_self, Defaults::Allowed) </ins> } ItemKind::TyAlias(..) | ItemKind::Enum(..) | ItemKind::Struct(..) | ItemKind::OpaqueTy(..) <del> | ItemKind::Union(..) => (None, true), _ => (None, false), </del> <ins> | ItemKind::Union(..) => (None, Defaults::Allowed), _ => (None, Defaults::FutureCompatDisallowed), </ins> } } <del> _ => (None, false), </del> <ins> // GATs Node::TraitItem(item) if matches!(item.kind, TraitItemKind::Type(..)) => { (None, Defaults::Deny) } Node::ImplItem(item) if matches!(item.kind, ImplItemKind::TyAlias(..)) => { (None, Defaults::Deny) } _ => (None, Defaults::FutureCompatDisallowed), </ins> }; let has_self = opt_self.is_some();

let type_start = own_start - has_self as u32 + params.len() as u32; let mut i = 0; <ins> const TYPE_DEFAULT_NOT_ALLOWED: &'static str = "defaults for type parameters are only allowed in  `struct`, `enum`, `type`, or `trait` definitions"; </ins> params.extend(ast_generics.params.iter().filter_map(|param| match param.kind { GenericParamKind::Lifetime { .. } => None, GenericParamKind::Type { ref default, synthetic, .. } => { <del> if !allow_defaults && default.is_some() { if !tcx.features().default_type_parameter_fallback { tcx.struct_span_lint_hir( lint::builtin::INVALID_TYPE_PARAM_DEFAULT, param.hir_id, param.span, |lint| { lint.build( "defaults for type parameters are only allowed in  `struct`, `enum`, `type`, or `trait` definitions", ) .emit(); }, ); </del> <ins> if default.is_some() { match allow_defaults { Defaults::Allowed => {} Defaults::FutureCompatDisallowed if tcx.features().default_type_parameter_fallback => {} Defaults::FutureCompatDisallowed => { tcx.struct_span_lint_hir( lint::builtin::INVALID_TYPE_PARAM_DEFAULT, param.hir_id, param.span, |lint| { lint.build(TYPE_DEFAULT_NOT_ALLOWED).emit(); }, ); } Defaults::Deny => { tcx.sess.span_err(param.span, TYPE_DEFAULT_NOT_ALLOWED); } </ins> } }

Some(param_def) } GenericParamKind::Const { default, .. } => { <del> if !allow_defaults && default.is_some() { </del> <ins> if !matches!(allow_defaults, Defaults::Allowed) && default.is_some() { </ins> tcx.sess.span_err( param.span, "defaults for const parameters are only allowed in 

<ins> // Check that we disallow GAT param defaults, even with `invalid_type_param_default` allowed #![allow(invalid_type_param_default)] trait Trait { type Assoc<T = u32>; //~^ defaults for type parameters are only allowed } impl Trait for () { type Assoc<T = u32> = u64; //~^ defaults for type parameters are only allowed } impl Trait for u32 { type Assoc<T = u32> = T; //~^ defaults for type parameters are only allowed } trait Other {} impl Other for u32 {} fn foo<T>() where T: Trait<Assoc = u32>, T::Assoc: Other { } fn main() { // errors foo::<()>(); // works foo::<u32>(); } </ins>

<ins> error: defaults for type parameters are only allowed in `struct`, `enum`, `type`, or `trait` definitions --> $DIR/type-param-defaults.rs:6:16 | LL |     type Assoc<T = u32>; |                ^^^^^^^ error: defaults for type parameters are only allowed in `struct`, `enum`, `type`, or `trait` definitions --> $DIR/type-param-defaults.rs:11:16 | LL |     type Assoc<T = u32> = u64; |                ^^^^^^^ error: defaults for type parameters are only allowed in `struct`, `enum`, `type`, or `trait` definitions --> $DIR/type-param-defaults.rs:16:16 | LL |     type Assoc<T = u32> = T; |                ^^^^^^^ error: aborting due to 3 previous errors </ins>