Skip to content

nll: respect user type annotations with constants in expressions #54571

Closed

Description

@nikomatsakis

Breaking out from #47184 as a subtask:

We need to respect user annotations when referencing constants in expressions. First job: come up with some test cases.

Activity

  1. added
    T-compilerRelevant to the compiler team, which will review and decide on the PR/issue.
    A-NLLArea: Non-lexical lifetimes (NLL)
    on Sep 25, 2018
  2. self-assigned this
    on Sep 25, 2018
  3. nikomatsakis commented on Sep 25, 2018

    @nikomatsakis
    ContributorAuthor

    Assigning to myself to investigate, write up some instructions, etc

  4. added
    NLL-soundWorking towards the "invalid code does not compile" goal
    on Sep 26, 2018
  5. nikomatsakis commented on Oct 2, 2018

    @nikomatsakis
    ContributorAuthor

    Test case #1 (should not compile, does):

    #![feature(nll)]
    
    trait Foo<'a> {
        const C: &'a u32;
    }
    
    impl<'a, T> Foo<'a> for T {
        const C: &'a u32 = &22;
    }
    
    fn foo<'a>(_: &'a u32) -> &'static u32 {
        <() as Foo<'a>>::C
    }
    
    fn main() {
    }
  6. nikomatsakis commented on Oct 2, 2018

    @nikomatsakis
    ContributorAuthor

    Test case #2 (same story):

    #![feature(nll)]
    
    struct Foo<'a> { x: &'a u32 }
    
    impl<'a> Foo<'a> {
        const C: &'a u32 = &22;
    }
    
    fn foo<'a>(_: &'a u32) -> &'static u32 {
        <Foo<'a>>::C
    }
    
    fn main() {
    }
  7. nikomatsakis commented on Oct 2, 2018

    @nikomatsakis
    ContributorAuthor

    Test case #3:

    #![feature(nll)]
    
    trait Foo<'a> {
        const C: &'a u32;
    }
    
    impl<'a, T> Foo<'a> for T {
        const C: &'a u32 = &22;
    }
    
    fn foo<'a, T: Foo<'a>>() -> &'static u32 {
        <T as Foo<'a>>::C
    }
    
    fn main() {
    }
  8. nikomatsakis commented on Oct 15, 2018

    @nikomatsakis
    ContributorAuthor

    The fix for this will have to build on #55093

  9. nikomatsakis commented on Oct 15, 2018

    @nikomatsakis
    ContributorAuthor

    That PR adds the ability for user type annotations to be more complex than they presently are. I think we need to extend the UserTypeAnnotation type to account for constants. In the branch, it is:

    pub enum UserTypeAnnotation<'tcx> {
        Ty(CanonicalTy<'tcx>),
        FnDef(DefId, CanonicalUserSubsts<'tcx>),
        AdtDef(&'tcx AdtDef, CanonicalUserSubsts<'tcx>),
    }

    So something like this:

    pub enum UserTypeAnnotation<'tcx> {
        Ty(CanonicalTy<'tcx>),
        FnDef(DefId, CanonicalUserSubsts<'tcx>),
        AdtDef(&'tcx AdtDef, CanonicalUserSubsts<'tcx>),
        ConstantDef(DefId, CanonicalUserSubsts<'tcx>),
    }

    Next, there is code that instantiates these "user type annotations" in various ways in:

    src/librustc_mir/borrow_check/nll/type_check/relate_tys.rs
    

    It looks sort of like this:

        match user_ty {
            UserTypeAnnotation::Ty(canonical_ty) => ...,
            UserTypeAnnotation::FnDef(def_id, canonical_substs) => ...,
            ...
        }

    I think we need to extend this with a case for ConstantDef -- or maybe we can actually adapt the FnDef code so it works for both cases (maybe even merge the two variants).

    It would work like so:

    • Instantiate the canonical_substs with fresh variables (like FnDef)
    • Fetch the type_of for def_id and substitute the canonical_substs (different from FnDef, but that same code would probably work for fns too)
    • Relate the types and apply the user_self_ty exactly as with FnDef

    If we do that, then the only thing we have left to do is to find the FIXME(#47184) spots that pertain to constants and propagate the user-substs onto those spots.

  10. nikomatsakis commented on Oct 17, 2018

    @nikomatsakis
    ContributorAuthor

    Fix in #55152

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

A-NLLArea: Non-lexical lifetimes (NLL)NLL-soundWorking towards the "invalid code does not compile" goalT-compilerRelevant to the compiler team, which will review and decide on the PR/issue.

Type

No type

Projects

No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions