Skip to content

Commit 3e74e5b

Browse files
committed
rustc: split Generics of a method from its parent Generics.
1 parent c1cfd58 commit 3e74e5b

File tree

25 files changed

+290
-264
lines changed

25 files changed

+290
-264
lines changed

src/librustc/infer/error_reporting.rs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,6 @@ use hir::def::Def;
8282
use hir::def_id::DefId;
8383
use infer::{self, TypeOrigin};
8484
use middle::region;
85-
use ty::subst;
8685
use ty::{self, TyCtxt, TypeFoldable};
8786
use ty::{Region, ReFree};
8887
use ty::error::TypeError;
@@ -1369,7 +1368,7 @@ impl<'a, 'gcx, 'tcx> Rebuilder<'a, 'gcx, 'tcx> {
13691368
let generics = self.tcx.lookup_generics(did);
13701369

13711370
let expected =
1372-
generics.regions.len(subst::TypeSpace) as u32;
1371+
generics.regions.len() as u32;
13731372
let lifetimes =
13741373
path.segments.last().unwrap().parameters.lifetimes();
13751374
let mut insert = Vec::new();

src/librustc/traits/error_reporting.rs

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -271,14 +271,10 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
271271
let def = self.tcx.lookup_trait_def(trait_ref.def_id);
272272
let trait_str = def.trait_ref.to_string();
273273
if let Some(ref istring) = item.value_str() {
274-
let mut generic_map = def.generics.types.iter_enumerated()
275-
.map(|(param, i, gen)| {
276-
(gen.name.as_str().to_string(),
277-
trait_ref.substs.types.get(param, i)
278-
.to_string())
279-
}).collect::<FnvHashMap<String, String>>();
280-
generic_map.insert("Self".to_string(),
281-
trait_ref.self_ty().to_string());
274+
let generic_map = def.generics.types.iter().map(|param| {
275+
(param.name.as_str().to_string(),
276+
trait_ref.substs.type_for_def(param).to_string())
277+
}).collect::<FnvHashMap<String, String>>();
282278
let parser = Parser::new(&istring);
283279
let mut errored = false;
284280
let err: String = parser.filter_map(|p| {

src/librustc/traits/object_safety.rs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,6 @@
2020
use super::elaborate_predicates;
2121

2222
use hir::def_id::DefId;
23-
use ty::subst;
2423
use traits;
2524
use ty::{self, ToPolyTraitRef, Ty, TyCtxt, TypeFoldable};
2625
use std::rc::Rc;
@@ -266,7 +265,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
266265
}
267266

268267
// We can't monomorphize things like `fn foo<A>(...)`.
269-
if !method.generics.types.is_empty_in(subst::FnSpace) {
268+
if !method.generics.types.is_empty() {
270269
return Some(MethodViolationCode::Generic);
271270
}
272271

src/librustc/ty/mod.rs

Lines changed: 5 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -757,33 +757,14 @@ impl RegionParameterDef {
757757
/// with an item or method. Analogous to hir::Generics.
758758
#[derive(Clone, Debug)]
759759
pub struct Generics<'tcx> {
760-
pub types: VecPerParamSpace<TypeParameterDef<'tcx>>,
761-
pub regions: VecPerParamSpace<RegionParameterDef>,
760+
pub parent: Option<DefId>,
761+
pub parent_regions: u32,
762+
pub parent_types: u32,
763+
pub regions: Vec<RegionParameterDef>,
764+
pub types: Vec<TypeParameterDef<'tcx>>,
762765
pub has_self: bool,
763766
}
764767

765-
impl<'tcx> Generics<'tcx> {
766-
pub fn empty() -> Generics<'tcx> {
767-
Generics {
768-
types: VecPerParamSpace::empty(),
769-
regions: VecPerParamSpace::empty(),
770-
has_self: false,
771-
}
772-
}
773-
774-
pub fn is_empty(&self) -> bool {
775-
self.types.is_empty() && self.regions.is_empty()
776-
}
777-
778-
pub fn has_type_params(&self, space: subst::ParamSpace) -> bool {
779-
!self.types.is_empty_in(space)
780-
}
781-
782-
pub fn has_region_params(&self, space: subst::ParamSpace) -> bool {
783-
!self.regions.is_empty_in(space)
784-
}
785-
}
786-
787768
/// Bounds on generics.
788769
#[derive(Clone)]
789770
pub struct GenericPredicates<'tcx> {

src/librustc/ty/structural_impls.rs

Lines changed: 0 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -832,20 +832,6 @@ impl<'tcx> TypeFoldable<'tcx> for ty::RegionParameterDef {
832832
}
833833
}
834834

835-
impl<'tcx> TypeFoldable<'tcx> for ty::Generics<'tcx> {
836-
fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) -> Self {
837-
ty::Generics {
838-
types: self.types.fold_with(folder),
839-
regions: self.regions.fold_with(folder),
840-
has_self: self.has_self
841-
}
842-
}
843-
844-
fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> bool {
845-
self.types.visit_with(visitor) || self.regions.visit_with(visitor)
846-
}
847-
}
848-
849835
impl<'tcx> TypeFoldable<'tcx> for ty::GenericPredicates<'tcx> {
850836
fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) -> Self {
851837
ty::GenericPredicates {

src/librustc/ty/subst.rs

Lines changed: 41 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -89,42 +89,55 @@ impl<'a, 'gcx, 'tcx> Substs<'tcx> {
8989
where FR: FnMut(&ty::RegionParameterDef, &Substs<'tcx>) -> ty::Region,
9090
FT: FnMut(&ty::TypeParameterDef<'tcx>, &Substs<'tcx>) -> Ty<'tcx> {
9191
let defs = tcx.lookup_generics(def_id);
92+
let num_regions = defs.parent_regions as usize + defs.regions.len();
93+
let num_types = defs.parent_types as usize + defs.types.len();
9294
let mut substs = Substs {
93-
types: VecPerParamSpace {
95+
regions: VecPerParamSpace {
9496
type_limit: 0,
95-
content: Vec::with_capacity(defs.types.content.len())
97+
content: Vec::with_capacity(num_regions)
9698
},
97-
regions: VecPerParamSpace {
99+
types: VecPerParamSpace {
98100
type_limit: 0,
99-
content: Vec::with_capacity(defs.regions.content.len())
101+
content: Vec::with_capacity(num_types)
100102
}
101103
};
102104

103-
for &space in &ParamSpace::all() {
104-
for def in defs.regions.get_slice(space) {
105-
assert_eq!(def.space, space);
106-
107-
let region = mk_region(def, &substs);
108-
substs.regions.content.push(region);
105+
substs.fill_item(tcx, defs, &mut mk_region, &mut mk_type);
109106

110-
if space == TypeSpace {
111-
substs.regions.type_limit += 1;
112-
}
113-
}
107+
Substs::new(tcx, substs.types, substs.regions)
108+
}
114109

115-
for def in defs.types.get_slice(space) {
116-
assert_eq!(def.space, space);
110+
fn fill_item<FR, FT>(&mut self,
111+
tcx: TyCtxt<'a, 'gcx, 'tcx>,
112+
defs: &ty::Generics<'tcx>,
113+
mk_region: &mut FR,
114+
mk_type: &mut FT)
115+
where FR: FnMut(&ty::RegionParameterDef, &Substs<'tcx>) -> ty::Region,
116+
FT: FnMut(&ty::TypeParameterDef<'tcx>, &Substs<'tcx>) -> Ty<'tcx> {
117+
if let Some(def_id) = defs.parent {
118+
let parent_defs = tcx.lookup_generics(def_id);
119+
self.fill_item(tcx, parent_defs, mk_region, mk_type);
120+
}
117121

118-
let ty = mk_type(def, &substs);
119-
substs.types.content.push(ty);
122+
for def in &defs.regions {
123+
let region = mk_region(def, self);
124+
self.regions.content.push(region);
120125

121-
if space == TypeSpace {
122-
substs.types.type_limit += 1;
123-
}
126+
if def.space == TypeSpace {
127+
self.regions.type_limit += 1;
128+
assert_eq!(self.regions.content.len(), self.regions.type_limit);
124129
}
125130
}
126131

127-
Substs::new(tcx, substs.types, substs.regions)
132+
for def in &defs.types {
133+
let ty = mk_type(def, self);
134+
self.types.content.push(ty);
135+
136+
if def.space == TypeSpace {
137+
self.types.type_limit += 1;
138+
assert_eq!(self.types.content.len(), self.types.type_limit);
139+
}
140+
}
128141
}
129142

130143
pub fn is_noop(&self) -> bool {
@@ -149,16 +162,14 @@ impl<'a, 'gcx, 'tcx> Substs<'tcx> {
149162
target_substs: &Substs<'tcx>)
150163
-> &'tcx Substs<'tcx> {
151164
let defs = tcx.lookup_generics(source_ancestor);
152-
assert_eq!(self.types.len(TypeSpace), defs.types.len(TypeSpace));
165+
assert_eq!(self.types.len(TypeSpace), defs.types.len());
153166
assert_eq!(target_substs.types.len(FnSpace), 0);
154-
assert_eq!(defs.types.len(FnSpace), 0);
155-
assert_eq!(self.regions.len(TypeSpace), defs.regions.len(TypeSpace));
167+
assert_eq!(self.regions.len(TypeSpace), defs.regions.len());
156168
assert_eq!(target_substs.regions.len(FnSpace), 0);
157-
assert_eq!(defs.regions.len(FnSpace), 0);
158169

159170
let Substs { mut types, mut regions } = target_substs.clone();
160-
types.content.extend(&self.types.as_full_slice()[defs.types.content.len()..]);
161-
regions.content.extend(&self.regions.as_full_slice()[defs.regions.content.len()..]);
171+
types.content.extend(&self.types.as_full_slice()[defs.types.len()..]);
172+
regions.content.extend(&self.regions.as_full_slice()[defs.regions.len()..]);
162173
Substs::new(tcx, types, regions)
163174
}
164175
}
@@ -597,8 +608,8 @@ impl<'a, 'gcx, 'tcx> ty::TraitRef<'tcx> {
597608
-> ty::TraitRef<'tcx> {
598609
let Substs { mut types, mut regions } = substs.clone();
599610
let defs = tcx.lookup_generics(trait_id);
600-
types.content.truncate(defs.types.type_limit);
601-
regions.content.truncate(defs.regions.type_limit);
611+
types.content.truncate(defs.types.len());
612+
regions.content.truncate(defs.regions.len());
602613

603614
ty::TraitRef {
604615
def_id: trait_id,

src/librustc/util/ppaux.rs

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -73,13 +73,15 @@ pub fn parameterized(f: &mut fmt::Formatter,
7373
let mut has_self = false;
7474
let (fn_trait_kind, item_name) = ty::tls::with(|tcx| {
7575
verbose = tcx.sess.verbose();
76-
let generics = tcx.lookup_generics(did);
76+
let mut generics = tcx.lookup_generics(did);
77+
if let Some(def_id) = generics.parent {
78+
generics = tcx.lookup_generics(def_id);
79+
}
7780
if !verbose {
78-
let ty_params = generics.types.get_slice(subst::TypeSpace);
79-
if ty_params.last().map_or(false, |def| def.default.is_some()) {
81+
if generics.types.last().map_or(false, |def| def.default.is_some()) {
8082
if let Some(substs) = tcx.lift(&substs) {
8183
let tps = substs.types.get_slice(subst::TypeSpace);
82-
for (def, actual) in ty_params.iter().zip(tps).rev() {
84+
for (def, actual) in generics.types.iter().zip(tps).rev() {
8385
if def.default.subst(tcx, substs) != Some(actual) {
8486
break;
8587
}

src/librustc_metadata/encoder.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -620,9 +620,9 @@ fn encode_info_for_method<'a, 'tcx>(ecx: &EncodeContext<'a, 'tcx>,
620620
if let Some(impl_item) = impl_item_opt {
621621
if let hir::ImplItemKind::Method(ref sig, _) = impl_item.node {
622622
encode_attributes(rbml_w, &impl_item.attrs);
623-
let scheme = ecx.tcx.lookup_item_type(m.def_id);
624-
let any_types = !scheme.generics.types.is_empty();
625-
let needs_inline = any_types || is_default_impl ||
623+
let generics = ecx.tcx.lookup_generics(m.def_id);
624+
let types = generics.parent_types as usize + generics.types.len();
625+
let needs_inline = types > 0 || is_default_impl ||
626626
attr::requests_inline(&impl_item.attrs);
627627
if needs_inline || sig.constness == hir::Constness::Const {
628628
encode_inlined_item(ecx,

src/librustc_metadata/tydecode.rs

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -149,9 +149,29 @@ impl<'a,'tcx> TyDecoder<'a,'tcx> {
149149
}
150150

151151
pub fn parse_generics(&mut self) -> &'tcx ty::Generics<'tcx> {
152-
let regions = self.parse_vec_per_param_space(|this| this.parse_region_param_def());
153-
let types = self.parse_vec_per_param_space(|this| this.parse_type_param_def());
152+
let parent = self.parse_opt(|this| this.parse_def());
153+
let parent_regions = self.parse_u32();
154+
assert_eq!(self.next(), '|');
155+
let parent_types = self.parse_u32();
156+
157+
let mut regions = vec![];
158+
assert_eq!(self.next(), '[');
159+
while self.peek() != ']' {
160+
regions.push(self.parse_region_param_def());
161+
}
162+
assert_eq!(self.next(), ']');
163+
164+
let mut types = vec![];
165+
assert_eq!(self.next(), '[');
166+
while self.peek() != ']' {
167+
types.push(self.parse_type_param_def());
168+
}
169+
assert_eq!(self.next(), ']');
170+
154171
self.tcx.alloc_generics(ty::Generics {
172+
parent: parent,
173+
parent_regions: parent_regions,
174+
parent_types: parent_types,
155175
regions: regions,
156176
types: types,
157177
has_self: self.next() == 'S'

src/librustc_metadata/tyencode.rs

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -274,10 +274,21 @@ pub fn enc_substs<'a, 'tcx>(w: &mut Cursor<Vec<u8>>, cx: &ctxt<'a, 'tcx>,
274274

275275
pub fn enc_generics<'a, 'tcx>(w: &mut Cursor<Vec<u8>>, cx: &ctxt<'a, 'tcx>,
276276
generics: &ty::Generics<'tcx>) {
277-
enc_vec_per_param_space(w, cx, &generics.regions,
278-
|w, cx, r| enc_region_param_def(w, cx, r));
279-
enc_vec_per_param_space(w, cx, &generics.types,
280-
|w, cx, ty| enc_type_param_def(w, cx, ty));
277+
enc_opt(w, generics.parent, |w, def_id| {
278+
write!(w, "{}|", (cx.ds)(cx.tcx, def_id));
279+
});
280+
write!(w, "{}|{}[",
281+
generics.parent_regions,
282+
generics.parent_types);
283+
284+
for r in &generics.regions {
285+
enc_region_param_def(w, cx, r)
286+
}
287+
write!(w, "][");
288+
for t in &generics.types {
289+
enc_type_param_def(w, cx, t);
290+
}
291+
write!(w, "]");
281292

282293
if generics.has_self {
283294
write!(w, "S");

src/librustc_trans/base.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2470,8 +2470,8 @@ pub fn filter_reachable_ids(tcx: TyCtxt, reachable: NodeSet) -> NodeSet {
24702470
hir_map::NodeImplItem(&hir::ImplItem {
24712471
node: hir::ImplItemKind::Method(..), .. }) => {
24722472
let def_id = tcx.map.local_def_id(id);
2473-
let scheme = tcx.lookup_item_type(def_id);
2474-
scheme.generics.types.is_empty()
2473+
let generics = tcx.lookup_generics(def_id);
2474+
generics.parent_types == 0 && generics.types.is_empty()
24752475
}
24762476

24772477
_ => false

src/librustc_trans/collector.rs

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -195,7 +195,7 @@ use rustc::hir::map as hir_map;
195195
use rustc::hir::def_id::DefId;
196196
use rustc::middle::lang_items::{ExchangeFreeFnLangItem, ExchangeMallocFnLangItem};
197197
use rustc::traits;
198-
use rustc::ty::subst::{self, Substs, Subst};
198+
use rustc::ty::subst::{Substs, Subst};
199199
use rustc::ty::{self, TypeFoldable, TyCtxt};
200200
use rustc::ty::adjustment::CustomCoerceUnsized;
201201
use rustc::mir::repr as mir;
@@ -1219,17 +1219,16 @@ fn create_trans_items_for_default_impls<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
12191219
def_id_to_string(tcx, impl_def_id));
12201220

12211221
if let Some(trait_ref) = tcx.impl_trait_ref(impl_def_id) {
1222-
let default_impls = tcx.provided_trait_methods(trait_ref.def_id);
12231222
let callee_substs = tcx.erase_regions(&trait_ref.substs);
12241223
let overridden_methods: FnvHashSet<_> = items.iter()
12251224
.map(|item| item.name)
12261225
.collect();
1227-
for default_impl in default_impls {
1228-
if overridden_methods.contains(&default_impl.name) {
1226+
for method in tcx.provided_trait_methods(trait_ref.def_id) {
1227+
if overridden_methods.contains(&method.name) {
12291228
continue;
12301229
}
12311230

1232-
if default_impl.generics.has_type_params(subst::FnSpace) {
1231+
if !method.generics.types.is_empty() {
12331232
continue;
12341233
}
12351234

@@ -1242,7 +1241,7 @@ fn create_trans_items_for_default_impls<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
12421241
callee_substs,
12431242
impl_def_id,
12441243
impl_substs,
1245-
default_impl.name);
1244+
method.name);
12461245

12471246
assert!(mth.is_provided);
12481247

@@ -1251,10 +1250,10 @@ fn create_trans_items_for_default_impls<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
12511250
continue;
12521251
}
12531252

1254-
if can_have_local_instance(tcx, default_impl.def_id) {
1253+
if can_have_local_instance(tcx, method.def_id) {
12551254
let empty_substs = tcx.erase_regions(&mth.substs);
12561255
let item = create_fn_trans_item(tcx,
1257-
default_impl.def_id,
1256+
method.def_id,
12581257
callee_substs,
12591258
empty_substs);
12601259
output.push(item);

0 commit comments

Comments
 (0)