@@ -13,6 +13,7 @@ use rustc_hir as hir;
13
13
use rustc_hir:: def_id:: LocalDefId ;
14
14
use rustc_hir:: intravisit:: { self , NestedVisitorMap , Visitor } ;
15
15
use rustc_middle:: hir:: map:: Map ;
16
+ use rustc_middle:: ty;
16
17
use rustc_middle:: ty:: query:: Providers ;
17
18
use rustc_middle:: ty:: TyCtxt ;
18
19
use rustc_session:: parse:: feature_err;
@@ -59,12 +60,73 @@ impl NonConstExpr {
59
60
fn check_mod_const_bodies ( tcx : TyCtxt < ' _ > , module_def_id : LocalDefId ) {
60
61
let mut vis = CheckConstVisitor :: new ( tcx) ;
61
62
tcx. hir ( ) . visit_item_likes_in_module ( module_def_id, & mut vis. as_deep_visitor ( ) ) ;
63
+ tcx. hir ( ) . visit_item_likes_in_module ( module_def_id, & mut CheckConstTraitVisitor :: new ( tcx) ) ;
62
64
}
63
65
64
66
pub ( crate ) fn provide ( providers : & mut Providers ) {
65
67
* providers = Providers { check_mod_const_bodies, ..* providers } ;
66
68
}
67
69
70
+ struct CheckConstTraitVisitor < ' tcx > {
71
+ tcx : TyCtxt < ' tcx > ,
72
+ }
73
+
74
+ impl < ' tcx > CheckConstTraitVisitor < ' tcx > {
75
+ fn new ( tcx : TyCtxt < ' tcx > ) -> Self {
76
+ CheckConstTraitVisitor { tcx }
77
+ }
78
+ }
79
+
80
+ impl < ' tcx > hir:: itemlikevisit:: ItemLikeVisitor < ' tcx > for CheckConstTraitVisitor < ' tcx > {
81
+ /// check for const trait impls, and errors if the impl uses provided/default functions
82
+ /// of the trait being implemented; as those provided functions can be non-const.
83
+ fn visit_item ( & mut self , item : & ' hir hir:: Item < ' hir > ) {
84
+ let _: Option < _ > = try {
85
+ if let hir:: ItemKind :: Impl ( ref imp) = item. kind {
86
+ if let hir:: Constness :: Const = imp. constness {
87
+ let did = imp. of_trait . as_ref ( ) ?. trait_def_id ( ) ?;
88
+ let trait_fn_cnt = self
89
+ . tcx
90
+ . associated_item_def_ids ( did)
91
+ . iter ( )
92
+ . filter ( |did| {
93
+ matches ! (
94
+ self . tcx. associated_item( * * did) ,
95
+ ty:: AssocItem { kind: ty:: AssocKind :: Fn , .. }
96
+ )
97
+ } )
98
+ . count ( ) ;
99
+
100
+ let impl_fn_cnt = imp
101
+ . items
102
+ . iter ( )
103
+ . filter ( |it| matches ! ( it. kind, hir:: AssocItemKind :: Fn { .. } ) )
104
+ . count ( ) ;
105
+
106
+ // number of trait functions unequal to functions in impl,
107
+ // meaning that one or more provided/default functions of the
108
+ // trait are used.
109
+ if trait_fn_cnt != impl_fn_cnt {
110
+ self . tcx
111
+ . sess
112
+ . struct_span_err (
113
+ item. span ,
114
+ "const trait implementations may not use default functions" ,
115
+ )
116
+ . emit ( ) ;
117
+ }
118
+ }
119
+ }
120
+ } ;
121
+ }
122
+
123
+ fn visit_trait_item ( & mut self , _: & ' hir hir:: TraitItem < ' hir > ) { }
124
+
125
+ fn visit_impl_item ( & mut self , _: & ' hir hir:: ImplItem < ' hir > ) { }
126
+
127
+ fn visit_foreign_item ( & mut self , _: & ' hir hir:: ForeignItem < ' hir > ) { }
128
+ }
129
+
68
130
#[ derive( Copy , Clone ) ]
69
131
struct CheckConstVisitor < ' tcx > {
70
132
tcx : TyCtxt < ' tcx > ,
0 commit comments