Repository: rust-lang/rust
File: compiler/rustc_ast_lowering/src/item.rs (Rust)

Code before:
                ident,
                generics,
                after_where_clause,
                bounds,
                ty,
                ..
            }) => {
                let mut generics = generics.clone();
                add_ty_alias_where_clause(&mut generics, after_where_clause, false);
                let (generics, kind) = self.lower_generics(
                    &generics,
                    i.id,
                    ImplTraitContext::Disallowed(ImplTraitPosition::Generic),
                    |this| {
                        let mut ty = ty.as_ref().map(|x| {
                            this.lower_ty_alloc(
                                x,
                                ImplTraitContext::Disallowed(ImplTraitPosition::AssocTy),
                            )
                        });
                        if matches!(i.kind.defaultness(), Defaultness::Final(..)) {
                            let guar = this.dcx().span_delayed_bug(
                                i.span,
                                "expected to lower associated type, but it is wrongly marked as `final`",
                            );
                            ty = Some(this.arena.alloc(this.ty(i.span, hir::TyKind::Err(guar))));
                        };
                        hir::TraitItemKind::Type(
                            this.lower_param_bounds(
                                bounds,
                                RelaxedBoundPolicy::Allowed,
                                ImplTraitContext::Disallowed(ImplTraitPosition::Generic),
                            ),
                            ty,
                        )
                    },
                );
                (*ident, generics, kind, ty.is_some())
            }
            AssocItemKind::Delegation(box delegation) => {
                let delegation_results = self.lower_delegation(delegation, i.id);
                let item_kind = hir::TraitItemKind::Fn(
                    delegation_results.sig,
                    hir::TraitFn::Provided(delegation_results.body_id),
                );
                (delegation.ident, delegation_results.generics, item_kind, true)
            }
            AssocItemKind::MacCall(..) | AssocItemKind::DelegationMac(..) => {
                panic!("macros should have been expanded by now")
            }
        };

Review comment (suggestion):
Lowering `trait Trait { final type X; }` and `trait Trait { final type X = Type; }` to `trait Trait { final type X = {type error}; }` is a bit roundabout and overkill.

I would just lower it to `trait Trait { type X; }` by mapping the `Final` to `Default { has_value }`. Let's do that for assoc tys & consts. Later analysis steps clearly don't assume that trait assoc consts & types can be final & aren't prepared to handle them, justifiably so.

Code after:
                ident,
                generics,
                after_where_clause,
                bounds,
                ty,
                ..
            }) => {
                let mut generics = generics.clone();
                add_ty_alias_where_clause(&mut generics, after_where_clause, false);
                let (generics, kind) = self.lower_generics(
                    &generics,
                    i.id,
                    ImplTraitContext::Disallowed(ImplTraitPosition::Generic),
                    |this| {
                        let ty = ty.as_ref().map(|x| {
                            this.lower_ty_alloc(
                                x,
                                ImplTraitContext::Disallowed(ImplTraitPosition::AssocTy),
                            )
                        });
                        hir::TraitItemKind::Type(
                            this.lower_param_bounds(
                                bounds,
                                RelaxedBoundPolicy::Allowed,
                                ImplTraitContext::Disallowed(ImplTraitPosition::Generic),
                            ),
                            ty,
                        )
                    },
                );
                (*ident, generics, kind, ty.is_some())
            }
            AssocItemKind::Delegation(box delegation) => {
                let delegation_results = self.lower_delegation(delegation, i.id);
                let item_kind = hir::TraitItemKind::Fn(
                    delegation_results.sig,
                    hir::TraitFn::Provided(delegation_results.body_id),
                );
                (delegation.ident, delegation_results.generics, item_kind, true)
            }
            AssocItemKind::MacCall(..) | AssocItemKind::DelegationMac(..) => {
                panic!("macros should have been expanded by now")
            }
        };

        let defaultness = match i.kind.defaultness() {
            // We do not yet support `final` on trait associated items other than functions.
            // Even though we reject `final` on non-functions during AST validation, we still
            // need to stop propagating it here because later compiler passes do not expect
            // and cannot handle such items.
            Defaultness::Final(..) if !matches!(i.kind, AssocItemKind::Fn(..)) => {