Skip to content

Commit df1a4c6

Browse files
committed
clean up check_consts checks
1 parent 324ca87 commit df1a4c6

File tree

1 file changed

+40
-147
lines changed
  • compiler/rustc_const_eval/src/transform/check_consts

1 file changed

+40
-147
lines changed

compiler/rustc_const_eval/src/transform/check_consts/check.rs

+40-147
Original file line numberDiff line numberDiff line change
@@ -5,17 +5,15 @@ use rustc_hir as hir;
55
use rustc_hir::def_id::DefId;
66
use rustc_index::bit_set::BitSet;
77
use rustc_infer::infer::TyCtxtInferExt;
8-
use rustc_infer::traits::{ImplSource, Obligation, ObligationCause};
8+
use rustc_infer::traits::ObligationCause;
99
use rustc_middle::mir::visit::{MutatingUseContext, NonMutatingUseContext, PlaceContext, Visitor};
1010
use rustc_middle::mir::*;
11-
use rustc_middle::traits::BuiltinImplSource;
12-
use rustc_middle::ty::GenericArgs;
13-
use rustc_middle::ty::{self, adjustment::PointerCoercion, Instance, InstanceDef, Ty, TyCtxt};
14-
use rustc_middle::ty::{TraitRef, TypeVisitableExt};
11+
use rustc_middle::ty::{self, adjustment::PointerCoercion, Ty, TyCtxt};
12+
use rustc_middle::ty::{Instance, InstanceDef, TypeVisitableExt};
1513
use rustc_mir_dataflow::Analysis;
1614
use rustc_span::{sym, Span, Symbol};
1715
use rustc_trait_selection::traits::error_reporting::TypeErrCtxtExt as _;
18-
use rustc_trait_selection::traits::{self, ObligationCauseCode, ObligationCtxt, SelectionContext};
16+
use rustc_trait_selection::traits::{self, ObligationCauseCode, ObligationCtxt};
1917
use rustc_type_ir::visit::{TypeSuperVisitable, TypeVisitor};
2018

2119
use std::mem;
@@ -752,143 +750,43 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> {
752750
infcx.err_ctxt().report_fulfillment_errors(errors);
753751
}
754752

753+
let mut is_trait = false;
755754
// Attempting to call a trait method?
756-
// FIXME(effects) do we need this?
757-
if let Some(trait_id) = tcx.trait_of_item(callee) {
755+
if tcx.trait_of_item(callee).is_some() {
758756
trace!("attempting to call a trait method");
759-
if !self.tcx.features().const_trait_impl {
757+
// trait method calls are only permitted when `effects` is enabled.
758+
// we don't error, since that is handled by typeck. We try to resolve
759+
// the trait into the concrete method, and uses that for const stability
760+
// checks.
761+
// FIXME(effects) we might consider moving const stability checks to typeck as well.
762+
if tcx.features().effects {
763+
is_trait = true;
764+
765+
if let Ok(Some(instance)) =
766+
Instance::resolve(tcx, param_env, callee, fn_args)
767+
&& let InstanceDef::Item(def) = instance.def
768+
{
769+
// Resolve a trait method call to its concrete implementation, which may be in a
770+
// `const` trait impl. This is only used for the const stability check below, since
771+
// we want to look at the concrete impl's stability.
772+
fn_args = instance.args;
773+
callee = def;
774+
}
775+
} else {
760776
self.check_op(ops::FnCallNonConst {
761777
caller,
762778
callee,
763779
args: fn_args,
764780
span: *fn_span,
765781
call_source: *call_source,
766-
feature: Some(sym::const_trait_impl),
782+
feature: Some(if tcx.features().const_trait_impl {
783+
sym::effects
784+
} else {
785+
sym::const_trait_impl
786+
}),
767787
});
768788
return;
769789
}
770-
771-
let trait_ref = TraitRef::from_method(tcx, trait_id, fn_args);
772-
let obligation =
773-
Obligation::new(tcx, ObligationCause::dummy(), param_env, trait_ref);
774-
775-
let implsrc = {
776-
let infcx = tcx.infer_ctxt().build();
777-
let mut selcx = SelectionContext::new(&infcx);
778-
selcx.select(&obligation)
779-
};
780-
781-
match implsrc {
782-
Ok(Some(ImplSource::Param(_))) if tcx.features().effects => {
783-
debug!(
784-
"const_trait_impl: provided {:?} via where-clause in {:?}",
785-
trait_ref, param_env
786-
);
787-
return;
788-
}
789-
// Closure: Fn{Once|Mut}
790-
Ok(Some(ImplSource::Builtin(BuiltinImplSource::Misc, _)))
791-
if trait_ref.self_ty().is_closure()
792-
&& tcx.fn_trait_kind_from_def_id(trait_id).is_some() =>
793-
{
794-
let ty::Closure(closure_def_id, fn_args) = *trait_ref.self_ty().kind()
795-
else {
796-
unreachable!()
797-
};
798-
if !tcx.is_const_fn_raw(closure_def_id) {
799-
self.check_op(ops::FnCallNonConst {
800-
caller,
801-
callee,
802-
args: fn_args,
803-
span: *fn_span,
804-
call_source: *call_source,
805-
feature: None,
806-
});
807-
808-
return;
809-
}
810-
}
811-
Ok(Some(ImplSource::UserDefined(data))) => {
812-
let callee_name = tcx.item_name(callee);
813-
814-
if let hir::Constness::NotConst = tcx.constness(data.impl_def_id) {
815-
self.check_op(ops::FnCallNonConst {
816-
caller,
817-
callee,
818-
args: fn_args,
819-
span: *fn_span,
820-
call_source: *call_source,
821-
feature: None,
822-
});
823-
return;
824-
}
825-
826-
if let Some(&did) = tcx
827-
.associated_item_def_ids(data.impl_def_id)
828-
.iter()
829-
.find(|did| tcx.item_name(**did) == callee_name)
830-
{
831-
// using internal args is ok here, since this is only
832-
// used for the `resolve` call below
833-
fn_args = GenericArgs::identity_for_item(tcx, did);
834-
callee = did;
835-
}
836-
}
837-
_ if !tcx.is_const_fn_raw(callee) => {
838-
// At this point, it is only legal when the caller is in a trait
839-
// marked with #[const_trait], and the callee is in the same trait.
840-
let mut nonconst_call_permission = false;
841-
if let Some(callee_trait) = tcx.trait_of_item(callee)
842-
&& tcx.has_attr(callee_trait, sym::const_trait)
843-
&& Some(callee_trait) == tcx.trait_of_item(caller.to_def_id())
844-
// Can only call methods when it's `<Self as TheTrait>::f`.
845-
&& tcx.types.self_param == fn_args.type_at(0)
846-
{
847-
nonconst_call_permission = true;
848-
}
849-
850-
if !nonconst_call_permission {
851-
let obligation = Obligation::new(
852-
tcx,
853-
ObligationCause::dummy_with_span(*fn_span),
854-
param_env,
855-
trait_ref,
856-
);
857-
858-
// improve diagnostics by showing what failed. Our requirements are stricter this time
859-
// as we are going to error again anyways.
860-
let infcx = tcx.infer_ctxt().build();
861-
if let Err(e) = implsrc {
862-
infcx.err_ctxt().report_selection_error(
863-
obligation.clone(),
864-
&obligation,
865-
&e,
866-
);
867-
}
868-
869-
self.check_op(ops::FnCallNonConst {
870-
caller,
871-
callee,
872-
args: fn_args,
873-
span: *fn_span,
874-
call_source: *call_source,
875-
feature: None,
876-
});
877-
return;
878-
}
879-
}
880-
_ => {}
881-
}
882-
883-
// Resolve a trait method call to its concrete implementation, which may be in a
884-
// `const` trait impl.
885-
let instance = Instance::resolve(tcx, param_env, callee, fn_args);
886-
debug!("Resolving ({:?}) -> {:?}", callee, instance);
887-
if let Ok(Some(func)) = instance {
888-
if let InstanceDef::Item(def) = func.def {
889-
callee = def;
890-
}
891-
}
892790
}
893791

894792
// At this point, we are calling a function, `callee`, whose `DefId` is known...
@@ -921,21 +819,16 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> {
921819
return;
922820
}
923821

924-
if !tcx.is_const_fn_raw(callee) {
925-
if !tcx.is_const_default_method(callee) {
926-
// To get to here we must have already found a const impl for the
927-
// trait, but for it to still be non-const can be that the impl is
928-
// using default method bodies.
929-
self.check_op(ops::FnCallNonConst {
930-
caller,
931-
callee,
932-
args: fn_args,
933-
span: *fn_span,
934-
call_source: *call_source,
935-
feature: None,
936-
});
937-
return;
938-
}
822+
if !tcx.is_const_fn_raw(callee) && !is_trait {
823+
self.check_op(ops::FnCallNonConst {
824+
caller,
825+
callee,
826+
args: fn_args,
827+
span: *fn_span,
828+
call_source: *call_source,
829+
feature: None,
830+
});
831+
return;
939832
}
940833

941834
// If the `const fn` we are trying to call is not const-stable, ensure that we have

0 commit comments

Comments
 (0)