]> git.proxmox.com Git - rustc.git/blobdiff - compiler/rustc_mir/src/transform/check_consts/validation.rs
New upstream version 1.55.0+dfsg1
[rustc.git] / compiler / rustc_mir / src / transform / check_consts / validation.rs
index 4fbd27c89d9c8f6b7f0338f3d2020ad1c3db6f28..cfc538ef500a12d2e43d4846dc8d46ca23c037b7 100644 (file)
@@ -822,12 +822,7 @@ impl Visitor<'tcx> for Validator<'mir, 'tcx> {
                     let obligation = Obligation::new(
                         ObligationCause::dummy(),
                         param_env,
-                        Binder::bind(
-                            TraitPredicate {
-                                trait_ref: TraitRef::from_method(tcx, trait_id, substs),
-                            },
-                            tcx,
-                        ),
+                        Binder::dummy(TraitPredicate { trait_ref }),
                     );
 
                     let implsrc = tcx.infer_ctxt().enter(|infcx| {
@@ -891,8 +886,37 @@ impl Visitor<'tcx> for Validator<'mir, 'tcx> {
                 }
 
                 if !tcx.is_const_fn_raw(callee) {
-                    self.check_op(ops::FnCallNonConst);
-                    return;
+                    let mut permitted = false;
+
+                    let callee_trait = tcx.trait_of_item(callee);
+                    if let Some(trait_id) = callee_trait {
+                        if tcx.has_attr(caller, sym::default_method_body_is_const) {
+                            // permit call to non-const fn when caller has default_method_body_is_const..
+                            if tcx.trait_of_item(caller) == callee_trait {
+                                // ..and caller and callee are in the same trait.
+                                permitted = true;
+                            }
+                        }
+                        if !permitted {
+                            // if trait's impls are all const, permit the call.
+                            let mut const_impls = true;
+                            tcx.for_each_relevant_impl(trait_id, substs.type_at(0), |imp| {
+                                if const_impls {
+                                    if let hir::Constness::NotConst = tcx.impl_constness(imp) {
+                                        const_impls = false;
+                                    }
+                                }
+                            });
+                            if const_impls {
+                                permitted = true;
+                            }
+                        }
+                    }
+
+                    if !permitted {
+                        self.check_op(ops::FnCallNonConst);
+                        return;
+                    }
                 }
 
                 // If the `const fn` we are trying to call is not const-stable, ensure that we have