@@ -8,6 +8,7 @@ use rustc_middle::ty::{self as ty, Ty, TypeVisitableExt};
8
8
use rustc_span:: symbol:: Ident ;
9
9
use rustc_span:: { ErrorGuaranteed , Span } ;
10
10
use rustc_trait_selection:: traits;
11
+ use smallvec:: SmallVec ;
11
12
12
13
use crate :: astconv:: {
13
14
AstConv , ConvertedBinding , ConvertedBindingKind , OnlySelfBounds , PredicateFilter ,
@@ -28,15 +29,11 @@ impl<'tcx> dyn AstConv<'tcx> + '_ {
28
29
let tcx = self . tcx ( ) ;
29
30
30
31
// Try to find an unbound in bounds.
31
- let mut unbound = None ;
32
+ let mut unbounds : SmallVec < [ _ ; 1 ] > = SmallVec :: new ( ) ;
32
33
let mut search_bounds = |ast_bounds : & ' tcx [ hir:: GenericBound < ' tcx > ] | {
33
34
for ab in ast_bounds {
34
35
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)
40
37
}
41
38
}
42
39
} ;
@@ -51,33 +48,41 @@ impl<'tcx> dyn AstConv<'tcx> + '_ {
51
48
}
52
49
}
53
50
51
+ if unbounds. len ( ) > 1 {
52
+ tcx. sess . emit_err ( errors:: MultipleRelaxedDefaultBounds {
53
+ spans : unbounds. iter ( ) . map ( |ptr| ptr. span ) . collect ( ) ,
54
+ } ) ;
55
+ }
56
+
54
57
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
+ }
74
66
}
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
+ ) ;
75
73
}
74
+
75
+ // If the above loop finished there was no `?Sized` bound; add implicitly sized if `Sized` is available.
76
76
if sized_def_id. is_none ( ) {
77
77
// No lang item for `Sized`, so we can't add it as a bound.
78
78
return ;
79
79
}
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
+ }
81
86
}
82
87
83
88
/// This helper takes a *converted* parameter type (`param_ty`)
0 commit comments