1
Fork 0

introduce a UserTypeAnnotation enum

This commit is contained in:
Niko Matsakis 2018-10-10 17:07:10 -04:00
parent e339e84fff
commit aed6e4a083
13 changed files with 126 additions and 88 deletions

View file

@ -587,3 +587,16 @@ impl<'a, 'gcx> HashStable<StableHashingContext<'a>> for mir::ClosureOutlivesSubj
} }
impl_stable_hash_for!(struct mir::interpret::GlobalId<'tcx> { instance, promoted }); impl_stable_hash_for!(struct mir::interpret::GlobalId<'tcx> { instance, promoted });
impl<'a, 'gcx> HashStable<StableHashingContext<'a>> for mir::UserTypeAnnotation<'gcx> {
fn hash_stable<W: StableHasherResult>(&self,
hcx: &mut StableHashingContext<'a>,
hasher: &mut StableHasher<W>) {
mem::discriminant(self).hash_stable(hcx, hasher);
match *self {
mir::UserTypeAnnotation::Ty(ref ty) => {
ty.hash_stable(hcx, hasher);
}
}
}
}

View file

@ -710,7 +710,7 @@ pub struct LocalDecl<'tcx> {
/// e.g. via `let x: T`, then we carry that type here. The MIR /// e.g. via `let x: T`, then we carry that type here. The MIR
/// borrow checker needs this information since it can affect /// borrow checker needs this information since it can affect
/// region inference. /// region inference.
pub user_ty: Option<(CanonicalTy<'tcx>, Span)>, pub user_ty: Option<(UserTypeAnnotation<'tcx>, Span)>,
/// Name of the local, used in debuginfo and pretty-printing. /// Name of the local, used in debuginfo and pretty-printing.
/// ///
@ -1737,7 +1737,7 @@ pub enum StatementKind<'tcx> {
/// - `Contravariant` -- requires that `T_y :> T` /// - `Contravariant` -- requires that `T_y :> T`
/// - `Invariant` -- requires that `T_y == T` /// - `Invariant` -- requires that `T_y == T`
/// - `Bivariant` -- no effect /// - `Bivariant` -- no effect
AscribeUserType(Place<'tcx>, ty::Variance, CanonicalTy<'tcx>), AscribeUserType(Place<'tcx>, ty::Variance, UserTypeAnnotation<'tcx>),
/// No-op. Useful for deleting instructions without affecting statement indices. /// No-op. Useful for deleting instructions without affecting statement indices.
Nop, Nop,
@ -2188,7 +2188,7 @@ pub enum AggregateKind<'tcx> {
&'tcx AdtDef, &'tcx AdtDef,
usize, usize,
&'tcx Substs<'tcx>, &'tcx Substs<'tcx>,
Option<CanonicalTy<'tcx>>, Option<UserTypeAnnotation<'tcx>>,
Option<usize>, Option<usize>,
), ),
@ -2392,7 +2392,7 @@ impl<'tcx> Debug for Rvalue<'tcx> {
/// this does not necessarily mean that they are "==" in Rust -- in /// this does not necessarily mean that they are "==" in Rust -- in
/// particular one must be wary of `NaN`! /// particular one must be wary of `NaN`!
#[derive(Clone, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable)] #[derive(Copy, Clone, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable)]
pub struct Constant<'tcx> { pub struct Constant<'tcx> {
pub span: Span, pub span: Span,
pub ty: Ty<'tcx>, pub ty: Ty<'tcx>,
@ -2402,11 +2402,25 @@ pub struct Constant<'tcx> {
/// indicate that `Vec<_>` was explicitly specified. /// indicate that `Vec<_>` was explicitly specified.
/// ///
/// Needed for NLL to impose user-given type constraints. /// Needed for NLL to impose user-given type constraints.
pub user_ty: Option<CanonicalTy<'tcx>>, pub user_ty: Option<UserTypeAnnotation<'tcx>>,
pub literal: &'tcx ty::Const<'tcx>, pub literal: &'tcx ty::Const<'tcx>,
} }
/// A user-given type annotation attached to a constant. These arise
/// from constants that are named via paths, like `Foo::<A>::new` and
/// so forth.
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable)]
pub enum UserTypeAnnotation<'tcx> {
Ty(CanonicalTy<'tcx>),
}
EnumTypeFoldableImpl! {
impl<'tcx> TypeFoldable<'tcx> for UserTypeAnnotation<'tcx> {
(UserTypeAnnotation::Ty)(ty),
}
}
newtype_index! { newtype_index! {
pub struct Promoted { pub struct Promoted {
DEBUG_FORMAT = "promoted[{}]" DEBUG_FORMAT = "promoted[{}]"

View file

@ -10,7 +10,7 @@
use hir::def_id::DefId; use hir::def_id::DefId;
use ty::subst::Substs; use ty::subst::Substs;
use ty::{CanonicalTy, ClosureSubsts, GeneratorSubsts, Region, Ty}; use ty::{ClosureSubsts, GeneratorSubsts, Region, Ty};
use mir::*; use mir::*;
use syntax_pos::Span; use syntax_pos::Span;
@ -147,9 +147,9 @@ macro_rules! make_mir_visitor {
fn visit_ascribe_user_ty(&mut self, fn visit_ascribe_user_ty(&mut self,
place: & $($mutability)* Place<'tcx>, place: & $($mutability)* Place<'tcx>,
variance: & $($mutability)* ty::Variance, variance: & $($mutability)* ty::Variance,
c_ty: & $($mutability)* CanonicalTy<'tcx>, user_ty: & $($mutability)* UserTypeAnnotation<'tcx>,
location: Location) { location: Location) {
self.super_ascribe_user_ty(place, variance, c_ty, location); self.super_ascribe_user_ty(place, variance, user_ty, location);
} }
fn visit_place(&mut self, fn visit_place(&mut self,
@ -214,8 +214,8 @@ macro_rules! make_mir_visitor {
self.super_ty(ty); self.super_ty(ty);
} }
fn visit_user_ty(&mut self, ty: & $($mutability)* CanonicalTy<'tcx>) { fn visit_user_type_annotation(&mut self, ty: & $($mutability)* UserTypeAnnotation<'tcx>) {
self.super_canonical_ty(ty); self.super_user_type_annotation(ty);
} }
fn visit_region(&mut self, fn visit_region(&mut self,
@ -390,9 +390,9 @@ macro_rules! make_mir_visitor {
StatementKind::AscribeUserType( StatementKind::AscribeUserType(
ref $($mutability)* place, ref $($mutability)* place,
ref $($mutability)* variance, ref $($mutability)* variance,
ref $($mutability)* c_ty, ref $($mutability)* user_ty,
) => { ) => {
self.visit_ascribe_user_ty(place, variance, c_ty, location); self.visit_ascribe_user_ty(place, variance, user_ty, location);
} }
StatementKind::Nop => {} StatementKind::Nop => {}
} }
@ -637,10 +637,10 @@ macro_rules! make_mir_visitor {
fn super_ascribe_user_ty(&mut self, fn super_ascribe_user_ty(&mut self,
place: & $($mutability)* Place<'tcx>, place: & $($mutability)* Place<'tcx>,
_variance: & $($mutability)* ty::Variance, _variance: & $($mutability)* ty::Variance,
c_ty: & $($mutability)* CanonicalTy<'tcx>, user_ty: & $($mutability)* UserTypeAnnotation<'tcx>,
location: Location) { location: Location) {
self.visit_place(place, PlaceContext::Validate, location); self.visit_place(place, PlaceContext::Validate, location);
self.visit_user_ty(c_ty); self.visit_user_type_annotation(user_ty);
} }
fn super_place(&mut self, fn super_place(&mut self,
@ -736,7 +736,7 @@ macro_rules! make_mir_visitor {
source_info: *source_info, source_info: *source_info,
}); });
if let Some((user_ty, _)) = user_ty { if let Some((user_ty, _)) = user_ty {
self.visit_user_ty(user_ty); self.visit_user_type_annotation(user_ty);
} }
self.visit_source_info(source_info); self.visit_source_info(source_info);
self.visit_source_scope(visibility_scope); self.visit_source_scope(visibility_scope);
@ -783,7 +783,7 @@ macro_rules! make_mir_visitor {
self.visit_source_scope(scope); self.visit_source_scope(scope);
} }
fn super_canonical_ty(&mut self, _ty: & $($mutability)* CanonicalTy<'tcx>) { fn super_user_type_annotation(&mut self, _ty: & $($mutability)* UserTypeAnnotation<'tcx>) {
} }
fn super_ty(&mut self, _ty: & $($mutability)* Ty<'tcx>) { fn super_ty(&mut self, _ty: & $($mutability)* Ty<'tcx>) {

View file

@ -18,9 +18,10 @@ use rustc::mir::visit::TyContext;
use rustc::mir::visit::Visitor; use rustc::mir::visit::Visitor;
use rustc::mir::{BasicBlock, BasicBlockData, Location, Mir, Place, Rvalue}; use rustc::mir::{BasicBlock, BasicBlockData, Location, Mir, Place, Rvalue};
use rustc::mir::{Statement, Terminator}; use rustc::mir::{Statement, Terminator};
use rustc::mir::UserTypeAnnotation;
use rustc::ty::fold::TypeFoldable; use rustc::ty::fold::TypeFoldable;
use rustc::ty::subst::Substs; use rustc::ty::subst::Substs;
use rustc::ty::{self, CanonicalTy, ClosureSubsts, GeneratorSubsts, RegionVid}; use rustc::ty::{self, ClosureSubsts, GeneratorSubsts, RegionVid};
pub(super) fn generate_constraints<'cx, 'gcx, 'tcx>( pub(super) fn generate_constraints<'cx, 'gcx, 'tcx>(
infcx: &InferCtxt<'cx, 'gcx, 'tcx>, infcx: &InferCtxt<'cx, 'gcx, 'tcx>,
@ -179,7 +180,7 @@ impl<'cg, 'cx, 'gcx, 'tcx> Visitor<'tcx> for ConstraintGeneration<'cg, 'cx, 'gcx
&mut self, &mut self,
_place: &Place<'tcx>, _place: &Place<'tcx>,
_variance: &ty::Variance, _variance: &ty::Variance,
_c_ty: &CanonicalTy<'tcx>, _user_ty: &UserTypeAnnotation<'tcx>,
_location: Location, _location: Location,
) { ) {
} }

View file

@ -9,8 +9,8 @@
// except according to those terms. // except according to those terms.
use rustc::ty::subst::Substs; use rustc::ty::subst::Substs;
use rustc::ty::{self, CanonicalTy, ClosureSubsts, GeneratorSubsts, Ty, TypeFoldable}; use rustc::ty::{self, ClosureSubsts, GeneratorSubsts, Ty, TypeFoldable};
use rustc::mir::{BasicBlock, Location, Mir, Statement, StatementKind}; use rustc::mir::{BasicBlock, Location, Mir, Statement, StatementKind, UserTypeAnnotation};
use rustc::mir::visit::{MutVisitor, TyContext}; use rustc::mir::visit::{MutVisitor, TyContext};
use rustc::infer::{InferCtxt, NLLRegionVariableOrigin}; use rustc::infer::{InferCtxt, NLLRegionVariableOrigin};
@ -65,12 +65,12 @@ impl<'a, 'gcx, 'tcx> MutVisitor<'tcx> for NLLVisitor<'a, 'gcx, 'tcx> {
debug!("visit_ty: ty={:?}", ty); debug!("visit_ty: ty={:?}", ty);
} }
fn visit_user_ty(&mut self, _ty: &mut CanonicalTy<'tcx>) { fn visit_user_type_annotation(&mut self, _ty: &mut UserTypeAnnotation<'tcx>) {
// `user_ty` annotations represent the types that the user // User type annotations represent the types that the user
// wrote in the progarm. We don't want to erase the regions // wrote in the progarm. We don't want to erase the regions
// from these types: rather, we want to add them as // from these types: rather, we want to add them as
// constraints at type-check time. // constraints at type-check time.
debug!("visit_user_ty: skipping renumber"); debug!("visit_user_type_annotation: skipping renumber");
} }
fn visit_substs(&mut self, substs: &mut &'tcx Substs<'tcx>, location: Location) { fn visit_substs(&mut self, substs: &mut &'tcx Substs<'tcx>, location: Location) {

View file

@ -43,7 +43,7 @@ use rustc::traits::query::{Fallible, NoSolution};
use rustc::traits::{ObligationCause, PredicateObligations}; use rustc::traits::{ObligationCause, PredicateObligations};
use rustc::ty::fold::TypeFoldable; use rustc::ty::fold::TypeFoldable;
use rustc::ty::subst::{Subst, UnpackedKind}; use rustc::ty::subst::{Subst, UnpackedKind};
use rustc::ty::{self, CanonicalTy, RegionVid, ToPolyTraitRef, Ty, TyCtxt, TyKind}; use rustc::ty::{self, RegionVid, ToPolyTraitRef, Ty, TyCtxt, TyKind};
use std::rc::Rc; use std::rc::Rc;
use std::{fmt, iter}; use std::{fmt, iter};
use syntax_pos::{Span, DUMMY_SP}; use syntax_pos::{Span, DUMMY_SP};
@ -966,7 +966,7 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> {
&mut self, &mut self,
a: Ty<'tcx>, a: Ty<'tcx>,
v: ty::Variance, v: ty::Variance,
b: CanonicalTy<'tcx>, b: UserTypeAnnotation<'tcx>,
locations: Locations, locations: Locations,
category: ConstraintCategory, category: ConstraintCategory,
) -> Fallible<()> { ) -> Fallible<()> {
@ -1837,7 +1837,7 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> {
/// If this rvalue supports a user-given type annotation, then /// If this rvalue supports a user-given type annotation, then
/// extract and return it. This represents the final type of the /// extract and return it. This represents the final type of the
/// rvalue and will be unified with the inferred type. /// rvalue and will be unified with the inferred type.
fn rvalue_user_ty(&self, rvalue: &Rvalue<'tcx>) -> Option<CanonicalTy<'tcx>> { fn rvalue_user_ty(&self, rvalue: &Rvalue<'tcx>) -> Option<UserTypeAnnotation<'tcx>> {
match rvalue { match rvalue {
Rvalue::Use(_) Rvalue::Use(_)
| Rvalue::Repeat(..) | Rvalue::Repeat(..)

View file

@ -10,12 +10,12 @@
use borrow_check::nll::constraints::OutlivesConstraint; use borrow_check::nll::constraints::OutlivesConstraint;
use borrow_check::nll::type_check::{BorrowCheckContext, Locations}; use borrow_check::nll::type_check::{BorrowCheckContext, Locations};
use rustc::infer::{InferCtxt, NLLRegionVariableOrigin};
use rustc::infer::nll_relate::{TypeRelating, TypeRelatingDelegate}; use rustc::infer::nll_relate::{TypeRelating, TypeRelatingDelegate};
use rustc::mir::ConstraintCategory; use rustc::infer::{InferCtxt, NLLRegionVariableOrigin};
use rustc::mir::{ConstraintCategory, UserTypeAnnotation};
use rustc::traits::query::Fallible; use rustc::traits::query::Fallible;
use rustc::ty::relate::TypeRelation; use rustc::ty::relate::TypeRelation;
use rustc::ty::{self, CanonicalTy, Ty}; use rustc::ty::{self, Ty};
use syntax_pos::DUMMY_SP; use syntax_pos::DUMMY_SP;
/// Adds sufficient constraints to ensure that `a <: b`. /// Adds sufficient constraints to ensure that `a <: b`.
@ -61,20 +61,21 @@ pub(super) fn relate_type_and_user_type<'tcx>(
infcx: &InferCtxt<'_, '_, 'tcx>, infcx: &InferCtxt<'_, '_, 'tcx>,
a: Ty<'tcx>, a: Ty<'tcx>,
v: ty::Variance, v: ty::Variance,
canonical_b: CanonicalTy<'tcx>, user_ty: UserTypeAnnotation<'tcx>,
locations: Locations, locations: Locations,
category: ConstraintCategory, category: ConstraintCategory,
borrowck_context: Option<&mut BorrowCheckContext<'_, 'tcx>>, borrowck_context: Option<&mut BorrowCheckContext<'_, 'tcx>>,
) -> Fallible<Ty<'tcx>> { ) -> Fallible<Ty<'tcx>> {
debug!( debug!(
"relate_type_and_user_type(a={:?}, v={:?}, b={:?}, locations={:?})", "relate_type_and_user_type(a={:?}, v={:?}, b={:?}, locations={:?})",
a, v, canonical_b, locations a, v, user_ty, locations
); );
let (b, _values) = infcx.instantiate_canonical_with_fresh_inference_vars( let (b, _values) = match user_ty {
DUMMY_SP, UserTypeAnnotation::Ty(canonical_ty) => {
&canonical_b, infcx.instantiate_canonical_with_fresh_inference_vars(DUMMY_SP, &canonical_ty)
); }
};
// The `TypeRelating` code assumes that the "canonical variables" // The `TypeRelating` code assumes that the "canonical variables"
// appear in the "a" side, so flip `Contravariant` ambient // appear in the "a" side, so flip `Contravariant` ambient

View file

@ -20,7 +20,7 @@ use build::{GuardFrame, GuardFrameLocal, LocalsForNode};
use hair::*; use hair::*;
use rustc::hir; use rustc::hir;
use rustc::mir::*; use rustc::mir::*;
use rustc::ty::{self, CanonicalTy, Ty}; use rustc::ty::{self, Ty};
use rustc_data_structures::bit_set::BitSet; use rustc_data_structures::bit_set::BitSet;
use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::fx::FxHashMap;
use syntax::ast::{Name, NodeId}; use syntax::ast::{Name, NodeId};
@ -491,7 +491,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
pub fn visit_bindings( pub fn visit_bindings(
&mut self, &mut self,
pattern: &Pattern<'tcx>, pattern: &Pattern<'tcx>,
mut pattern_user_ty: Option<(CanonicalTy<'tcx>, Span)>, mut pattern_user_ty: Option<(UserTypeAnnotation<'tcx>, Span)>,
f: &mut impl FnMut( f: &mut impl FnMut(
&mut Self, &mut Self,
Mutability, Mutability,
@ -500,7 +500,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
NodeId, NodeId,
Span, Span,
Ty<'tcx>, Ty<'tcx>,
Option<(CanonicalTy<'tcx>, Span)>, Option<(UserTypeAnnotation<'tcx>, Span)>,
), ),
) { ) {
match *pattern.kind { match *pattern.kind {
@ -626,7 +626,7 @@ struct Binding<'tcx> {
struct Ascription<'tcx> { struct Ascription<'tcx> {
span: Span, span: Span,
source: Place<'tcx>, source: Place<'tcx>,
user_ty: CanonicalTy<'tcx>, user_ty: UserTypeAnnotation<'tcx>,
} }
#[derive(Clone, Debug)] #[derive(Clone, Debug)]
@ -1470,7 +1470,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
num_patterns: usize, num_patterns: usize,
var_id: NodeId, var_id: NodeId,
var_ty: Ty<'tcx>, var_ty: Ty<'tcx>,
user_var_ty: Option<(CanonicalTy<'tcx>, Span)>, user_var_ty: Option<(UserTypeAnnotation<'tcx>, Span)>,
has_guard: ArmHasGuard, has_guard: ArmHasGuard,
opt_match_place: Option<(Option<Place<'tcx>>, Span)>, opt_match_place: Option<(Option<Place<'tcx>>, Span)>,
pat_span: Span, pat_span: Span,

View file

@ -86,12 +86,12 @@ fn mirror_stmts<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
let mut pattern = cx.pattern_from_hir(&local.pat); let mut pattern = cx.pattern_from_hir(&local.pat);
if let Some(ty) = &local.ty { if let Some(ty) = &local.ty {
if let Some(user_ty) = cx.tables.user_provided_tys().get(ty.hir_id) { if let Some(&user_ty) = cx.tables.user_provided_tys().get(ty.hir_id) {
pattern = Pattern { pattern = Pattern {
ty: pattern.ty, ty: pattern.ty,
span: pattern.span, span: pattern.span,
kind: Box::new(PatternKind::AscribeUserType { kind: Box::new(PatternKind::AscribeUserType {
user_ty: *user_ty, user_ty: UserTypeAnnotation::Ty(user_ty),
user_ty_span: ty.span, user_ty_span: ty.span,
subpattern: pattern subpattern: pattern
}) })

View file

@ -296,11 +296,11 @@ fn make_mirror_unadjusted<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
let user_ty = cx.tables().user_substs(fun.hir_id) let user_ty = cx.tables().user_substs(fun.hir_id)
.map(|user_substs| { .map(|user_substs| {
user_substs.unchecked_map(|user_substs| { UserTypeAnnotation::Ty(user_substs.unchecked_map(|user_substs| {
// Here, we just pair an `AdtDef` with the // Here, we just pair an `AdtDef` with the
// `user_substs`, so no new types etc are introduced. // `user_substs`, so no new types etc are introduced.
cx.tcx().mk_adt(adt_def, user_substs) cx.tcx().mk_adt(adt_def, user_substs)
}) }))
}); });
let field_refs = args.iter() let field_refs = args.iter()
@ -725,9 +725,11 @@ fn make_mirror_unadjusted<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
} }
hir::ExprKind::Type(ref source, ref ty) => { hir::ExprKind::Type(ref source, ref ty) => {
let user_provided_tys = cx.tables.user_provided_tys(); let user_provided_tys = cx.tables.user_provided_tys();
let user_ty = *user_provided_tys let user_ty = UserTypeAnnotation::Ty(
*user_provided_tys
.get(ty.hir_id) .get(ty.hir_id)
.expect(&format!("{:?} not found in user_provided_tys, source: {:?}", ty, source)); .expect(&format!("{:?} not found in user_provided_tys, source: {:?}", ty, source))
);
if source.is_place_expr() { if source.is_place_expr() {
ExprKind::PlaceTypeAscription { ExprKind::PlaceTypeAscription {
source: source.to_ref(), source: source.to_ref(),
@ -763,7 +765,7 @@ fn user_substs_applied_to_def(
cx: &mut Cx<'a, 'gcx, 'tcx>, cx: &mut Cx<'a, 'gcx, 'tcx>,
hir_id: hir::HirId, hir_id: hir::HirId,
def: &Def, def: &Def,
) -> Option<CanonicalTy<'tcx>> { ) -> Option<UserTypeAnnotation<'tcx>> {
match def { match def {
// A reference to something callable -- e.g., a fn, method, or // A reference to something callable -- e.g., a fn, method, or
// a tuple-struct or tuple-variant. This has the type of a // a tuple-struct or tuple-variant. This has the type of a
@ -772,11 +774,14 @@ fn user_substs_applied_to_def(
Def::Method(_) | Def::Method(_) |
Def::StructCtor(_, CtorKind::Fn) | Def::StructCtor(_, CtorKind::Fn) |
Def::VariantCtor(_, CtorKind::Fn) => Def::VariantCtor(_, CtorKind::Fn) =>
Some(cx.tables().user_substs(hir_id)?.unchecked_map(|user_substs| { Some(
UserTypeAnnotation::Ty(cx.tables().user_substs(hir_id)?.unchecked_map(|user_substs| {
// Here, we just pair a `DefId` with the // Here, we just pair a `DefId` with the
// `user_substs`, so no new types etc are introduced. // `user_substs`, so no new types etc are introduced.
cx.tcx().mk_fn_def(def.def_id(), user_substs) cx.tcx().mk_fn_def(def.def_id(), user_substs)
})), }),
)
),
Def::Const(_def_id) | Def::Const(_def_id) |
Def::AssociatedConst(_def_id) => Def::AssociatedConst(_def_id) =>

View file

@ -14,11 +14,11 @@
//! unit-tested and separated from the Rust source and compiler data //! unit-tested and separated from the Rust source and compiler data
//! structures. //! structures.
use rustc::mir::{BinOp, BorrowKind, Field, UnOp}; use rustc::mir::{BinOp, BorrowKind, UserTypeAnnotation, Field, UnOp};
use rustc::hir::def_id::DefId; use rustc::hir::def_id::DefId;
use rustc::middle::region; use rustc::middle::region;
use rustc::ty::subst::Substs; use rustc::ty::subst::Substs;
use rustc::ty::{AdtDef, CanonicalTy, UpvarSubsts, Region, Ty, Const}; use rustc::ty::{AdtDef, UpvarSubsts, Region, Ty, Const};
use rustc::hir; use rustc::hir;
use syntax::ast; use syntax::ast;
use syntax_pos::Span; use syntax_pos::Span;
@ -268,7 +268,7 @@ pub enum ExprKind<'tcx> {
/// Optional user-given substs: for something like `let x = /// Optional user-given substs: for something like `let x =
/// Bar::<T> { ... }`. /// Bar::<T> { ... }`.
user_ty: Option<CanonicalTy<'tcx>>, user_ty: Option<UserTypeAnnotation<'tcx>>,
fields: Vec<FieldExprRef<'tcx>>, fields: Vec<FieldExprRef<'tcx>>,
base: Option<FruInfo<'tcx>> base: Option<FruInfo<'tcx>>
@ -276,12 +276,12 @@ pub enum ExprKind<'tcx> {
PlaceTypeAscription { PlaceTypeAscription {
source: ExprRef<'tcx>, source: ExprRef<'tcx>,
/// Type that the user gave to this expression /// Type that the user gave to this expression
user_ty: CanonicalTy<'tcx>, user_ty: UserTypeAnnotation<'tcx>,
}, },
ValueTypeAscription { ValueTypeAscription {
source: ExprRef<'tcx>, source: ExprRef<'tcx>,
/// Type that the user gave to this expression /// Type that the user gave to this expression
user_ty: CanonicalTy<'tcx>, user_ty: UserTypeAnnotation<'tcx>,
}, },
Closure { Closure {
closure_id: DefId, closure_id: DefId,
@ -291,13 +291,7 @@ pub enum ExprKind<'tcx> {
}, },
Literal { Literal {
literal: &'tcx Const<'tcx>, literal: &'tcx Const<'tcx>,
user_ty: Option<UserTypeAnnotation<'tcx>>,
/// Optional user-given type: for something like
/// `collect::<Vec<_>>`, this would be present and would
/// indicate that `Vec<_>` was explicitly specified.
///
/// Needed for NLL to impose user-given type constraints.
user_ty: Option<CanonicalTy<'tcx>>,
}, },
InlineAsm { InlineAsm {
asm: &'tcx hir::InlineAsm, asm: &'tcx hir::InlineAsm,

View file

@ -20,9 +20,9 @@ use const_eval::{const_field, const_variant_index};
use hair::util::UserAnnotatedTyHelpers; use hair::util::UserAnnotatedTyHelpers;
use rustc::mir::{fmt_const_val, Field, BorrowKind, Mutability}; use rustc::mir::{fmt_const_val, Field, BorrowKind, Mutability, UserTypeAnnotation};
use rustc::mir::interpret::{Scalar, GlobalId, ConstValue, sign_extend}; use rustc::mir::interpret::{Scalar, GlobalId, ConstValue, sign_extend};
use rustc::ty::{self, CanonicalTy, TyCtxt, AdtDef, Ty, Region}; use rustc::ty::{self, Region, TyCtxt, AdtDef, Ty};
use rustc::ty::subst::{Substs, Kind}; use rustc::ty::subst::{Substs, Kind};
use rustc::hir::{self, PatKind, RangeEnd}; use rustc::hir::{self, PatKind, RangeEnd};
use rustc::hir::def::{Def, CtorKind}; use rustc::hir::def::{Def, CtorKind};
@ -69,7 +69,7 @@ pub enum PatternKind<'tcx> {
Wild, Wild,
AscribeUserType { AscribeUserType {
user_ty: CanonicalTy<'tcx>, user_ty: UserTypeAnnotation<'tcx>,
subpattern: Pattern<'tcx>, subpattern: Pattern<'tcx>,
user_ty_span: Span, user_ty_span: Span,
}, },
@ -980,7 +980,7 @@ macro_rules! CloneImpls {
CloneImpls!{ <'tcx> CloneImpls!{ <'tcx>
Span, Field, Mutability, ast::Name, ast::NodeId, usize, &'tcx ty::Const<'tcx>, Span, Field, Mutability, ast::Name, ast::NodeId, usize, &'tcx ty::Const<'tcx>,
Region<'tcx>, Ty<'tcx>, BindingMode<'tcx>, &'tcx AdtDef, Region<'tcx>, Ty<'tcx>, BindingMode<'tcx>, &'tcx AdtDef,
&'tcx Substs<'tcx>, &'tcx Kind<'tcx>, CanonicalTy<'tcx> &'tcx Substs<'tcx>, &'tcx Kind<'tcx>, UserTypeAnnotation<'tcx>
} }
impl<'tcx> PatternFoldable<'tcx> for FieldPattern<'tcx> { impl<'tcx> PatternFoldable<'tcx> for FieldPattern<'tcx> {

View file

@ -9,7 +9,8 @@
// except according to those terms. // except according to those terms.
use rustc::hir; use rustc::hir;
use rustc::ty::{self, AdtDef, CanonicalTy, TyCtxt}; use rustc::mir::UserTypeAnnotation;
use rustc::ty::{self, AdtDef, TyCtxt};
crate trait UserAnnotatedTyHelpers<'gcx: 'tcx, 'tcx> { crate trait UserAnnotatedTyHelpers<'gcx: 'tcx, 'tcx> {
fn tcx(&self) -> TyCtxt<'_, 'gcx, 'tcx>; fn tcx(&self) -> TyCtxt<'_, 'gcx, 'tcx>;
@ -20,32 +21,41 @@ crate trait UserAnnotatedTyHelpers<'gcx: 'tcx, 'tcx> {
&self, &self,
hir_id: hir::HirId, hir_id: hir::HirId,
adt_def: &'tcx AdtDef, adt_def: &'tcx AdtDef,
) -> Option<CanonicalTy<'tcx>> { ) -> Option<UserTypeAnnotation<'tcx>> {
let user_substs = self.tables().user_substs(hir_id)?; let user_substs = self.tables().user_substs(hir_id)?;
Some(user_substs.unchecked_map(|user_substs| { Some(UserTypeAnnotation::Ty(user_substs.unchecked_map(
|user_substs| {
// Here, we just pair an `AdtDef` with the // Here, we just pair an `AdtDef` with the
// `user_substs`, so no new types etc are introduced. // `user_substs`, so no new types etc are introduced.
self.tcx().mk_adt(adt_def, user_substs) self.tcx().mk_adt(adt_def, user_substs)
})) },
)))
} }
/// Looks up the type associated with this hir-id and applies the /// Looks up the type associated with this hir-id and applies the
/// user-given substitutions; the hir-id must map to a suitable /// user-given substitutions; the hir-id must map to a suitable
/// type. /// type.
fn user_substs_applied_to_ty_of_hir_id(&self, hir_id: hir::HirId) -> Option<CanonicalTy<'tcx>> { fn user_substs_applied_to_ty_of_hir_id(
&self,
hir_id: hir::HirId,
) -> Option<UserTypeAnnotation<'tcx>> {
let user_substs = self.tables().user_substs(hir_id)?; let user_substs = self.tables().user_substs(hir_id)?;
match &self.tables().node_id_to_type(hir_id).sty { match &self.tables().node_id_to_type(hir_id).sty {
ty::Adt(adt_def, _) => Some(user_substs.unchecked_map(|user_substs| { ty::Adt(adt_def, _) => Some(UserTypeAnnotation::Ty(user_substs.unchecked_map(
|user_substs| {
// Ok to call `unchecked_map` because we just pair an // Ok to call `unchecked_map` because we just pair an
// `AdtDef` with the `user_substs`, so no new types // `AdtDef` with the `user_substs`, so no new types
// etc are introduced. // etc are introduced.
self.tcx().mk_adt(adt_def, user_substs) self.tcx().mk_adt(adt_def, user_substs)
})), },
ty::FnDef(def_id, _) => Some(user_substs.unchecked_map(|user_substs| { ))),
ty::FnDef(def_id, _) => Some(UserTypeAnnotation::Ty(user_substs.unchecked_map(
|user_substs| {
// Here, we just pair a `DefId` with the // Here, we just pair a `DefId` with the
// `user_substs`, so no new types etc are introduced. // `user_substs`, so no new types etc are introduced.
self.tcx().mk_fn_def(*def_id, user_substs) self.tcx().mk_fn_def(*def_id, user_substs)
})), },
))),
sty => bug!( sty => bug!(
"sty: {:?} should not have user-substs {:?} recorded ", "sty: {:?} should not have user-substs {:?} recorded ",
sty, sty,