Skip to content

Commit df9d06d

Browse files
authored
Rollup merge of rust-lang#119072 - fee1-dead-contrib:effects-fixes, r=compiler-errors
Clean up `check_consts` and misc fixes 1. Remove most of the logic around erroring with trait methods. I have kept the part resolving it to a concrete impl, as that is used for const stability checks. 2. Turning on `effects` causes ICE with generic args, due to `~const Tr` when `Tr` is not `#[const_trait]` tripping up expectation in code that handles generic args, more specifically here: https://github.com/rust-lang/rust/blob/8681e077b8afa99d60acf8f8470a012a3ce709a5/compiler/rustc_hir_analysis/src/astconv/generics.rs#L377 We set `arg_count.correct` to `Err` to correctly signal that an error has already been reported. 3. UI test blesses. Edit(fmease): Fixes rust-lang#117244 (UI test is in rust-lang#119099 for now). r? compiler-errors
2 parents c03d978 + df1a4c6 commit df9d06d

37 files changed

+176
-299
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;
@@ -756,143 +754,43 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> {
756754
infcx.err_ctxt().report_fulfillment_errors(errors);
757755
}
758756

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

898796
// At this point, we are calling a function, `callee`, whose `DefId` is known...
@@ -925,21 +823,16 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> {
925823
return;
926824
}
927825

928-
if !tcx.is_const_fn_raw(callee) {
929-
if !tcx.is_const_default_method(callee) {
930-
// To get to here we must have already found a const impl for the
931-
// trait, but for it to still be non-const can be that the impl is
932-
// using default method bodies.
933-
self.check_op(ops::FnCallNonConst {
934-
caller,
935-
callee,
936-
args: fn_args,
937-
span: *fn_span,
938-
call_source: *call_source,
939-
feature: None,
940-
});
941-
return;
942-
}
826+
if !tcx.is_const_fn_raw(callee) && !is_trait {
827+
self.check_op(ops::FnCallNonConst {
828+
caller,
829+
callee,
830+
args: fn_args,
831+
span: *fn_span,
832+
call_source: *call_source,
833+
feature: None,
834+
});
835+
return;
943836
}
944837

945838
// 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

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)