@@ -8,6 +8,7 @@ use rustc_middle::ty::{self as ty, Ty, TypeVisitableExt};
88use rustc_span:: symbol:: Ident ;
99use rustc_span:: { ErrorGuaranteed , Span } ;
1010use rustc_trait_selection:: traits;
11+ use smallvec:: SmallVec ;
1112
1213use crate :: astconv:: {
1314 AstConv , ConvertedBinding , ConvertedBindingKind , OnlySelfBounds , PredicateFilter ,
@@ -28,15 +29,11 @@ impl<'tcx> dyn AstConv<'tcx> + '_ {
2829 let tcx = self . tcx ( ) ;
2930
3031 // Try to find an unbound in bounds.
31- let mut unbound = None ;
32+ let mut unbounds : SmallVec < [ _ ; 1 ] > = SmallVec :: new ( ) ;
3233 let mut search_bounds = |ast_bounds : & ' tcx [ hir:: GenericBound < ' tcx > ] | {
3334 for ab in ast_bounds {
3435 if let hir:: GenericBound :: Trait ( ptr, hir:: TraitBoundModifier :: Maybe ) = ab {
35- if unbound. is_none ( ) {
36- unbound = Some ( & ptr. trait_ref ) ;
37- } else {
38- tcx. sess . emit_err ( errors:: MultipleRelaxedDefaultBounds { span } ) ;
39- }
36+ unbounds. push ( ptr)
4037 }
4138 }
4239 } ;
@@ -51,33 +48,41 @@ impl<'tcx> dyn AstConv<'tcx> + '_ {
5148 }
5249 }
5350
51+ if unbounds. len ( ) > 1 {
52+ tcx. sess . emit_err ( errors:: MultipleRelaxedDefaultBounds {
53+ spans : unbounds. iter ( ) . map ( |ptr| ptr. span ) . collect ( ) ,
54+ } ) ;
55+ }
56+
5457 let sized_def_id = tcx. lang_items ( ) . sized_trait ( ) ;
55- match ( & sized_def_id, unbound) {
56- ( Some ( sized_def_id) , Some ( tpb) )
57- if tpb. path . res == Res :: Def ( DefKind :: Trait , * sized_def_id) =>
58- {
59- // There was in fact a `?Sized` bound, return without doing anything
60- return ;
61- }
62- ( _, Some ( _) ) => {
63- // There was a `?Trait` bound, but it was not `?Sized`; warn.
64- tcx. sess . span_warn (
65- span,
66- "default bound relaxed for a type parameter, but \
67- this does nothing because the given bound is not \
68- a default; only `?Sized` is supported",
69- ) ;
70- // Otherwise, add implicitly sized if `Sized` is available.
71- }
72- _ => {
73- // There was no `?Sized` bound; add implicitly sized if `Sized` is available.
58+
59+ let mut seen_sized_unbound = false ;
60+ for unbound in unbounds {
61+ if let Some ( sized_def_id) = sized_def_id {
62+ if unbound. trait_ref . path . res == Res :: Def ( DefKind :: Trait , sized_def_id) {
63+ seen_sized_unbound = true ;
64+ continue ;
65+ }
7466 }
67+ // There was a `?Trait` bound, but it was not `?Sized`; warn.
68+ tcx. sess . span_warn (
69+ unbound. span ,
70+ "relaxing a default bound only does something for `?Sized`; \
71+ all other traits are not bound by default",
72+ ) ;
7573 }
74+
75+ // If the above loop finished there was no `?Sized` bound; add implicitly sized if `Sized` is available.
7676 if sized_def_id. is_none ( ) {
7777 // No lang item for `Sized`, so we can't add it as a bound.
7878 return ;
7979 }
80- bounds. push_sized ( tcx, self_ty, span) ;
80+ if seen_sized_unbound {
81+ // There was in fact a `?Sized` bound, return without doing anything
82+ } else {
83+ // There was no `?Sized` bound; add implicitly sized if `Sized` is available.
84+ bounds. push_sized ( tcx, self_ty, span) ;
85+ }
8186 }
8287
8388 /// This helper takes a *converted* parameter type (`param_ty`)
0 commit comments