Skip to content

Commit 1443ac0

Browse files
committed
introduce a more expressive UserSubsts
1 parent 2a7fc22 commit 1443ac0

File tree

6 files changed

+122
-40
lines changed

6 files changed

+122
-40
lines changed

src/librustc/ich/impls_ty.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1417,3 +1417,8 @@ impl_stable_hash_for!(enum traits::QuantifierKind {
14171417
Universal,
14181418
Existential
14191419
});
1420+
1421+
impl_stable_hash_for!(struct ty::subst::UserSubsts<'tcx> { substs, user_self_ty });
1422+
1423+
impl_stable_hash_for!(struct ty::subst::UserSelfTy<'tcx> { impl_def_id, self_ty });
1424+

src/librustc/mir/mod.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ use syntax::ast::{self, Name};
3737
use syntax::symbol::InternedString;
3838
use syntax_pos::{Span, DUMMY_SP};
3939
use ty::fold::{TypeFoldable, TypeFolder, TypeVisitor};
40-
use ty::subst::{CanonicalSubsts, Subst, Substs};
40+
use ty::subst::{CanonicalUserSubsts, Subst, Substs};
4141
use ty::{self, AdtDef, CanonicalTy, ClosureSubsts, GeneratorSubsts, Region, Ty, TyCtxt};
4242
use util::ppaux;
4343

@@ -2413,8 +2413,8 @@ pub struct Constant<'tcx> {
24132413
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable)]
24142414
pub enum UserTypeAnnotation<'tcx> {
24152415
Ty(CanonicalTy<'tcx>),
2416-
FnDef(DefId, CanonicalSubsts<'tcx>),
2417-
AdtDef(&'tcx AdtDef, CanonicalSubsts<'tcx>),
2416+
FnDef(DefId, CanonicalUserSubsts<'tcx>),
2417+
AdtDef(&'tcx AdtDef, CanonicalUserSubsts<'tcx>),
24182418
}
24192419

24202420
EnumTypeFoldableImpl! {

src/librustc/ty/context.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ use middle::resolve_lifetime::{self, ObjectLifetimeDefault};
3333
use middle::stability;
3434
use mir::{self, Mir, interpret};
3535
use mir::interpret::Allocation;
36-
use ty::subst::{CanonicalSubsts, Kind, Substs, Subst};
36+
use ty::subst::{CanonicalUserSubsts, Kind, Substs, Subst};
3737
use ty::ReprOptions;
3838
use traits;
3939
use traits::{Clause, Clauses, GoalKind, Goal, Goals};
@@ -383,7 +383,7 @@ pub struct TypeckTables<'tcx> {
383383
/// If the user wrote `foo.collect::<Vec<_>>()`, then the
384384
/// canonical substitutions would include only `for<X> { Vec<X>
385385
/// }`.
386-
user_substs: ItemLocalMap<CanonicalSubsts<'tcx>>,
386+
user_substs: ItemLocalMap<CanonicalUserSubsts<'tcx>>,
387387

388388
adjustments: ItemLocalMap<Vec<ty::adjustment::Adjustment<'tcx>>>,
389389

@@ -573,14 +573,14 @@ impl<'tcx> TypeckTables<'tcx> {
573573
self.node_substs.get(&id.local_id).cloned()
574574
}
575575

576-
pub fn user_substs_mut(&mut self) -> LocalTableInContextMut<'_, CanonicalSubsts<'tcx>> {
576+
pub fn user_substs_mut(&mut self) -> LocalTableInContextMut<'_, CanonicalUserSubsts<'tcx>> {
577577
LocalTableInContextMut {
578578
local_id_root: self.local_id_root,
579579
data: &mut self.user_substs
580580
}
581581
}
582582

583-
pub fn user_substs(&self, id: hir::HirId) -> Option<CanonicalSubsts<'tcx>> {
583+
pub fn user_substs(&self, id: hir::HirId) -> Option<CanonicalUserSubsts<'tcx>> {
584584
validate_hir_id_for_typeck_tables(self.local_id_root, id, false);
585585
self.user_substs.get(&id.local_id).cloned()
586586
}

src/librustc/ty/subst.rs

Lines changed: 95 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -323,33 +323,6 @@ impl<'tcx> TypeFoldable<'tcx> for &'tcx Substs<'tcx> {
323323
}
324324
}
325325

326-
pub type CanonicalSubsts<'gcx> = Canonical<'gcx, &'gcx Substs<'gcx>>;
327-
328-
impl<'gcx> CanonicalSubsts<'gcx> {
329-
/// True if this represents a substitution like
330-
///
331-
/// ```text
332-
/// [?0, ?1, ?2]
333-
/// ```
334-
///
335-
/// i.e., each thing is mapped to a canonical variable with the same index.
336-
pub fn is_identity(&self) -> bool {
337-
self.value.iter().zip(CanonicalVar::new(0)..).all(|(kind, cvar)| {
338-
match kind.unpack() {
339-
UnpackedKind::Type(ty) => match ty.sty {
340-
ty::Infer(ty::CanonicalTy(cvar1)) => cvar == cvar1,
341-
_ => false,
342-
},
343-
344-
UnpackedKind::Lifetime(r) => match r {
345-
ty::ReCanonical(cvar1) => cvar == *cvar1,
346-
_ => false,
347-
},
348-
}
349-
})
350-
}
351-
}
352-
353326
impl<'tcx> serialize::UseSpecializedDecodable for &'tcx Substs<'tcx> {}
354327

355328
///////////////////////////////////////////////////////////////////////////
@@ -564,3 +537,98 @@ impl<'a, 'gcx, 'tcx> SubstFolder<'a, 'gcx, 'tcx> {
564537
self.tcx().mk_region(ty::fold::shift_region(*region, self.region_binders_passed))
565538
}
566539
}
540+
541+
pub type CanonicalUserSubsts<'tcx> = Canonical<'tcx, UserSubsts<'tcx>>;
542+
543+
impl CanonicalUserSubsts<'tcx> {
544+
/// True if this represents a substitution like
545+
///
546+
/// ```text
547+
/// [?0, ?1, ?2]
548+
/// ```
549+
///
550+
/// i.e., each thing is mapped to a canonical variable with the same index.
551+
pub fn is_identity(&self) -> bool {
552+
if self.value.user_self_ty.is_some() {
553+
return false;
554+
}
555+
556+
self.value.substs.iter().zip(CanonicalVar::new(0)..).all(|(kind, cvar)| {
557+
match kind.unpack() {
558+
UnpackedKind::Type(ty) => match ty.sty {
559+
ty::Infer(ty::CanonicalTy(cvar1)) => cvar == cvar1,
560+
_ => false,
561+
},
562+
563+
UnpackedKind::Lifetime(r) => match r {
564+
ty::ReCanonical(cvar1) => cvar == *cvar1,
565+
_ => false,
566+
},
567+
}
568+
})
569+
}
570+
}
571+
572+
/// Stores the user-given substs to reach some fully qualified path
573+
/// (e.g., `<T>::Item` or `<T as Trait>::Item`).
574+
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable)]
575+
pub struct UserSubsts<'tcx> {
576+
/// The substitutions for the item as given by the user.
577+
pub substs: &'tcx Substs<'tcx>,
578+
579+
/// The self-type, in the case of a `<T>::Item` path (when applied
580+
/// to an inherent impl). See `UserSubsts` below.
581+
pub user_self_ty: Option<UserSelfTy<'tcx>>,
582+
}
583+
584+
BraceStructTypeFoldableImpl! {
585+
impl<'tcx> TypeFoldable<'tcx> for UserSubsts<'tcx> {
586+
substs,
587+
user_self_ty,
588+
}
589+
}
590+
591+
BraceStructLiftImpl! {
592+
impl<'a, 'tcx> Lift<'tcx> for UserSubsts<'a> {
593+
type Lifted = UserSubsts<'tcx>;
594+
substs,
595+
user_self_ty,
596+
}
597+
}
598+
599+
/// Specifies the user-given self-type. In the case of a path that
600+
/// refers to a member in an inherent impl, this self-type is
601+
/// sometimes needed to constrain the type parameters on the impl. For
602+
/// example, in this code:
603+
///
604+
/// ```
605+
/// struct Foo<T> { }
606+
/// impl<A> Foo<A> { fn method() { } }
607+
/// ```
608+
///
609+
/// when you then have a path like `<Foo<&'static u32>>::method`,
610+
/// this struct would carry the def-id of the impl along with the
611+
/// self-type `Foo<u32>`. Then we can instantiate the parameters of
612+
/// the impl (with the substs from `UserSubsts`) and apply those to
613+
/// the self-type, giving `Foo<?A>`. Finally, we unify that with
614+
/// the self-type here, which contains `?A` to be `&'static u32`
615+
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable)]
616+
pub struct UserSelfTy<'tcx> {
617+
pub impl_def_id: DefId,
618+
pub self_ty: Ty<'tcx>,
619+
}
620+
621+
BraceStructTypeFoldableImpl! {
622+
impl<'tcx> TypeFoldable<'tcx> for UserSelfTy<'tcx> {
623+
impl_def_id,
624+
self_ty,
625+
}
626+
}
627+
628+
BraceStructLiftImpl! {
629+
impl<'a, 'tcx> Lift<'tcx> for UserSelfTy<'a> {
630+
type Lifted = UserSelfTy<'tcx>;
631+
impl_def_id,
632+
self_ty,
633+
}
634+
}

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

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ use rustc::infer::{InferCtxt, NLLRegionVariableOrigin};
1515
use rustc::mir::{ConstraintCategory, UserTypeAnnotation};
1616
use rustc::traits::query::Fallible;
1717
use rustc::ty::relate::TypeRelation;
18+
use rustc::ty::subst::UserSubsts;
1819
use rustc::ty::{self, Ty};
1920
use syntax_pos::DUMMY_SP;
2021

@@ -78,13 +79,15 @@ pub(super) fn relate_type_and_user_type<'tcx>(
7879
ty
7980
}
8081
UserTypeAnnotation::FnDef(def_id, canonical_substs) => {
81-
let (substs, _) =
82+
let (UserSubsts { substs, user_self_ty }, _) =
8283
infcx.instantiate_canonical_with_fresh_inference_vars(DUMMY_SP, &canonical_substs);
84+
assert!(user_self_ty.is_none()); // TODO for now
8385
infcx.tcx.mk_fn_def(def_id, substs)
8486
}
8587
UserTypeAnnotation::AdtDef(adt_def, canonical_substs) => {
86-
let (substs, _) =
88+
let (UserSubsts { substs, user_self_ty }, _) =
8789
infcx.instantiate_canonical_with_fresh_inference_vars(DUMMY_SP, &canonical_substs);
90+
assert!(user_self_ty.is_none()); // TODO for now
8891
infcx.tcx.mk_adt(adt_def, substs)
8992
}
9093
};

src/librustc_typeck/check/mod.rs

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -95,7 +95,7 @@ use rustc::infer::opaque_types::OpaqueTypeDecl;
9595
use rustc::infer::type_variable::{TypeVariableOrigin};
9696
use rustc::middle::region;
9797
use rustc::mir::interpret::{ConstValue, GlobalId};
98-
use rustc::ty::subst::{CanonicalSubsts, UnpackedKind, Subst, Substs};
98+
use rustc::ty::subst::{CanonicalUserSubsts, UnpackedKind, Subst, Substs, UserSubsts};
9999
use rustc::traits::{self, ObligationCause, ObligationCauseCode, TraitEngine};
100100
use rustc::ty::{self, Ty, TyCtxt, GenericParamDefKind, Visibility, ToPredicate, RegionKind};
101101
use rustc::ty::adjustment::{Adjust, Adjustment, AllowTwoPhase, AutoBorrow, AutoBorrowMutability};
@@ -2136,7 +2136,10 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
21362136
method.substs[i]
21372137
}
21382138
});
2139-
self.infcx.canonicalize_response(&just_method_substs)
2139+
self.infcx.canonicalize_response(&UserSubsts {
2140+
substs: just_method_substs,
2141+
user_self_ty: None, // not relevant here
2142+
})
21402143
});
21412144

21422145
debug!("write_method_call: user_substs = {:?}", user_substs);
@@ -2172,13 +2175,16 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
21722175
);
21732176

21742177
if !substs.is_noop() {
2175-
let user_substs = self.infcx.canonicalize_response(&substs);
2178+
let user_substs = self.infcx.canonicalize_response(&UserSubsts {
2179+
substs,
2180+
user_self_ty: None, // TODO -- fix in future commit
2181+
});
21762182
debug!("instantiate_value_path: user_substs = {:?}", user_substs);
21772183
self.write_user_substs(hir_id, user_substs);
21782184
}
21792185
}
21802186

2181-
pub fn write_user_substs(&self, hir_id: hir::HirId, substs: CanonicalSubsts<'tcx>) {
2187+
pub fn write_user_substs(&self, hir_id: hir::HirId, substs: CanonicalUserSubsts<'tcx>) {
21822188
debug!(
21832189
"write_user_substs({:?}, {:?}) in fcx {}",
21842190
hir_id,

0 commit comments

Comments
 (0)