Skip to content

user annotations in patterns #54757

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

Merged
merged 6 commits into from
Oct 9, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions src/librustc/mir/visit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -214,7 +214,7 @@ macro_rules! make_mir_visitor {
self.super_ty(ty);
}

fn visit_canonical_ty(&mut self, ty: & $($mutability)* CanonicalTy<'tcx>) {
fn visit_user_ty(&mut self, ty: & $($mutability)* CanonicalTy<'tcx>) {
self.super_canonical_ty(ty);
}

Expand Down Expand Up @@ -640,7 +640,7 @@ macro_rules! make_mir_visitor {
c_ty: & $($mutability)* CanonicalTy<'tcx>,
location: Location) {
self.visit_place(place, PlaceContext::Validate, location);
self.visit_canonical_ty(c_ty);
self.visit_user_ty(c_ty);
}

fn super_place(&mut self,
Expand Down Expand Up @@ -736,7 +736,7 @@ macro_rules! make_mir_visitor {
source_info: *source_info,
});
if let Some(user_ty) = user_ty {
self.visit_canonical_ty(user_ty);
self.visit_user_ty(user_ty);
}
self.visit_source_info(source_info);
self.visit_source_scope(visibility_scope);
Expand Down
23 changes: 9 additions & 14 deletions src/librustc_mir/borrow_check/nll/renumber.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@

use rustc::ty::subst::Substs;
use rustc::ty::{self, CanonicalTy, ClosureSubsts, GeneratorSubsts, Ty, TypeFoldable};
use rustc::mir::{BasicBlock, Location, Mir, Place, Statement, StatementKind};
use rustc::mir::{BasicBlock, Location, Mir, Statement, StatementKind};
use rustc::mir::visit::{MutVisitor, TyContext};
use rustc::infer::{InferCtxt, NLLRegionVariableOrigin};

Expand Down Expand Up @@ -65,6 +65,14 @@ impl<'a, 'gcx, 'tcx> MutVisitor<'tcx> for NLLVisitor<'a, 'gcx, 'tcx> {
debug!("visit_ty: ty={:?}", ty);
}

fn visit_user_ty(&mut self, _ty: &mut CanonicalTy<'tcx>) {
// `user_ty` annotations represent the types that the user
// wrote in the progarm. We don't want to erase the regions
// from these types: rather, we want to add them as
// constraints at type-check time.
debug!("visit_user_ty: skipping renumber");
}

fn visit_substs(&mut self, substs: &mut &'tcx Substs<'tcx>, location: Location) {
debug!("visit_substs(substs={:?}, location={:?})", substs, location);

Expand Down Expand Up @@ -112,19 +120,6 @@ impl<'a, 'gcx, 'tcx> MutVisitor<'tcx> for NLLVisitor<'a, 'gcx, 'tcx> {
debug!("visit_closure_substs: substs={:?}", substs);
}

fn visit_ascribe_user_ty(
&mut self,
_place: &mut Place<'tcx>,
_variance: &mut ty::Variance,
_c_ty: &mut CanonicalTy<'tcx>,
_location: Location,
) {
// User-assert-ty statements represent types that the user added explicitly.
// We don't want to erase the regions from these types: rather, we want to
// add them as constraints at type-check time.
debug!("visit_user_assert_ty: skipping renumber");
}

fn visit_statement(
&mut self,
block: BasicBlock,
Expand Down
8 changes: 8 additions & 0 deletions src/librustc_mir/build/matches/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1307,6 +1307,14 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
) {
for ascription in ascriptions {
let source_info = self.source_info(ascription.span);

debug!(
"adding user ascription at span {:?} of place {:?} and {:?}",
source_info.span,
ascription.source,
ascription.user_ty,
);

self.cfg.push(
block,
Statement {
Expand Down
46 changes: 8 additions & 38 deletions src/librustc_mir/hair/cx/expr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ use rustc_data_structures::indexed_vec::Idx;
use hair::cx::Cx;
use hair::cx::block;
use hair::cx::to_ref::ToRef;
use hair::util::UserAnnotatedTyHelpers;
use rustc::hir::def::{Def, CtorKind};
use rustc::mir::interpret::GlobalId;
use rustc::ty::{self, AdtKind, Ty};
Expand Down Expand Up @@ -475,7 +476,7 @@ fn make_mirror_unadjusted<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
adt_def: adt,
variant_index: 0,
substs,
user_ty: user_annotated_ty_for_adt(cx, expr.hir_id, adt),
user_ty: cx.user_substs_applied_to_adt(expr.hir_id, adt),
fields: field_refs(cx, fields),
base: base.as_ref().map(|base| {
FruInfo {
Expand All @@ -501,7 +502,7 @@ fn make_mirror_unadjusted<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
adt_def: adt,
variant_index: index,
substs,
user_ty: user_annotated_ty_for_adt(cx, expr.hir_id, adt),
user_ty: cx.user_substs_applied_to_adt(expr.hir_id, adt),
fields: field_refs(cx, fields),
base: None,
}
Expand Down Expand Up @@ -787,48 +788,17 @@ fn user_annotated_ty_for_def(
// user.
Def::StructCtor(_def_id, CtorKind::Const) |
Def::VariantCtor(_def_id, CtorKind::Const) =>
match &cx.tables().node_id_to_type(hir_id).sty {
ty::Adt(adt_def, _) => user_annotated_ty_for_adt(cx, hir_id, adt_def),
sty => bug!("unexpected sty: {:?}", sty),
},
cx.user_substs_applied_to_ty_of_hir_id(hir_id),

// `Self` is used in expression as a tuple struct constructor or an unit struct constructor
Def::SelfCtor(_) => {
let sty = &cx.tables().node_id_to_type(hir_id).sty;
match sty {
ty::FnDef(ref def_id, _) => {
Some(cx.tables().user_substs(hir_id)?.unchecked_map(|user_substs| {
// Here, we just pair a `DefId` with the
// `user_substs`, so no new types etc are introduced.
cx.tcx().mk_fn_def(*def_id, user_substs)
}))
}
ty::Adt(ref adt_def, _) => {
user_annotated_ty_for_adt(cx, hir_id, adt_def)
}
_ => {
bug!("unexpected sty: {:?}", sty)
}
}
}
Def::SelfCtor(_) =>
cx.user_substs_applied_to_ty_of_hir_id(hir_id),

_ =>
bug!("user_annotated_ty_for_def: unexpected def {:?} at {:?}", def, hir_id)
}
}

fn user_annotated_ty_for_adt(
cx: &mut Cx<'a, 'gcx, 'tcx>,
hir_id: hir::HirId,
adt_def: &'tcx AdtDef,
) -> Option<CanonicalTy<'tcx>> {
let user_substs = cx.tables().user_substs(hir_id)?;
Some(user_substs.unchecked_map(|user_substs| {
// Here, we just pair an `AdtDef` with the
// `user_substs`, so no new types etc are introduced.
cx.tcx().mk_adt(adt_def, user_substs)
}))
}

fn method_callee<'a, 'gcx, 'tcx>(
cx: &mut Cx<'a, 'gcx, 'tcx>,
expr: &hir::Expr,
Expand Down Expand Up @@ -943,7 +913,7 @@ fn convert_path_expr<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
adt_def,
variant_index: adt_def.variant_index_with_id(def_id),
substs,
user_ty: user_annotated_ty_for_adt(cx, expr.hir_id, adt_def),
user_ty: cx.user_substs_applied_to_adt(expr.hir_id, adt_def),
fields: vec![],
base: None,
}
Expand Down
11 changes: 11 additions & 0 deletions src/librustc_mir/hair/cx/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
//!

use hair::*;
use hair::util::UserAnnotatedTyHelpers;

use rustc_data_structures::indexed_vec::Idx;
use rustc::hir::def_id::{DefId, LOCAL_CRATE};
Expand Down Expand Up @@ -272,6 +273,16 @@ impl<'a, 'gcx, 'tcx> Cx<'a, 'gcx, 'tcx> {
}
}

impl UserAnnotatedTyHelpers<'gcx, 'tcx> for Cx<'_, 'gcx, 'tcx> {
fn tcx(&self) -> TyCtxt<'_, 'gcx, 'tcx> {
self.tcx()
}

fn tables(&self) -> &ty::TypeckTables<'tcx> {
self.tables()
}
}

fn lint_level_for_hir_id(tcx: TyCtxt, mut id: ast::NodeId) -> ast::NodeId {
// Right now we insert a `with_ignore` node in the dep graph here to
// ignore the fact that `lint_levels` below depends on the entire crate.
Expand Down
2 changes: 2 additions & 0 deletions src/librustc_mir/hair/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,8 @@ pub mod cx;
pub mod pattern;
pub use self::pattern::{BindingMode, Pattern, PatternKind, FieldPattern};

mod util;

#[derive(Copy, Clone, Debug)]
pub enum LintLevel {
Inherited,
Expand Down
47 changes: 39 additions & 8 deletions src/librustc_mir/hair/pattern/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@ pub(crate) use self::check_match::check_match;

use const_eval::{const_field, const_variant_index};

use hair::util::UserAnnotatedTyHelpers;

use rustc::mir::{fmt_const_val, Field, BorrowKind, Mutability};
use rustc::mir::interpret::{Scalar, GlobalId, ConstValue, sign_extend};
use rustc::ty::{self, CanonicalTy, TyCtxt, AdtDef, Ty, Region};
Expand Down Expand Up @@ -529,8 +531,9 @@ impl<'a, 'tcx> PatternContext<'a, 'tcx> {
field: Field::new(i),
pattern: self.lower_pattern(field),
})
.collect();
self.lower_variant_or_leaf(def, pat.span, ty, subpatterns)
.collect();

self.lower_variant_or_leaf(def, pat.hir_id, pat.span, ty, subpatterns)
}

PatKind::Struct(ref qpath, ref fields, _) => {
Expand All @@ -546,7 +549,7 @@ impl<'a, 'tcx> PatternContext<'a, 'tcx> {
})
.collect();

self.lower_variant_or_leaf(def, pat.span, ty, subpatterns)
self.lower_variant_or_leaf(def, pat.hir_id, pat.span, ty, subpatterns)
}
};

Expand Down Expand Up @@ -637,12 +640,12 @@ impl<'a, 'tcx> PatternContext<'a, 'tcx> {
fn lower_variant_or_leaf(
&mut self,
def: Def,
hir_id: hir::HirId,
span: Span,
ty: Ty<'tcx>,
subpatterns: Vec<FieldPattern<'tcx>>)
-> PatternKind<'tcx>
{
match def {
subpatterns: Vec<FieldPattern<'tcx>>,
) -> PatternKind<'tcx> {
let mut kind = match def {
Def::Variant(variant_id) | Def::VariantCtor(variant_id, ..) => {
let enum_id = self.tcx.parent_def_id(variant_id).unwrap();
let adt_def = self.tcx.adt_def(enum_id);
Expand Down Expand Up @@ -675,7 +678,24 @@ impl<'a, 'tcx> PatternContext<'a, 'tcx> {
self.errors.push(PatternError::NonConstPath(span));
PatternKind::Wild
}
};

if let Some(user_ty) = self.user_substs_applied_to_ty_of_hir_id(hir_id) {
let subpattern = Pattern {
span,
ty,
kind: Box::new(kind),
};

debug!("pattern user_ty = {:?} for pattern at {:?}", user_ty, span);

kind = PatternKind::AscribeUserType {
subpattern,
user_ty,
};
}

kind
}

/// Takes a HIR Path. If the path is a constant, evaluates it and feeds
Expand Down Expand Up @@ -729,7 +749,7 @@ impl<'a, 'tcx> PatternContext<'a, 'tcx> {
},
}
}
_ => self.lower_variant_or_leaf(def, span, ty, vec![]),
_ => self.lower_variant_or_leaf(def, id, span, ty, vec![]),
};

Pattern {
Expand Down Expand Up @@ -894,6 +914,17 @@ impl<'a, 'tcx> PatternContext<'a, 'tcx> {
}
}

impl UserAnnotatedTyHelpers<'tcx, 'tcx> for PatternContext<'_, 'tcx> {
fn tcx(&self) -> TyCtxt<'_, 'tcx, 'tcx> {
self.tcx
}

fn tables(&self) -> &ty::TypeckTables<'tcx> {
self.tables
}
}


pub trait PatternFoldable<'tcx> : Sized {
fn fold_with<F: PatternFolder<'tcx>>(&self, folder: &mut F) -> Self {
self.super_fold_with(folder)
Expand Down
56 changes: 56 additions & 0 deletions src/librustc_mir/hair/util.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

use rustc::hir;
use rustc::ty::{self, AdtDef, CanonicalTy, TyCtxt};

crate trait UserAnnotatedTyHelpers<'gcx: 'tcx, 'tcx> {
fn tcx(&self) -> TyCtxt<'_, 'gcx, 'tcx>;

fn tables(&self) -> &ty::TypeckTables<'tcx>;

fn user_substs_applied_to_adt(
&self,
hir_id: hir::HirId,
adt_def: &'tcx AdtDef,
) -> Option<CanonicalTy<'tcx>> {
let user_substs = self.tables().user_substs(hir_id)?;
Some(user_substs.unchecked_map(|user_substs| {
// Here, we just pair an `AdtDef` with the
// `user_substs`, so no new types etc are introduced.
self.tcx().mk_adt(adt_def, user_substs)
}))
}

/// Looks up the type associated with this hir-id and applies the
/// user-given substitutions; the hir-id must map to a suitable
/// type.
fn user_substs_applied_to_ty_of_hir_id(&self, hir_id: hir::HirId) -> Option<CanonicalTy<'tcx>> {
let user_substs = self.tables().user_substs(hir_id)?;
match &self.tables().node_id_to_type(hir_id).sty {
ty::Adt(adt_def, _) => Some(user_substs.unchecked_map(|user_substs| {
// Ok to call `unchecked_map` because we just pair an
// `AdtDef` with the `user_substs`, so no new types
// etc are introduced.
self.tcx().mk_adt(adt_def, user_substs)
})),
ty::FnDef(def_id, _) => Some(user_substs.unchecked_map(|user_substs| {
// Here, we just pair a `DefId` with the
// `user_substs`, so no new types etc are introduced.
self.tcx().mk_fn_def(*def_id, user_substs)
})),
sty => bug!(
"sty: {:?} should not have user-substs {:?} recorded ",
sty,
user_substs
),
}
}
}
Loading