about summary refs log tree commit diff
path: root/compiler/rustc_const_eval
diff options
context:
space:
mode:
authorDeadbeef <ent3rm4n@gmail.com>2023-03-24 09:17:51 +0000
committerDeadbeef <ent3rm4n@gmail.com>2023-03-28 08:39:55 +0000
commitb17e6680d668d136e643976c4079c7b1cac1b6b4 (patch)
treec08029cdf9c2042474cac25244ffd654f143273b /compiler/rustc_const_eval
parentcbc064b341be231403d181402a786cce7f1c73f1 (diff)
Move const trait bounds checks to MIR constck
Fixes #109543. When checking paths in HIR typeck, we don't want to check
for const predicates since all we want might just be a function pointer.
Therefore we move this to MIR constck and check that bounds are met
during MIR constck.
Diffstat (limited to 'compiler/rustc_const_eval')
-rw-r--r--compiler/rustc_const_eval/src/transform/check_consts/check.rs51
1 files changed, 26 insertions, 25 deletions
diff --git a/compiler/rustc_const_eval/src/transform/check_consts/check.rs b/compiler/rustc_const_eval/src/transform/check_consts/check.rs
index 0d9cd78fe12..d6110a050f2 100644
--- a/compiler/rustc_const_eval/src/transform/check_consts/check.rs
+++ b/compiler/rustc_const_eval/src/transform/check_consts/check.rs
@@ -722,6 +722,32 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> {
                     }
                 };
 
+                // Check that all trait bounds that are marked as `~const` can be satisfied.
+                //
+                // Typeck only does a "non-const" check since it operates on HIR and cannot distinguish
+                // which path expressions are getting called on and which path expressions are only used
+                // as function pointers. This is required for correctness.
+                let infcx = tcx.infer_ctxt().build();
+                let ocx = ObligationCtxt::new(&infcx);
+
+                let predicates = tcx.predicates_of(callee).instantiate(tcx, substs);
+                let cause = ObligationCause::new(
+                    terminator.source_info.span,
+                    self.body.source.def_id().expect_local(),
+                    ObligationCauseCode::ItemObligation(callee),
+                );
+                let normalized_predicates = ocx.normalize(&cause, param_env, predicates);
+                ocx.register_obligations(traits::predicates_for_generics(
+                    |_, _| cause.clone(),
+                    self.param_env,
+                    normalized_predicates,
+                ));
+
+                let errors = ocx.select_all_or_error();
+                if !errors.is_empty() {
+                    infcx.err_ctxt().report_fulfillment_errors(&errors);
+                }
+
                 // Attempting to call a trait method?
                 if let Some(trait_id) = tcx.trait_of_item(callee) {
                     trace!("attempting to call a trait method");
@@ -749,31 +775,6 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> {
                         selcx.select(&obligation)
                     };
 
-                    // do a well-formedness check on the trait method being called. This is because typeck only does a
-                    // "non-const" check. This is required for correctness here.
-                    {
-                        let infcx = tcx.infer_ctxt().build();
-                        let ocx = ObligationCtxt::new(&infcx);
-
-                        let predicates = tcx.predicates_of(callee).instantiate(tcx, substs);
-                        let cause = ObligationCause::new(
-                            terminator.source_info.span,
-                            self.body.source.def_id().expect_local(),
-                            ObligationCauseCode::ItemObligation(callee),
-                        );
-                        let normalized_predicates = ocx.normalize(&cause, param_env, predicates);
-                        ocx.register_obligations(traits::predicates_for_generics(
-                            |_, _| cause.clone(),
-                            self.param_env,
-                            normalized_predicates,
-                        ));
-
-                        let errors = ocx.select_all_or_error();
-                        if !errors.is_empty() {
-                            infcx.err_ctxt().report_fulfillment_errors(&errors);
-                        }
-                    }
-
                     match implsrc {
                         Ok(Some(ImplSource::Param(_, ty::BoundConstness::ConstIfConst))) => {
                             debug!(