diff --git a/src/librustdoc/html/render/mod.rs b/src/librustdoc/html/render/mod.rs
index dc34c7844bf..9e993499276 100644
--- a/src/librustdoc/html/render/mod.rs
+++ b/src/librustdoc/html/render/mod.rs
@@ -1794,13 +1794,64 @@ fn render_impl(
let mut default_impl_items = Buffer::empty_from(w);
let impl_ = i.inner_impl();
+ // Impl items are grouped by kinds:
+ //
+ // 1. Types
+ // 2. Constants
+ // 3. Functions
+ //
+ // This order is because you can have associated types in associated constants, and both in
+ // associcated functions. So with this order, when reading from top to bottom, you should always
+ // see all items definitions before they're actually used.
+ let mut assoc_consts = Vec::new();
+ let mut methods = Vec::new();
+
if !impl_.is_negative_trait_impl() {
for trait_item in &impl_.items {
+ match *trait_item.kind {
+ clean::MethodItem(..) | clean::TyMethodItem(_) => methods.push(trait_item),
+ clean::TyAssocConstItem(..) | clean::AssocConstItem(_) => {
+ assoc_consts.push(trait_item)
+ }
+ clean::TyAssocTypeItem(..) | clean::AssocTypeItem(..) => {
+ // We render it directly since they're supposed to come first.
+ doc_impl_item(
+ &mut default_impl_items,
+ &mut impl_items,
+ cx,
+ trait_item,
+ if trait_.is_some() { &i.impl_item } else { parent },
+ link,
+ render_mode,
+ false,
+ trait_,
+ rendering_params,
+ );
+ }
+ _ => {}
+ }
+ }
+
+ for assoc_const in assoc_consts {
doc_impl_item(
&mut default_impl_items,
&mut impl_items,
cx,
- trait_item,
+ assoc_const,
+ if trait_.is_some() { &i.impl_item } else { parent },
+ link,
+ render_mode,
+ false,
+ trait_,
+ rendering_params,
+ );
+ }
+ for method in methods {
+ doc_impl_item(
+ &mut default_impl_items,
+ &mut impl_items,
+ cx,
+ method,
if trait_.is_some() { &i.impl_item } else { parent },
link,
render_mode,