Rollup merge of #92780 - b-naber:postpone-const-eval-coherence, r=lcnr

Directly use ConstValue for single literals in blocks

Addresses the minimal repro in https://github.com/rust-lang/rust/issues/92186, but doesn't fix the underlying problem (which would be solved by solving the anon subst problem afaict).

I do, however, think that it makes sense in general to treat single literals in anon blocks as const values directly, especially in light of the problem that the issue refers to (anon const evaluation being postponed until infer variables in substs can be resolved, which was introduced by https://github.com/rust-lang/rust/pull/90023), i.e. while we do get warnings for those unnecessary braces, we should try to avoid errors caused by those braces if possible.
This commit is contained in:
Matthias Krüger 2022-01-18 22:00:47 +01:00 committed by GitHub
commit 5a4f47460b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 55 additions and 21 deletions

View File

@ -36,6 +36,7 @@ impl<'tcx> Const<'tcx> {
Self::from_opt_const_arg_anon_const(tcx, ty::WithOptConstParam::unknown(def_id)) Self::from_opt_const_arg_anon_const(tcx, ty::WithOptConstParam::unknown(def_id))
} }
#[instrument(skip(tcx), level = "debug")]
pub fn from_opt_const_arg_anon_const( pub fn from_opt_const_arg_anon_const(
tcx: TyCtxt<'tcx>, tcx: TyCtxt<'tcx>,
def: ty::WithOptConstParam<LocalDefId>, def: ty::WithOptConstParam<LocalDefId>,
@ -51,6 +52,7 @@ impl<'tcx> Const<'tcx> {
}; };
let expr = &tcx.hir().body(body_id).value; let expr = &tcx.hir().body(body_id).value;
debug!(?expr);
let ty = tcx.type_of(def.def_id_for_type_of()); let ty = tcx.type_of(def.def_id_for_type_of());
@ -67,11 +69,21 @@ impl<'tcx> Const<'tcx> {
} }
} }
#[instrument(skip(tcx), level = "debug")]
fn try_eval_lit_or_param( fn try_eval_lit_or_param(
tcx: TyCtxt<'tcx>, tcx: TyCtxt<'tcx>,
ty: Ty<'tcx>, ty: Ty<'tcx>,
expr: &'tcx hir::Expr<'tcx>, expr: &'tcx hir::Expr<'tcx>,
) -> Option<&'tcx Self> { ) -> Option<&'tcx Self> {
// Unwrap a block, so that e.g. `{ P }` is recognised as a parameter. Const arguments
// currently have to be wrapped in curly brackets, so it's necessary to special-case.
let expr = match &expr.kind {
hir::ExprKind::Block(block, _) if block.stmts.is_empty() && block.expr.is_some() => {
block.expr.as_ref().unwrap()
}
_ => expr,
};
let lit_input = match expr.kind { let lit_input = match expr.kind {
hir::ExprKind::Lit(ref lit) => Some(LitToConstInput { lit: &lit.node, ty, neg: false }), hir::ExprKind::Lit(ref lit) => Some(LitToConstInput { lit: &lit.node, ty, neg: false }),
hir::ExprKind::Unary(hir::UnOp::Neg, ref expr) => match expr.kind { hir::ExprKind::Unary(hir::UnOp::Neg, ref expr) => match expr.kind {
@ -97,15 +109,6 @@ impl<'tcx> Const<'tcx> {
} }
} }
// Unwrap a block, so that e.g. `{ P }` is recognised as a parameter. Const arguments
// currently have to be wrapped in curly brackets, so it's necessary to special-case.
let expr = match &expr.kind {
hir::ExprKind::Block(block, _) if block.stmts.is_empty() && block.expr.is_some() => {
block.expr.as_ref().unwrap()
}
_ => expr,
};
use hir::{def::DefKind::ConstParam, def::Res, ExprKind, Path, QPath}; use hir::{def::DefKind::ConstParam, def::Res, ExprKind, Path, QPath};
match expr.kind { match expr.kind {
ExprKind::Path(QPath::Resolved(_, &Path { res: Res::Def(ConstParam, def_id), .. })) => { ExprKind::Path(QPath::Resolved(_, &Path { res: Res::Def(ConstParam, def_id), .. })) => {

View File

@ -53,6 +53,7 @@ pub fn add_placeholder_note(err: &mut rustc_errors::DiagnosticBuilder<'_>) {
/// If there are types that satisfy both impls, invokes `on_overlap` /// If there are types that satisfy both impls, invokes `on_overlap`
/// with a suitably-freshened `ImplHeader` with those types /// with a suitably-freshened `ImplHeader` with those types
/// substituted. Otherwise, invokes `no_overlap`. /// substituted. Otherwise, invokes `no_overlap`.
#[instrument(skip(tcx, skip_leak_check, on_overlap, no_overlap), level = "debug")]
pub fn overlapping_impls<F1, F2, R>( pub fn overlapping_impls<F1, F2, R>(
tcx: TyCtxt<'_>, tcx: TyCtxt<'_>,
impl1_def_id: DefId, impl1_def_id: DefId,
@ -65,12 +66,6 @@ where
F1: FnOnce(OverlapResult<'_>) -> R, F1: FnOnce(OverlapResult<'_>) -> R,
F2: FnOnce() -> R, F2: FnOnce() -> R,
{ {
debug!(
"overlapping_impls(\
impl1_def_id={:?}, \
impl2_def_id={:?})",
impl1_def_id, impl2_def_id,
);
// Before doing expensive operations like entering an inference context, do // Before doing expensive operations like entering an inference context, do
// a quick check via fast_reject to tell if the impl headers could possibly // a quick check via fast_reject to tell if the impl headers could possibly
// unify. // unify.
@ -85,6 +80,7 @@ where
.any(|(ty1, ty2)| { .any(|(ty1, ty2)| {
let t1 = fast_reject::simplify_type(tcx, ty1, SimplifyParams::No, StripReferences::No); let t1 = fast_reject::simplify_type(tcx, ty1, SimplifyParams::No, StripReferences::No);
let t2 = fast_reject::simplify_type(tcx, ty2, SimplifyParams::No, StripReferences::No); let t2 = fast_reject::simplify_type(tcx, ty2, SimplifyParams::No, StripReferences::No);
if let (Some(t1), Some(t2)) = (t1, t2) { if let (Some(t1), Some(t2)) = (t1, t2) {
// Simplified successfully // Simplified successfully
t1 != t2 t1 != t2

View File

@ -117,9 +117,8 @@ pub fn translate_substs<'a, 'tcx>(
/// Specialization is determined by the sets of types to which the impls apply; /// Specialization is determined by the sets of types to which the impls apply;
/// `impl1` specializes `impl2` if it applies to a subset of the types `impl2` applies /// `impl1` specializes `impl2` if it applies to a subset of the types `impl2` applies
/// to. /// to.
#[instrument(skip(tcx), level = "debug")]
pub(super) fn specializes(tcx: TyCtxt<'_>, (impl1_def_id, impl2_def_id): (DefId, DefId)) -> bool { pub(super) fn specializes(tcx: TyCtxt<'_>, (impl1_def_id, impl2_def_id): (DefId, DefId)) -> bool {
debug!("specializes({:?}, {:?})", impl1_def_id, impl2_def_id);
// The feature gate should prevent introducing new specializations, but not // The feature gate should prevent introducing new specializations, but not
// taking advantage of upstream ones. // taking advantage of upstream ones.
let features = tcx.features(); let features = tcx.features();

View File

@ -0,0 +1,12 @@
// check-pass
#![feature(generic_const_exprs)]
#![allow(incomplete_features)]
pub struct Foo<const N: usize>;
pub trait Bar<T> {}
impl<T> Bar<T> for Foo<{ 1 }> {}
impl<T> Bar<T> for Foo<{ 2 }> {}
fn main() {}

View File

@ -15,9 +15,20 @@ LL | let _: A<'a, u16, {2u32}, {3u32}> = A::<'b, u32, {2u32}, {3u32}> { data
| | | |
| expected due to this | expected due to this
| |
= note: expected struct `A<'a, u16, {2u32}, {3u32}>` = note: expected struct `A<'a, u16, _, _>`
found struct `A<'b, u32, {2u32}, {3u32}>` found struct `A<'b, u32, _, _>`
error: aborting due to 2 previous errors error[E0308]: mismatched types
--> $DIR/types-mismatch-const-args.rs:18:41
|
LL | let _: A<'a, u16, {4u32}, {3u32}> = A::<'b, u32, {2u32}, {3u32}> { data: PhantomData };
| -------------------------- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `u16`, found `u32`
| |
| expected due to this
|
= note: expected struct `A<'a, u16, 4_u32, _>`
found struct `A<'b, u32, 2_u32, _>`
error: aborting due to 3 previous errors
For more information about this error, try `rustc --explain E0308`. For more information about this error, try `rustc --explain E0308`.

View File

@ -20,6 +20,17 @@ LL | let _: A<'a, u16, {2u32}, {3u32}> = A::<'b, u32, {2u32}, {3u32}> { data
= note: expected struct `A<'a, u16, _, _>` = note: expected struct `A<'a, u16, _, _>`
found struct `A<'b, u32, _, _>` found struct `A<'b, u32, _, _>`
error: aborting due to 2 previous errors error[E0308]: mismatched types
--> $DIR/types-mismatch-const-args.rs:18:41
|
LL | let _: A<'a, u16, {4u32}, {3u32}> = A::<'b, u32, {2u32}, {3u32}> { data: PhantomData };
| -------------------------- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `u16`, found `u32`
| |
| expected due to this
|
= note: expected struct `A<'a, u16, 4_u32, _>`
found struct `A<'b, u32, 2_u32, _>`
error: aborting due to 3 previous errors
For more information about this error, try `rustc --explain E0308`. For more information about this error, try `rustc --explain E0308`.

View File

@ -15,6 +15,8 @@ fn a<'a, 'b>() {
//~^ ERROR mismatched types //~^ ERROR mismatched types
let _: A<'a, u16, {2u32}, {3u32}> = A::<'b, u32, {2u32}, {3u32}> { data: PhantomData }; let _: A<'a, u16, {2u32}, {3u32}> = A::<'b, u32, {2u32}, {3u32}> { data: PhantomData };
//~^ ERROR mismatched types //~^ ERROR mismatched types
let _: A<'a, u16, {4u32}, {3u32}> = A::<'b, u32, {2u32}, {3u32}> { data: PhantomData };
//~^ ERROR mismatched types
} }
pub fn main() {} pub fn main() {}