@@ -87,19 +87,14 @@ impl<'a, 'gcx> CheckCrateVisitor<'a, 'gcx> {
8787 }
8888 }
8989
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 )
9994 }
10095
10196 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) ;
10398
10499 self . promotable &= if let Some ( fn_id) = self . tcx . hir . as_local_node_id ( def_id) {
105100 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
333328 match def {
334329 Def :: VariantCtor ( ..) | Def :: StructCtor ( ..) |
335330 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) => {
341340 v. visit_nested_body ( body) ;
342341 v. tcx . rvalue_promotable_to_static . borrow ( ) [ & body. node_id ]
343342 }
344- _ => false
343+ None => false
345344 }
346345 } else {
347346 v. tcx . const_is_rvalue_promotable_to_static ( did)
348347 } ;
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) ;
349353 }
354+
350355 _ => {
351356 v. promotable = false ;
352357 }
0 commit comments