@@ -87,19 +87,14 @@ impl<'a, 'gcx> CheckCrateVisitor<'a, 'gcx> {
87
87
}
88
88
}
89
89
90
- // Adds the worst effect out of all the values of one type.
91
- fn add_type ( & mut self , ty : Ty < ' gcx > ) {
92
- if !ty. is_freeze ( self . tcx , self . param_env , DUMMY_SP ) {
93
- self . promotable = false ;
94
- }
95
-
96
- if ty. needs_drop ( self . tcx , self . param_env ) {
97
- self . promotable = false ;
98
- }
90
+ // Returns true iff all the values of the type are promotable.
91
+ fn type_has_only_promotable_values ( & mut self , ty : Ty < ' gcx > ) -> bool {
92
+ ty. is_freeze ( self . tcx , self . param_env , DUMMY_SP ) &&
93
+ !ty. needs_drop ( self . tcx , self . param_env )
99
94
}
100
95
101
96
fn handle_const_fn_call ( & mut self , def_id : DefId , ret_ty : Ty < ' gcx > ) {
102
- self . add_type ( ret_ty) ;
97
+ self . promotable &= self . type_has_only_promotable_values ( ret_ty) ;
103
98
104
99
self . promotable &= if let Some ( fn_id) = self . tcx . hir . as_local_node_id ( def_id) {
105
100
FnLikeNode :: from_node ( self . tcx . hir . get ( fn_id) ) . map_or ( false , |fn_like| {
@@ -333,20 +328,30 @@ fn check_expr<'a, 'tcx>(v: &mut CheckCrateVisitor<'a, 'tcx>, e: &hir::Expr, node
333
328
match def {
334
329
Def :: VariantCtor ( ..) | Def :: StructCtor ( ..) |
335
330
Def :: Fn ( ..) | Def :: Method ( ..) => { }
336
- Def :: AssociatedConst ( _) => v. add_type ( node_ty) ,
337
- Def :: Const ( did) => {
338
- v. promotable &= if let Some ( node_id) = v. tcx . hir . as_local_node_id ( did) {
339
- match v. tcx . hir . expect_item ( node_id) . node {
340
- hir:: ItemConst ( _, body) => {
331
+
332
+ Def :: Const ( did) |
333
+ Def :: AssociatedConst ( did) => {
334
+ let promotable = if v. tcx . trait_of_item ( did) . is_some ( ) {
335
+ // Don't peek inside trait associated constants.
336
+ false
337
+ } else if let Some ( node_id) = v. tcx . hir . as_local_node_id ( did) {
338
+ match v. tcx . hir . maybe_body_owned_by ( node_id) {
339
+ Some ( body) => {
341
340
v. visit_nested_body ( body) ;
342
341
v. tcx . rvalue_promotable_to_static . borrow ( ) [ & body. node_id ]
343
342
}
344
- _ => false
343
+ None => false
345
344
}
346
345
} else {
347
346
v. tcx . const_is_rvalue_promotable_to_static ( did)
348
347
} ;
348
+
349
+ // Just in case the type is more specific than the definition,
350
+ // e.g. impl associated const with type parameters, check it.
351
+ // Also, trait associated consts are relaxed by this.
352
+ v. promotable &= promotable || v. type_has_only_promotable_values ( node_ty) ;
349
353
}
354
+
350
355
_ => {
351
356
v. promotable = false ;
352
357
}
0 commit comments