@@ -16,19 +16,60 @@ use crate::bounds::Bounds;
16
16
use crate :: errors;
17
17
18
18
impl < ' tcx > dyn AstConv < ' tcx > + ' _ {
19
- /// Sets `implicitly_sized` to true on `Bounds` if necessary
20
- pub ( crate ) fn add_implicitly_sized (
19
+ /// Sets Sized or default_auto_traits to true on `Bounds` if necessary
20
+ pub ( crate ) fn add_implicit_traits (
21
21
& self ,
22
22
bounds : & mut Bounds < ' tcx > ,
23
23
self_ty : Ty < ' tcx > ,
24
24
ast_bounds : & ' tcx [ hir:: GenericBound < ' tcx > ] ,
25
25
self_ty_where_predicates : Option < ( LocalDefId , & ' tcx [ hir:: WherePredicate < ' tcx > ] ) > ,
26
26
span : Span ,
27
+ ) {
28
+ hir:: lang_items:: DEFAULT_TRAITS . iter ( ) . for_each ( |default_trait| {
29
+ self . add_implicit_trait (
30
+ * default_trait,
31
+ bounds,
32
+ self_ty,
33
+ ast_bounds,
34
+ self_ty_where_predicates,
35
+ span,
36
+ ) ;
37
+ } ) ;
38
+ }
39
+
40
+ pub ( crate ) fn add_implicit_trait (
41
+ & self ,
42
+ trait_ : hir:: LangItem ,
43
+ bounds : & mut Bounds < ' tcx > ,
44
+ self_ty : Ty < ' tcx > ,
45
+ ast_bounds : & ' tcx [ hir:: GenericBound < ' tcx > ] ,
46
+ self_ty_where_predicates : Option < ( LocalDefId , & ' tcx [ hir:: WherePredicate < ' tcx > ] ) > ,
47
+ span : Span ,
27
48
) {
28
49
let tcx = self . tcx ( ) ;
29
- let sized_def_id = tcx. lang_items ( ) . sized_trait ( ) ;
30
- let mut seen_negative_sized_bound = false ;
31
- let mut seen_positive_sized_bound = false ;
50
+ let trait_id = tcx. lang_items ( ) . get ( trait_) ;
51
+
52
+ if self . check_for_implicit_trait ( trait_id, ast_bounds, self_ty_where_predicates)
53
+ && ( trait_ == hir:: LangItem :: Sized || tcx. features ( ) . default_auto_traits )
54
+ {
55
+ // There was no `?Trait` or `!Trait` bound;
56
+ // add `Trait` if it's available.
57
+ bounds. push_lang_item_trait ( tcx, self_ty, trait_, span) ;
58
+ }
59
+ }
60
+
61
+ fn check_for_implicit_trait (
62
+ & self ,
63
+ trait_def_id : Option < DefId > ,
64
+ ast_bounds : & ' tcx [ hir:: GenericBound < ' tcx > ] ,
65
+ self_ty_where_predicates : Option < ( LocalDefId , & ' tcx [ hir:: WherePredicate < ' tcx > ] ) > ,
66
+ ) -> bool {
67
+ let Some ( trait_def_id) = trait_def_id else {
68
+ return false ;
69
+ } ;
70
+ let tcx = self . tcx ( ) ;
71
+ let mut seen_negative_bound = false ;
72
+ let mut seen_positive_bound = false ;
32
73
33
74
// Try to find an unbound in bounds.
34
75
let mut unbounds: SmallVec < [ _ ; 1 ] > = SmallVec :: new ( ) ;
@@ -40,17 +81,13 @@ impl<'tcx> dyn AstConv<'tcx> + '_ {
40
81
match modifier {
41
82
hir:: TraitBoundModifier :: Maybe => unbounds. push ( ptr) ,
42
83
hir:: TraitBoundModifier :: Negative => {
43
- if let Some ( sized_def_id) = sized_def_id
44
- && ptr. trait_ref . path . res == Res :: Def ( DefKind :: Trait , sized_def_id)
45
- {
46
- seen_negative_sized_bound = true ;
84
+ if ptr. trait_ref . path . res == Res :: Def ( DefKind :: Trait , trait_def_id) {
85
+ seen_negative_bound = true ;
47
86
}
48
87
}
49
88
hir:: TraitBoundModifier :: None => {
50
- if let Some ( sized_def_id) = sized_def_id
51
- && ptr. trait_ref . path . res == Res :: Def ( DefKind :: Trait , sized_def_id)
52
- {
53
- seen_positive_sized_bound = true ;
89
+ if ptr. trait_ref . path . res == Res :: Def ( DefKind :: Trait , trait_def_id) {
90
+ seen_positive_bound = true ;
54
91
}
55
92
}
56
93
_ => { }
@@ -68,36 +105,29 @@ impl<'tcx> dyn AstConv<'tcx> + '_ {
68
105
}
69
106
}
70
107
71
- if unbounds. len ( ) > 1 {
72
- tcx. dcx ( ) . emit_err ( errors:: MultipleRelaxedDefaultBounds {
73
- spans : unbounds. iter ( ) . map ( |ptr| ptr. span ) . collect ( ) ,
74
- } ) ;
75
- }
76
-
77
- let mut seen_sized_unbound = false ;
108
+ let mut seen_unbound = false ;
78
109
for unbound in unbounds {
79
- if let Some ( sized_def_id) = sized_def_id
80
- && unbound. trait_ref . path . res == Res :: Def ( DefKind :: Trait , sized_def_id)
81
- {
82
- seen_sized_unbound = true ;
83
- continue ;
110
+ let unbound_def_id = unbound. trait_ref . trait_def_id ( ) ;
111
+ if unbound_def_id == Some ( trait_def_id) {
112
+ seen_unbound = true ;
84
113
}
85
- // There was a `?Trait` bound, but it was not `?Sized`; warn.
86
- tcx. dcx ( ) . span_warn (
87
- unbound. span ,
88
- "relaxing a default bound only does something for `?Sized`; \
89
- all other traits are not bound by default",
90
- ) ;
91
- }
92
114
93
- if seen_sized_unbound || seen_negative_sized_bound || seen_positive_sized_bound {
94
- // There was in fact a `?Sized`, `!Sized` or explicit `Sized` bound;
95
- // we don't need to do anything.
96
- } else if sized_def_id. is_some ( ) {
97
- // There was no `?Sized`, `!Sized` or explicit `Sized` bound;
98
- // add `Sized` if it's available.
99
- bounds. push_sized ( tcx, self_ty, span) ;
115
+ let emit_relax_err = || {
116
+ tcx. dcx ( ) . span_warn (
117
+ unbound. span ,
118
+ "relaxing a default bound only does something for `?Sized` and `default_auto_traits`; \
119
+ all other traits are not bound by default",
120
+ ) ;
121
+ } ;
122
+
123
+ match unbound_def_id {
124
+ Some ( def_id) if !tcx. lang_items ( ) . is_default_trait ( def_id) => emit_relax_err ( ) ,
125
+ None => emit_relax_err ( ) ,
126
+ _ => { }
127
+ }
100
128
}
129
+
130
+ !( seen_unbound || seen_negative_bound || seen_positive_bound)
101
131
}
102
132
103
133
/// This helper takes a *converted* parameter type (`param_ty`)
0 commit comments