Skip to content

Commit

Permalink
rustc: reduce Substs and Generics to a simple immutable API.
Browse files Browse the repository at this point in the history
  • Loading branch information
eddyb committed Aug 17, 2016
1 parent bfdfa1c commit 4158673
Show file tree
Hide file tree
Showing 80 changed files with 1,226 additions and 1,548 deletions.
2 changes: 1 addition & 1 deletion src/librustc/infer/error_reporting.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1366,7 +1366,7 @@ impl<'a, 'gcx, 'tcx> Rebuilder<'a, 'gcx, 'tcx> {
hir::TyPath(ref maybe_qself, ref path) => {
match self.tcx.expect_def(cur_ty.id) {
Def::Enum(did) | Def::TyAlias(did) | Def::Struct(did) => {
let generics = self.tcx.lookup_item_type(did).generics;
let generics = self.tcx.lookup_generics(did);

let expected =
generics.regions.len(subst::TypeSpace) as u32;
Expand Down
44 changes: 7 additions & 37 deletions src/librustc/infer/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,9 +25,7 @@ use middle::mem_categorization as mc;
use middle::mem_categorization::McResult;
use middle::region::CodeExtent;
use mir::tcx::LvalueTy;
use ty::subst;
use ty::subst::Substs;
use ty::subst::Subst;
use ty::subst::{Subst, Substs};
use ty::adjustment;
use ty::{TyVid, IntVid, FloatVid};
use ty::{self, Ty, TyCtxt};
Expand Down Expand Up @@ -1236,43 +1234,15 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {

/// Given a set of generics defined on a type or impl, returns a substitution mapping each
/// type/region parameter to a fresh inference variable.
pub fn fresh_substs_for_generics(&self,
span: Span,
generics: &ty::Generics<'tcx>)
-> &'tcx subst::Substs<'tcx>
{
let substs = Substs::from_generics(generics, |def, _| {
pub fn fresh_substs_for_item(&self,
span: Span,
def_id: DefId)
-> &'tcx Substs<'tcx> {
Substs::for_item(self.tcx, def_id, |def, _| {
self.region_var_for_def(span, def)
}, |def, substs| {
self.type_var_for_def(span, def, substs)
});

self.tcx.mk_substs(substs)
}

/// Given a set of generics defined on a trait, returns a substitution mapping each output
/// type/region parameter to a fresh inference variable, and mapping the self type to
/// `self_ty`.
pub fn fresh_substs_for_trait(&self,
span: Span,
generics: &ty::Generics<'tcx>,
self_ty: Ty<'tcx>)
-> &'tcx subst::Substs<'tcx>
{
assert!(generics.types.len(subst::SelfSpace) == 1);
assert!(generics.types.len(subst::FnSpace) == 0);

let substs = Substs::from_generics(generics, |def, _| {
self.region_var_for_def(span, def)
}, |def, substs| {
if def.space == subst::SelfSpace {
self_ty
} else {
self.type_var_for_def(span, def, substs)
}
});

self.tcx.mk_substs(substs)
})
}

pub fn fresh_bound_region(&self, debruijn: ty::DebruijnIndex) -> ty::Region {
Expand Down
16 changes: 9 additions & 7 deletions src/librustc/middle/cstore.rs
Original file line number Diff line number Diff line change
Expand Up @@ -154,14 +154,16 @@ pub trait CrateStore<'tcx> {
fn item_variances(&self, def: DefId) -> ty::ItemVariances;
fn repr_attrs(&self, def: DefId) -> Vec<attr::ReprAttr>;
fn item_type<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, def: DefId)
-> ty::TypeScheme<'tcx>;
-> Ty<'tcx>;
fn visible_parent_map<'a>(&'a self) -> ::std::cell::RefMut<'a, DefIdMap<DefId>>;
fn item_name(&self, def: DefId) -> ast::Name;
fn opt_item_name(&self, def: DefId) -> Option<ast::Name>;
fn item_predicates<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, def: DefId)
-> ty::GenericPredicates<'tcx>;
fn item_super_predicates<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, def: DefId)
-> ty::GenericPredicates<'tcx>;
fn item_generics<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, def: DefId)
-> &'tcx ty::Generics<'tcx>;
fn item_attrs(&self, def_id: DefId) -> Vec<ast::Attribute>;
fn trait_def<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, def: DefId)-> ty::TraitDef<'tcx>;
fn adt_def<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, def: DefId) -> ty::AdtDefMaster<'tcx>;
Expand All @@ -187,8 +189,7 @@ pub trait CrateStore<'tcx> {
fn impl_parent(&self, impl_def_id: DefId) -> Option<DefId>;

// trait/impl-item info
fn trait_of_item<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId)
-> Option<DefId>;
fn trait_of_item(&self, def_id: DefId) -> Option<DefId>;
fn impl_or_trait_item<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, def: DefId)
-> Option<ty::ImplOrTraitItem<'tcx>>;

Expand Down Expand Up @@ -334,7 +335,7 @@ impl<'tcx> CrateStore<'tcx> for DummyCrateStore {
fn item_variances(&self, def: DefId) -> ty::ItemVariances { bug!("item_variances") }
fn repr_attrs(&self, def: DefId) -> Vec<attr::ReprAttr> { bug!("repr_attrs") }
fn item_type<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, def: DefId)
-> ty::TypeScheme<'tcx> { bug!("item_type") }
-> Ty<'tcx> { bug!("item_type") }
fn visible_parent_map<'a>(&'a self) -> ::std::cell::RefMut<'a, DefIdMap<DefId>> {
bug!("visible_parent_map")
}
Expand All @@ -344,6 +345,8 @@ impl<'tcx> CrateStore<'tcx> for DummyCrateStore {
-> ty::GenericPredicates<'tcx> { bug!("item_predicates") }
fn item_super_predicates<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, def: DefId)
-> ty::GenericPredicates<'tcx> { bug!("item_super_predicates") }
fn item_generics<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, def: DefId)
-> &'tcx ty::Generics<'tcx> { bug!("item_generics") }
fn item_attrs(&self, def_id: DefId) -> Vec<ast::Attribute> { bug!("item_attrs") }
fn trait_def<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, def: DefId)-> ty::TraitDef<'tcx>
{ bug!("trait_def") }
Expand Down Expand Up @@ -379,8 +382,7 @@ impl<'tcx> CrateStore<'tcx> for DummyCrateStore {
fn impl_parent(&self, def: DefId) -> Option<DefId> { bug!("impl_parent") }

// trait/impl-item info
fn trait_of_item<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId)
-> Option<DefId> { bug!("trait_of_item") }
fn trait_of_item(&self, def_id: DefId) -> Option<DefId> { bug!("trait_of_item") }
fn impl_or_trait_item<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, def: DefId)
-> Option<ty::ImplOrTraitItem<'tcx>> { bug!("impl_or_trait_item") }

Expand Down Expand Up @@ -583,7 +585,7 @@ pub mod tls {
pub trait DecodingContext<'tcx> {
fn tcx<'a>(&'a self) -> TyCtxt<'a, 'tcx, 'tcx>;
fn decode_ty(&self, decoder: &mut OpaqueDecoder) -> ty::Ty<'tcx>;
fn decode_substs(&self, decoder: &mut OpaqueDecoder) -> Substs<'tcx>;
fn decode_substs(&self, decoder: &mut OpaqueDecoder) -> &'tcx Substs<'tcx>;
fn translate_def_id(&self, def_id: DefId) -> DefId;
}

Expand Down
25 changes: 17 additions & 8 deletions src/librustc/middle/dead.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ use hir::{self, pat_util, PatKind};
use hir::intravisit::{self, Visitor};

use middle::privacy;
use ty::{self, TyCtxt};
use ty::{self, subst, TyCtxt};
use hir::def::Def;
use hir::def_id::{DefId};
use lint;
Expand Down Expand Up @@ -88,15 +88,24 @@ impl<'a, 'tcx> MarkSymbolVisitor<'a, 'tcx> {
fn lookup_and_handle_definition(&mut self, id: ast::NodeId) {
use ty::TypeVariants::{TyEnum, TyStruct};

let def = self.tcx.expect_def(id);

// If `bar` is a trait item, make sure to mark Foo as alive in `Foo::bar`
self.tcx.tables.borrow().item_substs.get(&id)
.and_then(|substs| substs.substs.self_ty())
.map(|ty| match ty.sty {
TyEnum(tyid, _) | TyStruct(tyid, _) => self.check_def_id(tyid.did),
_ => (),
});
match def {
Def::AssociatedTy(..) | Def::Method(_) | Def::AssociatedConst(_)
if self.tcx.trait_of_item(def.def_id()).is_some() => {
if let Some(substs) = self.tcx.tables.borrow().item_substs.get(&id) {
match substs.substs.types.get(subst::SelfSpace, 0).sty {
TyEnum(tyid, _) | TyStruct(tyid, _) => {
self.check_def_id(tyid.did)
}
_ => {}
}
}
}
_ => {}
}

let def = self.tcx.expect_def(id);
match def {
Def::Const(_) | Def::AssociatedConst(..) => {
self.check_def_id(def.def_id());
Expand Down
9 changes: 2 additions & 7 deletions src/librustc/mir/repr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1073,10 +1073,7 @@ impl<'tcx> Debug for Rvalue<'tcx> {
let variant_def = &adt_def.variants[variant];

ppaux::parameterized(fmt, substs, variant_def.did,
ppaux::Ns::Value, &[],
|tcx| {
Some(tcx.lookup_item_type(variant_def.did).generics)
})?;
ppaux::Ns::Value, &[])?;

match variant_def.kind {
ty::VariantKind::Unit => Ok(()),
Expand Down Expand Up @@ -1169,9 +1166,7 @@ impl<'tcx> Debug for Literal<'tcx> {
use self::Literal::*;
match *self {
Item { def_id, substs } => {
ppaux::parameterized(
fmt, substs, def_id, ppaux::Ns::Value, &[],
|tcx| Some(tcx.lookup_item_type(def_id).generics))
ppaux::parameterized(fmt, substs, def_id, ppaux::Ns::Value, &[])
}
Value { ref value } => {
write!(fmt, "const ")?;
Expand Down
4 changes: 1 addition & 3 deletions src/librustc/traits/error_reporting.rs
Original file line number Diff line number Diff line change
Expand Up @@ -221,9 +221,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {

self.tcx.lookup_trait_def(trait_ref.def_id)
.for_each_relevant_impl(self.tcx, trait_self_ty, |def_id| {
let ity = tcx.lookup_item_type(def_id);
let impl_substs = self.fresh_substs_for_generics(obligation.cause.span,
&ity.generics);
let impl_substs = self.fresh_substs_for_item(obligation.cause.span, def_id);
let impl_trait_ref = tcx
.impl_trait_ref(def_id)
.unwrap()
Expand Down
3 changes: 1 addition & 2 deletions src/librustc/traits/fulfill.rs
Original file line number Diff line number Diff line change
Expand Up @@ -160,10 +160,9 @@ impl<'a, 'gcx, 'tcx> DeferredObligation<'tcx> {
// We can resolve the `impl Trait` to its concrete type.
if let Some(ty_scheme) = tcx.opt_lookup_item_type(def_id) {
let concrete_ty = ty_scheme.ty.subst(tcx, substs);
let concrete_substs = Substs::new_trait(vec![], vec![], concrete_ty);
let predicate = ty::TraitRef {
def_id: self.predicate.def_id(),
substs: tcx.mk_substs(concrete_substs)
substs: Substs::new_trait(tcx, vec![], vec![], concrete_ty)
}.to_predicate();

let original_obligation = Obligation::new(self.cause.clone(),
Expand Down
4 changes: 2 additions & 2 deletions src/librustc/traits/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ pub use self::ObligationCauseCode::*;

use hir::def_id::DefId;
use middle::free_region::FreeRegionMap;
use ty::subst;
use ty::subst::Substs;
use ty::{self, Ty, TyCtxt, TypeFoldable};
use infer::InferCtxt;

Expand Down Expand Up @@ -272,7 +272,7 @@ pub enum Vtable<'tcx, N> {
#[derive(Clone, PartialEq, Eq)]
pub struct VtableImplData<'tcx, N> {
pub impl_def_id: DefId,
pub substs: &'tcx subst::Substs<'tcx>,
pub substs: &'tcx Substs<'tcx>,
pub nested: Vec<N>
}

Expand Down
19 changes: 7 additions & 12 deletions src/librustc/traits/object_safety.rs
Original file line number Diff line number Diff line change
Expand Up @@ -166,25 +166,20 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
}

fn trait_has_sized_self(self, trait_def_id: DefId) -> bool {
let trait_def = self.lookup_trait_def(trait_def_id);
let trait_predicates = self.lookup_predicates(trait_def_id);
self.generics_require_sized_self(&trait_def.generics, &trait_predicates)
self.generics_require_sized_self(trait_def_id)
}

fn generics_require_sized_self(self,
generics: &ty::Generics<'gcx>,
predicates: &ty::GenericPredicates<'gcx>)
-> bool
{
fn generics_require_sized_self(self, def_id: DefId) -> bool {
let sized_def_id = match self.lang_items.sized_trait() {
Some(def_id) => def_id,
None => { return false; /* No Sized trait, can't require it! */ }
};

// Search for a predicate like `Self : Sized` amongst the trait bounds.
let free_substs = self.construct_free_substs(generics,
let free_substs = self.construct_free_substs(def_id,
self.region_maps.node_extent(ast::DUMMY_NODE_ID));
let predicates = predicates.instantiate(self, &free_substs).predicates;
let predicates = self.lookup_predicates(def_id);
let predicates = predicates.instantiate(self, free_substs).predicates;
elaborate_predicates(self, predicates)
.any(|predicate| {
match predicate {
Expand Down Expand Up @@ -214,7 +209,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
{
// Any method that has a `Self : Sized` requisite is otherwise
// exempt from the regulations.
if self.generics_require_sized_self(&method.generics, &method.predicates) {
if self.generics_require_sized_self(method.def_id) {
return None;
}

Expand All @@ -231,7 +226,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
-> bool
{
// Any method that has a `Self : Sized` requisite can't be called.
if self.generics_require_sized_self(&method.generics, &method.predicates) {
if self.generics_require_sized_self(method.def_id) {
return false;
}

Expand Down
49 changes: 28 additions & 21 deletions src/librustc/traits/select.rs
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ use traits;
use ty::fast_reject;
use ty::relate::TypeRelation;

use rustc_data_structures::bitvec::BitVector;
use rustc_data_structures::snapshot_vec::{SnapshotVecDelegate, SnapshotVec};
use std::cell::RefCell;
use std::fmt;
Expand Down Expand Up @@ -1935,7 +1936,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {

// for `PhantomData<T>`, we pass `T`
ty::TyStruct(def, substs) if def.is_phantom_data() => {
substs.types.get_slice(TypeSpace).to_vec()
substs.types.as_full_slice().to_vec()
}

ty::TyStruct(def, substs) | ty::TyEnum(def, substs) => {
Expand Down Expand Up @@ -2584,30 +2585,33 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
} else {
return Err(Unimplemented);
};
let mut ty_params = vec![];
let mut ty_params = BitVector::new(substs_a.types.len(TypeSpace));
let mut found = false;
for ty in field.walk() {
if let ty::TyParam(p) = ty.sty {
assert!(p.space == TypeSpace);
let idx = p.idx as usize;
if !ty_params.contains(&idx) {
ty_params.push(idx);
}
ty_params.insert(p.idx as usize);
found = true;
}
}
if ty_params.is_empty() {
if !found {
return Err(Unimplemented);
}

// Replace type parameters used in unsizing with
// TyError and ensure they do not affect any other fields.
// This could be checked after type collection for any struct
// with a potentially unsized trailing field.
let mut new_substs = substs_a.clone();
for &i in &ty_params {
new_substs.types.get_mut_slice(TypeSpace)[i] = tcx.types.err;
}
let types = substs_a.types.map_enumerated(|(_, i, ty)| {
if ty_params.contains(i) {
tcx.types.err
} else {
ty
}
});
let substs = Substs::new(tcx, types, substs_a.regions.clone());
for &ty in fields.split_last().unwrap().1 {
if ty.subst(tcx, &new_substs).references_error() {
if ty.subst(tcx, substs).references_error() {
return Err(Unimplemented);
}
}
Expand All @@ -2618,11 +2622,15 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {

// Check that the source structure with the target's
// type parameters is a subtype of the target.
for &i in &ty_params {
let param_b = *substs_b.types.get(TypeSpace, i);
new_substs.types.get_mut_slice(TypeSpace)[i] = param_b;
}
let new_struct = tcx.mk_struct(def, tcx.mk_substs(new_substs));
let types = substs_a.types.map_enumerated(|(_, i, ty)| {
if ty_params.contains(i) {
*substs_b.types.get(TypeSpace, i)
} else {
ty
}
});
let substs = Substs::new(tcx, types, substs_a.regions.clone());
let new_struct = tcx.mk_struct(def, substs);
let origin = TypeOrigin::Misc(obligation.cause.span);
let InferOk { obligations, .. } =
self.infcx.sub_types(false, origin, new_struct, target)
Expand Down Expand Up @@ -2691,12 +2699,11 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
snapshot);
let skol_obligation_trait_ref = skol_obligation.trait_ref;

let impl_substs = util::fresh_type_vars_for_impl(self.infcx,
obligation.cause.span,
impl_def_id);
let impl_substs = self.infcx.fresh_substs_for_item(obligation.cause.span,
impl_def_id);

let impl_trait_ref = impl_trait_ref.subst(self.tcx(),
&impl_substs);
impl_substs);

let impl_trait_ref =
project::normalize_with_depth(self,
Expand Down
Loading

0 comments on commit 4158673

Please sign in to comment.