mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-22 23:04:33 +00:00
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:
commit
5a4f47460b
@ -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), .. })) => {
|
||||||
|
@ -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
|
||||||
|
@ -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();
|
||||||
|
12
src/test/ui/const-generics/issues/issue-92186.rs
Normal file
12
src/test/ui/const-generics/issues/issue-92186.rs
Normal 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() {}
|
@ -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`.
|
||||||
|
@ -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`.
|
||||||
|
@ -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() {}
|
||||||
|
Loading…
Reference in New Issue
Block a user