@@ -16,19 +16,60 @@ use crate::bounds::Bounds;
1616use crate :: errors;
1717
1818impl < ' 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 (
2121 & self ,
2222 bounds : & mut Bounds < ' tcx > ,
2323 self_ty : Ty < ' tcx > ,
2424 ast_bounds : & ' tcx [ hir:: GenericBound < ' tcx > ] ,
2525 self_ty_where_predicates : Option < ( LocalDefId , & ' tcx [ hir:: WherePredicate < ' tcx > ] ) > ,
2626 span : Span ,
2727 ) {
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 ,
48+ ) {
49+ let tcx = self . tcx ( ) ;
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+ } ;
2870 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 ;
71+ let mut seen_negative_bound = false ;
72+ let mut seen_positive_bound = false ;
3273
3374 // Try to find an unbound in bounds.
3475 let mut unbounds: SmallVec < [ _ ; 1 ] > = SmallVec :: new ( ) ;
@@ -40,17 +81,14 @@ impl<'tcx> dyn AstConv<'tcx> + '_ {
4081 match modifier {
4182 hir:: TraitBoundModifier :: Maybe => unbounds. push ( ptr) ,
4283 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 ;
4786 }
4887 }
4988 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)
89+ if ptr. trait_ref . path . res == Res :: Def ( DefKind :: Trait , trait_def_id)
5290 {
53- seen_positive_sized_bound = true ;
91+ seen_positive_bound = true ;
5492 }
5593 }
5694 _ => { }
@@ -68,36 +106,29 @@ impl<'tcx> dyn AstConv<'tcx> + '_ {
68106 }
69107 }
70108
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 ;
109+ let mut seen_unbound = false ;
78110 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 ;
111+ let unbound_def_id = unbound. trait_ref . trait_def_id ( ) ;
112+ if unbound_def_id == Some ( trait_def_id) {
113+ seen_unbound = true ;
84114 }
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- }
92115
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) ;
116+ let emit_relax_err = || {
117+ tcx. dcx ( ) . span_warn (
118+ unbound. span ,
119+ "relaxing a default bound only does something for `?Sized` and `default_auto_traits`; \
120+ all other traits are not bound by default",
121+ ) ;
122+ } ;
123+
124+ match unbound_def_id {
125+ Some ( def_id) if !tcx. lang_items ( ) . is_default_trait ( def_id) => emit_relax_err ( ) ,
126+ None => emit_relax_err ( ) ,
127+ _ => { }
128+ }
100129 }
130+
131+ !( seen_unbound || seen_negative_bound || seen_positive_bound)
101132 }
102133
103134 /// This helper takes a *converted* parameter type (`param_ty`)
0 commit comments