@@ -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 ,
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 ,
2748 ) {
2849 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 ;
3273
3374 // Try to find an unbound in bounds.
3475 let mut unbounds: SmallVec < [ _ ; 1 ] > = SmallVec :: new ( ) ;
@@ -40,17 +81,13 @@ 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)
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 ;
5491 }
5592 }
5693 _ => { }
@@ -68,36 +105,29 @@ impl<'tcx> dyn AstConv<'tcx> + '_ {
68105 }
69106 }
70107
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 ;
78109 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 ;
84113 }
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- }
92114
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+ }
100128 }
129+
130+ !( seen_unbound || seen_negative_bound || seen_positive_bound)
101131 }
102132
103133 /// This helper takes a *converted* parameter type (`param_ty`)
0 commit comments