From d5ebdfc2c55e6ec3c6e50775d7c30d4c29d78651 Mon Sep 17 00:00:00 2001 From: Deadbeef Date: Sat, 25 Nov 2023 13:11:38 +0000 Subject: [PATCH 1/2] effects: Run `enforce_context_effects` for all method calls --- compiler/rustc_hir_typeck/src/callee.rs | 4 +- compiler/rustc_hir_typeck/src/expr.rs | 4 +- .../rustc_hir_typeck/src/fn_ctxt/_impl.rs | 3 +- compiler/rustc_hir_typeck/src/lib.rs | 6 +- compiler/rustc_hir_typeck/src/op.rs | 4 +- compiler/rustc_hir_typeck/src/place_op.rs | 6 +- .../src/thir/pattern/const_to_pat.rs | 8 +- .../call-generic-method-nonconst.rs | 8 +- .../call-generic-method-nonconst.stderr | 18 +++++ .../effects/minicore.rs | 4 +- .../effects/minicore.stderr | 79 +++++++++++++------ 11 files changed, 96 insertions(+), 48 deletions(-) create mode 100644 tests/ui/rfcs/rfc-2632-const-trait-impl/call-generic-method-nonconst.stderr diff --git a/compiler/rustc_hir_typeck/src/callee.rs b/compiler/rustc_hir_typeck/src/callee.rs index d40ac59baa4..fa5833a78a2 100644 --- a/compiler/rustc_hir_typeck/src/callee.rs +++ b/compiler/rustc_hir_typeck/src/callee.rs @@ -845,7 +845,7 @@ fn confirm_overloaded_call( expected, ); - self.write_method_call(call_expr.hir_id, method_callee); + self.write_method_call(call_expr.hir_id, call_expr.span, method_callee); output_type } } @@ -895,7 +895,7 @@ pub fn resolve(self, fcx: &FnCtxt<'a, 'tcx>) { adjustments.extend(autoref); fcx.apply_adjustments(self.callee_expr, adjustments); - fcx.write_method_call(self.call_expr.hir_id, method_callee); + fcx.write_method_call(self.call_expr.hir_id, self.call_expr.span, method_callee); } None => { // This can happen if `#![no_core]` is used and the `fn/fn_mut/fn_once` diff --git a/compiler/rustc_hir_typeck/src/expr.rs b/compiler/rustc_hir_typeck/src/expr.rs index fdf1152a235..b0d32c5a199 100644 --- a/compiler/rustc_hir_typeck/src/expr.rs +++ b/compiler/rustc_hir_typeck/src/expr.rs @@ -1313,9 +1313,7 @@ fn check_method_call( Ok(method) => { // We could add a "consider `foo::`" suggestion here, but I wasn't able to // trigger this codepath causing `structurally_resolve_type` to emit an error. - - self.enforce_context_effects(expr.hir_id, expr.span, method.def_id, method.args); - self.write_method_call(expr.hir_id, method); + self.write_method_call(expr.hir_id, expr.span, method); Ok(method) } Err(error) => { diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs index 9bacebb1039..569ed8dfcaf 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs @@ -159,7 +159,8 @@ pub(in super::super) fn write_resolution( } #[instrument(level = "debug", skip(self))] - pub fn write_method_call(&self, hir_id: hir::HirId, method: MethodCallee<'tcx>) { + pub fn write_method_call(&self, hir_id: hir::HirId, span: Span, method: MethodCallee<'tcx>) { + self.enforce_context_effects(hir_id, span, method.def_id, method.args); self.write_resolution(hir_id, Ok((DefKind::AssocFn, method.def_id))); self.write_args(hir_id, method.args); } diff --git a/compiler/rustc_hir_typeck/src/lib.rs b/compiler/rustc_hir_typeck/src/lib.rs index 66a0f4ed9de..8709cef5947 100644 --- a/compiler/rustc_hir_typeck/src/lib.rs +++ b/compiler/rustc_hir_typeck/src/lib.rs @@ -442,9 +442,13 @@ fn fatally_break_rust(tcx: TyCtxt<'_>) { } } +/// `expected` here is the expected number of explicit generic arguments on the trait. fn has_expected_num_generic_args(tcx: TyCtxt<'_>, trait_did: DefId, expected: usize) -> bool { let generics = tcx.generics_of(trait_did); - generics.count() == expected + if generics.has_self { 1 } else { 0 } + generics.count() + == expected + + if generics.has_self { 1 } else { 0 } + + if generics.host_effect_index.is_some() { 1 } else { 0 } } pub fn provide(providers: &mut Providers) { diff --git a/compiler/rustc_hir_typeck/src/op.rs b/compiler/rustc_hir_typeck/src/op.rs index f40406c6726..c7b785fbcd0 100644 --- a/compiler/rustc_hir_typeck/src/op.rs +++ b/compiler/rustc_hir_typeck/src/op.rs @@ -291,7 +291,7 @@ fn check_overloaded_binop( .push(autoref); } } - self.write_method_call(expr.hir_id, method); + self.write_method_call(expr.hir_id, expr.span, method); method.sig.output() } @@ -781,7 +781,7 @@ pub fn check_user_unop( assert!(op.is_by_value()); match self.lookup_op_method(operand_ty, None, Op::Unary(op, ex.span), expected) { Ok(method) => { - self.write_method_call(ex.hir_id, method); + self.write_method_call(ex.hir_id, ex.span, method); method.sig.output() } Err(errors) => { diff --git a/compiler/rustc_hir_typeck/src/place_op.rs b/compiler/rustc_hir_typeck/src/place_op.rs index f8ca3a4f3d7..12ebde25c33 100644 --- a/compiler/rustc_hir_typeck/src/place_op.rs +++ b/compiler/rustc_hir_typeck/src/place_op.rs @@ -38,7 +38,7 @@ pub(super) fn lookup_derefing( span_bug!(expr.span, "input to deref is not a ref?"); } let ty = self.make_overloaded_place_return_type(method).ty; - self.write_method_call(expr.hir_id, method); + self.write_method_call(expr.hir_id, expr.span, method); Some(ty) } @@ -179,7 +179,7 @@ fn try_index_step( } self.apply_adjustments(base_expr, adjustments); - self.write_method_call(expr.hir_id, method); + self.write_method_call(expr.hir_id, expr.span, method); return Some((input_ty, self.make_overloaded_place_return_type(method).ty)); } @@ -404,7 +404,7 @@ fn convert_place_op_to_mutable( None => return, }; debug!("convert_place_op_to_mutable: method={:?}", method); - self.write_method_call(expr.hir_id, method); + self.write_method_call(expr.hir_id, expr.span, method); let ty::Ref(region, _, hir::Mutability::Mut) = method.sig.inputs()[0].kind() else { span_bug!(expr.span, "input to mutable place op is not a mut ref?"); diff --git a/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs b/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs index 440767927d7..c4bf2f23899 100644 --- a/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs +++ b/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs @@ -263,13 +263,13 @@ fn type_has_partial_eq_impl(&self, ty: Ty<'tcx>) -> bool { // (If there isn't, then we can safely issue a hard // error, because that's never worked, due to compiler // using `PartialEq::eq` in this scenario in the past.) - let partial_eq_trait_id = - self.tcx().require_lang_item(hir::LangItem::PartialEq, Some(self.span)); + let tcx = self.tcx(); + let partial_eq_trait_id = tcx.require_lang_item(hir::LangItem::PartialEq, Some(self.span)); let partial_eq_obligation = Obligation::new( - self.tcx(), + tcx, ObligationCause::dummy(), self.param_env, - ty::TraitRef::new(self.tcx(), partial_eq_trait_id, [ty, ty]), + ty::TraitRef::new(tcx, partial_eq_trait_id, [ty, ty]), ); // This *could* accept a type that isn't actually `PartialEq`, because region bounds get diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/call-generic-method-nonconst.rs b/tests/ui/rfcs/rfc-2632-const-trait-impl/call-generic-method-nonconst.rs index eada4ceafe9..b9331caaf8e 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/call-generic-method-nonconst.rs +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/call-generic-method-nonconst.rs @@ -1,7 +1,4 @@ -// check-pass -// known-bug: #110395 - -#![feature(const_trait_impl)] +#![feature(const_trait_impl, effects)] struct S; @@ -24,6 +21,7 @@ const fn equals_self(t: &T) -> bool { // it not using the impl. pub const EQ: bool = equals_self(&S); -// FIXME(effects) ~^ ERROR +//~^ ERROR +// FIXME(effects) the diagnostics here isn't ideal, we shouldn't get `` fn main() {} diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/call-generic-method-nonconst.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/call-generic-method-nonconst.stderr new file mode 100644 index 00000000000..4fe296d4d3f --- /dev/null +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/call-generic-method-nonconst.stderr @@ -0,0 +1,18 @@ +error[E0277]: the trait bound `S: ~const Foo` is not satisfied + --> $DIR/call-generic-method-nonconst.rs:23:34 + | +LL | pub const EQ: bool = equals_self(&S); + | ----------- ^^ the trait `Foo` is not implemented for `S` + | | + | required by a bound introduced by this call + | + = help: the trait `Foo` is implemented for `S` +note: required by a bound in `equals_self` + --> $DIR/call-generic-method-nonconst.rs:16:25 + | +LL | const fn equals_self(t: &T) -> bool { + | ^^^^^^^^^^ required by this bound in `equals_self` + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/minicore.rs b/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/minicore.rs index c38b4b3f1a2..67da5f9533c 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/minicore.rs +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/minicore.rs @@ -21,7 +21,7 @@ trait Add { fn add(self, rhs: Rhs) -> Self::Output; } -// FIXME we shouldn't need to have to specify `Rhs`. +// FIXME(effects) we shouldn't need to have to specify `Rhs`. impl const Add for i32 { type Output = i32; fn add(self, rhs: i32) -> i32 { @@ -336,7 +336,7 @@ fn from_str(s: &str) -> Result { } #[lang = "eq"] -#[const_trait] +// FIXME #[const_trait] trait PartialEq { fn eq(&self, other: &Rhs) -> bool; fn ne(&self, other: &Rhs) -> bool { diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/minicore.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/minicore.stderr index 02429374218..19e6f6bffc6 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/minicore.stderr +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/minicore.stderr @@ -1,32 +1,61 @@ -error[E0369]: cannot add `i32` to `i32` - --> $DIR/minicore.rs:33:20 +warning: to use a constant of type `&str` in a pattern, the type must implement `PartialEq` + --> $DIR/minicore.rs:332:9 | -LL | let x = 42_i32 + 43_i32; - | ------ ^ ------ i32 - | | - | i32 - -error[E0369]: cannot add `i32` to `i32` - --> $DIR/minicore.rs:37:20 +LL | "true" => Ok(true), + | ^^^^^^ | -LL | let x = 42_i32 + 43_i32; - | ------ ^ ------ i32 - | | - | i32 + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #116122 + = note: `#[warn(const_patterns_without_partial_eq)]` on by default -error[E0600]: cannot apply unary operator `!` to type `bool` - --> $DIR/minicore.rs:343:9 +warning: to use a constant of type `&str` in a pattern, the type must implement `PartialEq` + --> $DIR/minicore.rs:333:9 | -LL | !self.eq(other) - | ^^^^^^^^^^^^^^^ cannot apply unary operator `!` - -error[E0600]: cannot apply unary operator `!` to type `bool` - --> $DIR/minicore.rs:365:9 +LL | "false" => Ok(false), + | ^^^^^^^ | -LL | !self - | ^^^^^ cannot apply unary operator `!` + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #116122 -error: aborting due to 4 previous errors +error[E0493]: destructor of `Self` cannot be evaluated at compile-time + --> $DIR/minicore.rs:494:9 + | +LL | *self = source.clone() + | ^^^^^ + | | + | the destructor for this type cannot be evaluated in constant functions + | value is dropped here + +error[E0493]: destructor of `T` cannot be evaluated at compile-time + --> $DIR/minicore.rs:504:35 + | +LL | const fn drop(_: T) {} + | ^ - value is dropped here + | | + | the destructor for this type cannot be evaluated in constant functions + +error: aborting due to 2 previous errors; 2 warnings emitted + +For more information about this error, try `rustc --explain E0493`. +Future incompatibility report: Future breakage diagnostic: +warning: to use a constant of type `&str` in a pattern, the type must implement `PartialEq` + --> $DIR/minicore.rs:332:9 + | +LL | "true" => Ok(true), + | ^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #116122 + = note: `#[warn(const_patterns_without_partial_eq)]` on by default + +Future breakage diagnostic: +warning: to use a constant of type `&str` in a pattern, the type must implement `PartialEq` + --> $DIR/minicore.rs:333:9 + | +LL | "false" => Ok(false), + | ^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #116122 + = note: `#[warn(const_patterns_without_partial_eq)]` on by default -Some errors have detailed explanations: E0369, E0600. -For more information about an error, try `rustc --explain E0369`. From dd3437b71839d124a8974bcfe853d800cc1c5198 Mon Sep 17 00:00:00 2001 From: Deadbeef Date: Mon, 27 Nov 2023 11:45:01 +0000 Subject: [PATCH 2/2] rename method --- compiler/rustc_hir_typeck/src/callee.rs | 8 ++++++-- compiler/rustc_hir_typeck/src/expr.rs | 2 +- compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs | 7 ++++++- compiler/rustc_hir_typeck/src/op.rs | 4 ++-- compiler/rustc_hir_typeck/src/place_op.rs | 6 +++--- 5 files changed, 18 insertions(+), 9 deletions(-) diff --git a/compiler/rustc_hir_typeck/src/callee.rs b/compiler/rustc_hir_typeck/src/callee.rs index fa5833a78a2..365170a6bbf 100644 --- a/compiler/rustc_hir_typeck/src/callee.rs +++ b/compiler/rustc_hir_typeck/src/callee.rs @@ -845,7 +845,7 @@ fn confirm_overloaded_call( expected, ); - self.write_method_call(call_expr.hir_id, call_expr.span, method_callee); + self.write_method_call_and_enforce_effects(call_expr.hir_id, call_expr.span, method_callee); output_type } } @@ -895,7 +895,11 @@ pub fn resolve(self, fcx: &FnCtxt<'a, 'tcx>) { adjustments.extend(autoref); fcx.apply_adjustments(self.callee_expr, adjustments); - fcx.write_method_call(self.call_expr.hir_id, self.call_expr.span, method_callee); + fcx.write_method_call_and_enforce_effects( + self.call_expr.hir_id, + self.call_expr.span, + method_callee, + ); } None => { // This can happen if `#![no_core]` is used and the `fn/fn_mut/fn_once` diff --git a/compiler/rustc_hir_typeck/src/expr.rs b/compiler/rustc_hir_typeck/src/expr.rs index b0d32c5a199..e9a93bbb8ab 100644 --- a/compiler/rustc_hir_typeck/src/expr.rs +++ b/compiler/rustc_hir_typeck/src/expr.rs @@ -1313,7 +1313,7 @@ fn check_method_call( Ok(method) => { // We could add a "consider `foo::`" suggestion here, but I wasn't able to // trigger this codepath causing `structurally_resolve_type` to emit an error. - self.write_method_call(expr.hir_id, expr.span, method); + self.write_method_call_and_enforce_effects(expr.hir_id, expr.span, method); Ok(method) } Err(error) => { diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs index 569ed8dfcaf..3d3bf50c1cc 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs @@ -159,7 +159,12 @@ pub(in super::super) fn write_resolution( } #[instrument(level = "debug", skip(self))] - pub fn write_method_call(&self, hir_id: hir::HirId, span: Span, method: MethodCallee<'tcx>) { + pub fn write_method_call_and_enforce_effects( + &self, + hir_id: hir::HirId, + span: Span, + method: MethodCallee<'tcx>, + ) { self.enforce_context_effects(hir_id, span, method.def_id, method.args); self.write_resolution(hir_id, Ok((DefKind::AssocFn, method.def_id))); self.write_args(hir_id, method.args); diff --git a/compiler/rustc_hir_typeck/src/op.rs b/compiler/rustc_hir_typeck/src/op.rs index c7b785fbcd0..fcb3f8f47bd 100644 --- a/compiler/rustc_hir_typeck/src/op.rs +++ b/compiler/rustc_hir_typeck/src/op.rs @@ -291,7 +291,7 @@ fn check_overloaded_binop( .push(autoref); } } - self.write_method_call(expr.hir_id, expr.span, method); + self.write_method_call_and_enforce_effects(expr.hir_id, expr.span, method); method.sig.output() } @@ -781,7 +781,7 @@ pub fn check_user_unop( assert!(op.is_by_value()); match self.lookup_op_method(operand_ty, None, Op::Unary(op, ex.span), expected) { Ok(method) => { - self.write_method_call(ex.hir_id, ex.span, method); + self.write_method_call_and_enforce_effects(ex.hir_id, ex.span, method); method.sig.output() } Err(errors) => { diff --git a/compiler/rustc_hir_typeck/src/place_op.rs b/compiler/rustc_hir_typeck/src/place_op.rs index 12ebde25c33..79e41ef9227 100644 --- a/compiler/rustc_hir_typeck/src/place_op.rs +++ b/compiler/rustc_hir_typeck/src/place_op.rs @@ -38,7 +38,7 @@ pub(super) fn lookup_derefing( span_bug!(expr.span, "input to deref is not a ref?"); } let ty = self.make_overloaded_place_return_type(method).ty; - self.write_method_call(expr.hir_id, expr.span, method); + self.write_method_call_and_enforce_effects(expr.hir_id, expr.span, method); Some(ty) } @@ -179,7 +179,7 @@ fn try_index_step( } self.apply_adjustments(base_expr, adjustments); - self.write_method_call(expr.hir_id, expr.span, method); + self.write_method_call_and_enforce_effects(expr.hir_id, expr.span, method); return Some((input_ty, self.make_overloaded_place_return_type(method).ty)); } @@ -404,7 +404,7 @@ fn convert_place_op_to_mutable( None => return, }; debug!("convert_place_op_to_mutable: method={:?}", method); - self.write_method_call(expr.hir_id, expr.span, method); + self.write_method_call_and_enforce_effects(expr.hir_id, expr.span, method); let ty::Ref(region, _, hir::Mutability::Mut) = method.sig.inputs()[0].kind() else { span_bug!(expr.span, "input to mutable place op is not a mut ref?");