Refactor UserTypeAnnotation.
This commit refactors the `UserTypeAnnotation` type to be referred to by an index within `UserTypeProjection`. `UserTypeAnnotation` is instead kept in an `IndexVec` within the `Mir` struct. Further, instead of `UserTypeAnnotation` containing canonicalized types, it now contains normal types and the entire `UserTypeAnnotation` is canonicalized. To support this, the type was moved from the `rustc::mir` module to `rustc::ty` module.
This commit is contained in:
parent
7155690ffc
commit
24a7a010d1
27 changed files with 485 additions and 364 deletions
|
|
@ -494,22 +494,5 @@ impl<'a, 'gcx> HashStable<StableHashingContext<'a>> for mir::ClosureOutlivesSubj
|
|||
|
||||
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);
|
||||
}
|
||||
mir::UserTypeAnnotation::TypeOf(ref def_id, ref substs) => {
|
||||
def_id.hash_stable(hcx, hasher);
|
||||
substs.hash_stable(hcx, hasher);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl_stable_hash_for!(struct mir::UserTypeProjection<'tcx> { base, projs });
|
||||
impl_stable_hash_for!(struct mir::UserTypeProjections<'tcx> { contents });
|
||||
|
|
|
|||
|
|
@ -1251,3 +1251,29 @@ impl_stable_hash_for!(
|
|||
goal,
|
||||
}
|
||||
);
|
||||
|
||||
impl<'a, 'gcx> HashStable<StableHashingContext<'a>> for ty::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 {
|
||||
ty::UserTypeAnnotation::Ty(ref ty) => {
|
||||
ty.hash_stable(hcx, hasher);
|
||||
}
|
||||
ty::UserTypeAnnotation::TypeOf(ref def_id, ref substs) => {
|
||||
def_id.hash_stable(hcx, hasher);
|
||||
substs.hash_stable(hcx, hasher);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> HashStable<StableHashingContext<'a>> for ty::UserTypeAnnotationIndex {
|
||||
#[inline]
|
||||
fn hash_stable<W: StableHasherResult>(&self,
|
||||
hcx: &mut StableHashingContext<'a>,
|
||||
hasher: &mut StableHasher<W>) {
|
||||
self.index().hash_stable(hcx, hasher);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -27,9 +27,12 @@ use syntax::ast::{self, Name};
|
|||
use syntax::symbol::InternedString;
|
||||
use syntax_pos::{Span, DUMMY_SP};
|
||||
use ty::fold::{TypeFoldable, TypeFolder, TypeVisitor};
|
||||
use ty::subst::{CanonicalUserSubsts, Subst, Substs};
|
||||
use ty::{self, AdtDef, CanonicalTy, ClosureSubsts, GeneratorSubsts, Region, Ty, TyCtxt};
|
||||
use ty::subst::{Subst, Substs};
|
||||
use ty::layout::VariantIdx;
|
||||
use ty::{
|
||||
self, AdtDef, CanonicalUserTypeAnnotations, ClosureSubsts, GeneratorSubsts, Region, Ty, TyCtxt,
|
||||
UserTypeAnnotationIndex, UserTypeAnnotation,
|
||||
};
|
||||
use util::ppaux;
|
||||
|
||||
pub use mir::interpret::AssertMessage;
|
||||
|
|
@ -121,6 +124,9 @@ pub struct Mir<'tcx> {
|
|||
/// variables and temporaries.
|
||||
pub local_decls: LocalDecls<'tcx>,
|
||||
|
||||
/// User type annotations
|
||||
pub user_type_annotations: CanonicalUserTypeAnnotations<'tcx>,
|
||||
|
||||
/// Number of arguments this function takes.
|
||||
///
|
||||
/// Starting at local 1, `arg_count` locals will be provided by the caller
|
||||
|
|
@ -161,7 +167,8 @@ impl<'tcx> Mir<'tcx> {
|
|||
source_scope_local_data: ClearCrossCrate<IndexVec<SourceScope, SourceScopeLocalData>>,
|
||||
promoted: IndexVec<Promoted, Mir<'tcx>>,
|
||||
yield_ty: Option<Ty<'tcx>>,
|
||||
local_decls: IndexVec<Local, LocalDecl<'tcx>>,
|
||||
local_decls: LocalDecls<'tcx>,
|
||||
user_type_annotations: CanonicalUserTypeAnnotations<'tcx>,
|
||||
arg_count: usize,
|
||||
upvar_decls: Vec<UpvarDecl>,
|
||||
span: Span,
|
||||
|
|
@ -185,6 +192,7 @@ impl<'tcx> Mir<'tcx> {
|
|||
generator_drop: None,
|
||||
generator_layout: None,
|
||||
local_decls,
|
||||
user_type_annotations,
|
||||
arg_count,
|
||||
upvar_decls,
|
||||
spread_arg: None,
|
||||
|
|
@ -418,6 +426,7 @@ impl_stable_hash_for!(struct Mir<'tcx> {
|
|||
generator_drop,
|
||||
generator_layout,
|
||||
local_decls,
|
||||
user_type_annotations,
|
||||
arg_count,
|
||||
upvar_decls,
|
||||
spread_arg,
|
||||
|
|
@ -2232,7 +2241,7 @@ pub enum AggregateKind<'tcx> {
|
|||
&'tcx AdtDef,
|
||||
VariantIdx,
|
||||
&'tcx Substs<'tcx>,
|
||||
Option<UserTypeAnnotation<'tcx>>,
|
||||
Option<UserTypeAnnotationIndex>,
|
||||
Option<usize>,
|
||||
),
|
||||
|
||||
|
|
@ -2446,38 +2455,11 @@ pub struct Constant<'tcx> {
|
|||
/// indicate that `Vec<_>` was explicitly specified.
|
||||
///
|
||||
/// Needed for NLL to impose user-given type constraints.
|
||||
pub user_ty: Option<UserTypeAnnotation<'tcx>>,
|
||||
pub user_ty: Option<UserTypeAnnotationIndex>,
|
||||
|
||||
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>),
|
||||
|
||||
/// The canonical type is the result of `type_of(def_id)` with the
|
||||
/// given substitutions applied.
|
||||
TypeOf(DefId, CanonicalUserSubsts<'tcx>),
|
||||
}
|
||||
|
||||
EnumTypeFoldableImpl! {
|
||||
impl<'tcx> TypeFoldable<'tcx> for UserTypeAnnotation<'tcx> {
|
||||
(UserTypeAnnotation::Ty)(ty),
|
||||
(UserTypeAnnotation::TypeOf)(def, substs),
|
||||
}
|
||||
}
|
||||
|
||||
EnumLiftImpl! {
|
||||
impl<'a, 'tcx> Lift<'tcx> for UserTypeAnnotation<'a> {
|
||||
type Lifted = UserTypeAnnotation<'tcx>;
|
||||
(UserTypeAnnotation::Ty)(ty),
|
||||
(UserTypeAnnotation::TypeOf)(def, substs),
|
||||
}
|
||||
}
|
||||
|
||||
/// A collection of projections into user types.
|
||||
///
|
||||
/// They are projections because a binding can occur a part of a
|
||||
|
|
@ -2556,7 +2538,7 @@ impl<'tcx> UserTypeProjections<'tcx> {
|
|||
/// determined by finding the type of the `.0` field from `T`.
|
||||
#[derive(Clone, Debug, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable)]
|
||||
pub struct UserTypeProjection<'tcx> {
|
||||
pub base: UserTypeAnnotation<'tcx>,
|
||||
pub base: UserTypeAnnotationIndex,
|
||||
pub projs: Vec<ProjectionElem<'tcx, (), ()>>,
|
||||
}
|
||||
|
||||
|
|
@ -2970,6 +2952,7 @@ CloneTypeFoldableAndLiftImpls! {
|
|||
SourceScope,
|
||||
SourceScopeData,
|
||||
SourceScopeLocalData,
|
||||
UserTypeAnnotationIndex,
|
||||
}
|
||||
|
||||
BraceStructTypeFoldableImpl! {
|
||||
|
|
@ -2983,6 +2966,7 @@ BraceStructTypeFoldableImpl! {
|
|||
generator_drop,
|
||||
generator_layout,
|
||||
local_decls,
|
||||
user_type_annotations,
|
||||
arg_count,
|
||||
upvar_decls,
|
||||
spread_arg,
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
use hir::def_id::DefId;
|
||||
use infer::canonical::Canonical;
|
||||
use ty::subst::Substs;
|
||||
use ty::{ClosureSubsts, GeneratorSubsts, Region, Ty};
|
||||
use mir::*;
|
||||
|
|
@ -219,9 +220,10 @@ macro_rules! make_mir_visitor {
|
|||
|
||||
fn visit_user_type_annotation(
|
||||
&mut self,
|
||||
ty: & $($mutability)* UserTypeAnnotation<'tcx>,
|
||||
index: UserTypeAnnotationIndex,
|
||||
ty: & $($mutability)* Canonical<'tcx, UserTypeAnnotation<'tcx>>,
|
||||
) {
|
||||
self.super_user_type_annotation(ty);
|
||||
self.super_user_type_annotation(index, ty);
|
||||
}
|
||||
|
||||
fn visit_region(&mut self,
|
||||
|
|
@ -307,6 +309,14 @@ macro_rules! make_mir_visitor {
|
|||
self.visit_local_decl(local, & $($mutability)* mir.local_decls[local]);
|
||||
}
|
||||
|
||||
for index in mir.user_type_annotations.indices() {
|
||||
let (span, annotation) = & $($mutability)* mir.user_type_annotations[index];
|
||||
self.visit_user_type_annotation(
|
||||
index, annotation
|
||||
);
|
||||
self.visit_span(span);
|
||||
}
|
||||
|
||||
self.visit_span(&$($mutability)* mir.span);
|
||||
}
|
||||
|
||||
|
|
@ -865,18 +875,14 @@ macro_rules! make_mir_visitor {
|
|||
|
||||
fn super_user_type_projection(
|
||||
&mut self,
|
||||
ty: & $($mutability)* UserTypeProjection<'tcx>,
|
||||
_ty: & $($mutability)* UserTypeProjection<'tcx>,
|
||||
) {
|
||||
let UserTypeProjection {
|
||||
ref $($mutability)* base,
|
||||
projs: _, // Note: Does not visit projection elems!
|
||||
} = *ty;
|
||||
self.visit_user_type_annotation(base);
|
||||
}
|
||||
|
||||
fn super_user_type_annotation(
|
||||
&mut self,
|
||||
_ty: & $($mutability)* UserTypeAnnotation<'tcx>,
|
||||
_index: UserTypeAnnotationIndex,
|
||||
_ty: & $($mutability)* Canonical<'tcx, UserTypeAnnotation<'tcx>>,
|
||||
) {
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@ use hir::map as hir_map;
|
|||
use hir::map::DefPathHash;
|
||||
use lint::{self, Lint};
|
||||
use ich::{StableHashingContext, NodeIdHashingMode};
|
||||
use infer::canonical::{CanonicalVarInfo, CanonicalVarInfos};
|
||||
use infer::canonical::{Canonical, CanonicalVarInfo, CanonicalVarInfos};
|
||||
use infer::outlives::free_region_map::FreeRegionMap;
|
||||
use middle::cstore::CrateStoreDyn;
|
||||
use middle::cstore::EncodedMetadata;
|
||||
|
|
@ -23,7 +23,7 @@ use middle::resolve_lifetime::{self, ObjectLifetimeDefault};
|
|||
use middle::stability;
|
||||
use mir::{self, Mir, interpret, ProjectionKind};
|
||||
use mir::interpret::Allocation;
|
||||
use ty::subst::{CanonicalUserSubsts, Kind, Substs, Subst};
|
||||
use ty::subst::{Kind, Substs, Subst};
|
||||
use ty::ReprOptions;
|
||||
use traits;
|
||||
use traits::{Clause, Clauses, GoalKind, Goal, Goals};
|
||||
|
|
@ -38,8 +38,8 @@ use ty::GenericParamDefKind;
|
|||
use ty::layout::{LayoutDetails, TargetDataLayout, VariantIdx};
|
||||
use ty::query;
|
||||
use ty::steal::Steal;
|
||||
use ty::BindingMode;
|
||||
use ty::CanonicalTy;
|
||||
use ty::subst::{UserSubsts, UnpackedKind};
|
||||
use ty::{BoundVar, BindingMode};
|
||||
use ty::CanonicalPolyFnSig;
|
||||
use util::nodemap::{DefIdMap, DefIdSet, ItemLocalMap};
|
||||
use util::nodemap::{FxHashMap, FxHashSet};
|
||||
|
|
@ -49,7 +49,7 @@ use rustc_data_structures::stable_hasher::{HashStable, hash_stable_hashmap,
|
|||
StableHasher, StableHasherResult,
|
||||
StableVec};
|
||||
use arena::{TypedArena, SyncDroplessArena};
|
||||
use rustc_data_structures::indexed_vec::IndexVec;
|
||||
use rustc_data_structures::indexed_vec::{Idx, IndexVec};
|
||||
use rustc_data_structures::sync::{self, Lrc, Lock, WorkerLocal};
|
||||
use std::any::Any;
|
||||
use std::borrow::Borrow;
|
||||
|
|
@ -342,26 +342,21 @@ pub struct TypeckTables<'tcx> {
|
|||
/// other items.
|
||||
node_substs: ItemLocalMap<&'tcx Substs<'tcx>>,
|
||||
|
||||
/// Stores the canonicalized types provided by the user. See also
|
||||
/// `AscribeUserType` statement in MIR.
|
||||
user_provided_tys: ItemLocalMap<CanonicalTy<'tcx>>,
|
||||
/// This will either store the canonicalized types provided by the user
|
||||
/// or the substitutions that the user explicitly gave (if any) attached
|
||||
/// to `id`. These will not include any inferred values. The canonical form
|
||||
/// is used to capture things like `_` or other unspecified values.
|
||||
///
|
||||
/// For example, if the user wrote `foo.collect::<Vec<_>>()`, then the
|
||||
/// canonical substitutions would include only `for<X> { Vec<X> }`.
|
||||
///
|
||||
/// See also `AscribeUserType` statement in MIR.
|
||||
user_provided_types: ItemLocalMap<CanonicalUserTypeAnnotation<'tcx>>,
|
||||
|
||||
/// Stores the canonicalized types provided by the user. See also
|
||||
/// `AscribeUserType` statement in MIR.
|
||||
pub user_provided_sigs: DefIdMap<CanonicalPolyFnSig<'tcx>>,
|
||||
|
||||
/// Stores the substitutions that the user explicitly gave (if any)
|
||||
/// attached to `id`. These will not include any inferred
|
||||
/// values. The canonical form is used to capture things like `_`
|
||||
/// or other unspecified values.
|
||||
///
|
||||
/// Example:
|
||||
///
|
||||
/// If the user wrote `foo.collect::<Vec<_>>()`, then the
|
||||
/// canonical substitutions would include only `for<X> { Vec<X>
|
||||
/// }`.
|
||||
user_substs: ItemLocalMap<CanonicalUserSubsts<'tcx>>,
|
||||
|
||||
adjustments: ItemLocalMap<Vec<ty::adjustment::Adjustment<'tcx>>>,
|
||||
|
||||
/// Stores the actual binding mode for all instances of hir::BindingAnnotation.
|
||||
|
|
@ -432,11 +427,10 @@ impl<'tcx> TypeckTables<'tcx> {
|
|||
local_id_root,
|
||||
type_dependent_defs: Default::default(),
|
||||
field_indices: Default::default(),
|
||||
user_provided_tys: Default::default(),
|
||||
user_provided_types: Default::default(),
|
||||
user_provided_sigs: Default::default(),
|
||||
node_types: Default::default(),
|
||||
node_substs: Default::default(),
|
||||
user_substs: Default::default(),
|
||||
adjustments: Default::default(),
|
||||
pat_binding_modes: Default::default(),
|
||||
pat_adjustments: Default::default(),
|
||||
|
|
@ -491,17 +485,21 @@ impl<'tcx> TypeckTables<'tcx> {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn user_provided_tys(&self) -> LocalTableInContext<'_, CanonicalTy<'tcx>> {
|
||||
pub fn user_provided_types(
|
||||
&self
|
||||
) -> LocalTableInContext<'_, CanonicalUserTypeAnnotation<'tcx>> {
|
||||
LocalTableInContext {
|
||||
local_id_root: self.local_id_root,
|
||||
data: &self.user_provided_tys
|
||||
data: &self.user_provided_types
|
||||
}
|
||||
}
|
||||
|
||||
pub fn user_provided_tys_mut(&mut self) -> LocalTableInContextMut<'_, CanonicalTy<'tcx>> {
|
||||
pub fn user_provided_types_mut(
|
||||
&mut self
|
||||
) -> LocalTableInContextMut<'_, CanonicalUserTypeAnnotation<'tcx>> {
|
||||
LocalTableInContextMut {
|
||||
local_id_root: self.local_id_root,
|
||||
data: &mut self.user_provided_tys
|
||||
data: &mut self.user_provided_types
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -551,18 +549,6 @@ impl<'tcx> TypeckTables<'tcx> {
|
|||
self.node_substs.get(&id.local_id).cloned()
|
||||
}
|
||||
|
||||
pub fn user_substs_mut(&mut self) -> LocalTableInContextMut<'_, CanonicalUserSubsts<'tcx>> {
|
||||
LocalTableInContextMut {
|
||||
local_id_root: self.local_id_root,
|
||||
data: &mut self.user_substs
|
||||
}
|
||||
}
|
||||
|
||||
pub fn user_substs(&self, id: hir::HirId) -> Option<CanonicalUserSubsts<'tcx>> {
|
||||
validate_hir_id_for_typeck_tables(self.local_id_root, id, false);
|
||||
self.user_substs.get(&id.local_id).cloned()
|
||||
}
|
||||
|
||||
// Returns the type of a pattern as a monotype. Like @expr_ty, this function
|
||||
// doesn't provide type parameter substitutions.
|
||||
pub fn pat_ty(&self, pat: &hir::Pat) -> Ty<'tcx> {
|
||||
|
|
@ -739,11 +725,10 @@ impl<'a, 'gcx> HashStable<StableHashingContext<'a>> for TypeckTables<'gcx> {
|
|||
local_id_root,
|
||||
ref type_dependent_defs,
|
||||
ref field_indices,
|
||||
ref user_provided_tys,
|
||||
ref user_provided_types,
|
||||
ref user_provided_sigs,
|
||||
ref node_types,
|
||||
ref node_substs,
|
||||
ref user_substs,
|
||||
ref adjustments,
|
||||
ref pat_binding_modes,
|
||||
ref pat_adjustments,
|
||||
|
|
@ -763,11 +748,10 @@ impl<'a, 'gcx> HashStable<StableHashingContext<'a>> for TypeckTables<'gcx> {
|
|||
hcx.with_node_id_hashing_mode(NodeIdHashingMode::HashDefPath, |hcx| {
|
||||
type_dependent_defs.hash_stable(hcx, hasher);
|
||||
field_indices.hash_stable(hcx, hasher);
|
||||
user_provided_tys.hash_stable(hcx, hasher);
|
||||
user_provided_types.hash_stable(hcx, hasher);
|
||||
user_provided_sigs.hash_stable(hcx, hasher);
|
||||
node_types.hash_stable(hcx, hasher);
|
||||
node_substs.hash_stable(hcx, hasher);
|
||||
user_substs.hash_stable(hcx, hasher);
|
||||
adjustments.hash_stable(hcx, hasher);
|
||||
pat_binding_modes.hash_stable(hcx, hasher);
|
||||
pat_adjustments.hash_stable(hcx, hasher);
|
||||
|
|
@ -805,6 +789,84 @@ impl<'a, 'gcx> HashStable<StableHashingContext<'a>> for TypeckTables<'gcx> {
|
|||
}
|
||||
}
|
||||
|
||||
newtype_index! {
|
||||
pub struct UserTypeAnnotationIndex {
|
||||
DEBUG_FORMAT = "UserTypeAnnotation({})",
|
||||
const START_INDEX = 0,
|
||||
}
|
||||
}
|
||||
|
||||
/// Mapping of type annotation indices to canonical user type annotations.
|
||||
pub type CanonicalUserTypeAnnotations<'tcx> =
|
||||
IndexVec<UserTypeAnnotationIndex, (Span, CanonicalUserTypeAnnotation<'tcx>)>;
|
||||
|
||||
/// Canonicalized user type annotation.
|
||||
pub type CanonicalUserTypeAnnotation<'gcx> = Canonical<'gcx, UserTypeAnnotation<'gcx>>;
|
||||
|
||||
impl CanonicalUserTypeAnnotation<'gcx> {
|
||||
/// Returns `true` if this represents a substitution of the form `[?0, ?1, ?2]`,
|
||||
/// i.e. each thing is mapped to a canonical variable with the same index.
|
||||
pub fn is_identity(&self) -> bool {
|
||||
match self.value {
|
||||
UserTypeAnnotation::Ty(_) => false,
|
||||
UserTypeAnnotation::TypeOf(_, user_substs) => {
|
||||
if user_substs.user_self_ty.is_some() {
|
||||
return false;
|
||||
}
|
||||
|
||||
user_substs.substs.iter().zip(BoundVar::new(0)..).all(|(kind, cvar)| {
|
||||
match kind.unpack() {
|
||||
UnpackedKind::Type(ty) => match ty.sty {
|
||||
ty::Bound(debruijn, b) => {
|
||||
// We only allow a `ty::INNERMOST` index in substitutions.
|
||||
assert_eq!(debruijn, ty::INNERMOST);
|
||||
cvar == b.var
|
||||
}
|
||||
_ => false,
|
||||
},
|
||||
|
||||
UnpackedKind::Lifetime(r) => match r {
|
||||
ty::ReLateBound(debruijn, br) => {
|
||||
// We only allow a `ty::INNERMOST` index in substitutions.
|
||||
assert_eq!(*debruijn, ty::INNERMOST);
|
||||
cvar == br.assert_bound_var()
|
||||
}
|
||||
_ => false,
|
||||
},
|
||||
}
|
||||
})
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// 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(Ty<'tcx>),
|
||||
|
||||
/// The canonical type is the result of `type_of(def_id)` with the
|
||||
/// given substitutions applied.
|
||||
TypeOf(DefId, UserSubsts<'tcx>),
|
||||
}
|
||||
|
||||
EnumTypeFoldableImpl! {
|
||||
impl<'tcx> TypeFoldable<'tcx> for UserTypeAnnotation<'tcx> {
|
||||
(UserTypeAnnotation::Ty)(ty),
|
||||
(UserTypeAnnotation::TypeOf)(def, substs),
|
||||
}
|
||||
}
|
||||
|
||||
EnumLiftImpl! {
|
||||
impl<'a, 'tcx> Lift<'tcx> for UserTypeAnnotation<'a> {
|
||||
type Lifted = UserTypeAnnotation<'tcx>;
|
||||
(UserTypeAnnotation::Ty)(ty),
|
||||
(UserTypeAnnotation::TypeOf)(def, substs),
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> CommonTypes<'tcx> {
|
||||
fn new(interners: &CtxtInterners<'tcx>) -> CommonTypes<'tcx> {
|
||||
let mk = |sty| CtxtInterners::intern_ty(interners, interners, sty);
|
||||
|
|
|
|||
|
|
@ -73,6 +73,10 @@ pub use self::binding::BindingMode::*;
|
|||
|
||||
pub use self::context::{TyCtxt, FreeRegionInfo, GlobalArenas, AllArenas, tls, keep_local};
|
||||
pub use self::context::{Lift, TypeckTables, CtxtInterners};
|
||||
pub use self::context::{
|
||||
UserTypeAnnotationIndex, UserTypeAnnotation, CanonicalUserTypeAnnotation,
|
||||
CanonicalUserTypeAnnotations,
|
||||
};
|
||||
|
||||
pub use self::instance::{Instance, InstanceDef};
|
||||
|
||||
|
|
|
|||
|
|
@ -2,12 +2,11 @@
|
|||
|
||||
use hir::def_id::DefId;
|
||||
use infer::canonical::Canonical;
|
||||
use ty::{self, BoundVar, Lift, List, Ty, TyCtxt};
|
||||
use ty::{self, Lift, List, Ty, TyCtxt};
|
||||
use ty::fold::{TypeFoldable, TypeFolder, TypeVisitor};
|
||||
|
||||
use serialize::{self, Encodable, Encoder, Decodable, Decoder};
|
||||
use syntax_pos::{Span, DUMMY_SP};
|
||||
use rustc_data_structures::indexed_vec::Idx;
|
||||
use smallvec::SmallVec;
|
||||
|
||||
use core::intrinsics;
|
||||
|
|
@ -559,43 +558,6 @@ impl<'a, 'gcx, 'tcx> SubstFolder<'a, 'gcx, 'tcx> {
|
|||
|
||||
pub type CanonicalUserSubsts<'tcx> = Canonical<'tcx, UserSubsts<'tcx>>;
|
||||
|
||||
impl CanonicalUserSubsts<'tcx> {
|
||||
/// True if this represents a substitution like
|
||||
///
|
||||
/// ```text
|
||||
/// [?0, ?1, ?2]
|
||||
/// ```
|
||||
///
|
||||
/// i.e., each thing is mapped to a canonical variable with the same index.
|
||||
pub fn is_identity(&self) -> bool {
|
||||
if self.value.user_self_ty.is_some() {
|
||||
return false;
|
||||
}
|
||||
|
||||
self.value.substs.iter().zip(BoundVar::new(0)..).all(|(kind, cvar)| {
|
||||
match kind.unpack() {
|
||||
UnpackedKind::Type(ty) => match ty.sty {
|
||||
ty::Bound(debruijn, b) => {
|
||||
// We only allow a `ty::INNERMOST` index in substitutions.
|
||||
assert_eq!(debruijn, ty::INNERMOST);
|
||||
cvar == b.var
|
||||
}
|
||||
_ => false,
|
||||
},
|
||||
|
||||
UnpackedKind::Lifetime(r) => match r {
|
||||
ty::ReLateBound(debruijn, br) => {
|
||||
// We only allow a `ty::INNERMOST` index in substitutions.
|
||||
assert_eq!(*debruijn, ty::INNERMOST);
|
||||
cvar == br.assert_bound_var()
|
||||
}
|
||||
_ => false,
|
||||
},
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
/// Stores the user-given substs to reach some fully qualified path
|
||||
/// (e.g., `<T>::Item` or `<T as Trait>::Item`).
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable)]
|
||||
|
|
|
|||
|
|
@ -1,6 +1,10 @@
|
|||
use rustc::infer::canonical::Canonical;
|
||||
use rustc::ty::subst::Substs;
|
||||
use rustc::ty::{self, ClosureSubsts, GeneratorSubsts, Ty, TypeFoldable};
|
||||
use rustc::mir::{Location, Mir, UserTypeAnnotation};
|
||||
use rustc::ty::{
|
||||
self, ClosureSubsts, GeneratorSubsts, Ty, TypeFoldable, UserTypeAnnotation,
|
||||
UserTypeAnnotationIndex,
|
||||
};
|
||||
use rustc::mir::{Location, Mir};
|
||||
use rustc::mir::visit::{MutVisitor, TyContext};
|
||||
use rustc::infer::{InferCtxt, NLLRegionVariableOrigin};
|
||||
|
||||
|
|
@ -55,7 +59,11 @@ impl<'a, 'gcx, 'tcx> MutVisitor<'tcx> for NLLVisitor<'a, 'gcx, 'tcx> {
|
|||
debug!("visit_ty: ty={:?}", ty);
|
||||
}
|
||||
|
||||
fn visit_user_type_annotation(&mut self, _ty: &mut UserTypeAnnotation<'tcx>) {
|
||||
fn visit_user_type_annotation(
|
||||
&mut self,
|
||||
_index: UserTypeAnnotationIndex,
|
||||
_ty: &mut Canonical<'tcx, UserTypeAnnotation<'tcx>>,
|
||||
) {
|
||||
// User type 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
|
||||
|
|
|
|||
|
|
@ -36,7 +36,10 @@ use rustc::traits::query::{Fallible, NoSolution};
|
|||
use rustc::traits::{ObligationCause, PredicateObligations};
|
||||
use rustc::ty::fold::TypeFoldable;
|
||||
use rustc::ty::subst::{Subst, Substs, UnpackedKind};
|
||||
use rustc::ty::{self, RegionVid, ToPolyTraitRef, Ty, TyCtxt, TyKind};
|
||||
use rustc::ty::{
|
||||
self, RegionVid, ToPolyTraitRef, Ty, TyCtxt, TyKind, UserTypeAnnotation,
|
||||
UserTypeAnnotationIndex,
|
||||
};
|
||||
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
|
||||
use rustc_data_structures::indexed_vec::{IndexVec, Idx};
|
||||
use rustc::ty::layout::VariantIdx;
|
||||
|
|
@ -272,19 +275,20 @@ impl<'a, 'b, 'gcx, 'tcx> Visitor<'tcx> for TypeVerifier<'a, 'b, 'gcx, 'tcx> {
|
|||
self.sanitize_constant(constant, location);
|
||||
self.sanitize_type(constant, constant.ty);
|
||||
|
||||
if let Some(user_ty) = constant.user_ty {
|
||||
if let Some(annotation_index) = constant.user_ty {
|
||||
if let Err(terr) = self.cx.relate_type_and_user_type(
|
||||
constant.ty,
|
||||
ty::Variance::Invariant,
|
||||
&UserTypeProjection { base: user_ty, projs: vec![], },
|
||||
&UserTypeProjection { base: annotation_index, projs: vec![], },
|
||||
location.to_locations(),
|
||||
ConstraintCategory::Boring,
|
||||
) {
|
||||
let annotation = self.cx.instantiated_type_annotations[&annotation_index];
|
||||
span_mirbug!(
|
||||
self,
|
||||
constant,
|
||||
"bad constant user type {:?} vs {:?}: {:?}",
|
||||
user_ty,
|
||||
annotation,
|
||||
constant.ty,
|
||||
terr,
|
||||
);
|
||||
|
|
@ -715,6 +719,15 @@ struct TypeChecker<'a, 'gcx: 'tcx, 'tcx: 'a> {
|
|||
reported_errors: FxHashSet<(Ty<'tcx>, Span)>,
|
||||
borrowck_context: Option<&'a mut BorrowCheckContext<'a, 'tcx>>,
|
||||
universal_region_relations: Option<&'a UniversalRegionRelations<'tcx>>,
|
||||
/// For each user-type annotation (identified by a UserTypeAnnotationIndex), we create
|
||||
/// an "instantiated" version at the beginning of type check, which replaces each
|
||||
/// canonical variable with a fresh inference variable. These instantiated versions are
|
||||
/// stored either in this field or in user_substs, depending on the kind of user-type
|
||||
/// annotation. They are then referenced by the code which has the job of enforcing these
|
||||
/// annotations. Part of the reason for this setup is that it allows us to enforce basic
|
||||
/// WF criteria on the types even if the code that referenced them is dead
|
||||
/// code (see #54943).
|
||||
instantiated_type_annotations: FxHashMap<UserTypeAnnotationIndex, UserTypeAnnotation<'tcx>>,
|
||||
}
|
||||
|
||||
struct BorrowCheckContext<'a, 'tcx: 'a> {
|
||||
|
|
@ -860,7 +873,7 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> {
|
|||
borrowck_context: Option<&'a mut BorrowCheckContext<'a, 'tcx>>,
|
||||
universal_region_relations: Option<&'a UniversalRegionRelations<'tcx>>,
|
||||
) -> Self {
|
||||
TypeChecker {
|
||||
let mut checker = Self {
|
||||
infcx,
|
||||
last_span: DUMMY_SP,
|
||||
mir,
|
||||
|
|
@ -871,7 +884,36 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> {
|
|||
borrowck_context,
|
||||
reported_errors: Default::default(),
|
||||
universal_region_relations,
|
||||
instantiated_type_annotations: Default::default(),
|
||||
};
|
||||
checker.instantiate_user_type_annotations();
|
||||
checker
|
||||
}
|
||||
|
||||
/// Instantiate canonical types from user type annotations in the `Mir` into the
|
||||
/// `TypeChecker`. Used when relating user type annotations and when checking if
|
||||
/// annotations are well-formed.
|
||||
fn instantiate_user_type_annotations(&mut self) {
|
||||
debug!(
|
||||
"instantiate_user_type_annotations: user_type_annotations={:?}",
|
||||
self.mir.user_type_annotations
|
||||
);
|
||||
for annotation_index in self.mir.user_type_annotations.indices() {
|
||||
let (span, canonical_annotation) = &self.mir.user_type_annotations[annotation_index];
|
||||
let (mut annotation, _) = self.infcx.instantiate_canonical_with_fresh_inference_vars(
|
||||
*span, &canonical_annotation
|
||||
);
|
||||
match annotation {
|
||||
UserTypeAnnotation::Ty(ref mut ty) =>
|
||||
*ty = self.normalize(ty, Locations::All(*span)),
|
||||
_ => {},
|
||||
}
|
||||
self.instantiated_type_annotations.insert(annotation_index, annotation);
|
||||
}
|
||||
debug!(
|
||||
"instantiate_user_type_annotations: instantiated_type_annotations={:?}",
|
||||
self.instantiated_type_annotations,
|
||||
);
|
||||
}
|
||||
|
||||
/// Given some operation `op` that manipulates types, proves
|
||||
|
|
@ -1003,18 +1045,13 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> {
|
|||
a, v, user_ty, locations,
|
||||
);
|
||||
|
||||
match user_ty.base {
|
||||
UserTypeAnnotation::Ty(canonical_ty) => {
|
||||
let (ty, _) = self.infcx
|
||||
.instantiate_canonical_with_fresh_inference_vars(DUMMY_SP, &canonical_ty);
|
||||
|
||||
match self.instantiated_type_annotations[&user_ty.base] {
|
||||
UserTypeAnnotation::Ty(ty) => {
|
||||
// The `TypeRelating` code assumes that "unresolved inference
|
||||
// variables" appear in the "a" side, so flip `Contravariant`
|
||||
// ambient variance to get the right relationship.
|
||||
let v1 = ty::Contravariant.xform(v);
|
||||
|
||||
let tcx = self.infcx.tcx;
|
||||
let ty = self.normalize(ty, locations);
|
||||
|
||||
// We need to follow any provided projetions into the type.
|
||||
//
|
||||
|
|
@ -1048,13 +1085,7 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> {
|
|||
self.relate_types(ty, v1, a, locations, category)?;
|
||||
}
|
||||
}
|
||||
UserTypeAnnotation::TypeOf(def_id, canonical_substs) => {
|
||||
let (
|
||||
user_substs,
|
||||
_,
|
||||
) = self.infcx
|
||||
.instantiate_canonical_with_fresh_inference_vars(DUMMY_SP, &canonical_substs);
|
||||
|
||||
UserTypeAnnotation::TypeOf(def_id, user_substs) => {
|
||||
let projs = self.infcx.tcx.intern_projs(&user_ty.projs);
|
||||
self.fully_perform_op(
|
||||
locations,
|
||||
|
|
@ -1225,19 +1256,20 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> {
|
|||
);
|
||||
}
|
||||
|
||||
if let Some(user_ty) = self.rvalue_user_ty(rv) {
|
||||
if let Some(annotation_index) = self.rvalue_user_ty(rv) {
|
||||
if let Err(terr) = self.relate_type_and_user_type(
|
||||
rv_ty,
|
||||
ty::Variance::Invariant,
|
||||
&UserTypeProjection { base: user_ty, projs: vec![], },
|
||||
&UserTypeProjection { base: annotation_index, projs: vec![], },
|
||||
location.to_locations(),
|
||||
ConstraintCategory::Boring,
|
||||
) {
|
||||
let annotation = self.instantiated_type_annotations[&annotation_index];
|
||||
span_mirbug!(
|
||||
self,
|
||||
stmt,
|
||||
"bad user type on rvalue ({:?} = {:?}): {:?}",
|
||||
user_ty,
|
||||
annotation,
|
||||
rv_ty,
|
||||
terr
|
||||
);
|
||||
|
|
@ -1282,21 +1314,23 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> {
|
|||
);
|
||||
};
|
||||
}
|
||||
StatementKind::AscribeUserType(ref place, variance, box ref c_ty) => {
|
||||
StatementKind::AscribeUserType(ref place, variance, box ref projection) => {
|
||||
let place_ty = place.ty(mir, tcx).to_ty(tcx);
|
||||
if let Err(terr) = self.relate_type_and_user_type(
|
||||
place_ty,
|
||||
variance,
|
||||
c_ty,
|
||||
projection,
|
||||
Locations::All(stmt.source_info.span),
|
||||
ConstraintCategory::TypeAnnotation,
|
||||
) {
|
||||
let annotation = self.instantiated_type_annotations[&projection.base];
|
||||
span_mirbug!(
|
||||
self,
|
||||
stmt,
|
||||
"bad type assert ({:?} <: {:?}): {:?}",
|
||||
"bad type assert ({:?} <: {:?} with projections {:?}): {:?}",
|
||||
place_ty,
|
||||
c_ty,
|
||||
annotation,
|
||||
projection.projs,
|
||||
terr
|
||||
);
|
||||
}
|
||||
|
|
@ -1955,7 +1989,7 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> {
|
|||
/// If this rvalue supports a user-given type annotation, then
|
||||
/// extract and return it. This represents the final type of the
|
||||
/// rvalue and will be unified with the inferred type.
|
||||
fn rvalue_user_ty(&self, rvalue: &Rvalue<'tcx>) -> Option<UserTypeAnnotation<'tcx>> {
|
||||
fn rvalue_user_ty(&self, rvalue: &Rvalue<'tcx>) -> Option<UserTypeAnnotationIndex> {
|
||||
match rvalue {
|
||||
Rvalue::Use(_)
|
||||
| Rvalue::Repeat(..)
|
||||
|
|
|
|||
|
|
@ -29,11 +29,16 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
|
|||
lint_level: _,
|
||||
value,
|
||||
} => this.as_constant(value),
|
||||
ExprKind::Literal { literal, user_ty } => Constant {
|
||||
span,
|
||||
ty,
|
||||
user_ty,
|
||||
literal,
|
||||
ExprKind::Literal { literal, user_ty } => {
|
||||
let user_ty = user_ty.map(|ty| {
|
||||
this.canonical_user_type_annotations.push((span, ty))
|
||||
});
|
||||
Constant {
|
||||
span,
|
||||
ty,
|
||||
user_ty,
|
||||
literal,
|
||||
}
|
||||
},
|
||||
_ => span_bug!(span, "expression is not a valid constant {:?}", kind),
|
||||
}
|
||||
|
|
|
|||
|
|
@ -133,6 +133,9 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
|
|||
ExprKind::PlaceTypeAscription { source, user_ty } => {
|
||||
let place = unpack!(block = this.as_place(block, source));
|
||||
if let Some(user_ty) = user_ty {
|
||||
let annotation_index = this.canonical_user_type_annotations.push(
|
||||
(source_info.span, user_ty)
|
||||
);
|
||||
this.cfg.push(
|
||||
block,
|
||||
Statement {
|
||||
|
|
@ -140,7 +143,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
|
|||
kind: StatementKind::AscribeUserType(
|
||||
place.clone(),
|
||||
Variance::Invariant,
|
||||
box UserTypeProjection { base: user_ty, projs: vec![], },
|
||||
box UserTypeProjection { base: annotation_index, projs: vec![], },
|
||||
),
|
||||
},
|
||||
);
|
||||
|
|
@ -153,6 +156,9 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
|
|||
block = this.as_temp(block, source.temp_lifetime, source, mutability)
|
||||
);
|
||||
if let Some(user_ty) = user_ty {
|
||||
let annotation_index = this.canonical_user_type_annotations.push(
|
||||
(source_info.span, user_ty)
|
||||
);
|
||||
this.cfg.push(
|
||||
block,
|
||||
Statement {
|
||||
|
|
@ -160,7 +166,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
|
|||
kind: StatementKind::AscribeUserType(
|
||||
Place::Local(temp.clone()),
|
||||
Variance::Invariant,
|
||||
box UserTypeProjection { base: user_ty, projs: vec![], },
|
||||
box UserTypeProjection { base: annotation_index, projs: vec![], },
|
||||
),
|
||||
},
|
||||
);
|
||||
|
|
|
|||
|
|
@ -331,6 +331,9 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
|
|||
.collect()
|
||||
};
|
||||
|
||||
let user_ty = user_ty.map(|ty| {
|
||||
this.canonical_user_type_annotations.push((expr_span, ty))
|
||||
});
|
||||
let adt = box AggregateKind::Adt(
|
||||
adt_def,
|
||||
variant_index,
|
||||
|
|
|
|||
|
|
@ -302,6 +302,9 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
|
|||
);
|
||||
|
||||
let ty_source_info = self.source_info(user_ty_span);
|
||||
let user_ty = box pat_ascription_ty.user_ty(
|
||||
&mut self.canonical_user_type_annotations, ty_source_info.span
|
||||
);
|
||||
self.cfg.push(
|
||||
block,
|
||||
Statement {
|
||||
|
|
@ -309,7 +312,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
|
|||
kind: StatementKind::AscribeUserType(
|
||||
place,
|
||||
ty::Variance::Invariant,
|
||||
box pat_ascription_ty.user_ty(),
|
||||
user_ty,
|
||||
),
|
||||
},
|
||||
);
|
||||
|
|
@ -1314,6 +1317,9 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
|
|||
ascription.user_ty,
|
||||
);
|
||||
|
||||
let user_ty = box ascription.user_ty.clone().user_ty(
|
||||
&mut self.canonical_user_type_annotations, source_info.span
|
||||
);
|
||||
self.cfg.push(
|
||||
block,
|
||||
Statement {
|
||||
|
|
@ -1321,7 +1327,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
|
|||
kind: StatementKind::AscribeUserType(
|
||||
ascription.source.clone(),
|
||||
ty::Variance::Covariant,
|
||||
box ascription.user_ty.clone().user_ty(),
|
||||
user_ty,
|
||||
),
|
||||
},
|
||||
);
|
||||
|
|
@ -1484,10 +1490,12 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
|
|||
BindingMode::ByValue => ty::BindingMode::BindByValue(mutability.into()),
|
||||
BindingMode::ByRef { .. } => ty::BindingMode::BindByReference(mutability.into()),
|
||||
};
|
||||
let user_ty = user_var_ty.clone().user_ty(&mut self.canonical_user_type_annotations);
|
||||
debug!("declare_binding: user_ty={:?}", user_ty);
|
||||
let local = LocalDecl::<'tcx> {
|
||||
mutability,
|
||||
ty: var_ty,
|
||||
user_ty: user_var_ty.clone().user_ty(),
|
||||
user_ty,
|
||||
name: Some(name),
|
||||
source_info,
|
||||
visibility_scope,
|
||||
|
|
|
|||
|
|
@ -379,6 +379,7 @@ struct Builder<'a, 'gcx: 'a+'tcx, 'tcx: 'a> {
|
|||
/// (A match binding can have two locals; the 2nd is for the arm's guard.)
|
||||
var_indices: NodeMap<LocalsForNode>,
|
||||
local_decls: IndexVec<Local, LocalDecl<'tcx>>,
|
||||
canonical_user_type_annotations: ty::CanonicalUserTypeAnnotations<'tcx>,
|
||||
upvar_decls: Vec<UpvarDecl>,
|
||||
unit_temp: Option<Place<'tcx>>,
|
||||
|
||||
|
|
@ -812,6 +813,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
|
|||
LocalDecl::new_return_place(return_ty, return_span),
|
||||
1,
|
||||
),
|
||||
canonical_user_type_annotations: IndexVec::new(),
|
||||
upvar_decls,
|
||||
var_indices: Default::default(),
|
||||
unit_temp: None,
|
||||
|
|
@ -845,6 +847,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
|
|||
IndexVec::new(),
|
||||
yield_ty,
|
||||
self.local_decls,
|
||||
self.canonical_user_type_annotations,
|
||||
self.arg_count,
|
||||
self.upvar_decls,
|
||||
self.fn_span,
|
||||
|
|
|
|||
|
|
@ -78,12 +78,13 @@ fn mirror_stmts<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
|
|||
let mut pattern = cx.pattern_from_hir(&local.pat);
|
||||
|
||||
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_types().get(ty.hir_id) {
|
||||
debug!("mirror_stmts: user_ty={:?}", user_ty);
|
||||
pattern = Pattern {
|
||||
ty: pattern.ty,
|
||||
span: pattern.span,
|
||||
kind: Box::new(PatternKind::AscribeUserType {
|
||||
user_ty: PatternTypeProjection::from_canonical_ty(user_ty),
|
||||
user_ty: PatternTypeProjection::from_user_type(user_ty),
|
||||
user_ty_span: ty.span,
|
||||
subpattern: pattern
|
||||
})
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@ use rustc::ty::adjustment::{Adjustment, Adjust, AutoBorrow, AutoBorrowMutability
|
|||
use rustc::ty::cast::CastKind as TyCastKind;
|
||||
use rustc::hir;
|
||||
use rustc::hir::def_id::LocalDefId;
|
||||
use rustc::mir::{BorrowKind};
|
||||
use rustc::mir::BorrowKind;
|
||||
use syntax_pos::Span;
|
||||
|
||||
impl<'tcx> Mirror<'tcx> for &'tcx hir::Expr {
|
||||
|
|
@ -283,9 +283,16 @@ fn make_mirror_unadjusted<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
|
|||
};
|
||||
if let Some((adt_def, index)) = adt_data {
|
||||
let substs = cx.tables().node_substs(fun.hir_id);
|
||||
|
||||
let user_ty = cx.tables().user_substs(fun.hir_id)
|
||||
.map(|user_substs| UserTypeAnnotation::TypeOf(adt_def.did, user_substs));
|
||||
let user_provided_types = cx.tables().user_provided_types();
|
||||
let user_ty = user_provided_types.get(fun.hir_id)
|
||||
.map(|u_ty| *u_ty)
|
||||
.map(|mut u_ty| {
|
||||
if let UserTypeAnnotation::TypeOf(ref mut did, _) = &mut u_ty.value {
|
||||
*did = adt_def.did;
|
||||
}
|
||||
u_ty
|
||||
});
|
||||
debug!("make_mirror_unadjusted: (call) user_ty={:?}", user_ty);
|
||||
|
||||
let field_refs = args.iter()
|
||||
.enumerate()
|
||||
|
|
@ -464,11 +471,14 @@ fn make_mirror_unadjusted<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
|
|||
ty::Adt(adt, substs) => {
|
||||
match adt.adt_kind() {
|
||||
AdtKind::Struct | AdtKind::Union => {
|
||||
let user_provided_types = cx.tables().user_provided_types();
|
||||
let user_ty = user_provided_types.get(expr.hir_id).map(|u_ty| *u_ty);
|
||||
debug!("make_mirror_unadjusted: (struct/union) user_ty={:?}", user_ty);
|
||||
ExprKind::Adt {
|
||||
adt_def: adt,
|
||||
variant_index: VariantIdx::new(0),
|
||||
substs,
|
||||
user_ty: cx.user_substs_applied_to_adt(expr.hir_id, adt),
|
||||
user_ty,
|
||||
fields: field_refs(cx, fields),
|
||||
base: base.as_ref().map(|base| {
|
||||
FruInfo {
|
||||
|
|
@ -487,11 +497,18 @@ fn make_mirror_unadjusted<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
|
|||
assert!(base.is_none());
|
||||
|
||||
let index = adt.variant_index_with_id(variant_id);
|
||||
let user_provided_types = cx.tables().user_provided_types();
|
||||
let user_ty = user_provided_types.get(expr.hir_id)
|
||||
.map(|u_ty| *u_ty);
|
||||
debug!(
|
||||
"make_mirror_unadjusted: (variant) user_ty={:?}",
|
||||
user_ty
|
||||
);
|
||||
ExprKind::Adt {
|
||||
adt_def: adt,
|
||||
variant_index: index,
|
||||
substs,
|
||||
user_ty: cx.user_substs_applied_to_adt(expr.hir_id, adt),
|
||||
user_ty,
|
||||
fields: field_refs(cx, fields),
|
||||
base: None,
|
||||
}
|
||||
|
|
@ -635,8 +652,8 @@ fn make_mirror_unadjusted<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
|
|||
}
|
||||
hir::ExprKind::Cast(ref source, ref cast_ty) => {
|
||||
// Check for a user-given type annotation on this `cast`
|
||||
let user_ty = cx.tables.user_provided_tys().get(cast_ty.hir_id)
|
||||
.map(|&t| UserTypeAnnotation::Ty(t));
|
||||
let user_provided_types = cx.tables.user_provided_types();
|
||||
let user_ty = user_provided_types.get(cast_ty.hir_id);
|
||||
|
||||
debug!(
|
||||
"cast({:?}) has ty w/ hir_id {:?} and user provided ty {:?}",
|
||||
|
|
@ -742,20 +759,20 @@ fn make_mirror_unadjusted<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
|
|||
span: expr.span,
|
||||
kind: cast,
|
||||
};
|
||||
debug!("make_mirror_unadjusted: (cast) user_ty={:?}", user_ty);
|
||||
|
||||
ExprKind::ValueTypeAscription {
|
||||
source: cast_expr.to_ref(),
|
||||
user_ty: Some(user_ty),
|
||||
user_ty: Some(*user_ty),
|
||||
}
|
||||
} else {
|
||||
cast
|
||||
}
|
||||
}
|
||||
hir::ExprKind::Type(ref source, ref ty) => {
|
||||
let user_provided_tys = cx.tables.user_provided_tys();
|
||||
let user_ty = user_provided_tys
|
||||
.get(ty.hir_id)
|
||||
.map(|&c_ty| UserTypeAnnotation::Ty(c_ty));
|
||||
let user_provided_types = cx.tables.user_provided_types();
|
||||
let user_ty = user_provided_types.get(ty.hir_id).map(|u_ty| *u_ty);
|
||||
debug!("make_mirror_unadjusted: (type) user_ty={:?}", user_ty);
|
||||
if source.is_place_expr() {
|
||||
ExprKind::PlaceTypeAscription {
|
||||
source: source.to_ref(),
|
||||
|
|
@ -792,8 +809,9 @@ fn user_substs_applied_to_def(
|
|||
cx: &mut Cx<'a, 'gcx, 'tcx>,
|
||||
hir_id: hir::HirId,
|
||||
def: &Def,
|
||||
) -> Option<UserTypeAnnotation<'tcx>> {
|
||||
match def {
|
||||
) -> Option<ty::CanonicalUserTypeAnnotation<'tcx>> {
|
||||
debug!("user_substs_applied_to_def: def={:?}", def);
|
||||
let user_provided_type = match def {
|
||||
// A reference to something callable -- e.g., a fn, method, or
|
||||
// a tuple-struct or tuple-variant. This has the type of a
|
||||
// `Fn` but with the user-given substitutions.
|
||||
|
|
@ -802,8 +820,7 @@ fn user_substs_applied_to_def(
|
|||
Def::StructCtor(_, CtorKind::Fn) |
|
||||
Def::VariantCtor(_, CtorKind::Fn) |
|
||||
Def::Const(_) |
|
||||
Def::AssociatedConst(_) =>
|
||||
Some(UserTypeAnnotation::TypeOf(def.def_id(), cx.tables().user_substs(hir_id)?)),
|
||||
Def::AssociatedConst(_) => cx.tables().user_provided_types().get(hir_id).map(|u_ty| *u_ty),
|
||||
|
||||
// A unit struct/variant which is used as a value (e.g.,
|
||||
// `None`). This has the type of the enum/struct that defines
|
||||
|
|
@ -819,7 +836,9 @@ fn user_substs_applied_to_def(
|
|||
|
||||
_ =>
|
||||
bug!("user_substs_applied_to_def: unexpected def {:?} at {:?}", def, hir_id)
|
||||
}
|
||||
};
|
||||
debug!("user_substs_applied_to_def: user_provided_type={:?}", user_provided_type);
|
||||
user_provided_type
|
||||
}
|
||||
|
||||
fn method_callee<'a, 'gcx, 'tcx>(
|
||||
|
|
@ -839,6 +858,7 @@ fn method_callee<'a, 'gcx, 'tcx>(
|
|||
span_bug!(expr.span, "no type-dependent def for method callee")
|
||||
});
|
||||
let user_ty = user_substs_applied_to_def(cx, expr.hir_id, def);
|
||||
debug!("method_callee: user_ty={:?}", user_ty);
|
||||
(def.def_id(), cx.tables().node_substs(expr.hir_id), user_ty)
|
||||
}
|
||||
};
|
||||
|
|
@ -906,6 +926,7 @@ fn convert_path_expr<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
|
|||
Def::VariantCtor(_, CtorKind::Fn) |
|
||||
Def::SelfCtor(..) => {
|
||||
let user_ty = user_substs_applied_to_def(cx, expr.hir_id, &def);
|
||||
debug!("convert_path_expr: user_ty={:?}", user_ty);
|
||||
ExprKind::Literal {
|
||||
literal: ty::Const::zero_sized(
|
||||
cx.tcx,
|
||||
|
|
@ -918,6 +939,7 @@ fn convert_path_expr<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
|
|||
Def::Const(def_id) |
|
||||
Def::AssociatedConst(def_id) => {
|
||||
let user_ty = user_substs_applied_to_def(cx, expr.hir_id, &def);
|
||||
debug!("convert_path_expr: (const) user_ty={:?}", user_ty);
|
||||
ExprKind::Literal {
|
||||
literal: ty::Const::unevaluated(
|
||||
cx.tcx,
|
||||
|
|
@ -931,6 +953,9 @@ fn convert_path_expr<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
|
|||
|
||||
Def::StructCtor(def_id, CtorKind::Const) |
|
||||
Def::VariantCtor(def_id, CtorKind::Const) => {
|
||||
let user_provided_types = cx.tables.user_provided_types();
|
||||
let user_provided_type = user_provided_types.get(expr.hir_id).map(|u_ty| *u_ty);
|
||||
debug!("convert_path_expr: user_provided_type={:?}", user_provided_type);
|
||||
match cx.tables().node_id_to_type(expr.hir_id).sty {
|
||||
// A unit struct/variant which is used as a value.
|
||||
// We return a completely different ExprKind here to account for this special case.
|
||||
|
|
@ -939,7 +964,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: cx.user_substs_applied_to_adt(expr.hir_id, adt_def),
|
||||
user_ty: user_provided_type,
|
||||
fields: vec![],
|
||||
base: None,
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,11 +4,12 @@
|
|||
//! unit-tested and separated from the Rust source and compiler data
|
||||
//! structures.
|
||||
|
||||
use rustc::mir::{BinOp, BorrowKind, UserTypeAnnotation, Field, UnOp};
|
||||
use rustc::mir::{BinOp, BorrowKind, Field, UnOp};
|
||||
use rustc::hir::def_id::DefId;
|
||||
use rustc::infer::canonical::Canonical;
|
||||
use rustc::middle::region;
|
||||
use rustc::ty::subst::Substs;
|
||||
use rustc::ty::{AdtDef, UpvarSubsts, Region, Ty, Const};
|
||||
use rustc::ty::{AdtDef, UpvarSubsts, Region, Ty, Const, UserTypeAnnotation};
|
||||
use rustc::ty::layout::VariantIdx;
|
||||
use rustc::hir;
|
||||
use syntax::ast;
|
||||
|
|
@ -265,7 +266,7 @@ pub enum ExprKind<'tcx> {
|
|||
|
||||
/// Optional user-given substs: for something like `let x =
|
||||
/// Bar::<T> { ... }`.
|
||||
user_ty: Option<UserTypeAnnotation<'tcx>>,
|
||||
user_ty: Option<Canonical<'tcx, UserTypeAnnotation<'tcx>>>,
|
||||
|
||||
fields: Vec<FieldExprRef<'tcx>>,
|
||||
base: Option<FruInfo<'tcx>>
|
||||
|
|
@ -273,12 +274,12 @@ pub enum ExprKind<'tcx> {
|
|||
PlaceTypeAscription {
|
||||
source: ExprRef<'tcx>,
|
||||
/// Type that the user gave to this expression
|
||||
user_ty: Option<UserTypeAnnotation<'tcx>>,
|
||||
user_ty: Option<Canonical<'tcx, UserTypeAnnotation<'tcx>>>,
|
||||
},
|
||||
ValueTypeAscription {
|
||||
source: ExprRef<'tcx>,
|
||||
/// Type that the user gave to this expression
|
||||
user_ty: Option<UserTypeAnnotation<'tcx>>,
|
||||
user_ty: Option<Canonical<'tcx, UserTypeAnnotation<'tcx>>>,
|
||||
},
|
||||
Closure {
|
||||
closure_id: DefId,
|
||||
|
|
@ -288,7 +289,7 @@ pub enum ExprKind<'tcx> {
|
|||
},
|
||||
Literal {
|
||||
literal: &'tcx Const<'tcx>,
|
||||
user_ty: Option<UserTypeAnnotation<'tcx>>,
|
||||
user_ty: Option<Canonical<'tcx, UserTypeAnnotation<'tcx>>>,
|
||||
},
|
||||
InlineAsm {
|
||||
asm: &'tcx hir::InlineAsm,
|
||||
|
|
|
|||
|
|
@ -12,9 +12,10 @@ use hair::util::UserAnnotatedTyHelpers;
|
|||
use hair::constant::*;
|
||||
|
||||
use rustc::mir::{fmt_const_val, Field, BorrowKind, Mutability};
|
||||
use rustc::mir::{ProjectionElem, UserTypeAnnotation, UserTypeProjection, UserTypeProjections};
|
||||
use rustc::mir::{ProjectionElem, UserTypeProjection, UserTypeProjections};
|
||||
use rustc::mir::interpret::{Scalar, GlobalId, ConstValue, sign_extend};
|
||||
use rustc::ty::{self, Region, TyCtxt, AdtDef, Ty, Lift};
|
||||
use rustc::ty::{CanonicalUserTypeAnnotation, CanonicalUserTypeAnnotations, UserTypeAnnotation};
|
||||
use rustc::ty::subst::{Substs, Kind};
|
||||
use rustc::ty::layout::VariantIdx;
|
||||
use rustc::hir::{self, PatKind, RangeEnd};
|
||||
|
|
@ -63,9 +64,15 @@ pub(crate) struct PatternTypeProjections<'tcx> {
|
|||
}
|
||||
|
||||
impl<'tcx> PatternTypeProjections<'tcx> {
|
||||
pub(crate) fn user_ty(self) -> UserTypeProjections<'tcx> {
|
||||
pub(crate) fn user_ty(
|
||||
self,
|
||||
annotations: &mut CanonicalUserTypeAnnotations<'tcx>,
|
||||
) -> UserTypeProjections<'tcx> {
|
||||
UserTypeProjections::from_projections(
|
||||
self.contents.into_iter().map(|(pat_ty_proj, span)| (pat_ty_proj.user_ty(), span)))
|
||||
self.contents
|
||||
.into_iter()
|
||||
.map(|(pat_ty_proj, span)| (pat_ty_proj.user_ty(annotations, span), span))
|
||||
)
|
||||
}
|
||||
|
||||
pub(crate) fn none() -> Self {
|
||||
|
|
@ -115,30 +122,33 @@ impl<'tcx> PatternTypeProjections<'tcx> {
|
|||
}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct PatternTypeProjection<'tcx>(UserTypeProjection<'tcx>);
|
||||
pub struct PatternTypeProjection<'tcx> {
|
||||
pub base: CanonicalUserTypeAnnotation<'tcx>,
|
||||
pub projs: Vec<ProjectionElem<'tcx, (), ()>>,
|
||||
}
|
||||
|
||||
impl<'tcx> PatternTypeProjection<'tcx> {
|
||||
pub(crate) fn index(&self) -> Self {
|
||||
let mut new = self.clone();
|
||||
new.0.projs.push(ProjectionElem::Index(()));
|
||||
new.projs.push(ProjectionElem::Index(()));
|
||||
new
|
||||
}
|
||||
|
||||
pub(crate) fn subslice(&self, from: u32, to: u32) -> Self {
|
||||
let mut new = self.clone();
|
||||
new.0.projs.push(ProjectionElem::Subslice { from, to });
|
||||
new.projs.push(ProjectionElem::Subslice { from, to });
|
||||
new
|
||||
}
|
||||
|
||||
pub(crate) fn deref(&self) -> Self {
|
||||
let mut new = self.clone();
|
||||
new.0.projs.push(ProjectionElem::Deref);
|
||||
new.projs.push(ProjectionElem::Deref);
|
||||
new
|
||||
}
|
||||
|
||||
pub(crate) fn leaf(&self, field: Field) -> Self {
|
||||
let mut new = self.clone();
|
||||
new.0.projs.push(ProjectionElem::Field(field, ()));
|
||||
new.projs.push(ProjectionElem::Field(field, ()));
|
||||
new
|
||||
}
|
||||
|
||||
|
|
@ -147,24 +157,29 @@ impl<'tcx> PatternTypeProjection<'tcx> {
|
|||
variant_index: VariantIdx,
|
||||
field: Field) -> Self {
|
||||
let mut new = self.clone();
|
||||
new.0.projs.push(ProjectionElem::Downcast(adt_def, variant_index));
|
||||
new.0.projs.push(ProjectionElem::Field(field, ()));
|
||||
new.projs.push(ProjectionElem::Downcast(adt_def, variant_index));
|
||||
new.projs.push(ProjectionElem::Field(field, ()));
|
||||
new
|
||||
}
|
||||
|
||||
pub(crate) fn from_canonical_ty(c_ty: ty::CanonicalTy<'tcx>) -> Self {
|
||||
Self::from_user_type(UserTypeAnnotation::Ty(c_ty))
|
||||
pub(crate) fn from_user_type(user_annotation: CanonicalUserTypeAnnotation<'tcx>) -> Self {
|
||||
Self {
|
||||
base: user_annotation,
|
||||
projs: Vec::new(),
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn from_user_type(u_ty: UserTypeAnnotation<'tcx>) -> Self {
|
||||
Self::from_user_type_proj(UserTypeProjection { base: u_ty, projs: vec![], })
|
||||
pub(crate) fn user_ty(
|
||||
self,
|
||||
annotations: &mut CanonicalUserTypeAnnotations<'tcx>,
|
||||
span: Span,
|
||||
) -> UserTypeProjection<'tcx> {
|
||||
let annotation_index = annotations.push((span, self.base));
|
||||
UserTypeProjection {
|
||||
base: annotation_index,
|
||||
projs: self.projs
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn from_user_type_proj(u_ty: UserTypeProjection<'tcx>) -> Self {
|
||||
PatternTypeProjection(u_ty)
|
||||
}
|
||||
|
||||
pub(crate) fn user_ty(self) -> UserTypeProjection<'tcx> { self.0 }
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
|
|
@ -788,18 +803,14 @@ impl<'a, 'tcx> PatternContext<'a, 'tcx> {
|
|||
};
|
||||
|
||||
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);
|
||||
|
||||
let pat_ty = PatternTypeProjection::from_user_type(user_ty);
|
||||
debug!("lower_variant_or_leaf: user_ty={:?} span={:?}", user_ty, span);
|
||||
kind = PatternKind::AscribeUserType {
|
||||
subpattern,
|
||||
user_ty: pat_ty,
|
||||
subpattern: Pattern {
|
||||
span,
|
||||
ty,
|
||||
kind: Box::new(kind),
|
||||
},
|
||||
user_ty: PatternTypeProjection::from_user_type(user_ty),
|
||||
user_ty_span: span,
|
||||
};
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,37 +1,31 @@
|
|||
use rustc::hir;
|
||||
use rustc::mir::UserTypeAnnotation;
|
||||
use rustc::ty::{self, AdtDef, TyCtxt};
|
||||
use rustc::ty::{self, CanonicalUserTypeAnnotation, TyCtxt, UserTypeAnnotation};
|
||||
|
||||
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<UserTypeAnnotation<'tcx>> {
|
||||
let user_substs = self.tables().user_substs(hir_id)?;
|
||||
Some(UserTypeAnnotation::TypeOf(adt_def.did, 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<UserTypeAnnotation<'tcx>> {
|
||||
let user_substs = self.tables().user_substs(hir_id)?;
|
||||
) -> Option<CanonicalUserTypeAnnotation<'tcx>> {
|
||||
let user_provided_types = self.tables().user_provided_types();
|
||||
let mut user_ty = *user_provided_types.get(hir_id)?;
|
||||
debug!("user_subts_applied_to_ty_of_hir_id: user_ty={:?}", user_ty);
|
||||
match &self.tables().node_id_to_type(hir_id).sty {
|
||||
ty::Adt(adt_def, _) => Some(UserTypeAnnotation::TypeOf(adt_def.did, user_substs)),
|
||||
ty::FnDef(def_id, _) => Some(UserTypeAnnotation::TypeOf(*def_id, user_substs)),
|
||||
sty => bug!(
|
||||
"sty: {:?} should not have user-substs {:?} recorded ",
|
||||
sty,
|
||||
user_substs
|
||||
),
|
||||
ty::Adt(adt_def, ..) => {
|
||||
if let UserTypeAnnotation::TypeOf(ref mut did, _) = &mut user_ty.value {
|
||||
*did = adt_def.did;
|
||||
}
|
||||
Some(user_ty)
|
||||
}
|
||||
ty::FnDef(..) => Some(user_ty),
|
||||
sty =>
|
||||
bug!("sty: {:?} should not have user provided type {:?} recorded ", sty, user_ty),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -207,6 +207,7 @@ fn build_drop_shim<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
|||
IndexVec::new(),
|
||||
None,
|
||||
local_decls_for_sig(&sig, span),
|
||||
IndexVec::new(),
|
||||
sig.inputs().len(),
|
||||
vec![],
|
||||
span,
|
||||
|
|
@ -376,6 +377,7 @@ impl<'a, 'tcx> CloneShimBuilder<'a, 'tcx> {
|
|||
IndexVec::new(),
|
||||
None,
|
||||
self.local_decls,
|
||||
IndexVec::new(),
|
||||
self.sig.inputs().len(),
|
||||
vec![],
|
||||
self.span,
|
||||
|
|
@ -825,6 +827,7 @@ fn build_call_shim<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
|||
IndexVec::new(),
|
||||
None,
|
||||
local_decls,
|
||||
IndexVec::new(),
|
||||
sig.inputs().len(),
|
||||
vec![],
|
||||
span,
|
||||
|
|
@ -903,6 +906,7 @@ pub fn build_adt_ctor<'a, 'gcx, 'tcx>(infcx: &infer::InferCtxt<'a, 'gcx, 'tcx>,
|
|||
IndexVec::new(),
|
||||
None,
|
||||
local_decls,
|
||||
IndexVec::new(),
|
||||
sig.inputs().len(),
|
||||
vec![],
|
||||
span,
|
||||
|
|
|
|||
|
|
@ -400,6 +400,7 @@ pub fn promote_candidates<'a, 'tcx>(mir: &mut Mir<'tcx>,
|
|||
IndexVec::new(),
|
||||
None,
|
||||
initial_locals,
|
||||
IndexVec::new(),
|
||||
0,
|
||||
vec![],
|
||||
mir.span,
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@ use rustc::traits::{
|
|||
Normalized, Obligation, ObligationCause, TraitEngine, TraitEngineExt,
|
||||
};
|
||||
use rustc::ty::query::Providers;
|
||||
use rustc::ty::subst::{Kind, Subst, UserSelfTy, UserSubsts};
|
||||
use rustc::ty::subst::{Kind, Subst, UserSubsts, UserSelfTy};
|
||||
use rustc::ty::{
|
||||
FnSig, Lift, ParamEnv, ParamEnvAnd, PolyFnSig, Predicate, Ty, TyCtxt, TypeFoldable, Variance,
|
||||
};
|
||||
|
|
@ -44,28 +44,16 @@ fn type_op_ascribe_user_type<'tcx>(
|
|||
tcx.infer_ctxt()
|
||||
.enter_canonical_trait_query(&canonicalized, |infcx, fulfill_cx, key| {
|
||||
let (
|
||||
param_env,
|
||||
AscribeUserType {
|
||||
mir_ty,
|
||||
variance,
|
||||
def_id,
|
||||
user_substs,
|
||||
projs,
|
||||
},
|
||||
param_env, AscribeUserType { mir_ty, variance, def_id, user_substs, projs }
|
||||
) = key.into_parts();
|
||||
|
||||
debug!(
|
||||
"type_op_ascribe_user_type(\
|
||||
mir_ty={:?}, variance={:?}, def_id={:?}, user_substs={:?}, projs={:?}\
|
||||
)",
|
||||
mir_ty, variance, def_id, user_substs, projs,
|
||||
"type_op_user_type_relation: mir_ty={:?} variance={:?} def_id={:?} \
|
||||
user_substs={:?} projs={:?}",
|
||||
mir_ty, variance, def_id, user_substs, projs
|
||||
);
|
||||
|
||||
let mut cx = AscribeUserTypeCx {
|
||||
infcx,
|
||||
param_env,
|
||||
fulfill_cx,
|
||||
};
|
||||
let mut cx = AscribeUserTypeCx { infcx, param_env, fulfill_cx };
|
||||
cx.relate_mir_and_user_ty(mir_ty, variance, def_id, user_substs, projs)?;
|
||||
|
||||
Ok(())
|
||||
|
|
@ -130,10 +118,9 @@ impl AscribeUserTypeCx<'me, 'gcx, 'tcx> {
|
|||
projs: &[ProjectionKind<'tcx>],
|
||||
) -> Result<(), NoSolution> {
|
||||
let UserSubsts {
|
||||
substs,
|
||||
user_self_ty,
|
||||
substs,
|
||||
} = user_substs;
|
||||
|
||||
let tcx = self.tcx();
|
||||
|
||||
let ty = tcx.type_of(def_id);
|
||||
|
|
@ -174,8 +161,7 @@ impl AscribeUserTypeCx<'me, 'gcx, 'tcx> {
|
|||
if let Some(UserSelfTy {
|
||||
impl_def_id,
|
||||
self_ty,
|
||||
}) = user_self_ty
|
||||
{
|
||||
}) = user_self_ty {
|
||||
let impl_self_ty = self.tcx().type_of(impl_def_id);
|
||||
let impl_self_ty = self.subst(impl_self_ty, &substs);
|
||||
let impl_self_ty = self.normalize(impl_self_ty);
|
||||
|
|
|
|||
|
|
@ -102,13 +102,14 @@ use rustc::infer::type_variable::{TypeVariableOrigin};
|
|||
use rustc::middle::region;
|
||||
use rustc::mir::interpret::{ConstValue, GlobalId};
|
||||
use rustc::traits::{self, ObligationCause, ObligationCauseCode, TraitEngine};
|
||||
use rustc::ty::{self, AdtKind, Ty, TyCtxt, GenericParamDefKind, RegionKind, Visibility,
|
||||
ToPolyTraitRef, ToPredicate};
|
||||
use rustc::ty::{
|
||||
self, AdtKind, CanonicalUserTypeAnnotation, Ty, TyCtxt, GenericParamDefKind, Visibility,
|
||||
ToPolyTraitRef, ToPredicate, RegionKind, UserTypeAnnotation
|
||||
};
|
||||
use rustc::ty::adjustment::{Adjust, Adjustment, AllowTwoPhase, AutoBorrow, AutoBorrowMutability};
|
||||
use rustc::ty::fold::TypeFoldable;
|
||||
use rustc::ty::query::Providers;
|
||||
use rustc::ty::subst::{CanonicalUserSubsts, UnpackedKind, Subst, Substs,
|
||||
UserSelfTy, UserSubsts};
|
||||
use rustc::ty::subst::{UnpackedKind, Subst, Substs, UserSelfTy, UserSubsts};
|
||||
use rustc::ty::util::{Representability, IntTypeExt, Discr};
|
||||
use rustc::ty::layout::VariantIdx;
|
||||
use syntax_pos::{self, BytePos, Span, MultiSpan};
|
||||
|
|
@ -974,10 +975,12 @@ impl<'a, 'gcx, 'tcx> Visitor<'gcx> for GatherLocalsVisitor<'a, 'gcx, 'tcx> {
|
|||
o_ty
|
||||
};
|
||||
|
||||
let c_ty = self.fcx.inh.infcx.canonicalize_user_type_annotation(&revealed_ty);
|
||||
let c_ty = self.fcx.inh.infcx.canonicalize_user_type_annotation(
|
||||
&UserTypeAnnotation::Ty(revealed_ty)
|
||||
);
|
||||
debug!("visit_local: ty.hir_id={:?} o_ty={:?} revealed_ty={:?} c_ty={:?}",
|
||||
ty.hir_id, o_ty, revealed_ty, c_ty);
|
||||
self.fcx.tables.borrow_mut().user_provided_tys_mut().insert(ty.hir_id, c_ty);
|
||||
self.fcx.tables.borrow_mut().user_provided_types_mut().insert(ty.hir_id, c_ty);
|
||||
|
||||
Some(LocalTy { decl_ty: o_ty, revealed_ty })
|
||||
},
|
||||
|
|
@ -2108,8 +2111,6 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
|||
self.tables.borrow_mut().field_indices_mut().insert(hir_id, index);
|
||||
}
|
||||
|
||||
// The NodeId and the ItemLocalId must identify the same item. We just pass
|
||||
// both of them for consistency checking.
|
||||
pub fn write_method_call(&self,
|
||||
hir_id: hir::HirId,
|
||||
method: MethodCallee<'tcx>) {
|
||||
|
|
@ -2138,23 +2139,27 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
|||
if !method.substs.is_noop() {
|
||||
let method_generics = self.tcx.generics_of(method.def_id);
|
||||
if !method_generics.params.is_empty() {
|
||||
let user_substs = self.infcx.probe(|_| {
|
||||
let just_method_substs = Substs::for_item(self.tcx, method.def_id, |param, _| {
|
||||
let i = param.index as usize;
|
||||
if i < method_generics.parent_count {
|
||||
self.infcx.var_for_def(DUMMY_SP, param)
|
||||
} else {
|
||||
method.substs[i]
|
||||
}
|
||||
});
|
||||
self.infcx.canonicalize_user_type_annotation(&UserSubsts {
|
||||
substs: just_method_substs,
|
||||
let user_type_annotation = self.infcx.probe(|_| {
|
||||
let user_substs = UserSubsts {
|
||||
substs: Substs::for_item(self.tcx, method.def_id, |param, _| {
|
||||
let i = param.index as usize;
|
||||
if i < method_generics.parent_count {
|
||||
self.infcx.var_for_def(DUMMY_SP, param)
|
||||
} else {
|
||||
method.substs[i]
|
||||
}
|
||||
}),
|
||||
user_self_ty: None, // not relevant here
|
||||
})
|
||||
};
|
||||
|
||||
self.infcx.canonicalize_user_type_annotation(&UserTypeAnnotation::TypeOf(
|
||||
method.def_id,
|
||||
user_substs,
|
||||
))
|
||||
});
|
||||
|
||||
debug!("write_method_call: user_substs = {:?}", user_substs);
|
||||
self.write_user_substs(hir_id, user_substs);
|
||||
debug!("write_method_call: user_type_annotation={:?}", user_type_annotation);
|
||||
self.write_user_type_annotation(hir_id, user_type_annotation);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -2177,41 +2182,47 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
|||
/// This should be invoked **before any unifications have
|
||||
/// occurred**, so that annotations like `Vec<_>` are preserved
|
||||
/// properly.
|
||||
pub fn write_user_substs_from_substs(
|
||||
pub fn write_user_type_annotation_from_substs(
|
||||
&self,
|
||||
hir_id: hir::HirId,
|
||||
def_id: DefId,
|
||||
substs: &'tcx Substs<'tcx>,
|
||||
user_self_ty: Option<UserSelfTy<'tcx>>,
|
||||
) {
|
||||
debug!(
|
||||
"write_user_substs_from_substs({:?}, {:?}) in fcx {}",
|
||||
hir_id,
|
||||
substs,
|
||||
self.tag(),
|
||||
"write_user_type_annotation_from_substs: hir_id={:?} def_id={:?} substs={:?} \
|
||||
user_self_ty={:?} in fcx {}",
|
||||
hir_id, def_id, substs, user_self_ty, self.tag(),
|
||||
);
|
||||
|
||||
if !substs.is_noop() {
|
||||
let user_substs = self.infcx.canonicalize_user_type_annotation(&UserSubsts {
|
||||
substs,
|
||||
user_self_ty,
|
||||
});
|
||||
debug!("instantiate_value_path: user_substs = {:?}", user_substs);
|
||||
self.write_user_substs(hir_id, user_substs);
|
||||
let canonicalized = self.infcx.canonicalize_user_type_annotation(
|
||||
&UserTypeAnnotation::TypeOf(def_id, UserSubsts {
|
||||
substs,
|
||||
user_self_ty,
|
||||
})
|
||||
);
|
||||
debug!("write_user_type_annotation_from_substs: canonicalized={:?}", canonicalized);
|
||||
self.write_user_type_annotation(hir_id, canonicalized);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn write_user_substs(&self, hir_id: hir::HirId, substs: CanonicalUserSubsts<'tcx>) {
|
||||
pub fn write_user_type_annotation(
|
||||
&self,
|
||||
hir_id: hir::HirId,
|
||||
canonical_user_type_annotation: CanonicalUserTypeAnnotation<'tcx>,
|
||||
) {
|
||||
debug!(
|
||||
"write_user_substs({:?}, {:?}) in fcx {}",
|
||||
hir_id,
|
||||
substs,
|
||||
self.tag(),
|
||||
"write_user_type_annotation: hir_id={:?} canonical_user_type_annotation={:?} tag={}",
|
||||
hir_id, canonical_user_type_annotation, self.tag(),
|
||||
);
|
||||
|
||||
if !substs.is_identity() {
|
||||
self.tables.borrow_mut().user_substs_mut().insert(hir_id, substs);
|
||||
if !canonical_user_type_annotation.is_identity() {
|
||||
self.tables.borrow_mut().user_provided_types_mut().insert(
|
||||
hir_id, canonical_user_type_annotation
|
||||
);
|
||||
} else {
|
||||
debug!("write_user_substs: skipping identity substs");
|
||||
debug!("write_user_type_annotation: skipping identity substs");
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -2386,8 +2397,8 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
|||
// although I have my doubts). Other sorts of things are
|
||||
// already sufficiently enforced with erased regions. =)
|
||||
if ty.has_free_regions() || ty.has_projections() {
|
||||
let c_ty = self.infcx.canonicalize_response(&ty);
|
||||
self.tables.borrow_mut().user_provided_tys_mut().insert(ast_ty.hir_id, c_ty);
|
||||
let c_ty = self.infcx.canonicalize_response(&UserTypeAnnotation::Ty(ty));
|
||||
self.tables.borrow_mut().user_provided_types_mut().insert(ast_ty.hir_id, c_ty);
|
||||
}
|
||||
|
||||
ty
|
||||
|
|
@ -3734,7 +3745,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
|||
if let Some((variant, did, substs)) = variant {
|
||||
debug!("check_struct_path: did={:?} substs={:?}", did, substs);
|
||||
let hir_id = self.tcx.hir().node_to_hir_id(node_id);
|
||||
self.write_user_substs_from_substs(hir_id, substs, None);
|
||||
self.write_user_type_annotation_from_substs(hir_id, did, substs, None);
|
||||
|
||||
// Check bounds on type arguments used in the path.
|
||||
let bounds = self.instantiate_bounds(path_span, did, substs);
|
||||
|
|
@ -5290,7 +5301,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
|||
|
||||
// First, store the "user substs" for later.
|
||||
let hir_id = tcx.hir().node_to_hir_id(node_id);
|
||||
self.write_user_substs_from_substs(hir_id, substs, user_self_ty);
|
||||
self.write_user_type_annotation_from_substs(hir_id, def_id, substs, user_self_ty);
|
||||
|
||||
// Add all the obligations that are required, substituting and
|
||||
// normalized appropriately.
|
||||
|
|
|
|||
|
|
@ -357,7 +357,7 @@ impl<'cx, 'gcx, 'tcx> WritebackCx<'cx, 'gcx, 'tcx> {
|
|||
debug_assert_eq!(fcx_tables.local_id_root, self.tables.local_id_root);
|
||||
let common_local_id_root = fcx_tables.local_id_root.unwrap();
|
||||
|
||||
for (&local_id, c_ty) in fcx_tables.user_provided_tys().iter() {
|
||||
for (&local_id, c_ty) in fcx_tables.user_provided_types().iter() {
|
||||
let hir_id = hir::HirId {
|
||||
owner: common_local_id_root.index,
|
||||
local_id,
|
||||
|
|
@ -374,8 +374,17 @@ impl<'cx, 'gcx, 'tcx> WritebackCx<'cx, 'gcx, 'tcx> {
|
|||
};
|
||||
|
||||
self.tables
|
||||
.user_provided_tys_mut()
|
||||
.user_provided_types_mut()
|
||||
.insert(hir_id, c_ty.clone());
|
||||
|
||||
if let ty::UserTypeAnnotation::TypeOf(_, user_substs) = c_ty.value {
|
||||
if self.rustc_dump_user_substs {
|
||||
// This is a unit-testing mechanism.
|
||||
let node_id = self.tcx().hir().hir_to_node_id(hir_id);
|
||||
let span = self.tcx().hir().span(node_id);
|
||||
self.tcx().sess.span_err(span, &format!("user substs: {:?}", user_substs));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -573,22 +582,6 @@ impl<'cx, 'gcx, 'tcx> WritebackCx<'cx, 'gcx, 'tcx> {
|
|||
assert!(!substs.needs_infer() && !substs.has_placeholders());
|
||||
self.tables.node_substs_mut().insert(hir_id, substs);
|
||||
}
|
||||
|
||||
// Copy over any user-substs
|
||||
if let Some(user_substs) = self.fcx.tables.borrow().user_substs(hir_id) {
|
||||
let user_substs = self.tcx().lift_to_global(&user_substs).unwrap();
|
||||
self.tables.user_substs_mut().insert(hir_id, user_substs);
|
||||
|
||||
// Unit-testing mechanism:
|
||||
if self.rustc_dump_user_substs {
|
||||
let node_id = self.tcx().hir().hir_to_node_id(hir_id);
|
||||
let span = self.tcx().hir().span(node_id);
|
||||
self.tcx().sess.span_err(
|
||||
span,
|
||||
&format!("user substs: {:?}", user_substs),
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn visit_adjustments(&mut self, span: Span, hir_id: hir::HirId) {
|
||||
|
|
|
|||
|
|
@ -37,7 +37,7 @@ fn main() {
|
|||
// StorageLive(_4);
|
||||
// _4 = std::option::Option<std::boxed::Box<u32>>::None;
|
||||
// FakeRead(ForLet, _4);
|
||||
// AscribeUserType(_4, o, UserTypeProjection { base: Ty(Canonical { max_universe: U0, variables: [], value: std::option::Option<std::boxed::Box<u32>> }), projs: [] });
|
||||
// AscribeUserType(_4, o, UserTypeProjection { base: UserTypeAnnotation(1), projs: [] });
|
||||
// StorageLive(_5);
|
||||
// StorageLive(_6);
|
||||
// _6 = move _4;
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
error: user substs: Canonical { max_universe: U0, variables: [], value: UserSubsts { substs: [u32], user_self_ty: None } }
|
||||
error: user substs: UserSubsts { substs: [u32], user_self_ty: None }
|
||||
--> $DIR/dump-adt-brace-struct.rs:18:5
|
||||
|
|
||||
LL | SomeStruct::<u32> { t: 22 }; //~ ERROR [u32]
|
||||
|
|
|
|||
|
|
@ -1,26 +1,26 @@
|
|||
error: user substs: Canonical { max_universe: U0, variables: [], value: UserSubsts { substs: [u32], user_self_ty: None } }
|
||||
--> $DIR/dump-fn-method.rs:26:13
|
||||
|
|
||||
LL | let x = foo::<u32>; //~ ERROR [u32]
|
||||
| ^^^^^^^^^^
|
||||
|
||||
error: user substs: Canonical { max_universe: U0, variables: [CanonicalVarInfo { kind: Ty(General(U0)) }, CanonicalVarInfo { kind: Ty(General(U0)) }], value: UserSubsts { substs: [^0, u32, ^1], user_self_ty: None } }
|
||||
--> $DIR/dump-fn-method.rs:32:13
|
||||
|
|
||||
LL | let x = <_ as Bazoom<u32>>::method::<_>; //~ ERROR [^0, u32, ^1]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: user substs: Canonical { max_universe: U0, variables: [], value: UserSubsts { substs: [u8, u16, u32], user_self_ty: None } }
|
||||
--> $DIR/dump-fn-method.rs:36:13
|
||||
|
|
||||
LL | let x = <u8 as Bazoom<u16>>::method::<u32>; //~ ERROR [u8, u16, u32]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: user substs: Canonical { max_universe: U0, variables: [CanonicalVarInfo { kind: Ty(General(U0)) }, CanonicalVarInfo { kind: Ty(General(U0)) }], value: UserSubsts { substs: [^0, ^1, u32], user_self_ty: None } }
|
||||
error: user substs: UserSubsts { substs: [^0, ^1, u32], user_self_ty: None }
|
||||
--> $DIR/dump-fn-method.rs:44:5
|
||||
|
|
||||
LL | y.method::<u32>(44, 66); //~ ERROR [^0, ^1, u32]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: user substs: UserSubsts { substs: [^0, u32, ^1], user_self_ty: None }
|
||||
--> $DIR/dump-fn-method.rs:32:13
|
||||
|
|
||||
LL | let x = <_ as Bazoom<u32>>::method::<_>; //~ ERROR [^0, u32, ^1]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: user substs: UserSubsts { substs: [u8, u16, u32], user_self_ty: None }
|
||||
--> $DIR/dump-fn-method.rs:36:13
|
||||
|
|
||||
LL | let x = <u8 as Bazoom<u16>>::method::<u32>; //~ ERROR [u8, u16, u32]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: user substs: UserSubsts { substs: [u32], user_self_ty: None }
|
||||
--> $DIR/dump-fn-method.rs:26:13
|
||||
|
|
||||
LL | let x = foo::<u32>; //~ ERROR [u32]
|
||||
| ^^^^^^^^^^
|
||||
|
||||
error: aborting due to 4 previous errors
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue