about summary refs log tree commit diff
diff options
context:
space:
mode:
authorMichael Goulet <michael@errs.io>2024-10-15 13:20:41 -0400
committerMichael Goulet <michael@errs.io>2024-10-15 20:44:39 -0400
commitb4e9aad137800936b4fbc3c36da6ff2819b385b5 (patch)
tree48837ae160995496b8b16feb752781f6dce6a2dd
parente7c0d2750726c1f08b1de6956248ec78c4a97af6 (diff)
downloadrust-b4e9aad137800936b4fbc3c36da6ff2819b385b5.tar.gz
rust-b4e9aad137800936b4fbc3c36da6ff2819b385b5.zip
Rename can_coerce to may_coerce
-rw-r--r--compiler/rustc_hir_typeck/src/_match.rs4
-rw-r--r--compiler/rustc_hir_typeck/src/cast.rs8
-rw-r--r--compiler/rustc_hir_typeck/src/coercion.rs17
-rw-r--r--compiler/rustc_hir_typeck/src/expr.rs10
-rw-r--r--compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs10
-rw-r--r--compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs34
-rw-r--r--compiler/rustc_hir_typeck/src/method/suggest.rs4
-rw-r--r--compiler/rustc_hir_typeck/src/pat.rs2
8 files changed, 46 insertions, 43 deletions
diff --git a/compiler/rustc_hir_typeck/src/_match.rs b/compiler/rustc_hir_typeck/src/_match.rs
index 0d9d1910ae0..e68caa3e2e3 100644
--- a/compiler/rustc_hir_typeck/src/_match.rs
+++ b/compiler/rustc_hir_typeck/src/_match.rs
@@ -235,8 +235,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             Some(ret_coercion) => {
                 let ret_ty = ret_coercion.borrow().expected_ty();
                 let ret_ty = self.infcx.shallow_resolve(ret_ty);
-                self.can_coerce(arm_ty, ret_ty)
-                    && prior_arm.is_none_or(|(_, ty, _)| self.can_coerce(ty, ret_ty))
+                self.may_coerce(arm_ty, ret_ty)
+                    && prior_arm.is_none_or(|(_, ty, _)| self.may_coerce(ty, ret_ty))
                     // The match arms need to unify for the case of `impl Trait`.
                     && !matches!(ret_ty.kind(), ty::Alias(ty::Opaque, ..))
             }
diff --git a/compiler/rustc_hir_typeck/src/cast.rs b/compiler/rustc_hir_typeck/src/cast.rs
index 407191661a4..8fa6ab8503d 100644
--- a/compiler/rustc_hir_typeck/src/cast.rs
+++ b/compiler/rustc_hir_typeck/src/cast.rs
@@ -409,7 +409,7 @@ impl<'a, 'tcx> CastCheck<'tcx> {
                 let mut sugg_mutref = false;
                 if let ty::Ref(reg, cast_ty, mutbl) = *self.cast_ty.kind() {
                     if let ty::RawPtr(expr_ty, _) = *self.expr_ty.kind()
-                        && fcx.can_coerce(
+                        && fcx.may_coerce(
                             Ty::new_ref(fcx.tcx, fcx.tcx.lifetimes.re_erased, expr_ty, mutbl),
                             self.cast_ty,
                         )
@@ -418,14 +418,14 @@ impl<'a, 'tcx> CastCheck<'tcx> {
                     } else if let ty::Ref(expr_reg, expr_ty, expr_mutbl) = *self.expr_ty.kind()
                         && expr_mutbl == Mutability::Not
                         && mutbl == Mutability::Mut
-                        && fcx.can_coerce(Ty::new_mut_ref(fcx.tcx, expr_reg, expr_ty), self.cast_ty)
+                        && fcx.may_coerce(Ty::new_mut_ref(fcx.tcx, expr_reg, expr_ty), self.cast_ty)
                     {
                         sugg_mutref = true;
                     }
 
                     if !sugg_mutref
                         && sugg == None
-                        && fcx.can_coerce(
+                        && fcx.may_coerce(
                             Ty::new_ref(fcx.tcx, reg, self.expr_ty, mutbl),
                             self.cast_ty,
                         )
@@ -433,7 +433,7 @@ impl<'a, 'tcx> CastCheck<'tcx> {
                         sugg = Some((format!("&{}", mutbl.prefix_str()), false));
                     }
                 } else if let ty::RawPtr(_, mutbl) = *self.cast_ty.kind()
-                    && fcx.can_coerce(
+                    && fcx.may_coerce(
                         Ty::new_ref(fcx.tcx, fcx.tcx.lifetimes.re_erased, self.expr_ty, mutbl),
                         self.cast_ty,
                     )
diff --git a/compiler/rustc_hir_typeck/src/coercion.rs b/compiler/rustc_hir_typeck/src/coercion.rs
index bd0b9870298..a6df9e45db5 100644
--- a/compiler/rustc_hir_typeck/src/coercion.rs
+++ b/compiler/rustc_hir_typeck/src/coercion.rs
@@ -1083,21 +1083,24 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         })
     }
 
-    /// Same as `coerce()`, but without side-effects.
+    /// Probe whether `expr_ty` can be coerced to `target_ty`. This has no side-effects,
+    /// and may return false positives if types are not yet fully constrained by inference.
     ///
-    /// Returns false if the coercion creates any obligations that result in
-    /// errors.
-    pub(crate) fn can_coerce(&self, expr_ty: Ty<'tcx>, target: Ty<'tcx>) -> bool {
+    /// Returns false if the coercion is not possible, or if the coercion creates any
+    /// sub-obligations that result in errors.
+    ///
+    /// This should only be used for diagnostics.
+    pub(crate) fn may_coerce(&self, expr_ty: Ty<'tcx>, target_ty: Ty<'tcx>) -> bool {
         // FIXME(-Znext-solver): We need to structurally resolve both types here.
         let source = self.resolve_vars_with_obligations(expr_ty);
-        debug!("coercion::can_with_predicates({:?} -> {:?})", source, target);
+        debug!("coercion::can_with_predicates({:?} -> {:?})", source, target_ty);
 
         let cause = self.cause(DUMMY_SP, ObligationCauseCode::ExprAssignable);
         // We don't ever need two-phase here since we throw out the result of the coercion.
         // We also just always set `coerce_never` to true, since this is a heuristic.
         let coerce = Coerce::new(self, cause, AllowTwoPhase::No, true);
         self.probe(|_| {
-            let Ok(ok) = coerce.coerce(source, target) else {
+            let Ok(ok) = coerce.coerce(source, target_ty) else {
                 return false;
             };
             let ocx = ObligationCtxt::new(self);
@@ -1369,7 +1372,7 @@ pub fn can_coerce<'tcx>(
 ) -> bool {
     let root_ctxt = crate::typeck_root_ctxt::TypeckRootCtxt::new(tcx, body_id);
     let fn_ctxt = FnCtxt::new(&root_ctxt, param_env, body_id);
-    fn_ctxt.can_coerce(ty, output_ty)
+    fn_ctxt.may_coerce(ty, output_ty)
 }
 
 /// CoerceMany encapsulates the pattern you should use when you have
diff --git a/compiler/rustc_hir_typeck/src/expr.rs b/compiler/rustc_hir_typeck/src/expr.rs
index b310398a0f1..7bdd3c95ad1 100644
--- a/compiler/rustc_hir_typeck/src/expr.rs
+++ b/compiler/rustc_hir_typeck/src/expr.rs
@@ -1330,9 +1330,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             let refs_can_coerce = |lhs: Ty<'tcx>, rhs: Ty<'tcx>| {
                 let lhs = Ty::new_imm_ref(self.tcx, self.tcx.lifetimes.re_erased, lhs.peel_refs());
                 let rhs = Ty::new_imm_ref(self.tcx, self.tcx.lifetimes.re_erased, rhs.peel_refs());
-                self.can_coerce(rhs, lhs)
+                self.may_coerce(rhs, lhs)
             };
-            let (applicability, eq) = if self.can_coerce(rhs_ty, lhs_ty) {
+            let (applicability, eq) = if self.may_coerce(rhs_ty, lhs_ty) {
                 (Applicability::MachineApplicable, true)
             } else if refs_can_coerce(rhs_ty, lhs_ty) {
                 // The lhs and rhs are likely missing some references in either side. Subsequent
@@ -1349,7 +1349,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 let actual_lhs_ty = self.check_expr(rhs_expr);
                 (
                     Applicability::MaybeIncorrect,
-                    self.can_coerce(rhs_ty, actual_lhs_ty)
+                    self.may_coerce(rhs_ty, actual_lhs_ty)
                         || refs_can_coerce(rhs_ty, actual_lhs_ty),
                 )
             } else if let ExprKind::Binary(
@@ -1363,7 +1363,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 let actual_rhs_ty = self.check_expr(lhs_expr);
                 (
                     Applicability::MaybeIncorrect,
-                    self.can_coerce(actual_rhs_ty, lhs_ty)
+                    self.may_coerce(actual_rhs_ty, lhs_ty)
                         || refs_can_coerce(actual_rhs_ty, lhs_ty),
                 )
             } else {
@@ -1414,7 +1414,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                         self.param_env,
                     )
                     .may_apply();
-                if lhs_deref_ty_is_sized && self.can_coerce(rhs_ty, lhs_deref_ty) {
+                if lhs_deref_ty_is_sized && self.may_coerce(rhs_ty, lhs_deref_ty) {
                     err.span_suggestion_verbose(
                         lhs.span.shrink_to_lo(),
                         "consider dereferencing here to assign to the mutably borrowed value",
diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs
index fa471647d02..660cbc29d4c 100644
--- a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs
+++ b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs
@@ -658,7 +658,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 && fn_sig.inputs()[1..]
                     .iter()
                     .zip(input_types.iter())
-                    .all(|(expected, found)| self.can_coerce(*expected, *found))
+                    .all(|(expected, found)| self.may_coerce(*expected, *found))
                 && fn_sig.inputs()[1..].len() == input_types.len()
             {
                 err.span_suggestion_verbose(
@@ -722,7 +722,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
 
             let expectation = Expectation::rvalue_hint(self, expected_input_ty);
             let coerced_ty = expectation.only_has_type(self).unwrap_or(formal_input_ty);
-            let can_coerce = self.can_coerce(arg_ty, coerced_ty);
+            let can_coerce = self.may_coerce(arg_ty, coerced_ty);
             if !can_coerce {
                 return Compatibility::Incompatible(Some(ty::error::TypeError::Sorts(
                     ty::error::ExpectedFound::new(true, coerced_ty, arg_ty),
@@ -802,7 +802,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                         provided_arg_tys.iter().map(|(ty, _)| *ty).skip(mismatch_idx + tys.len()),
                     ),
                 ) {
-                    if !self.can_coerce(provided_ty, *expected_ty) {
+                    if !self.may_coerce(provided_ty, *expected_ty) {
                         satisfied = false;
                         break;
                     }
@@ -1023,7 +1023,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 std::iter::zip(formal_and_expected_inputs.iter(), removed_arg_tys.iter()).all(
                     |((expected_ty, _), (provided_ty, _))| {
                         !provided_ty.references_error()
-                            && self.can_coerce(*provided_ty, *expected_ty)
+                            && self.may_coerce(*provided_ty, *expected_ty)
                     },
                 )
             };
@@ -2124,7 +2124,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                                     let expr_ty = self.typeck_results.borrow().expr_ty(expr);
                                     let return_ty = fn_sig.output();
                                     if !matches!(expr.kind, hir::ExprKind::Ret(..))
-                                        && self.can_coerce(expr_ty, return_ty)
+                                        && self.may_coerce(expr_ty, return_ty)
                                     {
                                         found_semi = true;
                                     }
diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs
index 3e9e5326156..3f703c2fcf6 100644
--- a/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs
+++ b/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs
@@ -261,7 +261,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         if let hir::ExprKind::MethodCall(hir::PathSegment { ident: method, .. }, recv_expr, &[], _) =
             expr.kind
             && let Some(recv_ty) = self.typeck_results.borrow().expr_ty_opt(recv_expr)
-            && self.can_coerce(recv_ty, expected)
+            && self.may_coerce(recv_ty, expected)
             && let name = method.name.as_str()
             && (name.starts_with("to_") || name.starts_with("as_") || name == "into")
         {
@@ -349,7 +349,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             return true;
         }
 
-        if self.suggest_fn_call(err, expr, found, |output| self.can_coerce(output, expected))
+        if self.suggest_fn_call(err, expr, found, |output| self.may_coerce(output, expected))
             && let ty::FnDef(def_id, ..) = *found.kind()
             && let Some(sp) = self.tcx.hir().span_if_local(def_id)
         {
@@ -568,7 +568,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         if self.tcx.hir().is_inside_const_context(hir_id) || !expected.is_box() || found.is_box() {
             return false;
         }
-        if self.can_coerce(Ty::new_box(self.tcx, found), expected) {
+        if self.may_coerce(Ty::new_box(self.tcx, found), expected) {
             let suggest_boxing = match found.kind() {
                 ty::Tuple(tuple) if tuple.is_empty() => {
                     errors::SuggestBoxing::Unit { start: span.shrink_to_lo(), end: span }
@@ -663,7 +663,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         };
         match expected.kind() {
             ty::Adt(def, _) if Some(def.did()) == pin_did => {
-                if self.can_coerce(pin_box_found, expected) {
+                if self.may_coerce(pin_box_found, expected) {
                     debug!("can coerce {:?} to {:?}, suggesting Box::pin", pin_box_found, expected);
                     match found.kind() {
                         ty::Adt(def, _) if def.is_box() => {
@@ -689,7 +689,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                         }
                     }
                     true
-                } else if self.can_coerce(pin_found, expected) {
+                } else if self.may_coerce(pin_found, expected) {
                     match found.kind() {
                         ty::Adt(def, _) if def.is_box() => {
                             err.help("use `Box::pin`");
@@ -701,7 +701,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                     false
                 }
             }
-            ty::Adt(def, _) if def.is_box() && self.can_coerce(box_found, expected) => {
+            ty::Adt(def, _) if def.is_box() && self.may_coerce(box_found, expected) => {
                 // Check if the parent expression is a call to Pin::new. If it
                 // is and we were expecting a Box, ergo Pin<Box<expected>>, we
                 // can suggest Box::pin.
@@ -884,7 +884,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                     let ty = Binder::bind_with_vars(ty, bound_vars);
                     let ty = self.normalize(hir_ty.span, ty);
                     let ty = self.tcx.instantiate_bound_regions_with_erased(ty);
-                    if self.can_coerce(expected, ty) {
+                    if self.may_coerce(expected, ty) {
                         err.subdiagnostic(errors::ExpectedReturnTypeLabel::Other {
                             span: hir_ty.span,
                             expected,
@@ -1141,12 +1141,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                     ty::Asyncness::No => ty,
                 };
                 let ty = self.normalize(expr.span, ty);
-                self.can_coerce(found, ty)
+                self.may_coerce(found, ty)
             }
             hir::FnRetTy::DefaultReturn(_) if in_closure => {
                 self.ret_coercion.as_ref().map_or(false, |ret| {
                     let ret_ty = ret.borrow().expected_ty();
-                    self.can_coerce(found, ret_ty)
+                    self.may_coerce(found, ret_ty)
                 })
             }
             _ => false,
@@ -1510,7 +1510,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             provided_ty
         };
 
-        if !self.can_coerce(expected_ty, dummy_ty) {
+        if !self.may_coerce(expected_ty, dummy_ty) {
             return;
         }
         let msg = format!("use `{adt_name}::map_or` to deref inner value of `{adt_name}`");
@@ -1534,7 +1534,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         expected_ty: Ty<'tcx>,
     ) {
         if let ty::Slice(elem_ty) | ty::Array(elem_ty, _) = expected_ty.kind() {
-            if self.can_coerce(blk_ty, *elem_ty)
+            if self.may_coerce(blk_ty, *elem_ty)
                 && blk.stmts.is_empty()
                 && blk.rules == hir::BlockCheckMode::DefaultBlock
             {
@@ -1744,7 +1744,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         if item_ty.has_param() {
             return false;
         }
-        if self.can_coerce(item_ty, expected_ty) {
+        if self.may_coerce(item_ty, expected_ty) {
             err.span_suggestion_verbose(
                 segment.ident.span,
                 format!("try referring to the associated const `{capitalized_name}` instead",),
@@ -1804,7 +1804,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             // diagnostic in cases where we have `(&&T).clone()` and we expect `T`).
             && !results.expr_adjustments(callee_expr).iter().any(|adj| matches!(adj.kind, ty::adjustment::Adjust::Deref(..)))
             // Check that we're in fact trying to clone into the expected type
-            && self.can_coerce(*pointee_ty, expected_ty)
+            && self.may_coerce(*pointee_ty, expected_ty)
             && let trait_ref = ty::TraitRef::new(self.tcx, clone_trait_did, [expected_ty])
             // And the expected type doesn't implement `Clone`
             && !self.predicate_must_hold_considering_regions(&traits::Obligation::new(
@@ -2022,7 +2022,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             } else {
                 return false;
             };
-        if is_ctor || !self.can_coerce(args.type_at(0), expected) {
+        if is_ctor || !self.may_coerce(args.type_at(0), expected) {
             return false;
         }
 
@@ -2293,7 +2293,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                         .then(|| " (its field is private, but it's local to this crate and its privacy can be changed)".to_string());
 
                     let sole_field_ty = sole_field.ty(self.tcx, args);
-                    if self.can_coerce(expr_ty, sole_field_ty) {
+                    if self.may_coerce(expr_ty, sole_field_ty) {
                         let variant_path =
                             with_no_trimmed_paths!(self.tcx.def_path_str(variant.def_id));
                         // FIXME #56861: DRYer prelude filtering
@@ -2401,7 +2401,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         }
 
         let int_type = args.type_at(0);
-        if !self.can_coerce(expr_ty, int_type) {
+        if !self.may_coerce(expr_ty, int_type) {
             return false;
         }
 
@@ -2585,7 +2585,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                         Ty::new_imm_ref(self.tcx, self.tcx.lifetimes.re_static, checked_ty)
                     }
                 };
-                if self.can_coerce(ref_ty, expected) {
+                if self.may_coerce(ref_ty, expected) {
                     let mut sugg_sp = sp;
                     if let hir::ExprKind::MethodCall(segment, receiver, args, _) = expr.kind {
                         let clone_trait =
diff --git a/compiler/rustc_hir_typeck/src/method/suggest.rs b/compiler/rustc_hir_typeck/src/method/suggest.rs
index 7f68e19a313..9dd59541148 100644
--- a/compiler/rustc_hir_typeck/src/method/suggest.rs
+++ b/compiler/rustc_hir_typeck/src/method/suggest.rs
@@ -1934,7 +1934,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                             && fn_sig.inputs()[1..]
                                 .iter()
                                 .zip(args.into_iter())
-                                .all(|(expected, found)| self.can_coerce(*expected, *found))
+                                .all(|(expected, found)| self.may_coerce(*expected, *found))
                             && fn_sig.inputs()[1..].len() == args.len()
                         {
                             err.span_suggestion_verbose(
@@ -4148,7 +4148,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             return false;
         };
 
-        if !self.can_coerce(output, expected) {
+        if !self.may_coerce(output, expected) {
             return false;
         }
 
diff --git a/compiler/rustc_hir_typeck/src/pat.rs b/compiler/rustc_hir_typeck/src/pat.rs
index fb78da0a86c..5ce9bae81c1 100644
--- a/compiler/rustc_hir_typeck/src/pat.rs
+++ b/compiler/rustc_hir_typeck/src/pat.rs
@@ -1767,7 +1767,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 } else if inexistent_fields.len() == 1 {
                     match pat_field.pat.kind {
                         PatKind::Lit(expr)
-                            if !self.can_coerce(
+                            if !self.may_coerce(
                                 self.typeck_results.borrow().expr_ty(expr),
                                 self.field_ty(field.span, field_def, args),
                             ) => {}