Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

nll should preserve user types in type ascription #54331

Closed
nikomatsakis opened this issue Sep 18, 2018 · 1 comment
Closed

nll should preserve user types in type ascription #54331

nikomatsakis opened this issue Sep 18, 2018 · 1 comment
Assignees
Labels
A-NLL Area: Non-lexical lifetimes (NLL) NLL-sound Working towards the "invalid code does not compile" goal T-compiler Relevant to the compiler team, which will review and decide on the PR/issue.

Comments

@nikomatsakis
Copy link
Contributor

Spawned off from #47184. The following test case compiles, but it should not (playground):

#![allow(warnings)]
#![feature(nll)]
#![feature(type_ascription)]

fn main() {
    let x = 22_u32;
    let y: &u32 = &x: &'static u32;
}

The problem is that the "type ascription" expression is not preserving the full type that the user gave (&'static u32).

@nikomatsakis nikomatsakis added T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. A-NLL Area: Non-lexical lifetimes (NLL) labels Sep 18, 2018
@nikomatsakis nikomatsakis added this to the Edition 2018 RC 2 milestone Sep 18, 2018
@nikomatsakis
Copy link
Contributor Author

The first step to fix this is that we have to extend the HAIR to support user annotations. Currently we just remove ExprType ("type ascription") nodes when we create the HAIR:

hir::ExprKind::Type(ref source, _) => return source.make_mirror(cx),

So that means extending the HAIR ExprKind type:

pub enum ExprKind<'tcx> {

I imagine we would add a new variant like this:

/// Type ascription
ExprType {
    /// Type that the user gave to this expression
    user_ty: CanonicalTy<'tcx>,
}

We would then lower hir::ExprKind::Type to one of those nodes.

In order to populate it, we'll need to "preserve" the user-given type from the first round of type-checking. This is done via the user_provided_tys field in typeck-tables. An example where we do this is for local variables:

self.fcx.tables.borrow_mut().user_provided_tys_mut().insert(ty.hir_id, c_ty);

We would want to add similar code the ExprKind::Type case:

hir::ExprKind::Type(ref e, ref t) => {
let ty = self.to_ty(&t);
self.check_expr_eq_type(&e, ty);
ty
}

Here, we want to add something like

let c_ty = self.fcx.inh.infcx.canonicalize_response(&ty);
self.fcx.tables.borrow_mut().user_provided_tys_mut().insert(t.hir_id, c_ty);

When we lower the ExprKind::Type case, then, we can fetch the canonical type from the user_provided_tys using some code like this:

if let Some(user_ty) = cx.tables.user_provided_tys().get(ty.hir_id) {

Here, the key would be the hir_id of the type.

Then we have to modify the NLL type checker sort of like this code does:

if let Some(user_ty) = self.rvalue_user_ty(rv) {
if let Err(terr) = self.relate_type_and_user_type(
rv_ty,
ty::Variance::Invariant,
user_ty,
location.boring(),
) {
span_mirbug!(
self,
stmt,
"bad user type on rvalue ({:?} = {:?}): {:?}",
user_ty,
rv_ty,
terr
);
}
}

(In fact, I think we can then remove the user_ty field from ExprKind::Adt. We can instead represent it as an Adt wrapped in a Type. But that can happen later.)

@KiChjang KiChjang self-assigned this Sep 20, 2018
@matthewjasper matthewjasper added the NLL-sound Working towards the "invalid code does not compile" goal label Sep 22, 2018
bors added a commit that referenced this issue Oct 4, 2018
Lower type ascriptions to HAIR and MIR

Fixes #54331.

r? @nikomatsakis
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-NLL Area: Non-lexical lifetimes (NLL) NLL-sound Working towards the "invalid code does not compile" goal T-compiler Relevant to the compiler team, which will review and decide on the PR/issue.
Projects
None yet
Development

No branches or pull requests

3 participants