Skip to content

effects: Run enforce_context_effects for all method calls #118282

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Nov 28, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 6 additions & 2 deletions compiler/rustc_hir_typeck/src/callee.rs
Original file line number Diff line number Diff line change
Expand Up @@ -845,7 +845,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
expected,
);

self.write_method_call(call_expr.hir_id, method_callee);
self.write_method_call_and_enforce_effects(call_expr.hir_id, call_expr.span, method_callee);
output_type
}
}
Expand Down Expand Up @@ -895,7 +895,11 @@ impl<'a, 'tcx> DeferredCallResolution<'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_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`
Expand Down
4 changes: 1 addition & 3 deletions compiler/rustc_hir_typeck/src/expr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1313,9 +1313,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
Ok(method) => {
// We could add a "consider `foo::<params>`" 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_and_enforce_effects(expr.hir_id, expr.span, method);
Ok(method)
}
Err(error) => {
Expand Down
8 changes: 7 additions & 1 deletion compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs
Original file line number Diff line number Diff line change
Expand Up @@ -159,7 +159,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
}

#[instrument(level = "debug", skip(self))]
pub fn write_method_call(&self, hir_id: hir::HirId, 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);
}
Expand Down
6 changes: 5 additions & 1 deletion compiler/rustc_hir_typeck/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down
4 changes: 2 additions & 2 deletions compiler/rustc_hir_typeck/src/op.rs
Original file line number Diff line number Diff line change
Expand Up @@ -291,7 +291,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
.push(autoref);
}
}
self.write_method_call(expr.hir_id, method);
self.write_method_call_and_enforce_effects(expr.hir_id, expr.span, method);

method.sig.output()
}
Expand Down Expand Up @@ -781,7 +781,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
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_and_enforce_effects(ex.hir_id, ex.span, method);
method.sig.output()
}
Err(errors) => {
Expand Down
6 changes: 3 additions & 3 deletions compiler/rustc_hir_typeck/src/place_op.rs
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
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_and_enforce_effects(expr.hir_id, expr.span, method);
Some(ty)
}

Expand Down Expand Up @@ -179,7 +179,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
}
self.apply_adjustments(base_expr, adjustments);

self.write_method_call(expr.hir_id, 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));
}
Expand Down Expand Up @@ -404,7 +404,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
None => return,
};
debug!("convert_place_op_to_mutable: method={:?}", method);
self.write_method_call(expr.hir_id, 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?");
Expand Down
8 changes: 4 additions & 4 deletions compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs
Original file line number Diff line number Diff line change
Expand Up @@ -263,13 +263,13 @@ impl<'tcx> ConstToPat<'tcx> {
// (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
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,4 @@
// check-pass
// known-bug: #110395

#![feature(const_trait_impl)]
#![feature(const_trait_impl, effects)]

struct S;

Expand All @@ -24,6 +21,7 @@ const fn equals_self<T: ~const Foo>(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 `<false>`

fn main() {}
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
error[E0277]: the trait bound `S: ~const Foo<false>` is not satisfied
--> $DIR/call-generic-method-nonconst.rs:23:34
|
LL | pub const EQ: bool = equals_self(&S);
| ----------- ^^ the trait `Foo<false>` 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: ~const Foo>(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`.
4 changes: 2 additions & 2 deletions tests/ui/rfcs/rfc-2632-const-trait-impl/effects/minicore.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ trait Add<Rhs = Self> {
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<i32> for i32 {
type Output = i32;
fn add(self, rhs: i32) -> i32 {
Expand Down Expand Up @@ -336,7 +336,7 @@ fn from_str(s: &str) -> Result<bool, ()> {
}

#[lang = "eq"]
#[const_trait]
// FIXME #[const_trait]
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What breaks here, out of curiosity? from_str should be host = true, so why can't we evaluate the PartialEq obligation in the match above?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think the only explanation here for this breaking is that we begun checking == method calls. Having this led to ICEs about mismatched number of generic arguments for PartialEq.

trait PartialEq<Rhs: ?Sized = Self> {
fn eq(&self, other: &Rhs) -> bool;
fn ne(&self, other: &Rhs) -> bool {
Expand Down
75 changes: 52 additions & 23 deletions tests/ui/rfcs/rfc-2632-const-trait-impl/effects/minicore.stderr
Original file line number Diff line number Diff line change
@@ -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
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 <https://github.com/rust-lang/rust/issues/116122>
= note: `#[warn(const_patterns_without_partial_eq)]` on by default

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 <https://github.com/rust-lang/rust/issues/116122>

error[E0369]: cannot add `i32` to `i32`
--> $DIR/minicore.rs:37:20
error[E0493]: destructor of `Self` cannot be evaluated at compile-time
--> $DIR/minicore.rs:494:9
|
LL | let x = 42_i32 + 43_i32;
| ------ ^ ------ i32
| |
| i32
LL | *self = source.clone()
| ^^^^^
| |
| the destructor for this type cannot be evaluated in constant functions
| value is dropped here

error[E0600]: cannot apply unary operator `!` to type `bool`
--> $DIR/minicore.rs:343:9
error[E0493]: destructor of `T` cannot be evaluated at compile-time
--> $DIR/minicore.rs:504:35
|
LL | !self.eq(other)
| ^^^^^^^^^^^^^^^ cannot apply unary operator `!`
LL | const fn drop<T: ~const Destruct>(_: T) {}
| ^ - value is dropped here
| |
| the destructor for this type cannot be evaluated in constant functions

error[E0600]: cannot apply unary operator `!` to type `bool`
--> $DIR/minicore.rs:365:9
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),
| ^^^^^^
|
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 <https://github.com/rust-lang/rust/issues/116122>
= note: `#[warn(const_patterns_without_partial_eq)]` on by default

error: aborting due to 4 previous errors
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 <https://github.com/rust-lang/rust/issues/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`.