Skip to content

Commit a6fd875

Browse files
authored
Unrolled build for #152146
Rollup merge of #152146 - zedddie:mgca-improve-const-bindings-wfck, r=BoxyUwU mGCA: Add associated const type check #151642 r? BoxyUwU I didn't bless tests just yet as it only fixes the dyn arm
2 parents 7057231 + ec03e39 commit a6fd875

File tree

11 files changed

+167
-3
lines changed

11 files changed

+167
-3
lines changed

compiler/rustc_hir_analysis/src/check/wfcheck.rs

Lines changed: 30 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1569,11 +1569,40 @@ pub(super) fn check_where_clauses<'tcx>(wfcx: &WfCheckingCtxt<'_, 'tcx>, def_id:
15691569

15701570
let predicates = predicates.instantiate_identity(tcx);
15711571

1572+
let assoc_const_obligations: Vec<_> = predicates
1573+
.predicates
1574+
.iter()
1575+
.copied()
1576+
.zip(predicates.spans.iter().copied())
1577+
.filter_map(|(clause, sp)| {
1578+
let proj = clause.as_projection_clause()?;
1579+
let pred_binder = proj
1580+
.map_bound(|pred| {
1581+
pred.term.as_const().map(|ct| {
1582+
let assoc_const_ty = tcx
1583+
.type_of(pred.projection_term.def_id)
1584+
.instantiate(tcx, pred.projection_term.args);
1585+
ty::ClauseKind::ConstArgHasType(ct, assoc_const_ty)
1586+
})
1587+
})
1588+
.transpose();
1589+
pred_binder.map(|pred_binder| {
1590+
let cause = traits::ObligationCause::new(
1591+
sp,
1592+
wfcx.body_def_id,
1593+
ObligationCauseCode::WhereClause(def_id.to_def_id(), sp),
1594+
);
1595+
Obligation::new(tcx, cause, wfcx.param_env, pred_binder)
1596+
})
1597+
})
1598+
.collect();
1599+
15721600
assert_eq!(predicates.predicates.len(), predicates.spans.len());
15731601
let wf_obligations = predicates.into_iter().flat_map(|(p, sp)| {
15741602
traits::wf::clause_obligations(infcx, wfcx.param_env, wfcx.body_def_id, p, sp)
15751603
});
1576-
let obligations: Vec<_> = wf_obligations.chain(default_obligations).collect();
1604+
let obligations: Vec<_> =
1605+
wf_obligations.chain(default_obligations).chain(assoc_const_obligations).collect();
15771606
wfcx.register_obligations(obligations);
15781607
}
15791608

compiler/rustc_trait_selection/src/traits/wf.rs

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -951,6 +951,34 @@ impl<'a, 'tcx> TypeVisitor<TyCtxt<'tcx>> for WfPredicates<'a, 'tcx> {
951951
ty::Binder::dummy(ty::PredicateKind::DynCompatible(principal)),
952952
));
953953
}
954+
955+
if !t.has_escaping_bound_vars() {
956+
for projection in data.projection_bounds() {
957+
let pred_binder = projection
958+
.with_self_ty(tcx, t)
959+
.map_bound(|p| {
960+
p.term.as_const().map(|ct| {
961+
let assoc_const_ty = tcx
962+
.type_of(p.projection_term.def_id)
963+
.instantiate(tcx, p.projection_term.args);
964+
ty::PredicateKind::Clause(ty::ClauseKind::ConstArgHasType(
965+
ct,
966+
assoc_const_ty,
967+
))
968+
})
969+
})
970+
.transpose();
971+
if let Some(pred_binder) = pred_binder {
972+
self.out.push(traits::Obligation::with_depth(
973+
tcx,
974+
self.cause(ObligationCauseCode::WellFormed(None)),
975+
self.recursion_depth,
976+
self.param_env,
977+
pred_binder,
978+
));
979+
}
980+
}
981+
}
954982
}
955983

956984
// Inference variables are the complicated case, since we don't

tests/ui/const-generics/associated-const-bindings/dyn-compat-const-projection-behind-trait-alias-mentions-self.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ trait Trait {
1515
struct Hold<T: ?Sized>(T);
1616

1717
trait Bound = Trait<Y = { Hold::<Self> }>;
18+
//~^ ERROR the constant `Hold::<Self>` is not of type `i32`
1819

1920
fn main() {
2021
let _: dyn Bound; //~ ERROR associated constant binding in trait object type mentions `Self`
Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,23 @@
1+
error: the constant `Hold::<Self>` is not of type `i32`
2+
--> $DIR/dyn-compat-const-projection-behind-trait-alias-mentions-self.rs:17:21
3+
|
4+
LL | trait Bound = Trait<Y = { Hold::<Self> }>;
5+
| ^^^^^^^^^^^^^^^^^^^^ expected `i32`, found struct constructor
6+
|
7+
note: required by a const generic parameter in `Bound`
8+
--> $DIR/dyn-compat-const-projection-behind-trait-alias-mentions-self.rs:17:21
9+
|
10+
LL | trait Bound = Trait<Y = { Hold::<Self> }>;
11+
| ^^^^^^^^^^^^^^^^^^^^ required by this const generic parameter in `Bound`
12+
113
error: associated constant binding in trait object type mentions `Self`
2-
--> $DIR/dyn-compat-const-projection-behind-trait-alias-mentions-self.rs:20:12
14+
--> $DIR/dyn-compat-const-projection-behind-trait-alias-mentions-self.rs:21:12
315
|
416
LL | trait Bound = Trait<Y = { Hold::<Self> }>;
517
| -------------------- this binding mentions `Self`
618
...
719
LL | let _: dyn Bound;
820
| ^^^^^^^^^ contains a mention of `Self`
921

10-
error: aborting due to 1 previous error
22+
error: aborting due to 2 previous errors
1123

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
//! Check associated const binding with escaping bound vars doesn't cause ICE
2+
//! (#151642)
3+
//@ check-pass
4+
5+
#![feature(min_generic_const_args)]
6+
#![expect(incomplete_features)]
7+
8+
trait Trait2<'a> { type const ASSOC: i32; }
9+
fn g(_: for<'a> fn(Box<dyn Trait2<'a, ASSOC = 10>>)) {}
10+
11+
fn main() {}
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
//! Check that we correctly handle associated const bindings
2+
//! in `impl Trait` where the RHS is a const param (#151642).
3+
4+
#![feature(min_generic_const_args)]
5+
#![expect(incomplete_features)]
6+
7+
trait Trait { type const CT: bool; }
8+
9+
fn f<const N: i32>(_: impl Trait<CT = { N }>) {}
10+
//~^ ERROR the constant `N` is not of type `bool`
11+
fn main() {}
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
error: the constant `N` is not of type `bool`
2+
--> $DIR/wf-mismatch-1.rs:9:34
3+
|
4+
LL | fn f<const N: i32>(_: impl Trait<CT = { N }>) {}
5+
| ^^^^^^^^^^ expected `bool`, found `i32`
6+
|
7+
note: required by a const generic parameter in `f`
8+
--> $DIR/wf-mismatch-1.rs:9:34
9+
|
10+
LL | fn f<const N: i32>(_: impl Trait<CT = { N }>) {}
11+
| ^^^^^^^^^^ required by this const generic parameter in `f`
12+
13+
error: aborting due to 1 previous error
14+
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
//! Check that we correctly handle associated const bindings
2+
//! in `dyn Trait` where the RHS is a const param (#151642).
3+
4+
#![feature(min_generic_const_args)]
5+
#![expect(incomplete_features)]
6+
7+
trait Trait { type const CT: bool; }
8+
9+
fn f<const N: i32>() {
10+
let _: dyn Trait<CT = { N }>;
11+
//~^ ERROR the constant `N` is not of type `bool`
12+
}
13+
fn main() {}
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
error: the constant `N` is not of type `bool`
2+
--> $DIR/wf-mismatch-2.rs:10:12
3+
|
4+
LL | let _: dyn Trait<CT = { N }>;
5+
| ^^^^^^^^^^^^^^^^^^^^^ expected `bool`, found `i32`
6+
7+
error: aborting due to 1 previous error
8+
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
//! Check that we correctly handle associated const bindings
2+
//! where the RHS is a normalizable const projection (#151642).
3+
4+
#![feature(min_generic_const_args)]
5+
#![expect(incomplete_features)]
6+
7+
trait Trait { type const CT: bool; }
8+
9+
trait Bound { type const N: u32; }
10+
impl Bound for () { type const N: u32 = 0; }
11+
12+
fn f() { let _: dyn Trait<CT = { <() as Bound>::N }>; }
13+
//~^ ERROR the constant `0` is not of type `bool`
14+
fn g(_: impl Trait<CT = { <() as Bound>::N }>) {}
15+
//~^ ERROR the constant `0` is not of type `bool`
16+
17+
fn main() {}

0 commit comments

Comments
 (0)