about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2021-09-08 04:00:58 +0000
committerbors <bors@rust-lang.org>2021-09-08 04:00:58 +0000
commit72969f6526b6a3ff9f2bbfe73e26249d977794e7 (patch)
tree79047e9b18b82787886563078666119d76de5c14
parent0d0d2fe182e8980146e25cfcfff0c481892f81c6 (diff)
parent22ef04e22fc78ce0dcaaf8c8faa5944c983cdc1d (diff)
downloadrust-72969f6526b6a3ff9f2bbfe73e26249d977794e7.tar.gz
rust-72969f6526b6a3ff9f2bbfe73e26249d977794e7.zip
Auto merge of #88061 - jackh726:genericbound-cleanup, r=estebank
Remove `hir::GenericBound::Unsized`

Rather than "moving" the `?Sized` bounds to the param bounds, just also check where clauses in `astconv`. I also did some related cleanup here, but that's not strictly neccesary. Also going to do a perf run here.

r? `@estebank`
-rw-r--r--compiler/rustc_ast_lowering/src/item.rs46
-rw-r--r--compiler/rustc_ast_lowering/src/lib.rs25
-rw-r--r--compiler/rustc_hir/src/hir.rs5
-rw-r--r--compiler/rustc_hir/src/intravisit.rs1
-rw-r--r--compiler/rustc_hir_pretty/src/lib.rs3
-rw-r--r--compiler/rustc_middle/src/ty/diagnostics.rs12
-rw-r--r--compiler/rustc_save_analysis/src/dump_visitor.rs1
-rw-r--r--compiler/rustc_typeck/src/astconv/mod.rs317
-rw-r--r--compiler/rustc_typeck/src/collect.rs135
-rw-r--r--compiler/rustc_typeck/src/collect/item_bounds.rs30
-rw-r--r--src/librustdoc/clean/mod.rs9
-rw-r--r--src/test/ui/error-codes/e0119/complex-impl.stderr2
-rw-r--r--src/test/ui/generics/wrong-number-of-args.stderr88
-rw-r--r--src/test/ui/maybe-bounds-where.rs1
-rw-r--r--src/test/ui/maybe-bounds-where.stderr14
15 files changed, 300 insertions, 389 deletions
diff --git a/compiler/rustc_ast_lowering/src/item.rs b/compiler/rustc_ast_lowering/src/item.rs
index e0d4095d769..b7497c713f3 100644
--- a/compiler/rustc_ast_lowering/src/item.rs
+++ b/compiler/rustc_ast_lowering/src/item.rs
@@ -2,7 +2,6 @@ use super::{AnonymousLifetimeMode, LoweringContext, ParamMode};
 use super::{ImplTraitContext, ImplTraitPosition};
 use crate::Arena;
 
-use rustc_ast::node_id::NodeMap;
 use rustc_ast::ptr::P;
 use rustc_ast::visit::{self, AssocCtxt, FnCtxt, FnKind, Visitor};
 use rustc_ast::*;
@@ -1351,8 +1350,11 @@ impl<'hir> LoweringContext<'_, 'hir> {
         generics: &Generics,
         itctx: ImplTraitContext<'_, 'hir>,
     ) -> GenericsCtor<'hir> {
-        // Collect `?Trait` bounds in where clause and move them to parameter definitions.
-        let mut add_bounds: NodeMap<Vec<_>> = Default::default();
+        // Error if `?Trait` bounds in where clauses don't refer directly to type paramters.
+        // Note: we used to clone these bounds directly onto the type parameter (and avoid lowering
+        // these into hir when we lower thee where clauses), but this makes it quite difficult to
+        // keep track of the Span info. Now, `add_implicitly_sized` in `AstConv` checks both param bounds and
+        // where clauses for `?Sized`.
         for pred in &generics.where_clause.predicates {
             if let WherePredicate::BoundPredicate(ref bound_pred) = *pred {
                 'next_bound: for bound in &bound_pred.bounds {
@@ -1368,7 +1370,6 @@ impl<'hir> LoweringContext<'_, 'hir> {
                             {
                                 for param in &generics.params {
                                     if def_id == self.resolver.local_def_id(param.id).to_def_id() {
-                                        add_bounds.entry(param.id).or_default().push(bound.clone());
                                         continue 'next_bound;
                                     }
                                 }
@@ -1386,7 +1387,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
         }
 
         GenericsCtor {
-            params: self.lower_generic_params_mut(&generics.params, &add_bounds, itctx).collect(),
+            params: self.lower_generic_params_mut(&generics.params, itctx).collect(),
             where_clause: self.lower_where_clause(&generics.where_clause),
             span: self.lower_span(generics.span),
         }
@@ -1419,32 +1420,17 @@ impl<'hir> LoweringContext<'_, 'hir> {
                 ref bounded_ty,
                 ref bounds,
                 span,
-            }) => {
-                self.with_in_scope_lifetime_defs(&bound_generic_params, |this| {
-                    hir::WherePredicate::BoundPredicate(hir::WhereBoundPredicate {
-                        bound_generic_params: this.lower_generic_params(
-                            bound_generic_params,
-                            &NodeMap::default(),
-                            ImplTraitContext::disallowed(),
-                        ),
-                        bounded_ty: this.lower_ty(bounded_ty, ImplTraitContext::disallowed()),
-                        bounds: this.arena.alloc_from_iter(bounds.iter().map(
-                            |bound| match bound {
-                                // We used to ignore `?Trait` bounds, as they were copied into type
-                                // parameters already, but we need to keep them around only for
-                                // diagnostics when we suggest removal of `?Sized` bounds. See
-                                // `suggest_constraining_type_param`. This will need to change if
-                                // we ever allow something *other* than `?Sized`.
-                                GenericBound::Trait(p, TraitBoundModifier::Maybe) => {
-                                    hir::GenericBound::Unsized(this.lower_span(p.span))
-                                }
-                                _ => this.lower_param_bound(bound, ImplTraitContext::disallowed()),
-                            },
-                        )),
-                        span: this.lower_span(span),
-                    })
+            }) => self.with_in_scope_lifetime_defs(&bound_generic_params, |this| {
+                hir::WherePredicate::BoundPredicate(hir::WhereBoundPredicate {
+                    bound_generic_params: this
+                        .lower_generic_params(bound_generic_params, ImplTraitContext::disallowed()),
+                    bounded_ty: this.lower_ty(bounded_ty, ImplTraitContext::disallowed()),
+                    bounds: this.arena.alloc_from_iter(bounds.iter().map(|bound| {
+                        this.lower_param_bound(bound, ImplTraitContext::disallowed())
+                    })),
+                    span: this.lower_span(span),
                 })
-            }
+            }),
             WherePredicate::RegionPredicate(WhereRegionPredicate {
                 ref lifetime,
                 ref bounds,
diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs
index 5391d4b0c93..fa14764c42a 100644
--- a/compiler/rustc_ast_lowering/src/lib.rs
+++ b/compiler/rustc_ast_lowering/src/lib.rs
@@ -1313,7 +1313,6 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
                     hir::TyKind::BareFn(this.arena.alloc(hir::BareFnTy {
                         generic_params: this.lower_generic_params(
                             &f.generic_params,
-                            &NodeMap::default(),
                             ImplTraitContext::disallowed(),
                         ),
                         unsafety: this.lower_unsafety(f.unsafety),
@@ -1998,30 +1997,25 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
     fn lower_generic_params_mut<'s>(
         &'s mut self,
         params: &'s [GenericParam],
-        add_bounds: &'s NodeMap<Vec<GenericBound>>,
         mut itctx: ImplTraitContext<'s, 'hir>,
     ) -> impl Iterator<Item = hir::GenericParam<'hir>> + Captures<'a> + Captures<'s> {
-        params
-            .iter()
-            .map(move |param| self.lower_generic_param(param, add_bounds, itctx.reborrow()))
+        params.iter().map(move |param| self.lower_generic_param(param, itctx.reborrow()))
     }
 
     fn lower_generic_params(
         &mut self,
         params: &[GenericParam],
-        add_bounds: &NodeMap<Vec<GenericBound>>,
         itctx: ImplTraitContext<'_, 'hir>,
     ) -> &'hir [hir::GenericParam<'hir>] {
-        self.arena.alloc_from_iter(self.lower_generic_params_mut(params, add_bounds, itctx))
+        self.arena.alloc_from_iter(self.lower_generic_params_mut(params, itctx))
     }
 
     fn lower_generic_param(
         &mut self,
         param: &GenericParam,
-        add_bounds: &NodeMap<Vec<GenericBound>>,
         mut itctx: ImplTraitContext<'_, 'hir>,
     ) -> hir::GenericParam<'hir> {
-        let mut bounds: Vec<_> = self
+        let bounds: Vec<_> = self
             .with_anonymous_lifetime_mode(AnonymousLifetimeMode::ReportError, |this| {
                 this.lower_param_bounds_mut(&param.bounds, itctx.reborrow()).collect()
             });
@@ -2057,12 +2051,6 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
                 (param_name, kind)
             }
             GenericParamKind::Type { ref default, .. } => {
-                let add_bounds = add_bounds.get(&param.id).map_or(&[][..], |x| &x);
-                if !add_bounds.is_empty() {
-                    let params = self.lower_param_bounds_mut(add_bounds, itctx.reborrow());
-                    bounds.extend(params);
-                }
-
                 let kind = hir::GenericParamKind::Type {
                     default: default.as_ref().map(|x| {
                         self.lower_ty(x, ImplTraitContext::Disallowed(ImplTraitPosition::Other))
@@ -2123,11 +2111,8 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
         p: &PolyTraitRef,
         mut itctx: ImplTraitContext<'_, 'hir>,
     ) -> hir::PolyTraitRef<'hir> {
-        let bound_generic_params = self.lower_generic_params(
-            &p.bound_generic_params,
-            &NodeMap::default(),
-            itctx.reborrow(),
-        );
+        let bound_generic_params =
+            self.lower_generic_params(&p.bound_generic_params, itctx.reborrow());
 
         let trait_ref = self.with_in_scope_lifetime_defs(&p.bound_generic_params, |this| {
             // Any impl Trait types defined within this scope can capture
diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs
index 21fe894c6fc..84bc37170c6 100644
--- a/compiler/rustc_hir/src/hir.rs
+++ b/compiler/rustc_hir/src/hir.rs
@@ -441,10 +441,12 @@ pub enum GenericBound<'hir> {
     Trait(PolyTraitRef<'hir>, TraitBoundModifier),
     // FIXME(davidtwco): Introduce `PolyTraitRef::LangItem`
     LangItemTrait(LangItem, Span, HirId, &'hir GenericArgs<'hir>),
-    Unsized(Span),
     Outlives(Lifetime),
 }
 
+#[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))]
+rustc_data_structures::static_assert_size!(GenericBound<'_>, 48);
+
 impl GenericBound<'_> {
     pub fn trait_ref(&self) -> Option<&TraitRef<'_>> {
         match self {
@@ -458,7 +460,6 @@ impl GenericBound<'_> {
             GenericBound::Trait(t, ..) => t.span,
             GenericBound::LangItemTrait(_, span, ..) => *span,
             GenericBound::Outlives(l) => l.span,
-            GenericBound::Unsized(span) => *span,
         }
     }
 }
diff --git a/compiler/rustc_hir/src/intravisit.rs b/compiler/rustc_hir/src/intravisit.rs
index 2dd49eba442..137782a6dc7 100644
--- a/compiler/rustc_hir/src/intravisit.rs
+++ b/compiler/rustc_hir/src/intravisit.rs
@@ -871,7 +871,6 @@ pub fn walk_param_bound<'v, V: Visitor<'v>>(visitor: &mut V, bound: &'v GenericB
             visitor.visit_generic_args(span, args);
         }
         GenericBound::Outlives(ref lifetime) => visitor.visit_lifetime(lifetime),
-        GenericBound::Unsized(_) => {}
     }
 }
 
diff --git a/compiler/rustc_hir_pretty/src/lib.rs b/compiler/rustc_hir_pretty/src/lib.rs
index 42e51f4bb48..36054c04847 100644
--- a/compiler/rustc_hir_pretty/src/lib.rs
+++ b/compiler/rustc_hir_pretty/src/lib.rs
@@ -2232,9 +2232,6 @@ impl<'a> State<'a> {
                 GenericBound::Outlives(lt) => {
                     self.print_lifetime(lt);
                 }
-                GenericBound::Unsized(_) => {
-                    self.s.word("?Sized");
-                }
             }
         }
     }
diff --git a/compiler/rustc_middle/src/ty/diagnostics.rs b/compiler/rustc_middle/src/ty/diagnostics.rs
index 4cfb104bee3..092eae0fc5c 100644
--- a/compiler/rustc_middle/src/ty/diagnostics.rs
+++ b/compiler/rustc_middle/src/ty/diagnostics.rs
@@ -2,7 +2,6 @@
 
 use crate::ty::TyKind::*;
 use crate::ty::{InferTy, TyCtxt, TyS};
-use rustc_data_structures::fx::FxHashSet;
 use rustc_errors::{Applicability, DiagnosticBuilder};
 use rustc_hir as hir;
 use rustc_hir::def_id::DefId;
@@ -114,10 +113,8 @@ fn suggest_removing_unsized_bound(
     def_id: Option<DefId>,
 ) {
     // See if there's a `?Sized` bound that can be removed to suggest that.
-    // First look at the `where` clause because we can have `where T: ?Sized`, but that
-    // `?Sized` bound is *also* included in the `GenericParam` as a bound, which breaks
-    // the spans. Hence the somewhat involved logic that follows.
-    let mut where_unsized_bounds = FxHashSet::default();
+    // First look at the `where` clause because we can have `where T: ?Sized`,
+    // then look at params.
     for (where_pos, predicate) in generics.where_clause.predicates.iter().enumerate() {
         match predicate {
             WherePredicate::BoundPredicate(WhereBoundPredicate {
@@ -140,7 +137,6 @@ fn suggest_removing_unsized_bound(
             }) if segment.ident.as_str() == param_name => {
                 for (pos, bound) in bounds.iter().enumerate() {
                     match bound {
-                        hir::GenericBound::Unsized(_) => {}
                         hir::GenericBound::Trait(poly, hir::TraitBoundModifier::Maybe)
                             if poly.trait_ref.trait_def_id() == def_id => {}
                         _ => continue,
@@ -173,7 +169,6 @@ fn suggest_removing_unsized_bound(
                         //             ^^^^^^^^^
                         (_, pos, _, _) => bounds[pos - 1].span().shrink_to_hi().to(bound.span()),
                     };
-                    where_unsized_bounds.insert(bound.span());
                     err.span_suggestion_verbose(
                         sp,
                         "consider removing the `?Sized` bound to make the \
@@ -189,8 +184,7 @@ fn suggest_removing_unsized_bound(
     for (pos, bound) in param.bounds.iter().enumerate() {
         match bound {
             hir::GenericBound::Trait(poly, hir::TraitBoundModifier::Maybe)
-                if poly.trait_ref.trait_def_id() == def_id
-                    && !where_unsized_bounds.contains(&bound.span()) =>
+                if poly.trait_ref.trait_def_id() == def_id =>
             {
                 let sp = match (param.bounds.len(), pos) {
                     // T: ?Sized,
diff --git a/compiler/rustc_save_analysis/src/dump_visitor.rs b/compiler/rustc_save_analysis/src/dump_visitor.rs
index 08ed9ec73c8..3e99f4e29ef 100644
--- a/compiler/rustc_save_analysis/src/dump_visitor.rs
+++ b/compiler/rustc_save_analysis/src/dump_visitor.rs
@@ -693,7 +693,6 @@ impl<'tcx> DumpVisitor<'tcx> {
                     (Some(self.tcx.require_lang_item(lang_item, Some(span))), span)
                 }
                 hir::GenericBound::Outlives(..) => continue,
-                hir::GenericBound::Unsized(_) => continue,
             };
 
             if let Some(id) = def_id {
diff --git a/compiler/rustc_typeck/src/astconv/mod.rs b/compiler/rustc_typeck/src/astconv/mod.rs
index a795a52a25c..51bb09e4c54 100644
--- a/compiler/rustc_typeck/src/astconv/mod.rs
+++ b/compiler/rustc_typeck/src/astconv/mod.rs
@@ -111,11 +111,6 @@ pub trait AstConv<'tcx> {
     fn record_ty(&self, hir_id: hir::HirId, ty: Ty<'tcx>, span: Span);
 }
 
-pub enum SizedByDefault {
-    Yes,
-    No,
-}
-
 #[derive(Debug)]
 struct ConvertedBinding<'a, 'tcx> {
     hir_id: hir::HirId,
@@ -698,6 +693,61 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
         )
     }
 
+    fn instantiate_poly_trait_ref_inner(
+        &self,
+        hir_id: hir::HirId,
+        span: Span,
+        binding_span: Option<Span>,
+        constness: ty::BoundConstness,
+        bounds: &mut Bounds<'tcx>,
+        speculative: bool,
+        trait_ref_span: Span,
+        trait_def_id: DefId,
+        trait_segment: &hir::PathSegment<'_>,
+        args: &GenericArgs<'_>,
+        infer_args: bool,
+        self_ty: Ty<'tcx>,
+    ) -> GenericArgCountResult {
+        let (substs, arg_count) = self.create_substs_for_ast_path(
+            trait_ref_span,
+            trait_def_id,
+            &[],
+            trait_segment,
+            args,
+            infer_args,
+            Some(self_ty),
+        );
+
+        let tcx = self.tcx();
+        let bound_vars = tcx.late_bound_vars(hir_id);
+        debug!(?bound_vars);
+
+        let assoc_bindings = self.create_assoc_bindings_for_generic_args(args);
+
+        let poly_trait_ref =
+            ty::Binder::bind_with_vars(ty::TraitRef::new(trait_def_id, substs), bound_vars);
+
+        debug!(?poly_trait_ref, ?assoc_bindings);
+        bounds.trait_bounds.push((poly_trait_ref, span, constness));
+
+        let mut dup_bindings = FxHashMap::default();
+        for binding in &assoc_bindings {
+            // Specify type to assert that error was already reported in `Err` case.
+            let _: Result<_, ErrorReported> = self.add_predicates_for_ast_type_binding(
+                hir_id,
+                poly_trait_ref,
+                binding,
+                bounds,
+                speculative,
+                &mut dup_bindings,
+                binding_span.unwrap_or(binding.span),
+            );
+            // Okay to ignore `Err` because of `ErrorReported` (see above).
+        }
+
+        arg_count
+    }
+
     /// Given a trait bound like `Debug`, applies that trait bound the given self-type to construct
     /// a full trait reference. The resulting trait reference is returned. This may also generate
     /// auxiliary bounds, which are added to `bounds`.
@@ -718,7 +768,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
     /// `Bar<'a>`. The returned poly-trait-ref will have this binder instantiated explicitly,
     /// however.
     #[tracing::instrument(level = "debug", skip(self, span, constness, bounds, speculative))]
-    pub fn instantiate_poly_trait_ref(
+    pub(crate) fn instantiate_poly_trait_ref(
         &self,
         trait_ref: &hir::TraitRef<'_>,
         span: Span,
@@ -727,48 +777,34 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
         bounds: &mut Bounds<'tcx>,
         speculative: bool,
     ) -> GenericArgCountResult {
+        let hir_id = trait_ref.hir_ref_id;
+        let binding_span = None;
+        let trait_ref_span = trait_ref.path.span;
         let trait_def_id = trait_ref.trait_def_id().unwrap_or_else(|| FatalError.raise());
+        let trait_segment = trait_ref.path.segments.last().unwrap();
+        let args = trait_segment.args();
+        let infer_args = trait_segment.infer_args;
 
         self.prohibit_generics(trait_ref.path.segments.split_last().unwrap().1);
+        self.complain_about_internal_fn_trait(span, trait_def_id, trait_segment);
 
-        let tcx = self.tcx();
-        let bound_vars = tcx.late_bound_vars(trait_ref.hir_ref_id);
-        debug!(?bound_vars);
-
-        let (substs, arg_count) = self.create_substs_for_ast_trait_ref(
-            trait_ref.path.span,
+        self.instantiate_poly_trait_ref_inner(
+            hir_id,
+            span,
+            binding_span,
+            constness,
+            bounds,
+            speculative,
+            trait_ref_span,
             trait_def_id,
+            trait_segment,
+            args,
+            infer_args,
             self_ty,
-            trait_ref.path.segments.last().unwrap(),
-        );
-        let assoc_bindings = self
-            .create_assoc_bindings_for_generic_args(trait_ref.path.segments.last().unwrap().args());
-
-        let poly_trait_ref =
-            ty::Binder::bind_with_vars(ty::TraitRef::new(trait_def_id, substs), bound_vars);
-
-        debug!(?poly_trait_ref, ?assoc_bindings);
-        bounds.trait_bounds.push((poly_trait_ref, span, constness));
-
-        let mut dup_bindings = FxHashMap::default();
-        for binding in &assoc_bindings {
-            // Specify type to assert that error was already reported in `Err` case.
-            let _: Result<_, ErrorReported> = self.add_predicates_for_ast_type_binding(
-                trait_ref.hir_ref_id,
-                poly_trait_ref,
-                binding,
-                bounds,
-                speculative,
-                &mut dup_bindings,
-                binding.span,
-            );
-            // Okay to ignore `Err` because of `ErrorReported` (see above).
-        }
-
-        arg_count
+        )
     }
 
-    pub fn instantiate_lang_item_trait_ref(
+    pub(crate) fn instantiate_lang_item_trait_ref(
         &self,
         lang_item: hir::LangItem,
         span: Span,
@@ -777,36 +813,28 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
         self_ty: Ty<'tcx>,
         bounds: &mut Bounds<'tcx>,
     ) {
+        let binding_span = Some(span);
+        let constness = ty::BoundConstness::NotConst;
+        let speculative = false;
+        let trait_ref_span = span;
         let trait_def_id = self.tcx().require_lang_item(lang_item, Some(span));
+        let trait_segment = &hir::PathSegment::invalid();
+        let infer_args = false;
 
-        let (substs, _) = self.create_substs_for_ast_path(
+        self.instantiate_poly_trait_ref_inner(
+            hir_id,
             span,
+            binding_span,
+            constness,
+            bounds,
+            speculative,
+            trait_ref_span,
             trait_def_id,
-            &[],
-            &hir::PathSegment::invalid(),
+            trait_segment,
             args,
-            false,
-            Some(self_ty),
+            infer_args,
+            self_ty,
         );
-        let assoc_bindings = self.create_assoc_bindings_for_generic_args(args);
-        let tcx = self.tcx();
-        let bound_vars = tcx.late_bound_vars(hir_id);
-        let poly_trait_ref =
-            ty::Binder::bind_with_vars(ty::TraitRef::new(trait_def_id, substs), bound_vars);
-        bounds.trait_bounds.push((poly_trait_ref, span, ty::BoundConstness::NotConst));
-
-        let mut dup_bindings = FxHashMap::default();
-        for binding in assoc_bindings {
-            let _: Result<_, ErrorReported> = self.add_predicates_for_ast_type_binding(
-                hir_id,
-                poly_trait_ref,
-                &binding,
-                bounds,
-                false,
-                &mut dup_bindings,
-                span,
-            );
-        }
     }
 
     fn ast_path_to_mono_trait_ref(
@@ -853,46 +881,76 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
             .is_some()
     }
 
-    // Returns `true` if a bounds list includes `?Sized`.
-    pub fn is_unsized(&self, ast_bounds: &[hir::GenericBound<'_>], span: Span) -> bool {
+    // Sets `implicitly_sized` to true on `Bounds` if necessary
+    pub(crate) fn add_implicitly_sized<'hir>(
+        &self,
+        bounds: &mut Bounds<'hir>,
+        ast_bounds: &'hir [hir::GenericBound<'hir>],
+        self_ty_where_predicates: Option<(hir::HirId, &'hir [hir::WherePredicate<'hir>])>,
+        span: Span,
+    ) {
         let tcx = self.tcx();
 
         // Try to find an unbound in bounds.
         let mut unbound = None;
-        for ab in ast_bounds {
-            if let hir::GenericBound::Trait(ptr, hir::TraitBoundModifier::Maybe) = ab {
-                if unbound.is_none() {
-                    unbound = Some(&ptr.trait_ref);
-                } else {
-                    tcx.sess.emit_err(MultipleRelaxedDefaultBounds { span });
+        let mut search_bounds = |ast_bounds: &'hir [hir::GenericBound<'hir>]| {
+            for ab in ast_bounds {
+                if let hir::GenericBound::Trait(ptr, hir::TraitBoundModifier::Maybe) = ab {
+                    if unbound.is_none() {
+                        unbound = Some(&ptr.trait_ref);
+                    } else {
+                        tcx.sess.emit_err(MultipleRelaxedDefaultBounds { span });
+                    }
                 }
             }
-        }
-
-        let kind_id = tcx.lang_items().require(LangItem::Sized);
-        match unbound {
-            Some(tpb) => {
-                // FIXME(#8559) currently requires the unbound to be built-in.
-                if let Ok(kind_id) = kind_id {
-                    if tpb.path.res != Res::Def(DefKind::Trait, kind_id) {
-                        tcx.sess.span_warn(
-                            span,
-                            "default bound relaxed for a type parameter, but \
-                             this does nothing because the given bound is not \
-                             a default; only `?Sized` is supported",
-                        );
-                        return false;
+        };
+        search_bounds(ast_bounds);
+        if let Some((self_ty, where_clause)) = self_ty_where_predicates {
+            let self_ty_def_id = tcx.hir().local_def_id(self_ty).to_def_id();
+            for clause in where_clause {
+                match clause {
+                    hir::WherePredicate::BoundPredicate(pred) => {
+                        match pred.bounded_ty.kind {
+                            hir::TyKind::Path(hir::QPath::Resolved(_, path)) => match path.res {
+                                Res::Def(DefKind::TyParam, def_id) if def_id == self_ty_def_id => {}
+                                _ => continue,
+                            },
+                            _ => continue,
+                        }
+                        search_bounds(pred.bounds);
                     }
+                    _ => {}
                 }
             }
-            _ if kind_id.is_ok() => {
-                return false;
+        }
+
+        let sized_def_id = tcx.lang_items().require(LangItem::Sized);
+        match (&sized_def_id, unbound) {
+            (Ok(sized_def_id), Some(tpb))
+                if tpb.path.res == Res::Def(DefKind::Trait, *sized_def_id) =>
+            {
+                // There was in fact a `?Sized` bound, return without doing anything
+                return;
+            }
+            (_, Some(_)) => {
+                // There was a `?Trait` bound, but it was not `?Sized`; warn.
+                tcx.sess.span_warn(
+                    span,
+                    "default bound relaxed for a type parameter, but \
+                        this does nothing because the given bound is not \
+                        a default; only `?Sized` is supported",
+                );
+                // Otherwise, add implicitly sized if `Sized` is available.
             }
+            _ => {
+                // There was no `?Sized` bound; add implicitly sized if `Sized` is available.
+            }
+        }
+        if sized_def_id.is_err() {
             // No lang item for `Sized`, so we can't add it as a bound.
-            None => {}
+            return;
         }
-
-        true
+        bounds.implicitly_sized = Some(span);
     }
 
     /// This helper takes a *converted* parameter type (`param_ty`)
@@ -910,46 +968,43 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
     /// **A note on binders:** there is an implied binder around
     /// `param_ty` and `ast_bounds`. See `instantiate_poly_trait_ref`
     /// for more details.
-    #[tracing::instrument(level = "debug", skip(self, bounds))]
-    fn add_bounds(
+    #[tracing::instrument(level = "debug", skip(self, ast_bounds, bounds))]
+    pub(crate) fn add_bounds<'hir, I: Iterator<Item = &'hir hir::GenericBound<'hir>>>(
         &self,
         param_ty: Ty<'tcx>,
-        ast_bounds: &[hir::GenericBound<'_>],
+        ast_bounds: I,
         bounds: &mut Bounds<'tcx>,
         bound_vars: &'tcx ty::List<ty::BoundVariableKind>,
     ) {
         for ast_bound in ast_bounds {
-            match *ast_bound {
-                hir::GenericBound::Trait(ref b, hir::TraitBoundModifier::None) => {
-                    self.instantiate_poly_trait_ref(
-                        &b.trait_ref,
-                        b.span,
-                        ty::BoundConstness::NotConst,
+            match ast_bound {
+                hir::GenericBound::Trait(poly_trait_ref, modifier) => {
+                    let constness = match modifier {
+                        hir::TraitBoundModifier::MaybeConst => ty::BoundConstness::ConstIfConst,
+                        hir::TraitBoundModifier::None => ty::BoundConstness::NotConst,
+                        hir::TraitBoundModifier::Maybe => continue,
+                    };
+
+                    let _ = self.instantiate_poly_trait_ref(
+                        &poly_trait_ref.trait_ref,
+                        poly_trait_ref.span,
+                        constness,
                         param_ty,
                         bounds,
                         false,
                     );
                 }
-                hir::GenericBound::Trait(ref b, hir::TraitBoundModifier::MaybeConst) => {
-                    self.instantiate_poly_trait_ref(
-                        &b.trait_ref,
-                        b.span,
-                        ty::BoundConstness::ConstIfConst,
-                        param_ty,
-                        bounds,
-                        false,
+                &hir::GenericBound::LangItemTrait(lang_item, span, hir_id, args) => {
+                    self.instantiate_lang_item_trait_ref(
+                        lang_item, span, hir_id, args, param_ty, bounds,
                     );
                 }
-                hir::GenericBound::Trait(_, hir::TraitBoundModifier::Maybe)
-                | hir::GenericBound::Unsized(_) => {}
-                hir::GenericBound::LangItemTrait(lang_item, span, hir_id, args) => self
-                    .instantiate_lang_item_trait_ref(
-                        lang_item, span, hir_id, args, param_ty, bounds,
-                    ),
-                hir::GenericBound::Outlives(ref l) => bounds.region_bounds.push((
-                    ty::Binder::bind_with_vars(self.ast_region_to_region(l, None), bound_vars),
-                    l.span,
-                )),
+                hir::GenericBound::Outlives(lifetime) => {
+                    let region = self.ast_region_to_region(lifetime, None);
+                    bounds
+                        .region_bounds
+                        .push((ty::Binder::bind_with_vars(region, bound_vars), lifetime.span));
+                }
             }
         }
     }
@@ -970,24 +1025,20 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
     /// example above, but is not true in supertrait listings like `trait Foo: Bar + Baz`.
     ///
     /// `span` should be the declaration size of the parameter.
-    pub fn compute_bounds(
+    pub(crate) fn compute_bounds(
         &self,
         param_ty: Ty<'tcx>,
         ast_bounds: &[hir::GenericBound<'_>],
-        sized_by_default: SizedByDefault,
-        span: Span,
     ) -> Bounds<'tcx> {
-        self.compute_bounds_inner(param_ty, &ast_bounds, sized_by_default, span)
+        self.compute_bounds_inner(param_ty, &ast_bounds)
     }
 
     /// Convert the bounds in `ast_bounds` that refer to traits which define an associated type
     /// named `assoc_name` into ty::Bounds. Ignore the rest.
-    pub fn compute_bounds_that_match_assoc_type(
+    pub(crate) fn compute_bounds_that_match_assoc_type(
         &self,
         param_ty: Ty<'tcx>,
         ast_bounds: &[hir::GenericBound<'_>],
-        sized_by_default: SizedByDefault,
-        span: Span,
         assoc_name: Ident,
     ) -> Bounds<'tcx> {
         let mut result = Vec::new();
@@ -1002,25 +1053,17 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
             }
         }
 
-        self.compute_bounds_inner(param_ty, &result, sized_by_default, span)
+        self.compute_bounds_inner(param_ty, &result)
     }
 
     fn compute_bounds_inner(
         &self,
         param_ty: Ty<'tcx>,
         ast_bounds: &[hir::GenericBound<'_>],
-        sized_by_default: SizedByDefault,
-        span: Span,
     ) -> Bounds<'tcx> {
         let mut bounds = Bounds::default();
 
-        self.add_bounds(param_ty, ast_bounds, &mut bounds, ty::List::empty());
-
-        bounds.implicitly_sized = if let SizedByDefault::Yes = sized_by_default {
-            if !self.is_unsized(ast_bounds, span) { Some(span) } else { None }
-        } else {
-            None
-        };
+        self.add_bounds(param_ty, ast_bounds.iter(), &mut bounds, ty::List::empty());
 
         bounds
     }
@@ -1212,7 +1255,7 @@ 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_ty(ty::Projection(projection_ty.skip_binder()));
-                self.add_bounds(param_ty, ast_bounds, bounds, candidate.bound_vars());
+                self.add_bounds(param_ty, ast_bounds.iter(), bounds, candidate.bound_vars());
             }
         }
         Ok(())
diff --git a/compiler/rustc_typeck/src/collect.rs b/compiler/rustc_typeck/src/collect.rs
index 64120510e56..3688fa05e03 100644
--- a/compiler/rustc_typeck/src/collect.rs
+++ b/compiler/rustc_typeck/src/collect.rs
@@ -14,7 +14,7 @@
 //! At present, however, we do run collection across all items in the
 //! crate as a kind of pass. This should eventually be factored away.
 
-use crate::astconv::{AstConv, SizedByDefault};
+use crate::astconv::AstConv;
 use crate::bounds::Bounds;
 use crate::check::intrinsic::intrinsic_operation_unsafety;
 use crate::constrained_generic_params as cgp;
@@ -1156,18 +1156,10 @@ fn super_predicates_that_define_assoc_type(
                 &icx,
                 self_param_ty,
                 &bounds,
-                SizedByDefault::No,
-                item.span,
                 assoc_name,
             )
         } else {
-            <dyn AstConv<'_>>::compute_bounds(
-                &icx,
-                self_param_ty,
-                &bounds,
-                SizedByDefault::No,
-                item.span,
-            )
+            <dyn AstConv<'_>>::compute_bounds(&icx, self_param_ty, &bounds)
         };
 
         let superbounds1 = superbounds1.predicates(tcx, self_param_ty);
@@ -2176,12 +2168,13 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::GenericP
                 let param_ty = ty::ParamTy::new(index, name).to_ty(tcx);
                 index += 1;
 
-                let sized = SizedByDefault::Yes;
-                let bounds = <dyn AstConv<'_>>::compute_bounds(
+                let mut bounds = <dyn AstConv<'_>>::compute_bounds(&icx, param_ty, &param.bounds);
+                // Params are implicitly sized unless a `?Sized` bound is found
+                <dyn AstConv<'_>>::add_implicitly_sized(
                     &icx,
-                    param_ty,
+                    &mut bounds,
                     &param.bounds,
-                    sized,
+                    Some((param.hir_id, ast_generics.where_clause.predicates)),
                     param.span,
                 );
                 predicates.extend(bounds.predicates(tcx, param_ty));
@@ -2227,64 +2220,15 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::GenericP
                     }
                 }
 
-                for bound in bound_pred.bounds.iter() {
-                    match bound {
-                        hir::GenericBound::Trait(poly_trait_ref, modifier) => {
-                            let constness = match modifier {
-                                hir::TraitBoundModifier::None => ty::BoundConstness::NotConst,
-                                hir::TraitBoundModifier::MaybeConst => {
-                                    ty::BoundConstness::ConstIfConst
-                                }
-                                // We ignore `where T: ?Sized`, it is already part of
-                                // type parameter `T`.
-                                hir::TraitBoundModifier::Maybe => continue,
-                            };
-
-                            let mut bounds = Bounds::default();
-                            let _ = <dyn AstConv<'_>>::instantiate_poly_trait_ref(
-                                &icx,
-                                &poly_trait_ref.trait_ref,
-                                poly_trait_ref.span,
-                                constness,
-                                ty,
-                                &mut bounds,
-                                false,
-                            );
-                            predicates.extend(bounds.predicates(tcx, ty));
-                        }
-
-                        &hir::GenericBound::LangItemTrait(lang_item, span, hir_id, args) => {
-                            let mut bounds = Bounds::default();
-                            <dyn AstConv<'_>>::instantiate_lang_item_trait_ref(
-                                &icx,
-                                lang_item,
-                                span,
-                                hir_id,
-                                args,
-                                ty,
-                                &mut bounds,
-                            );
-                            predicates.extend(bounds.predicates(tcx, ty));
-                        }
-
-                        hir::GenericBound::Unsized(_) => {}
-
-                        hir::GenericBound::Outlives(lifetime) => {
-                            let region =
-                                <dyn AstConv<'_>>::ast_region_to_region(&icx, lifetime, None);
-                            predicates.insert((
-                                ty::Binder::bind_with_vars(
-                                    ty::PredicateKind::TypeOutlives(ty::OutlivesPredicate(
-                                        ty, region,
-                                    )),
-                                    bound_vars,
-                                )
-                                .to_predicate(tcx),
-                                lifetime.span,
-                            ));
-                        }
-                    }
-                }
+                let mut bounds = Bounds::default();
+                <dyn AstConv<'_>>::add_bounds(
+                    &icx,
+                    ty,
+                    bound_pred.bounds.iter(),
+                    &mut bounds,
+                    bound_vars,
+                );
+                predicates.extend(bounds.predicates(tcx, ty));
             }
 
             hir::WherePredicate::RegionPredicate(region_pred) => {
@@ -2498,45 +2442,14 @@ fn predicates_from_bound<'tcx>(
     param_ty: Ty<'tcx>,
     bound: &'tcx hir::GenericBound<'tcx>,
 ) -> Vec<(ty::Predicate<'tcx>, Span)> {
-    match *bound {
-        hir::GenericBound::Trait(ref tr, modifier) => {
-            let constness = match modifier {
-                hir::TraitBoundModifier::Maybe => return vec![],
-                hir::TraitBoundModifier::MaybeConst => ty::BoundConstness::ConstIfConst,
-                hir::TraitBoundModifier::None => ty::BoundConstness::NotConst,
-            };
-
-            let mut bounds = Bounds::default();
-            let _ = astconv.instantiate_poly_trait_ref(
-                &tr.trait_ref,
-                tr.span,
-                constness,
-                param_ty,
-                &mut bounds,
-                false,
-            );
-            bounds.predicates(astconv.tcx(), param_ty)
-        }
-        hir::GenericBound::LangItemTrait(lang_item, span, hir_id, args) => {
-            let mut bounds = Bounds::default();
-            astconv.instantiate_lang_item_trait_ref(
-                lang_item,
-                span,
-                hir_id,
-                args,
-                param_ty,
-                &mut bounds,
-            );
-            bounds.predicates(astconv.tcx(), param_ty)
-        }
-        hir::GenericBound::Unsized(_) => vec![],
-        hir::GenericBound::Outlives(ref lifetime) => {
-            let region = astconv.ast_region_to_region(lifetime, None);
-            let pred = ty::PredicateKind::TypeOutlives(ty::OutlivesPredicate(param_ty, region))
-                .to_predicate(astconv.tcx());
-            vec![(pred, lifetime.span)]
-        }
-    }
+    let mut bounds = Bounds::default();
+    astconv.add_bounds(
+        param_ty,
+        std::array::IntoIter::new([bound]),
+        &mut bounds,
+        ty::List::empty(),
+    );
+    bounds.predicates(astconv.tcx(), param_ty)
 }
 
 fn compute_sig_of_foreign_fn_decl<'tcx>(
diff --git a/compiler/rustc_typeck/src/collect/item_bounds.rs b/compiler/rustc_typeck/src/collect/item_bounds.rs
index 1d08c4450af..2bc048ac8a0 100644
--- a/compiler/rustc_typeck/src/collect/item_bounds.rs
+++ b/compiler/rustc_typeck/src/collect/item_bounds.rs
@@ -1,5 +1,5 @@
 use super::ItemCtxt;
-use crate::astconv::{AstConv, SizedByDefault};
+use crate::astconv::AstConv;
 use rustc_hir as hir;
 use rustc_infer::traits::util;
 use rustc_middle::ty::subst::InternalSubsts;
@@ -17,7 +17,7 @@ use rustc_span::Span;
 fn associated_type_bounds<'tcx>(
     tcx: TyCtxt<'tcx>,
     assoc_item_def_id: DefId,
-    bounds: &'tcx [hir::GenericBound<'tcx>],
+    ast_bounds: &'tcx [hir::GenericBound<'tcx>],
     span: Span,
 ) -> &'tcx [(ty::Predicate<'tcx>, Span)] {
     let item_ty = tcx.mk_projection(
@@ -25,13 +25,10 @@ fn associated_type_bounds<'tcx>(
         InternalSubsts::identity_for_item(tcx, assoc_item_def_id),
     );
 
-    let bounds = <dyn AstConv<'_>>::compute_bounds(
-        &ItemCtxt::new(tcx, assoc_item_def_id),
-        item_ty,
-        &bounds,
-        SizedByDefault::Yes,
-        span,
-    );
+    let icx = ItemCtxt::new(tcx, assoc_item_def_id);
+    let mut bounds = <dyn AstConv<'_>>::compute_bounds(&icx, item_ty, &ast_bounds);
+    // Associated types are implicitly sized unless a `?Sized` bound is found
+    <dyn AstConv<'_>>::add_implicitly_sized(&icx, &mut bounds, &ast_bounds, None, span);
 
     let trait_def_id = tcx.associated_item(assoc_item_def_id).container.id();
     let trait_predicates = tcx.trait_explicit_predicates_and_bounds(trait_def_id.expect_local());
@@ -59,21 +56,18 @@ fn associated_type_bounds<'tcx>(
 fn opaque_type_bounds<'tcx>(
     tcx: TyCtxt<'tcx>,
     opaque_def_id: DefId,
-    bounds: &'tcx [hir::GenericBound<'tcx>],
+    ast_bounds: &'tcx [hir::GenericBound<'tcx>],
     span: Span,
 ) -> &'tcx [(ty::Predicate<'tcx>, Span)] {
     ty::print::with_no_queries(|| {
         let item_ty =
             tcx.mk_opaque(opaque_def_id, InternalSubsts::identity_for_item(tcx, opaque_def_id));
 
-        let bounds = <dyn AstConv<'_>>::compute_bounds(
-            &ItemCtxt::new(tcx, opaque_def_id),
-            item_ty,
-            &bounds,
-            SizedByDefault::Yes,
-            span,
-        )
-        .predicates(tcx, item_ty);
+        let icx = ItemCtxt::new(tcx, opaque_def_id);
+        let mut bounds = <dyn AstConv<'_>>::compute_bounds(&icx, item_ty, &ast_bounds);
+        // Opaque types are implicitly sized unless a `?Sized` bound is found
+        <dyn AstConv<'_>>::add_implicitly_sized(&icx, &mut bounds, &ast_bounds, None, span);
+        let bounds = bounds.predicates(tcx, item_ty);
 
         debug!("opaque_type_bounds({}) = {:?}", tcx.def_path_str(opaque_def_id), bounds);
 
diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs
index 71348b3eb65..a95300217ab 100644
--- a/src/librustdoc/clean/mod.rs
+++ b/src/librustdoc/clean/mod.rs
@@ -129,7 +129,6 @@ impl Clean<GenericBound> for hir::GenericBound<'_> {
     fn clean(&self, cx: &mut DocContext<'_>) -> GenericBound {
         match *self {
             hir::GenericBound::Outlives(lt) => GenericBound::Outlives(lt.clean(cx)),
-            hir::GenericBound::Unsized(_) => GenericBound::maybe_sized(cx),
             hir::GenericBound::LangItemTrait(lang_item, span, _, generic_args) => {
                 let def_id = cx.tcx.require_lang_item(lang_item, Some(span));
 
@@ -557,19 +556,13 @@ impl Clean<Generics> for hir::Generics<'_> {
                 WherePredicate::BoundPredicate {
                     ty: Generic(ref name), ref mut bounds, ..
                 } => {
-                    if let [] | [GenericBound::TraitBound(_, hir::TraitBoundModifier::Maybe)] =
-                        &bounds[..]
-                    {
+                    if bounds.is_empty() {
                         for param in &mut generics.params {
                             match param.kind {
                                 GenericParamDefKind::Lifetime { .. } => {}
                                 GenericParamDefKind::Type { bounds: ref mut ty_bounds, .. } => {
                                     if &param.name == name {
                                         mem::swap(bounds, ty_bounds);
-                                        // We now keep track of `?Sized` obligations in the HIR.
-                                        // If we don't clear `ty_bounds` we end up with
-                                        // `fn foo<X: ?Sized>(_: X) where X: ?Sized`.
-                                        ty_bounds.clear();
                                         break;
                                     }
                                 }
diff --git a/src/test/ui/error-codes/e0119/complex-impl.stderr b/src/test/ui/error-codes/e0119/complex-impl.stderr
index 04babb06447..6a1a502749a 100644
--- a/src/test/ui/error-codes/e0119/complex-impl.stderr
+++ b/src/test/ui/error-codes/e0119/complex-impl.stderr
@@ -6,7 +6,7 @@ LL | impl<R> External for (Q, R) {}
    |
    = note: conflicting implementation in crate `complex_impl_support`:
            - impl<'a, 'b, 'c, T, U, V, W> External for (T, M<'a, 'b, 'c, Box<U>, V, W>)
-             where <U as FnOnce<(T,)>>::Output == V, <V as Iterator>::Item == T, 'b: 'a, T: 'a, U: FnOnce<(T,)>, U: 'static, V: Iterator, V: Clone, W: Add, <W as Add>::Output: Copy;
+             where <U as FnOnce<(T,)>>::Output == V, <V as Iterator>::Item == T, 'b: 'a, T: 'a, U: 'static, U: FnOnce<(T,)>, V: Iterator, V: Clone, W: Add, <W as Add>::Output: Copy;
 
 error[E0117]: only traits defined in the current crate can be implemented for arbitrary types
   --> $DIR/complex-impl.rs:9:1
diff --git a/src/test/ui/generics/wrong-number-of-args.stderr b/src/test/ui/generics/wrong-number-of-args.stderr
index 98e5cd6bab8..22da0dffbf2 100644
--- a/src/test/ui/generics/wrong-number-of-args.stderr
+++ b/src/test/ui/generics/wrong-number-of-args.stderr
@@ -440,17 +440,6 @@ note: trait defined here, with 1 lifetime parameter: `'a`
 LL |         trait GenericLifetimeAT<'a> {
    |               ^^^^^^^^^^^^^^^^^ --
 
-error[E0106]: missing lifetime specifier
-  --> $DIR/wrong-number-of-args.rs:169:44
-   |
-LL |         type C = Box<dyn GenericLifetimeAT<(), AssocTy=()>>;
-   |                                            ^ expected named lifetime parameter
-   |
-help: consider introducing a named lifetime parameter
-   |
-LL |         type C<'a> = Box<dyn GenericLifetimeAT<'a, (), AssocTy=()>>;
-   |               ++++                             +++
-
 error[E0107]: this trait takes 0 generic arguments but 1 generic argument was supplied
   --> $DIR/wrong-number-of-args.rs:169:26
    |
@@ -465,6 +454,17 @@ note: trait defined here, with 0 generic parameters
 LL |         trait GenericLifetimeAT<'a> {
    |               ^^^^^^^^^^^^^^^^^
 
+error[E0106]: missing lifetime specifier
+  --> $DIR/wrong-number-of-args.rs:169:44
+   |
+LL |         type C = Box<dyn GenericLifetimeAT<(), AssocTy=()>>;
+   |                                            ^ expected named lifetime parameter
+   |
+help: consider introducing a named lifetime parameter
+   |
+LL |         type C<'a> = Box<dyn GenericLifetimeAT<'a, (), AssocTy=()>>;
+   |               ++++                             +++
+
 error[E0107]: this trait takes 1 generic argument but 0 generic arguments were supplied
   --> $DIR/wrong-number-of-args.rs:181:26
    |
@@ -525,17 +525,6 @@ help: add missing generic argument
 LL |         type C = Box<dyn GenericTypeAT<'static, A, AssocTy=()>>;
    |                                               +++
 
-error[E0106]: missing lifetime specifier
-  --> $DIR/wrong-number-of-args.rs:201:48
-   |
-LL |         type A = Box<dyn GenericLifetimeTypeAT<AssocTy=()>>;
-   |                                                ^ expected named lifetime parameter
-   |
-help: consider introducing a named lifetime parameter
-   |
-LL |         type A<'a> = Box<dyn GenericLifetimeTypeAT<'a, AssocTy=()>>;
-   |               ++++                                 +++
-
 error[E0107]: this trait takes 1 generic argument but 0 generic arguments were supplied
   --> $DIR/wrong-number-of-args.rs:201:26
    |
@@ -552,6 +541,17 @@ help: add missing generic argument
 LL |         type A = Box<dyn GenericLifetimeTypeAT<A, AssocTy=()>>;
    |                                                ++
 
+error[E0106]: missing lifetime specifier
+  --> $DIR/wrong-number-of-args.rs:201:48
+   |
+LL |         type A = Box<dyn GenericLifetimeTypeAT<AssocTy=()>>;
+   |                                                ^ expected named lifetime parameter
+   |
+help: consider introducing a named lifetime parameter
+   |
+LL |         type A<'a> = Box<dyn GenericLifetimeTypeAT<'a, AssocTy=()>>;
+   |               ++++                                 +++
+
 error[E0107]: this trait takes 1 generic argument but 0 generic arguments were supplied
   --> $DIR/wrong-number-of-args.rs:207:26
    |
@@ -609,17 +609,6 @@ help: consider introducing a named lifetime parameter
 LL |         type D<'a> = Box<dyn GenericLifetimeTypeAT<'a, (), AssocTy=()>>;
    |               ++++                                 +++
 
-error[E0106]: missing lifetime specifier
-  --> $DIR/wrong-number-of-args.rs:221:48
-   |
-LL |         type E = Box<dyn GenericLifetimeTypeAT<(), (), AssocTy=()>>;
-   |                                                ^ expected named lifetime parameter
-   |
-help: consider introducing a named lifetime parameter
-   |
-LL |         type E<'a> = Box<dyn GenericLifetimeTypeAT<'a, (), (), AssocTy=()>>;
-   |               ++++                                 +++
-
 error[E0107]: this trait takes 1 generic argument but 2 generic arguments were supplied
   --> $DIR/wrong-number-of-args.rs:221:26
    |
@@ -634,6 +623,17 @@ note: trait defined here, with 1 generic parameter: `A`
 LL |         trait GenericLifetimeTypeAT<'a, A> {
    |               ^^^^^^^^^^^^^^^^^^^^^     -
 
+error[E0106]: missing lifetime specifier
+  --> $DIR/wrong-number-of-args.rs:221:48
+   |
+LL |         type E = Box<dyn GenericLifetimeTypeAT<(), (), AssocTy=()>>;
+   |                                                ^ expected named lifetime parameter
+   |
+help: consider introducing a named lifetime parameter
+   |
+LL |         type E<'a> = Box<dyn GenericLifetimeTypeAT<'a, (), (), AssocTy=()>>;
+   |               ++++                                 +++
+
 error[E0107]: this trait takes 1 lifetime argument but 2 lifetime arguments were supplied
   --> $DIR/wrong-number-of-args.rs:227:26
    |
@@ -767,17 +767,6 @@ help: add missing lifetime argument
 LL |         type B = Box<dyn GenericLifetimeLifetimeAT<'static, 'b, AssocTy=()>>;
    |                                                           ++++
 
-error[E0106]: missing lifetime specifiers
-  --> $DIR/wrong-number-of-args.rs:279:56
-   |
-LL |         type A = Box<dyn GenericLifetimeLifetimeTypeAT<AssocTy=()>>;
-   |                                                        ^ expected 2 lifetime parameters
-   |
-help: consider introducing a named lifetime parameter
-   |
-LL |         type A<'a> = Box<dyn GenericLifetimeLifetimeTypeAT<'a, 'a, AssocTy=()>>;
-   |               ++++                                         +++++++
-
 error[E0107]: this trait takes 1 generic argument but 0 generic arguments were supplied
   --> $DIR/wrong-number-of-args.rs:279:26
    |
@@ -794,6 +783,17 @@ help: add missing generic argument
 LL |         type A = Box<dyn GenericLifetimeLifetimeTypeAT<A, AssocTy=()>>;
    |                                                        ++
 
+error[E0106]: missing lifetime specifiers
+  --> $DIR/wrong-number-of-args.rs:279:56
+   |
+LL |         type A = Box<dyn GenericLifetimeLifetimeTypeAT<AssocTy=()>>;
+   |                                                        ^ expected 2 lifetime parameters
+   |
+help: consider introducing a named lifetime parameter
+   |
+LL |         type A<'a> = Box<dyn GenericLifetimeLifetimeTypeAT<'a, 'a, AssocTy=()>>;
+   |               ++++                                         +++++++
+
 error[E0107]: this trait takes 2 lifetime arguments but 1 lifetime argument was supplied
   --> $DIR/wrong-number-of-args.rs:285:26
    |
diff --git a/src/test/ui/maybe-bounds-where.rs b/src/test/ui/maybe-bounds-where.rs
index cf011653c20..d7af0c42480 100644
--- a/src/test/ui/maybe-bounds-where.rs
+++ b/src/test/ui/maybe-bounds-where.rs
@@ -11,6 +11,7 @@ trait Trait<'a> {}
 
 struct S4<T>(T) where for<'a> T: ?Trait<'a>;
 //~^ ERROR `?Trait` bounds are only permitted at the point where a type parameter is declared
+//~| WARN default bound relaxed for a type parameter
 
 struct S5<T>(*const T) where T: ?Trait<'static> + ?Sized;
 //~^ ERROR type parameter has more than one relaxed default bound
diff --git a/src/test/ui/maybe-bounds-where.stderr b/src/test/ui/maybe-bounds-where.stderr
index 0ef8e9e9c79..2aa6a8a3822 100644
--- a/src/test/ui/maybe-bounds-where.stderr
+++ b/src/test/ui/maybe-bounds-where.stderr
@@ -23,23 +23,29 @@ LL | struct S4<T>(T) where for<'a> T: ?Trait<'a>;
    |                               ^
 
 error: `?Trait` bounds are only permitted at the point where a type parameter is declared
-  --> $DIR/maybe-bounds-where.rs:20:18
+  --> $DIR/maybe-bounds-where.rs:21:18
    |
 LL |     fn f() where T: ?Sized {}
    |                  ^
 
+warning: default bound relaxed for a type parameter, but this does nothing because the given bound is not a default; only `?Sized` is supported
+  --> $DIR/maybe-bounds-where.rs:12:11
+   |
+LL | struct S4<T>(T) where for<'a> T: ?Trait<'a>;
+   |           ^
+
 error[E0203]: type parameter has more than one relaxed default bound, only one is supported
-  --> $DIR/maybe-bounds-where.rs:15:11
+  --> $DIR/maybe-bounds-where.rs:16:11
    |
 LL | struct S5<T>(*const T) where T: ?Trait<'static> + ?Sized;
    |           ^
 
 warning: default bound relaxed for a type parameter, but this does nothing because the given bound is not a default; only `?Sized` is supported
-  --> $DIR/maybe-bounds-where.rs:15:11
+  --> $DIR/maybe-bounds-where.rs:16:11
    |
 LL | struct S5<T>(*const T) where T: ?Trait<'static> + ?Sized;
    |           ^
 
-error: aborting due to 6 previous errors; 1 warning emitted
+error: aborting due to 6 previous errors; 2 warnings emitted
 
 For more information about this error, try `rustc --explain E0203`.