@@ -11,7 +11,6 @@ use rustc_hir::def_id::DefId;
11
11
use rustc_hir::{self as hir, LangItem};
12
12
use rustc_index::bit_set::BitSet;
13
13
use rustc_infer::infer::TyCtxtInferExt;
14
- use rustc_infer::traits::ObligationCause;
15
14
use rustc_middle::mir::visit::Visitor;
16
15
use rustc_middle::mir::*;
17
16
use rustc_middle::span_bug;
@@ -20,9 +19,11 @@ use rustc_middle::ty::{self, Instance, InstanceKind, Ty, TypeVisitableExt};
20
19
use rustc_mir_dataflow::Analysis;
21
20
use rustc_mir_dataflow::impls::MaybeStorageLive;
22
21
use rustc_mir_dataflow::storage::always_storage_live_locals;
23
- use rustc_span::{DUMMY_SP, Span, Symbol, sym};
22
+ use rustc_span::{Span, Symbol, sym};
24
23
use rustc_trait_selection::error_reporting::InferCtxtErrorExt;
25
- use rustc_trait_selection::traits::{self, ObligationCauseCode, ObligationCtxt};
24
+ use rustc_trait_selection::traits::{
25
+ Obligation, ObligationCause, ObligationCauseCode, ObligationCtxt,
26
+ };
26
27
use tracing::{debug, instrument, trace};
27
28
28
29
use super::ops::{self, NonConstOp, Status};
@@ -360,6 +361,60 @@ impl<'mir, 'tcx> Checker<'mir, 'tcx> {
360
361
// end of evaluation.
361
362
!is_transient
362
363
}
364
+
365
+ fn revalidate_conditional_constness(
366
+ &self,
367
+ callee: DefId,
368
+ callee_args: ty::GenericArgsRef<'tcx>,
369
+ call_source: CallSource,
370
+ call_span: Span,
371
+ ) {
372
+ let tcx = self.tcx;
373
+ if !tcx.is_conditionally_const(callee) {
374
+ return;
375
+ }
376
+
377
+ let infcx = tcx.infer_ctxt().build(self.body.typing_mode(tcx));
378
+ let ocx = ObligationCtxt::new_with_diagnostics(&infcx);
379
+
380
+ let const_conditions = tcx.const_conditions(callee).instantiate(tcx, callee_args);
381
+
382
+ let body_id = self.body.source.def_id().expect_local();
383
+ let host_polarity = match self.const_kind() {
384
+ hir::ConstContext::ConstFn => ty::BoundConstness::Maybe,
385
+ hir::ConstContext::Static(_) | hir::ConstContext::Const { .. } => {
386
+ ty::BoundConstness::Const
387
+ }
388
+ };
389
+ let const_conditions = ocx.normalize(
390
+ &ObligationCause::misc(call_span, body_id),
391
+ self.param_env,
392
+ const_conditions,
393
+ );
394
+ ocx.register_obligations(const_conditions.into_iter().map(|(trait_ref, span)| {
395
+ Obligation::new(
396
+ tcx,
397
+ ObligationCause::new(
398
+ call_span,
399
+ body_id,
400
+ ObligationCauseCode::WhereClause(callee, span),
401
+ ),
402
+ self.param_env,
403
+ trait_ref.to_host_effect_clause(tcx, host_polarity),
404
+ )
405
+ }));
406
+
407
+ let errors = ocx.select_all_or_error();
408
+ if !errors.is_empty() {
409
+ // FIXME(effects): Soon this should be unconditionally delaying a bug.
410
+ if matches!(call_source, CallSource::Normal) && tcx.features().effects() {
411
+ tcx.dcx()
412
+ .span_delayed_bug(call_span, "this should have reported a ~const error in HIR");
413
+ } else {
414
+ infcx.err_ctxt().report_fulfillment_errors(errors);
415
+ }
416
+ }
417
+ }
363
418
}
364
419
365
420
impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> {
@@ -584,31 +639,12 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> {
584
639
}
585
640
};
586
641
587
- // Check that all trait bounds that are marked as `~const` can be satisfied.
588
- //
589
- // Typeck only does a "non-const" check since it operates on HIR and cannot distinguish
590
- // which path expressions are getting called on and which path expressions are only used
591
- // as function pointers. This is required for correctness.
592
- let infcx = tcx.infer_ctxt().build(body.typing_mode(tcx));
593
- let ocx = ObligationCtxt::new_with_diagnostics(&infcx);
594
-
595
- let predicates = tcx.predicates_of(callee).instantiate(tcx, fn_args);
596
- let cause = ObligationCause::new(
642
+ self.revalidate_conditional_constness(
643
+ callee,
644
+ fn_args,
645
+ call_source,
597
646
terminator.source_info.span,
598
- self.body.source.def_id().expect_local(),
599
- ObligationCauseCode::WhereClause(callee, DUMMY_SP),
600
647
);
601
- let normalized_predicates = ocx.normalize(&cause, param_env, predicates);
602
- ocx.register_obligations(traits::predicates_for_generics(
603
- |_, _| cause.clone(),
604
- self.param_env,
605
- normalized_predicates,
606
- ));
607
-
608
- let errors = ocx.select_all_or_error();
609
- if !errors.is_empty() {
610
- infcx.err_ctxt().report_fulfillment_errors(errors);
611
- }
612
648
613
649
let mut is_trait = false;
614
650
// Attempting to call a trait method?
0 commit comments