From 27af8e45852536fd14817464610866c84ad838b0 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Fri, 3 Jun 2022 13:14:23 -0700 Subject: [PATCH] Normalize consts' tys when relating with adt_const_params --- compiler/rustc_middle/src/ty/relate.rs | 13 ++-- src/test/ui/const-generics/issue-97007.rs | 88 +++++++++++++++++++++++ 2 files changed, 97 insertions(+), 4 deletions(-) create mode 100644 src/test/ui/const-generics/issue-97007.rs diff --git a/compiler/rustc_middle/src/ty/relate.rs b/compiler/rustc_middle/src/ty/relate.rs index 8677405eebeda..9712d66b30a22 100644 --- a/compiler/rustc_middle/src/ty/relate.rs +++ b/compiler/rustc_middle/src/ty/relate.rs @@ -579,10 +579,15 @@ pub fn super_relate_consts<'tcx, R: TypeRelation<'tcx>>( debug!("{}.super_relate_consts(a = {:?}, b = {:?})", relation.tag(), a, b); let tcx = relation.tcx(); - // FIXME(oli-obk): once const generics can have generic types, this assertion - // will likely get triggered. Move to `normalize_erasing_regions` at that point. - let a_ty = tcx.erase_regions(a.ty()); - let b_ty = tcx.erase_regions(b.ty()); + let a_ty; + let b_ty; + if relation.tcx().features().adt_const_params { + a_ty = tcx.normalize_erasing_regions(relation.param_env(), a.ty()); + b_ty = tcx.normalize_erasing_regions(relation.param_env(), b.ty()); + } else { + a_ty = tcx.erase_regions(a.ty()); + b_ty = tcx.erase_regions(b.ty()); + } if a_ty != b_ty { relation.tcx().sess.delay_span_bug( DUMMY_SP, diff --git a/src/test/ui/const-generics/issue-97007.rs b/src/test/ui/const-generics/issue-97007.rs new file mode 100644 index 0000000000000..7036834c4b119 --- /dev/null +++ b/src/test/ui/const-generics/issue-97007.rs @@ -0,0 +1,88 @@ +// check-pass + +#![feature(adt_const_params, generic_const_exprs)] +#![allow(incomplete_features)] + +mod lib { + const N_ISLANDS: usize = 4; + const N_BRIDGES: usize = 7; + const BRIDGES: [(usize, usize); 7] = [(0, 1), (0, 1), (0, 2), (0, 3), (0, 3), (1, 2), (2, 3)]; + + pub type Matrix = [[usize; N_ISLANDS]; N_ISLANDS]; + + const EMPTY_MATRIX: Matrix = [[0; N_ISLANDS]; N_ISLANDS]; + + const fn build(mut matrix: Matrix, (to, from): (usize, usize)) -> Matrix { + matrix[to][from] += 1; + matrix[from][to] += 1; + matrix + } + + pub const fn walk(mut matrix: Matrix, from: usize, to: usize) -> Matrix { + matrix[from][to] -= 1; + matrix[to][from] -= 1; + matrix + } + + const fn to_matrix(bridges: [(usize, usize); N_BRIDGES]) -> Matrix { + let matrix = EMPTY_MATRIX; + + let matrix = build(matrix, bridges[0]); + let matrix = build(matrix, bridges[1]); + let matrix = build(matrix, bridges[2]); + let matrix = build(matrix, bridges[3]); + let matrix = build(matrix, bridges[4]); + let matrix = build(matrix, bridges[5]); + let matrix = build(matrix, bridges[6]); + + matrix + } + + const BRIDGE_MATRIX: [[usize; N_ISLANDS]; N_ISLANDS] = to_matrix(BRIDGES); + + pub struct Walk { + _p: (), + } + + impl Walk<0, BRIDGE_MATRIX> { + pub const fn new() -> Self { + Self { _p: () } + } + } + + impl Walk { + pub fn proceed_to( + self, + ) -> Walk { + Walk { _p: () } + } + } + + pub struct Trophy { + _p: (), + } + + impl Walk { + pub fn collect_prize(self) -> Trophy { + Trophy { _p: () } + } + } +} + +pub use lib::{Trophy, Walk}; + +fn main() { + // Example, taking the first step + let _ = Walk::new().proceed_to::<1>(); + + // Don't be so eager to collect the trophy + // let trophy = Walk::new() + // .proceed_to::<1>() + // .proceed_to::<0>() + // .collect_prize(); + + // Can't just make a Trophy out of thin air, you must earn it + // let trophy: Trophy = Trophy { _p: () }; + + // Can you collect the Trophy? +}