From a9a8f79f86a9251f29941bd79418e683692548e0 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Fri, 20 Sep 2024 20:17:13 -0400 Subject: [PATCH 1/2] Normalize unevaluated consts in GCE --- compiler/rustc_hir_typeck/src/writeback.rs | 37 +++++++++++++++++-- .../generic_const_exprs/issue-109141.rs | 3 +- .../generic_const_exprs/issue-109141.stderr | 33 ++--------------- .../generic_const_exprs/opaque_type.rs | 1 - .../generic_const_exprs/opaque_type.stderr | 14 ++----- 5 files changed, 40 insertions(+), 48 deletions(-) diff --git a/compiler/rustc_hir_typeck/src/writeback.rs b/compiler/rustc_hir_typeck/src/writeback.rs index c2555d2bb47dc..2fbbc3200e12a 100644 --- a/compiler/rustc_hir_typeck/src/writeback.rs +++ b/compiler/rustc_hir_typeck/src/writeback.rs @@ -803,7 +803,7 @@ impl<'cx, 'tcx> Resolver<'cx, 'tcx> { // We must deeply normalize in the new solver, since later lints // expect that types that show up in the typeck are fully // normalized. - let value = if self.should_normalize { + let mut value = if self.should_normalize { let body_id = tcx.hir().body_owner_def_id(self.body.id()); let cause = ObligationCause::misc(self.span.to_span(tcx), body_id); let at = self.fcx.at(&cause, self.fcx.param_env); @@ -818,12 +818,27 @@ impl<'cx, 'tcx> Resolver<'cx, 'tcx> { value }; + // Bail if there are any non-region infer. if value.has_non_region_infer() { let guar = self.report_error(value); - new_err(tcx, guar) - } else { - tcx.fold_regions(value, |_, _| tcx.lifetimes.re_erased) + value = new_err(tcx, guar); + } + + // Erase the regions from the ty, since it's not really meaningful what + // these region values are; there's not a trivial correspondence between + // regions in the HIR and MIR, so when we turn the body into MIR, there's + // no reason to keep regions around. They will be repopulated during MIR + // borrowck, and specifically region constraints will be populated during + // MIR typeck which is run on the new body. + value = tcx.fold_regions(value, |_, _| tcx.lifetimes.re_erased); + + // Normalize consts in writeback, because GCE doesn't normalize eagerly. + if tcx.features().generic_const_exprs { + value = + value.fold_with(&mut EagerlyNormalizeConsts { tcx, param_env: self.fcx.param_env }); } + + value } } @@ -858,3 +873,17 @@ impl<'cx, 'tcx> TypeFolder> for Resolver<'cx, 'tcx> { predicate } } + +struct EagerlyNormalizeConsts<'tcx> { + tcx: TyCtxt<'tcx>, + param_env: ty::ParamEnv<'tcx>, +} +impl<'tcx> TypeFolder> for EagerlyNormalizeConsts<'tcx> { + fn cx(&self) -> TyCtxt<'tcx> { + self.tcx + } + + fn fold_const(&mut self, ct: ty::Const<'tcx>) -> ty::Const<'tcx> { + self.tcx.try_normalize_erasing_regions(self.param_env, ct).unwrap_or(ct) + } +} diff --git a/tests/ui/const-generics/generic_const_exprs/issue-109141.rs b/tests/ui/const-generics/generic_const_exprs/issue-109141.rs index c6dd981cced00..5303b24717353 100644 --- a/tests/ui/const-generics/generic_const_exprs/issue-109141.rs +++ b/tests/ui/const-generics/generic_const_exprs/issue-109141.rs @@ -3,8 +3,7 @@ impl EntriesBuffer { fn a(&self) -> impl Iterator { - self.0.iter_mut() //~ ERROR: cannot borrow `*self.0` as mutable, as it is behind a `&` reference - //~| ERROR captures lifetime that does not appear in bounds + self.0.iter_mut() } } diff --git a/tests/ui/const-generics/generic_const_exprs/issue-109141.stderr b/tests/ui/const-generics/generic_const_exprs/issue-109141.stderr index 24f3ed7cdf15e..fcbd690459972 100644 --- a/tests/ui/const-generics/generic_const_exprs/issue-109141.stderr +++ b/tests/ui/const-generics/generic_const_exprs/issue-109141.stderr @@ -1,5 +1,5 @@ error[E0425]: cannot find value `HashesEntryLEN` in this scope - --> $DIR/issue-109141.rs:11:32 + --> $DIR/issue-109141.rs:10:32 | LL | struct EntriesBuffer(Box<[[u8; HashesEntryLEN]; 5]>); | ^^^^^^^^^^^^^^ not found in this scope @@ -9,33 +9,6 @@ help: you might be missing a const parameter LL | struct EntriesBuffer(Box<[[u8; HashesEntryLEN]; 5]>); | ++++++++++++++++++++++++++++++++++ -error[E0596]: cannot borrow `*self.0` as mutable, as it is behind a `&` reference - --> $DIR/issue-109141.rs:6:9 - | -LL | self.0.iter_mut() - | ^^^^^^ `self` is a `&` reference, so the data it refers to cannot be borrowed as mutable - | -help: consider changing this to be a mutable reference - | -LL | fn a(&mut self) -> impl Iterator { - | ~~~~~~~~~ - -error[E0700]: hidden type for `impl Iterator` captures lifetime that does not appear in bounds - --> $DIR/issue-109141.rs:6:9 - | -LL | fn a(&self) -> impl Iterator { - | ----- ------------- opaque type defined here - | | - | hidden type `std::slice::IterMut<'_, [u8; {const error}]>` captures the anonymous lifetime defined here -LL | self.0.iter_mut() - | ^^^^^^^^^^^^^^^^^ - | -help: add a `use<...>` bound to explicitly capture `'_` - | -LL | fn a(&self) -> impl Iterator + use<'_> { - | +++++++++ - -error: aborting due to 3 previous errors +error: aborting due to 1 previous error -Some errors have detailed explanations: E0425, E0596, E0700. -For more information about an error, try `rustc --explain E0425`. +For more information about this error, try `rustc --explain E0425`. diff --git a/tests/ui/const-generics/generic_const_exprs/opaque_type.rs b/tests/ui/const-generics/generic_const_exprs/opaque_type.rs index 7209290a36e0a..56b8acbf88cde 100644 --- a/tests/ui/const-generics/generic_const_exprs/opaque_type.rs +++ b/tests/ui/const-generics/generic_const_exprs/opaque_type.rs @@ -2,7 +2,6 @@ #![allow(incomplete_features)] type Foo = impl Sized; -//~^ ERROR: unconstrained opaque type fn with_bound() -> Foo where diff --git a/tests/ui/const-generics/generic_const_exprs/opaque_type.stderr b/tests/ui/const-generics/generic_const_exprs/opaque_type.stderr index c7a266205b4b5..e9fb8c0f403ae 100644 --- a/tests/ui/const-generics/generic_const_exprs/opaque_type.stderr +++ b/tests/ui/const-generics/generic_const_exprs/opaque_type.stderr @@ -1,5 +1,5 @@ error[E0308]: mismatched types - --> $DIR/opaque_type.rs:11:17 + --> $DIR/opaque_type.rs:10:17 | LL | type Foo = impl Sized; | ---------- the found opaque type @@ -11,20 +11,12 @@ LL | let _: [u8; (N / 2) as Foo] = [0; (N / 2) as usize]; found opaque type `Foo` error[E0605]: non-primitive cast: `usize` as `Foo` - --> $DIR/opaque_type.rs:11:17 + --> $DIR/opaque_type.rs:10:17 | LL | let _: [u8; (N / 2) as Foo] = [0; (N / 2) as usize]; | ^^^^^^^^^^^^^^ an `as` expression can only be used to convert between primitive types or to coerce to a specific trait object -error: unconstrained opaque type - --> $DIR/opaque_type.rs:4:12 - | -LL | type Foo = impl Sized; - | ^^^^^^^^^^ - | - = note: `Foo` must be used in combination with a concrete type within the same module - -error: aborting due to 3 previous errors +error: aborting due to 2 previous errors Some errors have detailed explanations: E0308, E0605. For more information about an error, try `rustc --explain E0308`. From 920a973bdbb0aece426b85cf03a377108e064524 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Fri, 20 Sep 2024 20:16:49 -0400 Subject: [PATCH 2/2] Don't emit spurious error for pattern matched array with erroneous len const --- compiler/rustc_hir_typeck/src/pat.rs | 13 +------------ tests/ui/consts/issue-116186.rs | 2 +- tests/ui/consts/issue-116186.stderr | 11 ++--------- 3 files changed, 4 insertions(+), 22 deletions(-) diff --git a/compiler/rustc_hir_typeck/src/pat.rs b/compiler/rustc_hir_typeck/src/pat.rs index 45a6efc7a6a32..7dd6deb4fe6fd 100644 --- a/compiler/rustc_hir_typeck/src/pat.rs +++ b/compiler/rustc_hir_typeck/src/pat.rs @@ -11,7 +11,6 @@ use rustc_hir::def::{CtorKind, DefKind, Res}; use rustc_hir::pat_util::EnumerateAndAdjustIterator; use rustc_hir::{self as hir, BindingMode, ByRef, HirId, LangItem, Mutability, Pat, PatKind}; use rustc_infer::infer; -use rustc_middle::mir::interpret::ErrorHandled; use rustc_middle::ty::{self, Ty, TypeVisitableExt}; use rustc_middle::{bug, span_bug}; use rustc_session::lint::builtin::NON_EXHAUSTIVE_OMITTED_PATTERNS; @@ -2413,17 +2412,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { len: ty::Const<'tcx>, min_len: u64, ) -> (Option>, Ty<'tcx>) { - let len = match len.eval(self.tcx, self.param_env, span) { - Ok((_, val)) => val - .try_to_scalar() - .and_then(|scalar| scalar.try_to_scalar_int().ok()) - .map(|int| int.to_target_usize(self.tcx)), - Err(ErrorHandled::Reported(..)) => { - let guar = self.error_scrutinee_unfixed_length(span); - return (Some(Ty::new_error(self.tcx, guar)), arr_ty); - } - Err(ErrorHandled::TooGeneric(..)) => None, - }; + let len = len.try_eval_target_usize(self.tcx, self.param_env); let guar = if let Some(len) = len { // Now we know the length... diff --git a/tests/ui/consts/issue-116186.rs b/tests/ui/consts/issue-116186.rs index a77c38c64dc57..8bfb47629e7f4 100644 --- a/tests/ui/consts/issue-116186.rs +++ b/tests/ui/consts/issue-116186.rs @@ -4,7 +4,7 @@ fn something(path: [usize; N]) -> impl Clone { //~^ ERROR cannot find value `N` in this scope match path { - [] => 0, //~ ERROR cannot pattern-match on an array without a fixed length + [] => 0, _ => 1, }; } diff --git a/tests/ui/consts/issue-116186.stderr b/tests/ui/consts/issue-116186.stderr index e6eae2d9f55ef..46931f79dd0cb 100644 --- a/tests/ui/consts/issue-116186.stderr +++ b/tests/ui/consts/issue-116186.stderr @@ -9,13 +9,6 @@ help: you might be missing a const parameter LL | fn something(path: [usize; N]) -> impl Clone { | +++++++++++++++++++++ -error[E0730]: cannot pattern-match on an array without a fixed length - --> $DIR/issue-116186.rs:7:9 - | -LL | [] => 0, - | ^^ - -error: aborting due to 2 previous errors +error: aborting due to 1 previous error -Some errors have detailed explanations: E0425, E0730. -For more information about an error, try `rustc --explain E0425`. +For more information about this error, try `rustc --explain E0425`.