Skip to content

Commit dd851f7

Browse files
committed
Clean up check_consts and misc fixes
1 parent 43dcc9b commit dd851f7

38 files changed

+189
-295
lines changed

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

+52-140
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,8 @@ use rustc_infer::infer::TyCtxtInferExt;
88
use rustc_infer::traits::{ImplSource, Obligation, 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::{GenericArgs, Instance, InstanceDef, TraitRef, TypeVisitableExt};
1513
use rustc_mir_dataflow::Analysis;
1614
use rustc_span::{sym, Span, Symbol};
1715
use rustc_trait_selection::traits::error_reporting::TypeErrCtxtExt as _;
@@ -752,142 +750,61 @@ 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?
757755
if let Some(trait_id) = tcx.trait_of_item(callee) {
758756
trace!("attempting to call a trait method");
759-
if !self.tcx.features().const_trait_impl {
760-
self.check_op(ops::FnCallNonConst {
761-
caller,
762-
callee,
763-
args: fn_args,
764-
span: *fn_span,
765-
call_source: *call_source,
766-
feature: Some(sym::const_trait_impl),
767-
});
768-
return;
769-
}
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))) => {
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+
let trait_ref = TraitRef::from_method(tcx, trait_id, fn_args);
765+
let obligation =
766+
Obligation::new(tcx, ObligationCause::dummy(), param_env, trait_ref);
767+
768+
let implsrc = {
769+
let infcx = tcx.infer_ctxt().build();
770+
let mut selcx = SelectionContext::new(&infcx);
771+
selcx.select(&obligation)
772+
};
773+
if let Ok(Some(ImplSource::UserDefined(data))) = implsrc {
812774
let callee_name = tcx.item_name(callee);
813775

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-
826776
if let Some(&did) = tcx
827777
.associated_item_def_ids(data.impl_def_id)
828778
.iter()
829779
.find(|did| tcx.item_name(**did) == callee_name)
830780
{
831-
// using internal args is ok here, since this is only
832-
// used for the `resolve` call below
833781
fn_args = GenericArgs::identity_for_item(tcx, did);
834782
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-
);
783+
// Resolve a trait method call to its concrete implementation, which may be in a
784+
// `const` trait impl.
785+
let instance = Instance::resolve(tcx, param_env, callee, fn_args);
786+
debug!("Resolving ({:?}) -> {:?}", callee, instance);
787+
if let Ok(Some(func)) = instance {
788+
if let InstanceDef::Item(def) = func.def {
789+
callee = def;
790+
}
867791
}
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;
878792
}
879793
}
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-
}
794+
} else {
795+
self.check_op(ops::FnCallNonConst {
796+
caller,
797+
callee,
798+
args: fn_args,
799+
span: *fn_span,
800+
call_source: *call_source,
801+
feature: Some(if tcx.features().const_trait_impl {
802+
sym::effects
803+
} else {
804+
sym::const_trait_impl
805+
}),
806+
});
807+
return;
891808
}
892809
}
893810

@@ -921,21 +838,16 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> {
921838
return;
922839
}
923840

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-
}
841+
if !tcx.is_const_fn_raw(callee) && !is_trait {
842+
self.check_op(ops::FnCallNonConst {
843+
caller,
844+
callee,
845+
args: fn_args,
846+
span: *fn_span,
847+
call_source: *call_source,
848+
feature: None,
849+
});
850+
return;
939851
}
940852

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

compiler/rustc_hir_analysis/src/astconv/mod.rs

+9-8
Original file line numberDiff line numberDiff line change
@@ -378,7 +378,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
378378
assert!(self_ty.is_none());
379379
}
380380

381-
let arg_count = check_generic_arg_count(
381+
let mut arg_count = check_generic_arg_count(
382382
tcx,
383383
span,
384384
def_id,
@@ -560,6 +560,14 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
560560
inferred_params: vec![],
561561
infer_args,
562562
};
563+
if let ty::BoundConstness::ConstIfConst = constness
564+
&& generics.has_self
565+
&& !tcx.has_attr(def_id, sym::const_trait)
566+
{
567+
let e = tcx.sess.emit_err(crate::errors::ConstBoundForNonConstTrait { span });
568+
arg_count.correct =
569+
Err(GenericArgCountMismatch { reported: Some(e), invalid_args: vec![] });
570+
}
563571
let args = create_args_for_parent_generic_args(
564572
tcx,
565573
def_id,
@@ -570,13 +578,6 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
570578
&mut args_ctx,
571579
);
572580

573-
if let ty::BoundConstness::ConstIfConst = constness
574-
&& generics.has_self
575-
&& !tcx.has_attr(def_id, sym::const_trait)
576-
{
577-
tcx.sess.emit_err(crate::errors::ConstBoundForNonConstTrait { span });
578-
}
579-
580581
(args, arg_count)
581582
}
582583

compiler/rustc_hir_analysis/src/structured_errors/wrong_number_of_generic_args.rs

+1-3
Original file line numberDiff line numberDiff line change
@@ -186,9 +186,7 @@ impl<'a, 'tcx> WrongNumberOfGenericArgs<'a, 'tcx> {
186186
fn num_provided_type_or_const_args(&self) -> usize {
187187
match self.angle_brackets {
188188
AngleBrackets::Missing => 0,
189-
// Only lifetime arguments can be implied
190-
AngleBrackets::Implied => 0,
191-
AngleBrackets::Available => self.gen_args.num_generic_params(),
189+
AngleBrackets::Implied | AngleBrackets::Available => self.gen_args.num_generic_params(),
192190
}
193191
}
194192

tests/ui/consts/auxiliary/closure-in-foreign-crate.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
#![crate_type = "lib"]
2-
#![feature(const_closures, const_trait_impl)]
2+
#![feature(const_closures, const_trait_impl, effects)]
33
#![allow(incomplete_features)]
44

55
pub const fn test() {

tests/ui/consts/const-float-classify.rs

+6-23
Original file line numberDiff line numberDiff line change
@@ -1,41 +1,24 @@
11
// compile-flags: -Zmir-opt-level=0
2-
// known-bug: #110395
3-
// FIXME run-pass
2+
// run-pass
43

54
#![feature(const_float_bits_conv)]
65
#![feature(const_float_classify)]
7-
#![feature(const_trait_impl)]
6+
#![feature(const_trait_impl, effects)]
87

98
// Don't promote
109
const fn nop<T>(x: T) -> T { x }
1110

12-
// FIXME(const-hack): replace with PartialEq
13-
#[const_trait]
14-
trait MyEq<T> {
15-
fn eq(self, b: T) -> bool;
16-
}
17-
18-
impl const MyEq<bool> for bool {
19-
fn eq(self, b: bool) -> bool {
20-
self == b
21-
}
22-
}
23-
24-
impl const MyEq<NonDet> for bool {
25-
fn eq(self, _: NonDet) -> bool {
11+
impl const PartialEq<NonDet> for bool {
12+
fn eq(&self, _: &NonDet) -> bool {
2613
true
2714
}
2815
}
2916

30-
const fn eq<A: ~const MyEq<B>, B>(x: A, y: B) -> bool {
31-
x.eq(y)
32-
}
33-
3417
macro_rules! const_assert {
3518
($a:expr, $b:expr) => {
3619
{
37-
const _: () = assert!(eq($a, $b));
38-
assert!(eq(nop($a), nop($b)));
20+
const _: () = assert!($a == $b);
21+
assert!(nop($a) == nop($b));
3922
}
4023
};
4124
}

tests/ui/consts/const-float-classify.stderr

-11
This file was deleted.

tests/ui/consts/const-try.stderr

+2
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ note: impl defined here, but it is not `const`
1010
LL | impl const Try for TryMe {
1111
| ^^^^^^^^^^^^^^^^^^^^^^^^
1212
= note: calls in constant functions are limited to constant functions, tuple structs and tuple variants
13+
= help: add `#![feature(effects)]` to the crate attributes to enable
1314

1415
error[E0015]: `?` cannot convert from residual of `TryMe` in constant functions
1516
--> $DIR/const-try.rs:33:5
@@ -23,6 +24,7 @@ note: impl defined here, but it is not `const`
2324
LL | impl const FromResidual<Error> for TryMe {
2425
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
2526
= note: calls in constant functions are limited to constant functions, tuple structs and tuple variants
27+
= help: add `#![feature(effects)]` to the crate attributes to enable
2628

2729
error: aborting due to 2 previous errors
2830

tests/ui/consts/const_cmp_type_id.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
// known-bug: #110395
22
#![feature(const_type_id)]
3-
#![feature(const_trait_impl)]
3+
#![feature(const_trait_impl, effects)]
44

55
use std::any::TypeId;
66

0 commit comments

Comments
 (0)