Skip to content

Commit d5bd4e2

Browse files
committed
Partially implement ConstArgHasType
1 parent da159eb commit d5bd4e2

30 files changed

+206
-327
lines changed

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

Lines changed: 1 addition & 8 deletions
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

Lines changed: 24 additions & 2 deletions
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

Lines changed: 16 additions & 0 deletions
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

Lines changed: 31 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -429,16 +429,37 @@ 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 = self.selcx.infcx.shallow_resolve_const(ct);
441+
match ct.kind() {
442+
ty::ConstKind::Infer(ty::InferConst::Var(vid)) => {
443+
pending_obligation.stalled_on.clear();
444+
pending_obligation.stalled_on.extend([TyOrConstInferVar::Const(vid)]);
445+
ProcessResult::Unchanged
446+
}
447+
ty::ConstKind::Error(_) => return ProcessResult::Changed(vec![]),
448+
_ => {
449+
match self.selcx.infcx.at(&obligation.cause, obligation.param_env).eq(
450+
// Only really excercised by generic_const_exprs
451+
DefineOpaqueTypes::Yes,
452+
ct.ty(),
453+
ty,
454+
) {
455+
Ok(inf_ok) => {
456+
ProcessResult::Changed(mk_pending(inf_ok.into_obligations()))
457+
}
458+
Err(_) => ProcessResult::Error(FulfillmentErrorCode::Select(
459+
SelectionError::Unimplemented,
460+
)),
461+
}
462+
}
442463
}
443464
}
444465

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

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -992,10 +992,27 @@ 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 = self.infcx.shallow_resolve_const(ct);
1004+
let ct_ty = match ct.kind() {
1005+
ty::ConstKind::Infer(ty::InferConst::Var(_)) => {
1006+
return Ok(EvaluatedToAmbig);
1007+
}
1008+
ty::ConstKind::Error(_) => return Ok(EvaluatedToOk),
1009+
_ => ct.ty(),
1010+
};
1011+
9951012
match self.infcx.at(&obligation.cause, obligation.param_env).eq(
9961013
// Only really excercised by generic_const_exprs
9971014
DefineOpaqueTypes::Yes,
998-
ct.ty(),
1015+
ct_ty,
9991016
ty,
10001017
) {
10011018
Ok(inf_ok) => self.evaluate_predicates_recursively(
Lines changed: 2 additions & 5 deletions
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/crashes/122638.rs

Lines changed: 0 additions & 12 deletions
This file was deleted.

tests/crashes/123141-2.rs

Lines changed: 0 additions & 23 deletions
This file was deleted.

tests/crashes/123141.rs

Lines changed: 14 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,23 @@
11
//@ known-bug: #123141
2-
trait ConstChunksExactTrait<T> {
3-
fn const_chunks_exact<const N: usize>(&self) -> ConstChunksExact<'_, T, { N }>;
2+
3+
trait Trait {
4+
fn next(self) -> Self::Item;
5+
type Item;
46
}
57

6-
impl<T> ConstChunksExactTrait<T> for [T] {}
8+
struct Foo<T: ?Sized>(T);
79

8-
struct ConstChunksExact<'a, T: 'a, const N: usize> {}
10+
impl<T: ?Sized, U> Trait for Foo<U> {
11+
type Item = Foo<T>;
12+
fn next(self) -> Self::Item {
13+
loop {}
14+
}
15+
}
916

10-
impl<'a, T, const N: usize> Iterator for ConstChunksExact<'a, T, { rem }> {
11-
type Item = &'a [T; N];
17+
fn opaque() -> impl Trait {
18+
Foo::<_>(10_u32)
1219
}
1320

1421
fn main() {
15-
let slice = &[1i32, 2, 3, 4, 5, 6, 7, 7, 9, 1i32];
16-
17-
let mut iter = [[1, 2, 3], [4, 5, 6], [7, 8, 9]].iter();
18-
19-
for a in slice.const_chunks_exact::<3>() {
20-
assert_eq!(a, iter.next().unwrap());
21-
}
22+
opaque().next();
2223
}

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

Lines changed: 1 addition & 0 deletions
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() {}

0 commit comments

Comments
 (0)