Skip to content

Commit c951676

Browse files
committed
Partially implement ConstArgHasType
1 parent 71213fd commit c951676

23 files changed

+156
-275
lines changed

compiler/rustc_infer/src/infer/relate/combine.rs

+1-8
Original file line numberDiff line numberDiff line change
@@ -22,11 +22,10 @@ use super::glb::Glb;
2222
use super::lub::Lub;
2323
use super::type_relating::TypeRelating;
2424
use super::StructurallyRelateAliases;
25-
use crate::infer::{DefineOpaqueTypes, InferCtxt, InferOk, TypeTrace};
25+
use crate::infer::{DefineOpaqueTypes, InferCtxt, TypeTrace};
2626
use crate::traits::{Obligation, PredicateObligations};
2727
use rustc_middle::bug;
2828
use rustc_middle::infer::unify_key::EffectVarValue;
29-
use rustc_middle::traits::ObligationCause;
3029
use rustc_middle::ty::error::{ExpectedFound, TypeError};
3130
use rustc_middle::ty::relate::{RelateResult, TypeRelation};
3231
use rustc_middle::ty::{self, InferConst, Ty, TyCtxt, TypeVisitableExt, Upcast};
@@ -159,12 +158,6 @@ impl<'tcx> InferCtxt<'tcx> {
159158
let a = self.shallow_resolve_const(a);
160159
let b = self.shallow_resolve_const(b);
161160

162-
// It is always an error if the types of two constants that are related are not equal.
163-
let InferOk { value: (), obligations } = self
164-
.at(&ObligationCause::dummy_with_span(relation.span()), relation.param_env())
165-
.eq(DefineOpaqueTypes::No, a.ty(), b.ty())?;
166-
relation.register_obligations(obligations);
167-
168161
match (a.kind(), b.kind()) {
169162
(
170163
ty::ConstKind::Infer(InferConst::Var(a_vid)),

compiler/rustc_trait_selection/src/solve/mod.rs

+24-2
Original file line numberDiff line numberDiff line change
@@ -197,8 +197,30 @@ impl<'a, 'tcx> EvalCtxt<'a, InferCtxt<'tcx>> {
197197
goal: Goal<'tcx, (ty::Const<'tcx>, Ty<'tcx>)>,
198198
) -> QueryResult<'tcx> {
199199
let (ct, ty) = goal.predicate;
200-
self.eq(goal.param_env, ct.ty(), ty)?;
201-
self.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
200+
201+
// FIXME(BoxyUwU): Really we should not be calling `ct.ty()` for any variant
202+
// other than `ConstKind::Value`. Unfortunately this would require looking in the
203+
// env for any `ConstArgHasType` assumptions for parameters and placeholders. I
204+
// have not yet gotten around to implementing this though.
205+
//
206+
// We do still stall on infer vars though as otherwise a goal like:
207+
// `ConstArgHasType(?x: usize, usize)` can succeed even though it might later
208+
// get unified with some const that is not of type `usize`.
209+
match ct.kind() {
210+
// FIXME: Ignore effect vars because canonicalization doesn't handle them correctly
211+
// and if we stall on the var then we wind up creating ambiguity errors in a probe
212+
// for this goal which contains an effect var. Which then ends up ICEing.
213+
ty::ConstKind::Infer(ty::InferConst::Var(_)) => {
214+
self.evaluate_added_goals_and_make_canonical_response(Certainty::AMBIGUOUS)
215+
}
216+
ty::ConstKind::Error(_) => {
217+
self.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
218+
}
219+
_ => {
220+
self.eq(goal.param_env, ct.ty(), ty)?;
221+
self.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
222+
}
223+
}
202224
}
203225
}
204226

compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs

+16
Original file line numberDiff line numberDiff line change
@@ -2685,6 +2685,22 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
26852685
.with_span_label(span, format!("cannot satisfy `{predicate}`"))
26862686
}
26872687
}
2688+
2689+
// Given some `ConstArgHasType(?x, usize)`, we should not emit an error such as
2690+
// "type annotations needed: cannot satisfy the constant `_` has type `usize`"
2691+
// Instead we should emit a normal error suggesting the user to turbofish the
2692+
// const parameter that is currently being inferred. Unfortunately we cannot
2693+
// nicely emit such an error so we delay an ICE incase nobody else reports it
2694+
// for us.
2695+
ty::PredicateKind::Clause(ty::ClauseKind::ConstArgHasType(ct, ty)) => {
2696+
return self.tcx.sess.dcx().span_delayed_bug(
2697+
span,
2698+
format!(
2699+
"`ambiguous ConstArgHasType({:?}, {:?}) unaccompanied by inference error`",
2700+
ct, ty
2701+
),
2702+
);
2703+
}
26882704
_ => {
26892705
if let Some(e) = self.tainted_by_errors() {
26902706
return e;

compiler/rustc_trait_selection/src/traits/fulfill.rs

+38-10
Original file line numberDiff line numberDiff line change
@@ -429,16 +429,44 @@ impl<'a, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'tcx> {
429429
// This is because this is not ever a useful obligation to report
430430
// as the cause of an overflow.
431431
ty::PredicateKind::Clause(ty::ClauseKind::ConstArgHasType(ct, ty)) => {
432-
match self.selcx.infcx.at(&obligation.cause, obligation.param_env).eq(
433-
// Only really excercised by generic_const_exprs
434-
DefineOpaqueTypes::Yes,
435-
ct.ty(),
436-
ty,
437-
) {
438-
Ok(inf_ok) => ProcessResult::Changed(mk_pending(inf_ok.into_obligations())),
439-
Err(_) => ProcessResult::Error(FulfillmentErrorCode::Select(
440-
SelectionError::Unimplemented,
441-
)),
432+
// FIXME(BoxyUwU): Really we should not be calling `ct.ty()` for any variant
433+
// other than `ConstKind::Value`. Unfortunately this would require looking in the
434+
// env for any `ConstArgHasType` assumptions for parameters and placeholders. I
435+
// don't really want to implement this in the old solver so I haven't.
436+
//
437+
// We do still stall on infer vars though as otherwise a goal like:
438+
// `ConstArgHasType(?x: usize, usize)` can succeed even though it might later
439+
// get unified with some const that is not of type `usize`.
440+
let (ct, ty) = self.selcx.infcx.resolve_vars_if_possible((ct, ty));
441+
match ct.kind() {
442+
ty::ConstKind::Infer(inf) => {
443+
pending_obligation.stalled_on.clear();
444+
let inf = match inf {
445+
ty::InferConst::Var(vid) => TyOrConstInferVar::Const(vid),
446+
ty::InferConst::EffectVar(vid) => TyOrConstInferVar::Effect(vid),
447+
ty::InferConst::Fresh(_) => {
448+
bug!("encountered fresh {:?} in fulfill", ct)
449+
}
450+
};
451+
pending_obligation.stalled_on.extend([inf]);
452+
ProcessResult::Unchanged
453+
}
454+
ty::ConstKind::Error(_) => return ProcessResult::Changed(vec![]),
455+
_ => {
456+
match self.selcx.infcx.at(&obligation.cause, obligation.param_env).eq(
457+
// Only really excercised by generic_const_exprs
458+
DefineOpaqueTypes::Yes,
459+
ct.ty(),
460+
ty,
461+
) {
462+
Ok(inf_ok) => {
463+
ProcessResult::Changed(mk_pending(inf_ok.into_obligations()))
464+
}
465+
Err(_) => ProcessResult::Error(FulfillmentErrorCode::Select(
466+
SelectionError::Unimplemented,
467+
)),
468+
}
469+
}
442470
}
443471
}
444472

compiler/rustc_trait_selection/src/traits/select/mod.rs

+16-1
Original file line numberDiff line numberDiff line change
@@ -992,10 +992,25 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
992992
}
993993
ty::PredicateKind::Ambiguous => Ok(EvaluatedToAmbig),
994994
ty::PredicateKind::Clause(ty::ClauseKind::ConstArgHasType(ct, ty)) => {
995+
// FIXME(BoxyUwU): Really we should not be calling `ct.ty()` for any variant
996+
// other than `ConstKind::Value`. Unfortunately this would require looking in the
997+
// env for any `ConstArgHasType` assumptions for parameters and placeholders. I
998+
// don't really want to implement this in the old solver so I haven't.
999+
//
1000+
// We do still stall on infer vars though as otherwise a goal like:
1001+
// `ConstArgHasType(?x: usize, usize)` can succeed even though it might later
1002+
// get unified with some const that is not of type `usize`.
1003+
let (ct, ty) = self.infcx.resolve_vars_if_possible((ct, ty));
1004+
let ct_ty = match ct.kind() {
1005+
ty::ConstKind::Infer(_) => return Ok(EvaluatedToAmbig),
1006+
ty::ConstKind::Error(_) => return Ok(EvaluatedToOk),
1007+
_ => ct.ty(),
1008+
};
1009+
9951010
match self.infcx.at(&obligation.cause, obligation.param_env).eq(
9961011
// Only really excercised by generic_const_exprs
9971012
DefineOpaqueTypes::Yes,
998-
ct.ty(),
1013+
ct_ty,
9991014
ty,
10001015
) {
10011016
Ok(inf_ok) => self.evaluate_predicates_recursively(
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,14 @@
1+
//@ known-bug: #121858
12
#![feature(generic_const_exprs)]
2-
#![allow(incomplete_features)]
33

44
struct Outer<const A: i64, const B: usize>();
55
impl<const A: usize, const B: usize> Outer<A, B>
6-
//~^ ERROR: `A` is not of type `i64`
7-
//~| ERROR: mismatched types
86
where
97
[(); A + (B * 2)]:,
108
{
11-
fn o() {}
9+
fn o() -> Union {}
1210
}
1311

1412
fn main() {
1513
Outer::<1, 1>::o();
16-
//~^ ERROR: no function or associated item named `o` found
1714
}

tests/ui/coherence/negative-coherence/generic_const_type_mismatch.rs

+1
Original file line numberDiff line numberDiff line change
@@ -8,5 +8,6 @@ impl<const N: u8> Trait for [(); N] {}
88
//~^ ERROR: mismatched types
99
impl<const N: i8> Trait for [(); N] {}
1010
//~^ ERROR: mismatched types
11+
//~| ERROR: conflicting implementations of trait `Trait`
1112

1213
fn main() {}

tests/ui/coherence/negative-coherence/generic_const_type_mismatch.stderr

+12-2
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,12 @@
1+
error[E0119]: conflicting implementations of trait `Trait` for type `[(); _]`
2+
--> $DIR/generic_const_type_mismatch.rs:9:1
3+
|
4+
LL | impl<const N: u8> Trait for [(); N] {}
5+
| ----------------------------------- first implementation here
6+
LL |
7+
LL | impl<const N: i8> Trait for [(); N] {}
8+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `[(); _]`
9+
110
error[E0308]: mismatched types
211
--> $DIR/generic_const_type_mismatch.rs:7:34
312
|
@@ -10,6 +19,7 @@ error[E0308]: mismatched types
1019
LL | impl<const N: i8> Trait for [(); N] {}
1120
| ^ expected `usize`, found `i8`
1221

13-
error: aborting due to 2 previous errors
22+
error: aborting due to 3 previous errors
1423

15-
For more information about this error, try `rustc --explain E0308`.
24+
Some errors have detailed explanations: E0119, E0308.
25+
For more information about an error, try `rustc --explain E0119`.

tests/ui/const-generics/bad-subst-const-kind.rs

+4-2
Original file line numberDiff line numberDiff line change
@@ -10,5 +10,7 @@ impl<const N: u64> Q for [u8; N] {
1010
const ASSOC: usize = 1;
1111
}
1212

13-
pub fn test() -> [u8; <[u8; 13] as Q>::ASSOC] { todo!() }
14-
//~^ ERROR: `[u8; 13]: Q` is not satisfied
13+
pub fn test() -> [u8; <[u8; 13] as Q>::ASSOC] {
14+
//~^ ERROR: the constant `13` is not of type `u64`
15+
todo!()
16+
}
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,16 @@
1-
error[E0277]: the trait bound `[u8; 13]: Q` is not satisfied
1+
error: the constant `13` is not of type `u64`
22
--> $DIR/bad-subst-const-kind.rs:13:24
33
|
4-
LL | pub fn test() -> [u8; <[u8; 13] as Q>::ASSOC] { todo!() }
5-
| ^^^^^^^^ the trait `Q` is not implemented for `[u8; 13]`
4+
LL | pub fn test() -> [u8; <[u8; 13] as Q>::ASSOC] {
5+
| ^^^^^^^^ expected `u64`, found `usize`
66
|
7-
= help: the trait `Q` is implemented for `[u8; N]`
7+
note: required for `[u8; 13]` to implement `Q`
8+
--> $DIR/bad-subst-const-kind.rs:8:20
9+
|
10+
LL | impl<const N: u64> Q for [u8; N] {
11+
| ------------ ^ ^^^^^^^
12+
| |
13+
| unsatisfied trait bound introduced here
814

915
error[E0308]: mismatched types
1016
--> $DIR/bad-subst-const-kind.rs:8:31
@@ -14,5 +20,4 @@ LL | impl<const N: u64> Q for [u8; N] {
1420

1521
error: aborting due to 2 previous errors
1622

17-
Some errors have detailed explanations: E0277, E0308.
18-
For more information about an error, try `rustc --explain E0277`.
23+
For more information about this error, try `rustc --explain E0308`.

tests/ui/const-generics/defaults/doesnt_infer.rs

+3-1
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,9 @@
33
struct Foo<const N: u32 = 2>;
44

55
impl<const N: u32> Foo<N> {
6-
fn foo() -> Self { loop {} }
6+
fn foo() -> Self {
7+
loop {}
8+
}
79
}
810

911
fn main() {

tests/ui/const-generics/defaults/doesnt_infer.stderr

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
error[E0282]: type annotations needed for `Foo<_>`
2-
--> $DIR/doesnt_infer.rs:11:9
2+
--> $DIR/doesnt_infer.rs:13:9
33
|
44
LL | let foo = Foo::foo();
55
| ^^^

tests/ui/const-generics/generic_arg_infer/issue-91614.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -4,5 +4,5 @@ use std::simd::Mask;
44

55
fn main() {
66
let y = Mask::<_, _>::splat(false);
7-
//~^ ERROR: type annotations needed for
7+
//~^ ERROR: type annotations needed
88
}

tests/ui/const-generics/generic_const_exprs/ice-125520-layout-mismatch-mulwithoverflow.rs

-27
This file was deleted.

0 commit comments

Comments
 (0)