Skip to content

Commit 8ff3d1b

Browse files
committed
Auto merge of rust-lang#118379 - compiler-errors:const-params-for-partialeq, r=fee1-dead
Fix `PartialEq` args when `#[const_trait]` is enabled This is based off of your PR that enforces effects on all methods, so just see the last commits. r? fee1-dead
2 parents abe34e9 + d3404d2 commit 8ff3d1b

File tree

8 files changed

+85
-91
lines changed

8 files changed

+85
-91
lines changed

compiler/rustc_hir_typeck/src/callee.rs

+3-36
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,8 @@ use crate::errors;
66
use rustc_ast::util::parser::PREC_POSTFIX;
77
use rustc_errors::{Applicability, Diagnostic, ErrorGuaranteed, StashKey};
88
use rustc_hir as hir;
9-
use rustc_hir::def::{self, CtorKind, DefKind, Namespace, Res};
9+
use rustc_hir::def::{self, CtorKind, Namespace, Res};
1010
use rustc_hir::def_id::DefId;
11-
use rustc_hir::HirId;
1211
use rustc_hir_analysis::autoderef::Autoderef;
1312
use rustc_infer::{
1413
infer,
@@ -373,7 +372,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
373372
) -> Ty<'tcx> {
374373
let (fn_sig, def_id) = match *callee_ty.kind() {
375374
ty::FnDef(def_id, args) => {
376-
self.enforce_context_effects(call_expr.hir_id, call_expr.span, def_id, args);
375+
self.enforce_context_effects(call_expr.span, def_id, args);
377376
let fn_sig = self.tcx.fn_sig(def_id).instantiate(self.tcx, args);
378377

379378
// Unit testing: function items annotated with
@@ -770,7 +769,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
770769
#[tracing::instrument(level = "debug", skip(self, span))]
771770
pub(super) fn enforce_context_effects(
772771
&self,
773-
call_expr_hir: HirId,
774772
span: Span,
775773
callee_did: DefId,
776774
callee_args: GenericArgsRef<'tcx>,
@@ -781,38 +779,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
781779
let generics = tcx.generics_of(callee_did);
782780
let Some(host_effect_index) = generics.host_effect_index else { return };
783781

784-
// if the callee does have the param, we need to equate the param to some const
785-
// value no matter whether the effects feature is enabled in the local crate,
786-
// because inference will fail if we don't.
787-
let mut host_always_on =
788-
!tcx.features().effects || tcx.sess.opts.unstable_opts.unleash_the_miri_inside_of_you;
789-
790-
// Compute the constness required by the context.
791-
let context = tcx.hir().enclosing_body_owner(call_expr_hir);
792-
let const_context = tcx.hir().body_const_context(context);
793-
794-
let kind = tcx.def_kind(context.to_def_id());
795-
debug_assert_ne!(kind, DefKind::ConstParam);
796-
797-
if tcx.has_attr(context.to_def_id(), sym::rustc_do_not_const_check) {
798-
trace!("do not const check this context");
799-
host_always_on = true;
800-
}
801-
802-
let effect = match const_context {
803-
_ if host_always_on => tcx.consts.true_,
804-
Some(hir::ConstContext::Static(_) | hir::ConstContext::Const { .. }) => {
805-
tcx.consts.false_
806-
}
807-
Some(hir::ConstContext::ConstFn) => {
808-
let host_idx = tcx
809-
.generics_of(context)
810-
.host_effect_index
811-
.expect("ConstContext::Maybe must have host effect param");
812-
ty::GenericArgs::identity_for_item(tcx, context).const_at(host_idx)
813-
}
814-
None => tcx.consts.true_,
815-
};
782+
let effect = tcx.expected_const_effect_param_for_body(self.body_id);
816783

817784
trace!(?effect, ?generics, ?callee_args);
818785

compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -165,7 +165,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
165165
span: Span,
166166
method: MethodCallee<'tcx>,
167167
) {
168-
self.enforce_context_effects(hir_id, span, method.def_id, method.args);
168+
self.enforce_context_effects(span, method.def_id, method.args);
169169
self.write_resolution(hir_id, Ok((DefKind::AssocFn, method.def_id)));
170170
self.write_args(hir_id, method.args);
171171
}

compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs

+1-6
Original file line numberDiff line numberDiff line change
@@ -282,12 +282,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
282282
span: provided_arg.span,
283283
});
284284
} else {
285-
self.enforce_context_effects(
286-
provided_arg.hir_id,
287-
provided_arg.span,
288-
def_id,
289-
args,
290-
)
285+
self.enforce_context_effects(provided_arg.span, def_id, args)
291286
}
292287
}
293288
} else {

compiler/rustc_middle/src/ty/util.rs

+51
Original file line numberDiff line numberDiff line change
@@ -779,6 +779,57 @@ impl<'tcx> TyCtxt<'tcx> {
779779
// the language.
780780
|| self.extern_crate(key.as_def_id()).is_some_and(|e| e.is_direct())
781781
}
782+
783+
pub fn expected_const_effect_param_for_body(self, def_id: LocalDefId) -> ty::Const<'tcx> {
784+
// if the callee does have the param, we need to equate the param to some const
785+
// value no matter whether the effects feature is enabled in the local crate,
786+
// because inference will fail if we don't.
787+
let mut host_always_on =
788+
!self.features().effects || self.sess.opts.unstable_opts.unleash_the_miri_inside_of_you;
789+
790+
// Compute the constness required by the context.
791+
let const_context = self.hir().body_const_context(def_id);
792+
793+
let kind = self.def_kind(def_id);
794+
debug_assert_ne!(kind, DefKind::ConstParam);
795+
796+
if self.has_attr(def_id, sym::rustc_do_not_const_check) {
797+
trace!("do not const check this context");
798+
host_always_on = true;
799+
}
800+
801+
match const_context {
802+
_ if host_always_on => self.consts.true_,
803+
Some(hir::ConstContext::Static(_) | hir::ConstContext::Const { .. }) => {
804+
self.consts.false_
805+
}
806+
Some(hir::ConstContext::ConstFn) => {
807+
let host_idx = self
808+
.generics_of(def_id)
809+
.host_effect_index
810+
.expect("ConstContext::Maybe must have host effect param");
811+
ty::GenericArgs::identity_for_item(self, def_id).const_at(host_idx)
812+
}
813+
None => self.consts.true_,
814+
}
815+
}
816+
817+
/// Constructs generic args for an item, optionally appending a const effect param type
818+
pub fn with_opt_const_effect_param(
819+
self,
820+
caller_def_id: LocalDefId,
821+
callee_def_id: DefId,
822+
args: impl IntoIterator<Item: Into<ty::GenericArg<'tcx>>>,
823+
) -> ty::GenericArgsRef<'tcx> {
824+
let generics = self.generics_of(callee_def_id);
825+
assert_eq!(generics.parent, None);
826+
827+
let opt_const_param = generics.host_effect_index.is_some().then(|| {
828+
ty::GenericArg::from(self.expected_const_effect_param_for_body(caller_def_id))
829+
});
830+
831+
self.mk_args_from_iter(args.into_iter().map(|arg| arg.into()).chain(opt_const_param))
832+
}
782833
}
783834

784835
struct OpaqueTypeExpander<'tcx> {

compiler/rustc_mir_build/src/build/matches/test.rs

+6-1
Original file line numberDiff line numberDiff line change
@@ -496,7 +496,12 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
496496
}
497497

498498
let eq_def_id = self.tcx.require_lang_item(LangItem::PartialEq, Some(source_info.span));
499-
let method = trait_method(self.tcx, eq_def_id, sym::eq, [ty, ty]);
499+
let method = trait_method(
500+
self.tcx,
501+
eq_def_id,
502+
sym::eq,
503+
self.tcx.with_opt_const_effect_param(self.def_id, eq_def_id, [ty, ty]),
504+
);
500505

501506
let bool_ty = self.tcx.types.bool;
502507
let eq_result = self.temp(bool_ty, source_info.span);

compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs

+10-2
Original file line numberDiff line numberDiff line change
@@ -258,18 +258,26 @@ impl<'tcx> ConstToPat<'tcx> {
258258

259259
#[instrument(level = "trace", skip(self), ret)]
260260
fn type_has_partial_eq_impl(&self, ty: Ty<'tcx>) -> bool {
261+
let tcx = self.tcx();
261262
// double-check there even *is* a semantic `PartialEq` to dispatch to.
262263
//
263264
// (If there isn't, then we can safely issue a hard
264265
// error, because that's never worked, due to compiler
265266
// using `PartialEq::eq` in this scenario in the past.)
266-
let tcx = self.tcx();
267267
let partial_eq_trait_id = tcx.require_lang_item(hir::LangItem::PartialEq, Some(self.span));
268268
let partial_eq_obligation = Obligation::new(
269269
tcx,
270270
ObligationCause::dummy(),
271271
self.param_env,
272-
ty::TraitRef::new(tcx, partial_eq_trait_id, [ty, ty]),
272+
ty::TraitRef::new(
273+
tcx,
274+
partial_eq_trait_id,
275+
tcx.with_opt_const_effect_param(
276+
tcx.hir().enclosing_body_owner(self.id),
277+
partial_eq_trait_id,
278+
[ty, ty],
279+
),
280+
),
273281
);
274282

275283
// This *could* accept a type that isn't actually `PartialEq`, because region bounds get

tests/ui/rfcs/rfc-2632-const-trait-impl/effects/minicore.rs

+10-1
Original file line numberDiff line numberDiff line change
@@ -336,14 +336,23 @@ fn from_str(s: &str) -> Result<bool, ()> {
336336
}
337337

338338
#[lang = "eq"]
339-
// FIXME #[const_trait]
339+
#[const_trait]
340340
trait PartialEq<Rhs: ?Sized = Self> {
341341
fn eq(&self, other: &Rhs) -> bool;
342342
fn ne(&self, other: &Rhs) -> bool {
343343
!self.eq(other)
344344
}
345345
}
346346

347+
impl<A: ?Sized, B: ?Sized> const PartialEq<&B> for &A
348+
where
349+
A: ~const PartialEq<B>,
350+
{
351+
fn eq(&self, other: &&B) -> bool {
352+
PartialEq::eq(*self, *other)
353+
}
354+
}
355+
347356
// FIXME(effects): again, this should not error without Rhs specified
348357
impl PartialEq<str> for str {
349358
fn eq(&self, other: &str) -> bool {
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,5 @@
1-
warning: to use a constant of type `&str` in a pattern, the type must implement `PartialEq`
2-
--> $DIR/minicore.rs:332:9
3-
|
4-
LL | "true" => Ok(true),
5-
| ^^^^^^
6-
|
7-
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
8-
= note: for more information, see issue #116122 <https://github.com/rust-lang/rust/issues/116122>
9-
= note: `#[warn(const_patterns_without_partial_eq)]` on by default
10-
11-
warning: to use a constant of type `&str` in a pattern, the type must implement `PartialEq`
12-
--> $DIR/minicore.rs:333:9
13-
|
14-
LL | "false" => Ok(false),
15-
| ^^^^^^^
16-
|
17-
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
18-
= note: for more information, see issue #116122 <https://github.com/rust-lang/rust/issues/116122>
19-
201
error[E0493]: destructor of `Self` cannot be evaluated at compile-time
21-
--> $DIR/minicore.rs:494:9
2+
--> $DIR/minicore.rs:503:9
223
|
234
LL | *self = source.clone()
245
| ^^^^^
@@ -27,35 +8,13 @@ LL | *self = source.clone()
278
| value is dropped here
289

2910
error[E0493]: destructor of `T` cannot be evaluated at compile-time
30-
--> $DIR/minicore.rs:504:35
11+
--> $DIR/minicore.rs:513:35
3112
|
3213
LL | const fn drop<T: ~const Destruct>(_: T) {}
3314
| ^ - value is dropped here
3415
| |
3516
| the destructor for this type cannot be evaluated in constant functions
3617

37-
error: aborting due to 2 previous errors; 2 warnings emitted
18+
error: aborting due to 2 previous errors
3819

3920
For more information about this error, try `rustc --explain E0493`.
40-
Future incompatibility report: Future breakage diagnostic:
41-
warning: to use a constant of type `&str` in a pattern, the type must implement `PartialEq`
42-
--> $DIR/minicore.rs:332:9
43-
|
44-
LL | "true" => Ok(true),
45-
| ^^^^^^
46-
|
47-
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
48-
= note: for more information, see issue #116122 <https://github.com/rust-lang/rust/issues/116122>
49-
= note: `#[warn(const_patterns_without_partial_eq)]` on by default
50-
51-
Future breakage diagnostic:
52-
warning: to use a constant of type `&str` in a pattern, the type must implement `PartialEq`
53-
--> $DIR/minicore.rs:333:9
54-
|
55-
LL | "false" => Ok(false),
56-
| ^^^^^^^
57-
|
58-
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
59-
= note: for more information, see issue #116122 <https://github.com/rust-lang/rust/issues/116122>
60-
= note: `#[warn(const_patterns_without_partial_eq)]` on by default
61-

0 commit comments

Comments
 (0)