Unnamed repository; edit this file 'description' to name the repository.
Auto merge of #13882 - Veykril:bin-op-adjust, r=Veykril
Write down adjustments introduced by binary operators
bors 2023-01-03
parent 17cc78f · parent 506895f · commit e75e2f8
-rw-r--r--crates/hir-ty/src/infer/expr.rs36
-rw-r--r--crates/hir-ty/src/tests.rs27
-rw-r--r--crates/hir-ty/src/tests/coercion.rs34
-rw-r--r--crates/ide/src/inlay_hints.rs4
-rw-r--r--crates/ide/src/inlay_hints/discriminant.rs (renamed from crates/ide/src/inlay_hints/discrimant.rs)0
-rw-r--r--crates/test-utils/src/minicore.rs6
6 files changed, 86 insertions, 21 deletions
diff --git a/crates/hir-ty/src/infer/expr.rs b/crates/hir-ty/src/infer/expr.rs
index a5dd020676..2e5c424410 100644
--- a/crates/hir-ty/src/infer/expr.rs
+++ b/crates/hir-ty/src/infer/expr.rs
@@ -6,7 +6,7 @@ use std::{
};
use chalk_ir::{
- cast::Cast, fold::Shift, DebruijnIndex, GenericArgData, Mutability, TyVariableKind,
+ cast::Cast, fold::Shift, DebruijnIndex, GenericArgData, Mutability, TyKind, TyVariableKind,
};
use hir_def::{
expr::{
@@ -34,8 +34,8 @@ use crate::{
primitive::{self, UintTy},
static_lifetime, to_chalk_trait_id,
utils::{generics, Generics},
- AdtId, Binders, CallableDefId, FnPointer, FnSig, FnSubst, Interner, Rawness, Scalar,
- Substitution, TraitRef, Ty, TyBuilder, TyExt, TyKind,
+ Adjust, Adjustment, AdtId, AutoBorrow, Binders, CallableDefId, FnPointer, FnSig, FnSubst,
+ Interner, Rawness, Scalar, Substitution, TraitRef, Ty, TyBuilder, TyExt,
};
use super::{
@@ -1038,14 +1038,38 @@ impl<'a> InferenceContext<'a> {
self.infer_expr_coerce(rhs, &Expectation::has_type(rhs_ty.clone()));
let ret_ty = match method_ty.callable_sig(self.db) {
- Some(sig) => sig.ret().clone(),
+ Some(sig) => {
+ let p_left = &sig.params()[0];
+ if matches!(op, BinaryOp::CmpOp(..) | BinaryOp::Assignment { .. }) {
+ if let &TyKind::Ref(mtbl, _, _) = p_left.kind(Interner) {
+ self.write_expr_adj(
+ lhs,
+ vec![Adjustment {
+ kind: Adjust::Borrow(AutoBorrow::Ref(mtbl)),
+ target: p_left.clone(),
+ }],
+ );
+ }
+ }
+ let p_right = &sig.params()[1];
+ if matches!(op, BinaryOp::CmpOp(..)) {
+ if let &TyKind::Ref(mtbl, _, _) = p_right.kind(Interner) {
+ self.write_expr_adj(
+ rhs,
+ vec![Adjustment {
+ kind: Adjust::Borrow(AutoBorrow::Ref(mtbl)),
+ target: p_right.clone(),
+ }],
+ );
+ }
+ }
+ sig.ret().clone()
+ }
None => self.err_ty(),
};
let ret_ty = self.normalize_associated_types_in(ret_ty);
- // FIXME: record autoref adjustments
-
// use knowledge of built-in binary ops, which can sometimes help inference
if let Some(builtin_rhs) = self.builtin_binary_op_rhs_expectation(op, lhs_ty.clone()) {
self.unify(&builtin_rhs, &rhs_ty);
diff --git a/crates/hir-ty/src/tests.rs b/crates/hir-ty/src/tests.rs
index 7bcf89ff59..ba5d9c2412 100644
--- a/crates/hir-ty/src/tests.rs
+++ b/crates/hir-ty/src/tests.rs
@@ -94,11 +94,12 @@ fn check_impl(ra_fixture: &str, allow_none: bool, only_types: bool, display_sour
types.insert(file_range, expected.trim_start_matches("type: ").to_string());
} else if expected.starts_with("expected") {
mismatches.insert(file_range, expected);
- } else if expected.starts_with("adjustments: ") {
+ } else if expected.starts_with("adjustments:") {
adjustments.insert(
file_range,
expected
- .trim_start_matches("adjustments: ")
+ .trim_start_matches("adjustments:")
+ .trim()
.split(',')
.map(|it| it.trim().to_string())
.filter(|it| !it.is_empty())
@@ -176,17 +177,17 @@ fn check_impl(ra_fixture: &str, allow_none: bool, only_types: bool, display_sour
assert_eq!(actual, expected);
}
if let Some(expected) = adjustments.remove(&range) {
- if let Some(adjustments) = inference_result.expr_adjustments.get(&expr) {
- assert_eq!(
- expected,
- adjustments
- .iter()
- .map(|Adjustment { kind, .. }| format!("{kind:?}"))
- .collect::<Vec<_>>()
- );
- } else {
- panic!("expected {expected:?} adjustments, found none");
- }
+ let adjustments = inference_result
+ .expr_adjustments
+ .get(&expr)
+ .map_or_else(Default::default, |it| &**it);
+ assert_eq!(
+ expected,
+ adjustments
+ .iter()
+ .map(|Adjustment { kind, .. }| format!("{kind:?}"))
+ .collect::<Vec<_>>()
+ );
}
}
diff --git a/crates/hir-ty/src/tests/coercion.rs b/crates/hir-ty/src/tests/coercion.rs
index 7e3aecc2ae..3e110abaf4 100644
--- a/crates/hir-ty/src/tests/coercion.rs
+++ b/crates/hir-ty/src/tests/coercion.rs
@@ -807,3 +807,37 @@ fn main() {
"#,
);
}
+
+#[test]
+fn adjust_comparison_arguments() {
+ check_no_mismatches(
+ r"
+//- minicore: eq
+struct Struct;
+impl core::cmp::PartialEq for Struct {
+ fn eq(&self, other: &Self) -> bool { true }
+}
+fn test() {
+ Struct == Struct;
+ // ^^^^^^ adjustments: Borrow(Ref(Not))
+ // ^^^^^^ adjustments: Borrow(Ref(Not))
+}",
+ );
+}
+
+#[test]
+fn adjust_assign_lhs() {
+ check_no_mismatches(
+ r"
+//- minicore: add
+struct Struct;
+impl core::ops::AddAssign for Struct {
+ fn add_assign(&mut self, other: Self) {}
+}
+fn test() {
+ Struct += Struct;
+ // ^^^^^^ adjustments: Borrow(Ref(Mut))
+ // ^^^^^^ adjustments:
+}",
+ );
+}
diff --git a/crates/ide/src/inlay_hints.rs b/crates/ide/src/inlay_hints.rs
index 9ec3f7f29a..368c8aaa93 100644
--- a/crates/ide/src/inlay_hints.rs
+++ b/crates/ide/src/inlay_hints.rs
@@ -24,7 +24,7 @@ mod chaining;
mod param_name;
mod binding_mode;
mod bind_pat;
-mod discrimant;
+mod discriminant;
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct InlayHintsConfig {
@@ -376,7 +376,7 @@ fn hints(
_ => None,
},
ast::Variant(v) => {
- discrimant::hints(hints, famous_defs, config, file_id, &v)
+ discriminant::hints(hints, famous_defs, config, file_id, &v)
},
// FIXME: fn-ptr type, dyn fn type, and trait object type elisions
ast::Type(_) => None,
diff --git a/crates/ide/src/inlay_hints/discrimant.rs b/crates/ide/src/inlay_hints/discriminant.rs
index f32c4bdf28..f32c4bdf28 100644
--- a/crates/ide/src/inlay_hints/discrimant.rs
+++ b/crates/ide/src/inlay_hints/discriminant.rs
diff --git a/crates/test-utils/src/minicore.rs b/crates/test-utils/src/minicore.rs
index 750b64fea6..3ca63fcab9 100644
--- a/crates/test-utils/src/minicore.rs
+++ b/crates/test-utils/src/minicore.rs
@@ -382,6 +382,12 @@ pub mod ops {
type Output;
fn add(self, rhs: Rhs) -> Self::Output;
}
+
+ #[lang = "add_assign"]
+ #[const_trait]
+ pub trait AddAssign<Rhs = Self> {
+ fn add_assign(&mut self, rhs: Rhs);
+ }
// endregion:add
// region:generator