Skip to content

Commit

Permalink
Rollup merge of rust-lang#92780 - b-naber:postpone-const-eval-coheren…
Browse files Browse the repository at this point in the history
…ce, r=lcnr

Directly use ConstValue for single literals in blocks

Addresses the minimal repro in rust-lang#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 rust-lang#90023), i.e. while we do get warnings for those unnecessary braces, we should try to avoid errors caused by those braces if possible.
  • Loading branch information
matthiaskrgr authored Jan 18, 2022
2 parents ff476b3 + 7dac626 commit 5a4f474
Show file tree
Hide file tree
Showing 7 changed files with 55 additions and 21 deletions.
21 changes: 12 additions & 9 deletions compiler/rustc_middle/src/ty/consts.rs
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ impl<'tcx> Const<'tcx> {
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(
tcx: TyCtxt<'tcx>,
def: ty::WithOptConstParam<LocalDefId>,
Expand All @@ -51,6 +52,7 @@ impl<'tcx> Const<'tcx> {
};

let expr = &tcx.hir().body(body_id).value;
debug!(?expr);

let ty = tcx.type_of(def.def_id_for_type_of());

Expand All @@ -67,11 +69,21 @@ impl<'tcx> Const<'tcx> {
}
}

#[instrument(skip(tcx), level = "debug")]
fn try_eval_lit_or_param(
tcx: TyCtxt<'tcx>,
ty: Ty<'tcx>,
expr: &'tcx hir::Expr<'tcx>,
) -> 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 {
hir::ExprKind::Lit(ref lit) => Some(LitToConstInput { lit: &lit.node, ty, neg: false }),
hir::ExprKind::Unary(hir::UnOp::Neg, ref expr) => match expr.kind {
Expand All @@ -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};
match expr.kind {
ExprKind::Path(QPath::Resolved(_, &Path { res: Res::Def(ConstParam, def_id), .. })) => {
Expand Down
8 changes: 2 additions & 6 deletions compiler/rustc_trait_selection/src/traits/coherence.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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`
/// with a suitably-freshened `ImplHeader` with those types
/// substituted. Otherwise, invokes `no_overlap`.
#[instrument(skip(tcx, skip_leak_check, on_overlap, no_overlap), level = "debug")]
pub fn overlapping_impls<F1, F2, R>(
tcx: TyCtxt<'_>,
impl1_def_id: DefId,
Expand All @@ -65,12 +66,6 @@ where
F1: FnOnce(OverlapResult<'_>) -> 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
// a quick check via fast_reject to tell if the impl headers could possibly
// unify.
Expand All @@ -85,6 +80,7 @@ where
.any(|(ty1, ty2)| {
let t1 = fast_reject::simplify_type(tcx, ty1, SimplifyParams::No, StripReferences::No);
let t2 = fast_reject::simplify_type(tcx, ty2, SimplifyParams::No, StripReferences::No);

if let (Some(t1), Some(t2)) = (t1, t2) {
// Simplified successfully
t1 != t2
Expand Down
3 changes: 1 addition & 2 deletions compiler/rustc_trait_selection/src/traits/specialize/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -117,9 +117,8 @@ pub fn translate_substs<'a, 'tcx>(
/// 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
/// to.
#[instrument(skip(tcx), level = "debug")]
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
// taking advantage of upstream ones.
let features = tcx.features();
Expand Down
12 changes: 12 additions & 0 deletions src/test/ui/const-generics/issues/issue-92186.rs
Original file line number Diff line number Diff line change
@@ -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() {}
17 changes: 14 additions & 3 deletions src/test/ui/const-generics/types-mismatch-const-args.full.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,20 @@ LL | let _: A<'a, u16, {2u32}, {3u32}> = A::<'b, u32, {2u32}, {3u32}> { data
| |
| expected due to this
|
= note: expected struct `A<'a, u16, {2u32}, {3u32}>`
found struct `A<'b, u32, {2u32}, {3u32}>`
= note: expected struct `A<'a, u16, _, _>`
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`.
13 changes: 12 additions & 1 deletion src/test/ui/const-generics/types-mismatch-const-args.min.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,17 @@ LL | let _: A<'a, u16, {2u32}, {3u32}> = A::<'b, u32, {2u32}, {3u32}> { data
= note: expected struct `A<'a, u16, _, _>`
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`.
2 changes: 2 additions & 0 deletions src/test/ui/const-generics/types-mismatch-const-args.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@ fn a<'a, 'b>() {
//~^ ERROR mismatched types
let _: A<'a, u16, {2u32}, {3u32}> = A::<'b, u32, {2u32}, {3u32}> { data: PhantomData };
//~^ ERROR mismatched types
let _: A<'a, u16, {4u32}, {3u32}> = A::<'b, u32, {2u32}, {3u32}> { data: PhantomData };
//~^ ERROR mismatched types
}

pub fn main() {}

0 comments on commit 5a4f474

Please sign in to comment.