about summary refs log tree commit diff
path: root/compiler/rustc_trait_selection/src
diff options
context:
space:
mode:
authorBoxy <supbscripter@gmail.com>2024-05-29 17:06:50 +0100
committerBoxy <supbscripter@gmail.com>2024-05-29 17:06:54 +0100
commitd5bd4e233d2bb4415138e384e66379eedbc7e76e (patch)
tree48097f82d6b2ccf2d0f8aec6744f377d16f2bd06 /compiler/rustc_trait_selection/src
parentda159eb331b27df528185c616b394bb0e1d2a4bd (diff)
downloadrust-d5bd4e233d2bb4415138e384e66379eedbc7e76e.tar.gz
rust-d5bd4e233d2bb4415138e384e66379eedbc7e76e.zip
Partially implement `ConstArgHasType`
Diffstat (limited to 'compiler/rustc_trait_selection/src')
-rw-r--r--compiler/rustc_trait_selection/src/solve/mod.rs26
-rw-r--r--compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs16
-rw-r--r--compiler/rustc_trait_selection/src/traits/fulfill.rs41
-rw-r--r--compiler/rustc_trait_selection/src/traits/select/mod.rs19
4 files changed, 89 insertions, 13 deletions
diff --git a/compiler/rustc_trait_selection/src/solve/mod.rs b/compiler/rustc_trait_selection/src/solve/mod.rs
index a432090f78c..f9febd290fe 100644
--- a/compiler/rustc_trait_selection/src/solve/mod.rs
+++ b/compiler/rustc_trait_selection/src/solve/mod.rs
@@ -197,8 +197,30 @@ impl<'a, 'tcx> EvalCtxt<'a, InferCtxt<'tcx>> {
         goal: Goal<'tcx, (ty::Const<'tcx>, Ty<'tcx>)>,
     ) -> QueryResult<'tcx> {
         let (ct, ty) = goal.predicate;
-        self.eq(goal.param_env, ct.ty(), ty)?;
-        self.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
+
+        // FIXME(BoxyUwU): Really we should not be calling `ct.ty()` for any variant
+        // other than `ConstKind::Value`. Unfortunately this would require looking in the
+        // env for any `ConstArgHasType` assumptions for parameters and placeholders. I
+        // have not yet gotten around to implementing this though.
+        //
+        // We do still stall on infer vars though as otherwise a goal like:
+        // `ConstArgHasType(?x: usize, usize)` can succeed even though it might later
+        // get unified with some const that is not of type `usize`.
+        match ct.kind() {
+            // FIXME: Ignore effect vars because canonicalization doesn't handle them correctly
+            // and if we stall on the var then we wind up creating ambiguity errors in a probe
+            // for this goal which contains an effect var. Which then ends up ICEing.
+            ty::ConstKind::Infer(ty::InferConst::Var(_)) => {
+                self.evaluate_added_goals_and_make_canonical_response(Certainty::AMBIGUOUS)
+            }
+            ty::ConstKind::Error(_) => {
+                self.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
+            }
+            _ => {
+                self.eq(goal.param_env, ct.ty(), ty)?;
+                self.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
+            }
+        }
     }
 }
 
diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs
index 46953a61296..7f995b315f7 100644
--- a/compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs
+++ b/compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs
@@ -2685,6 +2685,22 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
                     .with_span_label(span, format!("cannot satisfy `{predicate}`"))
                 }
             }
+
+            // Given some `ConstArgHasType(?x, usize)`, we should not emit an error such as
+            // "type annotations needed: cannot satisfy the constant `_` has type `usize`"
+            // Instead we should emit a normal error suggesting the user to turbofish the
+            // const parameter that is currently being inferred. Unfortunately we cannot
+            // nicely emit such an error so we delay an ICE incase nobody else reports it
+            // for us.
+            ty::PredicateKind::Clause(ty::ClauseKind::ConstArgHasType(ct, ty)) => {
+                return self.tcx.sess.dcx().span_delayed_bug(
+                    span,
+                    format!(
+                        "`ambiguous ConstArgHasType({:?}, {:?}) unaccompanied by inference error`",
+                        ct, ty
+                    ),
+                );
+            }
             _ => {
                 if let Some(e) = self.tainted_by_errors() {
                     return e;
diff --git a/compiler/rustc_trait_selection/src/traits/fulfill.rs b/compiler/rustc_trait_selection/src/traits/fulfill.rs
index 07fcf109fda..c64d1be751c 100644
--- a/compiler/rustc_trait_selection/src/traits/fulfill.rs
+++ b/compiler/rustc_trait_selection/src/traits/fulfill.rs
@@ -429,16 +429,37 @@ impl<'a, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'tcx> {
                 // This is because this is not ever a useful obligation to report
                 // as the cause of an overflow.
                 ty::PredicateKind::Clause(ty::ClauseKind::ConstArgHasType(ct, ty)) => {
-                    match self.selcx.infcx.at(&obligation.cause, obligation.param_env).eq(
-                        // Only really excercised by generic_const_exprs
-                        DefineOpaqueTypes::Yes,
-                        ct.ty(),
-                        ty,
-                    ) {
-                        Ok(inf_ok) => ProcessResult::Changed(mk_pending(inf_ok.into_obligations())),
-                        Err(_) => ProcessResult::Error(FulfillmentErrorCode::Select(
-                            SelectionError::Unimplemented,
-                        )),
+                    // FIXME(BoxyUwU): Really we should not be calling `ct.ty()` for any variant
+                    // other than `ConstKind::Value`. Unfortunately this would require looking in the
+                    // env for any `ConstArgHasType` assumptions for parameters and placeholders. I
+                    // don't really want to implement this in the old solver so I haven't.
+                    //
+                    // We do still stall on infer vars though as otherwise a goal like:
+                    // `ConstArgHasType(?x: usize, usize)` can succeed even though it might later
+                    // get unified with some const that is not of type `usize`.
+                    let ct = self.selcx.infcx.shallow_resolve_const(ct);
+                    match ct.kind() {
+                        ty::ConstKind::Infer(ty::InferConst::Var(vid)) => {
+                            pending_obligation.stalled_on.clear();
+                            pending_obligation.stalled_on.extend([TyOrConstInferVar::Const(vid)]);
+                            ProcessResult::Unchanged
+                        }
+                        ty::ConstKind::Error(_) => return ProcessResult::Changed(vec![]),
+                        _ => {
+                            match self.selcx.infcx.at(&obligation.cause, obligation.param_env).eq(
+                                // Only really excercised by generic_const_exprs
+                                DefineOpaqueTypes::Yes,
+                                ct.ty(),
+                                ty,
+                            ) {
+                                Ok(inf_ok) => {
+                                    ProcessResult::Changed(mk_pending(inf_ok.into_obligations()))
+                                }
+                                Err(_) => ProcessResult::Error(FulfillmentErrorCode::Select(
+                                    SelectionError::Unimplemented,
+                                )),
+                            }
+                        }
                     }
                 }
 
diff --git a/compiler/rustc_trait_selection/src/traits/select/mod.rs b/compiler/rustc_trait_selection/src/traits/select/mod.rs
index 696b1c15115..1f53e8cc671 100644
--- a/compiler/rustc_trait_selection/src/traits/select/mod.rs
+++ b/compiler/rustc_trait_selection/src/traits/select/mod.rs
@@ -992,10 +992,27 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
                 }
                 ty::PredicateKind::Ambiguous => Ok(EvaluatedToAmbig),
                 ty::PredicateKind::Clause(ty::ClauseKind::ConstArgHasType(ct, ty)) => {
+                    // FIXME(BoxyUwU): Really we should not be calling `ct.ty()` for any variant
+                    // other than `ConstKind::Value`. Unfortunately this would require looking in the
+                    // env for any `ConstArgHasType` assumptions for parameters and placeholders. I
+                    // don't really want to implement this in the old solver so I haven't.
+                    //
+                    // We do still stall on infer vars though as otherwise a goal like:
+                    // `ConstArgHasType(?x: usize, usize)` can succeed even though it might later
+                    // get unified with some const that is not of type `usize`.
+                    let ct = self.infcx.shallow_resolve_const(ct);
+                    let ct_ty = match ct.kind() {
+                        ty::ConstKind::Infer(ty::InferConst::Var(_)) => {
+                            return Ok(EvaluatedToAmbig);
+                        }
+                        ty::ConstKind::Error(_) => return Ok(EvaluatedToOk),
+                        _ => ct.ty(),
+                    };
+
                     match self.infcx.at(&obligation.cause, obligation.param_env).eq(
                         // Only really excercised by generic_const_exprs
                         DefineOpaqueTypes::Yes,
-                        ct.ty(),
+                        ct_ty,
                         ty,
                     ) {
                         Ok(inf_ok) => self.evaluate_predicates_recursively(