Skip to content

lazy_normalization_consts breaks unsize coercion in rare cases #78369

Open

Description

@lcnr
#![feature(lazy_normalization_consts)]
struct P<T: ?Sized>([u8; 1 + 4], T);

fn main() {
    let x: Box<P<[u8; 0]>> = Box::new(P(Default::default(), [0; 0]));
    let _: Box<P<[u8]>> = x;
}

This works on stable but fails with the following error when using lazy_normalization_consts

error[E0308]: mismatched types
 --> src/main.rs:6:27
  |
6 |     let _: Box<P<[u8]>> = x;
  |            ------------   ^ expected slice `[u8]`, found array `[u8; 0]`
  |            |
  |            expected due to this
  |
  = note: expected struct `Box<P<[u8]>>`
             found struct `Box<P<[u8; 0]>>`

For this to fail the struct has to contain a type referencing an unevaluated constant, struct P<T: ?Sized>([u8; 5], T) does work.

assigning to myself, but won't get to this right away. If you are interested in working on this before that feel free to do so.

cc @nikomatsakis @varkor

Activity

  1. self-assigned this
    on Oct 25, 2020
  2. added
    T-compilerRelevant to the compiler team, which will review and decide on the PR/issue.
    on Oct 26, 2020
  3. lcnr commented on Nov 16, 2020

    @lcnr
    ContributorAuthor

    The issue is here

    for field in prefix_fields {
    for arg in tcx.type_of(field.did).walk() {
    if let Some(i) = maybe_unsizing_param_idx(arg) {
    if unsizing_params.contains(i) {
    return Err(Unimplemented);
    }
    }
    }
    }

    in combination with

    stack.extend(substs.iter().rev());

    We currently look at all substs while we should only look at the generic params which are actually mentioned by the constant.
    The correct solution would be to instead walk the AbstractConst in case it exists, but for that we would have to move that to rustc_middle and also need to access the TyCtxt everywhere which seems difficult.

    I am currently thinking about moving AbstractConsts directly into ConstKind as the current ConstKind::Unevaluated is really unhelpful when dealing with anonymous constants. That would simplify dealing with them as we can then just treat them pretty much exactly like other projections, 🤔 would be a big change though, so it might make sense allocate some time to discuss this before doing anything stupid here...

    cc @oli-obk

  4. added
    requires-nightlyThis issue requires a nightly compiler in some way. When possible, use a F-* label instead.
    on Nov 16, 2020
  5. oli-obk commented on Nov 16, 2020

    @oli-obk
    Contributor

    I don't think we can remove Unevaluated. There are cases where we can neither build an abstract const nor evaluate it to a concrete constant. And once we have an abstract const, we can't turn that abstract const into a concrete one, so we'd need to keep the information about the uneavluated source around anyway. Can you elaborate on the changes you were thinking about?

  6. lcnr commented on Nov 16, 2020

    @lcnr
    ContributorAuthor

    I am not too sure how to actually do this yet... probably by adding an optional reference to &'tcx [Node<'tcx>] to Unevaluated 🤔

    we might not be able to just evaluate mir_abstract_const eagerly as that can cause query cycles though. I forgot what actually causes the cycles without lazy normalization

  7. oli-obk commented on Nov 16, 2020

    @oli-obk
    Contributor

    At that point you're just talking about caching, so one thing that we could also do is change the Unevaluated variant to be a tuple variant around an UnevaluatedConst which has methods for evaluating or converting to an abstract const, without exposing the internal fields anymore. The evaluation is already cached via the query system, and I think the abstract const building, too? So this would just be an API change to make it less painful to use.

  8. removed their assignment
    on Nov 11, 2025
  9. lcnr commented on Nov 11, 2025

    @lcnr
    ContributorAuthor

    will be replaced by MGCA cc @BoxyUwU

  10. removed
    requires-nightlyThis issue requires a nightly compiler in some way. When possible, use a F-* label instead.
    on Dec 12, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    A-lazy-normalizationArea: Lazy normalization (tracking issue: #60471)C-bugCategory: This is a bug.F-generic_const_exprs`#![feature(generic_const_exprs)]`T-compilerRelevant to the compiler team, which will review and decide on the PR/issue.

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions