From e314636b866a8b1b8a98e45ccac9a2204e72b65a Mon Sep 17 00:00:00 2001 From: Eduard Burtescu Date: Mon, 13 Jun 2016 20:10:32 +0300 Subject: [PATCH 01/12] rustc: use Vec instead of VecPerParamSpace for ty::GenericPredicates. --- src/librustc/traits/object_safety.rs | 2 +- src/librustc/traits/project.rs | 2 +- src/librustc/traits/select.rs | 2 +- src/librustc/ty/mod.rs | 16 +++++----- src/librustc/ty/subst.rs | 20 ------------ src/librustc/util/ppaux.rs | 2 +- src/librustc_metadata/common.rs | 5 ++- src/librustc_metadata/decoder.rs | 18 +++-------- src/librustc_metadata/encoder.rs | 11 ++----- src/librustc_trans/collector.rs | 2 +- src/librustc_trans/meth.rs | 2 +- src/librustc_typeck/astconv.rs | 3 +- src/librustc_typeck/check/compare_method.rs | 31 +++++++++--------- src/librustc_typeck/check/dropck.rs | 10 ++---- src/librustc_typeck/check/method/probe.rs | 2 +- src/librustc_typeck/collect.rs | 32 ++++++++----------- src/librustdoc/clean/inline.rs | 33 ++++++++++++++++--- src/librustdoc/clean/mod.rs | 29 ++++++++--------- src/librustdoc/clean/simplify.rs | 35 +++++++-------------- 19 files changed, 109 insertions(+), 148 deletions(-) diff --git a/src/librustc/traits/object_safety.rs b/src/librustc/traits/object_safety.rs index 4889895860129..8ddb14e08e31e 100644 --- a/src/librustc/traits/object_safety.rs +++ b/src/librustc/traits/object_safety.rs @@ -184,7 +184,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { // Search for a predicate like `Self : Sized` amongst the trait bounds. let free_substs = self.construct_free_substs(generics, self.region_maps.node_extent(ast::DUMMY_NODE_ID)); - let predicates = predicates.instantiate(self, &free_substs).predicates.into_vec(); + let predicates = predicates.instantiate(self, &free_substs).predicates; elaborate_predicates(self, predicates) .any(|predicate| { match predicate { diff --git a/src/librustc/traits/project.rs b/src/librustc/traits/project.rs index aed4f43932411..d580deed0756a 100644 --- a/src/librustc/traits/project.rs +++ b/src/librustc/traits/project.rs @@ -811,7 +811,7 @@ fn assemble_candidates_from_trait_def<'cx, 'gcx, 'tcx>( // If so, extract what we know from the trait and try to come up with a good answer. let trait_predicates = selcx.tcx().lookup_predicates(def_id); let bounds = trait_predicates.instantiate(selcx.tcx(), substs); - let bounds = elaborate_predicates(selcx.tcx(), bounds.predicates.into_vec()); + let bounds = elaborate_predicates(selcx.tcx(), bounds.predicates); assemble_candidates_from_predicates(selcx, obligation, obligation_trait_ref, diff --git a/src/librustc/traits/select.rs b/src/librustc/traits/select.rs index b61cb0d3eee72..6b9de746f66c3 100644 --- a/src/librustc/traits/select.rs +++ b/src/librustc/traits/select.rs @@ -1214,7 +1214,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { bounds); let matching_bound = - util::elaborate_predicates(self.tcx(), bounds.predicates.into_vec()) + util::elaborate_predicates(self.tcx(), bounds.predicates) .filter_to_traits() .find( |bound| self.probe( diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs index cfc2e89f9d5a1..4f39a711010b7 100644 --- a/src/librustc/ty/mod.rs +++ b/src/librustc/ty/mod.rs @@ -178,7 +178,7 @@ impl<'a, 'gcx, 'tcx> ImplHeader<'tcx> { impl_def_id: impl_def_id, self_ty: tcx.lookup_item_type(impl_def_id).ty, trait_ref: tcx.impl_trait_ref(impl_def_id), - predicates: tcx.lookup_predicates(impl_def_id).predicates.into_vec(), + predicates: tcx.lookup_predicates(impl_def_id).predicates }.subst(tcx, &impl_substs); let traits::Normalized { value: mut header, obligations } = @@ -775,13 +775,13 @@ impl<'tcx> Generics<'tcx> { /// Bounds on generics. #[derive(Clone)] pub struct GenericPredicates<'tcx> { - pub predicates: VecPerParamSpace>, + pub predicates: Vec>, } impl<'a, 'gcx, 'tcx> GenericPredicates<'tcx> { pub fn empty() -> GenericPredicates<'tcx> { GenericPredicates { - predicates: VecPerParamSpace::empty(), + predicates: vec![] } } @@ -797,9 +797,9 @@ impl<'a, 'gcx, 'tcx> GenericPredicates<'tcx> { -> InstantiatedPredicates<'tcx> { InstantiatedPredicates { - predicates: self.predicates.map(|pred| { + predicates: self.predicates.iter().map(|pred| { pred.subst_supertrait(tcx, poly_trait_ref) - }) + }).collect() } } } @@ -1193,12 +1193,12 @@ impl<'tcx> Predicate<'tcx> { /// [usize:Bar]]`. #[derive(Clone)] pub struct InstantiatedPredicates<'tcx> { - pub predicates: VecPerParamSpace>, + pub predicates: Vec>, } impl<'tcx> InstantiatedPredicates<'tcx> { pub fn empty() -> InstantiatedPredicates<'tcx> { - InstantiatedPredicates { predicates: VecPerParamSpace::empty() } + InstantiatedPredicates { predicates: vec![] } } pub fn is_empty(&self) -> bool { @@ -2909,7 +2909,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { let tcx = self.global_tcx(); let bounds = generic_predicates.instantiate(tcx, &free_substs); let bounds = tcx.liberate_late_bound_regions(free_id_outlive, &ty::Binder(bounds)); - let predicates = bounds.predicates.into_vec(); + let predicates = bounds.predicates; // Finally, we have to normalize the bounds in the environment, in // case they contain any associated type projections. This process diff --git a/src/librustc/ty/subst.rs b/src/librustc/ty/subst.rs index 595d965ffce26..25b108cee2755 100644 --- a/src/librustc/ty/subst.rs +++ b/src/librustc/ty/subst.rs @@ -217,14 +217,6 @@ pub struct VecPerParamSpace { content: Vec, } -/// The `split` function converts one `VecPerParamSpace` into this -/// `SeparateVecsPerParamSpace` structure. -pub struct SeparateVecsPerParamSpace { - pub types: Vec, - pub selfs: Vec, - pub fns: Vec, -} - impl fmt::Debug for VecPerParamSpace { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "[{:?};{:?};{:?}]", @@ -428,18 +420,6 @@ impl VecPerParamSpace { self.self_limit) } - pub fn split(self) -> SeparateVecsPerParamSpace { - let VecPerParamSpace { type_limit, self_limit, content } = self; - - let mut content_iter = content.into_iter(); - - SeparateVecsPerParamSpace { - types: content_iter.by_ref().take(type_limit).collect(), - selfs: content_iter.by_ref().take(self_limit - type_limit).collect(), - fns: content_iter.collect() - } - } - pub fn with_slice(mut self, space: ParamSpace, slice: &[T]) -> VecPerParamSpace where T: Clone diff --git a/src/librustc/util/ppaux.rs b/src/librustc/util/ppaux.rs index 896ef49de6f05..37750b568bba2 100644 --- a/src/librustc/util/ppaux.rs +++ b/src/librustc/util/ppaux.rs @@ -917,7 +917,7 @@ impl<'tcx> fmt::Display for ty::TypeVariants<'tcx> { let mut first = true; let mut is_sized = false; write!(f, "impl")?; - for predicate in bounds.predicates.into_vec() { + for predicate in bounds.predicates { if let Some(trait_ref) = predicate.to_opt_poly_trait_ref() { // Don't print +Sized, but rather +?Sized if absent. if Some(trait_ref.def_id()) == tcx.lang_items.sized_trait() { diff --git a/src/librustc_metadata/common.rs b/src/librustc_metadata/common.rs index ff072cce5db96..0011b59c70ed3 100644 --- a/src/librustc_metadata/common.rs +++ b/src/librustc_metadata/common.rs @@ -207,9 +207,8 @@ pub const tag_type_param_def: usize = 0x94; pub const tag_item_generics: usize = 0x95; pub const tag_method_ty_generics: usize = 0x96; -pub const tag_type_predicate: usize = 0x97; -pub const tag_self_predicate: usize = 0x98; -pub const tag_fn_predicate: usize = 0x99; +pub const tag_predicate: usize = 0x97; +// GAP 0x98, 0x99 pub const tag_unsafety: usize = 0x9a; diff --git a/src/librustc_metadata/decoder.rs b/src/librustc_metadata/decoder.rs index 64b614b56e12f..b91fb993f08ee 100644 --- a/src/librustc_metadata/decoder.rs +++ b/src/librustc_metadata/decoder.rs @@ -1622,21 +1622,11 @@ fn doc_predicates<'a, 'tcx>(base_doc: rbml::Doc, { let doc = reader::get_doc(base_doc, tag); - let mut predicates = subst::VecPerParamSpace::empty(); - for predicate_doc in reader::tagged_docs(doc, tag_type_predicate) { - predicates.push(subst::TypeSpace, - doc_predicate(cdata, predicate_doc, tcx)); - } - for predicate_doc in reader::tagged_docs(doc, tag_self_predicate) { - predicates.push(subst::SelfSpace, - doc_predicate(cdata, predicate_doc, tcx)); - } - for predicate_doc in reader::tagged_docs(doc, tag_fn_predicate) { - predicates.push(subst::FnSpace, - doc_predicate(cdata, predicate_doc, tcx)); + ty::GenericPredicates { + predicates: reader::tagged_docs(doc, tag_predicate).map(|predicate_doc| { + doc_predicate(cdata, predicate_doc, tcx) + }).collect() } - - ty::GenericPredicates { predicates: predicates } } pub fn is_defaulted_trait(cdata: Cmd, trait_id: DefIndex) -> bool { diff --git a/src/librustc_metadata/encoder.rs b/src/librustc_metadata/encoder.rs index cc1d07b33c7e8..288fb74cc18a1 100644 --- a/src/librustc_metadata/encoder.rs +++ b/src/librustc_metadata/encoder.rs @@ -26,7 +26,6 @@ use rustc::hir::def; use rustc::hir::def_id::{CRATE_DEF_INDEX, DefId}; use middle::dependency_format::Linkage; use rustc::dep_graph::{DepGraph, DepNode, DepTask}; -use rustc::ty::subst; use rustc::traits::specialization_graph; use rustc::ty::{self, Ty, TyCtxt}; use rustc::ty::util::IntTypeExt; @@ -541,14 +540,8 @@ fn encode_predicates_in_current_doc<'a,'tcx>(rbml_w: &mut Encoder, index: &mut CrateIndex<'a, 'tcx>, predicates: &ty::GenericPredicates<'tcx>) { - for (space, _, predicate) in predicates.predicates.iter_enumerated() { - let tag = match space { - subst::TypeSpace => tag_type_predicate, - subst::SelfSpace => tag_self_predicate, - subst::FnSpace => tag_fn_predicate - }; - - rbml_w.wr_tagged_u32(tag, + for predicate in &predicates.predicates { + rbml_w.wr_tagged_u32(tag_predicate, index.add_xref(XRef::Predicate(predicate.clone()))); } } diff --git a/src/librustc_trans/collector.rs b/src/librustc_trans/collector.rs index acc302430aee6..ffacbae1afd6f 100644 --- a/src/librustc_trans/collector.rs +++ b/src/librustc_trans/collector.rs @@ -1257,7 +1257,7 @@ fn create_trans_items_for_default_impls<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, assert!(mth.is_provided); let predicates = mth.method.predicates.predicates.subst(tcx, &mth.substs); - if !normalize_and_test_predicates(tcx, predicates.into_vec()) { + if !normalize_and_test_predicates(tcx, predicates) { continue; } diff --git a/src/librustc_trans/meth.rs b/src/librustc_trans/meth.rs index 3d6093d4d6960..169242fbf7270 100644 --- a/src/librustc_trans/meth.rs +++ b/src/librustc_trans/meth.rs @@ -289,7 +289,7 @@ pub fn get_vtable_methods<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, // try and trans it, in that case. Issue #23435. if mth.is_provided { let predicates = mth.method.predicates.predicates.subst(tcx, &mth.substs); - if !normalize_and_test_predicates(tcx, predicates.into_vec()) { + if !normalize_and_test_predicates(tcx, predicates) { debug!("get_vtable_methods: predicates do not hold"); return None; } diff --git a/src/librustc_typeck/astconv.rs b/src/librustc_typeck/astconv.rs index ed67c9fbe30be..a0af98dec7298 100644 --- a/src/librustc_typeck/astconv.rs +++ b/src/librustc_typeck/astconv.rs @@ -56,7 +56,6 @@ use hir::print as pprust; use middle::resolve_lifetime as rl; use rustc::lint; use rustc::ty::subst::{FnSpace, TypeSpace, SelfSpace, Subst, Substs, ParamSpace}; -use rustc::ty::subst::VecPerParamSpace; use rustc::traits; use rustc::ty::{self, Ty, TyCtxt, ToPredicate, TypeFoldable}; use rustc::ty::wf::object_region_bounds; @@ -1778,7 +1777,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o { let predicates = bounds.predicates(tcx, ty); let predicates = tcx.lift_to_global(&predicates).unwrap(); tcx.predicates.borrow_mut().insert(def_id, ty::GenericPredicates { - predicates: VecPerParamSpace::new(vec![], vec![], predicates) + predicates: predicates }); ty diff --git a/src/librustc_typeck/check/compare_method.rs b/src/librustc_typeck/check/compare_method.rs index e6ddc6ad69379..d501a8a184cee 100644 --- a/src/librustc_typeck/check/compare_method.rs +++ b/src/librustc_typeck/check/compare_method.rs @@ -13,7 +13,7 @@ use rustc::infer::{self, InferOk, TypeOrigin}; use rustc::ty; use rustc::traits::{self, Reveal}; use rustc::ty::error::ExpectedFound; -use rustc::ty::subst::{self, Subst, Substs, VecPerParamSpace}; +use rustc::ty::subst::{self, Subst, Substs}; use rustc::hir::map::Node; use rustc::hir::{ImplItemKind, TraitItem_}; @@ -213,6 +213,15 @@ pub fn compare_impl_method<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, return; } + // Depend on trait/impl predicates always being before method's own predicates, + // to be able to split method predicates into "inherited" and method-specific. + let trait_predicates = tcx.lookup_predicates(trait_m.container_id()).predicates; + let impl_predicates = tcx.lookup_predicates(impl_m.container_id()).predicates; + let trait_method_start = trait_predicates.len(); + let impl_method_start = impl_predicates.len(); + assert_eq!(&trait_predicates[..], &trait_m.predicates.predicates[..trait_method_start]); + assert_eq!(&impl_predicates[..], &impl_m.predicates.predicates[..impl_method_start]); + tcx.infer_ctxt(None, None, Reveal::NotSpecializable).enter(|mut infcx| { let mut fulfillment_cx = traits::FulfillmentContext::new(); @@ -224,15 +233,10 @@ pub fn compare_impl_method<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, // environment. We can't just use `impl_env.caller_bounds`, // however, because we want to replace all late-bound regions with // region variables. - let impl_bounds = - impl_m.predicates.instantiate(tcx, impl_to_skol_substs); + let impl_bounds = impl_m.predicates.instantiate(tcx, impl_to_skol_substs); debug!("compare_impl_method: impl_bounds={:?}", impl_bounds); - // Obtain the predicate split predicate sets for each. - let trait_pred = trait_bounds.predicates.split(); - let impl_pred = impl_bounds.predicates.split(); - // This is the only tricky bit of the new way we check implementation methods // We need to build a set of predicates where only the FnSpace bounds // are from the trait and we assume all other bounds from the implementation @@ -240,24 +244,21 @@ pub fn compare_impl_method<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, // // We then register the obligations from the impl_m and check to see // if all constraints hold. - let hybrid_preds = VecPerParamSpace::new( - impl_pred.types, - impl_pred.selfs, - trait_pred.fns - ); + let hybrid_preds = impl_bounds.predicates[..impl_method_start].iter() + .chain(trait_bounds.predicates[trait_method_start..].iter()); // Construct trait parameter environment and then shift it into the skolemized viewpoint. // The key step here is to update the caller_bounds's predicates to be // the new hybrid bounds we computed. let normalize_cause = traits::ObligationCause::misc(impl_m_span, impl_m_body_id); - let trait_param_env = impl_param_env.with_caller_bounds(hybrid_preds.into_vec()); + let trait_param_env = impl_param_env.with_caller_bounds(hybrid_preds.cloned().collect()); let trait_param_env = traits::normalize_param_env_or_error(tcx, trait_param_env, normalize_cause.clone()); // FIXME(@jroesch) this seems ugly, but is a temporary change infcx.parameter_environment = trait_param_env; - debug!("compare_impl_method: trait_bounds={:?}", + debug!("compare_impl_method: caller_bounds={:?}", infcx.parameter_environment.caller_bounds); let mut selcx = traits::SelectionContext::new(&infcx); @@ -266,7 +267,7 @@ pub fn compare_impl_method<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, infcx.replace_late_bound_regions_with_fresh_var( impl_m_span, infer::HigherRankedType, - &ty::Binder(impl_pred.fns)); + &ty::Binder(impl_bounds.predicates[impl_method_start..].to_vec())); for predicate in impl_pred_fns { let traits::Normalized { value: predicate, .. } = traits::normalize(&mut selcx, normalize_cause.clone(), &predicate); diff --git a/src/librustc_typeck/check/dropck.rs b/src/librustc_typeck/check/dropck.rs index f3a01ef7409fa..1e2446788adc9 100644 --- a/src/librustc_typeck/check/dropck.rs +++ b/src/librustc_typeck/check/dropck.rs @@ -179,10 +179,7 @@ fn ensure_drop_predicates_are_implied_by_item_defn<'a, 'tcx>( let generic_assumptions = tcx.lookup_predicates(self_type_did); let assumptions_in_impl_context = generic_assumptions.instantiate(tcx, &self_to_impl_substs); - assert!(assumptions_in_impl_context.predicates.is_empty_in(subst::SelfSpace)); - assert!(assumptions_in_impl_context.predicates.is_empty_in(subst::FnSpace)); - let assumptions_in_impl_context = - assumptions_in_impl_context.predicates.get_slice(subst::TypeSpace); + let assumptions_in_impl_context = assumptions_in_impl_context.predicates; // An earlier version of this code attempted to do this checking // via the traits::fulfill machinery. However, it ran into trouble @@ -190,10 +187,7 @@ fn ensure_drop_predicates_are_implied_by_item_defn<'a, 'tcx>( // 'a:'b and T:'b into region inference constraints. It is simpler // just to look for all the predicates directly. - assert!(dtor_predicates.predicates.is_empty_in(subst::SelfSpace)); - assert!(dtor_predicates.predicates.is_empty_in(subst::FnSpace)); - let predicates = dtor_predicates.predicates.get_slice(subst::TypeSpace); - for predicate in predicates { + for predicate in &dtor_predicates.predicates { // (We do not need to worry about deep analysis of type // expressions etc because the Drop impls are already forced // to take on a structure that is roughly an alpha-renaming of diff --git a/src/librustc_typeck/check/method/probe.rs b/src/librustc_typeck/check/method/probe.rs index 99f1b13d4e4ab..e4701bb119559 100644 --- a/src/librustc_typeck/check/method/probe.rs +++ b/src/librustc_typeck/check/method/probe.rs @@ -799,7 +799,7 @@ impl<'a, 'gcx, 'tcx> ProbeContext<'a, 'gcx, 'tcx> { let trait_predicates = self.tcx.lookup_predicates(def_id); let bounds = trait_predicates.instantiate(self.tcx, substs); - let predicates = bounds.predicates.into_vec(); + let predicates = bounds.predicates; debug!("assemble_projection_candidates: predicates={:?}", predicates); for poly_bound in diff --git a/src/librustc_typeck/collect.rs b/src/librustc_typeck/collect.rs index d38065f4f1238..22da4ab9c43fa 100644 --- a/src/librustc_typeck/collect.rs +++ b/src/librustc_typeck/collect.rs @@ -65,7 +65,7 @@ use middle::lang_items::SizedTraitLangItem; use middle::const_val::ConstVal; use rustc_const_eval::EvalHint::UncheckedExprHint; use rustc_const_eval::{eval_const_expr_partial, report_const_eval_err}; -use rustc::ty::subst::{Substs, FnSpace, ParamSpace, SelfSpace, TypeSpace, VecPerParamSpace}; +use rustc::ty::subst::{Substs, FnSpace, ParamSpace, SelfSpace, TypeSpace}; use rustc::ty::{ToPredicate, ImplContainer, ImplOrTraitItemContainer, TraitContainer}; use rustc::ty::{self, ToPolyTraitRef, Ty, TyCtxt, TypeScheme}; use rustc::ty::{VariantKind}; @@ -1185,9 +1185,7 @@ fn ensure_super_predicates_step(ccx: &CrateCtxt, // generic types: let trait_def = trait_def_of_item(ccx, item); let self_predicate = ty::GenericPredicates { - predicates: VecPerParamSpace::new(vec![], - vec![trait_def.trait_ref.to_predicate()], - vec![]) + predicates: vec![trait_def.trait_ref.to_predicate()] }; let scope = &(generics, &self_predicate); @@ -1209,7 +1207,7 @@ fn ensure_super_predicates_step(ccx: &CrateCtxt, // Combine the two lists to form the complete set of superbounds: let superbounds = superbounds1.into_iter().chain(superbounds2).collect(); let superpredicates = ty::GenericPredicates { - predicates: VecPerParamSpace::new(superbounds, vec![], vec![]) + predicates: superbounds }; debug!("superpredicates for trait {:?} = {:?}", tcx.map.local_def_id(item.id), @@ -1368,7 +1366,7 @@ fn convert_trait_predicates<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, it: &hir::Item) // Add in a predicate that `Self:Trait` (where `Trait` is the // current trait). This is needed for builtin bounds. let self_predicate = trait_def.trait_ref.to_poly_trait_ref().to_predicate(); - base_predicates.predicates.push(SelfSpace, self_predicate); + base_predicates.predicates.push(self_predicate); // add in the explicit where-clauses let mut trait_predicates = @@ -1379,7 +1377,7 @@ fn convert_trait_predicates<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, it: &hir::Item) &trait_predicates, trait_def.trait_ref, items); - trait_predicates.predicates.extend(TypeSpace, assoc_predicates.into_iter()); + trait_predicates.predicates.extend(assoc_predicates); let prev_predicates = tcx.predicates.borrow_mut().insert(def_id, trait_predicates); assert!(prev_predicates.is_none()); @@ -1784,8 +1782,7 @@ fn ty_generic_predicates<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>, SizedByDefault::Yes, None, param.span); - let predicates = bounds.predicates(ccx.tcx, param_ty); - result.predicates.extend(space, predicates.into_iter()); + result.predicates.extend(bounds.predicates(ccx.tcx, param_ty)); } // Collect the region predicates that were declared inline as @@ -1803,7 +1800,7 @@ fn ty_generic_predicates<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>, for bound in ¶m.bounds { let bound_region = ast_region_to_region(ccx.tcx, bound); let outlives = ty::Binder(ty::OutlivesPredicate(region, bound_region)); - result.predicates.push(space, outlives.to_predicate()); + result.predicates.push(outlives.to_predicate()); } } @@ -1827,17 +1824,17 @@ fn ty_generic_predicates<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>, poly_trait_ref, &mut projections); - result.predicates.push(space, trait_ref.to_predicate()); + result.predicates.push(trait_ref.to_predicate()); for projection in &projections { - result.predicates.push(space, projection.to_predicate()); + result.predicates.push(projection.to_predicate()); } } &hir::TyParamBound::RegionTyParamBound(ref lifetime) => { let region = ast_region_to_region(tcx, lifetime); let pred = ty::Binder(ty::OutlivesPredicate(ty, region)); - result.predicates.push(space, ty::Predicate::TypeOutlives(pred)) + result.predicates.push(ty::Predicate::TypeOutlives(pred)) } } } @@ -1848,7 +1845,7 @@ fn ty_generic_predicates<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>, for bound in ®ion_pred.bounds { let r2 = ast_region_to_region(tcx, bound); let pred = ty::Binder(ty::OutlivesPredicate(r1, r2)); - result.predicates.push(space, ty::Predicate::RegionOutlives(pred)) + result.predicates.push(ty::Predicate::RegionOutlives(pred)) } } @@ -1861,7 +1858,7 @@ fn ty_generic_predicates<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>, } } - return result; + result } fn ty_generics<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>, @@ -2221,9 +2218,6 @@ fn enforce_impl_params_are_constrained<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, let impl_scheme = ccx.tcx.lookup_item_type(impl_def_id); let impl_trait_ref = ccx.tcx.impl_trait_ref(impl_def_id); - assert!(impl_predicates.predicates.is_empty_in(FnSpace)); - assert!(impl_predicates.predicates.is_empty_in(SelfSpace)); - // The trait reference is an input, so find all type parameters // reachable from there, to start (if this is an inherent impl, // then just examine the self type). @@ -2233,7 +2227,7 @@ fn enforce_impl_params_are_constrained<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, input_parameters.extend(ctp::parameters_for(trait_ref, false)); } - ctp::setup_constraining_predicates(impl_predicates.predicates.get_mut_slice(TypeSpace), + ctp::setup_constraining_predicates(&mut impl_predicates.predicates, impl_trait_ref, &mut input_parameters); diff --git a/src/librustdoc/clean/inline.rs b/src/librustdoc/clean/inline.rs index 3d6925041cf5b..cea12404298fc 100644 --- a/src/librustdoc/clean/inline.rs +++ b/src/librustdoc/clean/inline.rs @@ -395,8 +395,12 @@ pub fn build_impl<'a, 'tcx>(cx: &DocContext, }; // Not sure the choice of ParamSpace actually matters here, // because an associated type won't have generics on the LHS - let typedef = (type_scheme, ty::GenericPredicates::empty(), - subst::ParamSpace::TypeSpace).clean(cx); + let typedef = clean::Typedef { + type_: type_scheme.ty.clean(cx), + generics: (&type_scheme.generics, + &ty::GenericPredicates::empty(), + subst::TypeSpace).clean(cx) + }; Some(clean::Item { name: Some(assoc_ty.name.clean(cx)), inner: clean::TypedefItem(typedef, true), @@ -512,11 +516,32 @@ fn build_static<'a, 'tcx>(cx: &DocContext, tcx: TyCtxt<'a, 'tcx, 'tcx>, /// its associated types as well. We specifically move these clauses to the /// associated types instead when displaying, so when we're genering the /// generics for the trait itself we need to be sure to remove them. +/// We also need to remove the implied "recursive" Self: Trait bound. /// /// The inverse of this filtering logic can be found in the `Clean` /// implementation for `AssociatedType` fn filter_non_trait_generics(trait_did: DefId, mut g: clean::Generics) -> clean::Generics { + for pred in &mut g.where_predicates { + match *pred { + clean::WherePredicate::BoundPredicate { + ty: clean::Generic(ref s), + ref mut bounds + } if *s == "Self" => { + bounds.retain(|bound| { + match *bound { + clean::TyParamBound::TraitBound(clean::PolyTrait { + trait_: clean::ResolvedPath { did, .. }, + .. + }, _) => did != trait_did, + _ => true + } + }); + } + _ => {} + } + } + g.where_predicates.retain(|pred| { match *pred { clean::WherePredicate::BoundPredicate { @@ -524,8 +549,8 @@ fn filter_non_trait_generics(trait_did: DefId, mut g: clean::Generics) self_type: box clean::Generic(ref s), trait_: box clean::ResolvedPath { did, .. }, name: ref _name, - }, .. - } => *s != "Self" || did != trait_did, + }, ref bounds + } => !(*s == "Self" && did == trait_did) && !bounds.is_empty(), _ => true, } }); diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index 99d2732c4bb06..0da833d147ee5 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -1010,8 +1010,7 @@ impl<'a, 'tcx> Clean for (&'a ty::Generics<'tcx>, srp.clean(cx) }).collect::>(); - let mut where_predicates = preds.predicates.get_slice(space) - .to_vec().clean(cx); + let mut where_predicates = preds.predicates.to_vec().clean(cx); // Type parameters and have a Sized bound by default unless removed with // ?Sized. Scan through the predicates and mark any type parameter with @@ -1363,7 +1362,17 @@ impl Clean for hir::ImplItem { impl<'tcx> Clean for ty::Method<'tcx> { fn clean(&self, cx: &DocContext) -> Item { - let generics = (&self.generics, &self.predicates, + // Depend on trait/impl predicates always being before method's own predicates, + // to be able to split method predicates into "inherited" and method-specific. + let outer_predicates = cx.tcx().lookup_predicates(self.container_id()).predicates; + let method_start = outer_predicates.len(); + assert_eq!(&outer_predicates[..], &self.predicates.predicates[..method_start]); + + let method_predicates = ty::GenericPredicates { + predicates: self.predicates.predicates[method_start..].to_vec() + }; + + let generics = (&self.generics, &method_predicates, subst::FnSpace).clean(cx); let mut decl = (self.def_id, &self.fty.sig).clean(cx); match self.explicit_self { @@ -1863,8 +1872,7 @@ impl<'tcx> Clean for ty::Ty<'tcx> { let item_predicates = cx.tcx().lookup_predicates(def_id); let substs = cx.tcx().lift(&substs).unwrap(); let bounds = item_predicates.instantiate(cx.tcx(), substs); - let predicates = bounds.predicates.into_vec(); - ImplTrait(predicates.into_iter().filter_map(|predicate| { + ImplTrait(bounds.predicates.into_iter().filter_map(|predicate| { predicate.to_opt_poly_trait_ref().clean(cx) }).collect()) } @@ -2967,17 +2975,6 @@ impl<'tcx> Clean for ty::AssociatedType<'tcx> { } } -impl<'a> Clean for (ty::TypeScheme<'a>, ty::GenericPredicates<'a>, - ParamSpace) { - fn clean(&self, cx: &DocContext) -> Typedef { - let (ref ty_scheme, ref predicates, ps) = *self; - Typedef { - type_: ty_scheme.ty.clean(cx), - generics: (&ty_scheme.generics, predicates, ps).clean(cx) - } - } -} - fn lang_struct(cx: &DocContext, did: Option, t: ty::Ty, name: &str, fallback: fn(Box) -> Type) -> Type { diff --git a/src/librustdoc/clean/simplify.rs b/src/librustdoc/clean/simplify.rs index c0faa04323e47..7ae177439064f 100644 --- a/src/librustdoc/clean/simplify.rs +++ b/src/librustdoc/clean/simplify.rs @@ -30,11 +30,11 @@ use std::mem; use std::collections::BTreeMap; use rustc::hir::def_id::DefId; -use rustc::ty::subst; +use rustc::ty; use clean::PathParameters as PP; use clean::WherePredicate as WP; -use clean::{self, Clean}; +use clean; use core::DocContext; pub fn where_clauses(cx: &DocContext, clauses: Vec) -> Vec { @@ -153,27 +153,16 @@ fn trait_is_same_or_supertrait(cx: &DocContext, child: DefId, if child == trait_ { return true } - let def = cx.tcx().lookup_trait_def(child); - let predicates = cx.tcx().lookup_predicates(child); - let generics = (&def.generics, &predicates, subst::TypeSpace).clean(cx); - generics.where_predicates.iter().filter_map(|pred| { - match *pred { - clean::WherePredicate::BoundPredicate { - ty: clean::Generic(ref s), - ref bounds - } if *s == "Self" => Some(bounds), - _ => None, - } - }).flat_map(|bounds| bounds).any(|bound| { - let poly_trait = match *bound { - clean::TraitBound(ref t, _) => t, - _ => return false, - }; - match poly_trait.trait_ { - clean::ResolvedPath { did, .. } => { - trait_is_same_or_supertrait(cx, did, trait_) + let predicates = cx.tcx().lookup_super_predicates(child).predicates; + predicates.iter().filter_map(|pred| { + if let ty::Predicate::Trait(ref pred) = *pred { + if pred.0.trait_ref.self_ty().is_self() { + Some(pred.def_id()) + } else { + None } - _ => false, + } else { + None } - }) + }).any(|did| trait_is_same_or_supertrait(cx, did, trait_)) } From b354ae95a29a7f78059a1a9fc867dd2e8639671a Mon Sep 17 00:00:00 2001 From: Eduard Burtescu Date: Mon, 13 Jun 2016 20:13:37 +0300 Subject: [PATCH 02/12] rustc: move the SelfSpace before TypeSpace in Substs. --- src/librustc/traits/error_reporting.rs | 2 +- src/librustc/traits/select.rs | 5 +- src/librustc/ty/subst.rs | 75 +++++++++---------- src/librustc_trans/base.rs | 4 +- src/librustc_typeck/check/mod.rs | 2 +- .../trait-method-default-impl.rs | 10 +-- .../compile-fail/variance-associated-types.rs | 4 +- .../compile-fail/variance-object-types.rs | 2 +- .../compile-fail/variance-region-bounds.rs | 2 +- .../compile-fail/variance-regions-direct.rs | 14 ++-- .../compile-fail/variance-regions-indirect.rs | 10 +-- .../compile-fail/variance-trait-bounds.rs | 10 +-- .../variance-trait-object-bound.rs | 2 +- .../compile-fail/variance-types-bounds.rs | 10 +-- src/test/compile-fail/variance-types.rs | 12 +-- 15 files changed, 82 insertions(+), 82 deletions(-) diff --git a/src/librustc/traits/error_reporting.rs b/src/librustc/traits/error_reporting.rs index cf004767b2aac..4c8489ff07159 100644 --- a/src/librustc/traits/error_reporting.rs +++ b/src/librustc/traits/error_reporting.rs @@ -182,7 +182,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { let rps = self.region_vars_for_defs(obligation.cause.span, rps); let mut substs = subst::Substs::new( subst::VecPerParamSpace::empty(), - subst::VecPerParamSpace::new(rps, Vec::new(), Vec::new())); + subst::VecPerParamSpace::new(Vec::new(), rps, Vec::new())); self.type_vars_for_defs(obligation.cause.span, TypeSpace, &mut substs, diff --git a/src/librustc/traits/select.rs b/src/librustc/traits/select.rs index 6b9de746f66c3..9c7dd7ccd7011 100644 --- a/src/librustc/traits/select.rs +++ b/src/librustc/traits/select.rs @@ -1602,7 +1602,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { return; } }; - let target = obligation.predicate.0.input_types()[0]; + let target = obligation.predicate.skip_binder().input_types()[1]; debug!("assemble_candidates_for_unsizing(source={:?}, target={:?})", source, target); @@ -2476,7 +2476,8 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { // regions here. See the comment there for more details. let source = self.infcx.shallow_resolve( tcx.no_late_bound_regions(&obligation.self_ty()).unwrap()); - let target = self.infcx.shallow_resolve(obligation.predicate.0.input_types()[0]); + let target = obligation.predicate.skip_binder().input_types()[1]; + let target = self.infcx.shallow_resolve(target); debug!("confirm_builtin_unsize_candidate(source={:?}, target={:?})", source, target); diff --git a/src/librustc/ty/subst.rs b/src/librustc/ty/subst.rs index 25b108cee2755..0fe8d09664008 100644 --- a/src/librustc/ty/subst.rs +++ b/src/librustc/ty/subst.rs @@ -48,8 +48,8 @@ impl<'a, 'gcx, 'tcx> Substs<'tcx> { r: Vec) -> Substs<'tcx> { - Substs::new(VecPerParamSpace::new(t, Vec::new(), Vec::new()), - VecPerParamSpace::new(r, Vec::new(), Vec::new())) + Substs::new(VecPerParamSpace::new(vec![], t, vec![]), + VecPerParamSpace::new(vec![], r, vec![])) } pub fn new_trait(t: Vec>, @@ -57,8 +57,8 @@ impl<'a, 'gcx, 'tcx> Substs<'tcx> { s: Ty<'tcx>) -> Substs<'tcx> { - Substs::new(VecPerParamSpace::new(t, vec!(s), Vec::new()), - VecPerParamSpace::new(r, Vec::new(), Vec::new())) + Substs::new(VecPerParamSpace::new(vec![s], t, vec![]), + VecPerParamSpace::new(vec![], r, vec![])) } pub fn empty() -> Substs<'tcx> { @@ -169,28 +169,28 @@ impl<'tcx> Decodable for &'tcx Substs<'tcx> { #[derive(PartialOrd, Ord, PartialEq, Eq, Copy, Clone, Hash, RustcEncodable, RustcDecodable, Debug)] pub enum ParamSpace { - TypeSpace, // Type parameters attached to a type definition, trait, or impl SelfSpace, // Self parameter on a trait + TypeSpace, // Type parameters attached to a type definition, trait, or impl FnSpace, // Type parameters attached to a method or fn } impl ParamSpace { pub fn all() -> [ParamSpace; 3] { - [TypeSpace, SelfSpace, FnSpace] + [SelfSpace, TypeSpace, FnSpace] } pub fn to_uint(self) -> usize { match self { - TypeSpace => 0, - SelfSpace => 1, + SelfSpace => 0, + TypeSpace => 1, FnSpace => 2, } } pub fn from_uint(u: usize) -> ParamSpace { match u { - 0 => TypeSpace, - 1 => SelfSpace, + 0 => SelfSpace, + 1 => TypeSpace, 2 => FnSpace, _ => bug!("Invalid ParamSpace: {}", u) } @@ -209,19 +209,19 @@ pub struct VecPerParamSpace { // Here is how the representation corresponds to the abstraction // i.e. the "abstraction function" AF: // - // AF(self) = (self.content[..self.type_limit], - // self.content[self.type_limit..self.self_limit], - // self.content[self.self_limit..]) - type_limit: usize, + // AF(self) = (self.content[..self.self_limit], + // self.content[self.self_limit..self.type_limit], + // self.content[self.type_limit..]) self_limit: usize, + type_limit: usize, content: Vec, } impl fmt::Debug for VecPerParamSpace { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "[{:?};{:?};{:?}]", - self.get_slice(TypeSpace), self.get_slice(SelfSpace), + self.get_slice(TypeSpace), self.get_slice(FnSpace)) } } @@ -229,44 +229,44 @@ impl fmt::Debug for VecPerParamSpace { impl VecPerParamSpace { fn limits(&self, space: ParamSpace) -> (usize, usize) { match space { - TypeSpace => (0, self.type_limit), - SelfSpace => (self.type_limit, self.self_limit), - FnSpace => (self.self_limit, self.content.len()), + SelfSpace => (0, self.self_limit), + TypeSpace => (self.self_limit, self.type_limit), + FnSpace => (self.type_limit, self.content.len()), } } pub fn empty() -> VecPerParamSpace { VecPerParamSpace { - type_limit: 0, self_limit: 0, + type_limit: 0, content: Vec::new() } } - /// `t` is the type space. /// `s` is the self space. + /// `t` is the type space. /// `f` is the fn space. - pub fn new(t: Vec, s: Vec, f: Vec) -> VecPerParamSpace { - let type_limit = t.len(); - let self_limit = type_limit + s.len(); + pub fn new(s: Vec, t: Vec, f: Vec) -> VecPerParamSpace { + let self_limit = s.len(); + let type_limit = self_limit + t.len(); - let mut content = t; - content.extend(s); + let mut content = s; + content.extend(t); content.extend(f); VecPerParamSpace { - type_limit: type_limit, self_limit: self_limit, + type_limit: type_limit, content: content, } } - fn new_internal(content: Vec, type_limit: usize, self_limit: usize) + fn new_internal(content: Vec, self_limit: usize, type_limit: usize) -> VecPerParamSpace { VecPerParamSpace { - type_limit: type_limit, self_limit: self_limit, + type_limit: type_limit, content: content, } } @@ -278,8 +278,8 @@ impl VecPerParamSpace { pub fn push(&mut self, space: ParamSpace, value: T) { let (_, limit) = self.limits(space); match space { - TypeSpace => { self.type_limit += 1; self.self_limit += 1; } - SelfSpace => { self.self_limit += 1; } + SelfSpace => { self.type_limit += 1; self.self_limit += 1; } + TypeSpace => { self.type_limit += 1; } FnSpace => { } } self.content.insert(limit, value); @@ -302,8 +302,8 @@ impl VecPerParamSpace { None } else { match space { - TypeSpace => { self.type_limit -= 1; self.self_limit -= 1; } - SelfSpace => { self.self_limit -= 1; } + SelfSpace => { self.type_limit -= 1; self.self_limit -= 1; } + TypeSpace => { self.type_limit -= 1; } FnSpace => {} } if self.content.is_empty() { @@ -388,8 +388,7 @@ impl VecPerParamSpace { pub fn all_vecs

(&self, mut pred: P) -> bool where P: FnMut(&[T]) -> bool, { - let spaces = [TypeSpace, SelfSpace, FnSpace]; - spaces.iter().all(|&space| { pred(self.get_slice(space)) }) + ParamSpace::all().iter().all(|&space| { pred(self.get_slice(space)) }) } pub fn all

(&self, pred: P) -> bool where P: FnMut(&T) -> bool { @@ -407,8 +406,8 @@ impl VecPerParamSpace { pub fn map(&self, pred: P) -> VecPerParamSpace where P: FnMut(&T) -> U { let result = self.iter().map(pred).collect(); VecPerParamSpace::new_internal(result, - self.type_limit, - self.self_limit) + self.self_limit, + self.type_limit) } pub fn map_enumerated(&self, pred: P) -> VecPerParamSpace where @@ -416,8 +415,8 @@ impl VecPerParamSpace { { let result = self.iter_enumerated().map(pred).collect(); VecPerParamSpace::new_internal(result, - self.type_limit, - self.self_limit) + self.self_limit, + self.type_limit) } pub fn with_slice(mut self, space: ParamSpace, slice: &[T]) diff --git a/src/librustc_trans/base.rs b/src/librustc_trans/base.rs index c78cda75e820e..3ea7f0d5eabb9 100644 --- a/src/librustc_trans/base.rs +++ b/src/librustc_trans/base.rs @@ -675,8 +675,8 @@ pub fn custom_coerce_unsize_info<'scx, 'tcx>(scx: &SharedCrateContext<'scx, 'tcx source_ty: Ty<'tcx>, target_ty: Ty<'tcx>) -> CustomCoerceUnsized { - let trait_substs = Substs::new(subst::VecPerParamSpace::new(vec![target_ty], - vec![source_ty], + let trait_substs = Substs::new(subst::VecPerParamSpace::new(vec![source_ty], + vec![target_ty], Vec::new()), subst::VecPerParamSpace::empty()); diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index d985d3ccbea89..76b9052af6820 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -2797,7 +2797,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { let rps = self.region_vars_for_defs(span, rps); let mut substs = subst::Substs::new( VecPerParamSpace::empty(), - VecPerParamSpace::new(rps, Vec::new(), Vec::new())); + VecPerParamSpace::new(Vec::new(), rps, Vec::new())); self.type_vars_for_defs(span, ParamSpace::TypeSpace, &mut substs, tps); let substd_ty = self.instantiate_type_scheme(span, &substs, &raw_ty); diff --git a/src/test/codegen-units/item-collection/trait-method-default-impl.rs b/src/test/codegen-units/item-collection/trait-method-default-impl.rs index 2b3b83cb7ec63..47892781902ea 100644 --- a/src/test/codegen-units/item-collection/trait-method-default-impl.rs +++ b/src/test/codegen-units/item-collection/trait-method-default-impl.rs @@ -37,7 +37,7 @@ impl SomeGenericTrait for i32 { // For the non-generic foo(), we should generate a codegen-item even if it // is not called anywhere - //~ TRANS_ITEM fn trait_method_default_impl::SomeGenericTrait[0]::foo[0] + //~ TRANS_ITEM fn trait_method_default_impl::SomeGenericTrait[0]::foo[0] } // Non-generic impl of generic trait @@ -54,16 +54,16 @@ fn main() { //~ TRANS_ITEM fn trait_method_default_impl::SomeTrait[0]::bar[0] let _ = 2i8.bar("&str"); - //~ TRANS_ITEM fn trait_method_default_impl::SomeGenericTrait[0]::bar[0] + //~ TRANS_ITEM fn trait_method_default_impl::SomeGenericTrait[0]::bar[0] 0i32.bar(0u64, 'c'); - //~ TRANS_ITEM fn trait_method_default_impl::SomeGenericTrait[0]::bar[0] + //~ TRANS_ITEM fn trait_method_default_impl::SomeGenericTrait[0]::bar[0] 0i32.bar(0u64, "&str"); - //~ TRANS_ITEM fn trait_method_default_impl::SomeGenericTrait[0]::bar[0] + //~ TRANS_ITEM fn trait_method_default_impl::SomeGenericTrait[0]::bar[0] 0u32.bar(0i8, &['c']); - //~ TRANS_ITEM fn trait_method_default_impl::SomeGenericTrait[0]::bar[0] + //~ TRANS_ITEM fn trait_method_default_impl::SomeGenericTrait[0]::bar[0] 0u32.bar(0i16, ()); } diff --git a/src/test/compile-fail/variance-associated-types.rs b/src/test/compile-fail/variance-associated-types.rs index 0ed0861d34af1..a3456b0628b35 100644 --- a/src/test/compile-fail/variance-associated-types.rs +++ b/src/test/compile-fail/variance-associated-types.rs @@ -20,12 +20,12 @@ trait Trait<'a> { } #[rustc_variance] -struct Foo<'a, T : Trait<'a>> { //~ ERROR ItemVariances(types=[[+];[];[]], regions=[[-];[];[]]) +struct Foo<'a, T : Trait<'a>> { //~ ERROR ItemVariances(types=[[];[+];[]], regions=[[];[-];[]]) field: (T, &'a ()) } #[rustc_variance] -struct Bar<'a, T : Trait<'a>> { //~ ERROR ItemVariances(types=[[o];[];[]], regions=[[o];[];[]]) +struct Bar<'a, T : Trait<'a>> { //~ ERROR ItemVariances(types=[[];[o];[]], regions=[[];[o];[]]) field: >::Type } diff --git a/src/test/compile-fail/variance-object-types.rs b/src/test/compile-fail/variance-object-types.rs index 2b7b05970d90f..ffd829c38d3d3 100644 --- a/src/test/compile-fail/variance-object-types.rs +++ b/src/test/compile-fail/variance-object-types.rs @@ -18,7 +18,7 @@ use std::cell::Cell; // For better or worse, associated types are invariant, and hence we // get an invariant result for `'a`. #[rustc_variance] -struct Foo<'a> { //~ ERROR regions=[[o];[];[]] +struct Foo<'a> { //~ ERROR regions=[[];[o];[]] x: Box &'a i32 + 'static> } diff --git a/src/test/compile-fail/variance-region-bounds.rs b/src/test/compile-fail/variance-region-bounds.rs index dfa5dc1444151..6dd791f2558a7 100644 --- a/src/test/compile-fail/variance-region-bounds.rs +++ b/src/test/compile-fail/variance-region-bounds.rs @@ -13,7 +13,7 @@ #![feature(rustc_attrs)] #[rustc_variance] -trait Foo: 'static { //~ ERROR types=[[];[o];[]] +trait Foo: 'static { //~ ERROR types=[[o];[];[]] } #[rustc_variance] diff --git a/src/test/compile-fail/variance-regions-direct.rs b/src/test/compile-fail/variance-regions-direct.rs index bb452eecbfc8b..0c712d3fa0377 100644 --- a/src/test/compile-fail/variance-regions-direct.rs +++ b/src/test/compile-fail/variance-regions-direct.rs @@ -16,7 +16,7 @@ // Regions that just appear in normal spots are contravariant: #[rustc_variance] -struct Test2<'a, 'b, 'c> { //~ ERROR regions=[[-, -, -];[];[]] +struct Test2<'a, 'b, 'c> { //~ ERROR regions=[[];[-, -, -];[]] x: &'a isize, y: &'b [isize], c: &'c str @@ -25,7 +25,7 @@ struct Test2<'a, 'b, 'c> { //~ ERROR regions=[[-, -, -];[];[]] // Those same annotations in function arguments become covariant: #[rustc_variance] -struct Test3<'a, 'b, 'c> { //~ ERROR regions=[[+, +, +];[];[]] +struct Test3<'a, 'b, 'c> { //~ ERROR regions=[[];[+, +, +];[]] x: extern "Rust" fn(&'a isize), y: extern "Rust" fn(&'b [isize]), c: extern "Rust" fn(&'c str), @@ -34,7 +34,7 @@ struct Test3<'a, 'b, 'c> { //~ ERROR regions=[[+, +, +];[];[]] // Mutability induces invariance: #[rustc_variance] -struct Test4<'a, 'b:'a> { //~ ERROR regions=[[-, o];[];[]] +struct Test4<'a, 'b:'a> { //~ ERROR regions=[[];[-, o];[]] x: &'a mut &'b isize, } @@ -42,7 +42,7 @@ struct Test4<'a, 'b:'a> { //~ ERROR regions=[[-, o];[];[]] // contravariant context: #[rustc_variance] -struct Test5<'a, 'b:'a> { //~ ERROR regions=[[+, o];[];[]] +struct Test5<'a, 'b:'a> { //~ ERROR regions=[[];[+, o];[]] x: extern "Rust" fn(&'a mut &'b isize), } @@ -52,14 +52,14 @@ struct Test5<'a, 'b:'a> { //~ ERROR regions=[[+, o];[];[]] // argument list occurs in an invariant context. #[rustc_variance] -struct Test6<'a, 'b:'a> { //~ ERROR regions=[[-, o];[];[]] +struct Test6<'a, 'b:'a> { //~ ERROR regions=[[];[-, o];[]] x: &'a mut extern "Rust" fn(&'b isize), } // No uses at all is bivariant: #[rustc_variance] -struct Test7<'a> { //~ ERROR regions=[[*];[];[]] +struct Test7<'a> { //~ ERROR regions=[[];[*];[]] //~^ ERROR parameter `'a` is never used x: isize } @@ -67,7 +67,7 @@ struct Test7<'a> { //~ ERROR regions=[[*];[];[]] // Try enums too. #[rustc_variance] -enum Test8<'a, 'b, 'c:'b> { //~ ERROR regions=[[+, -, o];[];[]] +enum Test8<'a, 'b, 'c:'b> { //~ ERROR regions=[[];[+, -, o];[]] Test8A(extern "Rust" fn(&'a isize)), Test8B(&'b [isize]), Test8C(&'b mut &'c str), diff --git a/src/test/compile-fail/variance-regions-indirect.rs b/src/test/compile-fail/variance-regions-indirect.rs index 9beb90d0b2483..9bdb05e188dcf 100644 --- a/src/test/compile-fail/variance-regions-indirect.rs +++ b/src/test/compile-fail/variance-regions-indirect.rs @@ -15,7 +15,7 @@ #![feature(rustc_attrs)] #[rustc_variance] -enum Base<'a, 'b, 'c:'b, 'd> { //~ ERROR regions=[[+, -, o, *];[];[]] +enum Base<'a, 'b, 'c:'b, 'd> { //~ ERROR regions=[[];[+, -, o, *];[]] //~^ ERROR parameter `'d` is never used Test8A(extern "Rust" fn(&'a isize)), Test8B(&'b [isize]), @@ -23,25 +23,25 @@ enum Base<'a, 'b, 'c:'b, 'd> { //~ ERROR regions=[[+, -, o, *];[];[]] } #[rustc_variance] -struct Derived1<'w, 'x:'y, 'y, 'z> { //~ ERROR regions=[[*, o, -, +];[];[]] +struct Derived1<'w, 'x:'y, 'y, 'z> { //~ ERROR regions=[[];[*, o, -, +];[]] //~^ ERROR parameter `'w` is never used f: Base<'z, 'y, 'x, 'w> } #[rustc_variance] // Combine - and + to yield o -struct Derived2<'a, 'b:'a, 'c> { //~ ERROR regions=[[o, o, *];[];[]] +struct Derived2<'a, 'b:'a, 'c> { //~ ERROR regions=[[];[o, o, *];[]] //~^ ERROR parameter `'c` is never used f: Base<'a, 'a, 'b, 'c> } #[rustc_variance] // Combine + and o to yield o (just pay attention to 'a here) -struct Derived3<'a:'b, 'b, 'c> { //~ ERROR regions=[[o, -, *];[];[]] +struct Derived3<'a:'b, 'b, 'c> { //~ ERROR regions=[[];[o, -, *];[]] //~^ ERROR parameter `'c` is never used f: Base<'a, 'b, 'a, 'c> } #[rustc_variance] // Combine + and * to yield + (just pay attention to 'a here) -struct Derived4<'a, 'b, 'c:'b> { //~ ERROR regions=[[+, -, o];[];[]] +struct Derived4<'a, 'b, 'c:'b> { //~ ERROR regions=[[];[+, -, o];[]] f: Base<'a, 'b, 'c, 'a> } diff --git a/src/test/compile-fail/variance-trait-bounds.rs b/src/test/compile-fail/variance-trait-bounds.rs index b6f197987bab1..528be50c0b850 100644 --- a/src/test/compile-fail/variance-trait-bounds.rs +++ b/src/test/compile-fail/variance-trait-bounds.rs @@ -25,18 +25,18 @@ trait Setter { //~ ERROR types=[[o];[o];[]] } #[rustc_variance] -struct TestStruct> { //~ ERROR types=[[+, +];[];[]] +struct TestStruct> { //~ ERROR types=[[];[+, +];[]] t: T, u: U } #[rustc_variance] -enum TestEnum> {//~ ERROR types=[[*, +];[];[]] +enum TestEnum> {//~ ERROR types=[[];[*, +];[]] //~^ ERROR parameter `U` is never used Foo(T) } #[rustc_variance] -trait TestTrait> { //~ ERROR types=[[o, o];[o];[]] +trait TestTrait> { //~ ERROR types=[[o];[o, o];[]] fn getter(&self, u: U) -> T; } @@ -50,13 +50,13 @@ trait TestTrait3 { //~ ERROR types=[[o];[o];[]] } #[rustc_variance] -struct TestContraStruct> { //~ ERROR types=[[*, +];[];[]] +struct TestContraStruct> { //~ ERROR types=[[];[*, +];[]] //~^ ERROR parameter `U` is never used t: T } #[rustc_variance] -struct TestBox+Setter> { //~ ERROR types=[[*, +];[];[]] +struct TestBox+Setter> { //~ ERROR types=[[];[*, +];[]] //~^ ERROR parameter `U` is never used t: T } diff --git a/src/test/compile-fail/variance-trait-object-bound.rs b/src/test/compile-fail/variance-trait-object-bound.rs index f0ca1edd56387..b58540204986a 100644 --- a/src/test/compile-fail/variance-trait-object-bound.rs +++ b/src/test/compile-fail/variance-trait-object-bound.rs @@ -21,7 +21,7 @@ use std::mem; trait T { fn foo(&self); } #[rustc_variance] -struct TOption<'a> { //~ ERROR regions=[[-];[];[]] +struct TOption<'a> { //~ ERROR regions=[[];[-];[]] v: Option>, } diff --git a/src/test/compile-fail/variance-types-bounds.rs b/src/test/compile-fail/variance-types-bounds.rs index a02f20656e7b5..d110c402d3b77 100644 --- a/src/test/compile-fail/variance-types-bounds.rs +++ b/src/test/compile-fail/variance-types-bounds.rs @@ -14,24 +14,24 @@ #![feature(rustc_attrs)] #[rustc_variance] -struct TestImm { //~ ERROR types=[[+, +];[];[]] +struct TestImm { //~ ERROR types=[[];[+, +];[]] x: A, y: B, } #[rustc_variance] -struct TestMut { //~ ERROR types=[[+, o];[];[]] +struct TestMut { //~ ERROR types=[[];[+, o];[]] x: A, y: &'static mut B, } #[rustc_variance] -struct TestIndirect { //~ ERROR types=[[+, o];[];[]] +struct TestIndirect { //~ ERROR types=[[];[+, o];[]] m: TestMut } #[rustc_variance] -struct TestIndirect2 { //~ ERROR types=[[o, o];[];[]] +struct TestIndirect2 { //~ ERROR types=[[];[o, o];[]] n: TestMut, m: TestMut } @@ -68,7 +68,7 @@ trait SetterInTypeBound { //~ ERROR types=[[o];[o];[]] } #[rustc_variance] -struct TestObject { //~ ERROR types=[[o, o];[];[]] +struct TestObject { //~ ERROR types=[[];[o, o];[]] n: Box+Send>, m: Box+Send>, } diff --git a/src/test/compile-fail/variance-types.rs b/src/test/compile-fail/variance-types.rs index 2fd8bf20c7997..8c1a544334c2a 100644 --- a/src/test/compile-fail/variance-types.rs +++ b/src/test/compile-fail/variance-types.rs @@ -17,32 +17,32 @@ use std::cell::Cell; // not considered bivariant. #[rustc_variance] -struct InvariantMut<'a,A:'a,B:'a> { //~ ERROR types=[[o, o];[];[]], regions=[[-];[];[]] +struct InvariantMut<'a,A:'a,B:'a> { //~ ERROR types=[[];[o, o];[]], regions=[[];[-];[]] t: &'a mut (A,B) } #[rustc_variance] -struct InvariantCell { //~ ERROR types=[[o];[];[]] +struct InvariantCell { //~ ERROR types=[[];[o];[]] t: Cell } #[rustc_variance] -struct InvariantIndirect { //~ ERROR types=[[o];[];[]] +struct InvariantIndirect { //~ ERROR types=[[];[o];[]] t: InvariantCell } #[rustc_variance] -struct Covariant { //~ ERROR types=[[+];[];[]] +struct Covariant { //~ ERROR types=[[];[+];[]] t: A, u: fn() -> A } #[rustc_variance] -struct Contravariant { //~ ERROR types=[[-];[];[]] +struct Contravariant { //~ ERROR types=[[];[-];[]] t: fn(A) } #[rustc_variance] -enum Enum { //~ ERROR types=[[+, -, o];[];[]] +enum Enum { //~ ERROR types=[[];[+, -, o];[]] Foo(Covariant), Bar(Contravariant), Zed(Covariant,Contravariant) From 77dc61b5c68aacce4ab5d115b14825699ea6302b Mon Sep 17 00:00:00 2001 From: Eduard Burtescu Date: Mon, 13 Jun 2016 20:46:08 +0300 Subject: [PATCH 03/12] rustc: force all raw accesses to VecPerParamSpace through as_full_slice. --- src/librustc/traits/fulfill.rs | 2 +- src/librustc/ty/flags.rs | 4 +- src/librustc/ty/mod.rs | 13 ++++--- src/librustc/ty/structural_impls.rs | 2 +- src/librustc/ty/sty.rs | 8 ++-- src/librustc/ty/subst.rs | 43 +++------------------ src/librustc/ty/walk.rs | 10 ++--- src/librustc/ty/wf.rs | 2 +- src/librustc_metadata/encoder.rs | 4 +- src/librustc_trans/back/symbol_names.rs | 2 +- src/librustc_trans/debuginfo/mod.rs | 4 +- src/librustc_trans/debuginfo/type_names.rs | 2 +- src/librustc_trans/monomorphize.rs | 2 +- src/librustc_trans/trans_item.rs | 2 +- src/librustc_typeck/check/mod.rs | 5 ++- src/librustc_typeck/check/regionck.rs | 15 +++---- src/librustc_typeck/check/wfcheck.rs | 2 +- src/librustc_typeck/collect.rs | 2 +- src/librustc_typeck/variance/constraints.rs | 8 ++-- src/librustdoc/clean/mod.rs | 5 ++- 20 files changed, 52 insertions(+), 85 deletions(-) diff --git a/src/librustc/traits/fulfill.rs b/src/librustc/traits/fulfill.rs index 5ba7b914d6591..1ee1dc50b717d 100644 --- a/src/librustc/traits/fulfill.rs +++ b/src/librustc/traits/fulfill.rs @@ -142,7 +142,7 @@ impl<'a, 'gcx, 'tcx> DeferredObligation<'tcx> { // Auto trait obligations on `impl Trait`. if tcx.trait_has_default_impl(predicate.def_id()) { let substs = predicate.skip_binder().trait_ref.substs; - if substs.types.as_slice().len() == 1 && substs.regions.is_empty() { + if substs.types.as_full_slice().len() == 1 && substs.regions.is_empty() { if let ty::TyAnon(..) = predicate.skip_binder().self_ty().sty { return true; } diff --git a/src/librustc/ty/flags.rs b/src/librustc/ty/flags.rs index 0997d6c1a7562..3a5f3d421eaf7 100644 --- a/src/librustc/ty/flags.rs +++ b/src/librustc/ty/flags.rs @@ -209,8 +209,8 @@ impl FlagComputation { } fn add_substs(&mut self, substs: &subst::Substs) { - self.add_tys(substs.types.as_slice()); - for &r in &substs.regions { + self.add_tys(substs.types.as_full_slice()); + for &r in substs.regions.as_full_slice() { self.add_region(r); } } diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs index 4f39a711010b7..708dcb30f1b84 100644 --- a/src/librustc/ty/mod.rs +++ b/src/librustc/ty/mod.rs @@ -971,7 +971,7 @@ impl<'tcx> TraitPredicate<'tcx> { } pub fn input_types(&self) -> &[Ty<'tcx>] { - self.trait_ref.substs.types.as_slice() + self.trait_ref.substs.types.as_full_slice() } pub fn self_ty(&self) -> Ty<'tcx> { @@ -1113,7 +1113,7 @@ impl<'tcx> Predicate<'tcx> { pub fn walk_tys(&self) -> IntoIter> { let vec: Vec<_> = match *self { ty::Predicate::Trait(ref data) => { - data.0.trait_ref.substs.types.as_slice().to_vec() + data.0.trait_ref.substs.types.as_full_slice().to_vec() } ty::Predicate::Rfc1592(ref data) => { return data.walk_tys() @@ -1128,7 +1128,8 @@ impl<'tcx> Predicate<'tcx> { vec![] } ty::Predicate::Projection(ref data) => { - let trait_inputs = data.0.projection_ty.trait_ref.substs.types.as_slice(); + let trait_inputs = data.0.projection_ty.trait_ref.substs + .types.as_full_slice(); trait_inputs.iter() .cloned() .chain(Some(data.0.ty)) @@ -1220,7 +1221,7 @@ impl<'tcx> TraitRef<'tcx> { // now this is all the types that appear in the // trait-reference, but it should eventually exclude // associated types. - self.substs.types.as_slice() + self.substs.types.as_full_slice() } } @@ -2864,7 +2865,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { free_id_outlive: CodeExtent) -> Substs<'gcx> { // map T => T let mut types = VecPerParamSpace::empty(); - for def in generics.types.as_slice() { + for def in generics.types.as_full_slice() { debug!("construct_parameter_environment(): push_types_from_defs: def={:?}", def); types.push(def.space, self.global_tcx().mk_param_from_def(def)); @@ -2872,7 +2873,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { // map bound 'a => free 'a let mut regions = VecPerParamSpace::empty(); - for def in generics.regions.as_slice() { + for def in generics.regions.as_full_slice() { let region = ReFree(FreeRegion { scope: free_id_outlive, bound_region: def.to_bound_region() }); diff --git a/src/librustc/ty/structural_impls.rs b/src/librustc/ty/structural_impls.rs index 83413d16ffb3f..b0f8e2e13f7e0 100644 --- a/src/librustc/ty/structural_impls.rs +++ b/src/librustc/ty/structural_impls.rs @@ -433,7 +433,7 @@ impl<'tcx, T: TypeFoldable<'tcx>> TypeFoldable<'tcx> for VecPerParamSpace { } fn super_visit_with>(&self, visitor: &mut V) -> bool { - self.iter().any(|elem| elem.visit_with(visitor)) + self.as_full_slice().iter().any(|elem| elem.visit_with(visitor)) } } diff --git a/src/librustc/ty/sty.rs b/src/librustc/ty/sty.rs index 9680632ec4dcc..098943dfce29a 100644 --- a/src/librustc/ty/sty.rs +++ b/src/librustc/ty/sty.rs @@ -1211,19 +1211,19 @@ impl<'a, 'gcx, 'tcx> TyS<'tcx> { TyTrait(ref obj) => { let mut v = vec![obj.bounds.region_bound]; v.extend_from_slice(obj.principal.skip_binder() - .substs.regions.as_slice()); + .substs.regions.as_full_slice()); v } TyEnum(_, substs) | TyStruct(_, substs) | TyAnon(_, substs) => { - substs.regions.as_slice().to_vec() + substs.regions.as_full_slice().to_vec() } TyClosure(_, ref substs) => { - substs.func_substs.regions.as_slice().to_vec() + substs.func_substs.regions.as_full_slice().to_vec() } TyProjection(ref data) => { - data.trait_ref.substs.regions.as_slice().to_vec() + data.trait_ref.substs.regions.as_full_slice().to_vec() } TyFnDef(..) | TyFnPtr(_) | diff --git a/src/librustc/ty/subst.rs b/src/librustc/ty/subst.rs index 0fe8d09664008..10e7f3ad0d17f 100644 --- a/src/librustc/ty/subst.rs +++ b/src/librustc/ty/subst.rs @@ -19,9 +19,6 @@ use ty::fold::{TypeFoldable, TypeFolder}; use serialize::{Encodable, Encoder, Decodable, Decoder}; use std::fmt; -use std::iter::IntoIterator; -use std::slice::Iter; -use std::vec::{Vec, IntoIter}; use syntax_pos::{Span, DUMMY_SP}; /////////////////////////////////////////////////////////////////////////// @@ -365,26 +362,14 @@ impl VecPerParamSpace { &self.get_slice(space)[index] } - pub fn iter<'a>(&'a self) -> Iter<'a,T> { - self.content.iter() - } - - pub fn into_iter(self) -> IntoIter { - self.content.into_iter() - } - pub fn iter_enumerated<'a>(&'a self) -> EnumeratedItems<'a,T> { EnumeratedItems::new(self) } - pub fn as_slice(&self) -> &[T] { + pub fn as_full_slice(&self) -> &[T] { &self.content } - pub fn into_vec(self) -> Vec { - self.content - } - pub fn all_vecs

(&self, mut pred: P) -> bool where P: FnMut(&[T]) -> bool, { @@ -392,11 +377,11 @@ impl VecPerParamSpace { } pub fn all

(&self, pred: P) -> bool where P: FnMut(&T) -> bool { - self.iter().all(pred) + self.as_full_slice().iter().all(pred) } pub fn any

(&self, pred: P) -> bool where P: FnMut(&T) -> bool { - self.iter().any(pred) + self.as_full_slice().iter().any(pred) } pub fn is_empty(&self) -> bool { @@ -404,7 +389,7 @@ impl VecPerParamSpace { } pub fn map(&self, pred: P) -> VecPerParamSpace where P: FnMut(&T) -> U { - let result = self.iter().map(pred).collect(); + let result = self.as_full_slice().iter().map(pred).collect(); VecPerParamSpace::new_internal(result, self.self_limit, self.type_limit) @@ -478,29 +463,11 @@ impl<'a,T> Iterator for EnumeratedItems<'a,T> { } fn size_hint(&self) -> (usize, Option) { - let size = self.vec.as_slice().len(); + let size = self.vec.as_full_slice().len(); (size, Some(size)) } } -impl IntoIterator for VecPerParamSpace { - type Item = T; - type IntoIter = IntoIter; - - fn into_iter(self) -> IntoIter { - self.into_vec().into_iter() - } -} - -impl<'a,T> IntoIterator for &'a VecPerParamSpace { - type Item = &'a T; - type IntoIter = Iter<'a, T>; - - fn into_iter(self) -> Iter<'a, T> { - self.as_slice().into_iter() - } -} - /////////////////////////////////////////////////////////////////////////// // Public trait `Subst` diff --git a/src/librustc/ty/walk.rs b/src/librustc/ty/walk.rs index 9c1f9d9537a4f..3f87d80e337dd 100644 --- a/src/librustc/ty/walk.rs +++ b/src/librustc/ty/walk.rs @@ -79,10 +79,10 @@ fn push_subtypes<'tcx>(stack: &mut Vec>, parent_ty: Ty<'tcx>) { stack.push(mt.ty); } ty::TyProjection(ref data) => { - push_reversed(stack, data.trait_ref.substs.types.as_slice()); + push_reversed(stack, data.trait_ref.substs.types.as_full_slice()); } ty::TyTrait(box ty::TraitTy { ref principal, ref bounds }) => { - push_reversed(stack, principal.substs().types.as_slice()); + push_reversed(stack, principal.substs().types.as_full_slice()); push_reversed(stack, &bounds.projection_bounds.iter().map(|pred| { pred.0.ty }).collect::>()); @@ -90,17 +90,17 @@ fn push_subtypes<'tcx>(stack: &mut Vec>, parent_ty: Ty<'tcx>) { ty::TyEnum(_, ref substs) | ty::TyStruct(_, ref substs) | ty::TyAnon(_, ref substs) => { - push_reversed(stack, substs.types.as_slice()); + push_reversed(stack, substs.types.as_full_slice()); } ty::TyClosure(_, ref substs) => { - push_reversed(stack, substs.func_substs.types.as_slice()); + push_reversed(stack, substs.func_substs.types.as_full_slice()); push_reversed(stack, &substs.upvar_tys); } ty::TyTuple(ref ts) => { push_reversed(stack, ts); } ty::TyFnDef(_, substs, ref ft) => { - push_reversed(stack, substs.types.as_slice()); + push_reversed(stack, substs.types.as_full_slice()); push_sig_subtypes(stack, &ft.sig); } ty::TyFnPtr(ref ft) => { diff --git a/src/librustc/ty/wf.rs b/src/librustc/ty/wf.rs index bfc2e11d9fbce..009e3e2433431 100644 --- a/src/librustc/ty/wf.rs +++ b/src/librustc/ty/wf.rs @@ -261,7 +261,7 @@ impl<'a, 'gcx, 'tcx> WfPredicates<'a, 'gcx, 'tcx> { let cause = self.cause(traits::MiscObligation); self.out.extend( trait_ref.substs.types - .as_slice() + .as_full_slice() .iter() .filter(|ty| !ty.has_escaping_regions()) .map(|ty| traits::Obligation::new(cause.clone(), diff --git a/src/librustc_metadata/encoder.rs b/src/librustc_metadata/encoder.rs index 288fb74cc18a1..d19eb6391820a 100644 --- a/src/librustc_metadata/encoder.rs +++ b/src/librustc_metadata/encoder.rs @@ -515,7 +515,7 @@ fn encode_generics<'a, 'tcx>(rbml_w: &mut Encoder, { rbml_w.start_tag(tag); - for param in &generics.types { + for param in generics.types.as_full_slice() { rbml_w.start_tag(tag_type_param_def); tyencode::enc_type_param_def(rbml_w.writer, &ecx.ty_str_ctxt(), param); rbml_w.mark_stable_position(); @@ -523,7 +523,7 @@ fn encode_generics<'a, 'tcx>(rbml_w: &mut Encoder, } // Region parameters - for param in &generics.regions { + for param in generics.regions.as_full_slice() { rbml_w.start_tag(tag_region_param_def); tyencode::enc_region_param_def(rbml_w.writer, &ecx.ty_str_ctxt(), param); rbml_w.mark_stable_position(); diff --git a/src/librustc_trans/back/symbol_names.rs b/src/librustc_trans/back/symbol_names.rs index 5e2c0805c2ea3..bb27a308f71f7 100644 --- a/src/librustc_trans/back/symbol_names.rs +++ b/src/librustc_trans/back/symbol_names.rs @@ -252,7 +252,7 @@ impl<'a, 'tcx> Instance<'tcx> { // and should not matter anyhow. let instance_ty = scx.tcx().erase_regions(&instance_ty.ty); - let hash = get_symbol_hash(scx, &def_path, instance_ty, substs.types.as_slice()); + let hash = get_symbol_hash(scx, &def_path, instance_ty, substs.types.as_full_slice()); let mut buffer = SymbolPathBuffer { names: Vec::with_capacity(def_path.data.len()) diff --git a/src/librustc_trans/debuginfo/mod.rs b/src/librustc_trans/debuginfo/mod.rs index d6a4ce3c43a4e..1aae3b3127faa 100644 --- a/src/librustc_trans/debuginfo/mod.rs +++ b/src/librustc_trans/debuginfo/mod.rs @@ -358,7 +358,7 @@ pub fn create_function_debug_context<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, name_to_append_suffix_to: &mut String) -> DIArray { - let actual_types = param_substs.types.as_slice(); + let actual_types = param_substs.types.as_full_slice(); if actual_types.is_empty() { return create_DIArray(DIB(cx), &[]); @@ -381,7 +381,7 @@ pub fn create_function_debug_context<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, // Again, only create type information if full debuginfo is enabled let template_params: Vec<_> = if cx.sess().opts.debuginfo == FullDebugInfo { - generics.types.as_slice().iter().enumerate().map(|(i, param)| { + generics.types.as_full_slice().iter().enumerate().map(|(i, param)| { let actual_type = cx.tcx().normalize_associated_type(&actual_types[i]); let actual_type_metadata = type_metadata(cx, actual_type, syntax_pos::DUMMY_SP); let name = CString::new(param.name.as_str().as_bytes()).unwrap(); diff --git a/src/librustc_trans/debuginfo/type_names.rs b/src/librustc_trans/debuginfo/type_names.rs index 73b1c828663e1..4bca091ef95ac 100644 --- a/src/librustc_trans/debuginfo/type_names.rs +++ b/src/librustc_trans/debuginfo/type_names.rs @@ -181,7 +181,7 @@ pub fn push_debuginfo_type_name<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, output.push('<'); - for &type_parameter in &substs.types { + for &type_parameter in substs.types.as_full_slice() { push_debuginfo_type_name(cx, type_parameter, true, output); output.push_str(", "); } diff --git a/src/librustc_trans/monomorphize.rs b/src/librustc_trans/monomorphize.rs index e9aacaa0f954f..663c5167d1492 100644 --- a/src/librustc_trans/monomorphize.rs +++ b/src/librustc_trans/monomorphize.rs @@ -181,7 +181,7 @@ impl<'tcx> fmt::Display for Instance<'tcx> { impl<'tcx> Instance<'tcx> { pub fn new(def_id: DefId, substs: &'tcx Substs<'tcx>) -> Instance<'tcx> { - assert!(substs.regions.iter().all(|&r| r == ty::ReErased)); + assert!(substs.regions.as_full_slice().iter().all(|&r| r == ty::ReErased)); Instance { def: def_id, substs: substs } } pub fn mono<'a>(scx: &SharedCrateContext<'a, 'tcx>, def_id: DefId) -> Instance<'tcx> { diff --git a/src/librustc_trans/trans_item.rs b/src/librustc_trans/trans_item.rs index 90058f0b8329a..c1149279b4ddd 100644 --- a/src/librustc_trans/trans_item.rs +++ b/src/librustc_trans/trans_item.rs @@ -570,7 +570,7 @@ fn push_type_params<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, output.push('<'); - for &type_parameter in types { + for &type_parameter in types.as_full_slice() { push_unique_type_name(tcx, type_parameter, output); output.push_str(", "); } diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index 76b9052af6820..b82ce2f5bc4e0 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -888,7 +888,8 @@ fn check_on_unimplemented<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, // `{Self}` is allowed Position::ArgumentNamed(s) if s == "Self" => (), // So is `{A}` if A is a type parameter - Position::ArgumentNamed(s) => match types.iter().find(|t| { + Position::ArgumentNamed(s) => match types.as_full_slice() + .iter().find(|t| { t.name.as_str() == s }) { Some(_) => (), @@ -1895,7 +1896,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { /// Registers obligations that all types appearing in `substs` are well-formed. pub fn add_wf_bounds(&self, substs: &Substs<'tcx>, expr: &hir::Expr) { - for &ty in &substs.types { + for &ty in substs.types.as_full_slice() { self.register_wf_obligation(ty, expr.span, traits::MiscObligation); } } diff --git a/src/librustc_typeck/check/regionck.rs b/src/librustc_typeck/check/regionck.rs index 22ffcfbaae111..6f3d48282e25c 100644 --- a/src/librustc_typeck/check/regionck.rs +++ b/src/librustc_typeck/check/regionck.rs @@ -1445,11 +1445,11 @@ impl<'a, 'gcx, 'tcx> RegionCtxt<'a, 'gcx, 'tcx> { let origin = infer::ParameterInScope(origin, expr_span); - for ®ion in &substs.regions { + for ®ion in substs.regions.as_full_slice() { self.sub_regions(origin.clone(), expr_region, region); } - for &ty in &substs.types { + for &ty in substs.types.as_full_slice() { let ty = self.resolve_type(ty); self.type_must_outlive(origin.clone(), ty, expr_region); } @@ -1571,18 +1571,15 @@ impl<'a, 'gcx, 'tcx> RegionCtxt<'a, 'gcx, 'tcx> { // the problem is to add `T: 'r`, which isn't true. So, if there are no // inference variables, we use a verify constraint instead of adding // edges, which winds up enforcing the same condition. - let needs_infer = { - projection_ty.trait_ref.substs.types.iter().any(|t| t.needs_infer()) || - projection_ty.trait_ref.substs.regions.iter().any(|r| r.needs_infer()) - }; + let needs_infer = projection_ty.trait_ref.needs_infer(); if env_bounds.is_empty() && needs_infer { debug!("projection_must_outlive: no declared bounds"); - for &component_ty in &projection_ty.trait_ref.substs.types { + for &component_ty in projection_ty.trait_ref.substs.types.as_full_slice() { self.type_must_outlive(origin.clone(), component_ty, region); } - for &r in &projection_ty.trait_ref.substs.regions { + for &r in projection_ty.trait_ref.substs.regions.as_full_slice() { self.sub_regions(origin.clone(), region, r); } @@ -1600,7 +1597,7 @@ impl<'a, 'gcx, 'tcx> RegionCtxt<'a, 'gcx, 'tcx> { if !env_bounds.is_empty() && env_bounds[1..].iter().all(|b| *b == env_bounds[0]) { let unique_bound = env_bounds[0]; debug!("projection_must_outlive: unique declared bound = {:?}", unique_bound); - if projection_ty.trait_ref.substs.regions + if projection_ty.trait_ref.substs.regions.as_full_slice() .iter() .any(|r| env_bounds.contains(r)) { diff --git a/src/librustc_typeck/check/wfcheck.rs b/src/librustc_typeck/check/wfcheck.rs index 4bb9f4fd332f2..678c102a4de3b 100644 --- a/src/librustc_typeck/check/wfcheck.rs +++ b/src/librustc_typeck/check/wfcheck.rs @@ -621,7 +621,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { // Trait impl: take implied bounds from all types that // appear in the trait reference. let trait_ref = self.instantiate_type_scheme(span, free_substs, trait_ref); - trait_ref.substs.types.as_slice().to_vec() + trait_ref.substs.types.as_full_slice().to_vec() } None => { diff --git a/src/librustc_typeck/collect.rs b/src/librustc_typeck/collect.rs index 22da4ab9c43fa..69545aefb4446 100644 --- a/src/librustc_typeck/collect.rs +++ b/src/librustc_typeck/collect.rs @@ -1550,7 +1550,7 @@ fn convert_typed_item<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, // Debugging aid. if tcx.has_attr(ccx.tcx.map.local_def_id(it.id), "rustc_object_lifetime_default") { let object_lifetime_default_reprs: String = - scheme.generics.types.iter() + scheme.generics.types.as_full_slice().iter() .map(|t| match t.object_lifetime_default { ty::ObjectLifetimeDefault::Specific(r) => r.to_string(), d => format!("{:?}", d), diff --git a/src/librustc_typeck/variance/constraints.rs b/src/librustc_typeck/variance/constraints.rs index a4faee8f633ed..1e342d4b81971 100644 --- a/src/librustc_typeck/variance/constraints.rs +++ b/src/librustc_typeck/variance/constraints.rs @@ -302,8 +302,8 @@ impl<'a, 'tcx> ConstraintContext<'a, 'tcx> { self.add_constraints_from_substs( generics, trait_ref.def_id, - trait_def.generics.types.as_slice(), - trait_def.generics.regions.as_slice(), + trait_def.generics.types.as_full_slice(), + trait_def.generics.regions.as_full_slice(), trait_ref.substs, variance); } @@ -388,8 +388,8 @@ impl<'a, 'tcx> ConstraintContext<'a, 'tcx> { self.add_constraints_from_substs( generics, trait_ref.def_id, - trait_def.generics.types.as_slice(), - trait_def.generics.regions.as_slice(), + trait_def.generics.types.as_full_slice(), + trait_def.generics.regions.as_full_slice(), trait_ref.substs, variance); } diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index 0da833d147ee5..284e0d4dbddf3 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -788,8 +788,9 @@ impl<'tcx> Clean for ty::TraitRef<'tcx> { impl<'tcx> Clean>> for subst::Substs<'tcx> { fn clean(&self, cx: &DocContext) -> Option> { let mut v = Vec::new(); - v.extend(self.regions.iter().filter_map(|r| r.clean(cx)).map(RegionBound)); - v.extend(self.types.iter().map(|t| TraitBound(PolyTrait { + v.extend(self.regions.as_full_slice().iter().filter_map(|r| r.clean(cx)) + .map(RegionBound)); + v.extend(self.types.as_full_slice().iter().map(|t| TraitBound(PolyTrait { trait_: t.clean(cx), lifetimes: vec![] }, hir::TraitBoundModifier::None))); From c87063f07e8f74c1950f3fd099fb578a833682c5 Mon Sep 17 00:00:00 2001 From: Eduard Burtescu Date: Wed, 15 Jun 2016 01:40:09 +0300 Subject: [PATCH 04/12] rustc: avoid using subst::VecPerParamSpace::{empty,new} directly. --- src/librustc/traits/error_reporting.rs | 4 +--- src/librustc/ty/mod.rs | 23 +++++++++++++++-------- src/librustc/ty/subst.rs | 8 ++++++++ src/librustc_metadata/decoder.rs | 10 ++++------ src/librustc_mir/build/scope.rs | 7 ++----- src/librustc_trans/base.rs | 7 ++----- src/librustc_typeck/check/mod.rs | 4 +--- src/librustc_typeck/variance/solve.rs | 12 +++--------- src/librustc_typeck/variance/terms.rs | 7 ++----- 9 files changed, 38 insertions(+), 44 deletions(-) diff --git a/src/librustc/traits/error_reporting.rs b/src/librustc/traits/error_reporting.rs index 4c8489ff07159..b5133738ada8c 100644 --- a/src/librustc/traits/error_reporting.rs +++ b/src/librustc/traits/error_reporting.rs @@ -180,9 +180,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { ity.ty); let rps = self.region_vars_for_defs(obligation.cause.span, rps); - let mut substs = subst::Substs::new( - subst::VecPerParamSpace::empty(), - subst::VecPerParamSpace::new(Vec::new(), rps, Vec::new())); + let mut substs = subst::Substs::new_type(vec![], rps); self.type_vars_for_defs(obligation.cause.span, TypeSpace, &mut substs, diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs index 708dcb30f1b84..44532fcb4e64f 100644 --- a/src/librustc/ty/mod.rs +++ b/src/librustc/ty/mod.rs @@ -429,6 +429,15 @@ pub struct ItemVariances { pub regions: VecPerParamSpace, } +impl ItemVariances { + pub fn empty() -> ItemVariances { + ItemVariances { + types: VecPerParamSpace::empty(), + regions: VecPerParamSpace::empty(), + } + } +} + #[derive(Clone, PartialEq, RustcDecodable, RustcEncodable, Copy)] pub enum Variance { Covariant, // T <: T iff A <: B -- e.g., function return type @@ -2864,22 +2873,20 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { pub fn construct_free_substs(self, generics: &Generics<'gcx>, free_id_outlive: CodeExtent) -> Substs<'gcx> { // map T => T - let mut types = VecPerParamSpace::empty(); - for def in generics.types.as_full_slice() { + let types = generics.types.map(|def| { debug!("construct_parameter_environment(): push_types_from_defs: def={:?}", def); - types.push(def.space, self.global_tcx().mk_param_from_def(def)); - } + self.global_tcx().mk_param_from_def(def) + }); // map bound 'a => free 'a - let mut regions = VecPerParamSpace::empty(); - for def in generics.regions.as_full_slice() { + let regions = generics.regions.map(|def| { let region = ReFree(FreeRegion { scope: free_id_outlive, bound_region: def.to_bound_region() }); debug!("push_region_params {:?}", region); - regions.push(def.space, region); - } + region + }); Substs { types: types, diff --git a/src/librustc/ty/subst.rs b/src/librustc/ty/subst.rs index 10e7f3ad0d17f..63399ee138893 100644 --- a/src/librustc/ty/subst.rs +++ b/src/librustc/ty/subst.rs @@ -41,6 +41,14 @@ impl<'a, 'gcx, 'tcx> Substs<'tcx> { Substs { types: t, regions: r } } + pub fn new_fn(t: Vec>, + r: Vec) + -> Substs<'tcx> + { + Substs::new(VecPerParamSpace::new(vec![], vec![], t), + VecPerParamSpace::new(vec![], vec![], r)) + } + pub fn new_type(t: Vec>, r: Vec) -> Substs<'tcx> diff --git a/src/librustc_metadata/decoder.rs b/src/librustc_metadata/decoder.rs index b91fb993f08ee..eeb1859c01311 100644 --- a/src/librustc_metadata/decoder.rs +++ b/src/librustc_metadata/decoder.rs @@ -35,7 +35,6 @@ use middle::cstore::{DefLike, DlDef, DlField, DlImpl, tls}; use rustc::hir::def::Def; use rustc::hir::def_id::{DefId, DefIndex}; use middle::lang_items; -use rustc::ty::subst; use rustc::ty::{ImplContainer, TraitContainer}; use rustc::ty::{self, Ty, TyCtxt, TypeFoldable, VariantKind}; @@ -1580,25 +1579,24 @@ fn doc_generics<'a, 'tcx>(base_doc: rbml::Doc, { let doc = reader::get_doc(base_doc, tag); - let mut types = subst::VecPerParamSpace::empty(); + let mut generics = ty::Generics::empty(); for p in reader::tagged_docs(doc, tag_type_param_def) { let bd = TyDecoder::with_doc(tcx, cdata.cnum, p, &mut |did| translate_def_id(cdata, did)) .parse_type_param_def(); - types.push(bd.space, bd); + generics.types.push(bd.space, bd); } - let mut regions = subst::VecPerParamSpace::empty(); for p in reader::tagged_docs(doc, tag_region_param_def) { let bd = TyDecoder::with_doc(tcx, cdata.cnum, p, &mut |did| translate_def_id(cdata, did)) .parse_region_param_def(); - regions.push(bd.space, bd); + generics.regions.push(bd.space, bd); } - ty::Generics { types: types, regions: regions } + generics } fn doc_predicate<'a, 'tcx>(cdata: Cmd, diff --git a/src/librustc_mir/build/scope.rs b/src/librustc_mir/build/scope.rs index cae9e8379897c..6af9ad02b91ba 100644 --- a/src/librustc_mir/build/scope.rs +++ b/src/librustc_mir/build/scope.rs @@ -89,7 +89,7 @@ should go to. use build::{BlockAnd, BlockAndExtension, Builder, CFG, ScopeAuxiliary, ScopeId}; use rustc::middle::region::{CodeExtent, CodeExtentData}; use rustc::middle::lang_items; -use rustc::ty::subst::{Substs, Subst, VecPerParamSpace}; +use rustc::ty::subst::{Substs, Subst}; use rustc::ty::{Ty, TyCtxt}; use rustc::mir::repr::*; use syntax_pos::Span; @@ -750,10 +750,7 @@ fn build_free<'a, 'gcx, 'tcx>(tcx: TyCtxt<'a, 'gcx, 'tcx>, -> TerminatorKind<'tcx> { let free_func = tcx.lang_items.require(lang_items::BoxFreeFnLangItem) .unwrap_or_else(|e| tcx.sess.fatal(&e)); - let substs = tcx.mk_substs(Substs::new( - VecPerParamSpace::new(vec![], vec![], vec![data.item_ty]), - VecPerParamSpace::new(vec![], vec![], vec![]) - )); + let substs = tcx.mk_substs(Substs::new_fn(vec![data.item_ty], vec![])); TerminatorKind::Call { func: Operand::Constant(Constant { span: data.span, diff --git a/src/librustc_trans/base.rs b/src/librustc_trans/base.rs index 3ea7f0d5eabb9..0dcac188bb024 100644 --- a/src/librustc_trans/base.rs +++ b/src/librustc_trans/base.rs @@ -39,7 +39,7 @@ use rustc::cfg; use rustc::hir::def_id::DefId; use middle::lang_items::{LangItem, ExchangeMallocFnLangItem, StartFnLangItem}; use rustc::hir::pat_util::simple_name; -use rustc::ty::subst::{self, Substs}; +use rustc::ty::subst::Substs; use rustc::traits; use rustc::ty::{self, Ty, TyCtxt, TypeFoldable}; use rustc::ty::adjustment::CustomCoerceUnsized; @@ -675,10 +675,7 @@ pub fn custom_coerce_unsize_info<'scx, 'tcx>(scx: &SharedCrateContext<'scx, 'tcx source_ty: Ty<'tcx>, target_ty: Ty<'tcx>) -> CustomCoerceUnsized { - let trait_substs = Substs::new(subst::VecPerParamSpace::new(vec![source_ty], - vec![target_ty], - Vec::new()), - subst::VecPerParamSpace::empty()); + let trait_substs = Substs::new_trait(vec![target_ty], vec![], source_ty); let trait_ref = ty::Binder(ty::TraitRef { def_id: scx.tcx().lang_items.coerce_unsized_trait().unwrap(), diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index b82ce2f5bc4e0..fae64f3741974 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -2796,9 +2796,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { debug!("impl_self_ty: tps={:?} rps={:?} raw_ty={:?}", tps, rps, raw_ty); let rps = self.region_vars_for_defs(span, rps); - let mut substs = subst::Substs::new( - VecPerParamSpace::empty(), - VecPerParamSpace::new(Vec::new(), rps, Vec::new())); + let mut substs = subst::Substs::new_type(vec![], rps); self.type_vars_for_defs(span, ParamSpace::TypeSpace, &mut substs, tps); let substd_ty = self.instantiate_type_scheme(span, &substs, &raw_ty); diff --git a/src/librustc_typeck/variance/solve.rs b/src/librustc_typeck/variance/solve.rs index 0763cfd7e2e60..8bb49410a5bdc 100644 --- a/src/librustc_typeck/variance/solve.rs +++ b/src/librustc_typeck/variance/solve.rs @@ -15,7 +15,6 @@ //! optimal solution to the constraints. The final variance for each //! inferred is then written into the `variance_map` in the tcx. -use rustc::ty::subst::VecPerParamSpace; use rustc::ty; use std::rc::Rc; @@ -109,8 +108,7 @@ impl<'a, 'tcx> SolveContext<'a, 'tcx> { let num_inferred = self.terms_cx.num_inferred(); while index < num_inferred { let item_id = inferred_infos[index].item_id; - let mut types = VecPerParamSpace::empty(); - let mut regions = VecPerParamSpace::empty(); + let mut item_variances = ty::ItemVariances::empty(); while index < num_inferred && inferred_infos[index].item_id == item_id { let info = &inferred_infos[index]; @@ -118,17 +116,13 @@ impl<'a, 'tcx> SolveContext<'a, 'tcx> { debug!("Index {} Info {} / {:?} / {:?} Variance {:?}", index, info.index, info.kind, info.space, variance); match info.kind { - TypeParam => { types.push(info.space, variance); } - RegionParam => { regions.push(info.space, variance); } + TypeParam => { item_variances.types.push(info.space, variance); } + RegionParam => { item_variances.regions.push(info.space, variance); } } index += 1; } - let item_variances = ty::ItemVariances { - types: types, - regions: regions - }; debug!("item_id={} item_variances={:?}", item_id, item_variances); diff --git a/src/librustc_typeck/variance/terms.rs b/src/librustc_typeck/variance/terms.rs index d9e7e8cbf7df4..72f8d9cb23ba8 100644 --- a/src/librustc_typeck/variance/terms.rs +++ b/src/librustc_typeck/variance/terms.rs @@ -21,7 +21,7 @@ use arena::TypedArena; use dep_graph::DepTrackingMapConfig; -use rustc::ty::subst::{ParamSpace, FnSpace, TypeSpace, SelfSpace, VecPerParamSpace}; +use rustc::ty::subst::{ParamSpace, FnSpace, TypeSpace, SelfSpace}; use rustc::ty::{self, TyCtxt}; use rustc::ty::maps::ItemVariances; use std::fmt; @@ -112,10 +112,7 @@ pub fn determine_parameters_to_be_inferred<'a, 'tcx>( // cache and share the variance struct used for items with // no type/region parameters - empty_variances: Rc::new(ty::ItemVariances { - types: VecPerParamSpace::empty(), - regions: VecPerParamSpace::empty() - }) + empty_variances: Rc::new(ty::ItemVariances::empty()) }; // See README.md for a discussion on dep-graph management. From 5ef6af09e3b9df3dd01f0e4d53176b0a72ce5722 Mon Sep 17 00:00:00 2001 From: Eduard Burtescu Date: Wed, 17 Aug 2016 03:56:18 +0300 Subject: [PATCH 05/12] rustc: move defaulting's use of &mut Substs from InferCtxt to typeck. --- src/librustc/infer/mod.rs | 122 ++++++++++---------- src/librustc/traits/error_reporting.rs | 28 +---- src/librustc/traits/util.rs | 3 +- src/librustc/ty/subst.rs | 31 +++++ src/librustc_typeck/astconv.rs | 47 ++++---- src/librustc_typeck/check/method/confirm.rs | 84 ++++++-------- src/librustc_typeck/check/method/mod.rs | 33 +++--- src/librustc_typeck/check/method/probe.rs | 35 +++--- src/librustc_typeck/check/mod.rs | 50 +++----- src/librustc_typeck/collect.rs | 6 +- src/librustc_typeck/lib.rs | 2 +- src/librustc_typeck/variance/constraints.rs | 4 +- 12 files changed, 213 insertions(+), 232 deletions(-) diff --git a/src/librustc/infer/mod.rs b/src/librustc/infer/mod.rs index 24fadc549fafc..79eea7314cdf3 100644 --- a/src/librustc/infer/mod.rs +++ b/src/librustc/infer/mod.rs @@ -1172,15 +1172,6 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { self.tcx.mk_var(self.next_ty_var_id(false)) } - pub fn next_ty_var_with_default(&self, - default: Option>) -> Ty<'tcx> { - let ty_var_id = self.type_variables - .borrow_mut() - .new_var(false, default); - - self.tcx.mk_var(ty_var_id) - } - pub fn next_diverging_ty_var(&self) -> Ty<'tcx> { self.tcx.mk_var(self.next_ty_var_id(true)) } @@ -1205,35 +1196,49 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { ty::ReVar(self.region_vars.new_region_var(origin)) } + /// Create a region inference variable for the given + /// region parameter definition. + pub fn region_var_for_def(&self, + span: Span, + def: &ty::RegionParameterDef) + -> ty::Region { + self.next_region_var(EarlyBoundRegion(span, def.name)) + } + + /// Create a type inference variable for the given + /// type parameter definition. The substitutions are + /// for actual parameters that may be referred to by + /// the default of this type parameter, if it exists. + /// E.g. `struct Foo(...);` when + /// used in a path such as `Foo::::new()` will + /// use an inference variable for `C` with `[T, U]` + /// as the substitutions for the default, `(T, U)`. + pub fn type_var_for_def(&self, + span: Span, + def: &ty::TypeParameterDef<'tcx>, + substs: &Substs<'tcx>) + -> Ty<'tcx> { + let default = def.default.map(|default| { + type_variable::Default { + ty: default.subst_spanned(self.tcx, substs, Some(span)), + origin_span: span, + def_id: def.default_def_id + } + }); + + + let ty_var_id = self.type_variables + .borrow_mut() + .new_var(false, default); + + self.tcx.mk_var(ty_var_id) + } + pub fn region_vars_for_defs(&self, span: Span, defs: &[ty::RegionParameterDef]) -> Vec { - defs.iter() - .map(|d| self.next_region_var(EarlyBoundRegion(span, d.name))) - .collect() - } - - // We have to take `&mut Substs` in order to provide the correct substitutions for defaults - // along the way, for this reason we don't return them. - pub fn type_vars_for_defs(&self, - span: Span, - space: subst::ParamSpace, - substs: &mut Substs<'tcx>, - defs: &[ty::TypeParameterDef<'tcx>]) { - - for def in defs.iter() { - let default = def.default.map(|default| { - type_variable::Default { - ty: default.subst_spanned(self.tcx, substs, Some(span)), - origin_span: span, - def_id: def.default_def_id - } - }); - - let ty_var = self.next_ty_var_with_default(default); - substs.types.push(space, ty_var); - } + defs.iter().map(|def| self.region_var_for_def(span, def)).collect() } /// Given a set of generics defined on a type or impl, returns a substitution mapping each @@ -1243,21 +1248,13 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { generics: &ty::Generics<'tcx>) -> &'tcx subst::Substs<'tcx> { - let type_params = subst::VecPerParamSpace::empty(); - - let region_params = - generics.regions.map( - |d| self.next_region_var(EarlyBoundRegion(span, d.name))); - - let mut substs = subst::Substs::new(type_params, region_params); - - for space in subst::ParamSpace::all().iter() { - self.type_vars_for_defs( - span, - *space, - &mut substs, - generics.types.get_slice(*space)); - } + let type_defs = generics.types.as_full_slice(); + let region_defs = generics.regions.as_full_slice(); + let substs = Substs::from_param_defs(region_defs, type_defs, |def| { + self.region_var_for_def(span, def) + }, |def, substs| { + self.type_var_for_def(span, def, substs) + }); self.tcx.mk_substs(substs) } @@ -1269,25 +1266,24 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { span: Span, generics: &ty::Generics<'tcx>, self_ty: Ty<'tcx>) - -> subst::Substs<'tcx> + -> &'tcx subst::Substs<'tcx> { - assert!(generics.types.len(subst::SelfSpace) == 1); assert!(generics.types.len(subst::FnSpace) == 0); - assert!(generics.regions.len(subst::SelfSpace) == 0); - assert!(generics.regions.len(subst::FnSpace) == 0); - - let type_params = Vec::new(); - - let region_param_defs = generics.regions.get_slice(subst::TypeSpace); - let regions = self.region_vars_for_defs(span, region_param_defs); - let mut substs = subst::Substs::new_trait(type_params, regions, self_ty); - - let type_parameter_defs = generics.types.get_slice(subst::TypeSpace); - self.type_vars_for_defs(span, subst::TypeSpace, &mut substs, type_parameter_defs); + let type_defs = generics.types.as_full_slice(); + let region_defs = generics.regions.as_full_slice(); + let substs = Substs::from_param_defs(region_defs, type_defs, |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) + } + }); - return substs; + self.tcx.mk_substs(substs) } pub fn fresh_bound_region(&self, debruijn: ty::DebruijnIndex) -> ty::Region { diff --git a/src/librustc/traits/error_reporting.rs b/src/librustc/traits/error_reporting.rs index b5133738ada8c..5d50eac1716a3 100644 --- a/src/librustc/traits/error_reporting.rs +++ b/src/librustc/traits/error_reporting.rs @@ -31,7 +31,7 @@ use ty::{self, ToPredicate, ToPolyTraitRef, Ty, TyCtxt, TypeFoldable}; use ty::error::ExpectedFound; use ty::fast_reject; use ty::fold::TypeFolder; -use ty::subst::{self, Subst, TypeSpace}; +use ty::subst::{Subst, TypeSpace}; use util::nodemap::{FnvHashMap, FnvHashSet}; use std::cmp; @@ -167,27 +167,6 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { }); } - fn impl_substs(&self, - did: DefId, - obligation: PredicateObligation<'tcx>) - -> subst::Substs<'tcx> { - let tcx = self.tcx; - - let ity = tcx.lookup_item_type(did); - let (tps, rps, _) = - (ity.generics.types.get_slice(TypeSpace), - ity.generics.regions.get_slice(TypeSpace), - ity.ty); - - let rps = self.region_vars_for_defs(obligation.cause.span, rps); - let mut substs = subst::Substs::new_type(vec![], rps); - self.type_vars_for_defs(obligation.cause.span, - TypeSpace, - &mut substs, - tps); - substs - } - fn fuzzy_match_tys(&self, a: Ty<'tcx>, b: Ty<'tcx>) -> bool { /// returns the fuzzy category of a given type, or None /// if the type can be equated to any type. @@ -242,10 +221,13 @@ 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_trait_ref = tcx .impl_trait_ref(def_id) .unwrap() - .subst(tcx, &self.impl_substs(def_id, obligation.clone())); + .subst(tcx, impl_substs); let impl_self_ty = impl_trait_ref.self_ty(); diff --git a/src/librustc/traits/util.rs b/src/librustc/traits/util.rs index 818eb4eb2fb1e..80a3ad9122bd1 100644 --- a/src/librustc/traits/util.rs +++ b/src/librustc/traits/util.rs @@ -358,8 +358,7 @@ pub fn fresh_type_vars_for_impl<'a, 'gcx, 'tcx>(infcx: &InferCtxt<'a, 'gcx, 'tcx impl_def_id: DefId) -> &'tcx Substs<'tcx> { - let tcx = infcx.tcx; - let impl_generics = tcx.lookup_item_type(impl_def_id).generics; + let impl_generics = infcx.tcx.lookup_item_type(impl_def_id).generics; infcx.fresh_substs_for_generics(span, &impl_generics) } diff --git a/src/librustc/ty/subst.rs b/src/librustc/ty/subst.rs index 63399ee138893..34e7899e2fddb 100644 --- a/src/librustc/ty/subst.rs +++ b/src/librustc/ty/subst.rs @@ -73,6 +73,33 @@ impl<'a, 'gcx, 'tcx> Substs<'tcx> { } } + /// Creates a Substs for generic parameter definitions, + /// by calling closures to obtain each region and type. + /// The closures get to observe the Substs as they're + /// being built, which can be used to correctly + /// substitute defaults of type parameters. + pub fn from_generics(generics: &ty::Generics<'tcx>, + mut mk_region: FR, + mut mk_type: FT) + -> Substs<'tcx> + where FR: FnMut(&ty::RegionParameterDef, &Substs<'tcx>) -> ty::Region, + FT: FnMut(&ty::TypeParameterDef<'tcx>, &Substs<'tcx>) -> Ty<'tcx> { + let mut substs = Substs::empty(); + for &space in &ParamSpace::all() { + for def in generics.regions.get_slice(space) { + let region = mk_region(def, &substs); + assert_eq!(substs.regions.len(def.space), def.index as usize); + substs.regions.push(def.space, region); + } + for def in generics.types.get_slice(space) { + let ty = mk_type(def, &substs); + assert_eq!(substs.types.len(def.space), def.index as usize); + substs.types.push(def.space, ty); + } + } + substs + } + pub fn is_noop(&self) -> bool { self.regions.is_empty() && self.types.is_empty() } @@ -81,6 +108,10 @@ impl<'a, 'gcx, 'tcx> Substs<'tcx> { *self.types.get(ty_param_def.space, ty_param_def.index as usize) } + pub fn region_for_def(&self, def: &ty::RegionParameterDef) -> ty::Region { + *self.regions.get(def.space, def.index as usize) + } + pub fn self_ty(&self) -> Option> { self.types.get_self().cloned() } diff --git a/src/librustc_typeck/astconv.rs b/src/librustc_typeck/astconv.rs index a0af98dec7298..ea7b447632c07 100644 --- a/src/librustc_typeck/astconv.rs +++ b/src/librustc_typeck/astconv.rs @@ -55,7 +55,7 @@ use hir::def_id::DefId; use hir::print as pprust; use middle::resolve_lifetime as rl; use rustc::lint; -use rustc::ty::subst::{FnSpace, TypeSpace, SelfSpace, Subst, Substs, ParamSpace}; +use rustc::ty::subst::{FnSpace, TypeSpace, SelfSpace, Subst, Substs}; use rustc::traits; use rustc::ty::{self, Ty, TyCtxt, ToPredicate, TypeFoldable}; use rustc::ty::wf::object_region_bounds; @@ -115,11 +115,15 @@ pub trait AstConv<'gcx, 'tcx> { fn get_free_substs(&self) -> Option<&Substs<'tcx>>; /// What type should we use when a type is omitted? - fn ty_infer(&self, - param_and_substs: Option>, - substs: Option<&mut Substs<'tcx>>, - space: Option, - span: Span) -> Ty<'tcx>; + fn ty_infer(&self, span: Span) -> Ty<'tcx>; + + /// Same as ty_infer, but with a known type parameter definition. + fn ty_infer_for_def(&self, + _def: &ty::TypeParameterDef<'tcx>, + _substs: &Substs<'tcx>, + span: Span) -> Ty<'tcx> { + self.ty_infer(span) + } /// Projecting an associated type from a (potentially) /// higher-ranked trait reference is more complicated, because of @@ -535,26 +539,28 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o { self_ty: Option>) -> Vec> { - fn default_type_parameter<'tcx>(p: &ty::TypeParameterDef<'tcx>, self_ty: Option>) - -> Option> - { + let use_default = |p: &ty::TypeParameterDef<'tcx>| { if let Some(ref default) = p.default { if self_ty.is_none() && default.has_self_ty() { // There is no suitable inference default for a type parameter // that references self with no self-type provided. - return None; + return false; } } - Some(p.clone()) - } + true + }; if param_mode == PathParamMode::Optional && types_provided.is_empty() { - ty_param_defs - .iter() - .map(|p| self.ty_infer(default_type_parameter(p, self_ty), Some(&mut substs), - Some(TypeSpace), span)) - .collect() + ty_param_defs.iter().map(|def| { + let ty_var = if use_default(def) { + self.ty_infer_for_def(def, &substs, span) + } else { + self.ty_infer(span) + }; + substs.types.push(def.space, ty_var); + ty_var + }).collect() } else { types_provided } @@ -1828,7 +1834,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o { // values in a ExprClosure, or as // the type of local variables. Both of these cases are // handled specially and will not descend into this routine. - self.ty_infer(None, None, None, ast_ty.span) + self.ty_infer(ast_ty.span) } }; @@ -1845,7 +1851,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o { { match a.ty.node { hir::TyInfer if expected_ty.is_some() => expected_ty.unwrap(), - hir::TyInfer => self.ty_infer(None, None, None, a.ty.span), + hir::TyInfer => self.ty_infer(a.ty.span), _ => self.ast_ty_to_ty(rscope, &a.ty), } } @@ -2067,8 +2073,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o { let output_ty = match decl.output { _ if is_infer && expected_ret_ty.is_some() => expected_ret_ty.unwrap(), - _ if is_infer => - self.ty_infer(None, None, None, decl.output.span()), + _ if is_infer => self.ty_infer(decl.output.span()), hir::Return(ref output) => self.ast_ty_to_ty(&rb, &output), hir::DefaultReturn(..) => bug!(), diff --git a/src/librustc_typeck/check/method/confirm.rs b/src/librustc_typeck/check/method/confirm.rs index 5fac65bbfd655..d1d7259955576 100644 --- a/src/librustc_typeck/check/method/confirm.rs +++ b/src/librustc_typeck/check/method/confirm.rs @@ -198,7 +198,7 @@ impl<'a, 'gcx, 'tcx> ConfirmContext<'a, 'gcx, 'tcx> { fn fresh_receiver_substs(&mut self, self_ty: Ty<'tcx>, pick: &probe::Pick<'tcx>) - -> subst::Substs<'tcx> + -> &'tcx subst::Substs<'tcx> { match pick.kind { probe::InherentImplPick => { @@ -231,7 +231,7 @@ impl<'a, 'gcx, 'tcx> ConfirmContext<'a, 'gcx, 'tcx> { original_poly_trait_ref, upcast_trait_ref, trait_def_id); - upcast_trait_ref.substs.clone() + upcast_trait_ref.substs }) } @@ -249,9 +249,9 @@ impl<'a, 'gcx, 'tcx> ConfirmContext<'a, 'gcx, 'tcx> { let impl_trait_ref = self.instantiate_type_scheme( self.span, - &impl_polytype.substs, + impl_polytype.substs, &self.tcx.impl_trait_ref(impl_def_id).unwrap()); - impl_trait_ref.substs.clone() + impl_trait_ref.substs } probe::TraitPick => { @@ -271,7 +271,7 @@ impl<'a, 'gcx, 'tcx> ConfirmContext<'a, 'gcx, 'tcx> { probe::WhereClausePick(ref poly_trait_ref) => { // Where clauses can have bound regions in them. We need to instantiate // those to convert from a poly-trait-ref to a trait-ref. - self.replace_late_bound_regions_with_fresh_var(&poly_trait_ref).substs.clone() + self.replace_late_bound_regions_with_fresh_var(&poly_trait_ref).substs } } } @@ -303,8 +303,8 @@ impl<'a, 'gcx, 'tcx> ConfirmContext<'a, 'gcx, 'tcx> { fn instantiate_method_substs(&mut self, pick: &probe::Pick<'tcx>, - supplied_method_types: Vec>, - substs: subst::Substs<'tcx>) + mut supplied_method_types: Vec>, + substs: &subst::Substs<'tcx>) -> subst::Substs<'tcx> { // Determine the values for the generic parameters of the method. @@ -312,50 +312,42 @@ impl<'a, 'gcx, 'tcx> ConfirmContext<'a, 'gcx, 'tcx> { // variables. let num_supplied_types = supplied_method_types.len(); let method = pick.item.as_opt_method().unwrap(); - let method_types = method.generics.types.get_slice(subst::FnSpace); - let num_method_types = method_types.len(); - + let num_method_types = method.generics.types.len(subst::FnSpace); + + if num_supplied_types > 0 && num_supplied_types != num_method_types { + if num_method_types == 0 { + span_err!(self.tcx.sess, self.span, E0035, + "does not take type parameters"); + } else { + span_err!(self.tcx.sess, self.span, E0036, + "incorrect number of type parameters given for this method: \ + expected {}, found {}", + num_method_types, num_supplied_types); + } + supplied_method_types = vec![self.tcx.types.err; num_method_types]; + } // Create subst for early-bound lifetime parameters, combining // parameters from the type and those from the method. // // FIXME -- permit users to manually specify lifetimes - let method_regions = - self.region_vars_for_defs( - self.span, - pick.item.as_opt_method().unwrap() - .generics.regions.get_slice(subst::FnSpace)); - - let subst::Substs { types, regions } = substs; - let regions = regions.with_slice(subst::FnSpace, &method_regions); - let mut final_substs = subst::Substs { types: types, regions: regions }; - - if num_supplied_types == 0 { - self.type_vars_for_defs( - self.span, - subst::FnSpace, - &mut final_substs, - method_types); - } else if num_method_types == 0 { - span_err!(self.tcx.sess, self.span, E0035, - "does not take type parameters"); - self.type_vars_for_defs( - self.span, - subst::FnSpace, - &mut final_substs, - method_types); - } else if num_supplied_types != num_method_types { - span_err!(self.tcx.sess, self.span, E0036, - "incorrect number of type parameters given for this method: expected {}, found {}", - num_method_types, num_supplied_types); - final_substs.types.replace( - subst::FnSpace, - vec![self.tcx.types.err; num_method_types]); - } else { - final_substs.types.replace(subst::FnSpace, supplied_method_types); - } - - return final_substs; + let type_defs = method.generics.types.as_full_slice(); + let region_defs = method.generics.regions.as_full_slice(); + subst::Substs::from_param_defs(region_defs, type_defs, |def| { + if def.space != subst::FnSpace { + substs.region_for_def(def) + } else { + self.region_var_for_def(self.span, def) + } + }, |def, cur_substs| { + if def.space != subst::FnSpace { + substs.type_for_def(def) + } else if supplied_method_types.is_empty() { + self.type_var_for_def(self.span, def, cur_substs) + } else { + supplied_method_types[def.index as usize] + } + }) } fn unify_receivers(&mut self, diff --git a/src/librustc_typeck/check/method/mod.rs b/src/librustc_typeck/check/method/mod.rs index e6401be5b3ef6..532a5c0de4e46 100644 --- a/src/librustc_typeck/check/method/mod.rs +++ b/src/librustc_typeck/check/method/mod.rs @@ -182,29 +182,26 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { let trait_def = self.tcx.lookup_trait_def(trait_def_id); - let type_parameter_defs = trait_def.generics.types.get_slice(subst::TypeSpace); - let expected_number_of_input_types = type_parameter_defs.len(); - + if let Some(ref input_types) = opt_input_types { + assert_eq!(trait_def.generics.types.len(subst::TypeSpace), input_types.len()); + } assert_eq!(trait_def.generics.types.len(subst::FnSpace), 0); assert!(trait_def.generics.regions.is_empty()); // Construct a trait-reference `self_ty : Trait` - let mut substs = subst::Substs::new_trait(Vec::new(), Vec::new(), self_ty); - - match opt_input_types { - Some(input_types) => { - assert_eq!(expected_number_of_input_types, input_types.len()); - substs.types.replace(subst::ParamSpace::TypeSpace, input_types); + let type_defs = trait_def.generics.types.as_full_slice(); + let region_defs = trait_def.generics.regions.as_full_slice(); + let substs = subst::Substs::from_param_defs(region_defs, type_defs, |def| { + self.region_var_for_def(span, def) + }, |def, substs| { + if def.space == subst::SelfSpace { + self_ty + } else if let Some(ref input_types) = opt_input_types { + input_types[def.index as usize] + } else { + self.type_var_for_def(span, def, substs) } - - None => { - self.type_vars_for_defs( - span, - subst::ParamSpace::TypeSpace, - &mut substs, - type_parameter_defs); - } - } + }); let trait_ref = ty::TraitRef::new(trait_def_id, self.tcx.mk_substs(substs)); diff --git a/src/librustc_typeck/check/method/probe.rs b/src/librustc_typeck/check/method/probe.rs index e4701bb119559..44e371482c55c 100644 --- a/src/librustc_typeck/check/method/probe.rs +++ b/src/librustc_typeck/check/method/probe.rs @@ -1227,28 +1227,29 @@ impl<'a, 'gcx, 'tcx> ProbeContext<'a, 'gcx, 'tcx> { return impl_ty; } - let mut placeholder; + let placeholder; let mut substs = substs; if !method.generics.types.is_empty_in(subst::FnSpace) || !method.generics.regions.is_empty_in(subst::FnSpace) { - // In general, during probe we erase regions. See - // `impl_self_ty()` for an explanation. - let method_regions = - method.generics.regions.get_slice(subst::FnSpace) - .iter() - .map(|_| ty::ReErased) - .collect(); - - placeholder = (*substs).clone().with_method(Vec::new(), method_regions); - - self.type_vars_for_defs( - self.span, - subst::FnSpace, - &mut placeholder, - method.generics.types.get_slice(subst::FnSpace)); - + let type_defs = method.generics.types.as_full_slice(); + let region_defs = method.generics.regions.as_full_slice(); + placeholder = subst::Substs::from_param_defs(region_defs, type_defs, |def| { + if def.space != subst::FnSpace { + substs.region_for_def(def) + } else { + // In general, during probe we erase regions. See + // `impl_self_ty()` for an explanation. + ty::ReErased + } + }, |def, cur_substs| { + if def.space != subst::FnSpace { + substs.type_for_def(def) + } else { + self.type_var_for_def(self.span, def, cur_substs) + } + }); substs = &placeholder; } diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index fae64f3741974..b5018d51b7f56 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -1358,27 +1358,15 @@ impl<'a, 'gcx, 'tcx> AstConv<'gcx, 'tcx> for FnCtxt<'a, 'gcx, 'tcx> { trait_def.associated_type_names.contains(&assoc_name) } - fn ty_infer(&self, - ty_param_def: Option>, - substs: Option<&mut subst::Substs<'tcx>>, - space: Option, - span: Span) -> Ty<'tcx> { - // Grab the default doing subsitution - let default = ty_param_def.and_then(|def| { - def.default.map(|ty| type_variable::Default { - ty: ty.subst_spanned(self.tcx(), substs.as_ref().unwrap(), Some(span)), - origin_span: span, - def_id: def.default_def_id - }) - }); - - let ty_var = self.next_ty_var_with_default(default); + fn ty_infer(&self, _span: Span) -> Ty<'tcx> { + self.next_ty_var() + } - // Finally we add the type variable to the substs - match substs { - None => ty_var, - Some(substs) => { substs.types.push(space.unwrap(), ty_var); ty_var } - } + fn ty_infer_for_def(&self, + ty_param_def: &ty::TypeParameterDef<'tcx>, + substs: &subst::Substs<'tcx>, + span: Span) -> Ty<'tcx> { + self.type_var_for_def(span, ty_param_def, substs) } fn projected_ty_from_poly_trait_ref(&self, @@ -2785,20 +2773,11 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { span: Span, // (potential) receiver for this impl did: DefId) -> TypeAndSubsts<'tcx> { - let tcx = self.tcx; - - let ity = tcx.lookup_item_type(did); - let (tps, rps, raw_ty) = - (ity.generics.types.get_slice(subst::TypeSpace), - ity.generics.regions.get_slice(subst::TypeSpace), - ity.ty); + let ity = self.tcx.lookup_item_type(did); + debug!("impl_self_ty: ity={:?}", ity); - debug!("impl_self_ty: tps={:?} rps={:?} raw_ty={:?}", tps, rps, raw_ty); - - let rps = self.region_vars_for_defs(span, rps); - let mut substs = subst::Substs::new_type(vec![], rps); - self.type_vars_for_defs(span, ParamSpace::TypeSpace, &mut substs, tps); - let substd_ty = self.instantiate_type_scheme(span, &substs, &raw_ty); + let substs = self.fresh_substs_for_generics(span, &ity.generics); + let substd_ty = self.instantiate_type_scheme(span, &substs, &ity.ty); TypeAndSubsts { substs: substs, ty: substd_ty } } @@ -4532,7 +4511,10 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { // everything. if provided_len == 0 && !(require_type_space && space == subst::TypeSpace) { substs.types.replace(space, Vec::new()); - self.type_vars_for_defs(span, space, substs, &desired[..]); + for def in desired { + let ty_var = self.type_var_for_def(span, def, substs); + substs.types.push(def.space, ty_var); + } return; } diff --git a/src/librustc_typeck/collect.rs b/src/librustc_typeck/collect.rs index 69545aefb4446..0ddc051d4a868 100644 --- a/src/librustc_typeck/collect.rs +++ b/src/librustc_typeck/collect.rs @@ -362,11 +362,7 @@ impl<'a, 'tcx> AstConv<'tcx, 'tcx> for ItemCtxt<'a, 'tcx> { None } - fn ty_infer(&self, - _ty_param_def: Option>, - _substs: Option<&mut Substs<'tcx>>, - _space: Option, - span: Span) -> Ty<'tcx> { + fn ty_infer(&self, span: Span) -> Ty<'tcx> { struct_span_err!( self.tcx().sess, span, diff --git a/src/librustc_typeck/lib.rs b/src/librustc_typeck/lib.rs index 11743ade2d469..4ce6f8210c3c5 100644 --- a/src/librustc_typeck/lib.rs +++ b/src/librustc_typeck/lib.rs @@ -132,7 +132,7 @@ pub mod coherence; pub mod variance; pub struct TypeAndSubsts<'tcx> { - pub substs: Substs<'tcx>, + pub substs: &'tcx Substs<'tcx>, pub ty: Ty<'tcx>, } diff --git a/src/librustc_typeck/variance/constraints.rs b/src/librustc_typeck/variance/constraints.rs index 1e342d4b81971..50c568cfef8f6 100644 --- a/src/librustc_typeck/variance/constraints.rs +++ b/src/librustc_typeck/variance/constraints.rs @@ -464,7 +464,7 @@ impl<'a, 'tcx> ConstraintContext<'a, 'tcx> { self.declared_variance(p.def_id, def_id, TypeParam, p.space, p.index as usize); let variance_i = self.xform(variance, variance_decl); - let substs_ty = *substs.types.get(p.space, p.index as usize); + let substs_ty = substs.type_for_def(p); debug!("add_constraints_from_substs: variance_decl={:?} variance_i={:?}", variance_decl, variance_i); self.add_constraints_from_ty(generics, substs_ty, variance_i); @@ -475,7 +475,7 @@ impl<'a, 'tcx> ConstraintContext<'a, 'tcx> { self.declared_variance(p.def_id, def_id, RegionParam, p.space, p.index as usize); let variance_i = self.xform(variance, variance_decl); - let substs_r = *substs.regions.get(p.space, p.index as usize); + let substs_r = substs.region_for_def(p); self.add_constraints_from_region(generics, substs_r, variance_i); } } From 4b25f08512eab11aec151d8f718fca0d8840d0c0 Mon Sep 17 00:00:00 2001 From: Eduard Burtescu Date: Thu, 4 Aug 2016 15:52:57 +0300 Subject: [PATCH 06/12] rustc: move trait objects from TraitRef to ExistentialTraitRef. --- src/librustc/infer/mod.rs | 8 +- src/librustc/traits/coherence.rs | 4 +- src/librustc/traits/project.rs | 7 +- src/librustc/traits/select.rs | 49 +-- src/librustc/ty/context.rs | 25 +- src/librustc/ty/error.rs | 2 +- src/librustc/ty/fast_reject.rs | 2 +- src/librustc/ty/flags.rs | 21 +- src/librustc/ty/fold.rs | 9 - src/librustc/ty/item_path.rs | 2 +- src/librustc/ty/mod.rs | 6 +- src/librustc/ty/relate.rs | 89 ++-- src/librustc/ty/structural_impls.rs | 90 ++-- src/librustc/ty/sty.rs | 180 ++++---- src/librustc/ty/util.rs | 10 +- src/librustc/ty/walk.rs | 6 +- src/librustc/ty/wf.rs | 23 +- src/librustc/util/ppaux.rs | 104 ++--- src/librustc_metadata/astencode.rs | 49 --- src/librustc_metadata/tydecode.rs | 61 ++- src/librustc_metadata/tyencode.rs | 67 +-- src/librustc_trans/base.rs | 11 +- src/librustc_trans/collector.rs | 3 +- src/librustc_trans/debuginfo/metadata.rs | 2 +- src/librustc_trans/trans_item.rs | 8 +- src/librustc_typeck/astconv.rs | 463 ++++++++------------ src/librustc_typeck/check/cast.rs | 2 +- src/librustc_typeck/check/closure.rs | 11 +- src/librustc_typeck/check/method/confirm.rs | 20 +- src/librustc_typeck/check/method/mod.rs | 4 +- src/librustc_typeck/check/method/probe.rs | 37 +- src/librustc_typeck/check/method/suggest.rs | 2 +- src/librustc_typeck/check/regionck.rs | 4 +- src/librustc_typeck/coherence/mod.rs | 2 +- src/librustc_typeck/coherence/orphan.rs | 2 +- src/librustc_typeck/coherence/overlap.rs | 4 +- src/librustc_typeck/collect.rs | 34 +- src/librustc_typeck/variance/constraints.rs | 9 +- src/librustdoc/clean/mod.rs | 42 +- 39 files changed, 682 insertions(+), 792 deletions(-) diff --git a/src/librustc/infer/mod.rs b/src/librustc/infer/mod.rs index 79eea7314cdf3..951570679e08e 100644 --- a/src/librustc/infer/mod.rs +++ b/src/librustc/infer/mod.rs @@ -1248,9 +1248,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { generics: &ty::Generics<'tcx>) -> &'tcx subst::Substs<'tcx> { - let type_defs = generics.types.as_full_slice(); - let region_defs = generics.regions.as_full_slice(); - let substs = Substs::from_param_defs(region_defs, type_defs, |def| { + let substs = Substs::from_generics(generics, |def, _| { self.region_var_for_def(span, def) }, |def, substs| { self.type_var_for_def(span, def, substs) @@ -1271,9 +1269,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { assert!(generics.types.len(subst::SelfSpace) == 1); assert!(generics.types.len(subst::FnSpace) == 0); - let type_defs = generics.types.as_full_slice(); - let region_defs = generics.regions.as_full_slice(); - let substs = Substs::from_param_defs(region_defs, type_defs, |def| { + let substs = Substs::from_generics(generics, |def, _| { self.region_var_for_def(span, def) }, |def, substs| { if def.space == subst::SelfSpace { diff --git a/src/librustc/traits/coherence.rs b/src/librustc/traits/coherence.rs index b38f5f96de448..f1701d60fd0c0 100644 --- a/src/librustc/traits/coherence.rs +++ b/src/librustc/traits/coherence.rs @@ -231,7 +231,7 @@ fn fundamental_ty(tcx: TyCtxt, ty: Ty) -> bool { ty::TyEnum(def, _) | ty::TyStruct(def, _) => def.is_fundamental(), ty::TyTrait(ref data) => - tcx.has_attr(data.principal_def_id(), "fundamental"), + tcx.has_attr(data.principal.def_id(), "fundamental"), _ => false } @@ -275,7 +275,7 @@ fn ty_is_local_constructor(tcx: TyCtxt, ty: Ty, infer_is_local: InferIsLocal)-> } ty::TyTrait(ref tt) => { - tt.principal_def_id().is_local() + tt.principal.def_id().is_local() } ty::TyError => { diff --git a/src/librustc/traits/project.rs b/src/librustc/traits/project.rs index d580deed0756a..ea4fc1c25ab42 100644 --- a/src/librustc/traits/project.rs +++ b/src/librustc/traits/project.rs @@ -1133,10 +1133,9 @@ fn confirm_object_candidate<'cx, 'gcx, 'tcx>( object_ty) } }; - let projection_bounds = data.projection_bounds_with_self_ty(selcx.tcx(), object_ty); - let env_predicates = projection_bounds.iter() - .map(|p| p.to_predicate()) - .collect(); + let env_predicates = data.projection_bounds.iter().map(|p| { + p.with_self_ty(selcx.tcx(), object_ty).to_predicate() + }).collect(); let env_predicate = { let env_predicates = elaborate_predicates(selcx.tcx(), env_predicates); diff --git a/src/librustc/traits/select.rs b/src/librustc/traits/select.rs index 9c7dd7ccd7011..73108e7d37f88 100644 --- a/src/librustc/traits/select.rs +++ b/src/librustc/traits/select.rs @@ -1528,7 +1528,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { ty::TyTrait(ref data) => { match this.tcx().lang_items.to_builtin_kind(obligation.predicate.def_id()) { Some(bound @ ty::BoundSend) | Some(bound @ ty::BoundSync) => { - if data.bounds.builtin_bounds.contains(&bound) { + if data.builtin_bounds.contains(&bound) { debug!("assemble_candidates_from_object_ty: matched builtin bound, \ pushing candidate"); candidates.vec.push(BuiltinObjectCandidate); @@ -1538,7 +1538,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { _ => {} } - data.principal_trait_ref_with_self_ty(this.tcx(), self_ty) + data.principal.with_self_ty(this.tcx(), self_ty) } ty::TyInfer(ty::TyVar(_)) => { debug!("assemble_candidates_from_object_ty: ambiguous"); @@ -1622,7 +1622,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { // We always upcast when we can because of reason // #2 (region bounds). data_a.principal.def_id() == data_a.principal.def_id() && - data_a.bounds.builtin_bounds.is_superset(&data_b.bounds.builtin_bounds) + data_a.builtin_bounds.is_superset(&data_b.builtin_bounds) } // T -> Trait. @@ -2179,10 +2179,9 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { match self_ty.sty { ty::TyTrait(ref data) => { // OK to skip the binder, it is reintroduced below - let input_types = data.principal.skip_binder().substs.types.get_slice(TypeSpace); - let assoc_types = data.bounds.projection_bounds - .iter() - .map(|pb| pb.skip_binder().ty); + let input_types = data.principal.skip_binder().input_types(); + let assoc_types = data.projection_bounds.iter() + .map(|pb| pb.skip_binder().ty); let all_types: Vec<_> = input_types.iter().cloned() .chain(assoc_types) .collect(); @@ -2315,7 +2314,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { let self_ty = self.infcx.shallow_resolve(*obligation.self_ty().skip_binder()); let poly_trait_ref = match self_ty.sty { ty::TyTrait(ref data) => { - data.principal_trait_ref_with_self_ty(self.tcx(), self_ty) + data.principal.with_self_ty(self.tcx(), self_ty) } _ => { span_bug!(obligation.cause.span, @@ -2487,13 +2486,12 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { // Trait+Kx+'a -> Trait+Ky+'b (upcasts). (&ty::TyTrait(ref data_a), &ty::TyTrait(ref data_b)) => { // See assemble_candidates_for_unsizing for more info. - let bounds = ty::ExistentialBounds { - region_bound: data_b.bounds.region_bound, - builtin_bounds: data_b.bounds.builtin_bounds, - projection_bounds: data_a.bounds.projection_bounds.clone(), - }; - - let new_trait = tcx.mk_trait(data_a.principal.clone(), bounds); + let new_trait = tcx.mk_trait(ty::TraitObject { + principal: data_a.principal, + region_bound: data_b.region_bound, + builtin_bounds: data_b.builtin_bounds, + projection_bounds: data_a.projection_bounds.clone(), + }); let origin = TypeOrigin::Misc(obligation.cause.span); let InferOk { obligations, .. } = self.infcx.sub_types(false, origin, new_trait, target) @@ -2504,8 +2502,8 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { let cause = ObligationCause::new(obligation.cause.span, obligation.cause.body_id, ObjectCastObligation(target)); - let outlives = ty::OutlivesPredicate(data_a.bounds.region_bound, - data_b.bounds.region_bound); + let outlives = ty::OutlivesPredicate(data_a.region_bound, + data_b.region_bound); nested.push(Obligation::with_depth(cause, obligation.recursion_depth + 1, ty::Binder(outlives).to_predicate())); @@ -2513,12 +2511,12 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { // T -> Trait. (_, &ty::TyTrait(ref data)) => { - let mut object_dids = Some(data.principal_def_id()).into_iter(); + let mut object_dids = Some(data.principal.def_id()).into_iter(); // FIXME(#33243) -// data.bounds.builtin_bounds.iter().flat_map(|bound| { +// data.builtin_bounds.iter().flat_map(|bound| { // tcx.lang_items.from_builtin_kind(bound).ok() // }) -// .chain(Some(data.principal_def_id())); +// .chain(Some(data.principal.def_id())); if let Some(did) = object_dids.find(|did| { !tcx.is_object_safe(*did) }) { @@ -2535,10 +2533,10 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { }; // Create the obligation for casting from T to Trait. - push(data.principal_trait_ref_with_self_ty(tcx, source).to_predicate()); + push(data.principal.with_self_ty(tcx, source).to_predicate()); // We can only make objects from sized types. - let mut builtin_bounds = data.bounds.builtin_bounds; + let mut builtin_bounds = data.builtin_bounds; builtin_bounds.insert(ty::BoundSized); // Create additional obligations for all the various builtin @@ -2554,14 +2552,13 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { } // Create obligations for the projection predicates. - for bound in data.projection_bounds_with_self_ty(tcx, source) { - push(bound.to_predicate()); + for bound in &data.projection_bounds { + push(bound.with_self_ty(tcx, source).to_predicate()); } // If the type is `Foo+'a`, ensures that the type // being cast to `Foo+'a` outlives `'a`: - let outlives = ty::OutlivesPredicate(source, - data.bounds.region_bound); + let outlives = ty::OutlivesPredicate(source, data.region_bound); push(ty::Binder(outlives).to_predicate()); } diff --git a/src/librustc/ty/context.rs b/src/librustc/ty/context.rs index 4056fb01aa2c2..dfb5482ad873b 100644 --- a/src/librustc/ty/context.rs +++ b/src/librustc/ty/context.rs @@ -27,9 +27,9 @@ use ty::subst::{self, Substs}; use traits; use ty::{self, TraitRef, Ty, TypeAndMut}; use ty::{TyS, TypeVariants}; -use ty::{AdtDef, ClosureSubsts, ExistentialBounds, Region}; +use ty::{AdtDef, ClosureSubsts, Region}; use hir::FreevarMap; -use ty::{BareFnTy, InferTy, ParamTy, ProjectionTy, TraitTy}; +use ty::{BareFnTy, InferTy, ParamTy, ProjectionTy, TraitObject}; use ty::{TyVar, TyVid, IntVar, IntVid, FloatVar, FloatVid}; use ty::TypeVariants::*; use ty::layout::{Layout, TargetDataLayout}; @@ -1150,12 +1150,6 @@ impl_interners!('tcx, region: mk_region(Region, keep_local) -> Region ); -fn bound_list_is_sorted(bounds: &[ty::PolyProjectionPredicate]) -> bool { - bounds.is_empty() || - bounds[1..].iter().enumerate().all( - |(index, bound)| bounds[index].sort_key() <= bound.sort_key()) -} - impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { /// Create an unsafe fn ty based on a safe fn ty. pub fn safe_to_unsafe_fn_ty(self, bare_fn: &BareFnTy<'tcx>) -> Ty<'tcx> { @@ -1288,18 +1282,9 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { self.mk_ty(TyFnPtr(fty)) } - pub fn mk_trait(self, - principal: ty::PolyTraitRef<'tcx>, - bounds: ExistentialBounds<'tcx>) - -> Ty<'tcx> - { - assert!(bound_list_is_sorted(&bounds.projection_bounds)); - - let inner = box TraitTy { - principal: principal, - bounds: bounds - }; - self.mk_ty(TyTrait(inner)) + pub fn mk_trait(self, mut obj: TraitObject<'tcx>) -> Ty<'tcx> { + obj.projection_bounds.sort_by(|a, b| a.sort_key().cmp(&b.sort_key())); + self.mk_ty(TyTrait(box obj)) } pub fn mk_projection(self, diff --git a/src/librustc/ty/error.rs b/src/librustc/ty/error.rs index 42d5788568f1c..933746ebc2ad1 100644 --- a/src/librustc/ty/error.rs +++ b/src/librustc/ty/error.rs @@ -243,7 +243,7 @@ impl<'a, 'gcx, 'lcx, 'tcx> ty::TyS<'tcx> { ty::TyFnDef(..) => format!("fn item"), ty::TyFnPtr(_) => "fn pointer".to_string(), ty::TyTrait(ref inner) => { - format!("trait {}", tcx.item_path_str(inner.principal_def_id())) + format!("trait {}", tcx.item_path_str(inner.principal.def_id())) } ty::TyStruct(def, _) => { format!("struct `{}`", tcx.item_path_str(def.did)) diff --git a/src/librustc/ty/fast_reject.rs b/src/librustc/ty/fast_reject.rs index 9bf2daeb5f49b..f7472d611befe 100644 --- a/src/librustc/ty/fast_reject.rs +++ b/src/librustc/ty/fast_reject.rs @@ -61,7 +61,7 @@ pub fn simplify_type<'a, 'gcx, 'tcx>(tcx: TyCtxt<'a, 'gcx, 'tcx>, ty::TyArray(..) | ty::TySlice(_) => Some(VecSimplifiedType), ty::TyRawPtr(_) => Some(PtrSimplifiedType), ty::TyTrait(ref trait_info) => { - Some(TraitSimplifiedType(trait_info.principal_def_id())) + Some(TraitSimplifiedType(trait_info.principal.def_id())) } ty::TyStruct(def, _) => { Some(StructSimplifiedType(def.did)) diff --git a/src/librustc/ty/flags.rs b/src/librustc/ty/flags.rs index 3a5f3d421eaf7..6cc759c420d29 100644 --- a/src/librustc/ty/flags.rs +++ b/src/librustc/ty/flags.rs @@ -116,17 +116,16 @@ impl FlagComputation { self.add_substs(substs); } - &ty::TyTrait(box ty::TraitTy { ref principal, ref bounds }) => { + &ty::TyTrait(ref obj) => { let mut computation = FlagComputation::new(); - computation.add_substs(principal.0.substs); - for projection_bound in &bounds.projection_bounds { + computation.add_substs(obj.principal.skip_binder().substs); + for projection_bound in &obj.projection_bounds { let mut proj_computation = FlagComputation::new(); - proj_computation.add_projection_predicate(&projection_bound.0); + proj_computation.add_existential_projection(&projection_bound.0); self.add_bound_computation(&proj_computation); } self.add_bound_computation(&computation); - - self.add_bounds(bounds); + self.add_region(obj.region_bound); } &ty::TyBox(tt) | &ty::TyArray(tt, _) | &ty::TySlice(tt) => { @@ -199,9 +198,9 @@ impl FlagComputation { } } - fn add_projection_predicate(&mut self, projection_predicate: &ty::ProjectionPredicate) { - self.add_projection_ty(&projection_predicate.projection_ty); - self.add_ty(projection_predicate.ty); + fn add_existential_projection(&mut self, projection: &ty::ExistentialProjection) { + self.add_substs(projection.trait_ref.substs); + self.add_ty(projection.ty); } fn add_projection_ty(&mut self, projection_ty: &ty::ProjectionTy) { @@ -214,8 +213,4 @@ impl FlagComputation { self.add_region(r); } } - - fn add_bounds(&mut self, bounds: &ty::ExistentialBounds) { - self.add_region(bounds.region_bound); - } } diff --git a/src/librustc/ty/fold.rs b/src/librustc/ty/fold.rs index 3eeff6ee5792f..597261cca72bf 100644 --- a/src/librustc/ty/fold.rs +++ b/src/librustc/ty/fold.rs @@ -140,10 +140,6 @@ pub trait TypeFolder<'gcx: 'tcx, 'tcx> : Sized { t.super_fold_with(self) } - fn fold_trait_ref(&mut self, t: &ty::TraitRef<'tcx>) -> ty::TraitRef<'tcx> { - t.super_fold_with(self) - } - fn fold_impl_header(&mut self, imp: &ty::ImplHeader<'tcx>) -> ty::ImplHeader<'tcx> { imp.super_fold_with(self) } @@ -177,11 +173,6 @@ pub trait TypeFolder<'gcx: 'tcx, 'tcx> : Sized { r.super_fold_with(self) } - fn fold_existential_bounds(&mut self, s: &ty::ExistentialBounds<'tcx>) - -> ty::ExistentialBounds<'tcx> { - s.super_fold_with(self) - } - fn fold_autoref(&mut self, ar: &adjustment::AutoRef<'tcx>) -> adjustment::AutoRef<'tcx> { ar.super_fold_with(self) diff --git a/src/librustc/ty/item_path.rs b/src/librustc/ty/item_path.rs index 8ddd8bef36a6f..1dcc623d36558 100644 --- a/src/librustc/ty/item_path.rs +++ b/src/librustc/ty/item_path.rs @@ -322,7 +322,7 @@ pub fn characteristic_def_id_of_type(ty: Ty) -> Option { ty::TyStruct(adt_def, _) | ty::TyEnum(adt_def, _) => Some(adt_def.did), - ty::TyTrait(ref data) => Some(data.principal_def_id()), + ty::TyTrait(ref data) => Some(data.principal.def_id()), ty::TyArray(subty, _) | ty::TySlice(subty) | diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs index 44532fcb4e64f..6ac57a877a759 100644 --- a/src/librustc/ty/mod.rs +++ b/src/librustc/ty/mod.rs @@ -54,11 +54,13 @@ use hir::{ItemImpl, ItemTrait, PatKind}; use hir::intravisit::Visitor; pub use self::sty::{Binder, DebruijnIndex}; -pub use self::sty::{BuiltinBound, BuiltinBounds, ExistentialBounds}; +pub use self::sty::{BuiltinBound, BuiltinBounds}; pub use self::sty::{BareFnTy, FnSig, PolyFnSig}; -pub use self::sty::{ClosureTy, InferTy, ParamTy, ProjectionTy, TraitTy}; +pub use self::sty::{ClosureTy, InferTy, ParamTy, ProjectionTy, TraitObject}; pub use self::sty::{ClosureSubsts, TypeAndMut}; pub use self::sty::{TraitRef, TypeVariants, PolyTraitRef}; +pub use self::sty::{ExistentialTraitRef, PolyExistentialTraitRef}; +pub use self::sty::{ExistentialProjection, PolyExistentialProjection}; pub use self::sty::{BoundRegion, EarlyBoundRegion, FreeRegion, Region}; pub use self::sty::Issue32330; pub use self::sty::{TyVid, IntVid, FloatVid, RegionVid, SkolemizedRegionVid}; diff --git a/src/librustc/ty/relate.rs b/src/librustc/ty/relate.rs index 05a9b8111570d..aa48474e50cf1 100644 --- a/src/librustc/ty/relate.rs +++ b/src/librustc/ty/relate.rs @@ -326,24 +326,33 @@ impl<'tcx> Relate<'tcx> for ty::ProjectionTy<'tcx> { } } -impl<'tcx> Relate<'tcx> for ty::ProjectionPredicate<'tcx> { +impl<'tcx> Relate<'tcx> for ty::ExistentialProjection<'tcx> { fn relate<'a, 'gcx, R>(relation: &mut R, - a: &ty::ProjectionPredicate<'tcx>, - b: &ty::ProjectionPredicate<'tcx>) - -> RelateResult<'tcx, ty::ProjectionPredicate<'tcx>> + a: &ty::ExistentialProjection<'tcx>, + b: &ty::ExistentialProjection<'tcx>) + -> RelateResult<'tcx, ty::ExistentialProjection<'tcx>> where R: TypeRelation<'a, 'gcx, 'tcx>, 'gcx: 'a+'tcx, 'tcx: 'a { - let projection_ty = relation.relate(&a.projection_ty, &b.projection_ty)?; - let ty = relation.relate(&a.ty, &b.ty)?; - Ok(ty::ProjectionPredicate { projection_ty: projection_ty, ty: ty }) + if a.item_name != b.item_name { + Err(TypeError::ProjectionNameMismatched( + expected_found(relation, &a.item_name, &b.item_name))) + } else { + let trait_ref = relation.relate(&a.trait_ref, &b.trait_ref)?; + let ty = relation.relate(&a.ty, &b.ty)?; + Ok(ty::ExistentialProjection { + trait_ref: trait_ref, + item_name: a.item_name, + ty: ty + }) + } } } -impl<'tcx> Relate<'tcx> for Vec> { +impl<'tcx> Relate<'tcx> for Vec> { fn relate<'a, 'gcx, R>(relation: &mut R, - a: &Vec>, - b: &Vec>) - -> RelateResult<'tcx, Vec>> + a: &Vec>, + b: &Vec>) + -> RelateResult<'tcx, Vec>> where R: TypeRelation<'a, 'gcx, 'tcx>, 'gcx: 'a+'tcx, 'tcx: 'a { // To be compatible, `a` and `b` must be for precisely the @@ -361,27 +370,6 @@ impl<'tcx> Relate<'tcx> for Vec> { } } -impl<'tcx> Relate<'tcx> for ty::ExistentialBounds<'tcx> { - fn relate<'a, 'gcx, R>(relation: &mut R, - a: &ty::ExistentialBounds<'tcx>, - b: &ty::ExistentialBounds<'tcx>) - -> RelateResult<'tcx, ty::ExistentialBounds<'tcx>> - where R: TypeRelation<'a, 'gcx, 'tcx>, 'gcx: 'a+'tcx, 'tcx: 'a - { - let r = - relation.with_cause( - Cause::ExistentialRegionBound, - |relation| relation.relate_with_variance(ty::Contravariant, - &a.region_bound, - &b.region_bound))?; - let nb = relation.relate(&a.builtin_bounds, &b.builtin_bounds)?; - let pb = relation.relate(&a.projection_bounds, &b.projection_bounds)?; - Ok(ty::ExistentialBounds { region_bound: r, - builtin_bounds: nb, - projection_bounds: pb }) - } -} - impl<'tcx> Relate<'tcx> for ty::BuiltinBounds { fn relate<'a, 'gcx, R>(relation: &mut R, a: &ty::BuiltinBounds, @@ -416,6 +404,23 @@ impl<'tcx> Relate<'tcx> for ty::TraitRef<'tcx> { } } +impl<'tcx> Relate<'tcx> for ty::ExistentialTraitRef<'tcx> { + fn relate<'a, 'gcx, R>(relation: &mut R, + a: &ty::ExistentialTraitRef<'tcx>, + b: &ty::ExistentialTraitRef<'tcx>) + -> RelateResult<'tcx, ty::ExistentialTraitRef<'tcx>> + where R: TypeRelation<'a, 'gcx, 'tcx>, 'gcx: 'a+'tcx, 'tcx: 'a + { + // Different traits cannot be related + if a.def_id != b.def_id { + Err(TypeError::Traits(expected_found(relation, &a.def_id, &b.def_id))) + } else { + let substs = relate_item_substs(relation, a.def_id, a.substs, b.substs)?; + Ok(ty::ExistentialTraitRef { def_id: a.def_id, substs: substs }) + } + } +} + impl<'tcx> Relate<'tcx> for Ty<'tcx> { fn relate<'a, 'gcx, R>(relation: &mut R, a: &Ty<'tcx>, @@ -478,11 +483,23 @@ pub fn super_relate_tys<'a, 'gcx, 'tcx, R>(relation: &mut R, Ok(tcx.mk_enum(a_def, substs)) } - (&ty::TyTrait(ref a_), &ty::TyTrait(ref b_)) => + (&ty::TyTrait(ref a_obj), &ty::TyTrait(ref b_obj)) => { - let principal = relation.relate(&a_.principal, &b_.principal)?; - let bounds = relation.relate(&a_.bounds, &b_.bounds)?; - Ok(tcx.mk_trait(principal, bounds)) + let principal = relation.relate(&a_obj.principal, &b_obj.principal)?; + let r = + relation.with_cause( + Cause::ExistentialRegionBound, + |relation| relation.relate_with_variance(ty::Contravariant, + &a_obj.region_bound, + &b_obj.region_bound))?; + let nb = relation.relate(&a_obj.builtin_bounds, &b_obj.builtin_bounds)?; + let pb = relation.relate(&a_obj.projection_bounds, &b_obj.projection_bounds)?; + Ok(tcx.mk_trait(ty::TraitObject { + principal: principal, + region_bound: r, + builtin_bounds: nb, + projection_bounds: pb + })) } (&ty::TyStruct(a_def, a_substs), &ty::TyStruct(b_def, b_substs)) diff --git a/src/librustc/ty/structural_impls.rs b/src/librustc/ty/structural_impls.rs index b0f8e2e13f7e0..14005c1bd8b76 100644 --- a/src/librustc/ty/structural_impls.rs +++ b/src/librustc/ty/structural_impls.rs @@ -10,7 +10,7 @@ use infer::type_variable; use ty::subst::{self, VecPerParamSpace}; -use ty::{self, Lift, TraitRef, Ty, TyCtxt}; +use ty::{self, Lift, Ty, TyCtxt}; use ty::fold::{TypeFoldable, TypeFolder, TypeVisitor}; use std::rc::Rc; @@ -80,10 +80,20 @@ impl<'tcx> Lift<'tcx> for ty::Region { } } -impl<'a, 'tcx> Lift<'tcx> for TraitRef<'a> { - type Lifted = TraitRef<'tcx>; - fn lift_to_tcx<'b, 'gcx>(&self, tcx: TyCtxt<'b, 'gcx, 'tcx>) -> Option> { - tcx.lift(&self.substs).map(|substs| TraitRef { +impl<'a, 'tcx> Lift<'tcx> for ty::TraitRef<'a> { + type Lifted = ty::TraitRef<'tcx>; + fn lift_to_tcx<'b, 'gcx>(&self, tcx: TyCtxt<'b, 'gcx, 'tcx>) -> Option { + tcx.lift(&self.substs).map(|substs| ty::TraitRef { + def_id: self.def_id, + substs: substs + }) + } +} + +impl<'a, 'tcx> Lift<'tcx> for ty::ExistentialTraitRef<'a> { + type Lifted = ty::ExistentialTraitRef<'tcx>; + fn lift_to_tcx<'b, 'gcx>(&self, tcx: TyCtxt<'b, 'gcx, 'tcx>) -> Option { + tcx.lift(&self.substs).map(|substs| ty::ExistentialTraitRef { def_id: self.def_id, substs: substs }) @@ -141,6 +151,19 @@ impl<'a, 'tcx> Lift<'tcx> for ty::ProjectionPredicate<'a> { } } +impl<'a, 'tcx> Lift<'tcx> for ty::ExistentialProjection<'a> { + type Lifted = ty::ExistentialProjection<'tcx>; + fn lift_to_tcx<'b, 'gcx>(&self, tcx: TyCtxt<'b, 'gcx, 'tcx>) -> Option { + tcx.lift(&(self.trait_ref, self.ty)).map(|(trait_ref, ty)| { + ty::ExistentialProjection { + trait_ref: trait_ref, + item_name: self.item_name, + ty: ty + } + }) + } +} + impl<'a, 'tcx> Lift<'tcx> for ty::Predicate<'a> { type Lifted = ty::Predicate<'tcx>; fn lift_to_tcx<'b, 'gcx>(&self, tcx: TyCtxt<'b, 'gcx, 'tcx>) -> Option { @@ -437,16 +460,20 @@ impl<'tcx, T: TypeFoldable<'tcx>> TypeFoldable<'tcx> for VecPerParamSpace { } } -impl<'tcx> TypeFoldable<'tcx> for ty::TraitTy<'tcx> { +impl<'tcx> TypeFoldable<'tcx> for ty::TraitObject<'tcx> { fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) -> Self { - ty::TraitTy { + ty::TraitObject { principal: self.principal.fold_with(folder), - bounds: self.bounds.fold_with(folder), + region_bound: self.region_bound.fold_with(folder), + builtin_bounds: self.builtin_bounds, + projection_bounds: self.projection_bounds.fold_with(folder), } } fn super_visit_with>(&self, visitor: &mut V) -> bool { - self.principal.visit_with(visitor) || self.bounds.visit_with(visitor) + self.principal.visit_with(visitor) || + self.region_bound.visit_with(visitor) || + self.projection_bounds.visit_with(visitor) } } @@ -599,8 +626,17 @@ impl<'tcx> TypeFoldable<'tcx> for ty::TraitRef<'tcx> { } } - fn fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) -> Self { - folder.fold_trait_ref(self) + fn super_visit_with>(&self, visitor: &mut V) -> bool { + self.substs.visit_with(visitor) + } +} + +impl<'tcx> TypeFoldable<'tcx> for ty::ExistentialTraitRef<'tcx> { + fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) -> Self { + ty::ExistentialTraitRef { + def_id: self.def_id, + substs: self.substs.fold_with(folder), + } } fn super_visit_with>(&self, visitor: &mut V) -> bool { @@ -741,24 +777,6 @@ impl<'tcx> TypeFoldable<'tcx> for ty::BuiltinBounds { } } -impl<'tcx> TypeFoldable<'tcx> for ty::ExistentialBounds<'tcx> { - fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) -> Self { - ty::ExistentialBounds { - region_bound: self.region_bound.fold_with(folder), - builtin_bounds: self.builtin_bounds, - projection_bounds: self.projection_bounds.fold_with(folder), - } - } - - fn fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) -> Self { - folder.fold_existential_bounds(self) - } - - fn super_visit_with>(&self, visitor: &mut V) -> bool { - self.region_bound.visit_with(visitor) || self.projection_bounds.visit_with(visitor) - } -} - impl<'tcx> TypeFoldable<'tcx> for ty::TypeParameterDef<'tcx> { fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) -> Self { ty::TypeParameterDef { @@ -893,6 +911,20 @@ impl<'tcx> TypeFoldable<'tcx> for ty::ProjectionPredicate<'tcx> { } } +impl<'tcx> TypeFoldable<'tcx> for ty::ExistentialProjection<'tcx> { + fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) -> Self { + ty::ExistentialProjection { + trait_ref: self.trait_ref.fold_with(folder), + item_name: self.item_name, + ty: self.ty.fold_with(folder), + } + } + + fn super_visit_with>(&self, visitor: &mut V) -> bool { + self.trait_ref.visit_with(visitor) || self.ty.visit_with(visitor) + } +} + impl<'tcx> TypeFoldable<'tcx> for ty::ProjectionTy<'tcx> { fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) -> Self { ty::ProjectionTy { diff --git a/src/librustc/ty/sty.rs b/src/librustc/ty/sty.rs index 098943dfce29a..91214873f193d 100644 --- a/src/librustc/ty/sty.rs +++ b/src/librustc/ty/sty.rs @@ -152,7 +152,7 @@ pub enum TypeVariants<'tcx> { TyFnPtr(&'tcx BareFnTy<'tcx>), /// A trait, defined with `trait`. - TyTrait(Box>), + TyTrait(Box>), /// The anonymous type of a closure. Used to represent the type of /// `|a| a`. @@ -291,57 +291,11 @@ impl<'tcx> Decodable for ClosureSubsts<'tcx> { } #[derive(Clone, PartialEq, Eq, Hash)] -pub struct TraitTy<'tcx> { - pub principal: ty::PolyTraitRef<'tcx>, - pub bounds: ExistentialBounds<'tcx>, -} - -impl<'a, 'gcx, 'tcx> TraitTy<'tcx> { - pub fn principal_def_id(&self) -> DefId { - self.principal.0.def_id - } - - /// Object types don't have a self-type specified. Therefore, when - /// we convert the principal trait-ref into a normal trait-ref, - /// you must give *some* self-type. A common choice is `mk_err()` - /// or some skolemized type. - pub fn principal_trait_ref_with_self_ty(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>, - self_ty: Ty<'tcx>) - -> ty::PolyTraitRef<'tcx> - { - // otherwise the escaping regions would be captured by the binder - assert!(!self_ty.has_escaping_regions()); - - ty::Binder(TraitRef { - def_id: self.principal.0.def_id, - substs: tcx.mk_substs(self.principal.0.substs.with_self_ty(self_ty)), - }) - } - - pub fn projection_bounds_with_self_ty(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>, - self_ty: Ty<'tcx>) - -> Vec> - { - // otherwise the escaping regions would be captured by the binders - assert!(!self_ty.has_escaping_regions()); - - self.bounds.projection_bounds.iter() - .map(|in_poly_projection_predicate| { - let in_projection_ty = &in_poly_projection_predicate.0.projection_ty; - let substs = tcx.mk_substs(in_projection_ty.trait_ref.substs.with_self_ty(self_ty)); - let trait_ref = ty::TraitRef::new(in_projection_ty.trait_ref.def_id, - substs); - let projection_ty = ty::ProjectionTy { - trait_ref: trait_ref, - item_name: in_projection_ty.item_name - }; - ty::Binder(ty::ProjectionPredicate { - projection_ty: projection_ty, - ty: in_poly_projection_predicate.0.ty - }) - }) - .collect() - } +pub struct TraitObject<'tcx> { + pub principal: PolyExistentialTraitRef<'tcx>, + pub region_bound: ty::Region, + pub builtin_bounds: BuiltinBounds, + pub projection_bounds: Vec>, } /// A complete reference to a trait. These take numerous guises in syntax, @@ -392,6 +346,70 @@ impl<'tcx> PolyTraitRef<'tcx> { } } +/// An existential reference to a trait, where `Self` is erased. +/// For example, the trait object `Trait<'a, 'b, X, Y>` is: +/// +/// exists T. T: Trait<'a, 'b, X, Y> +/// +/// The substitutions don't include the erased `Self`, only trait +/// type and lifetime parameters (`[X, Y]` and `['a, 'b]` above). +#[derive(Copy, Clone, PartialEq, Eq, Hash)] +pub struct ExistentialTraitRef<'tcx> { + pub def_id: DefId, + pub substs: &'tcx Substs<'tcx>, +} + +impl<'a, 'gcx, 'tcx> ExistentialTraitRef<'tcx> { + pub fn erase_self_ty(tcx: TyCtxt<'a, 'gcx, 'tcx>, + trait_ref: ty::TraitRef<'tcx>) + -> ty::ExistentialTraitRef<'tcx> { + let mut substs = trait_ref.substs.clone(); + substs.types.pop(subst::SelfSpace); + ty::ExistentialTraitRef { + def_id: trait_ref.def_id, + substs: tcx.mk_substs(substs) + } + } + + pub fn input_types(&self) -> &[Ty<'tcx>] { + // Select only the "input types" from a trait-reference. For + // now this is all the types that appear in the + // trait-reference, but it should eventually exclude + // associated types. + self.substs.types.as_full_slice() + } +} + +pub type PolyExistentialTraitRef<'tcx> = Binder>; + +impl<'a, 'gcx, 'tcx> PolyExistentialTraitRef<'tcx> { + pub fn def_id(&self) -> DefId { + self.0.def_id + } + + pub fn input_types(&self) -> &[Ty<'tcx>] { + // FIXME(#20664) every use of this fn is probably a bug, it should yield Binder<> + self.0.input_types() + } + + /// Object types don't have a self-type specified. Therefore, when + /// we convert the principal trait-ref into a normal trait-ref, + /// you must give *some* self-type. A common choice is `mk_err()` + /// or some skolemized type. + pub fn with_self_ty(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>, + self_ty: Ty<'tcx>) + -> ty::PolyTraitRef<'tcx> + { + // otherwise the escaping regions would be captured by the binder + assert!(!self_ty.has_escaping_regions()); + + self.map_bound(|trait_ref| TraitRef { + def_id: trait_ref.def_id, + substs: tcx.mk_substs(trait_ref.substs.with_self_ty(self_ty)), + }) + } +} + /// Binder is a binder for higher-ranked lifetimes. It is part of the /// compiler's representation for things like `for<'a> Fn(&'a isize)` /// (which would be represented by the type `PolyTraitRef == @@ -730,27 +748,40 @@ pub enum InferTy { FreshFloatTy(u32) } -/// Bounds suitable for an existentially quantified type parameter -/// such as those that appear in object types or closure types. -#[derive(PartialEq, Eq, Hash, Clone)] -pub struct ExistentialBounds<'tcx> { - pub region_bound: ty::Region, - pub builtin_bounds: BuiltinBounds, - pub projection_bounds: Vec>, +/// A `ProjectionPredicate` for an `ExistentialTraitRef`. +#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)] +pub struct ExistentialProjection<'tcx> { + pub trait_ref: ExistentialTraitRef<'tcx>, + pub item_name: Name, + pub ty: Ty<'tcx> } -impl<'tcx> ExistentialBounds<'tcx> { - pub fn new(region_bound: ty::Region, - builtin_bounds: BuiltinBounds, - projection_bounds: Vec>) - -> Self { - let mut projection_bounds = projection_bounds; - projection_bounds.sort_by(|a, b| a.sort_key().cmp(&b.sort_key())); - ExistentialBounds { - region_bound: region_bound, - builtin_bounds: builtin_bounds, - projection_bounds: projection_bounds - } +pub type PolyExistentialProjection<'tcx> = Binder>; + +impl<'a, 'tcx, 'gcx> PolyExistentialProjection<'tcx> { + pub fn item_name(&self) -> Name { + self.0.item_name // safe to skip the binder to access a name + } + + pub fn sort_key(&self) -> (DefId, Name) { + (self.0.trait_ref.def_id, self.0.item_name) + } + + pub fn with_self_ty(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>, + self_ty: Ty<'tcx>) + -> ty::PolyProjectionPredicate<'tcx> + { + // otherwise the escaping regions would be captured by the binders + assert!(!self_ty.has_escaping_regions()); + + let trait_ref = self.map_bound(|proj| proj.trait_ref); + self.map_bound(|proj| ty::ProjectionPredicate { + projection_ty: ty::ProjectionTy { + trait_ref: trait_ref.with_self_ty(tcx, self_ty).0, + item_name: proj.item_name + }, + ty: proj.ty + }) } } @@ -1185,7 +1216,7 @@ impl<'a, 'gcx, 'tcx> TyS<'tcx> { pub fn ty_to_def_id(&self) -> Option { match self.sty { - TyTrait(ref tt) => Some(tt.principal_def_id()), + TyTrait(ref tt) => Some(tt.principal.def_id()), TyStruct(def, _) | TyEnum(def, _) => Some(def.did), TyClosure(id, _) => Some(id), @@ -1209,9 +1240,8 @@ impl<'a, 'gcx, 'tcx> TyS<'tcx> { vec![*region] } TyTrait(ref obj) => { - let mut v = vec![obj.bounds.region_bound]; - v.extend_from_slice(obj.principal.skip_binder() - .substs.regions.as_full_slice()); + let mut v = vec![obj.region_bound]; + v.extend_from_slice(obj.principal.skip_binder().substs.regions.as_full_slice()); v } TyEnum(_, substs) | diff --git a/src/librustc/ty/util.rs b/src/librustc/ty/util.rs index d7bb8ff2995aa..3c1f6e9199220 100644 --- a/src/librustc/ty/util.rs +++ b/src/librustc/ty/util.rs @@ -451,21 +451,21 @@ impl<'a, 'gcx, 'tcx> TypeVisitor<'tcx> for TypeIdHasher<'a, 'gcx, 'tcx> { // to sort them again by the name, in string form. // Hash the whole principal trait ref. - self.def_id(data.principal_def_id()); + self.def_id(data.principal.def_id()); data.principal.visit_with(self); // Hash region and builtin bounds. - data.bounds.region_bound.visit_with(self); - self.hash(data.bounds.builtin_bounds); + data.region_bound.visit_with(self); + self.hash(data.builtin_bounds); // Only projection bounds are left, sort and hash them. - let mut projection_bounds: Vec<_> = data.bounds.projection_bounds + let mut projection_bounds: Vec<_> = data.projection_bounds .iter() .map(|b| (b.item_name().as_str(), b)) .collect(); projection_bounds.sort_by_key(|&(ref name, _)| name.clone()); for (name, bound) in projection_bounds { - self.def_id(bound.0.projection_ty.trait_ref.def_id); + self.def_id(bound.0.trait_ref.def_id); self.hash(name); bound.visit_with(self); } diff --git a/src/librustc/ty/walk.rs b/src/librustc/ty/walk.rs index 3f87d80e337dd..3bf539245571e 100644 --- a/src/librustc/ty/walk.rs +++ b/src/librustc/ty/walk.rs @@ -81,9 +81,9 @@ fn push_subtypes<'tcx>(stack: &mut Vec>, parent_ty: Ty<'tcx>) { ty::TyProjection(ref data) => { push_reversed(stack, data.trait_ref.substs.types.as_full_slice()); } - ty::TyTrait(box ty::TraitTy { ref principal, ref bounds }) => { - push_reversed(stack, principal.substs().types.as_full_slice()); - push_reversed(stack, &bounds.projection_bounds.iter().map(|pred| { + ty::TyTrait(ref obj) => { + push_reversed(stack, obj.principal.input_types()); + push_reversed(stack, &obj.projection_bounds.iter().map(|pred| { pred.0.ty }).collect::>()); } diff --git a/src/librustc/ty/wf.rs b/src/librustc/ty/wf.rs index 009e3e2433431..77d0835bf6bc1 100644 --- a/src/librustc/ty/wf.rs +++ b/src/librustc/ty/wf.rs @@ -406,13 +406,13 @@ impl<'a, 'gcx, 'tcx> WfPredicates<'a, 'gcx, 'tcx> { // FIXME(#33243): remove RFC1592 self.out.push(traits::Obligation::new( cause.clone(), - ty::Predicate::ObjectSafe(data.principal_def_id()) + ty::Predicate::ObjectSafe(data.principal.def_id()) )); let component_traits = - data.bounds.builtin_bounds.iter().flat_map(|bound| { + data.builtin_bounds.iter().flat_map(|bound| { tcx.lang_items.from_builtin_kind(bound).ok() }); -// .chain(Some(data.principal_def_id())); +// .chain(Some(data.principal.def_id())); self.out.extend( component_traits.map(|did| { traits::Obligation::new( cause.clone(), @@ -476,7 +476,7 @@ impl<'a, 'gcx, 'tcx> WfPredicates<'a, 'gcx, 'tcx> { .collect() } - fn from_object_ty(&mut self, ty: Ty<'tcx>, data: &ty::TraitTy<'tcx>) { + fn from_object_ty(&mut self, ty: Ty<'tcx>, data: &ty::TraitObject<'tcx>) { // Imagine a type like this: // // trait Foo { } @@ -512,10 +512,10 @@ impl<'a, 'gcx, 'tcx> WfPredicates<'a, 'gcx, 'tcx> { if !data.has_escaping_regions() { let implicit_bounds = object_region_bounds(self.infcx.tcx, - &data.principal, - data.bounds.builtin_bounds); + data.principal, + data.builtin_bounds); - let explicit_bound = data.bounds.region_bound; + let explicit_bound = data.region_bound; for implicit_bound in implicit_bounds { let cause = self.cause(traits::ReferenceOutlivesReferent(ty)); @@ -534,7 +534,7 @@ impl<'a, 'gcx, 'tcx> WfPredicates<'a, 'gcx, 'tcx> { /// `ty::required_region_bounds`, see that for more information. pub fn object_region_bounds<'a, 'gcx, 'tcx>( tcx: TyCtxt<'a, 'gcx, 'tcx>, - principal: &ty::PolyTraitRef<'tcx>, + principal: ty::PolyExistentialTraitRef<'tcx>, others: ty::BuiltinBounds) -> Vec { @@ -543,13 +543,8 @@ pub fn object_region_bounds<'a, 'gcx, 'tcx>( // a skolemized type. let open_ty = tcx.mk_infer(ty::FreshTy(0)); - // Note that we preserve the overall binding levels here. - assert!(!open_ty.has_escaping_regions()); - let substs = tcx.mk_substs(principal.0.substs.with_self_ty(open_ty)); - let trait_refs = vec!(ty::Binder(ty::TraitRef::new(principal.0.def_id, substs))); - let mut predicates = others.to_predicates(tcx, open_ty); - predicates.extend(trait_refs.iter().map(|t| t.to_predicate())); + predicates.push(principal.with_self_ty(tcx, open_ty).to_predicate()); tcx.required_region_bounds(open_ty, predicates) } diff --git a/src/librustc/util/ppaux.rs b/src/librustc/util/ppaux.rs index 37750b568bba2..fb0b6413fab40 100644 --- a/src/librustc/util/ppaux.rs +++ b/src/librustc/util/ppaux.rs @@ -288,7 +288,8 @@ fn in_binder<'a, 'gcx, 'tcx, T, U>(f: &mut fmt::Formatter, /// projection bounds, so we just stuff them altogether. But in /// reality we should eventually sort things out better. #[derive(Clone, Debug)] -struct TraitAndProjections<'tcx>(ty::TraitRef<'tcx>, Vec>); +struct TraitAndProjections<'tcx>(ty::ExistentialTraitRef<'tcx>, + Vec>); impl<'tcx> TypeFoldable<'tcx> for TraitAndProjections<'tcx> { fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) -> Self { @@ -311,24 +312,24 @@ impl<'tcx> fmt::Display for TraitAndProjections<'tcx> { } } -impl<'tcx> fmt::Display for ty::TraitTy<'tcx> { +impl<'tcx> fmt::Display for ty::TraitObject<'tcx> { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - let bounds = &self.bounds; - // Generate the main trait ref, including associated types. ty::tls::with(|tcx| { let principal = tcx.lift(&self.principal.0) .expect("could not lift TraitRef for printing"); - let projections = tcx.lift(&bounds.projection_bounds[..]) - .expect("could not lift projections for printing"); - let projections = projections.into_iter().map(|p| p.0).collect(); + let projections = self.projection_bounds.iter().map(|p| { + let projection = tcx.lift(p) + .expect("could not lift projection for printing"); + projection.with_self_ty(tcx, tcx.types.err).0 + }).collect(); let tap = ty::Binder(TraitAndProjections(principal, projections)); in_binder(f, tcx, &ty::Binder(""), Some(tap)) })?; // Builtin bounds. - for bound in &bounds.builtin_bounds { + for bound in &self.builtin_bounds { write!(f, " + {:?}", bound)?; } @@ -337,7 +338,7 @@ impl<'tcx> fmt::Display for ty::TraitTy<'tcx> { // use thread-local data of some kind? There are also // advantages to just showing the region, since it makes // people aware that it's there. - let bound = bounds.region_bound.to_string(); + let bound = self.region_bound.to_string(); if !bound.is_empty() { write!(f, " + {}", bound)?; } @@ -397,10 +398,13 @@ impl<'tcx> fmt::Debug for ty::TraitRef<'tcx> { // when printing out the debug representation, we don't need // to enumerate the `for<...>` etc because the debruijn index // tells you everything you need to know. - match self.substs.self_ty() { - None => write!(f, "{}", *self), - Some(self_ty) => write!(f, "<{:?} as {}>", self_ty, *self) - } + write!(f, "<{:?} as {}>", self.self_ty(), *self) + } +} + +impl<'tcx> fmt::Debug for ty::ExistentialTraitRef<'tcx> { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "{}", *self) } } @@ -448,11 +452,38 @@ impl<'tcx> fmt::Debug for ty::adjustment::AutoDerefRef<'tcx> { } } -impl<'tcx> fmt::Debug for ty::TraitTy<'tcx> { +impl<'tcx> fmt::Debug for ty::TraitObject<'tcx> { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!(f, "TraitTy({:?},{:?})", - self.principal, - self.bounds) + let mut empty = true; + let mut maybe_continue = |f: &mut fmt::Formatter| { + if empty { + empty = false; + Ok(()) + } else { + write!(f, " + ") + } + }; + + maybe_continue(f)?; + write!(f, "{:?}", self.principal)?; + + let region_str = format!("{:?}", self.region_bound); + if !region_str.is_empty() { + maybe_continue(f)?; + write!(f, "{}", region_str)?; + } + + for bound in &self.builtin_bounds { + maybe_continue(f)?; + write!(f, "{:?}", bound)?; + } + + for projection_bound in &self.projection_bounds { + maybe_continue(f)?; + write!(f, "{:?}", projection_bound)?; + } + + Ok(()) } } @@ -668,38 +699,6 @@ impl<'tcx> fmt::Display for ty::FnSig<'tcx> { } } -impl<'tcx> fmt::Debug for ty::ExistentialBounds<'tcx> { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - let mut empty = true; - let mut maybe_continue = |f: &mut fmt::Formatter| { - if empty { - empty = false; - Ok(()) - } else { - write!(f, " + ") - } - }; - - let region_str = format!("{:?}", self.region_bound); - if !region_str.is_empty() { - maybe_continue(f)?; - write!(f, "{}", region_str)?; - } - - for bound in &self.builtin_bounds { - maybe_continue(f)?; - write!(f, "{:?}", bound)?; - } - - for projection_bound in &self.projection_bounds { - maybe_continue(f)?; - write!(f, "{:?}", projection_bound)?; - } - - Ok(()) - } -} - impl fmt::Display for ty::BuiltinBounds { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { let mut bounds = self.iter(); @@ -819,6 +818,13 @@ impl<'tcx> fmt::Display for ty::TraitRef<'tcx> { } } +impl<'tcx> fmt::Display for ty::ExistentialTraitRef<'tcx> { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + parameterized(f, self.substs, self.def_id, Ns::Type, &[], + |tcx| Some(tcx.lookup_trait_def(self.def_id).generics.clone())) + } +} + impl<'tcx> fmt::Display for ty::TypeVariants<'tcx> { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match *self { diff --git a/src/librustc_metadata/astencode.rs b/src/librustc_metadata/astencode.rs index b8e66530ea153..c552e612504e9 100644 --- a/src/librustc_metadata/astencode.rs +++ b/src/librustc_metadata/astencode.rs @@ -524,16 +524,8 @@ pub fn encode_cast_kind(ebml_w: &mut Encoder, kind: cast::CastKind) { trait rbml_writer_helpers<'tcx> { fn emit_region(&mut self, ecx: &e::EncodeContext, r: ty::Region); fn emit_ty<'a>(&mut self, ecx: &e::EncodeContext<'a, 'tcx>, ty: Ty<'tcx>); - fn emit_tys<'a>(&mut self, ecx: &e::EncodeContext<'a, 'tcx>, tys: &[Ty<'tcx>]); - fn emit_predicate<'a>(&mut self, ecx: &e::EncodeContext<'a, 'tcx>, - predicate: &ty::Predicate<'tcx>); - fn emit_trait_ref<'a>(&mut self, ecx: &e::EncodeContext<'a, 'tcx>, - ty: &ty::TraitRef<'tcx>); fn emit_substs<'a>(&mut self, ecx: &e::EncodeContext<'a, 'tcx>, substs: &subst::Substs<'tcx>); - fn emit_existential_bounds<'b>(&mut self, ecx: &e::EncodeContext<'b,'tcx>, - bounds: &ty::ExistentialBounds<'tcx>); - fn emit_builtin_bounds(&mut self, ecx: &e::EncodeContext, bounds: &ty::BuiltinBounds); fn emit_upvar_capture(&mut self, ecx: &e::EncodeContext, capture: &ty::UpvarCapture); fn emit_auto_adjustment<'a>(&mut self, ecx: &e::EncodeContext<'a, 'tcx>, adj: &adjustment::AutoAdjustment<'tcx>); @@ -556,39 +548,6 @@ impl<'a, 'tcx> rbml_writer_helpers<'tcx> for Encoder<'a> { ty))); } - fn emit_tys<'b>(&mut self, ecx: &e::EncodeContext<'b, 'tcx>, tys: &[Ty<'tcx>]) { - self.emit_from_vec(tys, |this, ty| Ok(this.emit_ty(ecx, *ty))); - } - - fn emit_trait_ref<'b>(&mut self, ecx: &e::EncodeContext<'b, 'tcx>, - trait_ref: &ty::TraitRef<'tcx>) { - self.emit_opaque(|this| Ok(tyencode::enc_trait_ref(&mut this.cursor, - &ecx.ty_str_ctxt(), - *trait_ref))); - } - - fn emit_predicate<'b>(&mut self, ecx: &e::EncodeContext<'b, 'tcx>, - predicate: &ty::Predicate<'tcx>) { - self.emit_opaque(|this| { - Ok(tyencode::enc_predicate(&mut this.cursor, - &ecx.ty_str_ctxt(), - predicate)) - }); - } - - fn emit_existential_bounds<'b>(&mut self, ecx: &e::EncodeContext<'b,'tcx>, - bounds: &ty::ExistentialBounds<'tcx>) { - self.emit_opaque(|this| Ok(tyencode::enc_existential_bounds(&mut this.cursor, - &ecx.ty_str_ctxt(), - bounds))); - } - - fn emit_builtin_bounds(&mut self, ecx: &e::EncodeContext, bounds: &ty::BuiltinBounds) { - self.emit_opaque(|this| Ok(tyencode::enc_builtin_bounds(&mut this.cursor, - &ecx.ty_str_ctxt(), - bounds))); - } - fn emit_upvar_capture(&mut self, ecx: &e::EncodeContext, capture: &ty::UpvarCapture) { use rustc_serialize::Encoder; @@ -879,8 +838,6 @@ trait rbml_decoder_decoder_helpers<'tcx> { -> ty::PolyTraitRef<'tcx>; fn read_predicate<'a, 'b>(&mut self, dcx: &DecodeContext<'a, 'b, 'tcx>) -> ty::Predicate<'tcx>; - fn read_existential_bounds<'a, 'b>(&mut self, dcx: &DecodeContext<'a, 'b, 'tcx>) - -> ty::ExistentialBounds<'tcx>; fn read_substs<'a, 'b>(&mut self, dcx: &DecodeContext<'a, 'b, 'tcx>) -> subst::Substs<'tcx>; fn read_upvar_capture(&mut self, dcx: &DecodeContext) @@ -988,12 +945,6 @@ impl<'a, 'tcx> rbml_decoder_decoder_helpers<'tcx> for reader::Decoder<'a> { self.read_ty_encoded(dcx, |decoder| decoder.parse_predicate()) } - fn read_existential_bounds<'b, 'c>(&mut self, dcx: &DecodeContext<'b, 'c, 'tcx>) - -> ty::ExistentialBounds<'tcx> - { - self.read_ty_encoded(dcx, |decoder| decoder.parse_existential_bounds()) - } - fn read_substs<'b, 'c>(&mut self, dcx: &DecodeContext<'b, 'c, 'tcx>) -> subst::Substs<'tcx> { self.read_opaque(|_, doc| { diff --git a/src/librustc_metadata/tydecode.rs b/src/librustc_metadata/tydecode.rs index 7b4919bb4773b..11c155cbd5b9f 100644 --- a/src/librustc_metadata/tydecode.rs +++ b/src/librustc_metadata/tydecode.rs @@ -307,6 +307,12 @@ impl<'a,'tcx> TyDecoder<'a,'tcx> { ty::TraitRef {def_id: def, substs: substs} } + pub fn parse_existential_trait_ref(&mut self) -> ty::ExistentialTraitRef<'tcx> { + let def = self.parse_def(); + let substs = self.tcx.mk_substs(self.parse_substs()); + ty::ExistentialTraitRef {def_id: def, substs: substs} + } + pub fn parse_ty(&mut self) -> Ty<'tcx> { let tcx = self.tcx; match self.next() { @@ -340,10 +346,30 @@ impl<'a,'tcx> TyDecoder<'a,'tcx> { } 'x' => { assert_eq!(self.next(), '['); - let trait_ref = ty::Binder(self.parse_trait_ref()); - let bounds = self.parse_existential_bounds(); + let trait_ref = ty::Binder(self.parse_existential_trait_ref()); + let builtin_bounds = self.parse_builtin_bounds(); + let region_bound = self.parse_region(); + let mut projection_bounds = Vec::new(); + + loop { + match self.next() { + 'P' => { + let bound = self.parse_existential_projection(); + projection_bounds.push(ty::Binder(bound)); + } + '.' => { break; } + c => { + bug!("parse_bounds: bad bounds ('{}')", c) + } + } + } assert_eq!(self.next(), ']'); - return tcx.mk_trait(trait_ref, bounds); + return tcx.mk_trait(ty::TraitObject { + principal: trait_ref, + region_bound: region_bound, + builtin_bounds: builtin_bounds, + projection_bounds: projection_bounds + }); } 'p' => { assert_eq!(self.next(), '['); @@ -588,6 +614,14 @@ impl<'a,'tcx> TyDecoder<'a,'tcx> { } } + fn parse_existential_projection(&mut self) -> ty::ExistentialProjection<'tcx> { + ty::ExistentialProjection { + trait_ref: self.parse_existential_trait_ref(), + item_name: token::intern(&self.parse_str('|')), + ty: self.parse_ty(), + } + } + pub fn parse_type_param_def(&mut self) -> ty::TypeParameterDef<'tcx> { let name = self.parse_name(':'); let def_id = self.parse_def(); @@ -649,27 +683,6 @@ impl<'a,'tcx> TyDecoder<'a,'tcx> { } } - pub fn parse_existential_bounds(&mut self) -> ty::ExistentialBounds<'tcx> { - let builtin_bounds = self.parse_builtin_bounds(); - let region_bound = self.parse_region(); - let mut projection_bounds = Vec::new(); - - loop { - match self.next() { - 'P' => { - projection_bounds.push(ty::Binder(self.parse_projection_predicate())); - } - '.' => { break; } - c => { - bug!("parse_bounds: bad bounds ('{}')", c) - } - } - } - - ty::ExistentialBounds::new( - region_bound, builtin_bounds, projection_bounds) - } - fn parse_builtin_bounds(&mut self) -> ty::BuiltinBounds { let mut builtin_bounds = ty::BuiltinBounds::empty(); loop { diff --git a/src/librustc_metadata/tyencode.rs b/src/librustc_metadata/tyencode.rs index 15bafcdd3c99e..8deb1eb6ac31d 100644 --- a/src/librustc_metadata/tyencode.rs +++ b/src/librustc_metadata/tyencode.rs @@ -104,11 +104,26 @@ pub fn enc_ty<'a, 'tcx>(w: &mut Cursor>, cx: &ctxt<'a, 'tcx>, t: Ty<'tcx enc_substs(w, cx, substs); write!(w, "]"); } - ty::TyTrait(box ty::TraitTy { ref principal, - ref bounds }) => { + ty::TyTrait(ref obj) => { write!(w, "x["); - enc_trait_ref(w, cx, principal.0); - enc_existential_bounds(w, cx, bounds); + enc_existential_trait_ref(w, cx, obj.principal.0); + enc_builtin_bounds(w, cx, &obj.builtin_bounds); + + enc_region(w, cx, obj.region_bound); + + // Encode projection_bounds in a stable order + let mut projection_bounds: Vec<_> = obj.projection_bounds + .iter() + .map(|b| (b.item_name().as_str(), b)) + .collect(); + projection_bounds.sort_by_key(|&(ref name, _)| name.clone()); + + for tp in projection_bounds.iter().map(|&(_, tp)| tp) { + write!(w, "P"); + enc_existential_projection(w, cx, &tp.0); + } + + write!(w, "."); write!(w, "]"); } ty::TyTuple(ts) => { @@ -344,6 +359,12 @@ pub fn enc_trait_ref<'a, 'tcx>(w: &mut Cursor>, cx: &ctxt<'a, 'tcx>, enc_substs(w, cx, s.substs); } +fn enc_existential_trait_ref<'a, 'tcx>(w: &mut Cursor>, cx: &ctxt<'a, 'tcx>, + s: ty::ExistentialTraitRef<'tcx>) { + write!(w, "{}|", (cx.ds)(cx.tcx, s.def_id)); + enc_substs(w, cx, s.substs); +} + fn enc_unsafety(w: &mut Cursor>, p: hir::Unsafety) { match p { hir::Unsafety::Normal => write!(w, "n"), @@ -386,7 +407,7 @@ fn enc_fn_sig<'a, 'tcx>(w: &mut Cursor>, cx: &ctxt<'a, 'tcx>, enc_ty(w, cx, fsig.0.output); } -pub fn enc_builtin_bounds(w: &mut Cursor>, _cx: &ctxt, bs: &ty::BuiltinBounds) { +fn enc_builtin_bounds(w: &mut Cursor>, _cx: &ctxt, bs: &ty::BuiltinBounds) { for bound in bs { match bound { ty::BoundSend => write!(w, "S"), @@ -399,28 +420,6 @@ pub fn enc_builtin_bounds(w: &mut Cursor>, _cx: &ctxt, bs: &ty::BuiltinB write!(w, "."); } -pub fn enc_existential_bounds<'a,'tcx>(w: &mut Cursor>, - cx: &ctxt<'a,'tcx>, - bs: &ty::ExistentialBounds<'tcx>) { - enc_builtin_bounds(w, cx, &bs.builtin_bounds); - - enc_region(w, cx, bs.region_bound); - - // Encode projection_bounds in a stable order - let mut projection_bounds: Vec<_> = bs.projection_bounds - .iter() - .map(|b| (b.item_name().as_str(), b)) - .collect(); - projection_bounds.sort_by_key(|&(ref name, _)| name.clone()); - - for tp in projection_bounds.iter().map(|&(_, tp)| tp) { - write!(w, "P"); - enc_projection_predicate(w, cx, &tp.0); - } - - write!(w, "."); -} - pub fn enc_type_param_def<'a, 'tcx>(w: &mut Cursor>, cx: &ctxt<'a, 'tcx>, v: &ty::TypeParameterDef<'tcx>) { write!(w, "{}:{}|{}|{}|{}|", @@ -489,7 +488,9 @@ pub fn enc_predicate<'a, 'tcx>(w: &mut Cursor>, } ty::Predicate::Projection(ty::Binder(ref data)) => { write!(w, "p"); - enc_projection_predicate(w, cx, data); + enc_trait_ref(w, cx, data.projection_ty.trait_ref); + write!(w, "{}|", data.projection_ty.item_name); + enc_ty(w, cx, data.ty); } ty::Predicate::WellFormed(data) => { write!(w, "w"); @@ -509,10 +510,10 @@ pub fn enc_predicate<'a, 'tcx>(w: &mut Cursor>, } } -fn enc_projection_predicate<'a, 'tcx>(w: &mut Cursor>, - cx: &ctxt<'a, 'tcx>, - data: &ty::ProjectionPredicate<'tcx>) { - enc_trait_ref(w, cx, data.projection_ty.trait_ref); - write!(w, "{}|", data.projection_ty.item_name); +fn enc_existential_projection<'a, 'tcx>(w: &mut Cursor>, + cx: &ctxt<'a, 'tcx>, + data: &ty::ExistentialProjection<'tcx>) { + enc_existential_trait_ref(w, cx, data.trait_ref); + write!(w, "{}|", data.item_name); enc_ty(w, cx, data.ty); } diff --git a/src/librustc_trans/base.rs b/src/librustc_trans/base.rs index 0dcac188bb024..749a7495421ed 100644 --- a/src/librustc_trans/base.rs +++ b/src/librustc_trans/base.rs @@ -562,14 +562,9 @@ pub fn unsized_info<'ccx, 'tcx>(ccx: &CrateContext<'ccx, 'tcx>, // change to the vtable. old_info.expect("unsized_info: missing old info for trait upcast") } - (_, &ty::TyTrait(box ty::TraitTy { ref principal, .. })) => { - // Note that we preserve binding levels here: - let substs = principal.0.substs.with_self_ty(source).erase_regions(); - let substs = ccx.tcx().mk_substs(substs); - let trait_ref = ty::Binder(ty::TraitRef { - def_id: principal.def_id(), - substs: substs, - }); + (_, &ty::TyTrait(ref data)) => { + let trait_ref = data.principal.with_self_ty(ccx.tcx(), source); + let trait_ref = ccx.tcx().erase_regions(&trait_ref); consts::ptrcast(meth::get_vtable(ccx, trait_ref), Type::vtable_ptr(ccx)) } diff --git a/src/librustc_trans/collector.rs b/src/librustc_trans/collector.rs index ffacbae1afd6f..277110347d01d 100644 --- a/src/librustc_trans/collector.rs +++ b/src/librustc_trans/collector.rs @@ -1055,8 +1055,7 @@ fn create_trans_items_for_vtable_methods<'a, 'tcx>(scx: &SharedCrateContext<'a, assert!(!trait_ty.needs_subst() && !impl_ty.needs_subst()); if let ty::TyTrait(ref trait_ty) = trait_ty.sty { - let poly_trait_ref = trait_ty.principal_trait_ref_with_self_ty(scx.tcx(), - impl_ty); + let poly_trait_ref = trait_ty.principal.with_self_ty(scx.tcx(), impl_ty); // Walk all methods of the trait, including those of its supertraits for trait_ref in traits::supertraits(scx.tcx(), poly_trait_ref) { diff --git a/src/librustc_trans/debuginfo/metadata.rs b/src/librustc_trans/debuginfo/metadata.rs index 3fe8b2b66791a..6a99f12b2788c 100644 --- a/src/librustc_trans/debuginfo/metadata.rs +++ b/src/librustc_trans/debuginfo/metadata.rs @@ -627,7 +627,7 @@ fn trait_pointer_metadata<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, // But it does not describe the trait's methods. let def_id = match trait_type.sty { - ty::TyTrait(ref data) => data.principal_def_id(), + ty::TyTrait(ref data) => data.principal.def_id(), _ => { bug!("debuginfo: Unexpected trait-object type in \ trait_pointer_metadata(): {:?}", diff --git a/src/librustc_trans/trans_item.rs b/src/librustc_trans/trans_item.rs index c1149279b4ddd..2dd07cf440553 100644 --- a/src/librustc_trans/trans_item.rs +++ b/src/librustc_trans/trans_item.rs @@ -476,10 +476,10 @@ pub fn push_unique_type_name<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, output.push(']'); }, ty::TyTrait(ref trait_data) => { - push_item_name(tcx, trait_data.principal.skip_binder().def_id, output); + push_item_name(tcx, trait_data.principal.def_id(), output); push_type_params(tcx, &trait_data.principal.skip_binder().substs.types, - &trait_data.bounds.projection_bounds, + &trait_data.projection_bounds, output); }, ty::TyFnDef(_, _, &ty::BareFnTy{ unsafety, abi, ref sig } ) | @@ -562,7 +562,7 @@ fn push_item_name(tcx: TyCtxt, fn push_type_params<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, types: &'tcx subst::VecPerParamSpace>, - projections: &[ty::PolyProjectionPredicate<'tcx>], + projections: &[ty::PolyExistentialProjection<'tcx>], output: &mut String) { if types.is_empty() && projections.is_empty() { return; @@ -577,7 +577,7 @@ fn push_type_params<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, for projection in projections { let projection = projection.skip_binder(); - let name = &projection.projection_ty.item_name.as_str(); + let name = &projection.item_name.as_str(); output.push_str(name); output.push_str("="); push_unique_type_name(tcx, projection.ty, output); diff --git a/src/librustc_typeck/astconv.rs b/src/librustc_typeck/astconv.rs index ea7b447632c07..ed4ea3c937b90 100644 --- a/src/librustc_typeck/astconv.rs +++ b/src/librustc_typeck/astconv.rs @@ -169,6 +169,11 @@ struct ConvertedBinding<'tcx> { type TraitAndProjections<'tcx> = (ty::PolyTraitRef<'tcx>, Vec>); +/// Dummy type used for the `Self` of a `TraitRef` created for converting +/// a trait object, and which gets removed in `ExistentialTraitRef`. +/// This type must not appear anywhere in other converted types. +const TRAIT_OBJECT_DUMMY_SELF: ty::TypeVariants<'static> = ty::TyInfer(ty::FreshTy(0)); + pub fn ast_region_to_region(tcx: TyCtxt, lifetime: &hir::Lifetime) -> ty::Region { let r = match tcx.named_region_map.defs.get(&lifetime.id) { @@ -478,48 +483,37 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o { type_substs.len() <= formal_ty_param_count); let mut substs = region_substs; - substs.types.extend(TypeSpace, type_substs.into_iter()); - match self_ty { - None => { - // If no self-type is provided, it's still possible that - // one was declared, because this could be an object type. - } - Some(ty) => { - // If a self-type is provided, one should have been - // "declared" (in other words, this should be a - // trait-ref). - assert!(decl_generics.types.get_self().is_some()); - substs.types.push(SelfSpace, ty); - } - } + // If a self-type was declared, one should be provided. + assert_eq!(decl_generics.types.get_self().is_some(), self_ty.is_some()); + substs.types.extend(SelfSpace, self_ty.into_iter()); + substs.types.extend(TypeSpace, type_substs.into_iter()); + let is_object = self_ty.map_or(false, |ty| ty.sty == TRAIT_OBJECT_DUMMY_SELF); let actual_supplied_ty_param_count = substs.types.len(TypeSpace); for param in &ty_param_defs[actual_supplied_ty_param_count..] { - if let Some(default) = param.default { + let default = if let Some(default) = param.default { // If we are converting an object type, then the // `Self` parameter is unknown. However, some of the // other type parameters may reference `Self` in their // defaults. This will lead to an ICE if we are not // careful! - if self_ty.is_none() && default.has_self_ty() { + if is_object && default.has_self_ty() { span_err!(tcx.sess, span, E0393, "the type parameter `{}` must be explicitly specified \ in an object type because its default value `{}` references \ the type `Self`", param.name, default); - substs.types.push(TypeSpace, tcx.types.err); + tcx.types.err } else { // This is a default type parameter. - let default = default.subst_spanned(tcx, - &substs, - Some(span)); - substs.types.push(TypeSpace, default); + default.subst_spanned(tcx, &substs, Some(span)) } } else { span_bug!(span, "extra parameter without default"); - } + }; + substs.types.push(TypeSpace, default); } debug!("create_substs_for_ast_path(decl_generics={:?}, self_ty={:?}) -> {:?}", @@ -539,11 +533,12 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o { self_ty: Option>) -> Vec> { + let is_object = self_ty.map_or(false, |ty| ty.sty == TRAIT_OBJECT_DUMMY_SELF); let use_default = |p: &ty::TypeParameterDef<'tcx>| { if let Some(ref default) = p.default { - if self_ty.is_none() && default.has_self_ty() { + if is_object && default.has_self_ty() { // There is no suitable inference default for a type parameter - // that references self with no self-type provided. + // that references self, in an object type. return false; } } @@ -709,7 +704,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o { pub fn instantiate_poly_trait_ref(&self, rscope: &RegionScope, ast_trait_ref: &hir::PolyTraitRef, - self_ty: Option>, + self_ty: Ty<'tcx>, poly_projections: &mut Vec>) -> ty::PolyTraitRef<'tcx> { @@ -734,7 +729,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o { pub fn instantiate_mono_trait_ref(&self, rscope: &RegionScope, trait_ref: &hir::TraitRef, - self_ty: Option>) + self_ty: Ty<'tcx>) -> ty::TraitRef<'tcx> { let trait_def_id = self.trait_def_id(trait_ref); @@ -760,32 +755,12 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o { } } - fn object_path_to_poly_trait_ref(&self, - rscope: &RegionScope, - span: Span, - param_mode: PathParamMode, - trait_def_id: DefId, - trait_path_ref_id: ast::NodeId, - trait_segment: &hir::PathSegment, - mut projections: &mut Vec>) - -> ty::PolyTraitRef<'tcx> - { - self.ast_path_to_poly_trait_ref(rscope, - span, - param_mode, - trait_def_id, - None, - trait_path_ref_id, - trait_segment, - projections) - } - fn ast_path_to_poly_trait_ref(&self, rscope: &RegionScope, span: Span, param_mode: PathParamMode, trait_def_id: DefId, - self_ty: Option>, + self_ty: Ty<'tcx>, path_id: ast::NodeId, trait_segment: &hir::PathSegment, poly_projections: &mut Vec>) @@ -808,21 +783,14 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o { trait_segment); let poly_trait_ref = ty::Binder(ty::TraitRef::new(trait_def_id, substs)); - { - let converted_bindings = - assoc_bindings - .iter() - .filter_map(|binding| { - // specify type to assert that error was already reported in Err case: - let predicate: Result<_, ErrorReported> = - self.ast_type_binding_to_poly_projection_predicate(path_id, - poly_trait_ref.clone(), - self_ty, - binding); - predicate.ok() // ok to ignore Err() because ErrorReported (see above) - }); - poly_projections.extend(converted_bindings); - } + poly_projections.extend(assoc_bindings.iter().filter_map(|binding| { + // specify type to assert that error was already reported in Err case: + let predicate: Result<_, ErrorReported> = + self.ast_type_binding_to_poly_projection_predicate(path_id, + poly_trait_ref, + binding); + predicate.ok() // ok to ignore Err() because ErrorReported (see above) + })); debug!("ast_path_to_poly_trait_ref(trait_segment={:?}, projections={:?}) -> {:?}", trait_segment, poly_projections, poly_trait_ref); @@ -834,7 +802,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o { span: Span, param_mode: PathParamMode, trait_def_id: DefId, - self_ty: Option>, + self_ty: Ty<'tcx>, trait_segment: &hir::PathSegment) -> ty::TraitRef<'tcx> { @@ -854,7 +822,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o { span: Span, param_mode: PathParamMode, trait_def_id: DefId, - self_ty: Option>, + self_ty: Ty<'tcx>, trait_segment: &hir::PathSegment) -> (&'tcx Substs<'tcx>, Vec>) { @@ -902,7 +870,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o { let substs = self.create_substs_for_ast_path(span, param_mode, &trait_def.generics, - self_ty, + Some(self_ty), types, regions); @@ -912,8 +880,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o { fn ast_type_binding_to_poly_projection_predicate( &self, path_id: ast::NodeId, - mut trait_ref: ty::PolyTraitRef<'tcx>, - self_ty: Option>, + trait_ref: ty::PolyTraitRef<'tcx>, binding: &ConvertedBinding<'tcx>) -> Result, ErrorReported> { @@ -967,62 +934,39 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o { // Simple case: X is defined in the current trait. if self.trait_defines_associated_type_named(trait_ref.def_id(), binding.item_name) { - return Ok(ty::Binder(ty::ProjectionPredicate { // <-------------------+ - projection_ty: ty::ProjectionTy { // | - trait_ref: trait_ref.skip_binder().clone(), // Binder moved here --+ - item_name: binding.item_name, - }, - ty: binding.ty, + return Ok(trait_ref.map_bound(|trait_ref| { + ty::ProjectionPredicate { + projection_ty: ty::ProjectionTy { + trait_ref: trait_ref, + item_name: binding.item_name, + }, + ty: binding.ty, + } })); } // Otherwise, we have to walk through the supertraits to find - // those that do. This is complicated by the fact that, for an - // object type, the `Self` type is not present in the - // substitutions (after all, it's being constructed right now), - // but the `supertraits` iterator really wants one. To handle - // this, we currently insert a dummy type and then remove it - // later. Yuck. - - let dummy_self_ty = tcx.mk_infer(ty::FreshTy(0)); - if self_ty.is_none() { // if converting for an object type - let mut dummy_substs = trait_ref.skip_binder().substs.clone(); // binder moved here -+ - assert!(dummy_substs.self_ty().is_none()); // | - dummy_substs.types.push(SelfSpace, dummy_self_ty); // | - trait_ref = ty::Binder(ty::TraitRef::new(trait_ref.def_id(), // <------------+ - tcx.mk_substs(dummy_substs))); - } - + // those that do. self.ensure_super_predicates(binding.span, trait_ref.def_id())?; - let mut candidates: Vec = + let candidates: Vec = traits::supertraits(tcx, trait_ref.clone()) .filter(|r| self.trait_defines_associated_type_named(r.def_id(), binding.item_name)) .collect(); - // If converting for an object type, then remove the dummy-ty from `Self` now. - // Yuckety yuck. - if self_ty.is_none() { - for candidate in &mut candidates { - let mut dummy_substs = candidate.0.substs.clone(); - assert!(dummy_substs.self_ty() == Some(dummy_self_ty)); - dummy_substs.types.pop(SelfSpace); - *candidate = ty::Binder(ty::TraitRef::new(candidate.def_id(), - tcx.mk_substs(dummy_substs))); - } - } - let candidate = self.one_bound_for_assoc_type(candidates, &trait_ref.to_string(), &binding.item_name.as_str(), binding.span)?; - Ok(ty::Binder(ty::ProjectionPredicate { // <-------------------------+ - projection_ty: ty::ProjectionTy { // | - trait_ref: candidate.skip_binder().clone(), // binder is moved up here --+ - item_name: binding.item_name, - }, - ty: binding.ty, + Ok(candidate.map_bound(|trait_ref| { + ty::ProjectionPredicate { + projection_ty: ty::ProjectionTy { + trait_ref: trait_ref, + item_name: binding.item_name, + }, + ty: binding.ty, + } })) } @@ -1059,11 +1003,12 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o { decl_ty.subst(self.tcx(), &substs) } - fn ast_ty_to_trait_ref(&self, - rscope: &RegionScope, - ty: &hir::Ty, - bounds: &[hir::TyParamBound]) - -> Result, ErrorReported> + fn ast_ty_to_object_trait_ref(&self, + rscope: &RegionScope, + span: Span, + ty: &hir::Ty, + bounds: &[hir::TyParamBound]) + -> Ty<'tcx> { /*! * In a type like `Foo + Send`, we want to wait to collect the @@ -1076,33 +1021,32 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o { * name, and reports an error otherwise. */ + let tcx = self.tcx(); match ty.node { hir::TyPath(None, ref path) => { - let resolution = self.tcx().expect_resolution(ty.id); + let resolution = tcx.expect_resolution(ty.id); match resolution.base_def { Def::Trait(trait_def_id) if resolution.depth == 0 => { - let mut projection_bounds = Vec::new(); - let trait_ref = - self.object_path_to_poly_trait_ref(rscope, - path.span, - PathParamMode::Explicit, - trait_def_id, - ty.id, - path.segments.last().unwrap(), - &mut projection_bounds); - Ok((trait_ref, projection_bounds)) + self.trait_path_to_object_type(rscope, + path.span, + PathParamMode::Explicit, + trait_def_id, + ty.id, + path.segments.last().unwrap(), + span, + partition_bounds(tcx, span, bounds)) } _ => { - struct_span_err!(self.tcx().sess, ty.span, E0172, + struct_span_err!(tcx.sess, ty.span, E0172, "expected a reference to a trait") .span_label(ty.span, &format!("expected a trait")) .emit(); - Err(ErrorReported) + tcx.types.err } } } _ => { - let mut err = struct_span_err!(self.tcx().sess, ty.span, E0178, + let mut err = struct_span_err!(tcx.sess, ty.span, E0178, "expected a path on the left-hand side \ of `+`, not `{}`", pprust::ty_to_string(ty)); @@ -1141,44 +1085,93 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o { } } err.emit(); - Err(ErrorReported) + tcx.types.err } } } - fn trait_ref_to_object_type(&self, - rscope: &RegionScope, - span: Span, - trait_ref: ty::PolyTraitRef<'tcx>, - projection_bounds: Vec>, - bounds: &[hir::TyParamBound]) - -> Ty<'tcx> - { - let existential_bounds = self.conv_existential_bounds(rscope, - span, - trait_ref.clone(), - projection_bounds, - bounds); - - let result = self.make_object_type(span, trait_ref, existential_bounds); - debug!("trait_ref_to_object_type: result={:?}", - result); - - result + /// Transform a PolyTraitRef into a PolyExistentialTraitRef by + /// removing the dummy Self type (TRAIT_OBJECT_DUMMY_SELF). + fn trait_ref_to_existential(&self, trait_ref: ty::TraitRef<'tcx>) + -> ty::ExistentialTraitRef<'tcx> { + assert_eq!(trait_ref.self_ty().sty, TRAIT_OBJECT_DUMMY_SELF); + ty::ExistentialTraitRef::erase_self_ty(self.tcx(), trait_ref) } - fn make_object_type(&self, - span: Span, - principal: ty::PolyTraitRef<'tcx>, - bounds: ty::ExistentialBounds<'tcx>) - -> Ty<'tcx> { + fn trait_path_to_object_type(&self, + rscope: &RegionScope, + path_span: Span, + param_mode: PathParamMode, + trait_def_id: DefId, + trait_path_ref_id: ast::NodeId, + trait_segment: &hir::PathSegment, + span: Span, + partitioned_bounds: PartitionedBounds) + -> Ty<'tcx> { let tcx = self.tcx(); - let object = ty::TraitTy { - principal: principal, - bounds: bounds + + let mut projection_bounds = vec![]; + let dummy_self = tcx.mk_ty(TRAIT_OBJECT_DUMMY_SELF); + let principal = self.ast_path_to_poly_trait_ref(rscope, + path_span, + param_mode, + trait_def_id, + dummy_self, + trait_path_ref_id, + trait_segment, + &mut projection_bounds); + + let PartitionedBounds { builtin_bounds, + trait_bounds, + region_bounds } = + partitioned_bounds; + + if !trait_bounds.is_empty() { + let b = &trait_bounds[0]; + let span = b.trait_ref.path.span; + struct_span_err!(self.tcx().sess, span, E0225, + "only the builtin traits can be used as closure or object bounds") + .span_label(span, &format!("non-builtin trait used as bounds")) + .emit(); + } + + // Erase the dummy_self (TRAIT_OBJECT_DUMMY_SELF) used above. + let existential_principal = principal.map_bound(|trait_ref| { + self.trait_ref_to_existential(trait_ref) + }); + let existential_projections = projection_bounds.iter().map(|bound| { + bound.map_bound(|b| { + let p = b.projection_ty; + ty::ExistentialProjection { + trait_ref: self.trait_ref_to_existential(p.trait_ref), + item_name: p.item_name, + ty: b.ty + } + }) + }).collect(); + + let region_bound = + self.compute_object_lifetime_bound(span, + ®ion_bounds, + existential_principal, + builtin_bounds); + + let region_bound = match region_bound { + Some(r) => r, + None => { + match rscope.object_lifetime_default(span) { + Some(r) => r, + None => { + span_err!(self.tcx().sess, span, E0228, + "the lifetime bound for this object type cannot be deduced \ + from context; please supply an explicit bound"); + ty::ReStatic + } + } + } }; - let object_trait_ref = - object.principal_trait_ref_with_self_ty(tcx, tcx.types.err); + + debug!("region_bound: {:?}", region_bound); // ensure the super predicates and stop if we encountered an error if self.ensure_super_predicates(span, principal.def_id()).is_err() { @@ -1198,7 +1191,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o { } let mut associated_types: FnvHashSet<(DefId, ast::Name)> = - traits::supertraits(tcx, object_trait_ref) + traits::supertraits(tcx, principal) .flat_map(|tr| { let trait_def = tcx.lookup_trait_def(tr.def_id()); trait_def.associated_type_names @@ -1208,7 +1201,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o { }) .collect(); - for projection_bound in &object.bounds.projection_bounds { + for projection_bound in &projection_bounds { let pair = (projection_bound.0.projection_ty.trait_ref.def_id, projection_bound.0.projection_ty.item_name); associated_types.remove(&pair); @@ -1224,7 +1217,14 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o { .emit(); } - tcx.mk_trait(object.principal, object.bounds) + let ty = tcx.mk_trait(ty::TraitObject { + principal: existential_principal, + region_bound: region_bound, + builtin_bounds: builtin_bounds, + projection_bounds: existential_projections + }); + debug!("trait_object_type: {:?}", ty); + ty } fn report_ambiguous_associated_type(&self, @@ -1458,7 +1458,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o { span, param_mode, trait_def_id, - Some(self_ty), + self_ty, trait_segment); debug!("qpath_to_ty: trait_ref={:?}", trait_ref); @@ -1520,23 +1520,17 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o { Def::Trait(trait_def_id) => { // N.B. this case overlaps somewhat with // TyObjectSum, see that fn for details - let mut projection_bounds = Vec::new(); - - let trait_ref = - self.object_path_to_poly_trait_ref(rscope, - span, - param_mode, - trait_def_id, - base_path_ref_id, - base_segments.last().unwrap(), - &mut projection_bounds); tcx.prohibit_type_params(base_segments.split_last().unwrap().1); - self.trait_ref_to_object_type(rscope, - span, - trait_ref, - projection_bounds, - &[]) + + self.trait_path_to_object_type(rscope, + span, + param_mode, + trait_def_id, + base_path_ref_id, + base_segments.last().unwrap(), + span, + partition_bounds(tcx, span, &[])) } Def::Enum(did) | Def::TyAlias(did) | Def::Struct(did) => { tcx.prohibit_type_params(base_segments.split_last().unwrap().1); @@ -1676,18 +1670,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o { tcx.mk_slice(self.ast_ty_to_ty(rscope, &ty)) } hir::TyObjectSum(ref ty, ref bounds) => { - match self.ast_ty_to_trait_ref(rscope, &ty, bounds) { - Ok((trait_ref, projection_bounds)) => { - self.trait_ref_to_object_type(rscope, - ast_ty.span, - trait_ref, - projection_bounds, - bounds) - } - Err(ErrorReported) => { - self.tcx().types.err - } - } + self.ast_ty_to_object_trait_ref(rscope, ast_ty.span, ty, bounds) } hir::TyPtr(ref mt) => { tcx.mk_ptr(ty::TypeAndMut { @@ -1764,7 +1747,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o { tcx.mk_fn_ptr(bare_fn_ty) } hir::TyPolyTraitRef(ref bounds) => { - self.conv_ty_poly_trait_ref(rscope, ast_ty.span, bounds) + self.conv_object_ty_poly_trait_ref(rscope, ast_ty.span, bounds) } hir::TyImplTrait(ref bounds) => { use collect::{compute_bounds, SizedByDefault}; @@ -2091,28 +2074,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o { } } - /// Given an existential type like `Foo+'a+Bar`, this routine converts - /// the `'a` and `Bar` intos an `ExistentialBounds` struct. - /// The `main_trait_refs` argument specifies the `Foo` -- it is absent - /// for closures. Eventually this should all be normalized, I think, - /// so that there is no "main trait ref" and instead we just have a flat - /// list of bounds as the existential type. - fn conv_existential_bounds(&self, - rscope: &RegionScope, - span: Span, - principal_trait_ref: ty::PolyTraitRef<'tcx>, - projection_bounds: Vec>, - ast_bounds: &[hir::TyParamBound]) - -> ty::ExistentialBounds<'tcx> - { - let partitioned_bounds = - partition_bounds(self.tcx(), span, ast_bounds); - - self.conv_existential_bounds_from_partitioned_bounds( - rscope, span, principal_trait_ref, projection_bounds, partitioned_bounds) - } - - fn conv_ty_poly_trait_ref(&self, + fn conv_object_ty_poly_trait_ref(&self, rscope: &RegionScope, span: Span, ast_bounds: &[hir::TyParamBound]) @@ -2120,75 +2082,24 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o { { let mut partitioned_bounds = partition_bounds(self.tcx(), span, &ast_bounds[..]); - let mut projection_bounds = Vec::new(); - let main_trait_bound = if !partitioned_bounds.trait_bounds.is_empty() { - let trait_bound = partitioned_bounds.trait_bounds.remove(0); - self.instantiate_poly_trait_ref(rscope, - trait_bound, - None, - &mut projection_bounds) + let trait_bound = if !partitioned_bounds.trait_bounds.is_empty() { + partitioned_bounds.trait_bounds.remove(0) } else { span_err!(self.tcx().sess, span, E0224, "at least one non-builtin trait is required for an object type"); return self.tcx().types.err; }; - let bounds = - self.conv_existential_bounds_from_partitioned_bounds(rscope, - span, - main_trait_bound.clone(), - projection_bounds, - partitioned_bounds); - - self.make_object_type(span, main_trait_bound, bounds) - } - - pub fn conv_existential_bounds_from_partitioned_bounds(&self, - rscope: &RegionScope, - span: Span, - principal_trait_ref: ty::PolyTraitRef<'tcx>, - projection_bounds: Vec>, // Empty for boxed closures - partitioned_bounds: PartitionedBounds) - -> ty::ExistentialBounds<'tcx> - { - let PartitionedBounds { builtin_bounds, - trait_bounds, - region_bounds } = - partitioned_bounds; - - if !trait_bounds.is_empty() { - let b = &trait_bounds[0]; - let span = b.trait_ref.path.span; - struct_span_err!(self.tcx().sess, span, E0225, - "only the builtin traits can be used as closure or object bounds") - .span_label(span, &format!("non-builtin trait used as bounds")) - .emit(); - } - - let region_bound = - self.compute_object_lifetime_bound(span, - ®ion_bounds, - principal_trait_ref, - builtin_bounds); - - let region_bound = match region_bound { - Some(r) => r, - None => { - match rscope.object_lifetime_default(span) { - Some(r) => r, - None => { - span_err!(self.tcx().sess, span, E0228, - "the lifetime bound for this object type cannot be deduced \ - from context; please supply an explicit bound"); - ty::ReStatic - } - } - } - }; - - debug!("region_bound: {:?}", region_bound); - - ty::ExistentialBounds::new(region_bound, builtin_bounds, projection_bounds) + let trait_ref = &trait_bound.trait_ref; + let trait_def_id = self.trait_def_id(trait_ref); + self.trait_path_to_object_type(rscope, + trait_ref.path.span, + PathParamMode::Explicit, + trait_def_id, + trait_ref.ref_id, + trait_ref.path.segments.last().unwrap(), + span, + partitioned_bounds) } /// Given the bounds on an object, determines what single region bound (if any) we can @@ -2199,7 +2110,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o { fn compute_object_lifetime_bound(&self, span: Span, explicit_region_bounds: &[&hir::Lifetime], - principal_trait_ref: ty::PolyTraitRef<'tcx>, + principal_trait_ref: ty::PolyExistentialTraitRef<'tcx>, builtin_bounds: ty::BuiltinBounds) -> Option // if None, use the default { @@ -2230,7 +2141,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o { // No explicit region bound specified. Therefore, examine trait // bounds and see if we can derive region bounds from those. let derived_region_bounds = - object_region_bounds(tcx, &principal_trait_ref, builtin_bounds); + object_region_bounds(tcx, principal_trait_ref, builtin_bounds); // If there are no derived region bounds, then report back that we // can find no region bound. The caller will use the default. diff --git a/src/librustc_typeck/check/cast.rs b/src/librustc_typeck/check/cast.rs index 7a4cc09a7d506..fb78d3a37ca23 100644 --- a/src/librustc_typeck/check/cast.rs +++ b/src/librustc_typeck/check/cast.rs @@ -78,7 +78,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { fn unsize_kind(&self, t: Ty<'tcx>) -> Option> { match t.sty { ty::TySlice(_) | ty::TyStr => Some(UnsizeKind::Length), - ty::TyTrait(ref tty) => Some(UnsizeKind::Vtable(tty.principal_def_id())), + ty::TyTrait(ref tty) => Some(UnsizeKind::Vtable(tty.principal.def_id())), ty::TyStruct(def, substs) => { // FIXME(arielb1): do some kind of normalization match def.struct_variant().fields.last() { diff --git a/src/librustc_typeck/check/closure.rs b/src/librustc_typeck/check/closure.rs index 3acb8017eec50..8a007293e64ff 100644 --- a/src/librustc_typeck/check/closure.rs +++ b/src/librustc_typeck/check/closure.rs @@ -102,12 +102,11 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { match expected_ty.sty { ty::TyTrait(ref object_type) => { - let proj_bounds = object_type.projection_bounds_with_self_ty(self.tcx, - self.tcx.types.err); - let sig = proj_bounds.iter() - .filter_map(|pb| self.deduce_sig_from_projection(pb)) - .next(); - let kind = self.tcx.lang_items.fn_trait_kind(object_type.principal_def_id()); + let sig = object_type.projection_bounds.iter().filter_map(|pb| { + let pb = pb.with_self_ty(self.tcx, self.tcx.types.err); + self.deduce_sig_from_projection(&pb) + }).next(); + let kind = self.tcx.lang_items.fn_trait_kind(object_type.principal.def_id()); (sig, kind) } ty::TyInfer(ty::TyVar(vid)) => { diff --git a/src/librustc_typeck/check/method/confirm.rs b/src/librustc_typeck/check/method/confirm.rs index d1d7259955576..250bf9265d1a4 100644 --- a/src/librustc_typeck/check/method/confirm.rs +++ b/src/librustc_typeck/check/method/confirm.rs @@ -210,7 +210,7 @@ impl<'a, 'gcx, 'tcx> ConfirmContext<'a, 'gcx, 'tcx> { probe::ObjectPick => { let trait_def_id = pick.item.container().id(); - self.extract_trait_ref(self_ty, |this, object_ty, data| { + self.extract_existential_trait_ref(self_ty, |this, object_ty, principal| { // The object data has no entry for the Self // Type. For the purposes of this method call, we // substitute the object type itself. This @@ -222,9 +222,9 @@ impl<'a, 'gcx, 'tcx> ConfirmContext<'a, 'gcx, 'tcx> { // been ruled out when we deemed the trait to be // "object safe". let original_poly_trait_ref = - data.principal_trait_ref_with_self_ty(this.tcx, object_ty); + principal.with_self_ty(this.tcx, object_ty); let upcast_poly_trait_ref = - this.upcast(original_poly_trait_ref.clone(), trait_def_id); + this.upcast(original_poly_trait_ref, trait_def_id); let upcast_trait_ref = this.replace_late_bound_regions_with_fresh_var(&upcast_poly_trait_ref); debug!("original_poly_trait_ref={:?} upcast_trait_ref={:?} target_trait={:?}", @@ -276,8 +276,12 @@ impl<'a, 'gcx, 'tcx> ConfirmContext<'a, 'gcx, 'tcx> { } } - fn extract_trait_ref(&mut self, self_ty: Ty<'tcx>, mut closure: F) -> R where - F: FnMut(&mut ConfirmContext<'a, 'gcx, 'tcx>, Ty<'tcx>, &ty::TraitTy<'tcx>) -> R, + fn extract_existential_trait_ref(&mut self, + self_ty: Ty<'tcx>, + mut closure: F) -> R + where F: FnMut(&mut ConfirmContext<'a, 'gcx, 'tcx>, + Ty<'tcx>, + ty::PolyExistentialTraitRef<'tcx>) -> R, { // If we specified that this is an object method, then the // self-type ought to be something that can be dereferenced to @@ -288,7 +292,7 @@ impl<'a, 'gcx, 'tcx> ConfirmContext<'a, 'gcx, 'tcx> { self.fcx.autoderef(self.span, self_ty) .filter_map(|(ty, _)| { match ty.sty { - ty::TyTrait(ref data) => Some(closure(self, ty, &data)), + ty::TyTrait(ref data) => Some(closure(self, ty, data.principal)), _ => None, } }) @@ -331,9 +335,7 @@ impl<'a, 'gcx, 'tcx> ConfirmContext<'a, 'gcx, 'tcx> { // parameters from the type and those from the method. // // FIXME -- permit users to manually specify lifetimes - let type_defs = method.generics.types.as_full_slice(); - let region_defs = method.generics.regions.as_full_slice(); - subst::Substs::from_param_defs(region_defs, type_defs, |def| { + subst::Substs::from_generics(&method.generics, |def, _| { if def.space != subst::FnSpace { substs.region_for_def(def) } else { diff --git a/src/librustc_typeck/check/method/mod.rs b/src/librustc_typeck/check/method/mod.rs index 532a5c0de4e46..ff34f37bde0dd 100644 --- a/src/librustc_typeck/check/method/mod.rs +++ b/src/librustc_typeck/check/method/mod.rs @@ -189,9 +189,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { assert!(trait_def.generics.regions.is_empty()); // Construct a trait-reference `self_ty : Trait` - let type_defs = trait_def.generics.types.as_full_slice(); - let region_defs = trait_def.generics.regions.as_full_slice(); - let substs = subst::Substs::from_param_defs(region_defs, type_defs, |def| { + let substs = subst::Substs::from_generics(&trait_def.generics, |def, _| { self.region_var_for_def(span, def) }, |def, substs| { if def.space == subst::SelfSpace { diff --git a/src/librustc_typeck/check/method/probe.rs b/src/librustc_typeck/check/method/probe.rs index 44e371482c55c..f6ac3235cf33e 100644 --- a/src/librustc_typeck/check/method/probe.rs +++ b/src/librustc_typeck/check/method/probe.rs @@ -290,8 +290,8 @@ impl<'a, 'gcx, 'tcx> ProbeContext<'a, 'gcx, 'tcx> { match self_ty.sty { ty::TyTrait(box ref data) => { - self.assemble_inherent_candidates_from_object(self_ty, data); - self.assemble_inherent_impl_candidates_for_type(data.principal_def_id()); + self.assemble_inherent_candidates_from_object(self_ty, data.principal); + self.assemble_inherent_impl_candidates_for_type(data.principal.def_id()); } ty::TyEnum(def, _) | ty::TyStruct(def, _) => { @@ -445,7 +445,7 @@ impl<'a, 'gcx, 'tcx> ProbeContext<'a, 'gcx, 'tcx> { fn assemble_inherent_candidates_from_object(&mut self, self_ty: Ty<'tcx>, - data: &ty::TraitTy<'tcx>) { + principal: ty::PolyExistentialTraitRef<'tcx>) { debug!("assemble_inherent_candidates_from_object(self_ty={:?})", self_ty); @@ -456,7 +456,7 @@ impl<'a, 'gcx, 'tcx> ProbeContext<'a, 'gcx, 'tcx> { // a substitution that replaces `Self` with the object type // itself. Hence, a `&self` method will wind up with an // argument type like `&Trait`. - let trait_ref = data.principal_trait_ref_with_self_ty(self.tcx, self_ty); + let trait_ref = principal.with_self_ty(self.tcx, self_ty); self.elaborate_bounds(&[trait_ref], |this, new_trait_ref, item| { let new_trait_ref = this.erase_late_bound_regions(&new_trait_ref); @@ -1227,15 +1227,16 @@ impl<'a, 'gcx, 'tcx> ProbeContext<'a, 'gcx, 'tcx> { return impl_ty; } - let placeholder; - let mut substs = substs; - if - !method.generics.types.is_empty_in(subst::FnSpace) || - !method.generics.regions.is_empty_in(subst::FnSpace) - { - let type_defs = method.generics.types.as_full_slice(); - let region_defs = method.generics.regions.as_full_slice(); - placeholder = subst::Substs::from_param_defs(region_defs, type_defs, |def| { + // Erase any late-bound regions from the method and substitute + // in the values from the substitution. + let xform_self_ty = method.fty.sig.input(0); + let xform_self_ty = self.erase_late_bound_regions(&xform_self_ty); + + if method.generics.types.is_empty_in(subst::FnSpace) && + method.generics.regions.is_empty_in(subst::FnSpace) { + xform_self_ty.subst(self.tcx, substs) + } else { + let substs = subst::Substs::from_generics(&method.generics, |def, _| { if def.space != subst::FnSpace { substs.region_for_def(def) } else { @@ -1250,16 +1251,8 @@ impl<'a, 'gcx, 'tcx> ProbeContext<'a, 'gcx, 'tcx> { self.type_var_for_def(self.span, def, cur_substs) } }); - substs = &placeholder; + xform_self_ty.subst(self.tcx, &substs) } - - // Erase any late-bound regions from the method and substitute - // in the values from the substitution. - let xform_self_ty = method.fty.sig.input(0); - let xform_self_ty = self.erase_late_bound_regions(&xform_self_ty); - let xform_self_ty = xform_self_ty.subst(self.tcx, substs); - - xform_self_ty } /// Get the type of an impl and generate substitutions with placeholders. diff --git a/src/librustc_typeck/check/method/suggest.rs b/src/librustc_typeck/check/method/suggest.rs index 54521782474fe..dc6fa334b74fc 100644 --- a/src/librustc_typeck/check/method/suggest.rs +++ b/src/librustc_typeck/check/method/suggest.rs @@ -358,7 +358,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { match ty.sty { ty::TyEnum(def, _) | ty::TyStruct(def, _) => def.did.is_local(), - ty::TyTrait(ref tr) => tr.principal_def_id().is_local(), + ty::TyTrait(ref tr) => tr.principal.def_id().is_local(), ty::TyParam(_) => true, diff --git a/src/librustc_typeck/check/regionck.rs b/src/librustc_typeck/check/regionck.rs index 6f3d48282e25c..8e34b0b8c5559 100644 --- a/src/librustc_typeck/check/regionck.rs +++ b/src/librustc_typeck/check/regionck.rs @@ -824,11 +824,11 @@ impl<'a, 'gcx, 'tcx> RegionCtxt<'a, 'gcx, 'tcx> { } /*From:*/ (_, - /*To: */ &ty::TyTrait(box ty::TraitTy { ref bounds, .. })) => { + /*To: */ &ty::TyTrait(ref obj)) => { // When T is existentially quantified as a trait // `Foo+'to`, it must outlive the region bound `'to`. self.type_must_outlive(infer::RelateObjectBound(cast_expr.span), - from_ty, bounds.region_bound); + from_ty, obj.region_bound); } /*From:*/ (&ty::TyBox(from_referent_ty), diff --git a/src/librustc_typeck/coherence/mod.rs b/src/librustc_typeck/coherence/mod.rs index 9b26e95f7fa55..485e744bf916e 100644 --- a/src/librustc_typeck/coherence/mod.rs +++ b/src/librustc_typeck/coherence/mod.rs @@ -75,7 +75,7 @@ impl<'a, 'gcx, 'tcx> CoherenceChecker<'a, 'gcx, 'tcx> { } TyTrait(ref t) => { - Some(t.principal_def_id()) + Some(t.principal.def_id()) } TyBox(_) => { diff --git a/src/librustc_typeck/coherence/orphan.rs b/src/librustc_typeck/coherence/orphan.rs index e426f0cb643b7..97aed4d5e82f9 100644 --- a/src/librustc_typeck/coherence/orphan.rs +++ b/src/librustc_typeck/coherence/orphan.rs @@ -80,7 +80,7 @@ impl<'cx, 'tcx> OrphanChecker<'cx, 'tcx> { self.check_def_id(item, def.did); } ty::TyTrait(ref data) => { - self.check_def_id(item, data.principal_def_id()); + self.check_def_id(item, data.principal.def_id()); } ty::TyBox(..) => { match self.tcx.lang_items.require_owned_box() { diff --git a/src/librustc_typeck/coherence/overlap.rs b/src/librustc_typeck/coherence/overlap.rs index 46a9ef8d5babb..f60fb9583a661 100644 --- a/src/librustc_typeck/coherence/overlap.rs +++ b/src/librustc_typeck/coherence/overlap.rs @@ -168,14 +168,14 @@ impl<'cx, 'tcx,'v> intravisit::Visitor<'v> for OverlapChecker<'cx, 'tcx> { // This is something like impl Trait1 for Trait2. Illegal // if Trait1 is a supertrait of Trait2 or Trait2 is not object safe. - if !self.tcx.is_object_safe(data.principal_def_id()) { + if !self.tcx.is_object_safe(data.principal.def_id()) { // This is an error, but it will be // reported by wfcheck. Ignore it // here. This is tested by // `coherence-impl-trait-for-trait-object-safe.rs`. } else { let mut supertrait_def_ids = - traits::supertrait_def_ids(self.tcx, data.principal_def_id()); + traits::supertrait_def_ids(self.tcx, data.principal.def_id()); if supertrait_def_ids.any(|d| d == trait_def_id) { span_err!(self.tcx.sess, item.span, E0371, "the object type `{}` automatically \ diff --git a/src/librustc_typeck/collect.rs b/src/librustc_typeck/collect.rs index 0ddc051d4a868..a2a162a7f5f74 100644 --- a/src/librustc_typeck/collect.rs +++ b/src/librustc_typeck/collect.rs @@ -722,7 +722,7 @@ fn convert_item(ccx: &CrateCtxt, it: &hir::Item) { AstConv::instantiate_mono_trait_ref(&ccx.icx(&()), &ExplicitRscope, ast_trait_ref, - None); + tcx.mk_self_type()); tcx.record_trait_has_default_impl(trait_ref.def_id); @@ -752,7 +752,7 @@ fn convert_item(ccx: &CrateCtxt, it: &hir::Item) { AstConv::instantiate_mono_trait_ref(&ccx.icx(&ty_predicates), &ExplicitRscope, ast_trait_ref, - Some(selfty)) + selfty) }); tcx.impl_trait_refs.borrow_mut().insert(def_id, trait_ref); @@ -1815,10 +1815,12 @@ fn ty_generic_predicates<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>, let mut projections = Vec::new(); let trait_ref = - conv_poly_trait_ref(&ccx.icx(&(base_predicates, ast_generics)), - ty, - poly_trait_ref, - &mut projections); + AstConv::instantiate_poly_trait_ref(&ccx.icx(&(base_predicates, + ast_generics)), + &ExplicitRscope, + poly_trait_ref, + ty, + &mut projections); result.predicates.push(trait_ref.to_predicate()); @@ -2069,7 +2071,7 @@ pub fn compute_bounds<'gcx: 'tcx, 'tcx>(astconv: &AstConv<'gcx, 'tcx>, let mut trait_bounds: Vec<_> = trait_bounds.iter().map(|&bound| { astconv.instantiate_poly_trait_ref(&rscope, bound, - Some(param_ty), + param_ty, &mut projection_bounds) }).collect(); @@ -2100,7 +2102,10 @@ fn predicates_from_bound<'tcx>(astconv: &AstConv<'tcx, 'tcx>, match *bound { hir::TraitTyParamBound(ref tr, hir::TraitBoundModifier::None) => { let mut projections = Vec::new(); - let pred = conv_poly_trait_ref(astconv, param_ty, tr, &mut projections); + let pred = astconv.instantiate_poly_trait_ref(&ExplicitRscope, + tr, + param_ty, + &mut projections); projections.into_iter() .map(|p| p.to_predicate()) .chain(Some(pred.to_predicate())) @@ -2117,19 +2122,6 @@ fn predicates_from_bound<'tcx>(astconv: &AstConv<'tcx, 'tcx>, } } -fn conv_poly_trait_ref<'gcx: 'tcx, 'tcx>(astconv: &AstConv<'gcx, 'tcx>, - param_ty: Ty<'tcx>, - trait_ref: &hir::PolyTraitRef, - projections: &mut Vec>) - -> ty::PolyTraitRef<'tcx> -{ - AstConv::instantiate_poly_trait_ref(astconv, - &ExplicitRscope, - trait_ref, - Some(param_ty), - projections) -} - fn compute_type_scheme_of_foreign_fn_decl<'a, 'tcx>( ccx: &CrateCtxt<'a, 'tcx>, id: DefId, diff --git a/src/librustc_typeck/variance/constraints.rs b/src/librustc_typeck/variance/constraints.rs index 50c568cfef8f6..6e6f9ce65c50f 100644 --- a/src/librustc_typeck/variance/constraints.rs +++ b/src/librustc_typeck/variance/constraints.rs @@ -396,19 +396,16 @@ impl<'a, 'tcx> ConstraintContext<'a, 'tcx> { ty::TyTrait(ref data) => { let poly_trait_ref = - data.principal_trait_ref_with_self_ty(self.tcx(), - self.tcx().types.err); + data.principal.with_self_ty(self.tcx(), self.tcx().types.err); // The type `Foo` is contravariant w/r/t `'a`: let contra = self.contravariant(variance); - self.add_constraints_from_region(generics, data.bounds.region_bound, contra); + self.add_constraints_from_region(generics, data.region_bound, contra); // Ignore the SelfSpace, it is erased. self.add_constraints_from_trait_ref(generics, poly_trait_ref.0, variance); - let projections = data.projection_bounds_with_self_ty(self.tcx(), - self.tcx().types.err); - for projection in &projections { + for projection in &data.projection_bounds { self.add_constraints_from_ty(generics, projection.0.ty, self.invariant); } } diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index 284e0d4dbddf3..ffe5b9aad2fb3 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -630,26 +630,6 @@ impl Clean for hir::TyParamBound { } } -impl<'tcx> Clean<(Vec, Vec)> for ty::ExistentialBounds<'tcx> { - fn clean(&self, cx: &DocContext) -> (Vec, Vec) { - let mut tp_bounds = vec![]; - self.region_bound.clean(cx).map(|b| tp_bounds.push(RegionBound(b))); - for bb in &self.builtin_bounds { - tp_bounds.push(bb.clean(cx)); - } - - let mut bindings = vec![]; - for &ty::Binder(ref pb) in &self.projection_bounds { - bindings.push(TypeBinding { - name: pb.projection_ty.item_name.clean(cx), - ty: pb.ty.clean(cx) - }); - } - - (tp_bounds, bindings) - } -} - fn external_path_params(cx: &DocContext, trait_did: Option, bindings: Vec, substs: &subst::Substs) -> PathParameters { let lifetimes = substs.regions.get_slice(subst::TypeSpace) @@ -1848,12 +1828,26 @@ impl<'tcx> Clean for ty::Ty<'tcx> { is_generic: false, } } - ty::TyTrait(box ty::TraitTy { ref principal, ref bounds }) => { - let did = principal.def_id(); + ty::TyTrait(ref obj) => { + let did = obj.principal.def_id(); inline::record_extern_fqn(cx, did, TypeTrait); - let (typarams, bindings) = bounds.clean(cx); + + let mut typarams = vec![]; + obj.region_bound.clean(cx).map(|b| typarams.push(RegionBound(b))); + for bb in &obj.builtin_bounds { + typarams.push(bb.clean(cx)); + } + + let mut bindings = vec![]; + for &ty::Binder(ref pb) in &obj.projection_bounds { + bindings.push(TypeBinding { + name: pb.item_name.clean(cx), + ty: pb.ty.clean(cx) + }); + } + let path = external_path(cx, &cx.tcx().item_name(did).as_str(), - Some(did), bindings, principal.substs()); + Some(did), bindings, obj.principal.0.substs); ResolvedPath { path: path, typarams: Some(typarams), From bfdfa1ce1d7275bbdb89ecb116bf765f19b204e1 Mon Sep 17 00:00:00 2001 From: Eduard Burtescu Date: Wed, 17 Aug 2016 04:05:00 +0300 Subject: [PATCH 07/12] rustc_typeck: use Substs::from_generics instead of manually building them. --- src/librustc/infer/mod.rs | 7 - src/librustc_typeck/astconv.rs | 379 ++++++++++-------------- src/librustc_typeck/check/mod.rs | 445 ++++++++++------------------- src/librustc_typeck/diagnostics.rs | 4 +- 4 files changed, 300 insertions(+), 535 deletions(-) diff --git a/src/librustc/infer/mod.rs b/src/librustc/infer/mod.rs index 951570679e08e..1e360cd43da12 100644 --- a/src/librustc/infer/mod.rs +++ b/src/librustc/infer/mod.rs @@ -1234,13 +1234,6 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { self.tcx.mk_var(ty_var_id) } - pub fn region_vars_for_defs(&self, - span: Span, - defs: &[ty::RegionParameterDef]) - -> Vec { - defs.iter().map(|def| self.region_var_for_def(span, def)).collect() - } - /// 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, diff --git a/src/librustc_typeck/astconv.rs b/src/librustc_typeck/astconv.rs index ed4ea3c937b90..11ca012fdedab 100644 --- a/src/librustc_typeck/astconv.rs +++ b/src/librustc_typeck/astconv.rs @@ -55,7 +55,7 @@ use hir::def_id::DefId; use hir::print as pprust; use middle::resolve_lifetime as rl; use rustc::lint; -use rustc::ty::subst::{FnSpace, TypeSpace, SelfSpace, Subst, Substs}; +use rustc::ty::subst::{TypeSpace, SelfSpace, Subst, Substs}; use rustc::traits; use rustc::ty::{self, Ty, TyCtxt, ToPredicate, TypeFoldable}; use rustc::ty::wf::object_region_bounds; @@ -350,64 +350,77 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o { param_mode: PathParamMode, decl_generics: &ty::Generics<'tcx>, item_segment: &hir::PathSegment) - -> Substs<'tcx> + -> &'tcx Substs<'tcx> { let tcx = self.tcx(); - // ast_path_substs() is only called to convert paths that are - // known to refer to traits, types, or structs. In these cases, - // all type parameters defined for the item being referenced will - // be in the TypeSpace or SelfSpace. - // - // Note: in the case of traits, the self parameter is also - // defined, but we don't currently create a `type_param_def` for - // `Self` because it is implicit. - assert!(decl_generics.regions.all(|d| d.space == TypeSpace)); - assert!(decl_generics.types.all(|d| d.space != FnSpace)); - - let (regions, types, assoc_bindings) = match item_segment.parameters { - hir::AngleBracketedParameters(ref data) => { - self.convert_angle_bracketed_parameters(rscope, span, decl_generics, data) - } + match item_segment.parameters { + hir::AngleBracketedParameters(_) => {} hir::ParenthesizedParameters(..) => { struct_span_err!(tcx.sess, span, E0214, "parenthesized parameters may only be used with a trait") .span_label(span, &format!("only traits may use parentheses")) .emit(); - let ty_param_defs = decl_generics.types.get_slice(TypeSpace); - (Substs::empty(), - ty_param_defs.iter().map(|_| tcx.types.err).collect(), - vec![]) + return tcx.mk_substs(Substs::from_generics(decl_generics, |_, _| { + ty::ReStatic + }, |_, _| { + tcx.types.err + })); } - }; + } + + let (substs, assoc_bindings) = + self.create_substs_for_ast_path(rscope, + span, + param_mode, + decl_generics, + &item_segment.parameters, + None); assoc_bindings.first().map(|b| self.tcx().prohibit_projection(b.span)); - self.create_substs_for_ast_path(span, - param_mode, - decl_generics, - None, - types, - regions) + substs } - fn create_region_substs(&self, + /// Given the type/region arguments provided to some path (along with + /// an implicit Self, if this is a trait reference) returns the complete + /// set of substitutions. This may involve applying defaulted type parameters. + /// + /// Note that the type listing given here is *exactly* what the user provided. + fn create_substs_for_ast_path(&self, rscope: &RegionScope, span: Span, + param_mode: PathParamMode, decl_generics: &ty::Generics<'tcx>, - regions_provided: Vec) - -> Substs<'tcx> + parameters: &hir::PathParameters, + self_ty: Option>) + -> (&'tcx Substs<'tcx>, Vec>) { let tcx = self.tcx(); + debug!("create_substs_for_ast_path(decl_generics={:?}, self_ty={:?}, \ + parameters={:?})", + decl_generics, self_ty, parameters); + + let (lifetimes, num_types_provided) = match *parameters { + hir::AngleBracketedParameters(ref data) => { + if param_mode == PathParamMode::Optional && data.types.is_empty() { + (&data.lifetimes[..], None) + } else { + (&data.lifetimes[..], Some(data.types.len())) + } + } + hir::ParenthesizedParameters(_) => (&[][..], Some(1)) + }; + // If the type is parameterized by this region, then replace this // region with the current anon region binding (in other words, // whatever & would get replaced with). let expected_num_region_params = decl_generics.regions.len(TypeSpace); - let supplied_num_region_params = regions_provided.len(); + let supplied_num_region_params = lifetimes.len(); let regions = if expected_num_region_params == supplied_num_region_params { - regions_provided + lifetimes.iter().map(|l| ast_region_to_region(tcx, l)).collect() } else { let anon_regions = rscope.anon_regions(span, expected_num_region_params); @@ -423,176 +436,111 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o { Err(_) => (0..expected_num_region_params).map(|_| ty::ReStatic).collect() } }; - Substs::new_type(vec![], regions) - } - /// Given the type/region arguments provided to some path (along with - /// an implicit Self, if this is a trait reference) returns the complete - /// set of substitutions. This may involve applying defaulted type parameters. - /// - /// Note that the type listing given here is *exactly* what the user provided. - /// - /// The `region_substs` should be the result of `create_region_substs` - /// -- that is, a substitution with no types but the correct number of - /// regions. - fn create_substs_for_ast_path(&self, - span: Span, - param_mode: PathParamMode, - decl_generics: &ty::Generics<'tcx>, - self_ty: Option>, - types_provided: Vec>, - region_substs: Substs<'tcx>) - -> Substs<'tcx> - { - let tcx = self.tcx(); + // If a self-type was declared, one should be provided. + assert_eq!(decl_generics.types.get_self().is_some(), self_ty.is_some()); - debug!("create_substs_for_ast_path(decl_generics={:?}, self_ty={:?}, \ - types_provided={:?}, region_substs={:?})", - decl_generics, self_ty, types_provided, - region_substs); - - assert_eq!(region_substs.regions.len(TypeSpace), decl_generics.regions.len(TypeSpace)); - assert!(region_substs.types.is_empty()); - - // Convert the type parameters supplied by the user. - let ty_param_defs = decl_generics.types.get_slice(TypeSpace); - let formal_ty_param_count = ty_param_defs.len(); - let required_ty_param_count = ty_param_defs.iter() - .take_while(|x| x.default.is_none()) - .count(); - - let mut type_substs = self.get_type_substs_for_defs(span, - types_provided, - param_mode, - ty_param_defs, - region_substs.clone(), - self_ty); - - let supplied_ty_param_count = type_substs.len(); - check_type_argument_count(self.tcx(), span, supplied_ty_param_count, - required_ty_param_count, formal_ty_param_count); - - if supplied_ty_param_count < required_ty_param_count { - while type_substs.len() < required_ty_param_count { - type_substs.push(tcx.types.err); - } - } else if supplied_ty_param_count > formal_ty_param_count { - type_substs.truncate(formal_ty_param_count); + // Check the number of type parameters supplied by the user. + if let Some(num_provided) = num_types_provided { + let ty_param_defs = decl_generics.types.get_slice(TypeSpace); + check_type_argument_count(tcx, span, num_provided, ty_param_defs); } - assert!(type_substs.len() >= required_ty_param_count && - type_substs.len() <= formal_ty_param_count); - let mut substs = region_substs; + let is_object = self_ty.map_or(false, |ty| ty.sty == TRAIT_OBJECT_DUMMY_SELF); + let default_needs_object_self = |p: &ty::TypeParameterDef<'tcx>| { + if let Some(ref default) = p.default { + if is_object && default.has_self_ty() { + // There is no suitable inference default for a type parameter + // that references self, in an object type. + return true; + } + } - // If a self-type was declared, one should be provided. - assert_eq!(decl_generics.types.get_self().is_some(), self_ty.is_some()); - substs.types.extend(SelfSpace, self_ty.into_iter()); - substs.types.extend(TypeSpace, type_substs.into_iter()); + false + }; + + let mut output_assoc_binding = None; + let substs = Substs::from_generics(decl_generics, |def, _| { + assert_eq!(def.space, TypeSpace); + regions[def.index as usize] + }, |def, substs| { + assert!(def.space == SelfSpace || def.space == TypeSpace); + let i = def.index as usize; + if def.space == SelfSpace { + // Self, which must have been provided. + assert_eq!(i, 0); + self_ty.expect("Self type parameter missing") + } else if num_types_provided.map_or(false, |n| i < n) { + // A provided type parameter. + match *parameters { + hir::AngleBracketedParameters(ref data) => { + self.ast_ty_arg_to_ty(rscope, Some(def), substs, &data.types[i]) + } + hir::ParenthesizedParameters(ref data) => { + assert_eq!(i, 0); + let (ty, assoc) = + self.convert_parenthesized_parameters(rscope, substs, data); + output_assoc_binding = Some(assoc); + ty + } + } + } else if num_types_provided.is_none() { + // No type parameters were provided, we can infer all. + let ty_var = if !default_needs_object_self(def) { + self.ty_infer_for_def(def, substs, span) + } else { + self.ty_infer(span) + }; + ty_var + } else if let Some(default) = def.default { + // No type parameter provided, but a default exists. - let is_object = self_ty.map_or(false, |ty| ty.sty == TRAIT_OBJECT_DUMMY_SELF); - let actual_supplied_ty_param_count = substs.types.len(TypeSpace); - for param in &ty_param_defs[actual_supplied_ty_param_count..] { - let default = if let Some(default) = param.default { // If we are converting an object type, then the // `Self` parameter is unknown. However, some of the // other type parameters may reference `Self` in their // defaults. This will lead to an ICE if we are not // careful! - if is_object && default.has_self_ty() { + if default_needs_object_self(def) { span_err!(tcx.sess, span, E0393, "the type parameter `{}` must be explicitly specified \ in an object type because its default value `{}` references \ the type `Self`", - param.name, + def.name, default); tcx.types.err } else { // This is a default type parameter. - default.subst_spanned(tcx, &substs, Some(span)) + default.subst_spanned(tcx, substs, Some(span)) } } else { - span_bug!(span, "extra parameter without default"); - }; - substs.types.push(TypeSpace, default); - } - - debug!("create_substs_for_ast_path(decl_generics={:?}, self_ty={:?}) -> {:?}", - decl_generics, self_ty, substs); - - substs - } - - /// Returns types_provided if it is not empty, otherwise populating the - /// type parameters with inference variables as appropriate. - fn get_type_substs_for_defs(&self, - span: Span, - types_provided: Vec>, - param_mode: PathParamMode, - ty_param_defs: &[ty::TypeParameterDef<'tcx>], - mut substs: Substs<'tcx>, - self_ty: Option>) - -> Vec> - { - let is_object = self_ty.map_or(false, |ty| ty.sty == TRAIT_OBJECT_DUMMY_SELF); - let use_default = |p: &ty::TypeParameterDef<'tcx>| { - if let Some(ref default) = p.default { - if is_object && default.has_self_ty() { - // There is no suitable inference default for a type parameter - // that references self, in an object type. - return false; - } + // We've already errored above about the mismatch. + tcx.types.err } + }); - true + let assoc_bindings = match *parameters { + hir::AngleBracketedParameters(ref data) => { + data.bindings.iter().map(|b| { + ConvertedBinding { + item_name: b.name, + ty: self.ast_ty_to_ty(rscope, &b.ty), + span: b.span + } + }).collect() + } + hir::ParenthesizedParameters(ref data) => { + vec![output_assoc_binding.unwrap_or_else(|| { + // This is an error condition, but we should + // get the associated type binding anyway. + self.convert_parenthesized_parameters(rscope, &substs, data).1 + })] + } }; - if param_mode == PathParamMode::Optional && types_provided.is_empty() { - ty_param_defs.iter().map(|def| { - let ty_var = if use_default(def) { - self.ty_infer_for_def(def, &substs, span) - } else { - self.ty_infer(span) - }; - substs.types.push(def.space, ty_var); - ty_var - }).collect() - } else { - types_provided - } - } + debug!("create_substs_for_ast_path(decl_generics={:?}, self_ty={:?}) -> {:?}", + decl_generics, self_ty, substs); - fn convert_angle_bracketed_parameters(&self, - rscope: &RegionScope, - span: Span, - decl_generics: &ty::Generics<'tcx>, - data: &hir::AngleBracketedParameterData) - -> (Substs<'tcx>, - Vec>, - Vec>) - { - let regions: Vec<_> = - data.lifetimes.iter() - .map(|l| ast_region_to_region(self.tcx(), l)) - .collect(); - - let region_substs = - self.create_region_substs(rscope, span, decl_generics, regions); - - let types: Vec<_> = - data.types.iter() - .enumerate() - .map(|(i,t)| self.ast_ty_arg_to_ty(rscope, decl_generics, - i, ®ion_substs, t)) - .collect(); - - let assoc_bindings: Vec<_> = - data.bindings.iter() - .map(|b| ConvertedBinding { item_name: b.name, - ty: self.ast_ty_to_ty(rscope, &b.ty), - span: b.span }) - .collect(); - - (region_substs, types, assoc_bindings) + (tcx.mk_substs(substs), assoc_bindings) } /// Returns the appropriate lifetime to use for any output lifetimes @@ -657,29 +605,18 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o { fn convert_parenthesized_parameters(&self, rscope: &RegionScope, - span: Span, - decl_generics: &ty::Generics<'tcx>, + region_substs: &Substs<'tcx>, data: &hir::ParenthesizedParameterData) - -> (Substs<'tcx>, - Vec>, - Vec>) + -> (Ty<'tcx>, ConvertedBinding<'tcx>) { - let region_substs = - self.create_region_substs(rscope, span, decl_generics, Vec::new()); - let anon_scope = rscope.anon_type_scope(); let binding_rscope = MaybeWithAnonTypes::new(BindingRscope::new(), anon_scope); - let inputs = - data.inputs.iter() - .map(|a_t| self.ast_ty_arg_to_ty(&binding_rscope, decl_generics, - 0, ®ion_substs, a_t)) - .collect::>>(); - + let inputs: Vec<_> = data.inputs.iter().map(|a_t| { + self.ast_ty_arg_to_ty(&binding_rscope, None, region_substs, a_t) + }).collect(); let input_params = vec![String::new(); inputs.len()]; let implied_output_region = self.find_implied_output_region(&inputs, input_params); - let input_ty = self.tcx().mk_tup(inputs); - let (output, output_span) = match data.output { Some(ref output_ty) => { (self.convert_ty_with_lifetime_elision(implied_output_region, @@ -698,7 +635,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o { span: output_span }; - (region_substs, vec![input_ty], vec![output_binding]) + (self.tcx().mk_tup(inputs), output_binding) } pub fn instantiate_poly_trait_ref(&self, @@ -838,8 +775,8 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o { } }; - let (regions, types, assoc_bindings) = match trait_segment.parameters { - hir::AngleBracketedParameters(ref data) => { + match trait_segment.parameters { + hir::AngleBracketedParameters(_) => { // For now, require that parenthetical notation be used // only with `Fn()` etc. if !self.tcx().sess.features.borrow().unboxed_closures && trait_def.paren_sugar { @@ -850,10 +787,8 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o { type parameters is subject to change. \ Use parenthetical notation (Fn(Foo, Bar) -> Baz) instead"); } - - self.convert_angle_bracketed_parameters(rscope, span, &trait_def.generics, data) } - hir::ParenthesizedParameters(ref data) => { + hir::ParenthesizedParameters(_) => { // For now, require that parenthetical notation be used // only with `Fn()` etc. if !self.tcx().sess.features.borrow().unboxed_closures && !trait_def.paren_sugar { @@ -862,19 +797,15 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o { "\ parenthetical notation is only stable when used with `Fn`-family traits"); } - - self.convert_parenthesized_parameters(rscope, span, &trait_def.generics, data) } - }; - - let substs = self.create_substs_for_ast_path(span, - param_mode, - &trait_def.generics, - Some(self_ty), - types, - regions); + } - (self.tcx().mk_substs(substs), assoc_bindings) + self.create_substs_for_ast_path(rscope, + span, + param_mode, + &trait_def.generics, + &trait_segment.parameters, + Some(self_ty)) } fn ast_type_binding_to_poly_projection_predicate( @@ -1000,7 +931,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o { return self.tcx().mk_box(*substs.types.get(TypeSpace, 0)); } - decl_ty.subst(self.tcx(), &substs) + decl_ty.subst(self.tcx(), substs) } fn ast_ty_to_object_trait_ref(&self, @@ -1473,24 +1404,20 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o { /// # Parameters /// /// * `this`, `rscope`: the surrounding context - /// * `decl_generics`: the generics of the struct/enum/trait declaration being - /// referenced - /// * `index`: the index of the type parameter being instantiated from the list - /// (we assume it is in the `TypeSpace`) + /// * `def`: the type parameter being instantiated (if available) /// * `region_substs`: a partial substitution consisting of /// only the region type parameters being supplied to this type. /// * `ast_ty`: the ast representation of the type being supplied - pub fn ast_ty_arg_to_ty(&self, - rscope: &RegionScope, - decl_generics: &ty::Generics<'tcx>, - index: usize, - region_substs: &Substs<'tcx>, - ast_ty: &hir::Ty) - -> Ty<'tcx> + fn ast_ty_arg_to_ty(&self, + rscope: &RegionScope, + def: Option<&ty::TypeParameterDef<'tcx>>, + region_substs: &Substs<'tcx>, + ast_ty: &hir::Ty) + -> Ty<'tcx> { let tcx = self.tcx(); - if let Some(def) = decl_generics.types.opt_get(TypeSpace, index) { + if let Some(def) = def { let object_lifetime_default = def.object_lifetime_default.subst(tcx, region_substs); let rscope1 = &ObjectLifetimeDefaultRscope::new(rscope, object_lifetime_default); self.ast_ty_to_ty(rscope1, ast_ty) @@ -2194,7 +2121,7 @@ pub fn partition_bounds<'a, 'b, 'gcx, 'tcx>(tcx: TyCtxt<'a, 'gcx, 'tcx>, let parameters = &segments[segments.len() - 1].parameters; if !parameters.types().is_empty() { check_type_argument_count(tcx, b.trait_ref.path.span, - parameters.types().len(), 0, 0); + parameters.types().len(), &[]); } if !parameters.lifetimes().is_empty() { report_lifetime_number_error(tcx, b.trait_ref.path.span, @@ -2225,7 +2152,9 @@ pub fn partition_bounds<'a, 'b, 'gcx, 'tcx>(tcx: TyCtxt<'a, 'gcx, 'tcx>, } fn check_type_argument_count(tcx: TyCtxt, span: Span, supplied: usize, - required: usize, accepted: usize) { + ty_param_defs: &[ty::TypeParameterDef]) { + let accepted = ty_param_defs.len(); + let required = ty_param_defs.iter().take_while(|x| x.default.is_none()) .count(); if supplied < required { let expected = if required < accepted { "expected at least" diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index b5018d51b7f56..c41bb1930d458 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -88,7 +88,7 @@ use hir::def::{Def, PathResolution}; use hir::def_id::DefId; use hir::pat_util; use rustc::infer::{self, InferCtxt, InferOk, TypeOrigin, TypeTrace, type_variable}; -use rustc::ty::subst::{self, Subst, Substs, VecPerParamSpace, ParamSpace}; +use rustc::ty::subst::{self, Subst, Substs}; use rustc::traits::{self, Reveal}; use rustc::ty::{GenericPredicates, TypeScheme}; use rustc::ty::{ParamTy, ParameterEnvironment}; @@ -1702,7 +1702,6 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { PathParamMode::Optional, &type_scheme.generics, path.segments.last().unwrap()); - let substs = self.tcx.mk_substs(substs); debug!("instantiate_type_path: ty={:?} substs={:?}", &type_scheme.ty, substs); let bounds = self.instantiate_bounds(path.span, substs, &type_predicates); let cause = traits::ObligationCause::new(path.span, self.body_id, @@ -4158,7 +4157,8 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { assert!(!segments.is_empty()); let mut ufcs_associated = None; - let mut segment_spaces: Vec<_>; + let mut type_segment = None; + let mut fn_segment = None; match def { // Case 1 and 1b. Reference to a *type* or *enum variant*. Def::SelfTy(..) | @@ -4172,40 +4172,18 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { Def::TyParam(..) => { // Everything but the final segment should have no // parameters at all. - segment_spaces = vec![None; segments.len() - 1]; - segment_spaces.push(Some(subst::TypeSpace)); + type_segment = segments.last(); } // Case 2. Reference to a top-level value. Def::Fn(..) | Def::Const(..) | Def::Static(..) => { - segment_spaces = vec![None; segments.len() - 1]; - segment_spaces.push(Some(subst::FnSpace)); - } - - // Case 3. Reference to a method. - Def::Method(def_id) => { - let container = self.tcx.impl_or_trait_item(def_id).container(); - match container { - ty::TraitContainer(trait_did) => { - callee::check_legal_trait_for_method_call(self.ccx, span, trait_did) - } - ty::ImplContainer(_) => {} - } - - if segments.len() >= 2 { - segment_spaces = vec![None; segments.len() - 2]; - segment_spaces.push(Some(subst::TypeSpace)); - segment_spaces.push(Some(subst::FnSpace)); - } else { - // `::method` will end up here, and so can `T::method`. - let self_ty = opt_self_ty.expect("UFCS sugared method missing Self"); - segment_spaces = vec![Some(subst::FnSpace)]; - ufcs_associated = Some((container, self_ty)); - } + fn_segment = segments.last(); } + // Case 3. Reference to a method or associated const. + Def::Method(def_id) | Def::AssociatedConst(def_id) => { let container = self.tcx.impl_or_trait_item(def_id).container(); match container { @@ -4216,15 +4194,13 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { } if segments.len() >= 2 { - segment_spaces = vec![None; segments.len() - 2]; - segment_spaces.push(Some(subst::TypeSpace)); - segment_spaces.push(None); + type_segment = Some(&segments[segments.len() - 2]); } else { - // `::CONST` will end up here, and so can `T::CONST`. - let self_ty = opt_self_ty.expect("UFCS sugared const missing Self"); - segment_spaces = vec![None]; + // `::assoc` will end up here, and so can `T::assoc`. + let self_ty = opt_self_ty.expect("UFCS sugared assoc missing Self"); ufcs_associated = Some((container, self_ty)); } + fn_segment = segments.last(); } // Other cases. Various nonsense that really shouldn't show up @@ -4234,51 +4210,27 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { Def::ForeignMod(..) | Def::Local(..) | Def::Label(..) | - Def::Upvar(..) => { - segment_spaces = vec![None; segments.len()]; - } + Def::Upvar(..) => {} Def::Err => { self.set_tainted_by_errors(); - segment_spaces = vec![None; segments.len()]; } } - assert_eq!(segment_spaces.len(), segments.len()); // In `>::method`, `A` and `B` are mandatory, but // `opt_self_ty` can also be Some for `Foo::method`, where Foo's // type parameters are not mandatory. let require_type_space = opt_self_ty.is_some() && ufcs_associated.is_none(); - debug!("segment_spaces={:?}", segment_spaces); - - // Next, examine the definition, and determine how many type - // parameters we expect from each space. - let type_defs = &type_scheme.generics.types; - let region_defs = &type_scheme.generics.regions; + debug!("type_segment={:?} fn_segment={:?}", type_segment, fn_segment); // Now that we have categorized what space the parameters for each // segment belong to, let's sort out the parameters that the user // provided (if any) into their appropriate spaces. We'll also report // errors if type parameters are provided in an inappropriate place. - let mut substs = Substs::empty(); - for (&opt_space, segment) in segment_spaces.iter().zip(segments) { - if let Some(space) = opt_space { - self.push_explicit_parameters_from_segment_to_substs(space, - span, - type_defs, - region_defs, - segment, - &mut substs); - } else { - self.tcx.prohibit_type_params(slice::ref_slice(segment)); - } - } - if let Some(self_ty) = opt_self_ty { - if type_defs.len(subst::SelfSpace) == 1 { - substs.types.push(subst::SelfSpace, self_ty); - } - } + let poly_segments = type_segment.is_some() as usize + + fn_segment.is_some() as usize; + self.tcx.prohibit_type_params(&segments[..segments.len() - poly_segments]); // Now we have to compare the types that the user *actually* // provided against the types that were *expected*. If the user @@ -4286,19 +4238,77 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { // variables. If the user provided some types, we may still need // to add defaults. If the user provided *too many* types, that's // a problem. - for &space in &[subst::SelfSpace, subst::TypeSpace, subst::FnSpace] { - self.adjust_type_parameters(span, space, type_defs, - require_type_space, &mut substs); - assert_eq!(substs.types.len(space), type_defs.len(space)); + self.check_path_parameter_count(subst::TypeSpace, + span, + &type_scheme.generics, + !require_type_space, + &mut type_segment); + self.check_path_parameter_count(subst::FnSpace, + span, + &type_scheme.generics, + true, + &mut fn_segment); + + let substs = Substs::from_generics(&type_scheme.generics, |def, _| { + let i = def.index as usize; + let segment = match def.space { + subst::SelfSpace => None, + subst::TypeSpace => type_segment, + subst::FnSpace => fn_segment + }; + let lifetimes = match segment.map(|s| &s.parameters) { + Some(&hir::AngleBracketedParameters(ref data)) => &data.lifetimes[..], + Some(&hir::ParenthesizedParameters(_)) => bug!(), + None => &[] + }; - self.adjust_region_parameters(span, space, region_defs, &mut substs); - assert_eq!(substs.regions.len(space), region_defs.len(space)); - } + if let Some(ast_lifetime) = lifetimes.get(i) { + ast_region_to_region(self.tcx, ast_lifetime) + } else { + self.region_var_for_def(span, def) + } + }, |def, substs| { + let i = def.index as usize; + let segment = match def.space { + subst::SelfSpace => None, + subst::TypeSpace => type_segment, + subst::FnSpace => fn_segment + }; + let types = match segment.map(|s| &s.parameters) { + Some(&hir::AngleBracketedParameters(ref data)) => &data.types[..], + Some(&hir::ParenthesizedParameters(_)) => bug!(), + None => &[] + }; + let can_omit = def.space != subst::TypeSpace || !require_type_space; + let default = if can_omit && types.len() == 0 { + def.default + } else { + None + }; + + if def.space == subst::SelfSpace && opt_self_ty.is_some() { + // Self, which has been provided. + assert_eq!(i, 0); + opt_self_ty.unwrap() + } else if let Some(ast_ty) = types.get(i) { + // A provided type parameter. + self.to_ty(ast_ty) + } else if let Some(default) = default { + // No type parameter provided, but a default exists. + default.subst_spanned(self.tcx, substs, Some(span)) + } else { + // No type parameters were provided, we can infer all. + // This can also be reached in some error cases: + // We prefer to use inference variables instead of + // TyError to let type inference recover somewhat. + self.type_var_for_def(span, def, substs) + } + }); // The things we are substituting into the type should not contain // escaping late-bound regions, and nor should the base type scheme. let substs = self.tcx.mk_substs(substs); - assert!(!substs.has_regions_escaping_depth(0)); + assert!(!substs.has_escaping_regions()); assert!(!type_scheme.has_escaping_regions()); // Add all the obligations that are required, substituting and @@ -4349,246 +4359,79 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { ty_substituted } - /// Finds the parameters that the user provided and adds them to `substs`. If too many - /// parameters are provided, then reports an error and clears the output vector. - /// - /// We clear the output vector because that will cause the `adjust_XXX_parameters()` later to - /// use inference variables. This seems less likely to lead to derived errors. - /// - /// Note that we *do not* check for *too few* parameters here. Due to the presence of defaults - /// etc that is more complicated. I wanted however to do the reporting of *too many* parameters - /// here because we can easily use the precise span of the N+1'th parameter. - fn push_explicit_parameters_from_segment_to_substs(&self, - space: subst::ParamSpace, - span: Span, - type_defs: &VecPerParamSpace>, - region_defs: &VecPerParamSpace, - segment: &hir::PathSegment, - substs: &mut Substs<'tcx>) - { - match segment.parameters { - hir::AngleBracketedParameters(ref data) => { - self.push_explicit_angle_bracketed_parameters_from_segment_to_substs( - space, type_defs, region_defs, data, substs); - } - - hir::ParenthesizedParameters(ref data) => { - span_err!(self.tcx.sess, span, E0238, - "parenthesized parameters may only be used with a trait"); - self.push_explicit_parenthesized_parameters_from_segment_to_substs( - space, span, type_defs, data, substs); - } - } - } - - fn push_explicit_angle_bracketed_parameters_from_segment_to_substs(&self, - space: subst::ParamSpace, - type_defs: &VecPerParamSpace>, - region_defs: &VecPerParamSpace, - data: &hir::AngleBracketedParameterData, - substs: &mut Substs<'tcx>) - { - { - let type_count = type_defs.len(space); - assert_eq!(substs.types.len(space), 0); - for (i, typ) in data.types.iter().enumerate() { - let t = self.to_ty(&typ); - if i < type_count { - substs.types.push(space, t); - } else if i == type_count { - struct_span_err!(self.tcx.sess, typ.span, E0087, - "too many type parameters provided: \ - expected at most {} parameter{}, \ - found {} parameter{}", - type_count, - if type_count == 1 {""} else {"s"}, - data.types.len(), - if data.types.len() == 1 {""} else {"s"}) - .span_label(typ.span , &format!("expected {} parameter{}", - type_count, - if type_count == 1 {""} else {"s"})).emit(); - substs.types.truncate(space, 0); - break; - } + /// Report errors if the provided parameters are too few or too many. + fn check_path_parameter_count(&self, + space: subst::ParamSpace, + span: Span, + generics: &ty::Generics<'tcx>, + can_omit: bool, + segment: &mut Option<&hir::PathSegment>) { + let (lifetimes, types, bindings) = match segment.map(|s| &s.parameters) { + Some(&hir::AngleBracketedParameters(ref data)) => { + (&data.lifetimes[..], &data.types[..], &data.bindings[..]) } - } - - if !data.bindings.is_empty() { - span_err!(self.tcx.sess, data.bindings[0].span, E0182, - "unexpected binding of associated item in expression path \ - (only allowed in type paths)"); - } - - { - let region_count = region_defs.len(space); - assert_eq!(substs.regions.len(space), 0); - for (i, lifetime) in data.lifetimes.iter().enumerate() { - let r = ast_region_to_region(self.tcx, lifetime); - if i < region_count { - substs.regions.push(space, r); - } else if i == region_count { - span_err!(self.tcx.sess, lifetime.span, E0088, - "too many lifetime parameters provided: \ - expected {} parameter{}, found {} parameter{}", - region_count, - if region_count == 1 {""} else {"s"}, - data.lifetimes.len(), - if data.lifetimes.len() == 1 {""} else {"s"}); - substs.regions.truncate(space, 0); - break; - } + Some(&hir::ParenthesizedParameters(_)) => { + span_bug!(span, "parenthesized parameters cannot appear in ExprPath"); } - } - } - - /// As with - /// `push_explicit_angle_bracketed_parameters_from_segment_to_substs`, - /// but intended for `Foo(A,B) -> C` form. This expands to - /// roughly the same thing as `Foo<(A,B),C>`. One important - /// difference has to do with the treatment of anonymous - /// regions, which are translated into bound regions (NYI). - fn push_explicit_parenthesized_parameters_from_segment_to_substs(&self, - space: subst::ParamSpace, - span: Span, - type_defs: &VecPerParamSpace>, - data: &hir::ParenthesizedParameterData, - substs: &mut Substs<'tcx>) - { - let type_count = type_defs.len(space); - if type_count < 2 { - span_err!(self.tcx.sess, span, E0167, - "parenthesized form always supplies 2 type parameters, \ - but only {} parameter(s) were expected", - type_count); - } - - let input_tys: Vec = - data.inputs.iter().map(|ty| self.to_ty(&ty)).collect(); - - let tuple_ty = self.tcx.mk_tup(input_tys); - - if type_count >= 1 { - substs.types.push(space, tuple_ty); - } - - let output_ty: Option = - data.output.as_ref().map(|ty| self.to_ty(&ty)); - - let output_ty = - output_ty.unwrap_or(self.tcx.mk_nil()); + None => (&[][..], &[][..], &[][..]) + }; - if type_count >= 2 { - substs.types.push(space, output_ty); - } - } + let count = |n| { + format!("{} parameter{}", n, if n == 1 { "" } else { "s" }) + }; - fn adjust_type_parameters(&self, - span: Span, - space: ParamSpace, - defs: &VecPerParamSpace>, - require_type_space: bool, - substs: &mut Substs<'tcx>) - { - let provided_len = substs.types.len(space); - let desired = defs.get_slice(space); - let required_len = desired.iter() - .take_while(|d| d.default.is_none()) - .count(); - - debug!("adjust_type_parameters(space={:?}, \ - provided_len={}, \ - desired_len={}, \ - required_len={})", - space, - provided_len, - desired.len(), - required_len); - - // Enforced by `push_explicit_parameters_from_segment_to_substs()`. - assert!(provided_len <= desired.len()); - - // Nothing specified at all: supply inference variables for - // everything. - if provided_len == 0 && !(require_type_space && space == subst::TypeSpace) { - substs.types.replace(space, Vec::new()); - for def in desired { - let ty_var = self.type_var_for_def(span, def, substs); - substs.types.push(def.space, ty_var); - } - return; + // Check provided lifetime parameters. + let lifetime_defs = generics.regions.get_slice(space); + if lifetimes.len() > lifetime_defs.len() { + let span = lifetimes[lifetime_defs.len()].span; + span_err!(self.tcx.sess, span, E0088, + "too many lifetime parameters provided: \ + expected {}, found {}", + count(lifetime_defs.len()), + count(lifetimes.len())); + } else if lifetimes.len() > 0 && lifetimes.len() < lifetime_defs.len() { + span_err!(self.tcx.sess, span, E0090, + "too few lifetime parameters provided: \ + expected {}, found {}", + count(lifetime_defs.len()), + count(lifetimes.len())); } - // Too few parameters specified: report an error and use Err - // for everything. - if provided_len < required_len { + // Check provided type parameters. + let type_defs = generics.types.get_slice(space); + let required_len = type_defs.iter() + .take_while(|d| d.default.is_none()) + .count(); + if types.len() > type_defs.len() { + let span = types[type_defs.len()].span; + struct_span_err!(self.tcx.sess, span, E0087, + "too many type parameters provided: \ + expected at most {}, found {}", + count(type_defs.len()), + count(types.len())) + .span_label(span, &format!("expected {}", + count(type_defs.len()))).emit(); + + // To prevent derived errors to accumulate due to extra + // type parameters, we force instantiate_value_path to + // use inference variables instead of the provided types. + *segment = None; + } else if !(can_omit && types.len() == 0) && types.len() < required_len { let qualifier = - if desired.len() != required_len { "at least " } else { "" }; + if type_defs.len() != required_len { "at least " } else { "" }; span_err!(self.tcx.sess, span, E0089, - "too few type parameters provided: expected {}{} parameter{}, \ - found {} parameter{}", - qualifier, required_len, - if required_len == 1 {""} else {"s"}, - provided_len, - if provided_len == 1 {""} else {"s"}); - substs.types.replace(space, vec![self.tcx.types.err; desired.len()]); - return; - } - - // Otherwise, add in any optional parameters that the user - // omitted. The case of *too many* parameters is handled - // already by - // push_explicit_parameters_from_segment_to_substs(). Note - // that the *default* type are expressed in terms of all prior - // parameters, so we have to substitute as we go with the - // partial substitution that we have built up. - for i in provided_len..desired.len() { - let default = desired[i].default.unwrap(); - let default = default.subst_spanned(self.tcx, substs, Some(span)); - substs.types.push(space, default); - } - assert_eq!(substs.types.len(space), desired.len()); - - debug!("Final substs: {:?}", substs); - } - - fn adjust_region_parameters(&self, - span: Span, - space: ParamSpace, - defs: &VecPerParamSpace, - substs: &mut Substs) - { - let provided_len = substs.regions.len(space); - let desired = defs.get_slice(space); - - // Enforced by `push_explicit_parameters_from_segment_to_substs()`. - assert!(provided_len <= desired.len()); - - // If nothing was provided, just use inference variables. - if provided_len == 0 { - substs.regions.replace( - space, - self.region_vars_for_defs(span, desired)); - return; + "too few type parameters provided: \ + expected {}{}, found {}", + qualifier, + count(required_len), + count(types.len())); } - // If just the right number were provided, everybody is happy. - if provided_len == desired.len() { - return; + if !bindings.is_empty() { + span_err!(self.tcx.sess, bindings[0].span, E0182, + "unexpected binding of associated item in expression path \ + (only allowed in type paths)"); } - - // Otherwise, too few were provided. Report an error and then - // use inference variables. - span_err!(self.tcx.sess, span, E0090, - "too few lifetime parameters provided: expected {} parameter{}, \ - found {} parameter{}", - desired.len(), - if desired.len() == 1 {""} else {"s"}, - provided_len, - if provided_len == 1 {""} else {"s"}); - - substs.regions.replace( - space, - self.region_vars_for_defs(span, desired)); } fn structurally_resolve_type_or_else(&self, sp: Span, ty: Ty<'tcx>, f: F) diff --git a/src/librustc_typeck/diagnostics.rs b/src/librustc_typeck/diagnostics.rs index 337b87ce994ad..fe1cb3d6badcd 100644 --- a/src/librustc_typeck/diagnostics.rs +++ b/src/librustc_typeck/diagnostics.rs @@ -4018,7 +4018,7 @@ register_diagnostics! { // E0141, // E0159, // use of trait `{}` as struct constructor // E0163, // merged into E0071 - E0167, +// E0167, // E0168, // E0173, // manual implementations of unboxed closure traits are experimental // E0174, @@ -4053,7 +4053,7 @@ register_diagnostics! { // E0235, // structure constructor specifies a structure of type but // E0236, // no lang item for range syntax // E0237, // no lang item for range syntax - E0238, // parenthesized parameters may only be used with a trait +// E0238, // parenthesized parameters may only be used with a trait // E0239, // `next` method of `Iterator` trait has unexpected type // E0240, // E0241, From 4158673ad7150f4fa02fbea3654e8cf1628beb0b Mon Sep 17 00:00:00 2001 From: Eduard Burtescu Date: Mon, 8 Aug 2016 23:39:49 +0300 Subject: [PATCH 08/12] rustc: reduce Substs and Generics to a simple immutable API. --- src/librustc/infer/error_reporting.rs | 2 +- src/librustc/infer/mod.rs | 44 +- src/librustc/middle/cstore.rs | 16 +- src/librustc/middle/dead.rs | 25 +- src/librustc/mir/repr.rs | 9 +- src/librustc/traits/error_reporting.rs | 4 +- src/librustc/traits/fulfill.rs | 3 +- src/librustc/traits/mod.rs | 4 +- src/librustc/traits/object_safety.rs | 19 +- src/librustc/traits/select.rs | 49 +- src/librustc/traits/specialize/mod.rs | 13 +- .../traits/specialize/specialization_graph.rs | 19 +- src/librustc/traits/util.rs | 22 +- src/librustc/ty/context.rs | 14 +- src/librustc/ty/flags.rs | 4 +- src/librustc/ty/fold.rs | 6 +- src/librustc/ty/maps.rs | 5 +- src/librustc/ty/mod.rs | 170 +++-- src/librustc/ty/relate.rs | 114 +-- src/librustc/ty/structural_impls.rs | 26 +- src/librustc/ty/sty.rs | 32 +- src/librustc/ty/subst.rs | 347 ++++----- src/librustc/ty/trait_def.rs | 4 +- src/librustc/ty/util.rs | 9 +- src/librustc/util/ppaux.rs | 128 ++-- .../borrowck/mir/elaborate_drops.rs | 5 +- src/librustc_const_eval/eval.rs | 16 +- src/librustc_driver/test.rs | 14 +- src/librustc_lint/builtin.rs | 11 +- src/librustc_metadata/astencode.rs | 18 +- src/librustc_metadata/common.rs | 13 +- src/librustc_metadata/csearch.rs | 15 +- src/librustc_metadata/decoder.rs | 80 +-- src/librustc_metadata/encoder.rs | 55 +- src/librustc_metadata/tls_context.rs | 2 +- src/librustc_metadata/tydecode.rs | 53 +- src/librustc_metadata/tyencode.rs | 27 +- src/librustc_mir/build/scope.rs | 2 +- src/librustc_mir/hair/cx/mod.rs | 6 +- src/librustc_save_analysis/lib.rs | 3 +- src/librustc_trans/_match.rs | 2 +- src/librustc_trans/adt.rs | 4 +- src/librustc_trans/base.rs | 10 +- src/librustc_trans/callee.rs | 26 +- src/librustc_trans/collector.rs | 51 +- src/librustc_trans/common.rs | 4 +- src/librustc_trans/consts.rs | 8 +- src/librustc_trans/context.rs | 20 +- src/librustc_trans/controlflow.rs | 4 +- src/librustc_trans/debuginfo/metadata.rs | 8 +- src/librustc_trans/debuginfo/mod.rs | 2 +- src/librustc_trans/debuginfo/type_names.rs | 4 +- src/librustc_trans/expr.rs | 2 +- src/librustc_trans/glue.rs | 4 +- src/librustc_trans/intrinsic.rs | 5 +- src/librustc_trans/meth.rs | 27 +- src/librustc_trans/mir/constant.rs | 9 +- src/librustc_trans/monomorphize.rs | 5 +- src/librustc_trans/partitioning.rs | 4 +- src/librustc_trans/trans_item.rs | 7 +- src/librustc_trans/type_of.rs | 5 +- src/librustc_typeck/astconv.rs | 46 +- src/librustc_typeck/check/_match.rs | 19 +- src/librustc_typeck/check/autoderef.rs | 2 +- src/librustc_typeck/check/compare_method.rs | 20 +- src/librustc_typeck/check/dropck.rs | 17 +- src/librustc_typeck/check/intrinsic.rs | 8 +- src/librustc_typeck/check/method/confirm.rs | 31 +- src/librustc_typeck/check/method/mod.rs | 6 +- src/librustc_typeck/check/method/probe.rs | 59 +- src/librustc_typeck/check/method/suggest.rs | 6 +- src/librustc_typeck/check/mod.rs | 120 ++-- src/librustc_typeck/check/writeback.rs | 41 +- src/librustc_typeck/collect.rs | 662 ++++++++---------- src/librustc_typeck/lib.rs | 4 +- src/librustc_typeck/rscope.rs | 31 +- src/librustc_typeck/variance/constraints.rs | 9 +- src/librustc_typeck/variance/solve.rs | 30 +- src/librustdoc/clean/inline.rs | 20 +- src/librustdoc/clean/mod.rs | 24 +- 80 files changed, 1226 insertions(+), 1548 deletions(-) diff --git a/src/librustc/infer/error_reporting.rs b/src/librustc/infer/error_reporting.rs index b0dec3277a996..21fccd2c6132d 100644 --- a/src/librustc/infer/error_reporting.rs +++ b/src/librustc/infer/error_reporting.rs @@ -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; diff --git a/src/librustc/infer/mod.rs b/src/librustc/infer/mod.rs index 1e360cd43da12..1b65b5dae0748 100644 --- a/src/librustc/infer/mod.rs +++ b/src/librustc/infer/mod.rs @@ -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}; @@ -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 { diff --git a/src/librustc/middle/cstore.rs b/src/librustc/middle/cstore.rs index 481fd332404ba..abb22783ddc84 100644 --- a/src/librustc/middle/cstore.rs +++ b/src/librustc/middle/cstore.rs @@ -154,7 +154,7 @@ pub trait CrateStore<'tcx> { fn item_variances(&self, def: DefId) -> ty::ItemVariances; fn repr_attrs(&self, def: DefId) -> Vec; 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>; fn item_name(&self, def: DefId) -> ast::Name; fn opt_item_name(&self, def: DefId) -> Option; @@ -162,6 +162,8 @@ pub trait CrateStore<'tcx> { -> 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; 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>; @@ -187,8 +189,7 @@ pub trait CrateStore<'tcx> { fn impl_parent(&self, impl_def_id: DefId) -> Option; // trait/impl-item info - fn trait_of_item<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) - -> Option; + fn trait_of_item(&self, def_id: DefId) -> Option; fn impl_or_trait_item<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, def: DefId) -> Option>; @@ -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 { 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> { bug!("visible_parent_map") } @@ -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 { bug!("item_attrs") } fn trait_def<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, def: DefId)-> ty::TraitDef<'tcx> { bug!("trait_def") } @@ -379,8 +382,7 @@ impl<'tcx> CrateStore<'tcx> for DummyCrateStore { fn impl_parent(&self, def: DefId) -> Option { bug!("impl_parent") } // trait/impl-item info - fn trait_of_item<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) - -> Option { bug!("trait_of_item") } + fn trait_of_item(&self, def_id: DefId) -> Option { bug!("trait_of_item") } fn impl_or_trait_item<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, def: DefId) -> Option> { bug!("impl_or_trait_item") } @@ -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; } diff --git a/src/librustc/middle/dead.rs b/src/librustc/middle/dead.rs index 2b59e603cc897..7412b5fc8048f 100644 --- a/src/librustc/middle/dead.rs +++ b/src/librustc/middle/dead.rs @@ -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; @@ -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()); diff --git a/src/librustc/mir/repr.rs b/src/librustc/mir/repr.rs index 2bde3d6554fee..f511d820fac58 100644 --- a/src/librustc/mir/repr.rs +++ b/src/librustc/mir/repr.rs @@ -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(()), @@ -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 ")?; diff --git a/src/librustc/traits/error_reporting.rs b/src/librustc/traits/error_reporting.rs index 5d50eac1716a3..e67c0ba8053d7 100644 --- a/src/librustc/traits/error_reporting.rs +++ b/src/librustc/traits/error_reporting.rs @@ -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() diff --git a/src/librustc/traits/fulfill.rs b/src/librustc/traits/fulfill.rs index 1ee1dc50b717d..3698027dca887 100644 --- a/src/librustc/traits/fulfill.rs +++ b/src/librustc/traits/fulfill.rs @@ -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(), diff --git a/src/librustc/traits/mod.rs b/src/librustc/traits/mod.rs index dc0807ba38fae..b86a54f01cf49 100644 --- a/src/librustc/traits/mod.rs +++ b/src/librustc/traits/mod.rs @@ -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; @@ -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 } diff --git a/src/librustc/traits/object_safety.rs b/src/librustc/traits/object_safety.rs index 8ddb14e08e31e..ecfa7930d0294 100644 --- a/src/librustc/traits/object_safety.rs +++ b/src/librustc/traits/object_safety.rs @@ -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 { @@ -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; } @@ -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; } diff --git a/src/librustc/traits/select.rs b/src/librustc/traits/select.rs index 73108e7d37f88..9099d6cd740d1 100644 --- a/src/librustc/traits/select.rs +++ b/src/librustc/traits/select.rs @@ -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; @@ -1935,7 +1936,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { // for `PhantomData`, 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) => { @@ -2584,17 +2585,16 @@ 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); } @@ -2602,12 +2602,16 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { // 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); } } @@ -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) @@ -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, diff --git a/src/librustc/traits/specialize/mod.rs b/src/librustc/traits/specialize/mod.rs index 38cccb9753df6..42865ca927de3 100644 --- a/src/librustc/traits/specialize/mod.rs +++ b/src/librustc/traits/specialize/mod.rs @@ -18,7 +18,7 @@ // fits together with the rest of the trait machinery. use super::{SelectionContext, FulfillmentContext}; -use super::util::{fresh_type_vars_for_impl, impl_trait_ref_and_oblig}; +use super::util::impl_trait_ref_and_oblig; use rustc_data_structures::fnv::FnvHashMap; use hir::def_id::DefId; @@ -101,7 +101,7 @@ pub fn translate_substs<'a, 'gcx, 'tcx>(infcx: &InferCtxt<'a, 'gcx, 'tcx>, }; // directly inherent the method generics, since those do not vary across impls - infcx.tcx.mk_substs(target_substs.with_method_from_subst(source_substs)) + source_substs.rebase_onto(infcx.tcx, source_impl, target_substs) } /// Is impl1 a specialization of impl2? @@ -141,11 +141,8 @@ pub fn specializes<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, } // create a parameter environment corresponding to a (skolemized) instantiation of impl1 - let scheme = tcx.lookup_item_type(impl1_def_id); - let predicates = tcx.lookup_predicates(impl1_def_id); let mut penv = tcx.construct_parameter_environment(DUMMY_SP, - &scheme.generics, - &predicates, + impl1_def_id, region::DUMMY_CODE_EXTENT); let impl1_trait_ref = tcx.impl_trait_ref(impl1_def_id) .unwrap() @@ -188,10 +185,10 @@ fn fulfill_implication<'a, 'gcx, 'tcx>(infcx: &InferCtxt<'a, 'gcx, 'tcx>, target_impl: DefId) -> Result<&'tcx Substs<'tcx>, ()> { let selcx = &mut SelectionContext::new(&infcx); - let target_substs = fresh_type_vars_for_impl(&infcx, DUMMY_SP, target_impl); + let target_substs = infcx.fresh_substs_for_item(DUMMY_SP, target_impl); let (target_trait_ref, obligations) = impl_trait_ref_and_oblig(selcx, target_impl, - &target_substs); + target_substs); // do the impls unify? If not, no specialization. if let Err(_) = infcx.eq_trait_refs(true, diff --git a/src/librustc/traits/specialize/specialization_graph.rs b/src/librustc/traits/specialize/specialization_graph.rs index a47cd23c64aa6..13193e1b2d71b 100644 --- a/src/librustc/traits/specialize/specialization_graph.rs +++ b/src/librustc/traits/specialize/specialization_graph.rs @@ -122,19 +122,18 @@ impl<'a, 'gcx, 'tcx> Children { if le == ge { // overlap, but no specialization; error out let trait_ref = impl_header.trait_ref.unwrap(); + let self_ty = trait_ref.self_ty(); Err(OverlapError { with_impl: possible_sibling, trait_desc: trait_ref.to_string(), - self_desc: trait_ref.substs.self_ty().and_then(|ty| { - // only report the Self type if it has at least - // some outer concrete shell; otherwise, it's - // not adding much information. - if ty.has_concrete_skeleton() { - Some(ty.to_string()) - } else { - None - } - }) + // only report the Self type if it has at least + // some outer concrete shell; otherwise, it's + // not adding much information. + self_desc: if self_ty.has_concrete_skeleton() { + Some(self_ty.to_string()) + } else { + None + } }) } else { Ok((le, ge)) diff --git a/src/librustc/traits/util.rs b/src/librustc/traits/util.rs index 80a3ad9122bd1..1954ce1993c5e 100644 --- a/src/librustc/traits/util.rs +++ b/src/librustc/traits/util.rs @@ -9,10 +9,8 @@ // except according to those terms. use hir::def_id::DefId; -use infer::InferCtxt; use ty::subst::{Subst, Substs}; use ty::{self, Ty, TyCtxt, ToPredicate, ToPolyTraitRef}; -use syntax_pos::Span; use util::common::ErrorReported; use util::nodemap::FnvHashSet; @@ -349,19 +347,6 @@ pub fn impl_trait_ref_and_oblig<'a, 'gcx, 'tcx>(selcx: &mut SelectionContext<'a, (impl_trait_ref, impl_obligations) } -// determine the `self` type, using fresh variables for all variables -// declared on the impl declaration e.g., `impl for Box<[(A,B)]>` -// would return ($0, $1) where $0 and $1 are freshly instantiated type -// variables. -pub fn fresh_type_vars_for_impl<'a, 'gcx, 'tcx>(infcx: &InferCtxt<'a, 'gcx, 'tcx>, - span: Span, - impl_def_id: DefId) - -> &'tcx Substs<'tcx> -{ - let impl_generics = infcx.tcx.lookup_item_type(impl_def_id).generics; - infcx.fresh_substs_for_generics(span, &impl_generics) -} - /// See `super::obligations_for_generics` pub fn predicates_for_generics<'tcx>(cause: ObligationCause<'tcx>, recursion_depth: usize, @@ -401,7 +386,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { Ok(def_id) => { Ok(ty::TraitRef { def_id: def_id, - substs: self.mk_substs(Substs::empty().with_self_ty(param_ty)) + substs: Substs::new_trait(self, vec![], vec![], param_ty) }) } Err(e) => { @@ -421,7 +406,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { { let trait_ref = ty::TraitRef { def_id: trait_def_id, - substs: self.mk_substs(Substs::new_trait(ty_params, vec![], param_ty)) + substs: Substs::new_trait(self, ty_params, vec![], param_ty) }; predicate_for_trait_ref(cause, trait_ref, recursion_depth) } @@ -509,10 +494,9 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { TupleArgumentsFlag::No => sig.0.inputs[0], TupleArgumentsFlag::Yes => self.mk_tup(sig.0.inputs.to_vec()), }; - let trait_substs = Substs::new_trait(vec![arguments_tuple], vec![], self_ty); let trait_ref = ty::TraitRef { def_id: fn_trait_def_id, - substs: self.mk_substs(trait_substs), + substs: Substs::new_trait(self, vec![arguments_tuple], vec![], self_ty), }; ty::Binder((trait_ref, sig.0.output)) } diff --git a/src/librustc/ty/context.rs b/src/librustc/ty/context.rs index dfb5482ad873b..9356b408a51cb 100644 --- a/src/librustc/ty/context.rs +++ b/src/librustc/ty/context.rs @@ -63,6 +63,7 @@ pub struct CtxtArenas<'tcx> { layout: TypedArena, // references + generics: TypedArena>, trait_defs: TypedArena>, adt_defs: TypedArena>, } @@ -78,6 +79,7 @@ impl<'tcx> CtxtArenas<'tcx> { stability: TypedArena::new(), layout: TypedArena::new(), + generics: TypedArena::new(), trait_defs: TypedArena::new(), adt_defs: TypedArena::new() } @@ -341,7 +343,8 @@ pub struct GlobalCtxt<'tcx> { pub adt_defs: RefCell>>, /// Maps from the def-id of an item (trait/struct/enum/fn) to its - /// associated predicates. + /// associated generics and predicates. + pub generics: RefCell>>, pub predicates: RefCell>>, /// Maps from the def-id of a trait to the list of @@ -583,13 +586,19 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { self.tables.borrow_mut().node_types.insert(id, ty); } + pub fn alloc_generics(self, generics: ty::Generics<'gcx>) + -> &'gcx ty::Generics<'gcx> { + self.global_interners.arenas.generics.alloc(generics) + } + pub fn intern_trait_def(self, def: ty::TraitDef<'gcx>) -> &'gcx ty::TraitDef<'gcx> { let did = def.trait_ref.def_id; - let interned = self.global_interners.arenas.trait_defs.alloc(def); + let interned = self.alloc_trait_def(def); if let Some(prev) = self.trait_defs.borrow_mut().insert(did, interned) { bug!("Tried to overwrite interned TraitDef: {:?}", prev) } + self.generics.borrow_mut().insert(did, interned.generics); interned } @@ -711,6 +720,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { impl_trait_refs: RefCell::new(DepTrackingMap::new(dep_graph.clone())), trait_defs: RefCell::new(DepTrackingMap::new(dep_graph.clone())), adt_defs: RefCell::new(DepTrackingMap::new(dep_graph.clone())), + generics: RefCell::new(DepTrackingMap::new(dep_graph.clone())), predicates: RefCell::new(DepTrackingMap::new(dep_graph.clone())), super_predicates: RefCell::new(DepTrackingMap::new(dep_graph.clone())), fulfilled_predicates: RefCell::new(fulfilled_predicates), diff --git a/src/librustc/ty/flags.rs b/src/librustc/ty/flags.rs index 6cc759c420d29..312b09cd27dfc 100644 --- a/src/librustc/ty/flags.rs +++ b/src/librustc/ty/flags.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use ty::subst; +use ty::subst::{self, Substs}; use ty::{self, Ty, TypeFlags, TypeFoldable}; pub struct FlagComputation { @@ -207,7 +207,7 @@ impl FlagComputation { self.add_substs(projection_ty.trait_ref.substs); } - fn add_substs(&mut self, substs: &subst::Substs) { + fn add_substs(&mut self, substs: &Substs) { self.add_tys(substs.types.as_full_slice()); for &r in substs.regions.as_full_slice() { self.add_region(r); diff --git a/src/librustc/ty/fold.rs b/src/librustc/ty/fold.rs index 597261cca72bf..2e114a801d6ed 100644 --- a/src/librustc/ty/fold.rs +++ b/src/librustc/ty/fold.rs @@ -40,7 +40,7 @@ //! and does not need to visit anything else. use middle::region; -use ty::subst; +use ty::subst::Substs; use ty::adjustment; use ty::{self, Binder, Ty, TyCtxt, TypeFlags}; @@ -145,8 +145,8 @@ pub trait TypeFolder<'gcx: 'tcx, 'tcx> : Sized { } fn fold_substs(&mut self, - substs: &'tcx subst::Substs<'tcx>) - -> &'tcx subst::Substs<'tcx> { + substs: &'tcx Substs<'tcx>) + -> &'tcx Substs<'tcx> { substs.super_fold_with(self) } diff --git a/src/librustc/ty/maps.rs b/src/librustc/ty/maps.rs index 57b1dd66bea9d..d5686906e6a7b 100644 --- a/src/librustc/ty/maps.rs +++ b/src/librustc/ty/maps.rs @@ -10,7 +10,7 @@ use dep_graph::{DepNode, DepTrackingMapConfig}; use hir::def_id::DefId; -use ty; +use ty::{self, Ty}; use std::marker::PhantomData; use std::rc::Rc; use syntax::{attr, ast}; @@ -30,7 +30,8 @@ macro_rules! dep_map_ty { } dep_map_ty! { ImplOrTraitItems: ImplOrTraitItems(DefId) -> ty::ImplOrTraitItem<'tcx> } -dep_map_ty! { Tcache: ItemSignature(DefId) -> ty::TypeScheme<'tcx> } +dep_map_ty! { Tcache: ItemSignature(DefId) -> Ty<'tcx> } +dep_map_ty! { Generics: ItemSignature(DefId) -> &'tcx ty::Generics<'tcx> } dep_map_ty! { Predicates: ItemSignature(DefId) -> ty::GenericPredicates<'tcx> } dep_map_ty! { SuperPredicates: ItemSignature(DefId) -> ty::GenericPredicates<'tcx> } dep_map_ty! { TraitItemDefIds: TraitItemDefIds(DefId) -> Rc> } diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs index 6ac57a877a759..36784e4006461 100644 --- a/src/librustc/ty/mod.rs +++ b/src/librustc/ty/mod.rs @@ -173,15 +173,14 @@ impl<'a, 'gcx, 'tcx> ImplHeader<'tcx> { -> ImplHeader<'tcx> { let tcx = selcx.tcx(); - let impl_generics = tcx.lookup_item_type(impl_def_id).generics; - let impl_substs = selcx.infcx().fresh_substs_for_generics(DUMMY_SP, &impl_generics); + let impl_substs = selcx.infcx().fresh_substs_for_item(DUMMY_SP, impl_def_id); let header = ImplHeader { impl_def_id: impl_def_id, self_ty: tcx.lookup_item_type(impl_def_id).ty, trait_ref: tcx.impl_trait_ref(impl_def_id), predicates: tcx.lookup_predicates(impl_def_id).predicates - }.subst(tcx, &impl_substs); + }.subst(tcx, impl_substs); let traits::Normalized { value: mut header, obligations } = traits::normalize(selcx, traits::ObligationCause::dummy(), &header); @@ -348,7 +347,7 @@ impl Visibility { #[derive(Clone, Debug)] pub struct Method<'tcx> { pub name: Name, - pub generics: Generics<'tcx>, + pub generics: &'tcx Generics<'tcx>, pub predicates: GenericPredicates<'tcx>, pub fty: &'tcx BareFnTy<'tcx>, pub explicit_self: ExplicitSelfCategory, @@ -360,7 +359,7 @@ pub struct Method<'tcx> { impl<'tcx> Method<'tcx> { pub fn new(name: Name, - generics: ty::Generics<'tcx>, + generics: &'tcx ty::Generics<'tcx>, predicates: GenericPredicates<'tcx>, fty: &'tcx BareFnTy<'tcx>, explicit_self: ExplicitSelfCategory, @@ -453,7 +452,7 @@ pub struct MethodCallee<'tcx> { /// Impl method ID, for inherent methods, or trait method ID, otherwise. pub def_id: DefId, pub ty: Ty<'tcx>, - pub substs: &'tcx subst::Substs<'tcx> + pub substs: &'tcx Substs<'tcx> } /// With method calls, we store some extra information in @@ -760,6 +759,7 @@ impl RegionParameterDef { pub struct Generics<'tcx> { pub types: VecPerParamSpace>, pub regions: VecPerParamSpace, + pub has_self: bool, } impl<'tcx> Generics<'tcx> { @@ -767,6 +767,7 @@ impl<'tcx> Generics<'tcx> { Generics { types: VecPerParamSpace::empty(), regions: VecPerParamSpace::empty(), + has_self: false, } } @@ -1224,7 +1225,7 @@ impl<'tcx> TraitRef<'tcx> { } pub fn self_ty(&self) -> Ty<'tcx> { - self.substs.self_ty().unwrap() + *self.substs.types.get(subst::SelfSpace, 0) } pub fn input_types(&self) -> &[Ty<'tcx>] { @@ -1298,23 +1299,17 @@ impl<'a, 'tcx> ParameterEnvironment<'tcx> { // so for now just grab environment for the impl let impl_id = tcx.map.get_parent(id); let impl_def_id = tcx.map.local_def_id(impl_id); - let scheme = tcx.lookup_item_type(impl_def_id); - let predicates = tcx.lookup_predicates(impl_def_id); tcx.construct_parameter_environment(impl_item.span, - &scheme.generics, - &predicates, + impl_def_id, tcx.region_maps.item_extent(id)) } hir::ImplItemKind::Method(_, ref body) => { let method_def_id = tcx.map.local_def_id(id); match tcx.impl_or_trait_item(method_def_id) { MethodTraitItem(ref method_ty) => { - let method_generics = &method_ty.generics; - let method_bounds = &method_ty.predicates; tcx.construct_parameter_environment( impl_item.span, - method_generics, - method_bounds, + method_ty.def_id, tcx.region_maps.call_site_extent(id, body.id)) } _ => { @@ -1332,11 +1327,8 @@ impl<'a, 'tcx> ParameterEnvironment<'tcx> { // so for now just grab environment for the trait let trait_id = tcx.map.get_parent(id); let trait_def_id = tcx.map.local_def_id(trait_id); - let trait_def = tcx.lookup_trait_def(trait_def_id); - let predicates = tcx.lookup_predicates(trait_def_id); tcx.construct_parameter_environment(trait_item.span, - &trait_def.generics, - &predicates, + trait_def_id, tcx.region_maps.item_extent(id)) } hir::MethodTraitItem(_, ref body) => { @@ -1346,8 +1338,6 @@ impl<'a, 'tcx> ParameterEnvironment<'tcx> { let method_def_id = tcx.map.local_def_id(id); match tcx.impl_or_trait_item(method_def_id) { MethodTraitItem(ref method_ty) => { - let method_generics = &method_ty.generics; - let method_bounds = &method_ty.predicates; let extent = if let Some(ref body) = *body { // default impl: use call_site extent as free_id_outlive bound. tcx.region_maps.call_site_extent(id, body.id) @@ -1357,8 +1347,7 @@ impl<'a, 'tcx> ParameterEnvironment<'tcx> { }; tcx.construct_parameter_environment( trait_item.span, - method_generics, - method_bounds, + method_ty.def_id, extent) } _ => { @@ -1375,13 +1364,10 @@ impl<'a, 'tcx> ParameterEnvironment<'tcx> { hir::ItemFn(_, _, _, _, _, ref body) => { // We assume this is a function. let fn_def_id = tcx.map.local_def_id(id); - let fn_scheme = tcx.lookup_item_type(fn_def_id); - let fn_predicates = tcx.lookup_predicates(fn_def_id); tcx.construct_parameter_environment( item.span, - &fn_scheme.generics, - &fn_predicates, + fn_def_id, tcx.region_maps.call_site_extent(id, body.id)) } hir::ItemEnum(..) | @@ -1391,20 +1377,14 @@ impl<'a, 'tcx> ParameterEnvironment<'tcx> { hir::ItemConst(..) | hir::ItemStatic(..) => { let def_id = tcx.map.local_def_id(id); - let scheme = tcx.lookup_item_type(def_id); - let predicates = tcx.lookup_predicates(def_id); tcx.construct_parameter_environment(item.span, - &scheme.generics, - &predicates, + def_id, tcx.region_maps.item_extent(id)) } hir::ItemTrait(..) => { let def_id = tcx.map.local_def_id(id); - let trait_def = tcx.lookup_trait_def(def_id); - let predicates = tcx.lookup_predicates(def_id); tcx.construct_parameter_environment(item.span, - &trait_def.generics, - &predicates, + def_id, tcx.region_maps.item_extent(id)) } _ => { @@ -1425,11 +1405,8 @@ impl<'a, 'tcx> ParameterEnvironment<'tcx> { } Some(ast_map::NodeForeignItem(item)) => { let def_id = tcx.map.local_def_id(id); - let scheme = tcx.lookup_item_type(def_id); - let predicates = tcx.lookup_predicates(def_id); tcx.construct_parameter_environment(item.span, - &scheme.generics, - &predicates, + def_id, ROOT_CODE_EXTENT) } _ => { @@ -1462,7 +1439,7 @@ impl<'a, 'tcx> ParameterEnvironment<'tcx> { /// `lookup_predicates`. #[derive(Clone, Debug)] pub struct TypeScheme<'tcx> { - pub generics: Generics<'tcx>, + pub generics: &'tcx Generics<'tcx>, pub ty: Ty<'tcx>, } @@ -1917,9 +1894,7 @@ impl<'a, 'tcx> AdtDefData<'tcx, 'tcx> { }; let sized_predicate = Binder(TraitRef { def_id: sized_trait, - substs: tcx.mk_substs(Substs::new_trait( - vec![], vec![], ty - )) + substs: Substs::new_trait(tcx, vec![], vec![], ty) }).to_predicate(); let predicates = tcx.lookup_predicates(self.did).predicates; if predicates.into_iter().any(|p| p == sized_predicate) { @@ -2170,7 +2145,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { pub fn node_id_item_substs(self, id: NodeId) -> ItemSubsts<'gcx> { match self.tables.borrow().item_substs.get(&id) { None => ItemSubsts { - substs: self.global_tcx().mk_substs(Substs::empty()) + substs: Substs::empty(self.global_tcx()) }, Some(ts) => ts.clone(), } @@ -2508,27 +2483,36 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { } // Register a given item type - pub fn register_item_type(self, did: DefId, ty: TypeScheme<'gcx>) { - self.tcache.borrow_mut().insert(did, ty); + pub fn register_item_type(self, did: DefId, scheme: TypeScheme<'gcx>) { + self.tcache.borrow_mut().insert(did, scheme.ty); + self.generics.borrow_mut().insert(did, scheme.generics); } // If the given item is in an external crate, looks up its type and adds it to // the type cache. Returns the type parameters and type. pub fn lookup_item_type(self, did: DefId) -> TypeScheme<'gcx> { - lookup_locally_or_in_crate_store( + let ty = lookup_locally_or_in_crate_store( "tcache", did, &self.tcache, - || self.sess.cstore.item_type(self.global_tcx(), did)) + || self.sess.cstore.item_type(self.global_tcx(), did)); + + TypeScheme { + ty: ty, + generics: self.lookup_generics(did) + } } pub fn opt_lookup_item_type(self, did: DefId) -> Option> { - if let Some(scheme) = self.tcache.borrow_mut().get(&did) { - return Some(scheme.clone()); + if did.krate != LOCAL_CRATE { + return Some(self.lookup_item_type(did)); } - if did.krate == LOCAL_CRATE { - None + if let Some(ty) = self.tcache.borrow().get(&did).cloned() { + Some(TypeScheme { + ty: ty, + generics: self.lookup_generics(did) + }) } else { - Some(self.sess.cstore.item_type(self.global_tcx(), did)) + None } } @@ -2557,6 +2541,13 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { self.lookup_adt_def_master(did) } + /// Given the did of an item, returns its generics. + pub fn lookup_generics(self, did: DefId) -> &'gcx Generics<'gcx> { + lookup_locally_or_in_crate_store( + "generics", did, &self.generics, + || self.sess.cstore.item_generics(self.global_tcx(), did)) + } + /// Given the did of an item, returns its full set of predicates. pub fn lookup_predicates(self, did: DefId) -> GenericPredicates<'gcx> { lookup_locally_or_in_crate_store( @@ -2812,18 +2803,18 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { } } - /// If the given def ID describes an item belonging to a trait (either a - /// default method or an implementation of a trait method), return the ID of - /// the trait that the method belongs to. Otherwise, return `None`. + /// If the given def ID describes an item belonging to a trait, + /// return the ID of the trait that the trait item belongs to. + /// Otherwise, return `None`. pub fn trait_of_item(self, def_id: DefId) -> Option { if def_id.krate != LOCAL_CRATE { - return self.sess.cstore.trait_of_item(self.global_tcx(), def_id); + return self.sess.cstore.trait_of_item(def_id); } - match self.impl_or_trait_items.borrow().get(&def_id).cloned() { + match self.impl_or_trait_items.borrow().get(&def_id) { Some(impl_or_trait_item) => { match impl_or_trait_item.container() { TraitContainer(def_id) => Some(def_id), - ImplContainer(def_id) => self.trait_id_of_impl(def_id), + ImplContainer(_) => None } } None => None @@ -2837,18 +2828,20 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { /// the same). /// Otherwise, return `None`. pub fn trait_item_of_item(self, def_id: DefId) -> Option { - let impl_item = match self.impl_or_trait_items.borrow().get(&def_id) { + let impl_or_trait_item = match self.impl_or_trait_items.borrow().get(&def_id) { Some(m) => m.clone(), None => return None, }; - let name = impl_item.name(); - match self.trait_of_item(def_id) { - Some(trait_did) => { - self.trait_items(trait_did).iter() - .find(|item| item.name() == name) - .map(|item| item.id()) + match impl_or_trait_item.container() { + TraitContainer(_) => Some(impl_or_trait_item.id()), + ImplContainer(def_id) => { + self.trait_id_of_impl(def_id).and_then(|trait_did| { + let name = impl_or_trait_item.name(); + self.trait_items(trait_did).iter() + .find(|item| item.name() == name) + .map(|item| item.id()) + }) } - None => None } } @@ -2860,7 +2853,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { // regions, so it shouldn't matter what we use for the free id let free_id_outlive = self.region_maps.node_extent(ast::DUMMY_NODE_ID); ty::ParameterEnvironment { - free_substs: self.mk_substs(Substs::empty()), + free_substs: Substs::empty(self), caller_bounds: Vec::new(), implicit_region_bound: ty::ReEmpty, free_id_outlive: free_id_outlive @@ -2872,28 +2865,21 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { /// In general, this means converting from bound parameters to /// free parameters. Since we currently represent bound/free type /// parameters in the same way, this only has an effect on regions. - pub fn construct_free_substs(self, generics: &Generics<'gcx>, - free_id_outlive: CodeExtent) -> Substs<'gcx> { - // map T => T - let types = generics.types.map(|def| { - debug!("construct_parameter_environment(): push_types_from_defs: def={:?}", - def); + pub fn construct_free_substs(self, def_id: DefId, + free_id_outlive: CodeExtent) + -> &'gcx Substs<'gcx> { + + let substs = Substs::for_item(self.global_tcx(), def_id, |def, _| { + // map bound 'a => free 'a + ReFree(FreeRegion { scope: free_id_outlive, + bound_region: def.to_bound_region() }) + }, |def, _| { + // map T => T self.global_tcx().mk_param_from_def(def) }); - // map bound 'a => free 'a - let regions = generics.regions.map(|def| { - let region = - ReFree(FreeRegion { scope: free_id_outlive, - bound_region: def.to_bound_region() }); - debug!("push_region_params {:?}", region); - region - }); - - Substs { - types: types, - regions: regions, - } + debug!("construct_parameter_environment: {:?}", substs); + substs } /// See `ParameterEnvironment` struct def'n for details. @@ -2901,8 +2887,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { /// for the `free_id_outlive` parameter. (But note that that is not always quite right.) pub fn construct_parameter_environment(self, span: Span, - generics: &ty::Generics<'gcx>, - generic_predicates: &ty::GenericPredicates<'gcx>, + def_id: DefId, free_id_outlive: CodeExtent) -> ParameterEnvironment<'gcx> { @@ -2910,14 +2895,15 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { // Construct the free substs. // - let free_substs = self.construct_free_substs(generics, free_id_outlive); + let free_substs = self.construct_free_substs(def_id, free_id_outlive); // // Compute the bounds on Self and the type parameters. // let tcx = self.global_tcx(); - let bounds = generic_predicates.instantiate(tcx, &free_substs); + let generic_predicates = tcx.lookup_predicates(def_id); + let bounds = generic_predicates.instantiate(tcx, free_substs); let bounds = tcx.liberate_late_bound_regions(free_id_outlive, &ty::Binder(bounds)); let predicates = bounds.predicates; @@ -2935,7 +2921,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { // let unnormalized_env = ty::ParameterEnvironment { - free_substs: tcx.mk_substs(free_substs), + free_substs: free_substs, implicit_region_bound: ty::ReScope(free_id_outlive), caller_bounds: predicates, free_id_outlive: free_id_outlive, diff --git a/src/librustc/ty/relate.rs b/src/librustc/ty/relate.rs index aa48474e50cf1..388e8926403fd 100644 --- a/src/librustc/ty/relate.rs +++ b/src/librustc/ty/relate.rs @@ -14,7 +14,7 @@ //! type equality, etc. use hir::def_id::DefId; -use ty::subst::{ParamSpace, Substs}; +use ty::subst::Substs; use ty::{self, Ty, TyCtxt, TypeFoldable}; use ty::error::{ExpectedFound, TypeError}; use std::rc::Rc; @@ -145,82 +145,44 @@ pub fn relate_substs<'a, 'gcx, 'tcx, R>(relation: &mut R, -> RelateResult<'tcx, &'tcx Substs<'tcx>> where R: TypeRelation<'a, 'gcx, 'tcx>, 'gcx: 'a+'tcx, 'tcx: 'a { - let mut substs = Substs::empty(); - - for &space in &ParamSpace::all() { - let a_tps = a_subst.types.get_slice(space); - let b_tps = b_subst.types.get_slice(space); - let t_variances = variances.map(|v| v.types.get_slice(space)); - let tps = relate_type_params(relation, t_variances, a_tps, b_tps)?; - substs.types.replace(space, tps); - } - - for &space in &ParamSpace::all() { - let a_regions = a_subst.regions.get_slice(space); - let b_regions = b_subst.regions.get_slice(space); - let r_variances = variances.map(|v| v.regions.get_slice(space)); - let regions = relate_region_params(relation, - r_variances, - a_regions, - b_regions)?; - substs.regions.replace(space, regions); - } - - Ok(relation.tcx().mk_substs(substs)) -} - -fn relate_type_params<'a, 'gcx, 'tcx, R>(relation: &mut R, - variances: Option<&[ty::Variance]>, - a_tys: &[Ty<'tcx>], - b_tys: &[Ty<'tcx>]) - -> RelateResult<'tcx, Vec>> - where R: TypeRelation<'a, 'gcx, 'tcx>, 'gcx: 'a+'tcx, 'tcx: 'a -{ - if a_tys.len() != b_tys.len() { - return Err(TypeError::TyParamSize(expected_found(relation, - &a_tys.len(), - &b_tys.len()))); - } - - (0 .. a_tys.len()) - .map(|i| { - let a_ty = a_tys[i]; - let b_ty = b_tys[i]; - let v = variances.map_or(ty::Invariant, |v| v[i]); - relation.relate_with_variance(v, &a_ty, &b_ty) - }) - .collect() -} + let tcx = relation.tcx(); + let mut result = Ok(()); + + let types = a_subst.types.map_enumerated(|(space, i, a_ty)| { + if result.is_err() { return tcx.types.err; } + + let b_ty = b_subst.types.get(space, i); + let variance = variances.map_or(ty::Invariant, |v| { + *v.types.get(space, i) + }); + match relation.relate_with_variance(variance, a_ty, b_ty) { + Ok(ty) => ty, + Err(e) => { + result = Err(e); + tcx.types.err + } + } + }); + result?; + + let regions = a_subst.regions.map_enumerated(|(space, i, a_r)| { + if result.is_err() { return ty::ReStatic; } + + let b_r = b_subst.regions.get(space, i); + let variance = variances.map_or(ty::Invariant, |v| { + *v.regions.get(space, i) + }); + match relation.relate_with_variance(variance, a_r, b_r) { + Ok(r) => r, + Err(e) => { + result = Err(e); + ty::ReStatic + } + } + }); + result?; -fn relate_region_params<'a, 'gcx, 'tcx, R>(relation: &mut R, - variances: Option<&[ty::Variance]>, - a_rs: &[ty::Region], - b_rs: &[ty::Region]) - -> RelateResult<'tcx, Vec> - where R: TypeRelation<'a, 'gcx, 'tcx>, 'gcx: 'a+'tcx, 'tcx: 'a -{ - let num_region_params = a_rs.len(); - - debug!("relate_region_params(a_rs={:?}, \ - b_rs={:?}, variances={:?})", - a_rs, - b_rs, - variances); - - assert_eq!(num_region_params, - variances.map_or(num_region_params, - |v| v.len())); - - assert_eq!(num_region_params, b_rs.len()); - - (0..a_rs.len()) - .map(|i| { - let a_r = a_rs[i]; - let b_r = b_rs[i]; - let variance = variances.map_or(ty::Invariant, |v| v[i]); - relation.relate_with_variance(variance, &a_r, &b_r) - }) - .collect() + Ok(Substs::new(tcx, types, regions)) } impl<'tcx> Relate<'tcx> for &'tcx ty::BareFnTy<'tcx> { diff --git a/src/librustc/ty/structural_impls.rs b/src/librustc/ty/structural_impls.rs index 14005c1bd8b76..9021b0587a013 100644 --- a/src/librustc/ty/structural_impls.rs +++ b/src/librustc/ty/structural_impls.rs @@ -9,7 +9,7 @@ // except according to those terms. use infer::type_variable; -use ty::subst::{self, VecPerParamSpace}; +use ty::subst::{Substs, VecPerParamSpace}; use ty::{self, Lift, Ty, TyCtxt}; use ty::fold::{TypeFoldable, TypeFolder, TypeVisitor}; @@ -702,13 +702,11 @@ impl<'tcx> TypeFoldable<'tcx> for &'tcx ty::Region { } } -impl<'tcx> TypeFoldable<'tcx> for &'tcx subst::Substs<'tcx> { +impl<'tcx> TypeFoldable<'tcx> for &'tcx Substs<'tcx> { fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) -> Self { - let substs = subst::Substs { - regions: self.regions.fold_with(folder), - types: self.types.fold_with(folder) - }; - folder.tcx().mk_substs(substs) + let types = self.types.fold_with(folder); + let regions = self.regions.fold_with(folder); + Substs::new(folder.tcx(), types, regions) } fn fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) -> Self { @@ -839,6 +837,7 @@ impl<'tcx> TypeFoldable<'tcx> for ty::Generics<'tcx> { ty::Generics { types: self.types.fold_with(folder), regions: self.regions.fold_with(folder), + has_self: self.has_self } } @@ -1018,19 +1017,6 @@ impl<'tcx> TypeFoldable<'tcx> for ty::ParameterEnvironment<'tcx> { } } -impl<'tcx> TypeFoldable<'tcx> for ty::TypeScheme<'tcx> { - fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) -> Self { - ty::TypeScheme { - generics: self.generics.fold_with(folder), - ty: self.ty.fold_with(folder), - } - } - - fn super_visit_with>(&self, visitor: &mut V) -> bool { - self.generics.visit_with(visitor) || self.ty.visit_with(visitor) - } -} - impl<'tcx, T: TypeFoldable<'tcx>> TypeFoldable<'tcx> for ty::error::ExpectedFound { fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) -> Self { ty::error::ExpectedFound { diff --git a/src/librustc/ty/sty.rs b/src/librustc/ty/sty.rs index 91214873f193d..f31b844f04fe6 100644 --- a/src/librustc/ty/sty.rs +++ b/src/librustc/ty/sty.rs @@ -359,18 +359,7 @@ pub struct ExistentialTraitRef<'tcx> { pub substs: &'tcx Substs<'tcx>, } -impl<'a, 'gcx, 'tcx> ExistentialTraitRef<'tcx> { - pub fn erase_self_ty(tcx: TyCtxt<'a, 'gcx, 'tcx>, - trait_ref: ty::TraitRef<'tcx>) - -> ty::ExistentialTraitRef<'tcx> { - let mut substs = trait_ref.substs.clone(); - substs.types.pop(subst::SelfSpace); - ty::ExistentialTraitRef { - def_id: trait_ref.def_id, - substs: tcx.mk_substs(substs) - } - } - +impl<'tcx> ExistentialTraitRef<'tcx> { pub fn input_types(&self) -> &[Ty<'tcx>] { // Select only the "input types" from a trait-reference. For // now this is all the types that appear in the @@ -382,7 +371,7 @@ impl<'a, 'gcx, 'tcx> ExistentialTraitRef<'tcx> { pub type PolyExistentialTraitRef<'tcx> = Binder>; -impl<'a, 'gcx, 'tcx> PolyExistentialTraitRef<'tcx> { +impl<'tcx> PolyExistentialTraitRef<'tcx> { pub fn def_id(&self) -> DefId { self.0.def_id } @@ -391,23 +380,6 @@ impl<'a, 'gcx, 'tcx> PolyExistentialTraitRef<'tcx> { // FIXME(#20664) every use of this fn is probably a bug, it should yield Binder<> self.0.input_types() } - - /// Object types don't have a self-type specified. Therefore, when - /// we convert the principal trait-ref into a normal trait-ref, - /// you must give *some* self-type. A common choice is `mk_err()` - /// or some skolemized type. - pub fn with_self_ty(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>, - self_ty: Ty<'tcx>) - -> ty::PolyTraitRef<'tcx> - { - // otherwise the escaping regions would be captured by the binder - assert!(!self_ty.has_escaping_regions()); - - self.map_bound(|trait_ref| TraitRef { - def_id: trait_ref.def_id, - substs: tcx.mk_substs(trait_ref.substs.with_self_ty(self_ty)), - }) - } } /// Binder is a binder for higher-ranked lifetimes. It is part of the diff --git a/src/librustc/ty/subst.rs b/src/librustc/ty/subst.rs index 34e7899e2fddb..00537f9d6c5dc 100644 --- a/src/librustc/ty/subst.rs +++ b/src/librustc/ty/subst.rs @@ -34,43 +34,45 @@ pub struct Substs<'tcx> { } impl<'a, 'gcx, 'tcx> Substs<'tcx> { - pub fn new(t: VecPerParamSpace>, + pub fn new(tcx: TyCtxt<'a, 'gcx, 'tcx>, + t: VecPerParamSpace>, r: VecPerParamSpace) - -> Substs<'tcx> + -> &'tcx Substs<'tcx> { - Substs { types: t, regions: r } + tcx.mk_substs(Substs { types: t, regions: r }) } - pub fn new_fn(t: Vec>, + pub fn new_fn(tcx: TyCtxt<'a, 'gcx, 'tcx>, + t: Vec>, r: Vec) - -> Substs<'tcx> + -> &'tcx Substs<'tcx> { - Substs::new(VecPerParamSpace::new(vec![], vec![], t), + Substs::new(tcx, VecPerParamSpace::new(vec![], vec![], t), VecPerParamSpace::new(vec![], vec![], r)) } - pub fn new_type(t: Vec>, + pub fn new_type(tcx: TyCtxt<'a, 'gcx, 'tcx>, + t: Vec>, r: Vec) - -> Substs<'tcx> + -> &'tcx Substs<'tcx> { - Substs::new(VecPerParamSpace::new(vec![], t, vec![]), + Substs::new(tcx, VecPerParamSpace::new(vec![], t, vec![]), VecPerParamSpace::new(vec![], r, vec![])) } - pub fn new_trait(t: Vec>, + pub fn new_trait(tcx: TyCtxt<'a, 'gcx, 'tcx>, + t: Vec>, r: Vec, s: Ty<'tcx>) - -> Substs<'tcx> + -> &'tcx Substs<'tcx> { - Substs::new(VecPerParamSpace::new(vec![s], t, vec![]), + Substs::new(tcx, VecPerParamSpace::new(vec![s], t, vec![]), VecPerParamSpace::new(vec![], r, vec![])) } - pub fn empty() -> Substs<'tcx> { - Substs { - types: VecPerParamSpace::empty(), - regions: VecPerParamSpace::empty(), - } + pub fn empty(tcx: TyCtxt<'a, 'gcx, 'tcx>) -> &'tcx Substs<'tcx> { + Substs::new(tcx, VecPerParamSpace::empty(), + VecPerParamSpace::empty()) } /// Creates a Substs for generic parameter definitions, @@ -78,26 +80,57 @@ impl<'a, 'gcx, 'tcx> Substs<'tcx> { /// The closures get to observe the Substs as they're /// being built, which can be used to correctly /// substitute defaults of type parameters. - pub fn from_generics(generics: &ty::Generics<'tcx>, - mut mk_region: FR, - mut mk_type: FT) - -> Substs<'tcx> + pub fn for_item(tcx: TyCtxt<'a, 'gcx, 'tcx>, + def_id: DefId, + mut mk_region: FR, + mut mk_type: FT) + -> &'tcx Substs<'tcx> where FR: FnMut(&ty::RegionParameterDef, &Substs<'tcx>) -> ty::Region, FT: FnMut(&ty::TypeParameterDef<'tcx>, &Substs<'tcx>) -> Ty<'tcx> { - let mut substs = Substs::empty(); + let defs = tcx.lookup_generics(def_id); + let mut substs = Substs { + types: VecPerParamSpace { + self_limit: 0, + type_limit: 0, + content: Vec::with_capacity(defs.types.content.len()) + }, + regions: VecPerParamSpace { + self_limit: 0, + type_limit: 0, + content: Vec::with_capacity(defs.regions.content.len()) + } + }; + for &space in &ParamSpace::all() { - for def in generics.regions.get_slice(space) { + for def in defs.regions.get_slice(space) { + assert_eq!(def.space, space); + assert!(space != SelfSpace); + let region = mk_region(def, &substs); - assert_eq!(substs.regions.len(def.space), def.index as usize); - substs.regions.push(def.space, region); + substs.regions.content.push(region); + + if space == TypeSpace { + substs.regions.type_limit += 1; + } } - for def in generics.types.get_slice(space) { + + for def in defs.types.get_slice(space) { + assert_eq!(def.space, space); + let ty = mk_type(def, &substs); - assert_eq!(substs.types.len(def.space), def.index as usize); - substs.types.push(def.space, ty); + substs.types.content.push(ty); + + if space == SelfSpace { + substs.types.self_limit += 1; + } + + if space <= TypeSpace { + substs.types.type_limit += 1; + } } } - substs + + Substs::new(tcx, substs.types, substs.regions) } pub fn is_noop(&self) -> bool { @@ -112,66 +145,32 @@ impl<'a, 'gcx, 'tcx> Substs<'tcx> { *self.regions.get(def.space, def.index as usize) } - pub fn self_ty(&self) -> Option> { - self.types.get_self().cloned() - } - - pub fn with_self_ty(&self, self_ty: Ty<'tcx>) -> Substs<'tcx> { - assert!(self.self_ty().is_none()); - let mut s = (*self).clone(); - s.types.push(SelfSpace, self_ty); - s - } - - pub fn erase_regions(self) -> Substs<'tcx> { - let Substs { types, regions } = self; - let regions = regions.map(|_| ty::ReErased); - Substs { types: types, regions: regions } - } - - pub fn with_method(self, - m_types: Vec>, - m_regions: Vec) - -> Substs<'tcx> - { - let Substs { types, regions } = self; - let types = types.with_slice(FnSpace, &m_types); - let regions = regions.with_slice(FnSpace, &m_regions); - Substs { types: types, regions: regions } - } - - pub fn with_method_from(&self, - meth_substs: &Substs<'tcx>) - -> Substs<'tcx> - { - let Substs { types, regions } = self.clone(); - let types = types.with_slice(FnSpace, meth_substs.types.get_slice(FnSpace)); - let regions = regions.with_slice(FnSpace, meth_substs.regions.get_slice(FnSpace)); - Substs { types: types, regions: regions } - } - - pub fn with_method_from_subst(&self, other: &Substs<'tcx>) -> Substs<'tcx> { - let Substs { types, regions } = self.clone(); - let types = types.with_slice(FnSpace, other.types.get_slice(FnSpace)); - let regions = regions.with_slice(FnSpace, other.regions.get_slice(FnSpace)); - Substs { types: types, regions: regions } - } - - /// Creates a trait-ref out of this substs, ignoring the FnSpace substs - pub fn to_trait_ref(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>, trait_id: DefId) - -> ty::TraitRef<'tcx> { - let Substs { mut types, mut regions } = self.clone(); - types.truncate(FnSpace, 0); - regions.truncate(FnSpace, 0); - - ty::TraitRef { - def_id: trait_id, - substs: tcx.mk_substs(Substs { types: types, regions: regions }) - } + /// Transform from substitutions for a child of `source_ancestor` + /// (e.g. a trait or impl) to substitutions for the same child + /// in a different item, with `target_substs` as the base for + /// the target impl/trait, with the source child-specific + /// parameters (e.g. method parameters) on top of that base. + pub fn rebase_onto(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>, + source_ancestor: DefId, + target_substs: &Substs<'tcx>) + -> &'tcx Substs<'tcx> { + let defs = tcx.lookup_generics(source_ancestor); + assert_eq!(self.types.len(SelfSpace), defs.types.len(SelfSpace)); + assert_eq!(self.types.len(TypeSpace), defs.types.len(TypeSpace)); + assert_eq!(target_substs.types.len(FnSpace), 0); + assert_eq!(defs.types.len(FnSpace), 0); + assert_eq!(self.regions.len(TypeSpace), defs.regions.len(TypeSpace)); + assert_eq!(target_substs.regions.len(FnSpace), 0); + assert_eq!(defs.regions.len(FnSpace), 0); + + let Substs { mut types, mut regions } = target_substs.clone(); + types.content.extend(&self.types.as_full_slice()[defs.types.content.len()..]); + regions.content.extend(&self.regions.as_full_slice()[defs.regions.content.len()..]); + Substs::new(tcx, types, regions) } } -impl<'tcx> Encodable for Substs<'tcx> { +impl<'tcx> Encodable for &'tcx Substs<'tcx> { fn encode(&self, s: &mut S) -> Result<(), S::Error> { cstore::tls::with_encoding_context(s, |ecx, rbml_w| { ecx.encode_substs(rbml_w, self); @@ -180,19 +179,10 @@ impl<'tcx> Encodable for Substs<'tcx> { } } -impl<'tcx> Decodable for Substs<'tcx> { - fn decode(d: &mut D) -> Result, D::Error> { - cstore::tls::with_decoding_context(d, |dcx, rbml_r| { - Ok(dcx.decode_substs(rbml_r)) - }) - } -} - impl<'tcx> Decodable for &'tcx Substs<'tcx> { fn decode(d: &mut D) -> Result<&'tcx Substs<'tcx>, D::Error> { let substs = cstore::tls::with_decoding_context(d, |dcx, rbml_r| { - let substs = dcx.decode_substs(rbml_r); - dcx.tcx().mk_substs(substs) + dcx.decode_substs(rbml_r) }); Ok(substs) @@ -307,70 +297,6 @@ impl VecPerParamSpace { } } - /// Appends `value` to the vector associated with `space`. - /// - /// Unlike the `push` method in `Vec`, this should not be assumed - /// to be a cheap operation (even when amortized over many calls). - pub fn push(&mut self, space: ParamSpace, value: T) { - let (_, limit) = self.limits(space); - match space { - SelfSpace => { self.type_limit += 1; self.self_limit += 1; } - TypeSpace => { self.type_limit += 1; } - FnSpace => { } - } - self.content.insert(limit, value); - } - - /// Appends `values` to the vector associated with `space`. - /// - /// Unlike the `extend` method in `Vec`, this should not be assumed - /// to be a cheap operation (even when amortized over many calls). - pub fn extend>(&mut self, space: ParamSpace, values: I) { - // This could be made more efficient, obviously. - for item in values { - self.push(space, item); - } - } - - pub fn pop(&mut self, space: ParamSpace) -> Option { - let (start, limit) = self.limits(space); - if start == limit { - None - } else { - match space { - SelfSpace => { self.type_limit -= 1; self.self_limit -= 1; } - TypeSpace => { self.type_limit -= 1; } - FnSpace => {} - } - if self.content.is_empty() { - None - } else { - Some(self.content.remove(limit - 1)) - } - } - } - - pub fn truncate(&mut self, space: ParamSpace, len: usize) { - // FIXME (#15435): slow; O(n^2); could enhance vec to make it O(n). - while self.len(space) > len { - self.pop(space); - } - } - - pub fn replace(&mut self, space: ParamSpace, elems: Vec) { - // FIXME (#15435): slow; O(n^2); could enhance vec to make it O(n). - self.truncate(space, 0); - for t in elems { - self.push(space, t); - } - } - - pub fn get_self<'a>(&'a self) -> Option<&'a T> { - let v = self.get_slice(SelfSpace); - assert!(v.len() <= 1); - if v.is_empty() { None } else { Some(&v[0]) } - } - pub fn len(&self, space: ParamSpace) -> usize { self.get_slice(space).len() } @@ -384,19 +310,6 @@ impl VecPerParamSpace { &self.content[start.. limit] } - pub fn get_mut_slice<'a>(&'a mut self, space: ParamSpace) -> &'a mut [T] { - let (start, limit) = self.limits(space); - &mut self.content[start.. limit] - } - - pub fn opt_get<'a>(&'a self, - space: ParamSpace, - index: usize) - -> Option<&'a T> { - let v = self.get_slice(space); - if index < v.len() { Some(&v[index]) } else { None } - } - pub fn get<'a>(&'a self, space: ParamSpace, index: usize) -> &'a T { &self.get_slice(space)[index] } @@ -409,12 +322,6 @@ impl VecPerParamSpace { &self.content } - pub fn all_vecs

(&self, mut pred: P) -> bool where - P: FnMut(&[T]) -> bool, - { - ParamSpace::all().iter().all(|&space| { pred(self.get_slice(space)) }) - } - pub fn all

(&self, pred: P) -> bool where P: FnMut(&T) -> bool { self.as_full_slice().iter().all(pred) } @@ -424,7 +331,7 @@ impl VecPerParamSpace { } pub fn is_empty(&self) -> bool { - self.all_vecs(|v| v.is_empty()) + self.content.is_empty() } pub fn map(&self, pred: P) -> VecPerParamSpace where P: FnMut(&T) -> U { @@ -442,18 +349,6 @@ impl VecPerParamSpace { self.self_limit, self.type_limit) } - - pub fn with_slice(mut self, space: ParamSpace, slice: &[T]) - -> VecPerParamSpace - where T: Clone - { - assert!(self.is_empty_in(space)); - for t in slice { - self.push(space, t.clone()); - } - - self - } } #[derive(Clone)] @@ -581,7 +476,7 @@ impl<'a, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for SubstFolder<'a, 'gcx, 'tcx> { // the specialized routine `ty::replace_late_regions()`. match r { ty::ReEarlyBound(data) => { - match self.substs.regions.opt_get(data.space, data.index as usize) { + match self.substs.regions.get_slice(data.space).get(data.index as usize) { Some(&r) => { self.shift_region_through_binders(r) } @@ -637,7 +532,7 @@ impl<'a, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for SubstFolder<'a, 'gcx, 'tcx> { impl<'a, 'gcx, 'tcx> SubstFolder<'a, 'gcx, 'tcx> { fn ty_for_param(&self, p: ty::ParamTy, source_ty: Ty<'tcx>) -> Ty<'tcx> { // Look up the type in the substitutions. It really should be in there. - let opt_ty = self.substs.types.opt_get(p.space, p.idx as usize); + let opt_ty = self.substs.types.get_slice(p.space).get(p.idx as usize); let ty = match opt_ty { Some(t) => *t, None => { @@ -718,3 +613,67 @@ impl<'a, 'gcx, 'tcx> SubstFolder<'a, 'gcx, 'tcx> { ty::fold::shift_region(region, self.region_binders_passed) } } + +// Helper methods that modify substitutions. + +impl<'a, 'gcx, 'tcx> ty::TraitRef<'tcx> { + pub fn from_method(tcx: TyCtxt<'a, 'gcx, 'tcx>, + trait_id: DefId, + substs: &Substs<'tcx>) + -> ty::TraitRef<'tcx> { + let Substs { mut types, mut regions } = substs.clone(); + let defs = tcx.lookup_generics(trait_id); + types.content.truncate(defs.types.type_limit); + regions.content.truncate(defs.regions.type_limit); + + ty::TraitRef { + def_id: trait_id, + substs: Substs::new(tcx, types, regions) + } + } +} + +impl<'a, 'gcx, 'tcx> ty::ExistentialTraitRef<'tcx> { + pub fn erase_self_ty(tcx: TyCtxt<'a, 'gcx, 'tcx>, + trait_ref: ty::TraitRef<'tcx>) + -> ty::ExistentialTraitRef<'tcx> { + let Substs { mut types, regions } = trait_ref.substs.clone(); + + assert_eq!(types.self_limit, 1); + types.self_limit = 0; + types.type_limit -= 1; + types.content.remove(0); + + ty::ExistentialTraitRef { + def_id: trait_ref.def_id, + substs: Substs::new(tcx, types, regions) + } + } +} + +impl<'a, 'gcx, 'tcx> ty::PolyExistentialTraitRef<'tcx> { + /// Object types don't have a self-type specified. Therefore, when + /// we convert the principal trait-ref into a normal trait-ref, + /// you must give *some* self-type. A common choice is `mk_err()` + /// or some skolemized type. + pub fn with_self_ty(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>, + self_ty: Ty<'tcx>) + -> ty::PolyTraitRef<'tcx> { + // otherwise the escaping regions would be captured by the binder + assert!(!self_ty.has_escaping_regions()); + + self.map_bound(|trait_ref| { + let Substs { mut types, regions } = trait_ref.substs.clone(); + + assert_eq!(types.self_limit, 0); + types.self_limit = 1; + types.type_limit += 1; + types.content.insert(0, self_ty); + + ty::TraitRef { + def_id: trait_ref.def_id, + substs: Substs::new(tcx, types, regions) + } + }) + } +} diff --git a/src/librustc/ty/trait_def.rs b/src/librustc/ty/trait_def.rs index a76dfc35dc1d3..61285e8f8b0a5 100644 --- a/src/librustc/ty/trait_def.rs +++ b/src/librustc/ty/trait_def.rs @@ -34,7 +34,7 @@ pub struct TraitDef<'tcx> { /// `Eq`, there is a single bound `Self : Eq`). This is so that /// default methods get to assume that the `Self` parameters /// implements the trait. - pub generics: ty::Generics<'tcx>, + pub generics: &'tcx ty::Generics<'tcx>, pub trait_ref: ty::TraitRef<'tcx>, @@ -76,7 +76,7 @@ pub struct TraitDef<'tcx> { impl<'a, 'gcx, 'tcx> TraitDef<'tcx> { pub fn new(unsafety: hir::Unsafety, paren_sugar: bool, - generics: ty::Generics<'tcx>, + generics: &'tcx ty::Generics<'tcx>, trait_ref: ty::TraitRef<'tcx>, associated_type_names: Vec) -> TraitDef<'tcx> { diff --git a/src/librustc/ty/util.rs b/src/librustc/ty/util.rs index 3c1f6e9199220..5a73439beac6e 100644 --- a/src/librustc/ty/util.rs +++ b/src/librustc/ty/util.rs @@ -11,7 +11,6 @@ //! misc. type-system utilities too small to deserve their own file use hir::def_id::DefId; -use ty::subst; use infer::InferCtxt; use hir::pat_util; use traits::{self, Reveal}; @@ -695,12 +694,10 @@ impl<'a, 'tcx> ty::TyS<'tcx> { return false; } - let types_a = substs_a.types.get_slice(subst::TypeSpace); - let types_b = substs_b.types.get_slice(subst::TypeSpace); + let types_a = substs_a.types.as_full_slice(); + let types_b = substs_b.types.as_full_slice(); - let mut pairs = types_a.iter().zip(types_b); - - pairs.all(|(&a, &b)| same_type(a, b)) + types_a.iter().zip(types_b).all(|(&a, &b)| same_type(a, b)) } _ => { a == b diff --git a/src/librustc/util/ppaux.rs b/src/librustc/util/ppaux.rs index fb0b6413fab40..cdbd307052364 100644 --- a/src/librustc/util/ppaux.rs +++ b/src/librustc/util/ppaux.rs @@ -10,7 +10,7 @@ use hir::def_id::DefId; -use ty::subst::{self, Subst}; +use ty::subst::{self, Subst, Substs}; use ty::{BrAnon, BrEnv, BrFresh, BrNamed}; use ty::{TyBool, TyChar, TyStruct, TyEnum}; use ty::{TyError, TyStr, TyArray, TySlice, TyFloat, TyFnDef, TyFnPtr}; @@ -65,69 +65,57 @@ pub enum Ns { fn number_of_supplied_defaults<'a, 'gcx, 'tcx>(tcx: TyCtxt<'a, 'gcx, 'tcx>, substs: &subst::Substs, space: subst::ParamSpace, - generics: ty::Generics<'tcx>) + generics: &ty::Generics<'tcx>) -> usize { - let has_self = substs.self_ty().is_some(); let ty_params = generics.types.get_slice(space); let tps = substs.types.get_slice(space); if ty_params.last().map_or(false, |def| def.default.is_some()) { let substs = tcx.lift(&substs); ty_params.iter().zip(tps).rev().take_while(|&(def, &actual)| { - match def.default { - Some(default) => { - if !has_self && default.has_self_ty() { - // In an object type, there is no `Self`, and - // thus if the default value references Self, - // the user will be required to give an - // explicit value. We can't even do the - // substitution below to check without causing - // an ICE. (#18956). - false - } else { - let default = tcx.lift(&default); - substs.and_then(|substs| default.subst(tcx, substs)) - == Some(actual) - } - } - None => false - } + substs.and_then(|substs| def.default.subst(tcx, substs)) + == Some(actual) }).count() } else { 0 } } -pub fn parameterized(f: &mut fmt::Formatter, - substs: &subst::Substs, - did: DefId, - ns: Ns, - projections: &[ty::ProjectionPredicate], - get_generics: GG) - -> fmt::Result - where GG: for<'a, 'gcx, 'tcx> FnOnce(TyCtxt<'a, 'gcx, 'tcx>) - -> Option> -{ - if let (Ns::Value, Some(self_ty)) = (ns, substs.self_ty()) { - write!(f, "<{} as ", self_ty)?; - } +pub fn parameterized(f: &mut fmt::Formatter, + substs: &subst::Substs, + did: DefId, + ns: Ns, + projections: &[ty::ProjectionPredicate]) + -> fmt::Result { + let (fn_trait_kind, verbose, item_name, is_in_trait) = ty::tls::with(|tcx| { + let is_in_trait = ns == Ns::Value && tcx.trait_of_item(did).is_some(); + if is_in_trait { + write!(f, "<{} as ", substs.types.get(subst::SelfSpace, 0))?; + } - let (fn_trait_kind, verbose, item_name) = ty::tls::with(|tcx| { let (did, item_name) = if ns == Ns::Value { // Try to get the impl/trait parent, if this is an // associated value item (method or constant). - tcx.trait_of_item(did).or_else(|| tcx.impl_of_method(did)) - .map_or((did, None), |parent| (parent, Some(tcx.item_name(did)))) + tcx.trait_of_item(did).or_else(|| { + // An impl could be a trait impl or an inherent one. + tcx.impl_of_method(did).map(|impl_def_id| { + tcx.trait_id_of_impl(impl_def_id) + .unwrap_or(impl_def_id) + }) + }).map_or((did, None), |parent| (parent, Some(tcx.item_name(did)))) } else { (did, None) }; write!(f, "{}", tcx.item_path_str(did))?; - Ok((tcx.lang_items.fn_trait_kind(did), tcx.sess.verbose(), item_name)) + Ok((tcx.lang_items.fn_trait_kind(did), + tcx.sess.verbose(), + item_name, + is_in_trait)) })?; if !verbose && fn_trait_kind.is_some() && projections.len() == 1 { let projection_ty = projections[0].ty; - if let TyTuple(ref args) = substs.types.get_slice(subst::TypeSpace)[0].sty { + if let TyTuple(ref args) = substs.types.get(subst::TypeSpace, 0).sty { return fn_sig(f, args, false, projection_ty); } } @@ -176,11 +164,8 @@ pub fn parameterized(f: &mut fmt::Formatter, 0 } else { ty::tls::with(|tcx| { - if let Some(generics) = get_generics(tcx) { - number_of_supplied_defaults(tcx, substs, subst::TypeSpace, generics) - } else { - 0 - } + let generics = tcx.lookup_generics(did); + number_of_supplied_defaults(tcx, substs, subst::TypeSpace, generics) }) }; @@ -204,7 +189,7 @@ pub fn parameterized(f: &mut fmt::Formatter, if ns == Ns::Value { empty.set(true); - if substs.self_ty().is_some() { + if is_in_trait { write!(f, ">")?; } @@ -288,7 +273,7 @@ fn in_binder<'a, 'gcx, 'tcx, T, U>(f: &mut fmt::Formatter, /// projection bounds, so we just stuff them altogether. But in /// reality we should eventually sort things out better. #[derive(Clone, Debug)] -struct TraitAndProjections<'tcx>(ty::ExistentialTraitRef<'tcx>, +struct TraitAndProjections<'tcx>(ty::TraitRef<'tcx>, Vec>); impl<'tcx> TypeFoldable<'tcx> for TraitAndProjections<'tcx> { @@ -307,8 +292,7 @@ impl<'tcx> fmt::Display for TraitAndProjections<'tcx> { parameterized(f, trait_ref.substs, trait_ref.def_id, Ns::Type, - projection_bounds, - |tcx| Some(tcx.lookup_trait_def(trait_ref.def_id).generics.clone())) + projection_bounds) } } @@ -316,12 +300,16 @@ impl<'tcx> fmt::Display for ty::TraitObject<'tcx> { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { // Generate the main trait ref, including associated types. ty::tls::with(|tcx| { - let principal = tcx.lift(&self.principal.0) - .expect("could not lift TraitRef for printing"); + // Use a type that can't appear in defaults of type parameters. + let dummy_self = tcx.mk_infer(ty::FreshTy(0)); + + let principal = tcx.lift(&self.principal) + .expect("could not lift TraitRef for printing") + .with_self_ty(tcx, dummy_self).0; let projections = self.projection_bounds.iter().map(|p| { - let projection = tcx.lift(p) - .expect("could not lift projection for printing"); - projection.with_self_ty(tcx, tcx.types.err).0 + tcx.lift(p) + .expect("could not lift projection for printing") + .with_self_ty(tcx, dummy_self).0 }).collect(); let tap = ty::Binder(TraitAndProjections(principal, projections)); @@ -380,7 +368,7 @@ impl<'tcx> fmt::Display for ty::TypeAndMut<'tcx> { } } -impl<'tcx> fmt::Debug for subst::Substs<'tcx> { +impl<'tcx> fmt::Debug for Substs<'tcx> { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "Substs[types={:?}, regions={:?}]", self.types, self.regions) @@ -404,7 +392,14 @@ impl<'tcx> fmt::Debug for ty::TraitRef<'tcx> { impl<'tcx> fmt::Debug for ty::ExistentialTraitRef<'tcx> { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!(f, "{}", *self) + ty::tls::with(|tcx| { + let dummy_self = tcx.mk_infer(ty::FreshTy(0)); + + let trait_ref = tcx.lift(&ty::Binder(*self)) + .expect("could not lift TraitRef for printing") + .with_self_ty(tcx, dummy_self).0; + parameterized(f, trait_ref.substs, trait_ref.def_id, Ns::Type, &[]) + }) } } @@ -813,15 +808,7 @@ impl fmt::Display for ty::Binder> impl<'tcx> fmt::Display for ty::TraitRef<'tcx> { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - parameterized(f, self.substs, self.def_id, Ns::Type, &[], - |tcx| Some(tcx.lookup_trait_def(self.def_id).generics.clone())) - } -} - -impl<'tcx> fmt::Display for ty::ExistentialTraitRef<'tcx> { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - parameterized(f, self.substs, self.def_id, Ns::Type, &[], - |tcx| Some(tcx.lookup_trait_def(self.def_id).generics.clone())) + parameterized(f, self.substs, self.def_id, Ns::Type, &[]) } } @@ -874,9 +861,7 @@ impl<'tcx> fmt::Display for ty::TypeVariants<'tcx> { } write!(f, "{} {{", bare_fn.sig.0)?; - parameterized( - f, substs, def_id, Ns::Value, &[], - |tcx| tcx.opt_lookup_item_type(def_id).map(|t| t.generics))?; + parameterized(f, substs, def_id, Ns::Value, &[])?; write!(f, "}}") } TyFnPtr(ref bare_fn) => { @@ -899,12 +884,7 @@ impl<'tcx> fmt::Display for ty::TypeVariants<'tcx> { !tcx.tcache.borrow().contains_key(&def.did) { write!(f, "{}<..>", tcx.item_path_str(def.did)) } else { - parameterized( - f, substs, def.did, Ns::Type, &[], - |tcx| { - tcx.opt_lookup_item_type(def.did). - map(|t| t.generics) - }) + parameterized(f, substs, def.did, Ns::Type, &[]) } }) } @@ -916,7 +896,7 @@ impl<'tcx> fmt::Display for ty::TypeVariants<'tcx> { // by looking up the projections associated with the def_id. let item_predicates = tcx.lookup_predicates(def_id); let substs = tcx.lift(&substs).unwrap_or_else(|| { - tcx.mk_substs(subst::Substs::empty()) + Substs::empty(tcx) }); let bounds = item_predicates.instantiate(tcx, substs); diff --git a/src/librustc_borrowck/borrowck/mir/elaborate_drops.rs b/src/librustc_borrowck/borrowck/mir/elaborate_drops.rs index f6e9484eda1a4..df91ec2b98d5d 100644 --- a/src/librustc_borrowck/borrowck/mir/elaborate_drops.rs +++ b/src/librustc_borrowck/borrowck/mir/elaborate_drops.rs @@ -859,10 +859,9 @@ impl<'b, 'tcx> ElaborateDropsCtxt<'b, 'tcx> { let unit_temp = Lvalue::Temp(self.patch.new_temp(tcx.mk_nil())); let free_func = tcx.lang_items.require(lang_items::BoxFreeFnLangItem) .unwrap_or_else(|e| tcx.sess.fatal(&e)); - let substs = tcx.mk_substs(Substs::new( + let substs = Substs::new(tcx, VecPerParamSpace::new(vec![], vec![], vec![ty]), - VecPerParamSpace::new(vec![], vec![], vec![]) - )); + VecPerParamSpace::new(vec![], vec![], vec![])); let fty = tcx.lookup_item_type(free_func).ty.subst(tcx, substs); self.patch.new_block(BasicBlockData { diff --git a/src/librustc_const_eval/eval.rs b/src/librustc_const_eval/eval.rs index 73b54c4374ffb..d71add3258fbd 100644 --- a/src/librustc_const_eval/eval.rs +++ b/src/librustc_const_eval/eval.rs @@ -22,8 +22,9 @@ use rustc::traits; use rustc::hir::def::{Def, PathResolution}; use rustc::hir::def_id::DefId; use rustc::hir::pat_util::def_to_path; -use rustc::ty::{self, Ty, TyCtxt, subst}; +use rustc::ty::{self, Ty, TyCtxt}; use rustc::ty::util::IntTypeExt; +use rustc::ty::subst::Substs; use rustc::traits::Reveal; use rustc::util::common::ErrorReported; use rustc::util::nodemap::NodeMap; @@ -93,7 +94,7 @@ fn lookup_variant_by_id<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, /// This generally happens in late/trans const evaluation. pub fn lookup_const_by_id<'a, 'tcx: 'a>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId, - substs: Option<&'tcx subst::Substs<'tcx>>) + substs: Option<&'tcx Substs<'tcx>>) -> Option<(&'tcx Expr, Option>)> { if let Some(node_id) = tcx.map.as_local_node_id(def_id) { match tcx.map.find(node_id) { @@ -110,7 +111,8 @@ pub fn lookup_const_by_id<'a, 'tcx: 'a>(tcx: TyCtxt<'a, 'tcx, 'tcx>, // If we have a trait item and the substitutions for it, // `resolve_trait_associated_const` will select an impl // or the default. - let trait_id = tcx.trait_of_item(def_id).unwrap(); + let trait_id = tcx.map.get_parent(node_id); + let trait_id = tcx.map.local_def_id(trait_id); resolve_trait_associated_const(tcx, ti, trait_id, substs) } else { // Technically, without knowing anything about the @@ -1045,16 +1047,14 @@ fn infer<'a, 'tcx>(i: ConstInt, fn resolve_trait_associated_const<'a, 'tcx: 'a>(tcx: TyCtxt<'a, 'tcx, 'tcx>, ti: &'tcx hir::TraitItem, trait_id: DefId, - rcvr_substs: &'tcx subst::Substs<'tcx>) + rcvr_substs: &'tcx Substs<'tcx>) -> Option<(&'tcx Expr, Option>)> { - let trait_ref = ty::Binder( - rcvr_substs.clone().erase_regions().to_trait_ref(tcx, trait_id) - ); + let trait_ref = ty::Binder(ty::TraitRef::new(trait_id, rcvr_substs)); debug!("resolve_trait_associated_const: trait_ref={:?}", trait_ref); - tcx.populate_implementations_for_trait_if_necessary(trait_ref.def_id()); + tcx.populate_implementations_for_trait_if_necessary(trait_id); tcx.infer_ctxt(None, None, Reveal::NotSpecializable).enter(|infcx| { let mut selcx = traits::SelectionContext::new(&infcx); let obligation = traits::Obligation::new(traits::ObligationCause::dummy(), diff --git a/src/librustc_driver/test.rs b/src/librustc_driver/test.rs index 7711091685d38..c84b195dd4b30 100644 --- a/src/librustc_driver/test.rs +++ b/src/librustc_driver/test.rs @@ -21,7 +21,7 @@ use rustc::middle::region::CodeExtentData; use rustc::middle::resolve_lifetime; use rustc::middle::stability; use rustc::ty::subst; -use rustc::ty::subst::Subst; +use rustc::ty::subst::{Subst, Substs}; use rustc::traits::Reveal; use rustc::ty::{self, Ty, TyCtxt, TypeFoldable}; use rustc::infer::{self, InferOk, InferResult, TypeOrigin}; @@ -678,8 +678,8 @@ fn subst_ty_renumber_bound() { env.t_fn(&[t_param], env.t_nil()) }; - let substs = subst::Substs::new_type(vec![t_rptr_bound1], vec![]); - let t_substituted = t_source.subst(env.infcx.tcx, &substs); + let substs = Substs::new_type(env.infcx.tcx, vec![t_rptr_bound1], vec![]); + let t_substituted = t_source.subst(env.infcx.tcx, substs); // t_expected = fn(&'a isize) let t_expected = { @@ -713,8 +713,8 @@ fn subst_ty_renumber_some_bounds() { env.t_pair(t_param, env.t_fn(&[t_param], env.t_nil())) }; - let substs = subst::Substs::new_type(vec![t_rptr_bound1], vec![]); - let t_substituted = t_source.subst(env.infcx.tcx, &substs); + let substs = Substs::new_type(env.infcx.tcx, vec![t_rptr_bound1], vec![]); + let t_substituted = t_source.subst(env.infcx.tcx, substs); // t_expected = (&'a isize, fn(&'a isize)) // @@ -775,8 +775,8 @@ fn subst_region_renumber_region() { env.t_fn(&[env.t_rptr(re_early)], env.t_nil()) }; - let substs = subst::Substs::new_type(vec![], vec![re_bound1]); - let t_substituted = t_source.subst(env.infcx.tcx, &substs); + let substs = Substs::new_type(env.infcx.tcx, vec![], vec![re_bound1]); + let t_substituted = t_source.subst(env.infcx.tcx, substs); // t_expected = fn(&'a isize) // diff --git a/src/librustc_lint/builtin.rs b/src/librustc_lint/builtin.rs index ed17f3533d49f..61d927239828b 100644 --- a/src/librustc_lint/builtin.rs +++ b/src/librustc_lint/builtin.rs @@ -465,16 +465,14 @@ impl LateLintPass for MissingCopyImplementations { return; } let def = cx.tcx.lookup_adt_def(cx.tcx.map.local_def_id(item.id)); - (def, cx.tcx.mk_struct(def, - cx.tcx.mk_substs(Substs::empty()))) + (def, cx.tcx.mk_struct(def, Substs::empty(cx.tcx))) } hir::ItemEnum(_, ref ast_generics) => { if ast_generics.is_parameterized() { return; } let def = cx.tcx.lookup_adt_def(cx.tcx.map.local_def_id(item.id)); - (def, cx.tcx.mk_enum(def, - cx.tcx.mk_substs(Substs::empty()))) + (def, cx.tcx.mk_enum(def, Substs::empty(cx.tcx))) } _ => return, }; @@ -898,7 +896,7 @@ impl LateLintPass for UnconditionalRecursion { // A trait method, from any number of possible sources. // Attempt to select a concrete impl before checking. ty::TraitContainer(trait_def_id) => { - let trait_ref = callee_substs.to_trait_ref(tcx, trait_def_id); + let trait_ref = ty::TraitRef::from_method(tcx, trait_def_id, callee_substs); let trait_ref = ty::Binder(trait_ref); let span = tcx.map.span(expr_id); let obligation = @@ -918,8 +916,7 @@ impl LateLintPass for UnconditionalRecursion { // If `T` is `Self`, then this call is inside // a default method definition. Ok(Some(traits::VtableParam(_))) => { - let self_ty = callee_substs.self_ty(); - let on_self = self_ty.map_or(false, |t| t.is_self()); + let on_self = trait_ref.self_ty().is_self(); // We can only be recurring in a default // method if we're being called literally // on the `Self` type. diff --git a/src/librustc_metadata/astencode.rs b/src/librustc_metadata/astencode.rs index c552e612504e9..1b00eee76f69b 100644 --- a/src/librustc_metadata/astencode.rs +++ b/src/librustc_metadata/astencode.rs @@ -34,7 +34,7 @@ use middle::const_qualif::ConstQualif; use rustc::hir::def::{self, Def}; use rustc::hir::def_id::DefId; use middle::region; -use rustc::ty::subst; +use rustc::ty::subst::Substs; use rustc::ty::{self, Ty, TyCtxt}; use syntax::ast; @@ -507,7 +507,7 @@ impl<'a, 'tcx> read_method_callee_helper<'tcx> for reader::Decoder<'a> { Ok(this.read_ty(dcx)) }).unwrap(), substs: this.read_struct_field("substs", 3, |this| { - Ok(dcx.tcx.mk_substs(this.read_substs(dcx))) + Ok(this.read_substs(dcx)) }).unwrap() })) }).unwrap() @@ -525,7 +525,7 @@ trait rbml_writer_helpers<'tcx> { fn emit_region(&mut self, ecx: &e::EncodeContext, r: ty::Region); fn emit_ty<'a>(&mut self, ecx: &e::EncodeContext<'a, 'tcx>, ty: Ty<'tcx>); fn emit_substs<'a>(&mut self, ecx: &e::EncodeContext<'a, 'tcx>, - substs: &subst::Substs<'tcx>); + substs: &Substs<'tcx>); fn emit_upvar_capture(&mut self, ecx: &e::EncodeContext, capture: &ty::UpvarCapture); fn emit_auto_adjustment<'a>(&mut self, ecx: &e::EncodeContext<'a, 'tcx>, adj: &adjustment::AutoAdjustment<'tcx>); @@ -569,7 +569,7 @@ impl<'a, 'tcx> rbml_writer_helpers<'tcx> for Encoder<'a> { } fn emit_substs<'b>(&mut self, ecx: &e::EncodeContext<'b, 'tcx>, - substs: &subst::Substs<'tcx>) { + substs: &Substs<'tcx>) { self.emit_opaque(|this| Ok(tyencode::enc_substs(&mut this.cursor, &ecx.ty_str_ctxt(), substs))); @@ -839,7 +839,7 @@ trait rbml_decoder_decoder_helpers<'tcx> { fn read_predicate<'a, 'b>(&mut self, dcx: &DecodeContext<'a, 'b, 'tcx>) -> ty::Predicate<'tcx>; fn read_substs<'a, 'b>(&mut self, dcx: &DecodeContext<'a, 'b, 'tcx>) - -> subst::Substs<'tcx>; + -> &'tcx Substs<'tcx>; fn read_upvar_capture(&mut self, dcx: &DecodeContext) -> ty::UpvarCapture; fn read_auto_adjustment<'a, 'b>(&mut self, dcx: &DecodeContext<'a, 'b, 'tcx>) @@ -859,7 +859,7 @@ trait rbml_decoder_decoder_helpers<'tcx> { cdata: &cstore::CrateMetadata) -> Vec>; fn read_substs_nodcx<'a>(&mut self, tcx: TyCtxt<'a, 'tcx, 'tcx>, cdata: &cstore::CrateMetadata) - -> subst::Substs<'tcx>; + -> &'tcx Substs<'tcx>; } impl<'a, 'tcx> rbml_decoder_decoder_helpers<'tcx> for reader::Decoder<'a> { @@ -884,7 +884,7 @@ impl<'a, 'tcx> rbml_decoder_decoder_helpers<'tcx> for reader::Decoder<'a> { fn read_substs_nodcx<'b>(&mut self, tcx: TyCtxt<'b, 'tcx, 'tcx>, cdata: &cstore::CrateMetadata) - -> subst::Substs<'tcx> + -> &'tcx Substs<'tcx> { self.read_opaque(|_, doc| { Ok( @@ -946,7 +946,7 @@ impl<'a, 'tcx> rbml_decoder_decoder_helpers<'tcx> for reader::Decoder<'a> { } fn read_substs<'b, 'c>(&mut self, dcx: &DecodeContext<'b, 'c, 'tcx>) - -> subst::Substs<'tcx> { + -> &'tcx Substs<'tcx> { self.read_opaque(|_, doc| { Ok(tydecode::TyDecoder::with_doc(dcx.tcx, dcx.cdata.cnum, doc, &mut |d| convert_def_id(dcx, d)) @@ -1140,7 +1140,7 @@ fn decode_side_tables(dcx: &DecodeContext, } c::tag_table_item_subst => { let item_substs = ty::ItemSubsts { - substs: dcx.tcx.mk_substs(val_dsr.read_substs(dcx)) + substs: val_dsr.read_substs(dcx) }; dcx.tcx.tables.borrow_mut().item_substs.insert( id, item_substs); diff --git a/src/librustc_metadata/common.rs b/src/librustc_metadata/common.rs index 0011b59c70ed3..99a3f3b00c8b0 100644 --- a/src/librustc_metadata/common.rs +++ b/src/librustc_metadata/common.rs @@ -196,16 +196,11 @@ pub const tag_attribute_is_sugared_doc: usize = 0x8c; // GAP 0x8d pub const tag_items_data_region: usize = 0x8e; -pub const tag_region_param_def: usize = 0x8f; -pub const tag_region_param_def_ident: usize = 0x90; -pub const tag_region_param_def_def_id: usize = 0x91; -pub const tag_region_param_def_space: usize = 0x92; -pub const tag_region_param_def_index: usize = 0x93; +pub const tag_item_generics: usize = 0x8f; +// GAP 0x90, 0x91, 0x92, 0x93, 0x94 -pub const tag_type_param_def: usize = 0x94; - -pub const tag_item_generics: usize = 0x95; -pub const tag_method_ty_generics: usize = 0x96; +pub const tag_item_predicates: usize = 0x95; +// GAP 0x96 pub const tag_predicate: usize = 0x97; // GAP 0x98, 0x99 diff --git a/src/librustc_metadata/csearch.rs b/src/librustc_metadata/csearch.rs index 2cdbd1b86012d..f6d698eb969d8 100644 --- a/src/librustc_metadata/csearch.rs +++ b/src/librustc_metadata/csearch.rs @@ -86,7 +86,7 @@ impl<'tcx> CrateStore<'tcx> for cstore::CStore { } fn item_type<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, def: DefId) - -> ty::TypeScheme<'tcx> + -> Ty<'tcx> { self.dep_graph.read(DepNode::MetaData(def)); let cdata = self.get_crate_data(def.krate); @@ -109,6 +109,14 @@ impl<'tcx> CrateStore<'tcx> for cstore::CStore { decoder::get_super_predicates(&cdata, def.index, tcx) } + fn item_generics<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, def: DefId) + -> &'tcx ty::Generics<'tcx> + { + self.dep_graph.read(DepNode::MetaData(def)); + let cdata = self.get_crate_data(def.krate); + decoder::get_generics(&cdata, def.index, tcx) + } + fn item_attrs(&self, def_id: DefId) -> Vec { self.dep_graph.read(DepNode::MetaData(def_id)); @@ -231,11 +239,10 @@ impl<'tcx> CrateStore<'tcx> for cstore::CStore { decoder::get_parent_impl(&*cdata, impl_def.index) } - fn trait_of_item<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> Option - { + fn trait_of_item(&self, def_id: DefId) -> Option { self.dep_graph.read(DepNode::MetaData(def_id)); let cdata = self.get_crate_data(def_id.krate); - decoder::get_trait_of_item(&cdata, def_id.index, tcx) + decoder::get_trait_of_item(&cdata, def_id.index) } fn impl_or_trait_item<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, def: DefId) diff --git a/src/librustc_metadata/decoder.rs b/src/librustc_metadata/decoder.rs index eeb1859c01311..e42825ef1e549 100644 --- a/src/librustc_metadata/decoder.rs +++ b/src/librustc_metadata/decoder.rs @@ -264,11 +264,6 @@ fn maybe_doc_type<'a, 'tcx>(doc: rbml::Doc, tcx: TyCtxt<'a, 'tcx, 'tcx>, cdata: }) } -pub fn item_type<'a, 'tcx>(_item_id: DefId, item: rbml::Doc, - tcx: TyCtxt<'a, 'tcx, 'tcx>, cdata: Cmd) -> Ty<'tcx> { - doc_type(item, tcx, cdata) -} - fn doc_trait_ref<'a, 'tcx>(doc: rbml::Doc, tcx: TyCtxt<'a, 'tcx, 'tcx>, cdata: Cmd) -> ty::TraitRef<'tcx> { TyDecoder::with_doc(tcx, cdata.cnum, doc, @@ -383,7 +378,7 @@ pub fn get_trait_def<'a, 'tcx>(cdata: Cmd, tcx: TyCtxt<'a, 'tcx, 'tcx>) -> ty::TraitDef<'tcx> { let item_doc = cdata.lookup_item(item_id); - let generics = doc_generics(item_doc, tcx, cdata, tag_item_generics); + let generics = doc_generics(item_doc, tcx, cdata); let unsafety = parse_unsafety(item_doc); let associated_type_names = parse_associated_type_names(item_doc); let paren_sugar = parse_paren_sugar(item_doc); @@ -493,7 +488,7 @@ pub fn get_adt_def<'a, 'tcx>(cdata: Cmd, // from the ctor. debug!("evaluating the ctor-type of {:?}", variant.name); - let ctor_ty = get_type(cdata, variant.did.index, tcx).ty; + let ctor_ty = get_type(cdata, variant.did.index, tcx); debug!("evaluating the ctor-type of {:?}.. {:?}", variant.name, ctor_ty); @@ -513,7 +508,7 @@ pub fn get_adt_def<'a, 'tcx>(cdata: Cmd, } else { for field in &variant.fields { debug!("evaluating the type of {:?}::{:?}", variant.name, field.name); - let ty = get_type(cdata, field.did.index, tcx).ty; + let ty = get_type(cdata, field.did.index, tcx); field.fulfill_ty(ty); debug!("evaluating the type of {:?}::{:?}: {:?}", variant.name, field.name, ty); @@ -530,7 +525,7 @@ pub fn get_predicates<'a, 'tcx>(cdata: Cmd, -> ty::GenericPredicates<'tcx> { let item_doc = cdata.lookup_item(item_id); - doc_predicates(item_doc, tcx, cdata, tag_item_generics) + doc_predicates(item_doc, tcx, cdata, tag_item_predicates) } pub fn get_super_predicates<'a, 'tcx>(cdata: Cmd, @@ -542,17 +537,20 @@ pub fn get_super_predicates<'a, 'tcx>(cdata: Cmd, doc_predicates(item_doc, tcx, cdata, tag_item_super_predicates) } +pub fn get_generics<'a, 'tcx>(cdata: Cmd, + item_id: DefIndex, + tcx: TyCtxt<'a, 'tcx, 'tcx>) + -> &'tcx ty::Generics<'tcx> +{ + let item_doc = cdata.lookup_item(item_id); + doc_generics(item_doc, tcx, cdata) +} + pub fn get_type<'a, 'tcx>(cdata: Cmd, id: DefIndex, tcx: TyCtxt<'a, 'tcx, 'tcx>) - -> ty::TypeScheme<'tcx> + -> Ty<'tcx> { let item_doc = cdata.lookup_item(id); - let t = item_type(DefId { krate: cdata.cnum, index: id }, item_doc, tcx, - cdata); - let generics = doc_generics(item_doc, tcx, cdata, tag_item_generics); - ty::TypeScheme { - generics: generics, - ty: t - } + doc_type(item_doc, tcx, cdata) } pub fn get_stability(cdata: Cmd, id: DefIndex) -> Option { @@ -960,8 +958,8 @@ pub fn get_impl_or_trait_item<'a, 'tcx>(cdata: Cmd, id: DefIndex, tcx: TyCtxt<'a })) } Some('r') | Some('p') => { - let generics = doc_generics(item_doc, tcx, cdata, tag_method_ty_generics); - let predicates = doc_predicates(item_doc, tcx, cdata, tag_method_ty_generics); + let generics = doc_generics(item_doc, tcx, cdata); + let predicates = doc_predicates(item_doc, tcx, cdata, tag_item_predicates); let ity = tcx.lookup_item_type(def_id).ty; let fty = match ity.sty { ty::TyFnDef(_, _, fty) => fty, @@ -1393,10 +1391,7 @@ pub fn each_implementation_for_trait(cdata: Cmd, } } -pub fn get_trait_of_item<'a, 'tcx>(cdata: Cmd, - id: DefIndex, - tcx: TyCtxt<'a, 'tcx, 'tcx>) - -> Option { +pub fn get_trait_of_item(cdata: Cmd, id: DefIndex) -> Option { let item_doc = cdata.lookup_item(id); let parent_item_id = match item_parent_item(cdata, item_doc) { None => return None, @@ -1405,10 +1400,6 @@ pub fn get_trait_of_item<'a, 'tcx>(cdata: Cmd, let parent_item_doc = cdata.lookup_item(parent_item_id.index); match item_family(parent_item_doc) { Trait => Some(item_def_id(parent_item_doc, cdata)), - Impl | DefaultImpl => { - reader::maybe_get_doc(parent_item_doc, tag_item_trait_ref) - .map(|_| item_trait_ref(parent_item_doc, tcx, cdata).def_id) - } _ => None } } @@ -1537,11 +1528,7 @@ pub fn is_extern_item<'a, 'tcx>(cdata: Cmd, }; let applicable = match item_family(item_doc) { ImmStatic | MutStatic => true, - Fn => { - let ty::TypeScheme { generics, .. } = get_type(cdata, id, tcx); - let no_generics = generics.types.is_empty(); - no_generics - }, + Fn => get_generics(cdata, id, tcx).types.is_empty(), _ => false, }; @@ -1573,30 +1560,13 @@ pub fn is_impl(cdata: Cmd, id: DefIndex) -> bool { fn doc_generics<'a, 'tcx>(base_doc: rbml::Doc, tcx: TyCtxt<'a, 'tcx, 'tcx>, - cdata: Cmd, - tag: usize) - -> ty::Generics<'tcx> + cdata: Cmd) + -> &'tcx ty::Generics<'tcx> { - let doc = reader::get_doc(base_doc, tag); - - let mut generics = ty::Generics::empty(); - for p in reader::tagged_docs(doc, tag_type_param_def) { - let bd = - TyDecoder::with_doc(tcx, cdata.cnum, p, - &mut |did| translate_def_id(cdata, did)) - .parse_type_param_def(); - generics.types.push(bd.space, bd); - } - - for p in reader::tagged_docs(doc, tag_region_param_def) { - let bd = - TyDecoder::with_doc(tcx, cdata.cnum, p, - &mut |did| translate_def_id(cdata, did)) - .parse_region_param_def(); - generics.regions.push(bd.space, bd); - } - - generics + let doc = reader::get_doc(base_doc, tag_item_generics); + TyDecoder::with_doc(tcx, cdata.cnum, doc, + &mut |did| translate_def_id(cdata, did)) + .parse_generics() } fn doc_predicate<'a, 'tcx>(cdata: Cmd, diff --git a/src/librustc_metadata/encoder.rs b/src/librustc_metadata/encoder.rs index d19eb6391820a..1e74b3c1ef48f 100644 --- a/src/librustc_metadata/encoder.rs +++ b/src/librustc_metadata/encoder.rs @@ -175,8 +175,7 @@ fn encode_bounds_and_type<'a, 'tcx>(rbml_w: &mut Encoder, index: &mut CrateIndex<'a, 'tcx>, scheme: &ty::TypeScheme<'tcx>, predicates: &ty::GenericPredicates<'tcx>) { - encode_generics(rbml_w, ecx, index, - &scheme.generics, &predicates, tag_item_generics); + encode_generics(rbml_w, ecx, index, &scheme.generics, &predicates); encode_type(ecx, rbml_w, scheme.ty); } @@ -510,50 +509,26 @@ fn encode_generics<'a, 'tcx>(rbml_w: &mut Encoder, ecx: &EncodeContext<'a, 'tcx>, index: &mut CrateIndex<'a, 'tcx>, generics: &ty::Generics<'tcx>, - predicates: &ty::GenericPredicates<'tcx>, - tag: usize) + predicates: &ty::GenericPredicates<'tcx>) { - rbml_w.start_tag(tag); - - for param in generics.types.as_full_slice() { - rbml_w.start_tag(tag_type_param_def); - tyencode::enc_type_param_def(rbml_w.writer, &ecx.ty_str_ctxt(), param); - rbml_w.mark_stable_position(); - rbml_w.end_tag(); - } - - // Region parameters - for param in generics.regions.as_full_slice() { - rbml_w.start_tag(tag_region_param_def); - tyencode::enc_region_param_def(rbml_w.writer, &ecx.ty_str_ctxt(), param); - rbml_w.mark_stable_position(); - rbml_w.end_tag(); - } - - encode_predicates_in_current_doc(rbml_w, ecx, index, predicates); - + rbml_w.start_tag(tag_item_generics); + tyencode::enc_generics(rbml_w.writer, &ecx.ty_str_ctxt(), generics); + rbml_w.mark_stable_position(); rbml_w.end_tag(); -} -fn encode_predicates_in_current_doc<'a,'tcx>(rbml_w: &mut Encoder, - _ecx: &EncodeContext<'a,'tcx>, - index: &mut CrateIndex<'a, 'tcx>, - predicates: &ty::GenericPredicates<'tcx>) -{ - for predicate in &predicates.predicates { - rbml_w.wr_tagged_u32(tag_predicate, - index.add_xref(XRef::Predicate(predicate.clone()))); - } + encode_predicates(rbml_w, index, predicates, tag_item_predicates); } fn encode_predicates<'a,'tcx>(rbml_w: &mut Encoder, - ecx: &EncodeContext<'a,'tcx>, index: &mut CrateIndex<'a, 'tcx>, predicates: &ty::GenericPredicates<'tcx>, tag: usize) { rbml_w.start_tag(tag); - encode_predicates_in_current_doc(rbml_w, ecx, index, predicates); + for predicate in &predicates.predicates { + rbml_w.wr_tagged_u32(tag_predicate, + index.add_xref(XRef::Predicate(predicate.clone()))); + } rbml_w.end_tag(); } @@ -564,8 +539,7 @@ fn encode_method_ty_fields<'a, 'tcx>(ecx: &EncodeContext<'a, 'tcx>, encode_def_id_and_key(ecx, rbml_w, method_ty.def_id); encode_name(rbml_w, method_ty.name); encode_generics(rbml_w, ecx, index, - &method_ty.generics, &method_ty.predicates, - tag_method_ty_generics); + &method_ty.generics, &method_ty.predicates); encode_visibility(rbml_w, method_ty.vis); encode_explicit_self(rbml_w, &method_ty.explicit_self); match method_ty.explicit_self { @@ -695,7 +669,7 @@ fn encode_info_for_associated_type<'a, 'tcx>(ecx: &EncodeContext<'a, 'tcx>, encode_attributes(rbml_w, &ii.attrs); encode_defaultness(rbml_w, ii.defaultness); } else { - encode_predicates(rbml_w, ecx, index, + encode_predicates(rbml_w, index, &ecx.tcx.lookup_predicates(associated_type.def_id), tag_item_generics); } @@ -1134,9 +1108,8 @@ fn encode_info_for_item<'a, 'tcx>(ecx: &EncodeContext<'a, 'tcx>, encode_defaulted(rbml_w, tcx.trait_has_default_impl(def_id)); encode_associated_type_names(rbml_w, &trait_def.associated_type_names); encode_generics(rbml_w, ecx, index, - &trait_def.generics, &trait_predicates, - tag_item_generics); - encode_predicates(rbml_w, ecx, index, + &trait_def.generics, &trait_predicates); + encode_predicates(rbml_w, index, &tcx.lookup_super_predicates(def_id), tag_item_super_predicates); encode_trait_ref(rbml_w, ecx, trait_def.trait_ref, tag_item_trait_ref); diff --git a/src/librustc_metadata/tls_context.rs b/src/librustc_metadata/tls_context.rs index 23142ca80ef0e..6e78cbcd28e73 100644 --- a/src/librustc_metadata/tls_context.rs +++ b/src/librustc_metadata/tls_context.rs @@ -74,7 +74,7 @@ impl<'a, 'tcx: 'a> tls::DecodingContext<'tcx> for DecodingContext<'a, 'tcx> { ty } - fn decode_substs(&self, decoder: &mut OpaqueDecoder) -> Substs<'tcx> { + fn decode_substs(&self, decoder: &mut OpaqueDecoder) -> &'tcx Substs<'tcx> { let def_id_convert = &mut |did| { decoder::translate_def_id(self.crate_metadata, did) }; diff --git a/src/librustc_metadata/tydecode.rs b/src/librustc_metadata/tydecode.rs index 11c155cbd5b9f..3f0fa9073aa36 100644 --- a/src/librustc_metadata/tydecode.rs +++ b/src/librustc_metadata/tydecode.rs @@ -20,8 +20,7 @@ use rustc::hir; use rustc::hir::def_id::{DefId, DefIndex}; use middle::region; -use rustc::ty::subst; -use rustc::ty::subst::VecPerParamSpace; +use rustc::ty::subst::{self, Substs, VecPerParamSpace}; use rustc::ty::{self, ToPredicate, Ty, TyCtxt, TypeFoldable}; use rbml; @@ -132,21 +131,31 @@ impl<'a,'tcx> TyDecoder<'a,'tcx> { fn parse_vec_per_param_space(&mut self, mut f: F) -> VecPerParamSpace where F: FnMut(&mut TyDecoder<'a, 'tcx>) -> T, { - let mut r = VecPerParamSpace::empty(); - for &space in &subst::ParamSpace::all() { + let (mut a, mut b, mut c) = (vec![], vec![], vec![]); + for r in &mut [&mut a, &mut b, &mut c] { assert_eq!(self.next(), '['); while self.peek() != ']' { - r.push(space, f(self)); + r.push(f(self)); } assert_eq!(self.next(), ']'); } - r + VecPerParamSpace::new(a, b, c) } - pub fn parse_substs(&mut self) -> subst::Substs<'tcx> { + pub fn parse_substs(&mut self) -> &'tcx Substs<'tcx> { let regions = self.parse_vec_per_param_space(|this| this.parse_region()); let types = self.parse_vec_per_param_space(|this| this.parse_ty()); - subst::Substs { types: types, regions: regions } + Substs::new(self.tcx, types, regions) + } + + pub fn parse_generics(&mut self) -> &'tcx ty::Generics<'tcx> { + let regions = self.parse_vec_per_param_space(|this| this.parse_region_param_def()); + let types = self.parse_vec_per_param_space(|this| this.parse_type_param_def()); + self.tcx.alloc_generics(ty::Generics { + regions: regions, + types: types, + has_self: self.next() == 'S' + }) } fn parse_bound_region(&mut self) -> ty::BoundRegion { @@ -302,15 +311,17 @@ impl<'a,'tcx> TyDecoder<'a,'tcx> { } pub fn parse_trait_ref(&mut self) -> ty::TraitRef<'tcx> { - let def = self.parse_def(); - let substs = self.tcx.mk_substs(self.parse_substs()); - ty::TraitRef {def_id: def, substs: substs} + ty::TraitRef { + def_id: self.parse_def(), + substs: self.parse_substs() + } } pub fn parse_existential_trait_ref(&mut self) -> ty::ExistentialTraitRef<'tcx> { - let def = self.parse_def(); - let substs = self.tcx.mk_substs(self.parse_substs()); - ty::ExistentialTraitRef {def_id: def, substs: substs} + ty::ExistentialTraitRef { + def_id: self.parse_def(), + substs: self.parse_substs() + } } pub fn parse_ty(&mut self) -> Ty<'tcx> { @@ -342,7 +353,7 @@ impl<'a,'tcx> TyDecoder<'a,'tcx> { let substs = self.parse_substs(); assert_eq!(self.next(), ']'); let def = self.tcx.lookup_adt_def(did); - return tcx.mk_enum(def, self.tcx.mk_substs(substs)); + return tcx.mk_enum(def, substs); } 'x' => { assert_eq!(self.next(), '['); @@ -406,7 +417,7 @@ impl<'a,'tcx> TyDecoder<'a,'tcx> { } 'F' => { let def_id = self.parse_def(); - let substs = self.tcx.mk_substs(self.parse_substs()); + let substs = self.parse_substs(); return tcx.mk_fn_def(def_id, substs, self.parse_bare_fn_ty()); } 'G' => { @@ -452,7 +463,7 @@ impl<'a,'tcx> TyDecoder<'a,'tcx> { let substs = self.parse_substs(); assert_eq!(self.next(), ']'); let def = self.tcx.lookup_adt_def(did); - return self.tcx.mk_struct(def, self.tcx.mk_substs(substs)); + return self.tcx.mk_struct(def, substs); } 'k' => { assert_eq!(self.next(), '['); @@ -464,7 +475,7 @@ impl<'a,'tcx> TyDecoder<'a,'tcx> { } assert_eq!(self.next(), '.'); assert_eq!(self.next(), ']'); - return self.tcx.mk_closure(did, self.tcx.mk_substs(substs), tys); + return self.tcx.mk_closure(did, substs, tys); } 'P' => { assert_eq!(self.next(), '['); @@ -477,7 +488,7 @@ impl<'a,'tcx> TyDecoder<'a,'tcx> { let def_id = self.parse_def(); let substs = self.parse_substs(); assert_eq!(self.next(), ']'); - return self.tcx.mk_anon(def_id, self.tcx.mk_substs(substs)); + return self.tcx.mk_anon(def_id, substs); } 'e' => { return tcx.types.err; @@ -622,7 +633,7 @@ impl<'a,'tcx> TyDecoder<'a,'tcx> { } } - pub fn parse_type_param_def(&mut self) -> ty::TypeParameterDef<'tcx> { + fn parse_type_param_def(&mut self) -> ty::TypeParameterDef<'tcx> { let name = self.parse_name(':'); let def_id = self.parse_def(); let space = self.parse_param_space(); @@ -644,7 +655,7 @@ impl<'a,'tcx> TyDecoder<'a,'tcx> { } } - pub fn parse_region_param_def(&mut self) -> ty::RegionParameterDef { + fn parse_region_param_def(&mut self) -> ty::RegionParameterDef { let name = self.parse_name(':'); let def_id = self.parse_def(); let space = self.parse_param_space(); diff --git a/src/librustc_metadata/tyencode.rs b/src/librustc_metadata/tyencode.rs index 8deb1eb6ac31d..130d15485829a 100644 --- a/src/librustc_metadata/tyencode.rs +++ b/src/librustc_metadata/tyencode.rs @@ -19,8 +19,7 @@ use std::io::prelude::*; use rustc::hir::def_id::DefId; use middle::region; -use rustc::ty::subst; -use rustc::ty::subst::VecPerParamSpace; +use rustc::ty::subst::{self, Substs, VecPerParamSpace}; use rustc::ty::ParamTy; use rustc::ty::{self, Ty, TyCtxt}; use rustc::util::nodemap::FnvHashMap; @@ -266,13 +265,27 @@ fn enc_vec_per_param_space<'a, 'tcx, T, F>(w: &mut Cursor>, } pub fn enc_substs<'a, 'tcx>(w: &mut Cursor>, cx: &ctxt<'a, 'tcx>, - substs: &subst::Substs<'tcx>) { + substs: &Substs<'tcx>) { enc_vec_per_param_space(w, cx, &substs.regions, |w, cx, &r| enc_region(w, cx, r)); enc_vec_per_param_space(w, cx, &substs.types, |w, cx, &ty| enc_ty(w, cx, ty)); } +pub fn enc_generics<'a, 'tcx>(w: &mut Cursor>, cx: &ctxt<'a, 'tcx>, + generics: &ty::Generics<'tcx>) { + enc_vec_per_param_space(w, cx, &generics.regions, + |w, cx, r| enc_region_param_def(w, cx, r)); + enc_vec_per_param_space(w, cx, &generics.types, + |w, cx, ty| enc_type_param_def(w, cx, ty)); + + if generics.has_self { + write!(w, "S"); + } else { + write!(w, "N"); + } +} + pub fn enc_region(w: &mut Cursor>, cx: &ctxt, r: ty::Region) { match r { ty::ReLateBound(id, br) => { @@ -420,8 +433,8 @@ fn enc_builtin_bounds(w: &mut Cursor>, _cx: &ctxt, bs: &ty::BuiltinBound write!(w, "."); } -pub fn enc_type_param_def<'a, 'tcx>(w: &mut Cursor>, cx: &ctxt<'a, 'tcx>, - v: &ty::TypeParameterDef<'tcx>) { +fn enc_type_param_def<'a, 'tcx>(w: &mut Cursor>, cx: &ctxt<'a, 'tcx>, + v: &ty::TypeParameterDef<'tcx>) { write!(w, "{}:{}|{}|{}|{}|", v.name, (cx.ds)(cx.tcx, v.def_id), v.space.to_uint(), v.index, (cx.ds)(cx.tcx, v.default_def_id)); @@ -429,8 +442,8 @@ pub fn enc_type_param_def<'a, 'tcx>(w: &mut Cursor>, cx: &ctxt<'a, 'tcx> enc_object_lifetime_default(w, cx, v.object_lifetime_default); } -pub fn enc_region_param_def(w: &mut Cursor>, cx: &ctxt, - v: &ty::RegionParameterDef) { +fn enc_region_param_def(w: &mut Cursor>, cx: &ctxt, + v: &ty::RegionParameterDef) { write!(w, "{}:{}|{}|{}|", v.name, (cx.ds)(cx.tcx, v.def_id), v.space.to_uint(), v.index); diff --git a/src/librustc_mir/build/scope.rs b/src/librustc_mir/build/scope.rs index 6af9ad02b91ba..229890483882c 100644 --- a/src/librustc_mir/build/scope.rs +++ b/src/librustc_mir/build/scope.rs @@ -750,7 +750,7 @@ fn build_free<'a, 'gcx, 'tcx>(tcx: TyCtxt<'a, 'gcx, 'tcx>, -> TerminatorKind<'tcx> { let free_func = tcx.lang_items.require(lang_items::BoxFreeFnLangItem) .unwrap_or_else(|e| tcx.sess.fatal(&e)); - let substs = tcx.mk_substs(Substs::new_fn(vec![data.item_ty], vec![])); + let substs = Substs::new_fn(tcx, vec![data.item_ty], vec![]); TerminatorKind::Call { func: Operand::Constant(Constant { span: data.span, diff --git a/src/librustc_mir/hair/cx/mod.rs b/src/librustc_mir/hair/cx/mod.rs index df1fec75939b5..972e7f5be7075 100644 --- a/src/librustc_mir/hair/cx/mod.rs +++ b/src/librustc_mir/hair/cx/mod.rs @@ -147,16 +147,16 @@ impl<'a, 'gcx, 'tcx> Cx<'a, 'gcx, 'tcx> { params: Vec>) -> (Ty<'tcx>, Literal<'tcx>) { let method_name = token::intern(method_name); - let substs = Substs::new_trait(params, vec![], self_ty); + let substs = Substs::new_trait(self.tcx, params, vec![], self_ty); for trait_item in self.tcx.trait_items(trait_def_id).iter() { match *trait_item { ty::ImplOrTraitItem::MethodTraitItem(ref method) => { if method.name == method_name { let method_ty = self.tcx.lookup_item_type(method.def_id); - let method_ty = method_ty.ty.subst(self.tcx, &substs); + let method_ty = method_ty.ty.subst(self.tcx, substs); return (method_ty, Literal::Item { def_id: method.def_id, - substs: self.tcx.mk_substs(substs), + substs: substs, }); } } diff --git a/src/librustc_save_analysis/lib.rs b/src/librustc_save_analysis/lib.rs index 16cd9186ce9bb..6c9cf1a5625b2 100644 --- a/src/librustc_save_analysis/lib.rs +++ b/src/librustc_save_analysis/lib.rs @@ -299,8 +299,7 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> { let mut result = String::from("<"); result.push_str(&rustc::hir::print::ty_to_string(&ty)); - if let Some(def_id) = self.tcx - .trait_of_item(self.tcx.map.local_def_id(id)) { + if let Some(def_id) = self.tcx.trait_id_of_impl(impl_id) { result.push_str(" as "); result.push_str(&self.tcx.item_path_str(def_id)); } diff --git a/src/librustc_trans/_match.rs b/src/librustc_trans/_match.rs index 27a8c1f1df476..d6866b27f98a5 100644 --- a/src/librustc_trans/_match.rs +++ b/src/librustc_trans/_match.rs @@ -895,7 +895,7 @@ fn compare_values<'blk, 'tcx>(cx: Block<'blk, 'tcx>, &format!("comparison of `{}`", rhs_t), StrEqFnLangItem); let args = [lhs_data, lhs_len, rhs_data, rhs_len]; - Callee::def(bcx.ccx(), did, bcx.tcx().mk_substs(Substs::empty())) + Callee::def(bcx.ccx(), did, Substs::empty(bcx.tcx())) .call(bcx, debug_loc, ArgVals(&args), None) } diff --git a/src/librustc_trans/adt.rs b/src/librustc_trans/adt.rs index 23c4258caf7bd..d48ec98a20dfb 100644 --- a/src/librustc_trans/adt.rs +++ b/src/librustc_trans/adt.rs @@ -48,7 +48,7 @@ use std; use std::rc::Rc; use llvm::{ValueRef, True, IntEQ, IntNE}; -use rustc::ty::subst; +use rustc::ty::subst::Substs; use rustc::ty::{self, Ty, TyCtxt}; use syntax::ast; use syntax::attr; @@ -544,7 +544,7 @@ impl<'tcx> Case<'tcx> { fn get_cases<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, adt: ty::AdtDef<'tcx>, - substs: &subst::Substs<'tcx>) + substs: &Substs<'tcx>) -> Vec> { adt.variants.iter().map(|vi| { let field_tys = vi.fields.iter().map(|field| { diff --git a/src/librustc_trans/base.rs b/src/librustc_trans/base.rs index 749a7495421ed..ee5d1d11fa0a6 100644 --- a/src/librustc_trans/base.rs +++ b/src/librustc_trans/base.rs @@ -218,7 +218,7 @@ pub fn malloc_raw_dyn<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, // Allocate space: let def_id = require_alloc_fn(bcx, info_ty, ExchangeMallocFnLangItem); - let r = Callee::def(bcx.ccx(), def_id, bcx.tcx().mk_substs(Substs::empty())) + let r = Callee::def(bcx.ccx(), def_id, Substs::empty(bcx.tcx())) .call(bcx, debug_loc, ArgVals(&[size, align]), None); Result::new(r.bcx, PointerCast(r.bcx, r.val, llty_ptr)) @@ -670,11 +670,9 @@ pub fn custom_coerce_unsize_info<'scx, 'tcx>(scx: &SharedCrateContext<'scx, 'tcx source_ty: Ty<'tcx>, target_ty: Ty<'tcx>) -> CustomCoerceUnsized { - let trait_substs = Substs::new_trait(vec![target_ty], vec![], source_ty); - let trait_ref = ty::Binder(ty::TraitRef { def_id: scx.tcx().lang_items.coerce_unsized_trait().unwrap(), - substs: scx.tcx().mk_substs(trait_substs) + substs: Substs::new_trait(scx.tcx(), vec![target_ty], vec![], source_ty) }); match fulfill_obligation(scx, DUMMY_SP, trait_ref) { @@ -1410,7 +1408,7 @@ impl<'blk, 'tcx> FunctionContext<'blk, 'tcx> { common::validate_substs(instance.substs); (instance.substs, Some(instance.def), Some(inlined_id)) } - None => (ccx.tcx().mk_substs(Substs::empty()), None, None) + None => (Substs::empty(ccx.tcx()), None, None) }; let local_id = def_id.and_then(|id| ccx.tcx().map.as_local_node_id(id)); @@ -2175,7 +2173,7 @@ pub fn maybe_create_entry_wrapper(ccx: &CrateContext) { Ok(id) => id, Err(s) => ccx.sess().fatal(&s) }; - let empty_substs = ccx.tcx().mk_substs(Substs::empty()); + let empty_substs = Substs::empty(ccx.tcx()); let start_fn = Callee::def(ccx, start_def_id, empty_substs).reify(ccx).val; let args = { let opaque_rust_main = diff --git a/src/librustc_trans/callee.rs b/src/librustc_trans/callee.rs index aaec2a47025a2..d50959b5ab302 100644 --- a/src/librustc_trans/callee.rs +++ b/src/librustc_trans/callee.rs @@ -22,7 +22,7 @@ use back::symbol_names; use llvm::{self, ValueRef, get_params}; use middle::cstore::LOCAL_CRATE; use rustc::hir::def_id::DefId; -use rustc::ty::subst; +use rustc::ty::subst::Substs; use rustc::traits; use rustc::hir::map as hir_map; use abi::{Abi, FnType}; @@ -105,13 +105,12 @@ impl<'tcx> Callee<'tcx> { /// Function or method definition. pub fn def<'a>(ccx: &CrateContext<'a, 'tcx>, def_id: DefId, - substs: &'tcx subst::Substs<'tcx>) + substs: &'tcx Substs<'tcx>) -> Callee<'tcx> { let tcx = ccx.tcx(); - if substs.self_ty().is_some() { - // Only trait methods can have a Self parameter. - return Callee::trait_method(ccx, def_id, substs); + if let Some(trait_id) = tcx.trait_of_item(def_id) { + return Callee::trait_method(ccx, trait_id, def_id, substs); } let maybe_node_id = inline::get_local_instance(ccx, def_id) @@ -144,24 +143,21 @@ impl<'tcx> Callee<'tcx> { /// Trait method, which has to be resolved to an impl method. pub fn trait_method<'a>(ccx: &CrateContext<'a, 'tcx>, + trait_id: DefId, def_id: DefId, - substs: &'tcx subst::Substs<'tcx>) + substs: &'tcx Substs<'tcx>) -> Callee<'tcx> { let tcx = ccx.tcx(); - let method_item = tcx.impl_or_trait_item(def_id); - let trait_id = method_item.container().id(); - let trait_ref = ty::Binder(substs.to_trait_ref(tcx, trait_id)); - let trait_ref = tcx.normalize_associated_type(&trait_ref); + let trait_ref = ty::TraitRef::from_method(tcx, trait_id, substs); + let trait_ref = tcx.normalize_associated_type(&ty::Binder(trait_ref)); match common::fulfill_obligation(ccx.shared(), DUMMY_SP, trait_ref) { traits::VtableImpl(vtable_impl) => { let impl_did = vtable_impl.impl_def_id; let mname = tcx.item_name(def_id); // create a concatenated set of substitutions which includes // those from the impl and those from the method: - let impl_substs = vtable_impl.substs.with_method_from(&substs); - let substs = tcx.mk_substs(impl_substs); - let mth = meth::get_impl_method(tcx, impl_did, substs, mname); + let mth = meth::get_impl_method(tcx, substs, impl_did, vtable_impl.substs, mname); // Translate the function, bypassing Callee::def. // That is because default methods have the same ID as the @@ -275,7 +271,7 @@ impl<'tcx> Callee<'tcx> { /// Given a DefId and some Substs, produces the monomorphic item type. fn def_ty<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId, - substs: &'tcx subst::Substs<'tcx>) + substs: &'tcx Substs<'tcx>) -> Ty<'tcx> { let ty = tcx.lookup_item_type(def_id).ty; monomorphize::apply_param_substs(tcx, substs, &ty) @@ -427,7 +423,7 @@ pub fn trans_fn_pointer_shim<'a, 'tcx>( /// - `substs`: values for each of the fn/method's parameters fn get_fn<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, def_id: DefId, - substs: &'tcx subst::Substs<'tcx>) + substs: &'tcx Substs<'tcx>) -> Datum<'tcx, Rvalue> { let tcx = ccx.tcx(); diff --git a/src/librustc_trans/collector.rs b/src/librustc_trans/collector.rs index 277110347d01d..82c86928783bc 100644 --- a/src/librustc_trans/collector.rs +++ b/src/librustc_trans/collector.rs @@ -732,7 +732,7 @@ fn find_drop_glue_neighbors<'a, 'tcx>(scx: &SharedCrateContext<'a, 'tcx>, create_fn_trans_item(scx.tcx(), exchange_free_fn_def_id, fn_substs, - scx.tcx().mk_substs(Substs::empty())); + Substs::empty(scx.tcx())); output.push(exchange_free_fn_trans_item); } @@ -753,8 +753,7 @@ fn find_drop_glue_neighbors<'a, 'tcx>(scx: &SharedCrateContext<'a, 'tcx>, .drop_trait() .unwrap(); - let self_type_substs = scx.tcx().mk_substs( - Substs::empty().with_self_ty(ty)); + let self_type_substs = Substs::new_trait(scx.tcx(), vec![], vec![], ty); let trait_ref = ty::TraitRef { def_id: drop_trait_def_id, @@ -770,7 +769,7 @@ fn find_drop_glue_neighbors<'a, 'tcx>(scx: &SharedCrateContext<'a, 'tcx>, let trans_item = create_fn_trans_item(scx.tcx(), destructor_did, substs, - scx.tcx().mk_substs(Substs::empty())); + Substs::empty(scx.tcx())); output.push(trans_item); } @@ -854,26 +853,15 @@ fn do_static_dispatch<'a, 'tcx>(scx: &SharedCrateContext<'a, 'tcx>, fn_substs, param_substs); - let is_trait_method = scx.tcx().trait_of_item(fn_def_id).is_some(); - - if is_trait_method { + if let Some(trait_def_id) = scx.tcx().trait_of_item(fn_def_id) { match scx.tcx().impl_or_trait_item(fn_def_id) { ty::MethodTraitItem(ref method) => { - match method.container { - ty::TraitContainer(trait_def_id) => { - debug!(" => trait method, attempting to find impl"); - do_static_trait_method_dispatch(scx, - method, - trait_def_id, - fn_substs, - param_substs) - } - ty::ImplContainer(_) => { - // This is already a concrete implementation - debug!(" => impl method"); - Some((fn_def_id, fn_substs)) - } - } + debug!(" => trait method, attempting to find impl"); + do_static_trait_method_dispatch(scx, + method, + trait_def_id, + fn_substs, + param_substs) } _ => bug!() } @@ -903,13 +891,12 @@ fn do_static_trait_method_dispatch<'a, 'tcx>(scx: &SharedCrateContext<'a, 'tcx>, callee_substs, param_substs); + let rcvr_substs = monomorphize::apply_param_substs(tcx, param_substs, &callee_substs); - - let trait_ref = ty::Binder(rcvr_substs.to_trait_ref(tcx, trait_id)); - let trait_ref = tcx.normalize_associated_type(&trait_ref); - let vtbl = fulfill_obligation(scx, DUMMY_SP, trait_ref); + let trait_ref = ty::TraitRef::from_method(tcx, trait_id, rcvr_substs); + let vtbl = fulfill_obligation(scx, DUMMY_SP, ty::Binder(trait_ref)); // Now that we know which impl is being used, we can dispatch to // the actual function: @@ -919,10 +906,10 @@ fn do_static_trait_method_dispatch<'a, 'tcx>(scx: &SharedCrateContext<'a, 'tcx>, substs: impl_substs, nested: _ }) => { - let callee_substs = impl_substs.with_method_from(&rcvr_substs); let impl_method = meth::get_impl_method(tcx, + rcvr_substs, impl_did, - tcx.mk_substs(callee_substs), + impl_substs, trait_method.name); Some((impl_method.method.def_id, &impl_method.substs)) } @@ -1076,7 +1063,7 @@ fn create_trans_items_for_vtable_methods<'a, 'tcx>(scx: &SharedCrateContext<'a, Some(create_fn_trans_item(scx.tcx(), impl_method.method.def_id, impl_method.substs, - scx.tcx().mk_substs(Substs::empty()))) + Substs::empty(scx.tcx()))) } else { None } @@ -1248,9 +1235,13 @@ fn create_trans_items_for_default_impls<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, // The substitutions we have are on the impl, so we grab // the method type from the impl to substitute into. + let impl_substs = Substs::for_item(tcx, impl_def_id, + |_, _| ty::ReErased, + |_, _| tcx.types.err); let mth = meth::get_impl_method(tcx, - impl_def_id, callee_substs, + impl_def_id, + impl_substs, default_impl.name); assert!(mth.is_provided); diff --git a/src/librustc_trans/common.rs b/src/librustc_trans/common.rs index 79cf77cd9d35d..b1aaea7d984c9 100644 --- a/src/librustc_trans/common.rs +++ b/src/librustc_trans/common.rs @@ -523,7 +523,7 @@ impl<'a, 'tcx> FunctionContext<'a, 'tcx> { let tcx = ccx.tcx(); match tcx.lang_items.eh_personality() { Some(def_id) if !base::wants_msvc_seh(ccx.sess()) => { - Callee::def(ccx, def_id, tcx.mk_substs(Substs::empty())).reify(ccx).val + Callee::def(ccx, def_id, Substs::empty(tcx)).reify(ccx).val } _ => { if let Some(llpersonality) = ccx.eh_personality().get() { @@ -550,7 +550,7 @@ impl<'a, 'tcx> FunctionContext<'a, 'tcx> { let tcx = ccx.tcx(); assert!(ccx.sess().target.target.options.custom_unwind_resume); if let Some(def_id) = tcx.lang_items.eh_unwind_resume() { - return Callee::def(ccx, def_id, tcx.mk_substs(Substs::empty())); + return Callee::def(ccx, def_id, Substs::empty(tcx)); } let ty = tcx.mk_fn_ptr(tcx.mk_bare_fn(ty::BareFnTy { diff --git a/src/librustc_trans/consts.rs b/src/librustc_trans/consts.rs index 3ecba3691d279..0e9898896778c 100644 --- a/src/librustc_trans/consts.rs +++ b/src/librustc_trans/consts.rs @@ -208,7 +208,7 @@ fn const_fn_call<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, let arg_ids = args.iter().map(|arg| arg.pat.id); let fn_args = arg_ids.zip(arg_vals.iter().cloned()).collect(); - let substs = ccx.tcx().mk_substs(substs.clone().erase_regions()); + let substs = ccx.tcx().erase_regions(&substs); let substs = monomorphize::apply_param_substs(ccx.tcx(), param_substs, &substs); @@ -222,7 +222,7 @@ pub fn get_const_expr<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, param_substs: &'tcx Substs<'tcx>) -> &'tcx hir::Expr { let substs = ccx.tcx().node_id_item_substs(ref_expr.id).substs; - let substs = ccx.tcx().mk_substs(substs.clone().erase_regions()); + let substs = ccx.tcx().erase_regions(&substs); let substs = monomorphize::apply_param_substs(ccx.tcx(), param_substs, &substs); @@ -271,7 +271,7 @@ fn get_const_val<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, param_substs: &'tcx Substs<'tcx>) -> Result { let expr = get_const_expr(ccx, def_id, ref_expr, param_substs); - let empty_substs = ccx.tcx().mk_substs(Substs::empty()); + let empty_substs = Substs::empty(ccx.tcx()); match get_const_expr_as_global(ccx, expr, ConstQualif::empty(), empty_substs, TrueConst::Yes) { Err(Runtime(err)) => { report_const_eval_err(ccx.tcx(), &err, expr.span, "expression").emit(); @@ -1160,7 +1160,7 @@ pub fn trans_static(ccx: &CrateContext, let v = if use_mir { ::mir::trans_static_initializer(ccx, def_id) } else { - let empty_substs = ccx.tcx().mk_substs(Substs::empty()); + let empty_substs = Substs::empty(ccx.tcx()); const_expr(ccx, expr, empty_substs, None, TrueConst::Yes) .map(|(v, _)| v) }.map_err(|e| e.into_inner())?; diff --git a/src/librustc_trans/context.rs b/src/librustc_trans/context.rs index 65eea1bbb6337..c31dbf8943e08 100644 --- a/src/librustc_trans/context.rs +++ b/src/librustc_trans/context.rs @@ -30,7 +30,7 @@ use monomorphize::Instance; use partitioning::CodegenUnit; use trans_item::TransItem; use type_::{Type, TypeNames}; -use rustc::ty::subst::{Substs, VecPerParamSpace}; +use rustc::ty::subst::Substs; use rustc::ty::{self, Ty, TyCtxt}; use session::config::NoDebugInfo; use session::Session; @@ -571,16 +571,9 @@ impl<'b, 'tcx> SharedCrateContext<'b, 'tcx> { /// Given the def-id of some item that has no type parameters, make /// a suitable "empty substs" for it. pub fn empty_substs_for_def_id(&self, item_def_id: DefId) -> &'tcx Substs<'tcx> { - let scheme = self.tcx().lookup_item_type(item_def_id); - self.empty_substs_for_scheme(&scheme) - } - - pub fn empty_substs_for_scheme(&self, scheme: &ty::TypeScheme<'tcx>) - -> &'tcx Substs<'tcx> { - assert!(scheme.generics.types.is_empty()); - self.tcx().mk_substs( - Substs::new(VecPerParamSpace::empty(), - scheme.generics.regions.map(|_| ty::ReErased))) + Substs::for_item(self.tcx(), item_def_id, |_, _| ty::ReErased, |_, _| { + bug!("empty_substs_for_def_id: {:?} has type parameters", item_def_id) + }) } pub fn symbol_hasher(&self) -> &RefCell { @@ -999,11 +992,6 @@ impl<'b, 'tcx> CrateContext<'b, 'tcx> { pub fn empty_substs_for_def_id(&self, item_def_id: DefId) -> &'tcx Substs<'tcx> { self.shared().empty_substs_for_def_id(item_def_id) } - - pub fn empty_substs_for_scheme(&self, scheme: &ty::TypeScheme<'tcx>) - -> &'tcx Substs<'tcx> { - self.shared().empty_substs_for_scheme(scheme) - } } pub struct TypeOfDepthLock<'a, 'tcx: 'a>(&'a LocalCrateContext<'tcx>); diff --git a/src/librustc_trans/controlflow.rs b/src/librustc_trans/controlflow.rs index 8845f124218bc..8b3a8a2bfccfb 100644 --- a/src/librustc_trans/controlflow.rs +++ b/src/librustc_trans/controlflow.rs @@ -401,7 +401,7 @@ pub fn trans_fail<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, let expr_file_line = consts::addr_of(ccx, expr_file_line_const, align, "panic_loc"); let args = vec!(expr_file_line); let did = langcall(bcx.tcx(), Some(call_info.span), "", PanicFnLangItem); - Callee::def(ccx, did, ccx.tcx().mk_substs(Substs::empty())) + Callee::def(ccx, did, Substs::empty(ccx.tcx())) .call(bcx, call_info.debug_loc(), ArgVals(&args), None).bcx } @@ -429,6 +429,6 @@ pub fn trans_fail_bounds_check<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, let file_line = consts::addr_of(ccx, file_line_const, align, "panic_bounds_check_loc"); let args = vec!(file_line, index, len); let did = langcall(bcx.tcx(), Some(call_info.span), "", PanicBoundsCheckFnLangItem); - Callee::def(ccx, did, ccx.tcx().mk_substs(Substs::empty())) + Callee::def(ccx, did, Substs::empty(ccx.tcx())) .call(bcx, call_info.debug_loc(), ArgVals(&args), None).bcx } diff --git a/src/librustc_trans/debuginfo/metadata.rs b/src/librustc_trans/debuginfo/metadata.rs index 6a99f12b2788c..e80dd28c5e502 100644 --- a/src/librustc_trans/debuginfo/metadata.rs +++ b/src/librustc_trans/debuginfo/metadata.rs @@ -27,7 +27,7 @@ use llvm::debuginfo::{DIType, DIFile, DIScope, DIDescriptor, DICompositeType}; use rustc::hir::def_id::DefId; use rustc::hir::pat_util; -use rustc::ty::subst; +use rustc::ty::subst::Substs; use rustc::hir::map as hir_map; use rustc::hir::{self, PatKind}; use {type_of, adt, machine, monomorphize}; @@ -315,7 +315,7 @@ impl<'tcx> TypeMap<'tcx> { fn from_def_id_and_substs<'a, 'tcx>(type_map: &mut TypeMap<'tcx>, cx: &CrateContext<'a, 'tcx>, def_id: DefId, - substs: &subst::Substs<'tcx>, + substs: &Substs<'tcx>, output: &mut String) { // First, find out the 'real' def_id of the type. Items inlined from // other crates have to be mapped back to their source. @@ -346,7 +346,7 @@ impl<'tcx> TypeMap<'tcx> { // Add the def-index as the second part output.push_str(&format!("{:x}", def_id.index.as_usize())); - let tps = substs.types.get_slice(subst::TypeSpace); + let tps = substs.types.as_full_slice(); if !tps.is_empty() { output.push('<'); @@ -1086,7 +1086,7 @@ impl<'tcx> MemberDescriptionFactory<'tcx> { // Creates MemberDescriptions for the fields of a struct struct StructMemberDescriptionFactory<'tcx> { variant: ty::VariantDef<'tcx>, - substs: &'tcx subst::Substs<'tcx>, + substs: &'tcx Substs<'tcx>, is_simd: bool, span: Span, } diff --git a/src/librustc_trans/debuginfo/mod.rs b/src/librustc_trans/debuginfo/mod.rs index 1aae3b3127faa..963cc09e1ab95 100644 --- a/src/librustc_trans/debuginfo/mod.rs +++ b/src/librustc_trans/debuginfo/mod.rs @@ -266,7 +266,7 @@ pub fn create_function_debug_context<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, // Get_template_parameters() will append a `<...>` clause to the function // name if necessary. - let generics = cx.tcx().lookup_item_type(fn_def_id).generics; + let generics = cx.tcx().lookup_generics(fn_def_id); let template_parameters = get_template_parameters(cx, &generics, instance.substs, diff --git a/src/librustc_trans/debuginfo/type_names.rs b/src/librustc_trans/debuginfo/type_names.rs index 4bca091ef95ac..20dbc8ac78eaf 100644 --- a/src/librustc_trans/debuginfo/type_names.rs +++ b/src/librustc_trans/debuginfo/type_names.rs @@ -12,7 +12,7 @@ use common::CrateContext; use rustc::hir::def_id::DefId; -use rustc::ty::subst; +use rustc::ty::subst::Substs; use rustc::ty::{self, Ty}; use rustc::hir; @@ -173,7 +173,7 @@ pub fn push_debuginfo_type_name<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, // would be possible but with inlining and LTO we have to use the least // common denominator - otherwise we would run into conflicts. fn push_type_params<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, - substs: &subst::Substs<'tcx>, + substs: &Substs<'tcx>, output: &mut String) { if substs.types.is_empty() { return; diff --git a/src/librustc_trans/expr.rs b/src/librustc_trans/expr.rs index 6c894ddad1a94..beb589c80bfc5 100644 --- a/src/librustc_trans/expr.rs +++ b/src/librustc_trans/expr.rs @@ -175,7 +175,7 @@ pub fn trans_into<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, hir::ExprPath(..) => { match bcx.tcx().expect_def(expr.id) { Def::Const(did) | Def::AssociatedConst(did) => { - let empty_substs = bcx.tcx().mk_substs(Substs::empty()); + let empty_substs = Substs::empty(bcx.tcx()); let const_expr = consts::get_const_expr(bcx.ccx(), did, expr, empty_substs); // Temporarily get cleanup scopes out of the way, diff --git a/src/librustc_trans/glue.rs b/src/librustc_trans/glue.rs index 93e5f4ba1e205..080844782f205 100644 --- a/src/librustc_trans/glue.rs +++ b/src/librustc_trans/glue.rs @@ -50,7 +50,7 @@ pub fn trans_exchange_free_dyn<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, let def_id = langcall(bcx.tcx(), None, "", ExchangeFreeFnLangItem); let args = [PointerCast(bcx, v, Type::i8p(bcx.ccx())), size, align]; - Callee::def(bcx.ccx(), def_id, bcx.tcx().mk_substs(Substs::empty())) + Callee::def(bcx.ccx(), def_id, Substs::empty(bcx.tcx())) .call(bcx, debug_loc, ArgVals(&args), None).bcx } @@ -356,7 +356,7 @@ fn trans_struct_drop<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, let trait_ref = ty::Binder(ty::TraitRef { def_id: tcx.lang_items.drop_trait().unwrap(), - substs: tcx.mk_substs(Substs::empty().with_self_ty(t)) + substs: Substs::new_trait(tcx, vec![], vec![], t) }); let vtbl = match fulfill_obligation(bcx.ccx().shared(), DUMMY_SP, trait_ref) { traits::VtableImpl(data) => data, diff --git a/src/librustc_trans/intrinsic.rs b/src/librustc_trans/intrinsic.rs index 7be173d17b487..133a98a2470f0 100644 --- a/src/librustc_trans/intrinsic.rs +++ b/src/librustc_trans/intrinsic.rs @@ -15,8 +15,7 @@ use intrinsics::{self, Intrinsic}; use libc; use llvm; use llvm::{ValueRef, TypeKind}; -use rustc::ty::subst; -use rustc::ty::subst::FnSpace; +use rustc::ty::subst::{FnSpace, Substs}; use abi::{Abi, FnType}; use adt; use base::*; @@ -1284,7 +1283,7 @@ fn span_invalid_monomorphization_error(a: &Session, b: Span, c: &str) { fn generic_simd_intrinsic<'blk, 'tcx, 'a> (bcx: Block<'blk, 'tcx>, name: &str, - substs: &'tcx subst::Substs<'tcx>, + substs: &'tcx Substs<'tcx>, callee_ty: Ty<'tcx>, args: Option<&[P]>, llargs: &[ValueRef], diff --git a/src/librustc_trans/meth.rs b/src/librustc_trans/meth.rs index 169242fbf7270..b051028ebda6b 100644 --- a/src/librustc_trans/meth.rs +++ b/src/librustc_trans/meth.rs @@ -15,8 +15,7 @@ use arena::TypedArena; use back::symbol_names; use llvm::{ValueRef, get_params}; use rustc::hir::def_id::DefId; -use rustc::ty::subst::{FnSpace, Subst, Substs}; -use rustc::ty::subst; +use rustc::ty::subst::{Subst, Substs}; use rustc::traits::{self, Reveal}; use abi::FnType; use base::*; @@ -221,20 +220,20 @@ pub fn get_vtable<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, pub fn get_vtable_methods<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, impl_id: DefId, - substs: &'tcx subst::Substs<'tcx>) + substs: &'tcx Substs<'tcx>) -> Vec>> { debug!("get_vtable_methods(impl_id={:?}, substs={:?}", impl_id, substs); - let trt_id = match tcx.impl_trait_ref(impl_id) { + let trait_id = match tcx.impl_trait_ref(impl_id) { Some(t_id) => t_id.def_id, None => bug!("make_impl_vtable: don't know how to \ make a vtable for a type impl!") }; - tcx.populate_implementations_for_trait_if_necessary(trt_id); + tcx.populate_implementations_for_trait_if_necessary(trait_id); - let trait_item_def_ids = tcx.trait_item_def_ids(trt_id); + let trait_item_def_ids = tcx.trait_item_def_ids(trait_id); trait_item_def_ids .iter() @@ -260,7 +259,7 @@ pub fn get_vtable_methods<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, let name = trait_method_type.name; // Some methods cannot be called on an object; skip those. - if !tcx.is_vtable_safe_method(trt_id, &trait_method_type) { + if !tcx.is_vtable_safe_method(trait_id, &trait_method_type) { debug!("get_vtable_methods: not vtable safe"); return None; } @@ -270,15 +269,13 @@ pub fn get_vtable_methods<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, // the method may have some early-bound lifetimes, add // regions for those - let num_dummy_regions = trait_method_type.generics.regions.len(FnSpace); - let dummy_regions = vec![ty::ReErased; num_dummy_regions]; - let method_substs = substs.clone() - .with_method(vec![], dummy_regions); - let method_substs = tcx.mk_substs(method_substs); + let method_substs = Substs::for_item(tcx, trait_method_def_id, + |_, _| ty::ReErased, + |_, _| tcx.types.err); // The substitutions we have are on the impl, so we grab // the method type from the impl to substitute into. - let mth = get_impl_method(tcx, impl_id, method_substs, name); + let mth = get_impl_method(tcx, method_substs, impl_id, substs, name); debug!("get_vtable_methods: mth={:?}", mth); @@ -309,8 +306,9 @@ pub struct ImplMethod<'tcx> { /// Locates the applicable definition of a method, given its name. pub fn get_impl_method<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, - impl_def_id: DefId, substs: &'tcx Substs<'tcx>, + impl_def_id: DefId, + impl_substs: &'tcx Substs<'tcx>, name: Name) -> ImplMethod<'tcx> { @@ -322,6 +320,7 @@ pub fn get_impl_method<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, match trait_def.ancestors(impl_def_id).fn_defs(tcx, name).next() { Some(node_item) => { let substs = tcx.normalizing_infer_ctxt(Reveal::All).enter(|infcx| { + let substs = substs.rebase_onto(tcx, trait_def_id, impl_substs); let substs = traits::translate_substs(&infcx, impl_def_id, substs, node_item.node); tcx.lift(&substs).unwrap_or_else(|| { diff --git a/src/librustc_trans/mir/constant.rs b/src/librustc_trans/mir/constant.rs index 31fee560fe369..4da973bb7f946 100644 --- a/src/librustc_trans/mir/constant.rs +++ b/src/librustc_trans/mir/constant.rs @@ -232,12 +232,9 @@ impl<'a, 'tcx> MirConstContext<'a, 'tcx> { args: IndexVec>) -> Result, ConstEvalFailure> { // Try to resolve associated constants. - if instance.substs.self_ty().is_some() { - // Only trait items can have a Self parameter. - let trait_item = ccx.tcx().impl_or_trait_item(instance.def); - let trait_id = trait_item.container().id(); - let substs = instance.substs; - let trait_ref = ty::Binder(substs.to_trait_ref(ccx.tcx(), trait_id)); + if let Some(trait_id) = ccx.tcx().trait_of_item(instance.def) { + let trait_ref = ty::TraitRef::new(trait_id, instance.substs); + let trait_ref = ty::Binder(trait_ref); let vtable = common::fulfill_obligation(ccx.shared(), DUMMY_SP, trait_ref); if let traits::VtableImpl(vtable_impl) = vtable { let name = ccx.tcx().item_name(instance.def); diff --git a/src/librustc_trans/monomorphize.rs b/src/librustc_trans/monomorphize.rs index 663c5167d1492..26278e886c29a 100644 --- a/src/librustc_trans/monomorphize.rs +++ b/src/librustc_trans/monomorphize.rs @@ -12,7 +12,6 @@ use llvm::ValueRef; use llvm; use rustc::hir::def_id::DefId; use rustc::infer::TransNormalize; -use rustc::ty::subst; use rustc::ty::subst::{Subst, Substs}; use rustc::ty::{self, Ty, TypeFoldable, TyCtxt}; use attributes; @@ -33,7 +32,7 @@ use trans_item::TransItem; pub fn monomorphic_fn<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, fn_id: DefId, - psubsts: &'tcx subst::Substs<'tcx>) + psubsts: &'tcx Substs<'tcx>) -> (ValueRef, Ty<'tcx>) { debug!("monomorphic_fn(fn_id={:?}, real_substs={:?})", fn_id, psubsts); assert!(!psubsts.types.needs_infer() && !psubsts.types.has_param_types()); @@ -174,7 +173,7 @@ pub struct Instance<'tcx> { impl<'tcx> fmt::Display for Instance<'tcx> { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - ppaux::parameterized(f, &self.substs, self.def, ppaux::Ns::Value, &[], |_| None) + ppaux::parameterized(f, &self.substs, self.def, ppaux::Ns::Value, &[]) } } diff --git a/src/librustc_trans/partitioning.rs b/src/librustc_trans/partitioning.rs index ade6e8abeb32a..f24ab0f65578c 100644 --- a/src/librustc_trans/partitioning.rs +++ b/src/librustc_trans/partitioning.rs @@ -125,6 +125,7 @@ use rustc::hir::map::DefPathData; use rustc::session::config::NUMBERED_CODEGEN_UNIT_MARKER; use rustc::ty::TyCtxt; use rustc::ty::item_path::characteristic_def_id_of_type; +use rustc::ty::subst; use std::cmp::Ordering; use std::hash::{Hash, Hasher, SipHasher}; use std::sync::Arc; @@ -486,7 +487,8 @@ fn characteristic_def_id_of_trans_item<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, // its self-type. If the self-type does not provide a characteristic // DefId, we use the location of the impl after all. - if let Some(self_ty) = instance.substs.self_ty() { + if tcx.trait_of_item(instance.def).is_some() { + let self_ty = *instance.substs.types.get(subst::SelfSpace, 0); // This is an implementation of a trait method. return characteristic_def_id_of_type(self_ty).or(Some(instance.def)); } diff --git a/src/librustc_trans/trans_item.rs b/src/librustc_trans/trans_item.rs index 2dd07cf440553..ebd4a80deb9ab 100644 --- a/src/librustc_trans/trans_item.rs +++ b/src/librustc_trans/trans_item.rs @@ -28,7 +28,7 @@ use rustc::hir; use rustc::hir::map as hir_map; use rustc::hir::def_id::DefId; use rustc::ty::{self, Ty, TyCtxt, TypeFoldable}; -use rustc::ty::subst; +use rustc::ty::subst::{Substs, VecPerParamSpace}; use rustc_const_eval::fatal_const_eval_err; use std::hash::{Hash, Hasher}; use syntax::ast::{self, NodeId}; @@ -352,8 +352,7 @@ impl<'a, 'tcx> TransItem<'tcx> { }, TransItem::Static(node_id) => { let def_id = hir_map.local_def_id(node_id); - let instance = Instance::new(def_id, - tcx.mk_substs(subst::Substs::empty())); + let instance = Instance::new(def_id, Substs::empty(tcx)); to_string_internal(tcx, "static ", instance) }, }; @@ -561,7 +560,7 @@ fn push_item_name(tcx: TyCtxt, } fn push_type_params<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, - types: &'tcx subst::VecPerParamSpace>, + types: &'tcx VecPerParamSpace>, projections: &[ty::PolyExistentialProjection<'tcx>], output: &mut String) { if types.is_empty() && projections.is_empty() { diff --git a/src/librustc_trans/type_of.rs b/src/librustc_trans/type_of.rs index e6794149fcb3b..7e592d1b74d7c 100644 --- a/src/librustc_trans/type_of.rs +++ b/src/librustc_trans/type_of.rs @@ -11,7 +11,6 @@ #![allow(non_camel_case_types)] use rustc::hir::def_id::DefId; -use rustc::ty::subst; use abi::FnType; use adt; use common::*; @@ -257,7 +256,7 @@ pub fn in_memory_type_of<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, t: Ty<'tcx>) -> // avoids creating more than one copy of the enum when one // of the enum's variants refers to the enum itself. let repr = adt::represent_type(cx, t); - let tps = substs.types.get_slice(subst::TypeSpace); + let tps = substs.types.as_full_slice(); let name = llvm_type_name(cx, def.did, tps); adt::incomplete_type_of(cx, &repr, &name[..]) } @@ -336,7 +335,7 @@ pub fn in_memory_type_of<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, t: Ty<'tcx>) -> // in *after* placing it into the type cache. This prevents // infinite recursion with recursive struct types. let repr = adt::represent_type(cx, t); - let tps = substs.types.get_slice(subst::TypeSpace); + let tps = substs.types.as_full_slice(); let name = llvm_type_name(cx, def.did, tps); adt::incomplete_type_of(cx, &repr, &name[..]) } diff --git a/src/librustc_typeck/astconv.rs b/src/librustc_typeck/astconv.rs index 11ca012fdedab..5655c7c8e7291 100644 --- a/src/librustc_typeck/astconv.rs +++ b/src/librustc_typeck/astconv.rs @@ -81,6 +81,10 @@ pub trait AstConv<'gcx, 'tcx> { /// A cache used for the result of `ast_ty_to_ty_cache` fn ast_ty_to_ty_cache(&self) -> &RefCell>>; + /// Returns the generic type and lifetime parameters for an item. + fn get_generics(&self, span: Span, id: DefId) + -> Result<&'tcx ty::Generics<'tcx>, ErrorReported>; + /// Identify the type scheme for an item with a type, like a type /// alias, fn, or struct. This allows you to figure out the set of /// type parameters defined on the item. @@ -348,7 +352,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o { rscope: &RegionScope, span: Span, param_mode: PathParamMode, - decl_generics: &ty::Generics<'tcx>, + def_id: DefId, item_segment: &hir::PathSegment) -> &'tcx Substs<'tcx> { @@ -362,11 +366,11 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o { .span_label(span, &format!("only traits may use parentheses")) .emit(); - return tcx.mk_substs(Substs::from_generics(decl_generics, |_, _| { + return Substs::for_item(tcx, def_id, |_, _| { ty::ReStatic }, |_, _| { tcx.types.err - })); + }); } } @@ -374,7 +378,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o { self.create_substs_for_ast_path(rscope, span, param_mode, - decl_generics, + def_id, &item_segment.parameters, None); @@ -392,16 +396,16 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o { rscope: &RegionScope, span: Span, param_mode: PathParamMode, - decl_generics: &ty::Generics<'tcx>, + def_id: DefId, parameters: &hir::PathParameters, self_ty: Option>) -> (&'tcx Substs<'tcx>, Vec>) { let tcx = self.tcx(); - debug!("create_substs_for_ast_path(decl_generics={:?}, self_ty={:?}, \ + debug!("create_substs_for_ast_path(def_id={:?}, self_ty={:?}, \ parameters={:?})", - decl_generics, self_ty, parameters); + def_id, self_ty, parameters); let (lifetimes, num_types_provided) = match *parameters { hir::AngleBracketedParameters(ref data) => { @@ -417,6 +421,14 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o { // If the type is parameterized by this region, then replace this // region with the current anon region binding (in other words, // whatever & would get replaced with). + let decl_generics = match self.get_generics(span, def_id) { + Ok(generics) => generics, + Err(ErrorReported) => { + // No convenient way to recover from a cycle here. Just bail. Sorry! + self.tcx().sess.abort_if_errors(); + bug!("ErrorReported returned, but no errors reports?") + } + }; let expected_num_region_params = decl_generics.regions.len(TypeSpace); let supplied_num_region_params = lifetimes.len(); let regions = if expected_num_region_params == supplied_num_region_params { @@ -438,7 +450,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o { }; // If a self-type was declared, one should be provided. - assert_eq!(decl_generics.types.get_self().is_some(), self_ty.is_some()); + assert_eq!(decl_generics.has_self, self_ty.is_some()); // Check the number of type parameters supplied by the user. if let Some(num_provided) = num_types_provided { @@ -460,7 +472,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o { }; let mut output_assoc_binding = None; - let substs = Substs::from_generics(decl_generics, |def, _| { + let substs = Substs::for_item(tcx, def_id, |def, _| { assert_eq!(def.space, TypeSpace); regions[def.index as usize] }, |def, substs| { @@ -532,7 +544,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o { vec![output_assoc_binding.unwrap_or_else(|| { // This is an error condition, but we should // get the associated type binding anyway. - self.convert_parenthesized_parameters(rscope, &substs, data).1 + self.convert_parenthesized_parameters(rscope, substs, data).1 })] } }; @@ -540,7 +552,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o { debug!("create_substs_for_ast_path(decl_generics={:?}, self_ty={:?}) -> {:?}", decl_generics, self_ty, substs); - (tcx.mk_substs(substs), assoc_bindings) + (substs, assoc_bindings) } /// Returns the appropriate lifetime to use for any output lifetimes @@ -803,7 +815,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o { self.create_substs_for_ast_path(rscope, span, param_mode, - &trait_def.generics, + trait_def_id, &trait_segment.parameters, Some(self_ty)) } @@ -910,10 +922,8 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o { -> Ty<'tcx> { let tcx = self.tcx(); - let (generics, decl_ty) = match self.get_item_type_scheme(span, did) { - Ok(ty::TypeScheme { generics, ty: decl_ty }) => { - (generics, decl_ty) - } + let decl_ty = match self.get_item_type_scheme(span, did) { + Ok(type_scheme) => type_scheme.ty, Err(ErrorReported) => { return tcx.types.err; } @@ -922,7 +932,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o { let substs = self.ast_path_substs_for_ty(rscope, span, param_mode, - &generics, + did, item_segment); // FIXME(#12938): This is a hack until we have full support for DST. @@ -1682,7 +1692,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o { // Create the anonymized type. let def_id = tcx.map.local_def_id(ast_ty.id); if let Some(anon_scope) = rscope.anon_type_scope() { - let substs = anon_scope.fresh_substs(tcx); + let substs = anon_scope.fresh_substs(self, ast_ty.span); let ty = tcx.mk_anon(tcx.map.local_def_id(ast_ty.id), substs); // Collect the bounds, i.e. the `A+B+'c` in `impl A+B+'c`. diff --git a/src/librustc_typeck/check/_match.rs b/src/librustc_typeck/check/_match.rs index 04f22b195110f..af24a7b51176c 100644 --- a/src/librustc_typeck/check/_match.rs +++ b/src/librustc_typeck/check/_match.rs @@ -547,10 +547,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { } // Type check the path. - let scheme = tcx.lookup_item_type(def.def_id()); - let predicates = tcx.lookup_predicates(def.def_id()); - let pat_ty = self.instantiate_value_path(segments, scheme, &predicates, - opt_ty, def, pat.span, pat.id); + let pat_ty = self.instantiate_value_path(segments, opt_ty, def, pat.span, pat.id); self.demand_suptype(pat.span, expected, pat_ty); } @@ -607,18 +604,16 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { } // Type check the path. - let scheme = tcx.lookup_item_type(def.def_id()); - let scheme = if scheme.ty.is_fn() { + let pat_ty = self.instantiate_value_path(segments, opt_ty, def, pat.span, pat.id); + + let pat_ty = if pat_ty.is_fn() { // Replace constructor type with constructed type for tuple struct patterns. - let fn_ret = tcx.no_late_bound_regions(&scheme.ty.fn_ret()).unwrap(); - ty::TypeScheme { ty: fn_ret, generics: scheme.generics } + tcx.no_late_bound_regions(&pat_ty.fn_ret()).unwrap() } else { // Leave the type as is for unit structs (backward compatibility). - scheme + pat_ty }; - let predicates = tcx.lookup_predicates(def.def_id()); - let pat_ty = self.instantiate_value_path(segments, scheme, &predicates, - opt_ty, def, pat.span, pat.id); + self.write_ty(pat.id, pat_ty); self.demand_eqtype(pat.span, expected, pat_ty); // Type check subpatterns. diff --git a/src/librustc_typeck/check/autoderef.rs b/src/librustc_typeck/check/autoderef.rs index 265422468fe2a..9a3cbabe55331 100644 --- a/src/librustc_typeck/check/autoderef.rs +++ b/src/librustc_typeck/check/autoderef.rs @@ -101,7 +101,7 @@ impl<'a, 'gcx, 'tcx> Autoderef<'a, 'gcx, 'tcx> { Some(f) => f, None => return None }, - substs: tcx.mk_substs(Substs::new_trait(vec![], vec![], self.cur_ty)) + substs: Substs::new_trait(tcx, vec![], vec![], self.cur_ty) }; let cause = traits::ObligationCause::misc(self.span, self.fcx.body_id); diff --git a/src/librustc_typeck/check/compare_method.rs b/src/librustc_typeck/check/compare_method.rs index d501a8a184cee..3cb528eba63e0 100644 --- a/src/librustc_typeck/check/compare_method.rs +++ b/src/librustc_typeck/check/compare_method.rs @@ -194,10 +194,8 @@ pub fn compare_impl_method<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, // Create mapping from trait to skolemized. let trait_to_skol_substs = - trait_to_impl_substs - .subst(tcx, impl_to_skol_substs).clone() - .with_method(impl_to_skol_substs.types.get_slice(subst::FnSpace).to_vec(), - impl_to_skol_substs.regions.get_slice(subst::FnSpace).to_vec()); + impl_to_skol_substs.rebase_onto(tcx, impl_m.container_id(), + trait_to_impl_substs.subst(tcx, impl_to_skol_substs)); debug!("compare_impl_method: trait_to_skol_substs={:?}", trait_to_skol_substs); @@ -208,7 +206,7 @@ pub fn compare_impl_method<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, impl_m, &trait_m.generics, &impl_m.generics, - &trait_to_skol_substs, + trait_to_skol_substs, impl_to_skol_substs) { return; } @@ -226,7 +224,7 @@ pub fn compare_impl_method<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, let mut fulfillment_cx = traits::FulfillmentContext::new(); // Normalize the associated types in the trait_bounds. - let trait_bounds = trait_m.predicates.instantiate(tcx, &trait_to_skol_substs); + let trait_bounds = trait_m.predicates.instantiate(tcx, trait_to_skol_substs); // Create obligations for each predicate declared by the impl // definition in the context of the trait's parameter @@ -323,7 +321,7 @@ pub fn compare_impl_method<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, infcx.parameter_environment.free_id_outlive, &trait_m.fty.sig); let trait_sig = - trait_sig.subst(tcx, &trait_to_skol_substs); + trait_sig.subst(tcx, trait_to_skol_substs); let trait_sig = assoc::normalize_associated_types_in(&infcx, &mut fulfillment_cx, @@ -454,16 +452,14 @@ pub fn compare_const_impl<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, // Create mapping from trait to skolemized. let trait_to_skol_substs = - trait_to_impl_substs - .subst(tcx, impl_to_skol_substs).clone() - .with_method(impl_to_skol_substs.types.get_slice(subst::FnSpace).to_vec(), - impl_to_skol_substs.regions.get_slice(subst::FnSpace).to_vec()); + impl_to_skol_substs.rebase_onto(tcx, impl_c.container.id(), + trait_to_impl_substs.subst(tcx, impl_to_skol_substs)); debug!("compare_const_impl: trait_to_skol_substs={:?}", trait_to_skol_substs); // Compute skolemized form of impl and trait const tys. let impl_ty = impl_c.ty.subst(tcx, impl_to_skol_substs); - let trait_ty = trait_c.ty.subst(tcx, &trait_to_skol_substs); + let trait_ty = trait_c.ty.subst(tcx, trait_to_skol_substs); let mut origin = TypeOrigin::Misc(impl_c_span); let err = infcx.commit_if_ok(|_| { diff --git a/src/librustc_typeck/check/dropck.rs b/src/librustc_typeck/check/dropck.rs index 1e2446788adc9..7d79fc4fbf878 100644 --- a/src/librustc_typeck/check/dropck.rs +++ b/src/librustc_typeck/check/dropck.rs @@ -15,7 +15,7 @@ use hir::def_id::DefId; use middle::free_region::FreeRegionMap; use rustc::infer; use middle::region; -use rustc::ty::subst::{self, Subst}; +use rustc::ty::subst::{self, Subst, Substs}; use rustc::ty::{self, Ty, TyCtxt}; use rustc::traits::{self, Reveal}; use util::nodemap::FnvHashSet; @@ -41,16 +41,14 @@ use syntax_pos::{self, Span}; /// cannot do `struct S; impl Drop for S { ... }`). /// pub fn check_drop_impl(ccx: &CrateCtxt, drop_impl_did: DefId) -> Result<(), ()> { - let ty::TypeScheme { generics: ref dtor_generics, - ty: dtor_self_type } = ccx.tcx.lookup_item_type(drop_impl_did); + let dtor_self_type = ccx.tcx.lookup_item_type(drop_impl_did).ty; let dtor_predicates = ccx.tcx.lookup_predicates(drop_impl_did); match dtor_self_type.sty { ty::TyEnum(adt_def, self_to_impl_substs) | ty::TyStruct(adt_def, self_to_impl_substs) => { ensure_drop_params_and_item_params_correspond(ccx, drop_impl_did, - dtor_generics, - &dtor_self_type, + dtor_self_type, adt_def.did)?; ensure_drop_predicates_are_implied_by_item_defn(ccx, @@ -73,8 +71,7 @@ pub fn check_drop_impl(ccx: &CrateCtxt, drop_impl_did: DefId) -> Result<(), ()> fn ensure_drop_params_and_item_params_correspond<'a, 'tcx>( ccx: &CrateCtxt<'a, 'tcx>, drop_impl_did: DefId, - drop_impl_generics: &ty::Generics<'tcx>, - drop_impl_ty: &ty::Ty<'tcx>, + drop_impl_ty: Ty<'tcx>, self_type_did: DefId) -> Result<(), ()> { let tcx = ccx.tcx; @@ -93,8 +90,8 @@ fn ensure_drop_params_and_item_params_correspond<'a, 'tcx>( let drop_impl_span = tcx.map.def_id_span(drop_impl_did, syntax_pos::DUMMY_SP); let fresh_impl_substs = - infcx.fresh_substs_for_generics(drop_impl_span, drop_impl_generics); - let fresh_impl_self_ty = drop_impl_ty.subst(tcx, &fresh_impl_substs); + infcx.fresh_substs_for_item(drop_impl_span, drop_impl_did); + let fresh_impl_self_ty = drop_impl_ty.subst(tcx, fresh_impl_substs); if let Err(_) = infcx.eq_types(true, infer::TypeOrigin::Misc(drop_impl_span), named_type, fresh_impl_self_ty) { @@ -131,7 +128,7 @@ fn ensure_drop_predicates_are_implied_by_item_defn<'a, 'tcx>( drop_impl_did: DefId, dtor_predicates: &ty::GenericPredicates<'tcx>, self_type_did: DefId, - self_to_impl_substs: &subst::Substs<'tcx>) -> Result<(), ()> { + self_to_impl_substs: &Substs<'tcx>) -> Result<(), ()> { // Here is an example, analogous to that from // `compare_impl_method`. diff --git a/src/librustc_typeck/check/intrinsic.rs b/src/librustc_typeck/check/intrinsic.rs index 4334f043772e3..bfedb4fa6e1a0 100644 --- a/src/librustc_typeck/check/intrinsic.rs +++ b/src/librustc_typeck/check/intrinsic.rs @@ -36,11 +36,11 @@ fn equate_intrinsic_type<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, let def_id = tcx.map.local_def_id(it.id); let i_ty = tcx.lookup_item_type(def_id); - let mut substs = Substs::empty(); - substs.types = i_ty.generics.types.map(|def| tcx.mk_param_from_def(def)); + let substs = Substs::for_item(tcx, def_id, + |_, _| ty::ReErased, + |def, _| tcx.mk_param_from_def(def)); - let fty = tcx.mk_fn_def(def_id, tcx.mk_substs(substs), - tcx.mk_bare_fn(ty::BareFnTy { + let fty = tcx.mk_fn_def(def_id, substs, tcx.mk_bare_fn(ty::BareFnTy { unsafety: hir::Unsafety::Unsafe, abi: abi, sig: ty::Binder(FnSig { diff --git a/src/librustc_typeck/check/method/confirm.rs b/src/librustc_typeck/check/method/confirm.rs index 250bf9265d1a4..c071fce98965f 100644 --- a/src/librustc_typeck/check/method/confirm.rs +++ b/src/librustc_typeck/check/method/confirm.rs @@ -12,7 +12,7 @@ use super::probe; use check::{FnCtxt, callee}; use hir::def_id::DefId; -use rustc::ty::subst::{self}; +use rustc::ty::subst::{self, Substs}; use rustc::traits; use rustc::ty::{self, LvaluePreference, NoPreference, PreferMutLvalue, Ty}; use rustc::ty::adjustment::{AdjustDerefRef, AutoDerefRef, AutoPtr}; @@ -42,10 +42,6 @@ struct InstantiatedMethodSig<'tcx> { /// argument is the receiver. method_sig: ty::FnSig<'tcx>, - /// Substitutions for all types/early-bound-regions declared on - /// the method. - all_substs: subst::Substs<'tcx>, - /// Generic bounds on the method's parameters which must be added /// as pending obligations. method_predicates: ty::InstantiatedPredicates<'tcx>, @@ -105,9 +101,8 @@ impl<'a, 'gcx, 'tcx> ConfirmContext<'a, 'gcx, 'tcx> { // Create the final signature for the method, replacing late-bound regions. let InstantiatedMethodSig { - method_sig, all_substs, method_predicates + method_sig, method_predicates } = self.instantiate_method_sig(&pick, all_substs); - let all_substs = self.tcx.mk_substs(all_substs); let method_self_ty = method_sig.inputs[0]; // Unify the (adjusted) self type with what the method expects. @@ -198,7 +193,7 @@ impl<'a, 'gcx, 'tcx> ConfirmContext<'a, 'gcx, 'tcx> { fn fresh_receiver_substs(&mut self, self_ty: Ty<'tcx>, pick: &probe::Pick<'tcx>) - -> &'tcx subst::Substs<'tcx> + -> &'tcx Substs<'tcx> { match pick.kind { probe::InherentImplPick => { @@ -256,16 +251,13 @@ impl<'a, 'gcx, 'tcx> ConfirmContext<'a, 'gcx, 'tcx> { probe::TraitPick => { let trait_def_id = pick.item.container().id(); - let trait_def = self.tcx.lookup_trait_def(trait_def_id); // Make a trait reference `$0 : Trait<$1...$n>` // consisting entirely of type variables. Later on in // the process we will unify the transformed-self-type // of the method with the actual type in order to // unify some of these variables. - self.fresh_substs_for_trait(self.span, - &trait_def.generics, - self.next_ty_var()) + self.fresh_substs_for_item(self.span, trait_def_id) } probe::WhereClausePick(ref poly_trait_ref) => { @@ -308,8 +300,8 @@ impl<'a, 'gcx, 'tcx> ConfirmContext<'a, 'gcx, 'tcx> { fn instantiate_method_substs(&mut self, pick: &probe::Pick<'tcx>, mut supplied_method_types: Vec>, - substs: &subst::Substs<'tcx>) - -> subst::Substs<'tcx> + substs: &Substs<'tcx>) + -> &'tcx Substs<'tcx> { // Determine the values for the generic parameters of the method. // If they were not explicitly supplied, just construct fresh @@ -335,7 +327,7 @@ impl<'a, 'gcx, 'tcx> ConfirmContext<'a, 'gcx, 'tcx> { // parameters from the type and those from the method. // // FIXME -- permit users to manually specify lifetimes - subst::Substs::from_generics(&method.generics, |def, _| { + Substs::for_item(self.tcx, method.def_id, |def, _| { if def.space != subst::FnSpace { substs.region_for_def(def) } else { @@ -376,7 +368,7 @@ impl<'a, 'gcx, 'tcx> ConfirmContext<'a, 'gcx, 'tcx> { fn instantiate_method_sig(&mut self, pick: &probe::Pick<'tcx>, - all_substs: subst::Substs<'tcx>) + all_substs: &'tcx Substs<'tcx>) -> InstantiatedMethodSig<'tcx> { debug!("instantiate_method_sig(pick={:?}, all_substs={:?})", @@ -387,7 +379,7 @@ impl<'a, 'gcx, 'tcx> ConfirmContext<'a, 'gcx, 'tcx> { // type/early-bound-regions substitutions performed. There can // be no late-bound regions appearing here. let method_predicates = pick.item.as_opt_method().unwrap() - .predicates.instantiate(self.tcx, &all_substs); + .predicates.instantiate(self.tcx, all_substs); let method_predicates = self.normalize_associated_types_in(self.span, &method_predicates); @@ -405,20 +397,19 @@ impl<'a, 'gcx, 'tcx> ConfirmContext<'a, 'gcx, 'tcx> { debug!("late-bound lifetimes from method instantiated, method_sig={:?}", method_sig); - let method_sig = self.instantiate_type_scheme(self.span, &all_substs, &method_sig); + let method_sig = self.instantiate_type_scheme(self.span, all_substs, &method_sig); debug!("type scheme substituted, method_sig={:?}", method_sig); InstantiatedMethodSig { method_sig: method_sig, - all_substs: all_substs, method_predicates: method_predicates, } } fn add_obligations(&mut self, fty: Ty<'tcx>, - all_substs: &subst::Substs<'tcx>, + all_substs: &Substs<'tcx>, method_predicates: &ty::InstantiatedPredicates<'tcx>) { debug!("add_obligations: fty={:?} all_substs={:?} method_predicates={:?}", fty, diff --git a/src/librustc_typeck/check/method/mod.rs b/src/librustc_typeck/check/method/mod.rs index ff34f37bde0dd..e5107af6ca04b 100644 --- a/src/librustc_typeck/check/method/mod.rs +++ b/src/librustc_typeck/check/method/mod.rs @@ -13,7 +13,7 @@ use check::FnCtxt; use hir::def::Def; use hir::def_id::DefId; -use rustc::ty::subst; +use rustc::ty::subst::{self, Substs}; use rustc::traits; use rustc::ty::{self, ToPredicate, ToPolyTraitRef, TraitRef, TypeFoldable}; use rustc::ty::adjustment::{AdjustDerefRef, AutoDerefRef, AutoPtr}; @@ -189,7 +189,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { assert!(trait_def.generics.regions.is_empty()); // Construct a trait-reference `self_ty : Trait` - let substs = subst::Substs::from_generics(&trait_def.generics, |def, _| { + let substs = Substs::for_item(self.tcx, trait_def_id, |def, _| { self.region_var_for_def(span, def) }, |def, substs| { if def.space == subst::SelfSpace { @@ -201,7 +201,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { } }); - let trait_ref = ty::TraitRef::new(trait_def_id, self.tcx.mk_substs(substs)); + let trait_ref = ty::TraitRef::new(trait_def_id, substs); // Construct an obligation let poly_trait_ref = trait_ref.to_poly_trait_ref(); diff --git a/src/librustc_typeck/check/method/probe.rs b/src/librustc_typeck/check/method/probe.rs index f6ac3235cf33e..448ea243655a8 100644 --- a/src/librustc_typeck/check/method/probe.rs +++ b/src/librustc_typeck/check/method/probe.rs @@ -16,8 +16,7 @@ use super::suggest; use check::{FnCtxt}; use hir::def_id::DefId; use hir::def::Def; -use rustc::ty::subst; -use rustc::ty::subst::Subst; +use rustc::ty::subst::{self, Subst, Substs}; use rustc::traits; use rustc::ty::{self, Ty, ToPolyTraitRef, TraitRef, TypeFoldable}; use rustc::infer::{InferOk, TypeOrigin}; @@ -80,9 +79,9 @@ struct Candidate<'tcx> { #[derive(Debug)] enum CandidateKind<'tcx> { - InherentImplCandidate(subst::Substs<'tcx>, + InherentImplCandidate(&'tcx Substs<'tcx>, /* Normalize obligations */ Vec>), - ExtensionImplCandidate(/* Impl */ DefId, subst::Substs<'tcx>, + ExtensionImplCandidate(/* Impl */ DefId, &'tcx Substs<'tcx>, /* Normalize obligations */ Vec>), ObjectCandidate, TraitCandidate, @@ -421,10 +420,10 @@ impl<'a, 'gcx, 'tcx> ProbeContext<'a, 'gcx, 'tcx> { } let (impl_ty, impl_substs) = self.impl_ty_and_substs(impl_def_id); - let impl_ty = impl_ty.subst(self.tcx, &impl_substs); + let impl_ty = impl_ty.subst(self.tcx, impl_substs); // Determine the receiver type that the method itself expects. - let xform_self_ty = self.xform_self_ty(&item, impl_ty, &impl_substs); + let xform_self_ty = self.xform_self_ty(&item, impl_ty, impl_substs); // We can't use normalize_associated_types_in as it will pollute the // fcx's fulfillment context after this probe is over. @@ -519,14 +518,14 @@ impl<'a, 'gcx, 'tcx> ProbeContext<'a, 'gcx, 'tcx> { trait_ref, trait_ref.substs, m); - assert_eq!(m.generics.types.get_slice(subst::TypeSpace).len(), - trait_ref.substs.types.get_slice(subst::TypeSpace).len()); - assert_eq!(m.generics.regions.get_slice(subst::TypeSpace).len(), - trait_ref.substs.regions.get_slice(subst::TypeSpace).len()); - assert_eq!(m.generics.types.get_slice(subst::SelfSpace).len(), - trait_ref.substs.types.get_slice(subst::SelfSpace).len()); - assert_eq!(m.generics.regions.get_slice(subst::SelfSpace).len(), - trait_ref.substs.regions.get_slice(subst::SelfSpace).len()); + assert_eq!(m.generics.types.len(subst::TypeSpace), + trait_ref.substs.types.len(subst::TypeSpace)); + assert_eq!(m.generics.regions.len(subst::TypeSpace), + trait_ref.substs.regions.len(subst::TypeSpace)); + assert_eq!(m.generics.types.len(subst::SelfSpace), + trait_ref.substs.types.len(subst::SelfSpace)); + assert_eq!(m.generics.regions.len(subst::SelfSpace), + trait_ref.substs.regions.len(subst::SelfSpace)); } // Because this trait derives from a where-clause, it @@ -665,7 +664,7 @@ impl<'a, 'gcx, 'tcx> ProbeContext<'a, 'gcx, 'tcx> { let impl_trait_ref = self.tcx.impl_trait_ref(impl_def_id) .unwrap() // we know this is a trait impl - .subst(self.tcx, &impl_substs); + .subst(self.tcx, impl_substs); debug!("impl_trait_ref={:?}", impl_trait_ref); @@ -753,14 +752,21 @@ impl<'a, 'gcx, 'tcx> ProbeContext<'a, 'gcx, 'tcx> { // for the purposes of our method lookup, we only take // receiver type into account, so we can just substitute // fresh types here to use during substitution and subtyping. - let trait_def = self.tcx.lookup_trait_def(trait_def_id); - let substs = self.fresh_substs_for_trait(self.span, - &trait_def.generics, - step.self_ty); + let substs = Substs::for_item(self.tcx, trait_def_id, |def, _| { + self.region_var_for_def(self.span, def) + }, |def, substs| { + if def.space == subst::SelfSpace { + assert_eq!(def.index, 0); + step.self_ty + } else { + assert_eq!(def.space, subst::TypeSpace); + self.type_var_for_def(self.span, def, substs) + } + }); let xform_self_ty = self.xform_self_ty(&item, step.self_ty, - &substs); + substs); self.inherent_candidates.push(Candidate { xform_self_ty: xform_self_ty, item: item.clone(), @@ -1192,7 +1198,7 @@ impl<'a, 'gcx, 'tcx> ProbeContext<'a, 'gcx, 'tcx> { fn xform_self_ty(&self, item: &ty::ImplOrTraitItem<'tcx>, impl_ty: Ty<'tcx>, - substs: &subst::Substs<'tcx>) + substs: &Substs<'tcx>) -> Ty<'tcx> { match item.as_opt_method() { @@ -1205,7 +1211,7 @@ impl<'a, 'gcx, 'tcx> ProbeContext<'a, 'gcx, 'tcx> { fn xform_method_self_ty(&self, method: &Rc>, impl_ty: Ty<'tcx>, - substs: &subst::Substs<'tcx>) + substs: &Substs<'tcx>) -> Ty<'tcx> { debug!("xform_self_ty(impl_ty={:?}, self_ty={:?}, substs={:?})", @@ -1236,7 +1242,7 @@ impl<'a, 'gcx, 'tcx> ProbeContext<'a, 'gcx, 'tcx> { method.generics.regions.is_empty_in(subst::FnSpace) { xform_self_ty.subst(self.tcx, substs) } else { - let substs = subst::Substs::from_generics(&method.generics, |def, _| { + let substs = Substs::for_item(self.tcx, method.def_id, |def, _| { if def.space != subst::FnSpace { substs.region_for_def(def) } else { @@ -1251,14 +1257,14 @@ impl<'a, 'gcx, 'tcx> ProbeContext<'a, 'gcx, 'tcx> { self.type_var_for_def(self.span, def, cur_substs) } }); - xform_self_ty.subst(self.tcx, &substs) + xform_self_ty.subst(self.tcx, substs) } } /// Get the type of an impl and generate substitutions with placeholders. fn impl_ty_and_substs(&self, impl_def_id: DefId) - -> (Ty<'tcx>, subst::Substs<'tcx>) + -> (Ty<'tcx>, &'tcx Substs<'tcx>) { let impl_pty = self.tcx.lookup_item_type(impl_def_id); @@ -1270,8 +1276,7 @@ impl<'a, 'gcx, 'tcx> ProbeContext<'a, 'gcx, 'tcx> { impl_pty.generics.regions.map( |_| ty::ReErased); // see erase_late_bound_regions() for an expl of why 'erased - let substs = subst::Substs::new(type_vars, region_placeholders); - (impl_pty.ty, substs) + (impl_pty.ty, Substs::new(self.tcx, type_vars, region_placeholders)) } /// Replace late-bound-regions bound by `value` with `'static` using diff --git a/src/librustc_typeck/check/method/suggest.rs b/src/librustc_typeck/check/method/suggest.rs index dc6fa334b74fc..573dae46456ba 100644 --- a/src/librustc_typeck/check/method/suggest.rs +++ b/src/librustc_typeck/check/method/suggest.rs @@ -54,10 +54,8 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { self.autoderef(span, ty).any(|(ty, _)| self.probe(|_| { let fn_once_substs = - Substs::new_trait(vec![self.next_ty_var()], vec![], ty); - let trait_ref = - ty::TraitRef::new(fn_once, - tcx.mk_substs(fn_once_substs)); + Substs::new_trait(tcx, vec![self.next_ty_var()], vec![], ty); + let trait_ref = ty::TraitRef::new(fn_once, fn_once_substs); let poly_trait_ref = trait_ref.to_poly_trait_ref(); let obligation = Obligation::misc(span, self.body_id, diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index c41bb1930d458..700fb2ecf42dd 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -90,7 +90,6 @@ use hir::pat_util; use rustc::infer::{self, InferCtxt, InferOk, TypeOrigin, TypeTrace, type_variable}; use rustc::ty::subst::{self, Subst, Substs}; use rustc::traits::{self, Reveal}; -use rustc::ty::{GenericPredicates, TypeScheme}; use rustc::ty::{ParamTy, ParameterEnvironment}; use rustc::ty::{LvaluePreference, NoPreference, PreferMutLvalue}; use rustc::ty::{self, ToPolyTraitRef, Ty, TyCtxt, Visibility}; @@ -745,26 +744,20 @@ pub fn check_item_type<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>, it: &'tcx hir::Item) { let impl_def_id = ccx.tcx.map.local_def_id(it.id); match ccx.tcx.impl_trait_ref(impl_def_id) { Some(impl_trait_ref) => { - let trait_def_id = impl_trait_ref.def_id; - check_impl_items_against_trait(ccx, it.span, impl_def_id, &impl_trait_ref, impl_items); - check_on_unimplemented( - ccx, - &ccx.tcx.lookup_trait_def(trait_def_id).generics, - it, - ccx.tcx.item_name(trait_def_id)); + let trait_def_id = impl_trait_ref.def_id; + check_on_unimplemented(ccx, trait_def_id, it); } None => { } } } hir::ItemTrait(..) => { let def_id = ccx.tcx.map.local_def_id(it.id); - let generics = &ccx.tcx.lookup_trait_def(def_id).generics; - check_on_unimplemented(ccx, generics, it, it.name); + check_on_unimplemented(ccx, def_id, it); } hir::ItemStruct(..) => { check_struct(ccx, it.id, it.span); @@ -872,9 +865,9 @@ fn check_trait_fn_not_const<'a,'tcx>(ccx: &CrateCtxt<'a, 'tcx>, } fn check_on_unimplemented<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, - generics: &ty::Generics, - item: &hir::Item, - name: ast::Name) { + def_id: DefId, + item: &hir::Item) { + let generics = ccx.tcx.lookup_generics(def_id); if let Some(ref attr) = item.attrs.iter().find(|a| { a.check_name("rustc_on_unimplemented") }) { @@ -894,6 +887,7 @@ fn check_on_unimplemented<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, }) { Some(_) => (), None => { + let name = ccx.tcx.item_name(def_id); span_err!(ccx.tcx.sess, attr.span, E0230, "there is no type parameter \ {} on trait {}", @@ -1301,6 +1295,12 @@ impl<'a, 'gcx, 'tcx> AstConv<'gcx, 'tcx> for FnCtxt<'a, 'gcx, 'tcx> { &self.ast_ty_to_ty_cache } + fn get_generics(&self, _: Span, id: DefId) + -> Result<&'tcx ty::Generics<'tcx>, ErrorReported> + { + Ok(self.tcx().lookup_generics(id)) + } + fn get_item_type_scheme(&self, _: Span, id: DefId) -> Result, ErrorReported> { @@ -1364,7 +1364,7 @@ impl<'a, 'gcx, 'tcx> AstConv<'gcx, 'tcx> for FnCtxt<'a, 'gcx, 'tcx> { fn ty_infer_for_def(&self, ty_param_def: &ty::TypeParameterDef<'tcx>, - substs: &subst::Substs<'tcx>, + substs: &Substs<'tcx>, span: Span) -> Ty<'tcx> { self.type_var_for_def(span, ty_param_def, substs) } @@ -1690,25 +1690,24 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { node_id: ast::NodeId) -> Ty<'tcx> { debug!("instantiate_type_path(did={:?}, path={:?})", did, path); - let mut type_scheme = self.tcx.lookup_item_type(did); - if type_scheme.ty.is_fn() { + let mut ty = self.tcx.lookup_item_type(did).ty; + if ty.is_fn() { // Tuple variants have fn type even in type namespace, extract true variant type from it - let fn_ret = self.tcx.no_late_bound_regions(&type_scheme.ty.fn_ret()).unwrap(); - type_scheme = ty::TypeScheme { ty: fn_ret, generics: type_scheme.generics } + ty = self.tcx.no_late_bound_regions(&type_scheme.ty.fn_ret()).unwrap(); } let type_predicates = self.tcx.lookup_predicates(did); let substs = AstConv::ast_path_substs_for_ty(self, self, path.span, PathParamMode::Optional, - &type_scheme.generics, + did, path.segments.last().unwrap()); - debug!("instantiate_type_path: ty={:?} substs={:?}", &type_scheme.ty, substs); + debug!("instantiate_type_path: ty={:?} substs={:?}", ty, substs); let bounds = self.instantiate_bounds(path.span, substs, &type_predicates); let cause = traits::ObligationCause::new(path.span, self.body_id, traits::ItemObligation(did)); self.add_obligations_for_parameters(cause, &bounds); - let ty_substituted = self.instantiate_type_scheme(path.span, substs, &type_scheme.ty); + let ty_substituted = self.instantiate_type_scheme(path.span, substs, &ty); self.write_ty(node_id, ty_substituted); self.write_substs(node_id, ty::ItemSubsts { substs: substs @@ -2775,7 +2774,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { let ity = self.tcx.lookup_item_type(did); debug!("impl_self_ty: ity={:?}", ity); - let substs = self.fresh_substs_for_generics(span, &ity.generics); + let substs = self.fresh_substs_for_item(span, did); let substd_ty = self.instantiate_type_scheme(span, &substs, &ity.ty); TypeAndSubsts { substs: substs, ty: substd_ty } @@ -3443,10 +3442,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { let (def, opt_ty, segments) = self.resolve_ty_and_def_ufcs(opt_self_ty, path, expr.id, expr.span); if def != Def::Err { - let (scheme, predicates) = self.type_scheme_and_predicates_for_def(expr.span, - def); - self.instantiate_value_path(segments, scheme, &predicates, - opt_ty, def, expr.span, id); + self.instantiate_value_path(segments, opt_ty, def, expr.span, id); } else { self.set_tainted_by_errors(); self.write_error(id); @@ -4036,54 +4032,19 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { *self.ps.borrow_mut() = prev; } - // Returns the type parameter count and the type for the given definition. - fn type_scheme_and_predicates_for_def(&self, - sp: Span, - defn: Def) - -> (TypeScheme<'tcx>, GenericPredicates<'tcx>) { - match defn { - Def::Local(_, nid) | Def::Upvar(_, nid, _, _) => { - let typ = self.local_ty(sp, nid); - (ty::TypeScheme { generics: ty::Generics::empty(), ty: typ }, - ty::GenericPredicates::empty()) - } - Def::Fn(id) | Def::Method(id) | - Def::Static(id, _) | Def::Variant(_, id) | - Def::Struct(id) | Def::Const(id) | Def::AssociatedConst(id) => { - (self.tcx.lookup_item_type(id), self.tcx.lookup_predicates(id)) - } - Def::Trait(_) | - Def::Enum(..) | - Def::TyAlias(..) | - Def::AssociatedTy(..) | - Def::PrimTy(_) | - Def::TyParam(..) | - Def::Mod(..) | - Def::ForeignMod(..) | - Def::Label(..) | - Def::SelfTy(..) | - Def::Err => { - span_bug!(sp, "expected value, found {:?}", defn); - } - } - } - // Instantiates the given path, which must refer to an item with the given // number of type parameters and type. pub fn instantiate_value_path(&self, segments: &[hir::PathSegment], - type_scheme: TypeScheme<'tcx>, - type_predicates: &ty::GenericPredicates<'tcx>, opt_self_ty: Option>, def: Def, span: Span, node_id: ast::NodeId) -> Ty<'tcx> { - debug!("instantiate_value_path(path={:?}, def={:?}, node_id={}, type_scheme={:?})", + debug!("instantiate_value_path(path={:?}, def={:?}, node_id={})", segments, def, - node_id, - type_scheme); + node_id); // We need to extract the type parameters supplied by the user in // the path `path`. Due to the current setup, this is a bit of a @@ -4210,11 +4171,8 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { Def::ForeignMod(..) | Def::Local(..) | Def::Label(..) | - Def::Upvar(..) => {} - - Def::Err => { - self.set_tainted_by_errors(); - } + Def::Upvar(..) | + Def::Err => {} } // In `>::method`, `A` and `B` are mandatory, but @@ -4232,6 +4190,21 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { fn_segment.is_some() as usize; self.tcx.prohibit_type_params(&segments[..segments.len() - poly_segments]); + match def { + Def::Local(_, nid) | Def::Upvar(_, nid, _, _) => { + let ty = self.local_ty(span, nid); + let ty = self.normalize_associated_types_in(span, &ty); + self.write_ty(node_id, ty); + self.write_substs(node_id, ty::ItemSubsts { + substs: Substs::empty(self.tcx) + }); + return ty; + } + _ => {} + } + let scheme = self.tcx.lookup_item_type(def.def_id()); + let type_predicates = self.tcx.lookup_predicates(def.def_id()); + // Now we have to compare the types that the user *actually* // provided against the types that were *expected*. If the user // did not provide any types, then we want to substitute inference @@ -4240,16 +4213,16 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { // a problem. self.check_path_parameter_count(subst::TypeSpace, span, - &type_scheme.generics, + scheme.generics, !require_type_space, &mut type_segment); self.check_path_parameter_count(subst::FnSpace, span, - &type_scheme.generics, + scheme.generics, true, &mut fn_segment); - let substs = Substs::from_generics(&type_scheme.generics, |def, _| { + let substs = Substs::for_item(self.tcx, def.def_id(), |def, _| { let i = def.index as usize; let segment = match def.space { subst::SelfSpace => None, @@ -4307,9 +4280,8 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { // The things we are substituting into the type should not contain // escaping late-bound regions, and nor should the base type scheme. - let substs = self.tcx.mk_substs(substs); assert!(!substs.has_escaping_regions()); - assert!(!type_scheme.has_escaping_regions()); + assert!(!scheme.ty.has_escaping_regions()); // Add all the obligations that are required, substituting and // normalized appropriately. @@ -4320,7 +4292,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { // Substitute the values for the type parameters into the type of // the referenced item. - let ty_substituted = self.instantiate_type_scheme(span, &substs, &type_scheme.ty); + let ty_substituted = self.instantiate_type_scheme(span, &substs, &scheme.ty); if let Some((ty::ImplContainer(impl_def_id), self_ty)) = ufcs_associated { diff --git a/src/librustc_typeck/check/writeback.rs b/src/librustc_typeck/check/writeback.rs index 5f8861f309948..6a475864f3b7d 100644 --- a/src/librustc_typeck/check/writeback.rs +++ b/src/librustc_typeck/check/writeback.rs @@ -18,7 +18,6 @@ use hir::def_id::DefId; use rustc::ty::{self, Ty, TyCtxt, MethodCall, MethodCallee}; use rustc::ty::adjustment; use rustc::ty::fold::{TypeFolder,TypeFoldable}; -use rustc::ty::subst::ParamSpace; use rustc::infer::{InferCtxt, FixupError}; use rustc::util::nodemap::DefIdMap; use write_substs_to_tcx; @@ -68,7 +67,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { wbcx.visit_closures(); wbcx.visit_liberated_fn_sigs(); wbcx.visit_fru_field_types(); - wbcx.visit_anon_types(); + wbcx.visit_anon_types(item_id); wbcx.visit_deferred_obligations(item_id); } } @@ -104,22 +103,20 @@ impl<'cx, 'gcx, 'tcx> WritebackCx<'cx, 'gcx, 'tcx> { } let free_substs = fcx.parameter_environment.free_substs; - for &space in &ParamSpace::all() { - for (i, r) in free_substs.regions.get_slice(space).iter().enumerate() { - match *r { - ty::ReFree(ty::FreeRegion { - bound_region: ty::BoundRegion::BrNamed(def_id, name, _), .. - }) => { - let bound_region = ty::ReEarlyBound(ty::EarlyBoundRegion { - space: space, - index: i as u32, - name: name, - }); - wbcx.free_to_bound_regions.insert(def_id, bound_region); - } - _ => { - bug!("{:?} is not a free region for an early-bound lifetime", r); - } + for (space, i, r) in free_substs.regions.iter_enumerated() { + match *r { + ty::ReFree(ty::FreeRegion { + bound_region: ty::BoundRegion::BrNamed(def_id, name, _), .. + }) => { + let bound_region = ty::ReEarlyBound(ty::EarlyBoundRegion { + space: space, + index: i as u32, + name: name, + }); + wbcx.free_to_bound_regions.insert(def_id, bound_region); + } + _ => { + bug!("{:?} is not a free region for an early-bound lifetime", r); } } } @@ -300,11 +297,13 @@ impl<'cx, 'gcx, 'tcx> WritebackCx<'cx, 'gcx, 'tcx> { } } - fn visit_anon_types(&self) { + fn visit_anon_types(&self, item_id: ast::NodeId) { if self.fcx.writeback_errors.get() { return } + let item_def_id = self.fcx.tcx.map.local_def_id(item_id); + let gcx = self.tcx().global_tcx(); for (&def_id, &concrete_ty) in self.fcx.anon_types.borrow().iter() { let reason = ResolvingAnonTy(def_id); @@ -345,9 +344,9 @@ impl<'cx, 'gcx, 'tcx> WritebackCx<'cx, 'gcx, 'tcx> { } }); - gcx.tcache.borrow_mut().insert(def_id, ty::TypeScheme { + gcx.register_item_type(def_id, ty::TypeScheme { ty: outside_ty, - generics: ty::Generics::empty() + generics: gcx.lookup_generics(item_def_id) }); } } diff --git a/src/librustc_typeck/collect.rs b/src/librustc_typeck/collect.rs index a2a162a7f5f74..77723ea973341 100644 --- a/src/librustc_typeck/collect.rs +++ b/src/librustc_typeck/collect.rs @@ -65,7 +65,7 @@ use middle::lang_items::SizedTraitLangItem; use middle::const_val::ConstVal; use rustc_const_eval::EvalHint::UncheckedExprHint; use rustc_const_eval::{eval_const_expr_partial, report_const_eval_err}; -use rustc::ty::subst::{Substs, FnSpace, ParamSpace, SelfSpace, TypeSpace}; +use rustc::ty::subst::{Substs, FnSpace, ParamSpace, SelfSpace, TypeSpace, VecPerParamSpace}; use rustc::ty::{ToPredicate, ImplContainer, ImplOrTraitItemContainer, TraitContainer}; use rustc::ty::{self, ToPolyTraitRef, Ty, TyCtxt, TypeScheme}; use rustc::ty::{VariantKind}; @@ -120,6 +120,7 @@ struct ItemCtxt<'a,'tcx:'a> { #[derive(Copy, Clone, PartialEq, Eq)] pub enum AstConvRequest { + GetGenerics(DefId), GetItemTypeScheme(DefId), GetTraitDef(DefId), EnsureSuperPredicates(DefId), @@ -187,6 +188,7 @@ impl<'a,'tcx> CrateCtxt<'a,'tcx> { err.span_label(span, &format!("cyclic reference")); match cycle[0] { + AstConvRequest::GetGenerics(def_id) | AstConvRequest::GetItemTypeScheme(def_id) | AstConvRequest::GetTraitDef(def_id) => { err.note( @@ -209,6 +211,7 @@ impl<'a,'tcx> CrateCtxt<'a,'tcx> { for request in &cycle[1..] { match *request { + AstConvRequest::GetGenerics(def_id) | AstConvRequest::GetItemTypeScheme(def_id) | AstConvRequest::GetTraitDef(def_id) => { err.note( @@ -231,6 +234,7 @@ impl<'a,'tcx> CrateCtxt<'a,'tcx> { } match cycle[0] { + AstConvRequest::GetGenerics(def_id) | AstConvRequest::GetItemTypeScheme(def_id) | AstConvRequest::GetTraitDef(def_id) => { err.note( @@ -303,6 +307,14 @@ impl<'a, 'tcx> AstConv<'tcx, 'tcx> for ItemCtxt<'a, 'tcx> { &self.ccx.ast_ty_to_ty_cache } + fn get_generics(&self, span: Span, id: DefId) + -> Result<&'tcx ty::Generics<'tcx>, ErrorReported> + { + self.ccx.cycle_check(span, AstConvRequest::GetGenerics(id), || { + Ok(generics_of_def_id(self.ccx, id)) + }) + } + fn get_item_type_scheme(&self, span: Span, id: DefId) -> Result, ErrorReported> { @@ -544,7 +556,6 @@ fn is_param<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, } } - fn convert_method<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, container: ImplOrTraitItemContainer, name: ast::Name, @@ -553,25 +564,22 @@ fn convert_method<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, sig: &hir::MethodSig, defaultness: hir::Defaultness, untransformed_rcvr_ty: Ty<'tcx>, - rcvr_ty_generics: &ty::Generics<'tcx>, rcvr_ty_predicates: &ty::GenericPredicates<'tcx>) { - let ty_generics = ty_generics_for_fn(ccx, &sig.generics, rcvr_ty_generics); + let def_id = ccx.tcx.map.local_def_id(id); + let ty_generics = generics_of_def_id(ccx, def_id); let ty_generic_predicates = ty_generic_predicates_for_fn(ccx, &sig.generics, rcvr_ty_predicates); let (fty, explicit_self_category) = { let anon_scope = match container { - ImplContainer(_) => Some(AnonTypeScope::new(&ty_generics)), + ImplContainer(_) => Some(AnonTypeScope::new(def_id)), TraitContainer(_) => None }; AstConv::ty_of_method(&ccx.icx(&(rcvr_ty_predicates, &sig.generics)), sig, untransformed_rcvr_ty, anon_scope) }; - let def_id = ccx.tcx.map.local_def_id(id); - let substs = mk_item_substs(ccx.tcx, &ty_generics); - let ty_method = ty::Method::new(name, ty_generics, ty_generic_predicates, @@ -582,16 +590,14 @@ fn convert_method<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, def_id, container); + let substs = mk_item_substs(&ccx.icx(&(rcvr_ty_predicates, &sig.generics)), + ccx.tcx.map.span(id), def_id); let fty = ccx.tcx.mk_fn_def(def_id, substs, ty_method.fty); debug!("method {} (id {}) has type {:?}", name, id, fty); - ccx.tcx.register_item_type(def_id, TypeScheme { - generics: ty_method.generics.clone(), - ty: fty - }); - ccx.tcx.predicates.borrow_mut().insert(def_id, ty_method.predicates.clone()); - + ccx.tcx.tcache.borrow_mut().insert(def_id, fty); write_ty_to_tcx(ccx, id, fty); + ccx.tcx.predicates.borrow_mut().insert(def_id, ty_method.predicates.clone()); debug!("writing method type: def_id={:?} mty={:?}", def_id, ty_method); @@ -601,7 +607,7 @@ fn convert_method<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, } fn convert_field<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, - struct_generics: &ty::Generics<'tcx>, + struct_generics: &'tcx ty::Generics<'tcx>, struct_predicates: &ty::GenericPredicates<'tcx>, field: &hir::StructField, ty_f: ty::FieldDefMaster<'tcx>) @@ -613,7 +619,7 @@ fn convert_field<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, /* add the field to the tcache */ ccx.tcx.register_item_type(ccx.tcx.map.local_def_id(field.id), ty::TypeScheme { - generics: struct_generics.clone(), + generics: struct_generics, ty: tt }); ccx.tcx.predicates.borrow_mut().insert(ccx.tcx.map.local_def_id(field.id), @@ -709,8 +715,9 @@ fn convert_item(ccx: &CrateCtxt, it: &hir::Item) { } } hir::ItemEnum(ref enum_definition, _) => { - let (scheme, predicates) = convert_typed_item(ccx, it); - write_ty_to_tcx(ccx, it.id, scheme.ty); + let def_id = ccx.tcx.map.local_def_id(it.id); + let scheme = type_scheme_of_def_id(ccx, def_id); + let predicates = predicates_of_item(ccx, it); convert_enum_variant_types(ccx, tcx.lookup_adt_def_master(ccx.tcx.map.local_def_id(it.id)), scheme, @@ -737,7 +744,7 @@ fn convert_item(ccx: &CrateCtxt, it: &hir::Item) { // Create generics from the generics specified in the impl head. debug!("convert: ast_generics={:?}", generics); let def_id = ccx.tcx.map.local_def_id(it.id); - let ty_generics = ty_generics_for_impl(ccx, generics); + let ty_generics = generics_of_def_id(ccx, def_id); let mut ty_predicates = ty_generic_predicates_for_type_or_impl(ccx, generics); debug!("convert: impl_bounds={:?}", ty_predicates); @@ -746,7 +753,7 @@ fn convert_item(ccx: &CrateCtxt, it: &hir::Item) { write_ty_to_tcx(ccx, it.id, selfty); tcx.register_item_type(def_id, - TypeScheme { generics: ty_generics.clone(), + TypeScheme { generics: ty_generics, ty: selfty }); let trait_ref = opt_trait_ref.as_ref().map(|ast_trait_ref| { AstConv::instantiate_mono_trait_ref(&ccx.icx(&ty_predicates), @@ -791,7 +798,7 @@ fn convert_item(ccx: &CrateCtxt, it: &hir::Item) { .to_ty(&ExplicitRscope, &ty); tcx.register_item_type(ccx.tcx.map.local_def_id(impl_item.id), TypeScheme { - generics: ty_generics.clone(), + generics: ty_generics, ty: ty, }); // Trait-associated constants are always public. @@ -829,7 +836,7 @@ fn convert_item(ccx: &CrateCtxt, it: &hir::Item) { convert_method(ccx, ImplContainer(def_id), impl_item.name, impl_item.id, method_vis, - sig, impl_item.defaultness, selfty, &ty_generics, + sig, impl_item.defaultness, selfty, &ty_predicates); } } @@ -856,7 +863,7 @@ fn convert_item(ccx: &CrateCtxt, it: &hir::Item) { .to_ty(&ExplicitRscope, ty); tcx.register_item_type(ccx.tcx.map.local_def_id(trait_item.id), TypeScheme { - generics: trait_def.generics.clone(), + generics: trait_def.generics, ty: ty, }); convert_associated_const(ccx, @@ -898,7 +905,6 @@ fn convert_item(ccx: &CrateCtxt, it: &hir::Item) { sig, hir::Defaultness::Default, tcx.mk_self_type(), - &trait_def.generics, &trait_predicates); } @@ -917,11 +923,11 @@ fn convert_item(ccx: &CrateCtxt, it: &hir::Item) { trait_item_def_ids); }, hir::ItemStruct(ref struct_def, _) => { - let (scheme, predicates) = convert_typed_item(ccx, it); - write_ty_to_tcx(ccx, it.id, scheme.ty); + let def_id = ccx.tcx.map.local_def_id(it.id); + let scheme = type_scheme_of_def_id(ccx, def_id); + let predicates = predicates_of_item(ccx, it); - let it_def_id = ccx.tcx.map.local_def_id(it.id); - let variant = tcx.lookup_adt_def_master(it_def_id).struct_variant(); + let variant = tcx.lookup_adt_def_master(def_id).struct_variant(); for (f, ty_f) in struct_def.fields().iter().zip(variant.fields.iter()) { convert_field(ccx, &scheme.generics, &predicates, f, ty_f) @@ -933,15 +939,14 @@ fn convert_item(ccx: &CrateCtxt, it: &hir::Item) { }, hir::ItemTy(_, ref generics) => { ensure_no_ty_param_bounds(ccx, it.span, generics, "type"); - let (scheme, _) = convert_typed_item(ccx, it); - write_ty_to_tcx(ccx, it.id, scheme.ty); + let def_id = ccx.tcx.map.local_def_id(it.id); + type_scheme_of_def_id(ccx, def_id); + predicates_of_item(ccx, it); }, _ => { - // This call populates the type cache with the converted type - // of the item in passing. All we have to do here is to write - // it into the node type table. - let (scheme, _) = convert_typed_item(ccx, it); - write_ty_to_tcx(ccx, it.id, scheme.ty); + let def_id = ccx.tcx.map.local_def_id(it.id); + type_scheme_of_def_id(ccx, def_id); + predicates_of_item(ccx, it); }, } } @@ -952,6 +957,8 @@ fn convert_variant_ctor<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, scheme: ty::TypeScheme<'tcx>, predicates: ty::GenericPredicates<'tcx>) { let tcx = ccx.tcx; + let def_id = tcx.map.local_def_id(ctor_id); + tcx.generics.borrow_mut().insert(def_id, scheme.generics); let ctor_ty = match variant.kind { VariantKind::Unit | VariantKind::Struct => scheme.ty, VariantKind::Tuple => { @@ -960,8 +967,8 @@ fn convert_variant_ctor<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, .iter() .map(|field| field.unsubst_ty()) .collect(); - let def_id = tcx.map.local_def_id(ctor_id); - let substs = mk_item_substs(tcx, &scheme.generics); + let substs = mk_item_substs(&ccx.icx(&predicates), + ccx.tcx.map.span(ctor_id), def_id); tcx.mk_fn_def(def_id, substs, tcx.mk_bare_fn(ty::BareFnTy { unsafety: hir::Unsafety::Normal, abi: abi::Abi::Rust, @@ -974,12 +981,8 @@ fn convert_variant_ctor<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, } }; write_ty_to_tcx(ccx, ctor_id, ctor_ty); + tcx.tcache.borrow_mut().insert(def_id, ctor_ty); tcx.predicates.borrow_mut().insert(tcx.map.local_def_id(ctor_id), predicates); - tcx.register_item_type(tcx.map.local_def_id(ctor_id), - TypeScheme { - generics: scheme.generics, - ty: ctor_ty - }); } fn convert_enum_variant_types<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, @@ -1237,7 +1240,9 @@ fn trait_def_of_item<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, } let (unsafety, generics, items) = match it.node { - hir::ItemTrait(unsafety, ref generics, _, ref items) => (unsafety, generics, items), + hir::ItemTrait(unsafety, ref generics, _, ref items) => { + (unsafety, generics, items) + } _ => span_bug!(it.span, "trait_def_of_item invoked on non-trait"), }; @@ -1253,9 +1258,8 @@ fn trait_def_of_item<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, err.emit(); } - let substs = ccx.tcx.mk_substs(mk_trait_substs(ccx, generics)); - - let ty_generics = ty_generics_for_trait(ccx, it.id, substs, generics); + let ty_generics = generics_of_def_id(ccx, def_id); + let substs = mk_item_substs(&ccx.icx(generics), it.span, def_id); let associated_type_names: Vec<_> = items.iter().filter_map(|trait_item| { match trait_item.node { @@ -1264,51 +1268,14 @@ fn trait_def_of_item<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, } }).collect(); - let trait_ref = ty::TraitRef { - def_id: def_id, - substs: substs, - }; - + let trait_ref = ty::TraitRef::new(def_id, substs); let trait_def = ty::TraitDef::new(unsafety, paren_sugar, ty_generics, trait_ref, associated_type_names); - return tcx.intern_trait_def(trait_def); - - fn mk_trait_substs<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, - generics: &hir::Generics) - -> Substs<'tcx> - { - let tcx = ccx.tcx; - - // Creates a no-op substitution for the trait's type parameters. - let regions = - generics.lifetimes - .iter() - .enumerate() - .map(|(i, def)| ty::ReEarlyBound(ty::EarlyBoundRegion { - space: TypeSpace, - index: i as u32, - name: def.lifetime.name - })) - .collect(); - - // Start with the generics in the type parameters... - let types: Vec<_> = - generics.ty_params - .iter() - .enumerate() - .map(|(i, def)| tcx.mk_param(TypeSpace, - i as u32, def.name)) - .collect(); - - // ...and also create the `Self` parameter. - let self_ty = tcx.mk_self_type(); - - Substs::new_trait(types, regions, self_ty) - } + tcx.intern_trait_def(trait_def) } fn trait_defines_associated_type_named(ccx: &CrateCtxt, @@ -1410,105 +1377,243 @@ fn convert_trait_predicates<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, it: &hir::Item) } } -fn type_scheme_of_def_id<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>, - def_id: DefId) - -> ty::TypeScheme<'tcx> -{ - if let Some(node_id) = ccx.tcx.map.as_local_node_id(def_id) { - match ccx.tcx.map.find(node_id) { - Some(hir_map::NodeItem(item)) => { - type_scheme_of_item(ccx, &item) +fn generics_of_def_id<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, + def_id: DefId) + -> &'tcx ty::Generics<'tcx> { + let tcx = ccx.tcx; + let node_id = if let Some(id) = tcx.map.as_local_node_id(def_id) { + id + } else { + return tcx.lookup_generics(def_id); + }; + tcx.generics.memoize(def_id, || { + use rustc::hir::map::*; + use rustc::hir::*; + + let mut opt_self = None; + let mut base_def_id = None; + let mut allow_defaults = false; + + let no_generics = hir::Generics::empty(); + let (space, ast_generics) = match tcx.map.get(node_id) { + NodeImplItem(&ImplItem { node: ImplItemKind::Method(ref sig, _), .. }) | + NodeTraitItem(&TraitItem { node: MethodTraitItem(ref sig, _), .. }) => { + let parent_id = tcx.map.get_parent(node_id); + base_def_id = Some(tcx.map.local_def_id(parent_id)); + (FnSpace, &sig.generics) } - Some(hir_map::NodeForeignItem(foreign_item)) => { - let abi = ccx.tcx.map.get_foreign_abi(node_id); - type_scheme_of_foreign_item(ccx, &foreign_item, abi) + + NodeImplItem(_) | + NodeTraitItem(_) => { + let parent_id = tcx.map.get_parent(node_id); + base_def_id = Some(tcx.map.local_def_id(parent_id)); + (FnSpace, &no_generics) } - x => { - bug!("unexpected sort of node in get_item_type_scheme(): {:?}", - x); + + NodeItem(item) => { + match item.node { + ItemFn(_, _, _, _, ref generics, _) => (FnSpace, generics), + ItemImpl(_, _, ref generics, _, _, _) => (TypeSpace, generics), + ItemTy(_, ref generics) | + ItemEnum(_, ref generics) | + ItemStruct(_, ref generics) => { + allow_defaults = true; + (TypeSpace, generics) + } + ItemTrait(_, ref generics, _, _) => { + // Add in the self type parameter. + // + // Something of a hack: use the node id for the trait, also as + // the node id for the Self type parameter. + let param_id = item.id; + + let parent = ccx.tcx.map.get_parent(param_id); + + let def = ty::TypeParameterDef { + space: SelfSpace, + index: 0, + name: keywords::SelfType.name(), + def_id: tcx.map.local_def_id(param_id), + default_def_id: tcx.map.local_def_id(parent), + default: None, + object_lifetime_default: ty::ObjectLifetimeDefault::BaseDefault, + }; + tcx.ty_param_defs.borrow_mut().insert(param_id, def.clone()); + opt_self = Some(def); + + allow_defaults = true; + (TypeSpace, generics) + } + _ => (TypeSpace, &no_generics) + } + } + + NodeForeignItem(item) => { + match item.node { + ForeignItemStatic(..) => (TypeSpace, &no_generics), + ForeignItemFn(_, ref generics) => (FnSpace, generics) + } } + + _ => (TypeSpace, &no_generics) + }; + + let empty_generics = ty::Generics::empty(); + let base_generics = base_def_id.map_or(&empty_generics, |def_id| { + generics_of_def_id(ccx, def_id) + }); + + let early_lifetimes = early_bound_lifetimes_from_generics(ccx, ast_generics); + let regions = early_lifetimes.iter().enumerate().map(|(i, l)| { + ty::RegionParameterDef { + name: l.lifetime.name, + space: space, + index: i as u32, + def_id: tcx.map.local_def_id(l.lifetime.id), + bounds: l.bounds.iter().map(|l| { + ast_region_to_region(tcx, l) + }).collect() + } + }).collect(); + + // Now create the real type parameters. + let types = ast_generics.ty_params.iter().enumerate().map(|(i, _)| { + get_or_create_type_parameter_def(ccx, ast_generics, space, i as u32, allow_defaults) + }).collect(); + + let has_self = base_generics.has_self || opt_self.is_some(); + let (regions, types) = match space { + SelfSpace => bug!(), + TypeSpace => { + assert_eq!(base_generics.regions.as_full_slice().len(), 0); + assert_eq!(base_generics.types.as_full_slice().len(), 0); + (VecPerParamSpace::new(vec![], regions, vec![]), + VecPerParamSpace::new(opt_self.into_iter().collect(), types, vec![])) + } + FnSpace => { + assert_eq!(base_generics.regions.len(FnSpace), 0); + assert_eq!(base_generics.types.len(FnSpace), 0); + (VecPerParamSpace::new(base_generics.regions.get_slice(SelfSpace).to_vec(), + base_generics.regions.get_slice(TypeSpace).to_vec(), + regions), + VecPerParamSpace::new(base_generics.types.get_slice(SelfSpace).to_vec(), + base_generics.types.get_slice(TypeSpace).to_vec(), + types)) + } + }; + + // Debugging aid. + if tcx.has_attr(def_id, "rustc_object_lifetime_default") { + let object_lifetime_default_reprs: String = + types.as_full_slice().iter().map(|t| { + match t.object_lifetime_default { + ty::ObjectLifetimeDefault::Specific(r) => r.to_string(), + d => format!("{:?}", d), + } + }).collect::>().join(","); + tcx.sess.span_err(tcx.map.span(node_id), &object_lifetime_default_reprs); } - } else { - ccx.tcx.lookup_item_type(def_id) - } + + tcx.alloc_generics(ty::Generics { + regions: regions, + types: types, + has_self: has_self + }) + }) } -fn type_scheme_of_item<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>, - item: &hir::Item) - -> ty::TypeScheme<'tcx> -{ - let item_def_id = ccx.tcx.map.local_def_id(item.id); - ccx.tcx.tcache.memoize(item_def_id, || { - // NB. Since the `memoized` function enters a new task, and we - // are giving this task access to the item `item`, we must - // register a read. - assert!(!ccx.tcx.map.is_inlined_def_id(item_def_id)); - ccx.tcx.dep_graph.read(DepNode::Hir(item_def_id)); - compute_type_scheme_of_item(ccx, item) +fn type_of_def_id<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, + def_id: DefId) + -> Ty<'tcx> { + let node_id = if let Some(id) = ccx.tcx.map.as_local_node_id(def_id) { + id + } else { + return ccx.tcx.lookup_item_type(def_id).ty; + }; + ccx.tcx.tcache.memoize(def_id, || { + use rustc::hir::map::*; + use rustc::hir::*; + + let ty = match ccx.tcx.map.get(node_id) { + NodeItem(item) => { + match item.node { + ItemStatic(ref t, _, _) | ItemConst(ref t, _) => { + ccx.icx(&()).to_ty(&ExplicitRscope, &t) + } + ItemFn(ref decl, unsafety, _, abi, ref generics, _) => { + let tofd = AstConv::ty_of_bare_fn(&ccx.icx(generics), unsafety, abi, &decl, + Some(AnonTypeScope::new(def_id))); + let substs = mk_item_substs(&ccx.icx(generics), item.span, def_id); + ccx.tcx.mk_fn_def(def_id, substs, tofd) + } + ItemTy(ref t, ref generics) => { + ccx.icx(generics).to_ty(&ExplicitRscope, &t) + } + ItemEnum(ref ei, ref generics) => { + let def = convert_enum_def(ccx, item, ei); + let substs = mk_item_substs(&ccx.icx(generics), item.span, def_id); + ccx.tcx.mk_enum(def, substs) + } + ItemStruct(ref si, ref generics) => { + let def = convert_struct_def(ccx, item, si); + let substs = mk_item_substs(&ccx.icx(generics), item.span, def_id); + ccx.tcx.mk_struct(def, substs) + } + ItemDefaultImpl(..) | + ItemTrait(..) | + ItemImpl(..) | + ItemMod(..) | + ItemForeignMod(..) | + ItemExternCrate(..) | + ItemUse(..) => { + span_bug!( + item.span, + "compute_type_of_item: unexpected item type: {:?}", + item.node); + } + } + } + NodeForeignItem(foreign_item) => { + let abi = ccx.tcx.map.get_foreign_abi(node_id); + + match foreign_item.node { + ForeignItemFn(ref fn_decl, ref generics) => { + compute_type_of_foreign_fn_decl( + ccx, ccx.tcx.map.local_def_id(foreign_item.id), + fn_decl, generics, abi) + } + ForeignItemStatic(ref t, _) => { + ccx.icx(&()).to_ty(&ExplicitRscope, t) + } + } + } + x => { + bug!("unexpected sort of node in type_of_def_id(): {:?}", x); + } + }; + + write_ty_to_tcx(ccx, node_id, ty); + ty }) } -fn compute_type_scheme_of_item<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>, - it: &hir::Item) - -> ty::TypeScheme<'tcx> -{ - let tcx = ccx.tcx; - match it.node { - hir::ItemStatic(ref t, _, _) | hir::ItemConst(ref t, _) => { - let ty = ccx.icx(&()).to_ty(&ExplicitRscope, &t); - ty::TypeScheme { ty: ty, generics: ty::Generics::empty() } - } - hir::ItemFn(ref decl, unsafety, _, abi, ref generics, _) => { - let ty_generics = ty_generics_for_fn(ccx, generics, &ty::Generics::empty()); - let tofd = AstConv::ty_of_bare_fn(&ccx.icx(generics), unsafety, abi, &decl, - Some(AnonTypeScope::new(&ty_generics))); - let def_id = ccx.tcx.map.local_def_id(it.id); - let substs = mk_item_substs(tcx, &ty_generics); - let ty = tcx.mk_fn_def(def_id, substs, tofd); - ty::TypeScheme { ty: ty, generics: ty_generics } - } - hir::ItemTy(ref t, ref generics) => { - let ty_generics = ty_generics_for_type(ccx, generics); - let ty = ccx.icx(generics).to_ty(&ExplicitRscope, &t); - ty::TypeScheme { ty: ty, generics: ty_generics } - } - hir::ItemEnum(ref ei, ref generics) => { - let def = convert_enum_def(ccx, it, ei); - let ty_generics = ty_generics_for_type(ccx, generics); - let substs = mk_item_substs(tcx, &ty_generics); - let t = tcx.mk_enum(def, substs); - ty::TypeScheme { ty: t, generics: ty_generics } - } - hir::ItemStruct(ref si, ref generics) => { - let def = convert_struct_def(ccx, it, si); - let ty_generics = ty_generics_for_type(ccx, generics); - let substs = mk_item_substs(tcx, &ty_generics); - let t = tcx.mk_struct(def, substs); - ty::TypeScheme { ty: t, generics: ty_generics } - } - hir::ItemDefaultImpl(..) | - hir::ItemTrait(..) | - hir::ItemImpl(..) | - hir::ItemMod(..) | - hir::ItemForeignMod(..) | - hir::ItemExternCrate(..) | - hir::ItemUse(..) => { - span_bug!( - it.span, - "compute_type_scheme_of_item: unexpected item type: {:?}", - it.node); +fn type_scheme_of_def_id<'a, 'tcx>(ccx: &CrateCtxt<'a,'tcx>, + def_id: DefId) + -> ty::TypeScheme<'tcx> { + if def_id.is_local() { + ty::TypeScheme { + generics: generics_of_def_id(ccx, def_id), + ty: type_of_def_id(ccx, def_id) } + } else { + ccx.tcx.lookup_item_type(def_id) } } -fn convert_typed_item<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, +fn predicates_of_item<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, it: &hir::Item) - -> (ty::TypeScheme<'tcx>, ty::GenericPredicates<'tcx>) -{ - let tcx = ccx.tcx; - - let tag = type_scheme_of_item(ccx, it); - let scheme = TypeScheme { generics: tag.generics, ty: tag.ty }; + -> ty::GenericPredicates<'tcx> { + let def_id = ccx.tcx.map.local_def_id(it.id); let predicates = match it.node { hir::ItemStatic(..) | hir::ItemConst(..) => { ty::GenericPredicates::empty() @@ -1516,12 +1621,8 @@ fn convert_typed_item<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, hir::ItemFn(_, _, _, _, ref ast_generics, _) => { ty_generic_predicates_for_fn(ccx, ast_generics, &ty::GenericPredicates::empty()) } - hir::ItemTy(_, ref generics) => { - ty_generic_predicates_for_type_or_impl(ccx, generics) - } - hir::ItemEnum(_, ref generics) => { - ty_generic_predicates_for_type_or_impl(ccx, generics) - } + hir::ItemTy(_, ref generics) | + hir::ItemEnum(_, ref generics) | hir::ItemStruct(_, ref generics) => { ty_generic_predicates_for_type_or_impl(ccx, generics) } @@ -1534,68 +1635,16 @@ fn convert_typed_item<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, hir::ItemForeignMod(..) => { span_bug!( it.span, - "compute_type_scheme_of_item: unexpected item type: {:?}", + "predicates_of_item: unexpected item type: {:?}", it.node); } }; - let prev_predicates = tcx.predicates.borrow_mut().insert(ccx.tcx.map.local_def_id(it.id), - predicates.clone()); + let prev_predicates = ccx.tcx.predicates.borrow_mut().insert(def_id, + predicates.clone()); assert!(prev_predicates.is_none()); - // Debugging aid. - if tcx.has_attr(ccx.tcx.map.local_def_id(it.id), "rustc_object_lifetime_default") { - let object_lifetime_default_reprs: String = - scheme.generics.types.as_full_slice().iter() - .map(|t| match t.object_lifetime_default { - ty::ObjectLifetimeDefault::Specific(r) => r.to_string(), - d => format!("{:?}", d), - }) - .collect::>() - .join(","); - - tcx.sess.span_err(it.span, &object_lifetime_default_reprs); - } - - return (scheme, predicates); -} - -fn type_scheme_of_foreign_item<'a, 'tcx>( - ccx: &CrateCtxt<'a, 'tcx>, - item: &hir::ForeignItem, - abi: abi::Abi) - -> ty::TypeScheme<'tcx> -{ - let item_def_id = ccx.tcx.map.local_def_id(item.id); - ccx.tcx.tcache.memoize(item_def_id, || { - // NB. Since the `memoized` function enters a new task, and we - // are giving this task access to the item `item`, we must - // register a read. - assert!(!ccx.tcx.map.is_inlined_def_id(item_def_id)); - ccx.tcx.dep_graph.read(DepNode::Hir(item_def_id)); - compute_type_scheme_of_foreign_item(ccx, item, abi) - }) -} - -fn compute_type_scheme_of_foreign_item<'a, 'tcx>( - ccx: &CrateCtxt<'a, 'tcx>, - it: &hir::ForeignItem, - abi: abi::Abi) - -> ty::TypeScheme<'tcx> -{ - match it.node { - hir::ForeignItemFn(ref fn_decl, ref generics) => { - compute_type_scheme_of_foreign_fn_decl( - ccx, ccx.tcx.map.local_def_id(it.id), - fn_decl, generics, abi) - } - hir::ForeignItemStatic(ref t, _) => { - ty::TypeScheme { - generics: ty::Generics::empty(), - ty: AstConv::ast_ty_to_ty(&ccx.icx(&()), &ExplicitRscope, t) - } - } - } + predicates } fn convert_foreign_item<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, @@ -1605,11 +1654,8 @@ fn convert_foreign_item<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, // map, and I regard each time that I use it as a personal and // moral failing, but at the moment it seems like the only // convenient way to extract the ABI. - ndm - let tcx = ccx.tcx; - let abi = tcx.map.get_foreign_abi(it.id); - - let scheme = type_scheme_of_foreign_item(ccx, it, abi); - write_ty_to_tcx(ccx, it.id, scheme.ty); + let def_id = ccx.tcx.map.local_def_id(it.id); + type_scheme_of_def_id(ccx, def_id); let predicates = match it.node { hir::ForeignItemFn(_, ref generics) => { @@ -1620,21 +1666,10 @@ fn convert_foreign_item<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, } }; - let prev_predicates = tcx.predicates.borrow_mut().insert(ccx.tcx.map.local_def_id(it.id), - predicates); + let prev_predicates = ccx.tcx.predicates.borrow_mut().insert(def_id, predicates); assert!(prev_predicates.is_none()); } -fn ty_generics_for_type<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, generics: &hir::Generics) - -> ty::Generics<'tcx> { - ty_generics(ccx, TypeSpace, generics, &ty::Generics::empty(), true) -} - -fn ty_generics_for_impl<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, generics: &hir::Generics) - -> ty::Generics<'tcx> { - ty_generics(ccx, TypeSpace, generics, &ty::Generics::empty(), false) -} - fn ty_generic_predicates_for_type_or_impl<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>, generics: &hir::Generics) -> ty::GenericPredicates<'tcx> @@ -1642,50 +1677,6 @@ fn ty_generic_predicates_for_type_or_impl<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>, ty_generic_predicates(ccx, TypeSpace, generics, &ty::GenericPredicates::empty()) } -fn ty_generics_for_trait<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, - trait_id: ast::NodeId, - substs: &'tcx Substs<'tcx>, - ast_generics: &hir::Generics) - -> ty::Generics<'tcx> -{ - debug!("ty_generics_for_trait(trait_id={:?}, substs={:?})", - ccx.tcx.map.local_def_id(trait_id), substs); - - let mut generics = ty_generics_for_type(ccx, ast_generics); - - // Add in the self type parameter. - // - // Something of a hack: use the node id for the trait, also as - // the node id for the Self type parameter. - let param_id = trait_id; - - let parent = ccx.tcx.map.get_parent(param_id); - - let def = ty::TypeParameterDef { - space: SelfSpace, - index: 0, - name: keywords::SelfType.name(), - def_id: ccx.tcx.map.local_def_id(param_id), - default_def_id: ccx.tcx.map.local_def_id(parent), - default: None, - object_lifetime_default: ty::ObjectLifetimeDefault::BaseDefault, - }; - - ccx.tcx.ty_param_defs.borrow_mut().insert(param_id, def.clone()); - - generics.types.push(SelfSpace, def); - - return generics; -} - -fn ty_generics_for_fn<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>, - generics: &hir::Generics, - base_generics: &ty::Generics<'tcx>) - -> ty::Generics<'tcx> -{ - ty_generics(ccx, FnSpace, generics, base_generics, false) -} - fn ty_generic_predicates_for_fn<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>, generics: &hir::Generics, base_predicates: &ty::GenericPredicates<'tcx>) @@ -1859,42 +1850,6 @@ fn ty_generic_predicates<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>, result } -fn ty_generics<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>, - space: ParamSpace, - ast_generics: &hir::Generics, - base_generics: &ty::Generics<'tcx>, - allow_defaults: bool) - -> ty::Generics<'tcx> -{ - let tcx = ccx.tcx; - let mut result = base_generics.clone(); - - let early_lifetimes = early_bound_lifetimes_from_generics(ccx, ast_generics); - for (i, l) in early_lifetimes.iter().enumerate() { - let bounds = l.bounds.iter() - .map(|l| ast_region_to_region(tcx, l)) - .collect(); - let def = ty::RegionParameterDef { name: l.lifetime.name, - space: space, - index: i as u32, - def_id: ccx.tcx.map.local_def_id(l.lifetime.id), - bounds: bounds }; - result.regions.push(space, def); - } - - assert!(result.types.is_empty_in(space)); - - // Now create the real type parameters. - for i in 0..ast_generics.ty_params.len() { - let def = - get_or_create_type_parameter_def(ccx, ast_generics, space, i as u32, allow_defaults); - debug!("ty_generics: def for type param: {:?}, {:?}", def, space); - result.types.push(space, def); - } - - result -} - fn convert_default_type_parameter<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, path: &P, space: ParamSpace, @@ -1969,6 +1924,9 @@ fn get_or_create_type_parameter_def<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>, tcx.ty_param_defs.borrow_mut().insert(param.id, def.clone()); + debug!("get_or_create_type_parameter_def: def for type param: {:?}, {:?}", + def, space); + def } @@ -2122,16 +2080,14 @@ fn predicates_from_bound<'tcx>(astconv: &AstConv<'tcx, 'tcx>, } } -fn compute_type_scheme_of_foreign_fn_decl<'a, 'tcx>( +fn compute_type_of_foreign_fn_decl<'a, 'tcx>( ccx: &CrateCtxt<'a, 'tcx>, - id: DefId, + def_id: DefId, decl: &hir::FnDecl, ast_generics: &hir::Generics, abi: abi::Abi) - -> ty::TypeScheme<'tcx> + -> Ty<'tcx> { - let ty_generics = ty_generics_for_fn(ccx, ast_generics, &ty::Generics::empty()); - let rb = BindingRscope::new(); let input_tys = decl.inputs .iter() @@ -2167,34 +2123,32 @@ fn compute_type_scheme_of_foreign_fn_decl<'a, 'tcx>( } } - let substs = mk_item_substs(ccx.tcx, &ty_generics); - let t_fn = ccx.tcx.mk_fn_def(id, substs, ccx.tcx.mk_bare_fn(ty::BareFnTy { + let id = ccx.tcx.map.as_local_node_id(def_id).unwrap(); + let substs = mk_item_substs(&ccx.icx(ast_generics), ccx.tcx.map.span(id), def_id); + ccx.tcx.mk_fn_def(def_id, substs, ccx.tcx.mk_bare_fn(ty::BareFnTy { abi: abi, unsafety: hir::Unsafety::Unsafe, sig: ty::Binder(ty::FnSig {inputs: input_tys, output: output, variadic: decl.variadic}), - })); - - ty::TypeScheme { - generics: ty_generics, - ty: t_fn - } + })) } -pub fn mk_item_substs<'a, 'gcx, 'tcx>(tcx: TyCtxt<'a, 'gcx, 'tcx>, - ty_generics: &ty::Generics) - -> &'tcx Substs<'tcx> -{ - let types = - ty_generics.types.map( - |def| tcx.mk_param_from_def(def)); - - let regions = - ty_generics.regions.map( - |def| def.to_early_bound_region()); +pub fn mk_item_substs<'gcx: 'tcx, 'tcx>(astconv: &AstConv<'gcx, 'tcx>, + span: Span, + def_id: DefId) + -> &'tcx Substs<'tcx> { + let tcx = astconv.tcx(); + // FIXME(eddyb) Do this request from Substs::for_item in librustc. + if let Err(ErrorReported) = astconv.get_generics(span, def_id) { + // No convenient way to recover from a cycle here. Just bail. Sorry! + tcx.sess.abort_if_errors(); + bug!("ErrorReported returned, but no errors reports?") + } - tcx.mk_substs(Substs::new(types, regions)) + Substs::for_item(tcx, def_id, + |def, _| def.to_early_bound_region(), + |def, _| tcx.mk_param_from_def(def)) } /// Checks that all the type parameters on an impl diff --git a/src/librustc_typeck/lib.rs b/src/librustc_typeck/lib.rs index 4ce6f8210c3c5..8a8232535c775 100644 --- a/src/librustc_typeck/lib.rs +++ b/src/librustc_typeck/lib.rs @@ -231,7 +231,7 @@ fn check_main_fn_ty(ccx: &CrateCtxt, _ => () } let main_def_id = tcx.map.local_def_id(main_id); - let substs = tcx.mk_substs(Substs::empty()); + let substs = Substs::empty(tcx); let se_ty = tcx.mk_fn_def(main_def_id, substs, tcx.mk_bare_fn(ty::BareFnTy { unsafety: hir::Unsafety::Normal, @@ -284,7 +284,7 @@ fn check_start_fn_ty(ccx: &CrateCtxt, } let start_def_id = ccx.tcx.map.local_def_id(start_id); - let substs = tcx.mk_substs(Substs::empty()); + let substs = Substs::empty(tcx); let se_ty = tcx.mk_fn_def(start_def_id, substs, tcx.mk_bare_fn(ty::BareFnTy { unsafety: hir::Unsafety::Normal, diff --git a/src/librustc_typeck/rscope.rs b/src/librustc_typeck/rscope.rs index 58d1ec9d02a95..9aca779dd89c4 100644 --- a/src/librustc_typeck/rscope.rs +++ b/src/librustc_typeck/rscope.rs @@ -8,10 +8,12 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. - -use rustc::ty::{self, TyCtxt}; +use rustc::hir::def_id::DefId; +use rustc::ty; use rustc::ty::subst::Substs; +use astconv::AstConv; + use std::cell::Cell; use syntax_pos::Span; @@ -71,33 +73,34 @@ pub trait RegionScope { } #[derive(Copy, Clone)] -pub struct AnonTypeScope<'a> { - generics: &'a ty::Generics<'a> +pub struct AnonTypeScope { + enclosing_item: DefId } -impl<'a, 'b, 'gcx, 'tcx> AnonTypeScope<'a> { - pub fn new(generics: &'a ty::Generics<'a>) -> AnonTypeScope<'a> { +impl<'gcx: 'tcx, 'tcx> AnonTypeScope { + pub fn new(enclosing_item: DefId) -> AnonTypeScope { AnonTypeScope { - generics: generics + enclosing_item: enclosing_item } } - pub fn fresh_substs(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>) -> &'tcx Substs<'tcx> { + pub fn fresh_substs(&self, astconv: &AstConv<'gcx, 'tcx>, span: Span) + -> &'tcx Substs<'tcx> { use collect::mk_item_substs; - mk_item_substs(tcx, self.generics) + mk_item_substs(astconv, span, self.enclosing_item) } } /// A scope wrapper which optionally allows anonymized types. #[derive(Copy, Clone)] -pub struct MaybeWithAnonTypes<'a, R> { +pub struct MaybeWithAnonTypes { base_scope: R, - anon_scope: Option> + anon_scope: Option } -impl<'a, R: RegionScope> MaybeWithAnonTypes<'a, R> { - pub fn new(base_scope: R, anon_scope: Option>) -> Self { +impl MaybeWithAnonTypes { + pub fn new(base_scope: R, anon_scope: Option) -> Self { MaybeWithAnonTypes { base_scope: base_scope, anon_scope: anon_scope @@ -105,7 +108,7 @@ impl<'a, R: RegionScope> MaybeWithAnonTypes<'a, R> { } } -impl<'a, R: RegionScope> RegionScope for MaybeWithAnonTypes<'a, R> { +impl RegionScope for MaybeWithAnonTypes { fn object_lifetime_default(&self, span: Span) -> Option { self.base_scope.object_lifetime_default(span) } diff --git a/src/librustc_typeck/variance/constraints.rs b/src/librustc_typeck/variance/constraints.rs index 6e6f9ce65c50f..8c9b4beb79d84 100644 --- a/src/librustc_typeck/variance/constraints.rs +++ b/src/librustc_typeck/variance/constraints.rs @@ -16,8 +16,7 @@ use dep_graph::DepTrackingMapConfig; use hir::def_id::DefId; use middle::resolve_lifetime as rl; -use rustc::ty::subst; -use rustc::ty::subst::ParamSpace; +use rustc::ty::subst::{self, ParamSpace, Substs}; use rustc::ty::{self, Ty, TyCtxt}; use rustc::ty::maps::ItemVariances; use rustc::hir::map as hir_map; @@ -370,8 +369,8 @@ impl<'a, 'tcx> ConstraintContext<'a, 'tcx> { self.add_constraints_from_substs( generics, def.did, - item_type.generics.types.get_slice(subst::TypeSpace), - item_type.generics.regions.get_slice(subst::TypeSpace), + item_type.generics.types.as_full_slice(), + item_type.generics.regions.as_full_slice(), substs, variance); } @@ -449,7 +448,7 @@ impl<'a, 'tcx> ConstraintContext<'a, 'tcx> { def_id: DefId, type_param_defs: &[ty::TypeParameterDef<'tcx>], region_param_defs: &[ty::RegionParameterDef], - substs: &subst::Substs<'tcx>, + substs: &Substs<'tcx>, variance: VarianceTermPtr<'a>) { debug!("add_constraints_from_substs(def_id={:?}, substs={:?}, variance={:?})", def_id, diff --git a/src/librustc_typeck/variance/solve.rs b/src/librustc_typeck/variance/solve.rs index 8bb49410a5bdc..22edf219dff75 100644 --- a/src/librustc_typeck/variance/solve.rs +++ b/src/librustc_typeck/variance/solve.rs @@ -16,6 +16,7 @@ //! inferred is then written into the `variance_map` in the tcx. use rustc::ty; +use rustc::ty::subst; use std::rc::Rc; use super::constraints::*; @@ -108,7 +109,9 @@ impl<'a, 'tcx> SolveContext<'a, 'tcx> { let num_inferred = self.terms_cx.num_inferred(); while index < num_inferred { let item_id = inferred_infos[index].item_id; - let mut item_variances = ty::ItemVariances::empty(); + + let (mut rs, mut rt, mut rf) = (vec![], vec![], vec![]); + let (mut ts, mut tt, mut tf) = (vec![], vec![], vec![]); while index < num_inferred && inferred_infos[index].item_id == item_id { let info = &inferred_infos[index]; @@ -116,13 +119,34 @@ impl<'a, 'tcx> SolveContext<'a, 'tcx> { debug!("Index {} Info {} / {:?} / {:?} Variance {:?}", index, info.index, info.kind, info.space, variance); match info.kind { - TypeParam => { item_variances.types.push(info.space, variance); } - RegionParam => { item_variances.regions.push(info.space, variance); } + TypeParam => { + let types = match info.space { + subst::SelfSpace => &mut ts, + subst::TypeSpace => &mut tt, + subst::FnSpace => &mut tf + }; + assert_eq!(types.len(), info.index); + types.push(variance); + } + RegionParam => { + let regions = match info.space { + subst::SelfSpace => &mut rs, + subst::TypeSpace => &mut rt, + subst::FnSpace => &mut rf + }; + assert_eq!(regions.len(), info.index); + regions.push(variance); + } } index += 1; } + let item_variances = ty::ItemVariances { + regions: subst::VecPerParamSpace::new(rs, rt, rf), + types: subst::VecPerParamSpace::new(ts, tt, tf) + }; + debug!("item_id={} item_variances={:?}", item_id, item_variances); diff --git a/src/librustdoc/clean/inline.rs b/src/librustdoc/clean/inline.rs index cea12404298fc..b4be201440ccf 100644 --- a/src/librustdoc/clean/inline.rs +++ b/src/librustdoc/clean/inline.rs @@ -161,7 +161,7 @@ pub fn build_external_trait<'a, 'tcx>(cx: &DocContext, tcx: TyCtxt<'a, 'tcx, 'tc let def = tcx.lookup_trait_def(did); let trait_items = tcx.trait_items(did).clean(cx); let predicates = tcx.lookup_predicates(did); - let generics = (&def.generics, &predicates, subst::TypeSpace).clean(cx); + let generics = (def.generics, &predicates, subst::TypeSpace).clean(cx); let generics = filter_non_trait_generics(did, generics); let (generics, supertrait_bounds) = separate_supertrait_bounds(generics); clean::Trait { @@ -189,7 +189,7 @@ fn build_external_function<'a, 'tcx>(cx: &DocContext, tcx: TyCtxt<'a, 'tcx, 'tcx let predicates = tcx.lookup_predicates(did); clean::Function { decl: decl, - generics: (&t.generics, &predicates, subst::FnSpace).clean(cx), + generics: (t.generics, &predicates, subst::FnSpace).clean(cx), unsafety: style, constness: constness, abi: abi, @@ -209,7 +209,7 @@ fn build_struct<'a, 'tcx>(cx: &DocContext, tcx: TyCtxt<'a, 'tcx, 'tcx>, &[..] if variant.kind == ty::VariantKind::Tuple => doctree::Tuple, _ => doctree::Plain, }, - generics: (&t.generics, &predicates, subst::TypeSpace).clean(cx), + generics: (t.generics, &predicates, subst::TypeSpace).clean(cx), fields: variant.fields.clean(cx), fields_stripped: false, } @@ -222,7 +222,7 @@ fn build_type<'a, 'tcx>(cx: &DocContext, tcx: TyCtxt<'a, 'tcx, 'tcx>, match t.ty.sty { ty::TyEnum(edef, _) if !tcx.sess.cstore.is_typedef(did) => { return clean::EnumItem(clean::Enum { - generics: (&t.generics, &predicates, subst::TypeSpace).clean(cx), + generics: (t.generics, &predicates, subst::TypeSpace).clean(cx), variants_stripped: false, variants: edef.variants.clean(cx), }) @@ -232,7 +232,7 @@ fn build_type<'a, 'tcx>(cx: &DocContext, tcx: TyCtxt<'a, 'tcx, 'tcx>, clean::TypedefItem(clean::Typedef { type_: t.ty.clean(cx), - generics: (&t.generics, &predicates, subst::TypeSpace).clean(cx), + generics: (t.generics, &predicates, subst::TypeSpace).clean(cx), }, false) } @@ -389,15 +389,11 @@ pub fn build_impl<'a, 'tcx>(cx: &DocContext, } ty::TypeTraitItem(ref assoc_ty) => { let did = assoc_ty.def_id; - let type_scheme = ty::TypeScheme { - ty: assoc_ty.ty.unwrap(), - generics: ty::Generics::empty() - }; // Not sure the choice of ParamSpace actually matters here, // because an associated type won't have generics on the LHS let typedef = clean::Typedef { - type_: type_scheme.ty.clean(cx), - generics: (&type_scheme.generics, + type_: assoc_ty.ty.unwrap().clean(cx), + generics: (&ty::Generics::empty(), &ty::GenericPredicates::empty(), subst::TypeSpace).clean(cx) }; @@ -438,7 +434,7 @@ pub fn build_impl<'a, 'tcx>(cx: &DocContext, provided_trait_methods: provided, trait_: trait_, for_: for_, - generics: (&ty.generics, &predicates, subst::TypeSpace).clean(cx), + generics: (ty.generics, &predicates, subst::TypeSpace).clean(cx), items: trait_items, polarity: polarity.map(|p| { p.clean(cx) }), }), diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index ffe5b9aad2fb3..f8a3a0af69752 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -41,7 +41,7 @@ use rustc::hir::def::Def; use rustc::hir::def_id::{DefId, DefIndex, CRATE_DEF_INDEX}; use rustc::hir::fold::Folder; use rustc::hir::print as pprust; -use rustc::ty::subst::{self, ParamSpace, VecPerParamSpace}; +use rustc::ty::subst::{self, ParamSpace, Substs, VecPerParamSpace}; use rustc::ty; use rustc::middle::stability; @@ -631,7 +631,7 @@ impl Clean for hir::TyParamBound { } fn external_path_params(cx: &DocContext, trait_did: Option, - bindings: Vec, substs: &subst::Substs) -> PathParameters { + bindings: Vec, substs: &Substs) -> PathParameters { let lifetimes = substs.regions.get_slice(subst::TypeSpace) .iter() .filter_map(|v| v.clean(cx)) @@ -676,7 +676,7 @@ fn external_path_params(cx: &DocContext, trait_did: Option, // trait_did should be set to a trait's DefId if called on a TraitRef, in order to sugar // from Fn<(A, B,), C> to Fn(A, B) -> C fn external_path(cx: &DocContext, name: &str, trait_did: Option, - bindings: Vec, substs: &subst::Substs) -> Path { + bindings: Vec, substs: &Substs) -> Path { Path { global: false, segments: vec![PathSegment { @@ -692,20 +692,20 @@ impl Clean for ty::BuiltinBound { Some(tcx) => tcx, None => return RegionBound(Lifetime::statik()) }; - let empty = subst::Substs::empty(); + let empty = Substs::empty(tcx); let (did, path) = match *self { ty::BoundSend => (tcx.lang_items.send_trait().unwrap(), - external_path(cx, "Send", None, vec![], &empty)), + external_path(cx, "Send", None, vec![], empty)), ty::BoundSized => (tcx.lang_items.sized_trait().unwrap(), - external_path(cx, "Sized", None, vec![], &empty)), + external_path(cx, "Sized", None, vec![], empty)), ty::BoundCopy => (tcx.lang_items.copy_trait().unwrap(), - external_path(cx, "Copy", None, vec![], &empty)), + external_path(cx, "Copy", None, vec![], empty)), ty::BoundSync => (tcx.lang_items.sync_trait().unwrap(), - external_path(cx, "Sync", None, vec![], &empty)), + external_path(cx, "Sync", None, vec![], empty)), }; inline::record_extern_fqn(cx, did, TypeTrait); TraitBound(PolyTrait { @@ -765,7 +765,7 @@ impl<'tcx> Clean for ty::TraitRef<'tcx> { } } -impl<'tcx> Clean>> for subst::Substs<'tcx> { +impl<'tcx> Clean>> for Substs<'tcx> { fn clean(&self, cx: &DocContext) -> Option> { let mut v = Vec::new(); v.extend(self.regions.as_full_slice().iter().filter_map(|r| r.clean(cx)) @@ -891,7 +891,7 @@ impl<'a> Clean for ty::Predicate<'a> { impl<'a> Clean for ty::TraitPredicate<'a> { fn clean(&self, cx: &DocContext) -> WherePredicate { WherePredicate::BoundPredicate { - ty: self.trait_ref.substs.self_ty().clean(cx).unwrap(), + ty: self.trait_ref.self_ty().clean(cx), bounds: vec![self.trait_ref.clean(cx)] } } @@ -1353,7 +1353,7 @@ impl<'tcx> Clean for ty::Method<'tcx> { predicates: self.predicates.predicates[method_start..].to_vec() }; - let generics = (&self.generics, &method_predicates, + let generics = (self.generics, &method_predicates, subst::FnSpace).clean(cx); let mut decl = (self.def_id, &self.fty.sig).clean(cx); match self.explicit_self { @@ -2923,7 +2923,7 @@ impl<'tcx> Clean for ty::AssociatedType<'tcx> { // applied to this associated type in question. let def = cx.tcx().lookup_trait_def(did); let predicates = cx.tcx().lookup_predicates(did); - let generics = (&def.generics, &predicates, subst::TypeSpace).clean(cx); + let generics = (def.generics, &predicates, subst::TypeSpace).clean(cx); generics.where_predicates.iter().filter_map(|pred| { let (name, self_type, trait_, bounds) = match *pred { WherePredicate::BoundPredicate { From c1cfd58cbdb84f834b8907dc5e1c7242c451225d Mon Sep 17 00:00:00 2001 From: Eduard Burtescu Date: Mon, 15 Aug 2016 01:07:09 +0300 Subject: [PATCH 09/12] rustc: remove SelfSpace from ParamSpace. --- src/librustc/hir/def.rs | 5 +- src/librustc/middle/dead.rs | 2 +- src/librustc/traits/coherence.rs | 6 +- src/librustc/traits/error_reporting.rs | 4 +- src/librustc/traits/object_safety.rs | 9 +- src/librustc/ty/context.rs | 2 +- src/librustc/ty/error.rs | 3 +- src/librustc/ty/flags.rs | 4 +- src/librustc/ty/mod.rs | 2 +- src/librustc/ty/sty.rs | 14 +++- src/librustc/ty/subst.rs | 78 ++++++----------- src/librustc/util/ppaux.rs | 67 +++++++-------- .../borrowck/mir/elaborate_drops.rs | 6 +- src/librustc_metadata/astencode.rs | 2 +- src/librustc_metadata/tydecode.rs | 6 +- src/librustc_resolve/lib.rs | 32 ++----- src/librustc_save_analysis/lib.rs | 2 +- src/librustc_trans/partitioning.rs | 2 +- src/librustc_typeck/astconv.rs | 52 ++++++++---- src/librustc_typeck/check/closure.rs | 2 +- src/librustc_typeck/check/method/mod.rs | 6 +- src/librustc_typeck/check/method/probe.rs | 8 +- src/librustc_typeck/check/mod.rs | 27 ++++-- src/librustc_typeck/check/wfcheck.rs | 45 +++------- src/librustc_typeck/coherence/mod.rs | 2 +- src/librustc_typeck/collect.rs | 83 +++++++------------ src/librustc_typeck/variance/constraints.rs | 8 +- src/librustc_typeck/variance/solve.rs | 10 +-- src/librustc_typeck/variance/terms.rs | 12 +-- src/librustdoc/clean/mod.rs | 38 +++++---- src/test/compile-fail/issue-26548.rs | 4 +- src/test/compile-fail/issue-26812.rs | 4 +- .../compile-fail/variance-associated-types.rs | 4 +- .../compile-fail/variance-object-types.rs | 2 +- .../compile-fail/variance-region-bounds.rs | 4 +- .../compile-fail/variance-regions-direct.rs | 14 ++-- .../compile-fail/variance-regions-indirect.rs | 10 +-- .../compile-fail/variance-trait-bounds.rs | 18 ++-- .../variance-trait-object-bound.rs | 2 +- .../compile-fail/variance-types-bounds.rs | 20 ++--- src/test/compile-fail/variance-types.rs | 12 +-- 41 files changed, 276 insertions(+), 357 deletions(-) diff --git a/src/librustc/hir/def.rs b/src/librustc/hir/def.rs index 218681efb7dc1..d15d51aed09a1 100644 --- a/src/librustc/hir/def.rs +++ b/src/librustc/hir/def.rs @@ -9,7 +9,6 @@ // except according to those terms. use hir::def_id::DefId; -use ty::subst::ParamSpace; use util::nodemap::NodeMap; use syntax::ast; use hir; @@ -31,7 +30,7 @@ pub enum Def { AssociatedTy(DefId /* trait */, DefId), Trait(DefId), PrimTy(hir::PrimTy), - TyParam(ParamSpace, u32, DefId, ast::Name), + TyParam(DefId), Upvar(DefId, // def id of closed over local ast::NodeId, // node id of closed over local usize, // index in the freevars list of the closure @@ -122,7 +121,7 @@ impl Def { match *self { Def::Fn(id) | Def::Mod(id) | Def::ForeignMod(id) | Def::Static(id, _) | Def::Variant(_, id) | Def::Enum(id) | Def::TyAlias(id) | Def::AssociatedTy(_, id) | - Def::TyParam(_, _, id, _) | Def::Struct(id) | Def::Trait(id) | + Def::TyParam(id) | Def::Struct(id) | Def::Trait(id) | Def::Method(id) | Def::Const(id) | Def::AssociatedConst(id) | Def::Local(id, _) | Def::Upvar(id, _, _, _) => { id diff --git a/src/librustc/middle/dead.rs b/src/librustc/middle/dead.rs index 7412b5fc8048f..20e281816b8b0 100644 --- a/src/librustc/middle/dead.rs +++ b/src/librustc/middle/dead.rs @@ -95,7 +95,7 @@ impl<'a, 'tcx> MarkSymbolVisitor<'a, 'tcx> { 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 { + match substs.substs.types.get(subst::TypeSpace, 0).sty { TyEnum(tyid, _) | TyStruct(tyid, _) => { self.check_def_id(tyid.did) } diff --git a/src/librustc/traits/coherence.rs b/src/librustc/traits/coherence.rs index f1701d60fd0c0..a5a415dd27c65 100644 --- a/src/librustc/traits/coherence.rs +++ b/src/librustc/traits/coherence.rs @@ -14,7 +14,6 @@ use super::{SelectionContext, Obligation, ObligationCause}; use middle::cstore::LOCAL_CRATE; use hir::def_id::DefId; -use ty::subst::TypeSpace; use ty::{self, Ty, TyCtxt}; use infer::{InferCtxt, TypeOrigin}; use syntax_pos::DUMMY_SP; @@ -160,12 +159,9 @@ fn orphan_check_trait_ref<'tcx>(tcx: TyCtxt, // First, create an ordered iterator over all the type parameters to the trait, with the self // type appearing first. - let input_tys = Some(trait_ref.self_ty()); - let input_tys = input_tys.iter().chain(trait_ref.substs.types.get_slice(TypeSpace)); - // Find the first input type that either references a type parameter OR // some local type. - for input_ty in input_tys { + for input_ty in trait_ref.input_types() { if ty_is_local(tcx, input_ty, infer_is_local) { debug!("orphan_check_trait_ref: ty_is_local `{:?}`", input_ty); diff --git a/src/librustc/traits/error_reporting.rs b/src/librustc/traits/error_reporting.rs index e67c0ba8053d7..77c1137c6c3be 100644 --- a/src/librustc/traits/error_reporting.rs +++ b/src/librustc/traits/error_reporting.rs @@ -232,8 +232,8 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { if let Ok(..) = self.can_equate(&trait_self_ty, &impl_self_ty) { self_match_impls.push(def_id); - if trait_ref.substs.types.get_slice(TypeSpace).iter() - .zip(impl_trait_ref.substs.types.get_slice(TypeSpace)) + if trait_ref.substs.types.get_slice(TypeSpace)[1..].iter() + .zip(&impl_trait_ref.substs.types.get_slice(TypeSpace)[1..]) .all(|(u,v)| self.fuzzy_match_tys(u, v)) { fuzzy_match_impls.push(def_id); diff --git a/src/librustc/traits/object_safety.rs b/src/librustc/traits/object_safety.rs index ecfa7930d0294..11cf759859c62 100644 --- a/src/librustc/traits/object_safety.rs +++ b/src/librustc/traits/object_safety.rs @@ -20,7 +20,7 @@ use super::elaborate_predicates; use hir::def_id::DefId; -use ty::subst::{self, SelfSpace, TypeSpace}; +use ty::subst; use traits; use ty::{self, ToPolyTraitRef, Ty, TyCtxt, TypeFoldable}; use std::rc::Rc; @@ -146,10 +146,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { match predicate { ty::Predicate::Trait(ref data) => { // In the case of a trait predicate, we can skip the "self" type. - data.0.trait_ref.substs.types.get_slice(TypeSpace) - .iter() - .cloned() - .any(|t| t.has_self_ty()) + data.0.trait_ref.input_types()[1..].iter().any(|t| t.has_self_ty()) } ty::Predicate::Projection(..) | ty::Predicate::WellFormed(..) | @@ -325,7 +322,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { ty.maybe_walk(|ty| { match ty.sty { ty::TyParam(ref param_ty) => { - if param_ty.space == SelfSpace { + if param_ty.is_self() { error = true; } diff --git a/src/librustc/ty/context.rs b/src/librustc/ty/context.rs index 9356b408a51cb..c2daa81ca7dab 100644 --- a/src/librustc/ty/context.rs +++ b/src/librustc/ty/context.rs @@ -1353,7 +1353,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { } pub fn mk_self_type(self) -> Ty<'tcx> { - self.mk_param(subst::SelfSpace, 0, keywords::SelfType.name()) + self.mk_param(subst::TypeSpace, 0, keywords::SelfType.name()) } pub fn mk_param_from_def(self, def: &ty::TypeParameterDef) -> Ty<'tcx> { diff --git a/src/librustc/ty/error.rs b/src/librustc/ty/error.rs index 933746ebc2ad1..17f9b6c25995c 100644 --- a/src/librustc/ty/error.rs +++ b/src/librustc/ty/error.rs @@ -9,7 +9,6 @@ // except according to those terms. use hir::def_id::DefId; -use ty::subst; use infer::type_variable; use ty::{self, BoundRegion, Region, Ty, TyCtxt}; @@ -258,7 +257,7 @@ impl<'a, 'gcx, 'lcx, 'tcx> ty::TyS<'tcx> { ty::TyInfer(ty::FreshFloatTy(_)) => "skolemized floating-point type".to_string(), ty::TyProjection(_) => "associated type".to_string(), ty::TyParam(ref p) => { - if p.space == subst::SelfSpace { + if p.is_self() { "Self".to_string() } else { "type parameter".to_string() diff --git a/src/librustc/ty/flags.rs b/src/librustc/ty/flags.rs index 312b09cd27dfc..900e1841fb592 100644 --- a/src/librustc/ty/flags.rs +++ b/src/librustc/ty/flags.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use ty::subst::{self, Substs}; +use ty::subst::Substs; use ty::{self, Ty, TypeFlags, TypeFoldable}; pub struct FlagComputation { @@ -77,7 +77,7 @@ impl FlagComputation { &ty::TyParam(ref p) => { self.add_flags(TypeFlags::HAS_LOCAL_NAMES); - if p.space == subst::SelfSpace { + if p.is_self() { self.add_flags(TypeFlags::HAS_SELF); } else { self.add_flags(TypeFlags::HAS_PARAMS); diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs index 36784e4006461..96537904d36e8 100644 --- a/src/librustc/ty/mod.rs +++ b/src/librustc/ty/mod.rs @@ -1225,7 +1225,7 @@ impl<'tcx> TraitRef<'tcx> { } pub fn self_ty(&self) -> Ty<'tcx> { - *self.substs.types.get(subst::SelfSpace, 0) + *self.substs.types.get(subst::TypeSpace, 0) } pub fn input_types(&self) -> &[Ty<'tcx>] { diff --git a/src/librustc/ty/sty.rs b/src/librustc/ty/sty.rs index f31b844f04fe6..8786e2d16d22a 100644 --- a/src/librustc/ty/sty.rs +++ b/src/librustc/ty/sty.rs @@ -305,7 +305,7 @@ pub struct TraitObject<'tcx> { /// /// This would be represented by a trait-reference where the def-id is the /// def-id for the trait `Foo` and the substs defines `T` as parameter 0 in the -/// `SelfSpace` and `U` as parameter 0 in the `TypeSpace`. +/// `TypeSpace` and `U` as parameter 1 in the `TypeSpace`. /// /// Trait references also appear in object types like `Foo`, but in /// that case the `Self` parameter is absent from the substitutions. @@ -512,7 +512,7 @@ impl<'a, 'gcx, 'tcx> ParamTy { } pub fn for_self() -> ParamTy { - ParamTy::new(subst::SelfSpace, 0, keywords::SelfType.name()) + ParamTy::new(subst::TypeSpace, 0, keywords::SelfType.name()) } pub fn for_def(def: &ty::TypeParameterDef) -> ParamTy { @@ -524,7 +524,13 @@ impl<'a, 'gcx, 'tcx> ParamTy { } pub fn is_self(&self) -> bool { - self.space == subst::SelfSpace && self.idx == 0 + if self.name == keywords::SelfType.name() { + assert_eq!(self.space, subst::TypeSpace); + assert_eq!(self.idx, 0); + true + } else { + false + } } } @@ -954,7 +960,7 @@ impl<'a, 'gcx, 'tcx> TyS<'tcx> { pub fn is_self(&self) -> bool { match self.sty { - TyParam(ref p) => p.space == subst::SelfSpace, + TyParam(ref p) => p.is_self(), _ => false } } diff --git a/src/librustc/ty/subst.rs b/src/librustc/ty/subst.rs index 00537f9d6c5dc..2f95baa562589 100644 --- a/src/librustc/ty/subst.rs +++ b/src/librustc/ty/subst.rs @@ -47,8 +47,8 @@ impl<'a, 'gcx, 'tcx> Substs<'tcx> { r: Vec) -> &'tcx Substs<'tcx> { - Substs::new(tcx, VecPerParamSpace::new(vec![], vec![], t), - VecPerParamSpace::new(vec![], vec![], r)) + Substs::new(tcx, VecPerParamSpace::new(vec![], t), + VecPerParamSpace::new(vec![], r)) } pub fn new_type(tcx: TyCtxt<'a, 'gcx, 'tcx>, @@ -56,18 +56,19 @@ impl<'a, 'gcx, 'tcx> Substs<'tcx> { r: Vec) -> &'tcx Substs<'tcx> { - Substs::new(tcx, VecPerParamSpace::new(vec![], t, vec![]), - VecPerParamSpace::new(vec![], r, vec![])) + Substs::new(tcx, VecPerParamSpace::new(t, vec![]), + VecPerParamSpace::new(r, vec![])) } pub fn new_trait(tcx: TyCtxt<'a, 'gcx, 'tcx>, - t: Vec>, + mut t: Vec>, r: Vec, s: Ty<'tcx>) -> &'tcx Substs<'tcx> { - Substs::new(tcx, VecPerParamSpace::new(vec![s], t, vec![]), - VecPerParamSpace::new(vec![], r, vec![])) + t.insert(0, s); + Substs::new(tcx, VecPerParamSpace::new(t, vec![]), + VecPerParamSpace::new(r, vec![])) } pub fn empty(tcx: TyCtxt<'a, 'gcx, 'tcx>) -> &'tcx Substs<'tcx> { @@ -90,12 +91,10 @@ impl<'a, 'gcx, 'tcx> Substs<'tcx> { let defs = tcx.lookup_generics(def_id); let mut substs = Substs { types: VecPerParamSpace { - self_limit: 0, type_limit: 0, content: Vec::with_capacity(defs.types.content.len()) }, regions: VecPerParamSpace { - self_limit: 0, type_limit: 0, content: Vec::with_capacity(defs.regions.content.len()) } @@ -104,7 +103,6 @@ impl<'a, 'gcx, 'tcx> Substs<'tcx> { for &space in &ParamSpace::all() { for def in defs.regions.get_slice(space) { assert_eq!(def.space, space); - assert!(space != SelfSpace); let region = mk_region(def, &substs); substs.regions.content.push(region); @@ -120,11 +118,7 @@ impl<'a, 'gcx, 'tcx> Substs<'tcx> { let ty = mk_type(def, &substs); substs.types.content.push(ty); - if space == SelfSpace { - substs.types.self_limit += 1; - } - - if space <= TypeSpace { + if space == TypeSpace { substs.types.type_limit += 1; } } @@ -155,7 +149,6 @@ impl<'a, 'gcx, 'tcx> Substs<'tcx> { target_substs: &Substs<'tcx>) -> &'tcx Substs<'tcx> { let defs = tcx.lookup_generics(source_ancestor); - assert_eq!(self.types.len(SelfSpace), defs.types.len(SelfSpace)); assert_eq!(self.types.len(TypeSpace), defs.types.len(TypeSpace)); assert_eq!(target_substs.types.len(FnSpace), 0); assert_eq!(defs.types.len(FnSpace), 0); @@ -195,29 +188,26 @@ impl<'tcx> Decodable for &'tcx Substs<'tcx> { #[derive(PartialOrd, Ord, PartialEq, Eq, Copy, Clone, Hash, RustcEncodable, RustcDecodable, Debug)] pub enum ParamSpace { - SelfSpace, // Self parameter on a trait TypeSpace, // Type parameters attached to a type definition, trait, or impl FnSpace, // Type parameters attached to a method or fn } impl ParamSpace { - pub fn all() -> [ParamSpace; 3] { - [SelfSpace, TypeSpace, FnSpace] + pub fn all() -> [ParamSpace; 2] { + [TypeSpace, FnSpace] } pub fn to_uint(self) -> usize { match self { - SelfSpace => 0, - TypeSpace => 1, - FnSpace => 2, + TypeSpace => 0, + FnSpace => 1, } } pub fn from_uint(u: usize) -> ParamSpace { match u { - 0 => SelfSpace, - 1 => TypeSpace, - 2 => FnSpace, + 0 => TypeSpace, + 1 => FnSpace, _ => bug!("Invalid ParamSpace: {}", u) } } @@ -235,18 +225,15 @@ pub struct VecPerParamSpace { // Here is how the representation corresponds to the abstraction // i.e. the "abstraction function" AF: // - // AF(self) = (self.content[..self.self_limit], - // self.content[self.self_limit..self.type_limit], + // AF(self) = (self.content[..self.type_limit], // self.content[self.type_limit..]) - self_limit: usize, type_limit: usize, content: Vec, } impl fmt::Debug for VecPerParamSpace { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!(f, "[{:?};{:?};{:?}]", - self.get_slice(SelfSpace), + write!(f, "[{:?};{:?}]", self.get_slice(TypeSpace), self.get_slice(FnSpace)) } @@ -255,43 +242,34 @@ impl fmt::Debug for VecPerParamSpace { impl VecPerParamSpace { fn limits(&self, space: ParamSpace) -> (usize, usize) { match space { - SelfSpace => (0, self.self_limit), - TypeSpace => (self.self_limit, self.type_limit), + TypeSpace => (0, self.type_limit), FnSpace => (self.type_limit, self.content.len()), } } pub fn empty() -> VecPerParamSpace { VecPerParamSpace { - self_limit: 0, type_limit: 0, content: Vec::new() } } - /// `s` is the self space. /// `t` is the type space. /// `f` is the fn space. - pub fn new(s: Vec, t: Vec, f: Vec) -> VecPerParamSpace { - let self_limit = s.len(); - let type_limit = self_limit + t.len(); + pub fn new(t: Vec, f: Vec) -> VecPerParamSpace { + let type_limit = t.len(); - let mut content = s; - content.extend(t); + let mut content = t; content.extend(f); VecPerParamSpace { - self_limit: self_limit, type_limit: type_limit, content: content, } } - fn new_internal(content: Vec, self_limit: usize, type_limit: usize) - -> VecPerParamSpace - { + fn new_internal(content: Vec, type_limit: usize) -> VecPerParamSpace { VecPerParamSpace { - self_limit: self_limit, type_limit: type_limit, content: content, } @@ -336,18 +314,14 @@ impl VecPerParamSpace { pub fn map(&self, pred: P) -> VecPerParamSpace where P: FnMut(&T) -> U { let result = self.as_full_slice().iter().map(pred).collect(); - VecPerParamSpace::new_internal(result, - self.self_limit, - self.type_limit) + VecPerParamSpace::new_internal(result, self.type_limit) } pub fn map_enumerated(&self, pred: P) -> VecPerParamSpace where P: FnMut((ParamSpace, usize, &T)) -> U, { let result = self.iter_enumerated().map(pred).collect(); - VecPerParamSpace::new_internal(result, - self.self_limit, - self.type_limit) + VecPerParamSpace::new_internal(result, self.type_limit) } } @@ -639,8 +613,6 @@ impl<'a, 'gcx, 'tcx> ty::ExistentialTraitRef<'tcx> { -> ty::ExistentialTraitRef<'tcx> { let Substs { mut types, regions } = trait_ref.substs.clone(); - assert_eq!(types.self_limit, 1); - types.self_limit = 0; types.type_limit -= 1; types.content.remove(0); @@ -665,8 +637,6 @@ impl<'a, 'gcx, 'tcx> ty::PolyExistentialTraitRef<'tcx> { self.map_bound(|trait_ref| { let Substs { mut types, regions } = trait_ref.substs.clone(); - assert_eq!(types.self_limit, 0); - types.self_limit = 1; types.type_limit += 1; types.content.insert(0, self_ty); diff --git a/src/librustc/util/ppaux.rs b/src/librustc/util/ppaux.rs index cdbd307052364..800ad865208aa 100644 --- a/src/librustc/util/ppaux.rs +++ b/src/librustc/util/ppaux.rs @@ -62,35 +62,36 @@ pub enum Ns { Value } -fn number_of_supplied_defaults<'a, 'gcx, 'tcx>(tcx: TyCtxt<'a, 'gcx, 'tcx>, - substs: &subst::Substs, - space: subst::ParamSpace, - generics: &ty::Generics<'tcx>) - -> usize -{ - let ty_params = generics.types.get_slice(space); - let tps = substs.types.get_slice(space); - if ty_params.last().map_or(false, |def| def.default.is_some()) { - let substs = tcx.lift(&substs); - ty_params.iter().zip(tps).rev().take_while(|&(def, &actual)| { - substs.and_then(|substs| def.default.subst(tcx, substs)) - == Some(actual) - }).count() - } else { - 0 - } -} - pub fn parameterized(f: &mut fmt::Formatter, substs: &subst::Substs, did: DefId, ns: Ns, projections: &[ty::ProjectionPredicate]) -> fmt::Result { - let (fn_trait_kind, verbose, item_name, is_in_trait) = ty::tls::with(|tcx| { - let is_in_trait = ns == Ns::Value && tcx.trait_of_item(did).is_some(); - if is_in_trait { - write!(f, "<{} as ", substs.types.get(subst::SelfSpace, 0))?; + let mut verbose = false; + let mut num_supplied_defaults = 0; + let mut has_self = false; + let (fn_trait_kind, item_name) = ty::tls::with(|tcx| { + verbose = tcx.sess.verbose(); + let generics = tcx.lookup_generics(did); + if !verbose { + let ty_params = generics.types.get_slice(subst::TypeSpace); + if ty_params.last().map_or(false, |def| def.default.is_some()) { + if let Some(substs) = tcx.lift(&substs) { + let tps = substs.types.get_slice(subst::TypeSpace); + for (def, actual) in ty_params.iter().zip(tps).rev() { + if def.default.subst(tcx, substs) != Some(actual) { + break; + } + num_supplied_defaults += 1; + } + } + } + } + + has_self = generics.has_self; + if ns == Ns::Value && has_self { + write!(f, "<{} as ", substs.types.get(subst::TypeSpace, 0))?; } let (did, item_name) = if ns == Ns::Value { @@ -107,15 +108,12 @@ pub fn parameterized(f: &mut fmt::Formatter, (did, None) }; write!(f, "{}", tcx.item_path_str(did))?; - Ok((tcx.lang_items.fn_trait_kind(did), - tcx.sess.verbose(), - item_name, - is_in_trait)) + Ok((tcx.lang_items.fn_trait_kind(did), item_name)) })?; if !verbose && fn_trait_kind.is_some() && projections.len() == 1 { let projection_ty = projections[0].ty; - if let TyTuple(ref args) = substs.types.get(subst::TypeSpace, 0).sty { + if let TyTuple(ref args) = substs.types.get(subst::TypeSpace, 1).sty { return fn_sig(f, args, false, projection_ty); } } @@ -160,18 +158,9 @@ pub fn parameterized(f: &mut fmt::Formatter, print_regions(f, "<", substs.regions.get_slice(subst::TypeSpace))?; - let num_supplied_defaults = if verbose { - 0 - } else { - ty::tls::with(|tcx| { - let generics = tcx.lookup_generics(did); - number_of_supplied_defaults(tcx, substs, subst::TypeSpace, generics) - }) - }; - let tps = substs.types.get_slice(subst::TypeSpace); - for &ty in &tps[..tps.len() - num_supplied_defaults] { + for &ty in &tps[has_self as usize..tps.len() - num_supplied_defaults] { start_or_continue(f, "<", ", ")?; write!(f, "{}", ty)?; } @@ -189,7 +178,7 @@ pub fn parameterized(f: &mut fmt::Formatter, if ns == Ns::Value { empty.set(true); - if is_in_trait { + if has_self { write!(f, ">")?; } diff --git a/src/librustc_borrowck/borrowck/mir/elaborate_drops.rs b/src/librustc_borrowck/borrowck/mir/elaborate_drops.rs index df91ec2b98d5d..9f300b5b29ba8 100644 --- a/src/librustc_borrowck/borrowck/mir/elaborate_drops.rs +++ b/src/librustc_borrowck/borrowck/mir/elaborate_drops.rs @@ -16,7 +16,7 @@ use super::{drop_flag_effects_for_location, on_all_children_bits}; use super::{DropFlagState, MoveDataParamEnv}; use super::patch::MirPatch; use rustc::ty::{self, Ty, TyCtxt}; -use rustc::ty::subst::{Subst, Substs, VecPerParamSpace}; +use rustc::ty::subst::{Subst, Substs}; use rustc::mir::repr::*; use rustc::mir::transform::{Pass, MirPass, MirSource}; use rustc::middle::const_val::ConstVal; @@ -859,9 +859,7 @@ impl<'b, 'tcx> ElaborateDropsCtxt<'b, 'tcx> { let unit_temp = Lvalue::Temp(self.patch.new_temp(tcx.mk_nil())); let free_func = tcx.lang_items.require(lang_items::BoxFreeFnLangItem) .unwrap_or_else(|e| tcx.sess.fatal(&e)); - let substs = Substs::new(tcx, - VecPerParamSpace::new(vec![], vec![], vec![ty]), - VecPerParamSpace::new(vec![], vec![], vec![])); + let substs = Substs::new_fn(tcx, vec![ty], vec![]); let fty = tcx.lookup_item_type(free_func).ty.subst(tcx, substs); self.patch.new_block(BasicBlockData { diff --git a/src/librustc_metadata/astencode.rs b/src/librustc_metadata/astencode.rs index 1b00eee76f69b..1ef48e6d6565f 100644 --- a/src/librustc_metadata/astencode.rs +++ b/src/librustc_metadata/astencode.rs @@ -413,7 +413,7 @@ impl tr for Def { Def::AssociatedTy(trait_did, did) => Def::AssociatedTy(trait_did.tr(dcx), did.tr(dcx)), Def::PrimTy(p) => Def::PrimTy(p), - Def::TyParam(s, index, def_id, n) => Def::TyParam(s, index, def_id.tr(dcx), n), + Def::TyParam(did) => Def::TyParam(did.tr(dcx)), Def::Upvar(_, nid1, index, nid2) => { let nid1 = dcx.tr_id(nid1); let nid2 = dcx.tr_id(nid2); diff --git a/src/librustc_metadata/tydecode.rs b/src/librustc_metadata/tydecode.rs index 3f0fa9073aa36..82d050a1de9d7 100644 --- a/src/librustc_metadata/tydecode.rs +++ b/src/librustc_metadata/tydecode.rs @@ -131,15 +131,15 @@ impl<'a,'tcx> TyDecoder<'a,'tcx> { fn parse_vec_per_param_space(&mut self, mut f: F) -> VecPerParamSpace where F: FnMut(&mut TyDecoder<'a, 'tcx>) -> T, { - let (mut a, mut b, mut c) = (vec![], vec![], vec![]); - for r in &mut [&mut a, &mut b, &mut c] { + let (mut a, mut b) = (vec![], vec![]); + for r in &mut [&mut a, &mut b] { assert_eq!(self.next(), '['); while self.peek() != ']' { r.push(f(self)); } assert_eq!(self.next(), ']'); } - VecPerParamSpace::new(a, b, c) + VecPerParamSpace::new(a, b) } pub fn parse_substs(&mut self) -> &'tcx Substs<'tcx> { diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs index 962509be324de..65e14eee4bc2b 100644 --- a/src/librustc_resolve/lib.rs +++ b/src/librustc_resolve/lib.rs @@ -49,7 +49,6 @@ use rustc::lint; use rustc::hir::def::*; use rustc::hir::def_id::{CRATE_DEF_INDEX, DefId}; use rustc::ty; -use rustc::ty::subst::{ParamSpace, FnSpace, TypeSpace}; use rustc::hir::{Freevar, FreevarMap, TraitCandidate, TraitMap, GlobMap}; use rustc::util::nodemap::{NodeMap, NodeSet, FnvHashMap, FnvHashSet}; @@ -557,7 +556,7 @@ impl<'a> Visitor for Resolver<'a> { fn visit_foreign_item(&mut self, foreign_item: &ForeignItem) { let type_parameters = match foreign_item.node { ForeignItemKind::Fn(_, ref generics) => { - HasTypeParameters(generics, FnSpace, ItemRibKind) + HasTypeParameters(generics, ItemRibKind) } ForeignItemKind::Static(..) => NoTypeParameters, }; @@ -625,10 +624,6 @@ enum TypeParameters<'a, 'b> { HasTypeParameters(// Type parameters. &'b Generics, - // Identifies the things that these parameters - // were declared on (type, fn, etc) - ParamSpace, - // The kind of the rib used for type parameters. RibKind<'a>), } @@ -1613,12 +1608,9 @@ impl<'a> Resolver<'a> { match item.node { ItemKind::Enum(_, ref generics) | ItemKind::Ty(_, ref generics) | - ItemKind::Struct(_, ref generics) => { - self.with_type_parameter_rib(HasTypeParameters(generics, TypeSpace, ItemRibKind), - |this| visit::walk_item(this, item)); - } + ItemKind::Struct(_, ref generics) | ItemKind::Fn(_, _, _, _, ref generics, _) => { - self.with_type_parameter_rib(HasTypeParameters(generics, FnSpace, ItemRibKind), + self.with_type_parameter_rib(HasTypeParameters(generics, ItemRibKind), |this| visit::walk_item(this, item)); } @@ -1634,10 +1626,7 @@ impl<'a> Resolver<'a> { ItemKind::Trait(_, ref generics, ref bounds, ref trait_items) => { // Create a new rib for the trait-wide type parameters. - self.with_type_parameter_rib(HasTypeParameters(generics, - TypeSpace, - ItemRibKind), - |this| { + self.with_type_parameter_rib(HasTypeParameters(generics, ItemRibKind), |this| { let local_def_id = this.definitions.local_def_id(item.id); this.with_self_rib(Def::SelfTy(Some(local_def_id), None), |this| { this.visit_generics(generics); @@ -1660,7 +1649,6 @@ impl<'a> Resolver<'a> { TraitItemKind::Method(ref sig, _) => { let type_parameters = HasTypeParameters(&sig.generics, - FnSpace, MethodRibKind(!sig.decl.has_self())); this.with_type_parameter_rib(type_parameters, |this| { visit::walk_trait_item(this, trait_item) @@ -1729,10 +1717,10 @@ impl<'a> Resolver<'a> { where F: FnOnce(&mut Resolver) { match type_parameters { - HasTypeParameters(generics, space, rib_kind) => { + HasTypeParameters(generics, rib_kind) => { let mut function_type_rib = Rib::new(rib_kind); let mut seen_bindings = HashSet::new(); - for (index, type_parameter) in generics.ty_params.iter().enumerate() { + for type_parameter in &generics.ty_params { let name = type_parameter.ident.name; debug!("with_type_parameter_rib: {}", type_parameter.id); @@ -1745,7 +1733,7 @@ impl<'a> Resolver<'a> { // plain insert (no renaming) let def_id = self.definitions.local_def_id(type_parameter.id); - let def = Def::TyParam(space, index as u32, def_id, name); + let def = Def::TyParam(def_id); function_type_rib.bindings.insert(ast::Ident::with_empty_ctxt(name), def); self.record_def(type_parameter.id, PathResolution::new(def)); } @@ -1917,10 +1905,7 @@ impl<'a> Resolver<'a> { item_id: NodeId, impl_items: &[ImplItem]) { // If applicable, create a rib for the type parameters. - self.with_type_parameter_rib(HasTypeParameters(generics, - TypeSpace, - ItemRibKind), - |this| { + self.with_type_parameter_rib(HasTypeParameters(generics, ItemRibKind), |this| { // Resolve the type parameters. this.visit_generics(generics); @@ -1953,7 +1938,6 @@ impl<'a> Resolver<'a> { // specific type parameters. let type_parameters = HasTypeParameters(&sig.generics, - FnSpace, MethodRibKind(!sig.decl.has_self())); this.with_type_parameter_rib(type_parameters, |this| { visit::walk_impl_item(this, impl_item); diff --git a/src/librustc_save_analysis/lib.rs b/src/librustc_save_analysis/lib.rs index 6c9cf1a5625b2..db535e22f194d 100644 --- a/src/librustc_save_analysis/lib.rs +++ b/src/librustc_save_analysis/lib.rs @@ -490,7 +490,7 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> { Def::Enum(def_id) | Def::TyAlias(def_id) | Def::Trait(def_id) | - Def::TyParam(_, _, def_id, _) => { + Def::TyParam(def_id) => { Some(Data::TypeRefData(TypeRefData { span: sub_span.unwrap(), ref_id: Some(def_id), diff --git a/src/librustc_trans/partitioning.rs b/src/librustc_trans/partitioning.rs index f24ab0f65578c..1e90f273301ff 100644 --- a/src/librustc_trans/partitioning.rs +++ b/src/librustc_trans/partitioning.rs @@ -488,7 +488,7 @@ fn characteristic_def_id_of_trans_item<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, // DefId, we use the location of the impl after all. if tcx.trait_of_item(instance.def).is_some() { - let self_ty = *instance.substs.types.get(subst::SelfSpace, 0); + let self_ty = *instance.substs.types.get(subst::TypeSpace, 0); // This is an implementation of a trait method. return characteristic_def_id_of_type(self_ty).or(Some(instance.def)); } diff --git a/src/librustc_typeck/astconv.rs b/src/librustc_typeck/astconv.rs index 5655c7c8e7291..109cfd2abf6e5 100644 --- a/src/librustc_typeck/astconv.rs +++ b/src/librustc_typeck/astconv.rs @@ -55,7 +55,7 @@ use hir::def_id::DefId; use hir::print as pprust; use middle::resolve_lifetime as rl; use rustc::lint; -use rustc::ty::subst::{TypeSpace, SelfSpace, Subst, Substs}; +use rustc::ty::subst::{TypeSpace, Subst, Substs}; use rustc::traits; use rustc::ty::{self, Ty, TyCtxt, ToPredicate, TypeFoldable}; use rustc::ty::wf::object_region_bounds; @@ -455,6 +455,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o { // Check the number of type parameters supplied by the user. if let Some(num_provided) = num_types_provided { let ty_param_defs = decl_generics.types.get_slice(TypeSpace); + let ty_param_defs = &ty_param_defs[self_ty.is_some() as usize..]; check_type_argument_count(tcx, span, num_provided, ty_param_defs); } @@ -476,13 +477,16 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o { assert_eq!(def.space, TypeSpace); regions[def.index as usize] }, |def, substs| { - assert!(def.space == SelfSpace || def.space == TypeSpace); + assert!(def.space == TypeSpace); let i = def.index as usize; - if def.space == SelfSpace { - // Self, which must have been provided. - assert_eq!(i, 0); - self_ty.expect("Self type parameter missing") - } else if num_types_provided.map_or(false, |n| i < n) { + + // Handle Self first, so we can adjust the index to match the AST. + if let (0, Some(ty)) = (i, self_ty) { + return ty; + } + + let i = i - self_ty.is_some() as usize; + if num_types_provided.map_or(false, |n| i < n) { // A provided type parameter. match *parameters { hir::AngleBracketedParameters(ref data) => { @@ -1325,8 +1329,9 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o { Err(ErrorReported) => return (tcx.types.err, Def::Err), } } - (&ty::TyParam(_), Def::TyParam(_, _, param_did, param_name)) => { + (&ty::TyParam(_), Def::TyParam(param_did)) => { let param_node_id = tcx.map.as_local_node_id(param_did).unwrap(); + let param_name = tcx.type_parameter_def(param_node_id).name; match self.find_bound_for_assoc_item(param_node_id, param_name, assoc_name, @@ -1336,10 +1341,13 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o { } } _ => { - self.report_ambiguous_associated_type(span, - &ty.to_string(), - "Trait", - &assoc_name.as_str()); + // Don't print TyErr to the user. + if !ty.references_error() { + self.report_ambiguous_associated_type(span, + &ty.to_string(), + "Trait", + &assoc_name.as_str()); + } return (tcx.types.err, Def::Err); } }; @@ -1477,9 +1485,25 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o { did, base_segments.last().unwrap()) } - Def::TyParam(space, index, _, name) => { + Def::TyParam(did) => { tcx.prohibit_type_params(base_segments); - tcx.mk_param(space, index, name) + + let node_id = tcx.map.as_local_node_id(did).unwrap(); + let param = tcx.ty_param_defs.borrow().get(&node_id) + .map(ty::ParamTy::for_def); + if let Some(p) = param { + p.to_ty(tcx) + } else { + // Only while computing defaults of earlier type + // parameters can a type parameter be missing its def. + struct_span_err!(tcx.sess, span, E0128, + "type parameters with a default cannot use \ + forward declared identifiers") + .span_label(span, &format!("defaulted type parameters \ + cannot be forward declared")) + .emit(); + tcx.types.err + } } Def::SelfTy(_, Some(impl_id)) => { // Self in impl (we know the concrete type). diff --git a/src/librustc_typeck/check/closure.rs b/src/librustc_typeck/check/closure.rs index 8a007293e64ff..087549a2f1c4c 100644 --- a/src/librustc_typeck/check/closure.rs +++ b/src/librustc_typeck/check/closure.rs @@ -204,7 +204,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { return None; } - let arg_param_ty = *trait_ref.substs().types.get(subst::TypeSpace, 0); + let arg_param_ty = *trait_ref.substs().types.get(subst::TypeSpace, 1); let arg_param_ty = self.resolve_type_vars_if_possible(&arg_param_ty); debug!("deduce_sig_from_projection: arg_param_ty {:?}", arg_param_ty); diff --git a/src/librustc_typeck/check/method/mod.rs b/src/librustc_typeck/check/method/mod.rs index e5107af6ca04b..a9e08461fd28e 100644 --- a/src/librustc_typeck/check/method/mod.rs +++ b/src/librustc_typeck/check/method/mod.rs @@ -183,7 +183,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { let trait_def = self.tcx.lookup_trait_def(trait_def_id); if let Some(ref input_types) = opt_input_types { - assert_eq!(trait_def.generics.types.len(subst::TypeSpace), input_types.len()); + assert_eq!(trait_def.generics.types.len(subst::TypeSpace) - 1, input_types.len()); } assert_eq!(trait_def.generics.types.len(subst::FnSpace), 0); assert!(trait_def.generics.regions.is_empty()); @@ -192,10 +192,10 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { let substs = Substs::for_item(self.tcx, trait_def_id, |def, _| { self.region_var_for_def(span, def) }, |def, substs| { - if def.space == subst::SelfSpace { + if def.index == 0 { self_ty } else if let Some(ref input_types) = opt_input_types { - input_types[def.index as usize] + input_types[def.index as usize - 1] } else { self.type_var_for_def(span, def, substs) } diff --git a/src/librustc_typeck/check/method/probe.rs b/src/librustc_typeck/check/method/probe.rs index 448ea243655a8..044de179917b4 100644 --- a/src/librustc_typeck/check/method/probe.rs +++ b/src/librustc_typeck/check/method/probe.rs @@ -522,10 +522,6 @@ impl<'a, 'gcx, 'tcx> ProbeContext<'a, 'gcx, 'tcx> { trait_ref.substs.types.len(subst::TypeSpace)); assert_eq!(m.generics.regions.len(subst::TypeSpace), trait_ref.substs.regions.len(subst::TypeSpace)); - assert_eq!(m.generics.types.len(subst::SelfSpace), - trait_ref.substs.types.len(subst::SelfSpace)); - assert_eq!(m.generics.regions.len(subst::SelfSpace), - trait_ref.substs.regions.len(subst::SelfSpace)); } // Because this trait derives from a where-clause, it @@ -755,11 +751,9 @@ impl<'a, 'gcx, 'tcx> ProbeContext<'a, 'gcx, 'tcx> { let substs = Substs::for_item(self.tcx, trait_def_id, |def, _| { self.region_var_for_def(self.span, def) }, |def, substs| { - if def.space == subst::SelfSpace { - assert_eq!(def.index, 0); + if def.index == 0 { step.self_ty } else { - assert_eq!(def.space, subst::TypeSpace); self.type_var_for_def(self.span, def, substs) } }); diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index 700fb2ecf42dd..ae3378f41f936 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -4225,7 +4225,6 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { let substs = Substs::for_item(self.tcx, def.def_id(), |def, _| { let i = def.index as usize; let segment = match def.space { - subst::SelfSpace => None, subst::TypeSpace => type_segment, subst::FnSpace => fn_segment }; @@ -4241,9 +4240,8 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { self.region_var_for_def(span, def) } }, |def, substs| { - let i = def.index as usize; + let mut i = def.index as usize; let segment = match def.space { - subst::SelfSpace => None, subst::TypeSpace => type_segment, subst::FnSpace => fn_segment }; @@ -4252,18 +4250,24 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { Some(&hir::ParenthesizedParameters(_)) => bug!(), None => &[] }; + + // Handle Self first, so we can adjust the index to match the AST. + if scheme.generics.has_self && def.space == subst::TypeSpace { + if i == 0 { + return opt_self_ty.unwrap_or_else(|| { + self.type_var_for_def(span, def, substs) + }); + } + i -= 1; + } + let can_omit = def.space != subst::TypeSpace || !require_type_space; let default = if can_omit && types.len() == 0 { def.default } else { None }; - - if def.space == subst::SelfSpace && opt_self_ty.is_some() { - // Self, which has been provided. - assert_eq!(i, 0); - opt_self_ty.unwrap() - } else if let Some(ast_ty) = types.get(i) { + if let Some(ast_ty) = types.get(i) { // A provided type parameter. self.to_ty(ast_ty) } else if let Some(default) = default { @@ -4371,6 +4375,11 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { // Check provided type parameters. let type_defs = generics.types.get_slice(space); + let type_defs = if space == subst::TypeSpace { + &type_defs[generics.has_self as usize..] + } else { + type_defs + }; let required_len = type_defs.iter() .take_while(|d| d.default.is_none()) .count(); diff --git a/src/librustc_typeck/check/wfcheck.rs b/src/librustc_typeck/check/wfcheck.rs index 678c102a4de3b..f2076895f0873 100644 --- a/src/librustc_typeck/check/wfcheck.rs +++ b/src/librustc_typeck/check/wfcheck.rs @@ -14,13 +14,12 @@ use CrateCtxt; use hir::def_id::DefId; use middle::region::{CodeExtent}; use rustc::infer::TypeOrigin; -use rustc::ty::subst::{self, TypeSpace, FnSpace, ParamSpace, SelfSpace}; +use rustc::ty::subst; use rustc::traits; use rustc::ty::{self, Ty, TyCtxt}; use std::collections::HashSet; use syntax::ast; -use syntax::parse::token::keywords; use syntax_pos::Span; use errors::DiagnosticBuilder; @@ -461,7 +460,7 @@ impl<'ccx, 'gcx> CheckTypeWellFormedVisitor<'ccx, 'gcx> { variances.types .iter_enumerated() .filter(|&(_, _, &variance)| variance != ty::Bivariant) - .map(|(space, index, _)| self.param_ty(ast_generics, space, index)) + .map(|(_, index, _)| self.param_ty(ast_generics, index)) .map(|p| Parameter::Type(p)) .collect(); @@ -470,52 +469,34 @@ impl<'ccx, 'gcx> CheckTypeWellFormedVisitor<'ccx, 'gcx> { &mut constrained_parameters); for (space, index, _) in variances.types.iter_enumerated() { - let param_ty = self.param_ty(ast_generics, space, index); + assert_eq!(space, subst::TypeSpace); + + let param_ty = self.param_ty(ast_generics, index); if constrained_parameters.contains(&Parameter::Type(param_ty)) { continue; } - let span = self.ty_param_span(ast_generics, item, space, index); + let span = ast_generics.ty_params[index].span; self.report_bivariance(span, param_ty.name); } for (space, index, &variance) in variances.regions.iter_enumerated() { + assert_eq!(space, subst::TypeSpace); + if variance != ty::Bivariant { continue; } - assert_eq!(space, TypeSpace); let span = ast_generics.lifetimes[index].lifetime.span; let name = ast_generics.lifetimes[index].lifetime.name; self.report_bivariance(span, name); } } - fn param_ty(&self, - ast_generics: &hir::Generics, - space: ParamSpace, - index: usize) - -> ty::ParamTy - { - let name = match space { - TypeSpace => ast_generics.ty_params[index].name, - SelfSpace => keywords::SelfType.name(), - FnSpace => bug!("Fn space occupied?"), - }; - - ty::ParamTy { space: space, idx: index as u32, name: name } - } - - fn ty_param_span(&self, - ast_generics: &hir::Generics, - item: &hir::Item, - space: ParamSpace, - index: usize) - -> Span - { - match space { - TypeSpace => ast_generics.ty_params[index].span, - SelfSpace => item.span, - FnSpace => span_bug!(item.span, "Fn space occupied?"), + fn param_ty(&self, ast_generics: &hir::Generics, index: usize) -> ty::ParamTy { + ty::ParamTy { + space: subst::TypeSpace, + idx: index as u32, + name: ast_generics.ty_params[index].name } } diff --git a/src/librustc_typeck/coherence/mod.rs b/src/librustc_typeck/coherence/mod.rs index 485e744bf916e..17a84e98e61e2 100644 --- a/src/librustc_typeck/coherence/mod.rs +++ b/src/librustc_typeck/coherence/mod.rs @@ -386,7 +386,7 @@ impl<'a, 'gcx, 'tcx> CoherenceChecker<'a, 'gcx, 'tcx> { let source = tcx.lookup_item_type(impl_did).ty; let trait_ref = self.crate_context.tcx.impl_trait_ref(impl_did).unwrap(); - let target = *trait_ref.substs.types.get(subst::TypeSpace, 0); + let target = *trait_ref.substs.types.get(subst::TypeSpace, 1); debug!("check_implementations_of_coerce_unsized: {:?} -> {:?} (bound)", source, target); diff --git a/src/librustc_typeck/collect.rs b/src/librustc_typeck/collect.rs index 77723ea973341..8eef384f2cf9f 100644 --- a/src/librustc_typeck/collect.rs +++ b/src/librustc_typeck/collect.rs @@ -65,7 +65,7 @@ use middle::lang_items::SizedTraitLangItem; use middle::const_val::ConstVal; use rustc_const_eval::EvalHint::UncheckedExprHint; use rustc_const_eval::{eval_const_expr_partial, report_const_eval_err}; -use rustc::ty::subst::{Substs, FnSpace, ParamSpace, SelfSpace, TypeSpace, VecPerParamSpace}; +use rustc::ty::subst::{Substs, FnSpace, ParamSpace, TypeSpace, VecPerParamSpace}; use rustc::ty::{ToPredicate, ImplContainer, ImplOrTraitItemContainer, TraitContainer}; use rustc::ty::{self, ToPolyTraitRef, Ty, TyCtxt, TypeScheme}; use rustc::ty::{VariantKind}; @@ -85,7 +85,6 @@ use std::rc::Rc; use syntax::{abi, ast, attr}; use syntax::parse::token::keywords; -use syntax::ptr::P; use syntax_pos::Span; use rustc::hir::{self, intravisit, map as hir_map, print as pprust}; @@ -546,7 +545,7 @@ fn is_param<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, let path_res = tcx.expect_resolution(ast_ty.id); match path_res.base_def { Def::SelfTy(Some(def_id), None) | - Def::TyParam(_, _, def_id, _) if path_res.depth == 0 => { + Def::TyParam(def_id) if path_res.depth == 0 => { def_id == tcx.map.local_def_id(param_id) } _ => false @@ -1333,7 +1332,7 @@ fn convert_trait_predicates<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, it: &hir::Item) // add in the explicit where-clauses let mut trait_predicates = - ty_generic_predicates(ccx, TypeSpace, generics, &base_predicates); + ty_generic_predicates(ccx, TypeSpace, generics, &base_predicates, true); let assoc_predicates = predicates_for_associated_types(ccx, generics, @@ -1430,7 +1429,7 @@ fn generics_of_def_id<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, let parent = ccx.tcx.map.get_parent(param_id); let def = ty::TypeParameterDef { - space: SelfSpace, + space: TypeSpace, index: 0, name: keywords::SelfType.name(), def_id: tcx.map.local_def_id(param_id), @@ -1477,27 +1476,25 @@ fn generics_of_def_id<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, }).collect(); // Now create the real type parameters. - let types = ast_generics.ty_params.iter().enumerate().map(|(i, _)| { - get_or_create_type_parameter_def(ccx, ast_generics, space, i as u32, allow_defaults) + let types = ast_generics.ty_params.iter().enumerate().map(|(i, p)| { + let i = opt_self.is_some() as u32 + i as u32; + get_or_create_type_parameter_def(ccx, ast_generics, space, i, p, allow_defaults) }).collect(); let has_self = base_generics.has_self || opt_self.is_some(); let (regions, types) = match space { - SelfSpace => bug!(), TypeSpace => { assert_eq!(base_generics.regions.as_full_slice().len(), 0); assert_eq!(base_generics.types.as_full_slice().len(), 0); - (VecPerParamSpace::new(vec![], regions, vec![]), - VecPerParamSpace::new(opt_self.into_iter().collect(), types, vec![])) + (VecPerParamSpace::new(regions, vec![]), + VecPerParamSpace::new(opt_self.into_iter().chain(types).collect(), vec![])) } FnSpace => { assert_eq!(base_generics.regions.len(FnSpace), 0); assert_eq!(base_generics.types.len(FnSpace), 0); - (VecPerParamSpace::new(base_generics.regions.get_slice(SelfSpace).to_vec(), - base_generics.regions.get_slice(TypeSpace).to_vec(), + (VecPerParamSpace::new(base_generics.regions.get_slice(TypeSpace).to_vec(), regions), - VecPerParamSpace::new(base_generics.types.get_slice(SelfSpace).to_vec(), - base_generics.types.get_slice(TypeSpace).to_vec(), + VecPerParamSpace::new(base_generics.types.get_slice(TypeSpace).to_vec(), types)) } }; @@ -1674,7 +1671,7 @@ fn ty_generic_predicates_for_type_or_impl<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>, generics: &hir::Generics) -> ty::GenericPredicates<'tcx> { - ty_generic_predicates(ccx, TypeSpace, generics, &ty::GenericPredicates::empty()) + ty_generic_predicates(ccx, TypeSpace, generics, &ty::GenericPredicates::empty(), false) } fn ty_generic_predicates_for_fn<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>, @@ -1682,7 +1679,7 @@ fn ty_generic_predicates_for_fn<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>, base_predicates: &ty::GenericPredicates<'tcx>) -> ty::GenericPredicates<'tcx> { - ty_generic_predicates(ccx, FnSpace, generics, base_predicates) + ty_generic_predicates(ccx, FnSpace, generics, base_predicates, false) } // Add the Sized bound, unless the type parameter is marked as `?Sized`. @@ -1752,7 +1749,8 @@ fn early_bound_lifetimes_from_generics<'a, 'tcx, 'hir>( fn ty_generic_predicates<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>, space: ParamSpace, ast_generics: &hir::Generics, - base_predicates: &ty::GenericPredicates<'tcx>) + base_predicates: &ty::GenericPredicates<'tcx>, + has_self: bool) -> ty::GenericPredicates<'tcx> { let tcx = ccx.tcx; @@ -1761,7 +1759,7 @@ fn ty_generic_predicates<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>, // Collect the predicates that were written inline by the user on each // type parameter (e.g., ``). for (index, param) in ast_generics.ty_params.iter().enumerate() { - let index = index as u32; + let index = has_self as u32 + index as u32; let param_ty = ty::ParamTy::new(space, index, param.name).to_ty(ccx.tcx); let bounds = compute_bounds(&ccx.icx(&(base_predicates, ast_generics)), param_ty, @@ -1850,50 +1848,22 @@ fn ty_generic_predicates<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>, result } -fn convert_default_type_parameter<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, - path: &P, - space: ParamSpace, - index: u32) - -> Ty<'tcx> -{ - let ty = AstConv::ast_ty_to_ty(&ccx.icx(&()), &ExplicitRscope, &path); - - for leaf_ty in ty.walk() { - if let ty::TyParam(p) = leaf_ty.sty { - if p.space == space && p.idx >= index { - struct_span_err!(ccx.tcx.sess, path.span, E0128, - "type parameters with a default cannot use \ - forward declared identifiers") - .span_label(path.span, &format!("defaulted type parameters \ - cannot be forward declared")) - .emit(); - - return ccx.tcx.types.err - } - } - } - - ty -} - fn get_or_create_type_parameter_def<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>, ast_generics: &hir::Generics, space: ParamSpace, index: u32, + param: &hir::TyParam, allow_defaults: bool) -> ty::TypeParameterDef<'tcx> { - let param = &ast_generics.ty_params[index as usize]; - let tcx = ccx.tcx; match tcx.ty_param_defs.borrow().get(¶m.id) { Some(d) => { return d.clone(); } None => { } } - let default = param.default.as_ref().map( - |def| convert_default_type_parameter(ccx, def, space, index) - ); + let default = + param.default.as_ref().map(|def| ccx.icx(&()).to_ty(&ExplicitRscope, def)); let object_lifetime_default = compute_object_lifetime_default(ccx, param.id, @@ -1922,6 +1892,10 @@ fn get_or_create_type_parameter_def<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>, object_lifetime_default: object_lifetime_default, }; + if def.name == keywords::SelfType.name() { + span_bug!(param.span, "`Self` should not be the name of a regular parameter"); + } + tcx.ty_param_defs.borrow_mut().insert(param.id, def.clone()); debug!("get_or_create_type_parameter_def: def for type param: {:?}, {:?}", @@ -2153,7 +2127,7 @@ pub fn mk_item_substs<'gcx: 'tcx, 'tcx>(astconv: &AstConv<'gcx, 'tcx>, /// Checks that all the type parameters on an impl fn enforce_impl_params_are_constrained<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, - ast_generics: &hir::Generics, + generics: &hir::Generics, impl_predicates: &mut ty::GenericPredicates<'tcx>, impl_def_id: DefId) { @@ -2173,12 +2147,11 @@ fn enforce_impl_params_are_constrained<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, impl_trait_ref, &mut input_parameters); - for (index, ty_param) in ast_generics.ty_params.iter().enumerate() { - let param_ty = ty::ParamTy { space: TypeSpace, - idx: index as u32, - name: ty_param.name }; + let ty_generics = generics_of_def_id(ccx, impl_def_id); + for (ty_param, param) in ty_generics.types.as_full_slice().iter().zip(&generics.ty_params) { + let param_ty = ty::ParamTy::for_def(ty_param); if !input_parameters.contains(&ctp::Parameter::Type(param_ty)) { - report_unused_parameter(ccx, ty_param.span, "type", ¶m_ty.to_string()); + report_unused_parameter(ccx, param.span, "type", ¶m_ty.to_string()); } } } diff --git a/src/librustc_typeck/variance/constraints.rs b/src/librustc_typeck/variance/constraints.rs index 8c9b4beb79d84..2b88689ff1295 100644 --- a/src/librustc_typeck/variance/constraints.rs +++ b/src/librustc_typeck/variance/constraints.rs @@ -361,9 +361,7 @@ impl<'a, 'tcx> ConstraintContext<'a, 'tcx> { // All type parameters on enums and structs should be // in the TypeSpace. - assert!(item_type.generics.types.is_empty_in(subst::SelfSpace)); assert!(item_type.generics.types.is_empty_in(subst::FnSpace)); - assert!(item_type.generics.regions.is_empty_in(subst::SelfSpace)); assert!(item_type.generics.regions.is_empty_in(subst::FnSpace)); self.add_constraints_from_substs( @@ -394,14 +392,12 @@ impl<'a, 'tcx> ConstraintContext<'a, 'tcx> { } ty::TyTrait(ref data) => { - let poly_trait_ref = - data.principal.with_self_ty(self.tcx(), self.tcx().types.err); - // The type `Foo` is contravariant w/r/t `'a`: let contra = self.contravariant(variance); self.add_constraints_from_region(generics, data.region_bound, contra); - // Ignore the SelfSpace, it is erased. + let poly_trait_ref = + data.principal.with_self_ty(self.tcx(), self.tcx().types.err); self.add_constraints_from_trait_ref(generics, poly_trait_ref.0, variance); for projection in &data.projection_bounds { diff --git a/src/librustc_typeck/variance/solve.rs b/src/librustc_typeck/variance/solve.rs index 22edf219dff75..9048d892b09d2 100644 --- a/src/librustc_typeck/variance/solve.rs +++ b/src/librustc_typeck/variance/solve.rs @@ -110,8 +110,8 @@ impl<'a, 'tcx> SolveContext<'a, 'tcx> { while index < num_inferred { let item_id = inferred_infos[index].item_id; - let (mut rs, mut rt, mut rf) = (vec![], vec![], vec![]); - let (mut ts, mut tt, mut tf) = (vec![], vec![], vec![]); + let (mut rt, mut rf) = (vec![], vec![]); + let (mut tt, mut tf) = (vec![], vec![]); while index < num_inferred && inferred_infos[index].item_id == item_id { let info = &inferred_infos[index]; @@ -121,7 +121,6 @@ impl<'a, 'tcx> SolveContext<'a, 'tcx> { match info.kind { TypeParam => { let types = match info.space { - subst::SelfSpace => &mut ts, subst::TypeSpace => &mut tt, subst::FnSpace => &mut tf }; @@ -130,7 +129,6 @@ impl<'a, 'tcx> SolveContext<'a, 'tcx> { } RegionParam => { let regions = match info.space { - subst::SelfSpace => &mut rs, subst::TypeSpace => &mut rt, subst::FnSpace => &mut rf }; @@ -143,8 +141,8 @@ impl<'a, 'tcx> SolveContext<'a, 'tcx> { } let item_variances = ty::ItemVariances { - regions: subst::VecPerParamSpace::new(rs, rt, rf), - types: subst::VecPerParamSpace::new(ts, tt, tf) + regions: subst::VecPerParamSpace::new(rt, rf), + types: subst::VecPerParamSpace::new(tt, tf) }; debug!("item_id={} item_variances={:?}", diff --git a/src/librustc_typeck/variance/terms.rs b/src/librustc_typeck/variance/terms.rs index 72f8d9cb23ba8..9dc38bb195c14 100644 --- a/src/librustc_typeck/variance/terms.rs +++ b/src/librustc_typeck/variance/terms.rs @@ -21,7 +21,7 @@ use arena::TypedArena; use dep_graph::DepTrackingMapConfig; -use rustc::ty::subst::{ParamSpace, FnSpace, TypeSpace, SelfSpace}; +use rustc::ty::subst::{ParamSpace, FnSpace, TypeSpace}; use rustc::ty::{self, TyCtxt}; use rustc::ty::maps::ItemVariances; use std::fmt; @@ -164,16 +164,16 @@ impl<'a, 'tcx> TermsContext<'a, 'tcx> { let inferreds_on_entry = self.num_inferred(); - if has_self { - self.add_inferred(item_id, TypeParam, SelfSpace, 0, item_id); - } - for (i, p) in generics.lifetimes.iter().enumerate() { let id = p.lifetime.id; self.add_inferred(item_id, RegionParam, TypeSpace, i, id); } + if has_self { + self.add_inferred(item_id, TypeParam, TypeSpace, 0, item_id); + } for (i, p) in generics.ty_params.iter().enumerate() { + let i = has_self as usize + i; self.add_inferred(item_id, TypeParam, TypeSpace, i, p.id); } @@ -233,7 +233,7 @@ impl<'a, 'tcx> TermsContext<'a, 'tcx> { -> ty::Variance { match space { - SelfSpace | FnSpace => { + FnSpace => { ty::Bivariant } diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index f8a3a0af69752..6fae7ddc24a89 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -41,7 +41,7 @@ use rustc::hir::def::Def; use rustc::hir::def_id::{DefId, DefIndex, CRATE_DEF_INDEX}; use rustc::hir::fold::Folder; use rustc::hir::print as pprust; -use rustc::ty::subst::{self, ParamSpace, Substs, VecPerParamSpace}; +use rustc::ty::subst::{self, Substs, VecPerParamSpace}; use rustc::ty; use rustc::middle::stability; @@ -630,13 +630,14 @@ impl Clean for hir::TyParamBound { } } -fn external_path_params(cx: &DocContext, trait_did: Option, +fn external_path_params(cx: &DocContext, trait_did: Option, has_self: bool, bindings: Vec, substs: &Substs) -> PathParameters { let lifetimes = substs.regions.get_slice(subst::TypeSpace) .iter() .filter_map(|v| v.clean(cx)) .collect(); - let types = substs.types.get_slice(subst::TypeSpace).to_vec(); + let types = substs.types.get_slice(subst::TypeSpace); + let types = types[has_self as usize..].to_vec(); match (trait_did, cx.tcx_opt()) { // Attempt to sugar an external path like Fn<(A, B,), C> to Fn(A, B) -> C @@ -675,13 +676,13 @@ fn external_path_params(cx: &DocContext, trait_did: Option, // trait_did should be set to a trait's DefId if called on a TraitRef, in order to sugar // from Fn<(A, B,), C> to Fn(A, B) -> C -fn external_path(cx: &DocContext, name: &str, trait_did: Option, +fn external_path(cx: &DocContext, name: &str, trait_did: Option, has_self: bool, bindings: Vec, substs: &Substs) -> Path { Path { global: false, segments: vec![PathSegment { name: name.to_string(), - params: external_path_params(cx, trait_did, bindings, substs) + params: external_path_params(cx, trait_did, has_self, bindings, substs) }], } } @@ -696,16 +697,16 @@ impl Clean for ty::BuiltinBound { let (did, path) = match *self { ty::BoundSend => (tcx.lang_items.send_trait().unwrap(), - external_path(cx, "Send", None, vec![], empty)), + external_path(cx, "Send", None, false, vec![], empty)), ty::BoundSized => (tcx.lang_items.sized_trait().unwrap(), - external_path(cx, "Sized", None, vec![], empty)), + external_path(cx, "Sized", None, false, vec![], empty)), ty::BoundCopy => (tcx.lang_items.copy_trait().unwrap(), - external_path(cx, "Copy", None, vec![], empty)), + external_path(cx, "Copy", None, false, vec![], empty)), ty::BoundSync => (tcx.lang_items.sync_trait().unwrap(), - external_path(cx, "Sync", None, vec![], empty)), + external_path(cx, "Sync", None, false, vec![], empty)), }; inline::record_extern_fqn(cx, did, TypeTrait); TraitBound(PolyTrait { @@ -728,14 +729,14 @@ impl<'tcx> Clean for ty::TraitRef<'tcx> { }; inline::record_extern_fqn(cx, self.def_id, TypeTrait); let path = external_path(cx, &tcx.item_name(self.def_id).as_str(), - Some(self.def_id), vec![], self.substs); + Some(self.def_id), true, vec![], self.substs); debug!("ty::TraitRef\n substs.types(TypeSpace): {:?}\n", - self.substs.types.get_slice(ParamSpace::TypeSpace)); + &self.input_types()[1..]); // collect any late bound regions let mut late_bounds = vec![]; - for &ty_s in self.substs.types.get_slice(ParamSpace::TypeSpace) { + for &ty_s in &self.input_types()[1..] { if let ty::TyTuple(ts) = ty_s.sty { for &ty_s in ts { if let ty::TyRef(ref reg, _) = ty_s.sty { @@ -982,8 +983,13 @@ impl<'a, 'tcx> Clean for (&'a ty::Generics<'tcx>, // Bounds in the type_params and lifetimes fields are repeated in the // predicates field (see rustc_typeck::collect::ty_generics), so remove // them. - let stripped_typarams = gens.types.get_slice(space).iter().map(|tp| { - tp.clean(cx) + let stripped_typarams = gens.types.get_slice(space).iter().filter_map(|tp| { + if tp.name == keywords::SelfType.name() { + assert_eq!(tp.index, 0); + None + } else { + Some(tp.clean(cx)) + } }).collect::>(); let stripped_lifetimes = gens.regions.get_slice(space).iter().map(|rp| { let mut srp = rp.clone(); @@ -1820,7 +1826,7 @@ impl<'tcx> Clean for ty::Ty<'tcx> { }; inline::record_extern_fqn(cx, did, kind); let path = external_path(cx, &cx.tcx().item_name(did).as_str(), - None, vec![], substs); + None, false, vec![], substs); ResolvedPath { path: path, typarams: None, @@ -1847,7 +1853,7 @@ impl<'tcx> Clean for ty::Ty<'tcx> { } let path = external_path(cx, &cx.tcx().item_name(did).as_str(), - Some(did), bindings, obj.principal.0.substs); + Some(did), false, bindings, obj.principal.0.substs); ResolvedPath { path: path, typarams: Some(typarams), diff --git a/src/test/compile-fail/issue-26548.rs b/src/test/compile-fail/issue-26548.rs index b6d5e5458ff08..2591d7bcbaef4 100644 --- a/src/test/compile-fail/issue-26548.rs +++ b/src/test/compile-fail/issue-26548.rs @@ -8,15 +8,13 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// error-pattern: overflow representing the type `S` +// error-pattern: overflow representing the type -#![feature(rustc_attrs)] trait Mirror { type It: ?Sized; } impl Mirror for T { type It = Self; } struct S(Option<::It>); -#[rustc_no_mir] // FIXME #27840 MIR tries to represent `std::option::Option` first. fn main() { let _s = S(None); } diff --git a/src/test/compile-fail/issue-26812.rs b/src/test/compile-fail/issue-26812.rs index 060a66846d36f..1dd008810788b 100644 --- a/src/test/compile-fail/issue-26812.rs +++ b/src/test/compile-fail/issue-26812.rs @@ -10,5 +10,7 @@ #![feature(default_type_parameter_fallback)] -fn avg(_: T) {} //~ ERROR associated type `Item` not found for `T` +fn avg(_: T) {} +//~^ ERROR type parameters with a default cannot use forward declared identifiers + fn main() {} diff --git a/src/test/compile-fail/variance-associated-types.rs b/src/test/compile-fail/variance-associated-types.rs index a3456b0628b35..9aa4d29c4ecf7 100644 --- a/src/test/compile-fail/variance-associated-types.rs +++ b/src/test/compile-fail/variance-associated-types.rs @@ -20,12 +20,12 @@ trait Trait<'a> { } #[rustc_variance] -struct Foo<'a, T : Trait<'a>> { //~ ERROR ItemVariances(types=[[];[+];[]], regions=[[];[-];[]]) +struct Foo<'a, T : Trait<'a>> { //~ ERROR ItemVariances(types=[[+];[]], regions=[[-];[]]) field: (T, &'a ()) } #[rustc_variance] -struct Bar<'a, T : Trait<'a>> { //~ ERROR ItemVariances(types=[[];[o];[]], regions=[[];[o];[]]) +struct Bar<'a, T : Trait<'a>> { //~ ERROR ItemVariances(types=[[o];[]], regions=[[o];[]]) field: >::Type } diff --git a/src/test/compile-fail/variance-object-types.rs b/src/test/compile-fail/variance-object-types.rs index ffd829c38d3d3..3c8b27f965a61 100644 --- a/src/test/compile-fail/variance-object-types.rs +++ b/src/test/compile-fail/variance-object-types.rs @@ -18,7 +18,7 @@ use std::cell::Cell; // For better or worse, associated types are invariant, and hence we // get an invariant result for `'a`. #[rustc_variance] -struct Foo<'a> { //~ ERROR regions=[[];[o];[]] +struct Foo<'a> { //~ ERROR regions=[[o];[]] x: Box &'a i32 + 'static> } diff --git a/src/test/compile-fail/variance-region-bounds.rs b/src/test/compile-fail/variance-region-bounds.rs index 6dd791f2558a7..ae5a8674f446c 100644 --- a/src/test/compile-fail/variance-region-bounds.rs +++ b/src/test/compile-fail/variance-region-bounds.rs @@ -13,11 +13,11 @@ #![feature(rustc_attrs)] #[rustc_variance] -trait Foo: 'static { //~ ERROR types=[[o];[];[]] +trait Foo: 'static { //~ ERROR types=[[o];[]] } #[rustc_variance] -trait Bar { //~ ERROR types=[[o];[o];[]] +trait Bar { //~ ERROR types=[[o, o];[]] fn do_it(&self) where T: 'static; } diff --git a/src/test/compile-fail/variance-regions-direct.rs b/src/test/compile-fail/variance-regions-direct.rs index 0c712d3fa0377..93d3d2773149e 100644 --- a/src/test/compile-fail/variance-regions-direct.rs +++ b/src/test/compile-fail/variance-regions-direct.rs @@ -16,7 +16,7 @@ // Regions that just appear in normal spots are contravariant: #[rustc_variance] -struct Test2<'a, 'b, 'c> { //~ ERROR regions=[[];[-, -, -];[]] +struct Test2<'a, 'b, 'c> { //~ ERROR regions=[[-, -, -];[]] x: &'a isize, y: &'b [isize], c: &'c str @@ -25,7 +25,7 @@ struct Test2<'a, 'b, 'c> { //~ ERROR regions=[[];[-, -, -];[]] // Those same annotations in function arguments become covariant: #[rustc_variance] -struct Test3<'a, 'b, 'c> { //~ ERROR regions=[[];[+, +, +];[]] +struct Test3<'a, 'b, 'c> { //~ ERROR regions=[[+, +, +];[]] x: extern "Rust" fn(&'a isize), y: extern "Rust" fn(&'b [isize]), c: extern "Rust" fn(&'c str), @@ -34,7 +34,7 @@ struct Test3<'a, 'b, 'c> { //~ ERROR regions=[[];[+, +, +];[]] // Mutability induces invariance: #[rustc_variance] -struct Test4<'a, 'b:'a> { //~ ERROR regions=[[];[-, o];[]] +struct Test4<'a, 'b:'a> { //~ ERROR regions=[[-, o];[]] x: &'a mut &'b isize, } @@ -42,7 +42,7 @@ struct Test4<'a, 'b:'a> { //~ ERROR regions=[[];[-, o];[]] // contravariant context: #[rustc_variance] -struct Test5<'a, 'b:'a> { //~ ERROR regions=[[];[+, o];[]] +struct Test5<'a, 'b:'a> { //~ ERROR regions=[[+, o];[]] x: extern "Rust" fn(&'a mut &'b isize), } @@ -52,14 +52,14 @@ struct Test5<'a, 'b:'a> { //~ ERROR regions=[[];[+, o];[]] // argument list occurs in an invariant context. #[rustc_variance] -struct Test6<'a, 'b:'a> { //~ ERROR regions=[[];[-, o];[]] +struct Test6<'a, 'b:'a> { //~ ERROR regions=[[-, o];[]] x: &'a mut extern "Rust" fn(&'b isize), } // No uses at all is bivariant: #[rustc_variance] -struct Test7<'a> { //~ ERROR regions=[[];[*];[]] +struct Test7<'a> { //~ ERROR regions=[[*];[]] //~^ ERROR parameter `'a` is never used x: isize } @@ -67,7 +67,7 @@ struct Test7<'a> { //~ ERROR regions=[[];[*];[]] // Try enums too. #[rustc_variance] -enum Test8<'a, 'b, 'c:'b> { //~ ERROR regions=[[];[+, -, o];[]] +enum Test8<'a, 'b, 'c:'b> { //~ ERROR regions=[[+, -, o];[]] Test8A(extern "Rust" fn(&'a isize)), Test8B(&'b [isize]), Test8C(&'b mut &'c str), diff --git a/src/test/compile-fail/variance-regions-indirect.rs b/src/test/compile-fail/variance-regions-indirect.rs index 9bdb05e188dcf..eeb981b707e31 100644 --- a/src/test/compile-fail/variance-regions-indirect.rs +++ b/src/test/compile-fail/variance-regions-indirect.rs @@ -15,7 +15,7 @@ #![feature(rustc_attrs)] #[rustc_variance] -enum Base<'a, 'b, 'c:'b, 'd> { //~ ERROR regions=[[];[+, -, o, *];[]] +enum Base<'a, 'b, 'c:'b, 'd> { //~ ERROR regions=[[+, -, o, *];[]] //~^ ERROR parameter `'d` is never used Test8A(extern "Rust" fn(&'a isize)), Test8B(&'b [isize]), @@ -23,25 +23,25 @@ enum Base<'a, 'b, 'c:'b, 'd> { //~ ERROR regions=[[];[+, -, o, *];[]] } #[rustc_variance] -struct Derived1<'w, 'x:'y, 'y, 'z> { //~ ERROR regions=[[];[*, o, -, +];[]] +struct Derived1<'w, 'x:'y, 'y, 'z> { //~ ERROR regions=[[*, o, -, +];[]] //~^ ERROR parameter `'w` is never used f: Base<'z, 'y, 'x, 'w> } #[rustc_variance] // Combine - and + to yield o -struct Derived2<'a, 'b:'a, 'c> { //~ ERROR regions=[[];[o, o, *];[]] +struct Derived2<'a, 'b:'a, 'c> { //~ ERROR regions=[[o, o, *];[]] //~^ ERROR parameter `'c` is never used f: Base<'a, 'a, 'b, 'c> } #[rustc_variance] // Combine + and o to yield o (just pay attention to 'a here) -struct Derived3<'a:'b, 'b, 'c> { //~ ERROR regions=[[];[o, -, *];[]] +struct Derived3<'a:'b, 'b, 'c> { //~ ERROR regions=[[o, -, *];[]] //~^ ERROR parameter `'c` is never used f: Base<'a, 'b, 'a, 'c> } #[rustc_variance] // Combine + and * to yield + (just pay attention to 'a here) -struct Derived4<'a, 'b, 'c:'b> { //~ ERROR regions=[[];[+, -, o];[]] +struct Derived4<'a, 'b, 'c:'b> { //~ ERROR regions=[[+, -, o];[]] f: Base<'a, 'b, 'c, 'a> } diff --git a/src/test/compile-fail/variance-trait-bounds.rs b/src/test/compile-fail/variance-trait-bounds.rs index 528be50c0b850..860dd6deefd5b 100644 --- a/src/test/compile-fail/variance-trait-bounds.rs +++ b/src/test/compile-fail/variance-trait-bounds.rs @@ -15,48 +15,48 @@ // influence variance. #[rustc_variance] -trait Getter { //~ ERROR types=[[o];[o];[]] +trait Getter { //~ ERROR types=[[o, o];[]] fn get(&self) -> T; } #[rustc_variance] -trait Setter { //~ ERROR types=[[o];[o];[]] +trait Setter { //~ ERROR types=[[o, o];[]] fn get(&self, T); } #[rustc_variance] -struct TestStruct> { //~ ERROR types=[[];[+, +];[]] +struct TestStruct> { //~ ERROR types=[[+, +];[]] t: T, u: U } #[rustc_variance] -enum TestEnum> {//~ ERROR types=[[];[*, +];[]] +enum TestEnum> {//~ ERROR types=[[*, +];[]] //~^ ERROR parameter `U` is never used Foo(T) } #[rustc_variance] -trait TestTrait> { //~ ERROR types=[[o];[o, o];[]] +trait TestTrait> { //~ ERROR types=[[o, o, o];[]] fn getter(&self, u: U) -> T; } #[rustc_variance] -trait TestTrait2 : Getter { //~ ERROR types=[[o];[o];[]] +trait TestTrait2 : Getter { //~ ERROR types=[[o, o];[]] } #[rustc_variance] -trait TestTrait3 { //~ ERROR types=[[o];[o];[]] +trait TestTrait3 { //~ ERROR types=[[o, o];[]] fn getter>(&self); } #[rustc_variance] -struct TestContraStruct> { //~ ERROR types=[[];[*, +];[]] +struct TestContraStruct> { //~ ERROR types=[[*, +];[]] //~^ ERROR parameter `U` is never used t: T } #[rustc_variance] -struct TestBox+Setter> { //~ ERROR types=[[];[*, +];[]] +struct TestBox+Setter> { //~ ERROR types=[[*, +];[]] //~^ ERROR parameter `U` is never used t: T } diff --git a/src/test/compile-fail/variance-trait-object-bound.rs b/src/test/compile-fail/variance-trait-object-bound.rs index b58540204986a..b37007a6d34e4 100644 --- a/src/test/compile-fail/variance-trait-object-bound.rs +++ b/src/test/compile-fail/variance-trait-object-bound.rs @@ -21,7 +21,7 @@ use std::mem; trait T { fn foo(&self); } #[rustc_variance] -struct TOption<'a> { //~ ERROR regions=[[];[-];[]] +struct TOption<'a> { //~ ERROR regions=[[-];[]] v: Option>, } diff --git a/src/test/compile-fail/variance-types-bounds.rs b/src/test/compile-fail/variance-types-bounds.rs index d110c402d3b77..8eb96814fa8f0 100644 --- a/src/test/compile-fail/variance-types-bounds.rs +++ b/src/test/compile-fail/variance-types-bounds.rs @@ -14,46 +14,46 @@ #![feature(rustc_attrs)] #[rustc_variance] -struct TestImm { //~ ERROR types=[[];[+, +];[]] +struct TestImm { //~ ERROR types=[[+, +];[]] x: A, y: B, } #[rustc_variance] -struct TestMut { //~ ERROR types=[[];[+, o];[]] +struct TestMut { //~ ERROR types=[[+, o];[]] x: A, y: &'static mut B, } #[rustc_variance] -struct TestIndirect { //~ ERROR types=[[];[+, o];[]] +struct TestIndirect { //~ ERROR types=[[+, o];[]] m: TestMut } #[rustc_variance] -struct TestIndirect2 { //~ ERROR types=[[];[o, o];[]] +struct TestIndirect2 { //~ ERROR types=[[o, o];[]] n: TestMut, m: TestMut } #[rustc_variance] -trait Getter { //~ ERROR types=[[o];[o];[]] +trait Getter { //~ ERROR types=[[o, o];[]] fn get(&self) -> A; } #[rustc_variance] -trait Setter { //~ ERROR types=[[o];[o];[]] +trait Setter { //~ ERROR types=[[o, o];[]] fn set(&mut self, a: A); } #[rustc_variance] -trait GetterSetter { //~ ERROR types=[[o];[o];[]] +trait GetterSetter { //~ ERROR types=[[o, o];[]] fn get(&self) -> A; fn set(&mut self, a: A); } #[rustc_variance] -trait GetterInTypeBound { //~ ERROR types=[[o];[o];[]] +trait GetterInTypeBound { //~ ERROR types=[[o, o];[]] // Here, the use of `A` in the method bound *does* affect // variance. Think of it as if the method requested a dictionary // for `T:Getter`. Since this dictionary is an input, it is @@ -63,12 +63,12 @@ trait GetterInTypeBound { //~ ERROR types=[[o];[o];[]] } #[rustc_variance] -trait SetterInTypeBound { //~ ERROR types=[[o];[o];[]] +trait SetterInTypeBound { //~ ERROR types=[[o, o];[]] fn do_it>(&self); } #[rustc_variance] -struct TestObject { //~ ERROR types=[[];[o, o];[]] +struct TestObject { //~ ERROR types=[[o, o];[]] n: Box+Send>, m: Box+Send>, } diff --git a/src/test/compile-fail/variance-types.rs b/src/test/compile-fail/variance-types.rs index 8c1a544334c2a..791b56caea02b 100644 --- a/src/test/compile-fail/variance-types.rs +++ b/src/test/compile-fail/variance-types.rs @@ -17,32 +17,32 @@ use std::cell::Cell; // not considered bivariant. #[rustc_variance] -struct InvariantMut<'a,A:'a,B:'a> { //~ ERROR types=[[];[o, o];[]], regions=[[];[-];[]] +struct InvariantMut<'a,A:'a,B:'a> { //~ ERROR types=[[o, o];[]], regions=[[-];[]] t: &'a mut (A,B) } #[rustc_variance] -struct InvariantCell { //~ ERROR types=[[];[o];[]] +struct InvariantCell { //~ ERROR types=[[o];[]] t: Cell } #[rustc_variance] -struct InvariantIndirect { //~ ERROR types=[[];[o];[]] +struct InvariantIndirect { //~ ERROR types=[[o];[]] t: InvariantCell } #[rustc_variance] -struct Covariant { //~ ERROR types=[[];[+];[]] +struct Covariant { //~ ERROR types=[[+];[]] t: A, u: fn() -> A } #[rustc_variance] -struct Contravariant { //~ ERROR types=[[];[-];[]] +struct Contravariant { //~ ERROR types=[[-];[]] t: fn(A) } #[rustc_variance] -enum Enum { //~ ERROR types=[[];[+, -, o];[]] +enum Enum { //~ ERROR types=[[+, -, o];[]] Foo(Covariant), Bar(Contravariant), Zed(Covariant,Contravariant) From 3e74e5bffe14ead921646d41bab436f8e6a69d33 Mon Sep 17 00:00:00 2001 From: Eduard Burtescu Date: Wed, 10 Aug 2016 20:39:09 +0300 Subject: [PATCH 10/12] rustc: split Generics of a method from its parent Generics. --- src/librustc/infer/error_reporting.rs | 3 +- src/librustc/traits/error_reporting.rs | 12 +- src/librustc/traits/object_safety.rs | 3 +- src/librustc/ty/mod.rs | 29 +---- src/librustc/ty/structural_impls.rs | 14 --- src/librustc/ty/subst.rs | 71 +++++++----- src/librustc/util/ppaux.rs | 10 +- src/librustc_metadata/encoder.rs | 6 +- src/librustc_metadata/tydecode.rs | 24 +++- src/librustc_metadata/tyencode.rs | 19 +++- src/librustc_trans/base.rs | 4 +- src/librustc_trans/collector.rs | 15 ++- src/librustc_trans/debuginfo/mod.rs | 17 ++- src/librustc_typeck/astconv.rs | 5 +- src/librustc_typeck/check/compare_method.rs | 10 +- src/librustc_typeck/check/intrinsic.rs | 4 +- src/librustc_typeck/check/method/confirm.rs | 2 +- src/librustc_typeck/check/method/mod.rs | 8 +- src/librustc_typeck/check/method/probe.rs | 21 ++-- src/librustc_typeck/check/mod.rs | 116 +++++++++++--------- src/librustc_typeck/check/wfcheck.rs | 6 +- src/librustc_typeck/collect.rs | 94 ++++++++-------- src/librustc_typeck/variance/constraints.rs | 26 ++--- src/librustdoc/clean/inline.rs | 21 ++-- src/librustdoc/clean/mod.rs | 14 +-- 25 files changed, 290 insertions(+), 264 deletions(-) diff --git a/src/librustc/infer/error_reporting.rs b/src/librustc/infer/error_reporting.rs index 21fccd2c6132d..9a6375719c1bc 100644 --- a/src/librustc/infer/error_reporting.rs +++ b/src/librustc/infer/error_reporting.rs @@ -82,7 +82,6 @@ use hir::def::Def; use hir::def_id::DefId; use infer::{self, TypeOrigin}; use middle::region; -use ty::subst; use ty::{self, TyCtxt, TypeFoldable}; use ty::{Region, ReFree}; use ty::error::TypeError; @@ -1369,7 +1368,7 @@ impl<'a, 'gcx, 'tcx> Rebuilder<'a, 'gcx, 'tcx> { let generics = self.tcx.lookup_generics(did); let expected = - generics.regions.len(subst::TypeSpace) as u32; + generics.regions.len() as u32; let lifetimes = path.segments.last().unwrap().parameters.lifetimes(); let mut insert = Vec::new(); diff --git a/src/librustc/traits/error_reporting.rs b/src/librustc/traits/error_reporting.rs index 77c1137c6c3be..77d7d5115efbc 100644 --- a/src/librustc/traits/error_reporting.rs +++ b/src/librustc/traits/error_reporting.rs @@ -271,14 +271,10 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { let def = self.tcx.lookup_trait_def(trait_ref.def_id); let trait_str = def.trait_ref.to_string(); if let Some(ref istring) = item.value_str() { - let mut generic_map = def.generics.types.iter_enumerated() - .map(|(param, i, gen)| { - (gen.name.as_str().to_string(), - trait_ref.substs.types.get(param, i) - .to_string()) - }).collect::>(); - generic_map.insert("Self".to_string(), - trait_ref.self_ty().to_string()); + let generic_map = def.generics.types.iter().map(|param| { + (param.name.as_str().to_string(), + trait_ref.substs.type_for_def(param).to_string()) + }).collect::>(); let parser = Parser::new(&istring); let mut errored = false; let err: String = parser.filter_map(|p| { diff --git a/src/librustc/traits/object_safety.rs b/src/librustc/traits/object_safety.rs index 11cf759859c62..25d2df8fdedb3 100644 --- a/src/librustc/traits/object_safety.rs +++ b/src/librustc/traits/object_safety.rs @@ -20,7 +20,6 @@ use super::elaborate_predicates; use hir::def_id::DefId; -use ty::subst; use traits; use ty::{self, ToPolyTraitRef, Ty, TyCtxt, TypeFoldable}; use std::rc::Rc; @@ -266,7 +265,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { } // We can't monomorphize things like `fn foo(...)`. - if !method.generics.types.is_empty_in(subst::FnSpace) { + if !method.generics.types.is_empty() { return Some(MethodViolationCode::Generic); } diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs index 96537904d36e8..689f2ad02c94c 100644 --- a/src/librustc/ty/mod.rs +++ b/src/librustc/ty/mod.rs @@ -757,33 +757,14 @@ impl RegionParameterDef { /// with an item or method. Analogous to hir::Generics. #[derive(Clone, Debug)] pub struct Generics<'tcx> { - pub types: VecPerParamSpace>, - pub regions: VecPerParamSpace, + pub parent: Option, + pub parent_regions: u32, + pub parent_types: u32, + pub regions: Vec, + pub types: Vec>, pub has_self: bool, } -impl<'tcx> Generics<'tcx> { - pub fn empty() -> Generics<'tcx> { - Generics { - types: VecPerParamSpace::empty(), - regions: VecPerParamSpace::empty(), - has_self: false, - } - } - - pub fn is_empty(&self) -> bool { - self.types.is_empty() && self.regions.is_empty() - } - - pub fn has_type_params(&self, space: subst::ParamSpace) -> bool { - !self.types.is_empty_in(space) - } - - pub fn has_region_params(&self, space: subst::ParamSpace) -> bool { - !self.regions.is_empty_in(space) - } -} - /// Bounds on generics. #[derive(Clone)] pub struct GenericPredicates<'tcx> { diff --git a/src/librustc/ty/structural_impls.rs b/src/librustc/ty/structural_impls.rs index 9021b0587a013..248d5d9062d59 100644 --- a/src/librustc/ty/structural_impls.rs +++ b/src/librustc/ty/structural_impls.rs @@ -832,20 +832,6 @@ impl<'tcx> TypeFoldable<'tcx> for ty::RegionParameterDef { } } -impl<'tcx> TypeFoldable<'tcx> for ty::Generics<'tcx> { - fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) -> Self { - ty::Generics { - types: self.types.fold_with(folder), - regions: self.regions.fold_with(folder), - has_self: self.has_self - } - } - - fn super_visit_with>(&self, visitor: &mut V) -> bool { - self.types.visit_with(visitor) || self.regions.visit_with(visitor) - } -} - impl<'tcx> TypeFoldable<'tcx> for ty::GenericPredicates<'tcx> { fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) -> Self { ty::GenericPredicates { diff --git a/src/librustc/ty/subst.rs b/src/librustc/ty/subst.rs index 2f95baa562589..594d15ad5f734 100644 --- a/src/librustc/ty/subst.rs +++ b/src/librustc/ty/subst.rs @@ -89,42 +89,55 @@ impl<'a, 'gcx, 'tcx> Substs<'tcx> { where FR: FnMut(&ty::RegionParameterDef, &Substs<'tcx>) -> ty::Region, FT: FnMut(&ty::TypeParameterDef<'tcx>, &Substs<'tcx>) -> Ty<'tcx> { let defs = tcx.lookup_generics(def_id); + let num_regions = defs.parent_regions as usize + defs.regions.len(); + let num_types = defs.parent_types as usize + defs.types.len(); let mut substs = Substs { - types: VecPerParamSpace { + regions: VecPerParamSpace { type_limit: 0, - content: Vec::with_capacity(defs.types.content.len()) + content: Vec::with_capacity(num_regions) }, - regions: VecPerParamSpace { + types: VecPerParamSpace { type_limit: 0, - content: Vec::with_capacity(defs.regions.content.len()) + content: Vec::with_capacity(num_types) } }; - for &space in &ParamSpace::all() { - for def in defs.regions.get_slice(space) { - assert_eq!(def.space, space); - - let region = mk_region(def, &substs); - substs.regions.content.push(region); + substs.fill_item(tcx, defs, &mut mk_region, &mut mk_type); - if space == TypeSpace { - substs.regions.type_limit += 1; - } - } + Substs::new(tcx, substs.types, substs.regions) + } - for def in defs.types.get_slice(space) { - assert_eq!(def.space, space); + fn fill_item(&mut self, + tcx: TyCtxt<'a, 'gcx, 'tcx>, + defs: &ty::Generics<'tcx>, + mk_region: &mut FR, + mk_type: &mut FT) + where FR: FnMut(&ty::RegionParameterDef, &Substs<'tcx>) -> ty::Region, + FT: FnMut(&ty::TypeParameterDef<'tcx>, &Substs<'tcx>) -> Ty<'tcx> { + if let Some(def_id) = defs.parent { + let parent_defs = tcx.lookup_generics(def_id); + self.fill_item(tcx, parent_defs, mk_region, mk_type); + } - let ty = mk_type(def, &substs); - substs.types.content.push(ty); + for def in &defs.regions { + let region = mk_region(def, self); + self.regions.content.push(region); - if space == TypeSpace { - substs.types.type_limit += 1; - } + if def.space == TypeSpace { + self.regions.type_limit += 1; + assert_eq!(self.regions.content.len(), self.regions.type_limit); } } - Substs::new(tcx, substs.types, substs.regions) + for def in &defs.types { + let ty = mk_type(def, self); + self.types.content.push(ty); + + if def.space == TypeSpace { + self.types.type_limit += 1; + assert_eq!(self.types.content.len(), self.types.type_limit); + } + } } pub fn is_noop(&self) -> bool { @@ -149,16 +162,14 @@ impl<'a, 'gcx, 'tcx> Substs<'tcx> { target_substs: &Substs<'tcx>) -> &'tcx Substs<'tcx> { let defs = tcx.lookup_generics(source_ancestor); - assert_eq!(self.types.len(TypeSpace), defs.types.len(TypeSpace)); + assert_eq!(self.types.len(TypeSpace), defs.types.len()); assert_eq!(target_substs.types.len(FnSpace), 0); - assert_eq!(defs.types.len(FnSpace), 0); - assert_eq!(self.regions.len(TypeSpace), defs.regions.len(TypeSpace)); + assert_eq!(self.regions.len(TypeSpace), defs.regions.len()); assert_eq!(target_substs.regions.len(FnSpace), 0); - assert_eq!(defs.regions.len(FnSpace), 0); let Substs { mut types, mut regions } = target_substs.clone(); - types.content.extend(&self.types.as_full_slice()[defs.types.content.len()..]); - regions.content.extend(&self.regions.as_full_slice()[defs.regions.content.len()..]); + types.content.extend(&self.types.as_full_slice()[defs.types.len()..]); + regions.content.extend(&self.regions.as_full_slice()[defs.regions.len()..]); Substs::new(tcx, types, regions) } } @@ -597,8 +608,8 @@ impl<'a, 'gcx, 'tcx> ty::TraitRef<'tcx> { -> ty::TraitRef<'tcx> { let Substs { mut types, mut regions } = substs.clone(); let defs = tcx.lookup_generics(trait_id); - types.content.truncate(defs.types.type_limit); - regions.content.truncate(defs.regions.type_limit); + types.content.truncate(defs.types.len()); + regions.content.truncate(defs.regions.len()); ty::TraitRef { def_id: trait_id, diff --git a/src/librustc/util/ppaux.rs b/src/librustc/util/ppaux.rs index 800ad865208aa..a62ee37613e50 100644 --- a/src/librustc/util/ppaux.rs +++ b/src/librustc/util/ppaux.rs @@ -73,13 +73,15 @@ pub fn parameterized(f: &mut fmt::Formatter, let mut has_self = false; let (fn_trait_kind, item_name) = ty::tls::with(|tcx| { verbose = tcx.sess.verbose(); - let generics = tcx.lookup_generics(did); + let mut generics = tcx.lookup_generics(did); + if let Some(def_id) = generics.parent { + generics = tcx.lookup_generics(def_id); + } if !verbose { - let ty_params = generics.types.get_slice(subst::TypeSpace); - if ty_params.last().map_or(false, |def| def.default.is_some()) { + if generics.types.last().map_or(false, |def| def.default.is_some()) { if let Some(substs) = tcx.lift(&substs) { let tps = substs.types.get_slice(subst::TypeSpace); - for (def, actual) in ty_params.iter().zip(tps).rev() { + for (def, actual) in generics.types.iter().zip(tps).rev() { if def.default.subst(tcx, substs) != Some(actual) { break; } diff --git a/src/librustc_metadata/encoder.rs b/src/librustc_metadata/encoder.rs index 1e74b3c1ef48f..0cde9b48d6f88 100644 --- a/src/librustc_metadata/encoder.rs +++ b/src/librustc_metadata/encoder.rs @@ -620,9 +620,9 @@ fn encode_info_for_method<'a, 'tcx>(ecx: &EncodeContext<'a, 'tcx>, if let Some(impl_item) = impl_item_opt { if let hir::ImplItemKind::Method(ref sig, _) = impl_item.node { encode_attributes(rbml_w, &impl_item.attrs); - let scheme = ecx.tcx.lookup_item_type(m.def_id); - let any_types = !scheme.generics.types.is_empty(); - let needs_inline = any_types || is_default_impl || + let generics = ecx.tcx.lookup_generics(m.def_id); + let types = generics.parent_types as usize + generics.types.len(); + let needs_inline = types > 0 || is_default_impl || attr::requests_inline(&impl_item.attrs); if needs_inline || sig.constness == hir::Constness::Const { encode_inlined_item(ecx, diff --git a/src/librustc_metadata/tydecode.rs b/src/librustc_metadata/tydecode.rs index 82d050a1de9d7..e8e3679a60ca2 100644 --- a/src/librustc_metadata/tydecode.rs +++ b/src/librustc_metadata/tydecode.rs @@ -149,9 +149,29 @@ impl<'a,'tcx> TyDecoder<'a,'tcx> { } pub fn parse_generics(&mut self) -> &'tcx ty::Generics<'tcx> { - let regions = self.parse_vec_per_param_space(|this| this.parse_region_param_def()); - let types = self.parse_vec_per_param_space(|this| this.parse_type_param_def()); + let parent = self.parse_opt(|this| this.parse_def()); + let parent_regions = self.parse_u32(); + assert_eq!(self.next(), '|'); + let parent_types = self.parse_u32(); + + let mut regions = vec![]; + assert_eq!(self.next(), '['); + while self.peek() != ']' { + regions.push(self.parse_region_param_def()); + } + assert_eq!(self.next(), ']'); + + let mut types = vec![]; + assert_eq!(self.next(), '['); + while self.peek() != ']' { + types.push(self.parse_type_param_def()); + } + assert_eq!(self.next(), ']'); + self.tcx.alloc_generics(ty::Generics { + parent: parent, + parent_regions: parent_regions, + parent_types: parent_types, regions: regions, types: types, has_self: self.next() == 'S' diff --git a/src/librustc_metadata/tyencode.rs b/src/librustc_metadata/tyencode.rs index 130d15485829a..27907596ca788 100644 --- a/src/librustc_metadata/tyencode.rs +++ b/src/librustc_metadata/tyencode.rs @@ -274,10 +274,21 @@ pub fn enc_substs<'a, 'tcx>(w: &mut Cursor>, cx: &ctxt<'a, 'tcx>, pub fn enc_generics<'a, 'tcx>(w: &mut Cursor>, cx: &ctxt<'a, 'tcx>, generics: &ty::Generics<'tcx>) { - enc_vec_per_param_space(w, cx, &generics.regions, - |w, cx, r| enc_region_param_def(w, cx, r)); - enc_vec_per_param_space(w, cx, &generics.types, - |w, cx, ty| enc_type_param_def(w, cx, ty)); + enc_opt(w, generics.parent, |w, def_id| { + write!(w, "{}|", (cx.ds)(cx.tcx, def_id)); + }); + write!(w, "{}|{}[", + generics.parent_regions, + generics.parent_types); + + for r in &generics.regions { + enc_region_param_def(w, cx, r) + } + write!(w, "]["); + for t in &generics.types { + enc_type_param_def(w, cx, t); + } + write!(w, "]"); if generics.has_self { write!(w, "S"); diff --git a/src/librustc_trans/base.rs b/src/librustc_trans/base.rs index ee5d1d11fa0a6..f190fbeb6feb9 100644 --- a/src/librustc_trans/base.rs +++ b/src/librustc_trans/base.rs @@ -2470,8 +2470,8 @@ pub fn filter_reachable_ids(tcx: TyCtxt, reachable: NodeSet) -> NodeSet { hir_map::NodeImplItem(&hir::ImplItem { node: hir::ImplItemKind::Method(..), .. }) => { let def_id = tcx.map.local_def_id(id); - let scheme = tcx.lookup_item_type(def_id); - scheme.generics.types.is_empty() + let generics = tcx.lookup_generics(def_id); + generics.parent_types == 0 && generics.types.is_empty() } _ => false diff --git a/src/librustc_trans/collector.rs b/src/librustc_trans/collector.rs index 82c86928783bc..76910304eebb0 100644 --- a/src/librustc_trans/collector.rs +++ b/src/librustc_trans/collector.rs @@ -195,7 +195,7 @@ use rustc::hir::map as hir_map; use rustc::hir::def_id::DefId; use rustc::middle::lang_items::{ExchangeFreeFnLangItem, ExchangeMallocFnLangItem}; use rustc::traits; -use rustc::ty::subst::{self, Substs, Subst}; +use rustc::ty::subst::{Substs, Subst}; use rustc::ty::{self, TypeFoldable, TyCtxt}; use rustc::ty::adjustment::CustomCoerceUnsized; use rustc::mir::repr as mir; @@ -1219,17 +1219,16 @@ fn create_trans_items_for_default_impls<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id_to_string(tcx, impl_def_id)); if let Some(trait_ref) = tcx.impl_trait_ref(impl_def_id) { - let default_impls = tcx.provided_trait_methods(trait_ref.def_id); let callee_substs = tcx.erase_regions(&trait_ref.substs); let overridden_methods: FnvHashSet<_> = items.iter() .map(|item| item.name) .collect(); - for default_impl in default_impls { - if overridden_methods.contains(&default_impl.name) { + for method in tcx.provided_trait_methods(trait_ref.def_id) { + if overridden_methods.contains(&method.name) { continue; } - if default_impl.generics.has_type_params(subst::FnSpace) { + if !method.generics.types.is_empty() { continue; } @@ -1242,7 +1241,7 @@ fn create_trans_items_for_default_impls<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, callee_substs, impl_def_id, impl_substs, - default_impl.name); + method.name); assert!(mth.is_provided); @@ -1251,10 +1250,10 @@ fn create_trans_items_for_default_impls<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, continue; } - if can_have_local_instance(tcx, default_impl.def_id) { + if can_have_local_instance(tcx, method.def_id) { let empty_substs = tcx.erase_regions(&mth.substs); let item = create_fn_trans_item(tcx, - default_impl.def_id, + method.def_id, callee_substs, empty_substs); output.push(item); diff --git a/src/librustc_trans/debuginfo/mod.rs b/src/librustc_trans/debuginfo/mod.rs index 963cc09e1ab95..684628e9a40fb 100644 --- a/src/librustc_trans/debuginfo/mod.rs +++ b/src/librustc_trans/debuginfo/mod.rs @@ -381,10 +381,11 @@ pub fn create_function_debug_context<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, // Again, only create type information if full debuginfo is enabled let template_params: Vec<_> = if cx.sess().opts.debuginfo == FullDebugInfo { - generics.types.as_full_slice().iter().enumerate().map(|(i, param)| { - let actual_type = cx.tcx().normalize_associated_type(&actual_types[i]); + let names = get_type_parameter_names(cx, generics); + actual_types.iter().zip(names).map(|(ty, name)| { + let actual_type = cx.tcx().normalize_associated_type(ty); let actual_type_metadata = type_metadata(cx, actual_type, syntax_pos::DUMMY_SP); - let name = CString::new(param.name.as_str().as_bytes()).unwrap(); + let name = CString::new(name.as_str().as_bytes()).unwrap(); unsafe { llvm::LLVMRustDIBuilderCreateTemplateTypeParameter( DIB(cx), @@ -403,6 +404,16 @@ pub fn create_function_debug_context<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, return create_DIArray(DIB(cx), &template_params[..]); } + fn get_type_parameter_names<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, + generics: &ty::Generics<'tcx>) + -> Vec { + let mut names = generics.parent.map_or(vec![], |def_id| { + get_type_parameter_names(cx, cx.tcx().lookup_generics(def_id)) + }); + names.extend(generics.types.iter().map(|param| param.name)); + names + } + fn get_containing_scope_and_span<'ccx, 'tcx>(cx: &CrateContext<'ccx, 'tcx>, instance: Instance<'tcx>) -> (DIScope, Span) { diff --git a/src/librustc_typeck/astconv.rs b/src/librustc_typeck/astconv.rs index 109cfd2abf6e5..a452b55a7d33d 100644 --- a/src/librustc_typeck/astconv.rs +++ b/src/librustc_typeck/astconv.rs @@ -429,7 +429,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o { bug!("ErrorReported returned, but no errors reports?") } }; - let expected_num_region_params = decl_generics.regions.len(TypeSpace); + let expected_num_region_params = decl_generics.regions.len(); let supplied_num_region_params = lifetimes.len(); let regions = if expected_num_region_params == supplied_num_region_params { lifetimes.iter().map(|l| ast_region_to_region(tcx, l)).collect() @@ -454,8 +454,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o { // Check the number of type parameters supplied by the user. if let Some(num_provided) = num_types_provided { - let ty_param_defs = decl_generics.types.get_slice(TypeSpace); - let ty_param_defs = &ty_param_defs[self_ty.is_some() as usize..]; + let ty_param_defs = &decl_generics.types[self_ty.is_some() as usize..]; check_type_argument_count(tcx, span, num_provided, ty_param_defs); } diff --git a/src/librustc_typeck/check/compare_method.rs b/src/librustc_typeck/check/compare_method.rs index 3cb528eba63e0..5bfe58e78f112 100644 --- a/src/librustc_typeck/check/compare_method.rs +++ b/src/librustc_typeck/check/compare_method.rs @@ -13,7 +13,7 @@ use rustc::infer::{self, InferOk, TypeOrigin}; use rustc::ty; use rustc::traits::{self, Reveal}; use rustc::ty::error::ExpectedFound; -use rustc::ty::subst::{self, Subst, Substs}; +use rustc::ty::subst::{Subst, Substs}; use rustc::hir::map::Node; use rustc::hir::{ImplItemKind, TraitItem_}; @@ -95,8 +95,8 @@ pub fn compare_impl_method<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, } } - let num_impl_m_type_params = impl_m.generics.types.len(subst::FnSpace); - let num_trait_m_type_params = trait_m.generics.types.len(subst::FnSpace); + let num_impl_m_type_params = impl_m.generics.types.len(); + let num_trait_m_type_params = trait_m.generics.types.len(); if num_impl_m_type_params != num_trait_m_type_params { span_err!(tcx.sess, impl_m_span, E0049, "method `{}` has {} type parameter{} \ @@ -389,8 +389,8 @@ pub fn compare_impl_method<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, -> bool { - let trait_params = trait_generics.regions.get_slice(subst::FnSpace); - let impl_params = impl_generics.regions.get_slice(subst::FnSpace); + let trait_params = &trait_generics.regions[..]; + let impl_params = &impl_generics.regions[..]; debug!("check_region_bounds_on_impl_method: \ trait_generics={:?} \ diff --git a/src/librustc_typeck/check/intrinsic.rs b/src/librustc_typeck/check/intrinsic.rs index bfedb4fa6e1a0..b2af51c12e6bb 100644 --- a/src/librustc_typeck/check/intrinsic.rs +++ b/src/librustc_typeck/check/intrinsic.rs @@ -49,7 +49,7 @@ fn equate_intrinsic_type<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, variadic: false, }), })); - let i_n_tps = i_ty.generics.types.len(subst::FnSpace); + let i_n_tps = i_ty.generics.types.len(); if i_n_tps != n_tps { struct_span_err!(tcx.sess, it.span, E0094, "intrinsic has wrong number of type \ @@ -321,7 +321,7 @@ pub fn check_platform_intrinsic_type(ccx: &CrateCtxt, let tcx = ccx.tcx; let i_ty = tcx.lookup_item_type(tcx.map.local_def_id(it.id)); - let i_n_tps = i_ty.generics.types.len(subst::FnSpace); + let i_n_tps = i_ty.generics.types.len(); let name = it.name.as_str(); let (n_tps, inputs, output) = match &*name { diff --git a/src/librustc_typeck/check/method/confirm.rs b/src/librustc_typeck/check/method/confirm.rs index c071fce98965f..8aa4ad56aea88 100644 --- a/src/librustc_typeck/check/method/confirm.rs +++ b/src/librustc_typeck/check/method/confirm.rs @@ -308,7 +308,7 @@ impl<'a, 'gcx, 'tcx> ConfirmContext<'a, 'gcx, 'tcx> { // variables. let num_supplied_types = supplied_method_types.len(); let method = pick.item.as_opt_method().unwrap(); - let num_method_types = method.generics.types.len(subst::FnSpace); + let num_method_types = method.generics.types.len(); if num_supplied_types > 0 && num_supplied_types != num_method_types { if num_method_types == 0 { diff --git a/src/librustc_typeck/check/method/mod.rs b/src/librustc_typeck/check/method/mod.rs index a9e08461fd28e..b057ad3150b51 100644 --- a/src/librustc_typeck/check/method/mod.rs +++ b/src/librustc_typeck/check/method/mod.rs @@ -183,15 +183,15 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { let trait_def = self.tcx.lookup_trait_def(trait_def_id); if let Some(ref input_types) = opt_input_types { - assert_eq!(trait_def.generics.types.len(subst::TypeSpace) - 1, input_types.len()); + assert_eq!(trait_def.generics.types.len() - 1, input_types.len()); } - assert_eq!(trait_def.generics.types.len(subst::FnSpace), 0); assert!(trait_def.generics.regions.is_empty()); // Construct a trait-reference `self_ty : Trait` let substs = Substs::for_item(self.tcx, trait_def_id, |def, _| { self.region_var_for_def(span, def) }, |def, substs| { + assert_eq!(def.space, subst::TypeSpace); if def.index == 0 { self_ty } else if let Some(ref input_types) = opt_input_types { @@ -221,8 +221,8 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { let tcx = self.tcx; let method_item = self.trait_item(trait_def_id, m_name).unwrap(); let method_ty = method_item.as_opt_method().unwrap(); - assert_eq!(method_ty.generics.types.len(subst::FnSpace), 0); - assert_eq!(method_ty.generics.regions.len(subst::FnSpace), 0); + assert_eq!(method_ty.generics.types.len(), 0); + assert_eq!(method_ty.generics.regions.len(), 0); debug!("lookup_in_trait_adjusted: method_item={:?} method_ty={:?}", method_item, method_ty); diff --git a/src/librustc_typeck/check/method/probe.rs b/src/librustc_typeck/check/method/probe.rs index 044de179917b4..c52bb36911a2a 100644 --- a/src/librustc_typeck/check/method/probe.rs +++ b/src/librustc_typeck/check/method/probe.rs @@ -518,9 +518,9 @@ impl<'a, 'gcx, 'tcx> ProbeContext<'a, 'gcx, 'tcx> { trait_ref, trait_ref.substs, m); - assert_eq!(m.generics.types.len(subst::TypeSpace), + assert_eq!(m.generics.parent_types as usize, trait_ref.substs.types.len(subst::TypeSpace)); - assert_eq!(m.generics.regions.len(subst::TypeSpace), + assert_eq!(m.generics.parent_regions as usize, trait_ref.substs.regions.len(subst::TypeSpace)); } @@ -1232,8 +1232,7 @@ impl<'a, 'gcx, 'tcx> ProbeContext<'a, 'gcx, 'tcx> { let xform_self_ty = method.fty.sig.input(0); let xform_self_ty = self.erase_late_bound_regions(&xform_self_ty); - if method.generics.types.is_empty_in(subst::FnSpace) && - method.generics.regions.is_empty_in(subst::FnSpace) { + if method.generics.types.is_empty() && method.generics.regions.is_empty() { xform_self_ty.subst(self.tcx, substs) } else { let substs = Substs::for_item(self.tcx, method.def_id, |def, _| { @@ -1260,17 +1259,13 @@ impl<'a, 'gcx, 'tcx> ProbeContext<'a, 'gcx, 'tcx> { impl_def_id: DefId) -> (Ty<'tcx>, &'tcx Substs<'tcx>) { - let impl_pty = self.tcx.lookup_item_type(impl_def_id); + let impl_ty = self.tcx.lookup_item_type(impl_def_id).ty; - let type_vars = - impl_pty.generics.types.map( - |_| self.next_ty_var()); + let substs = Substs::for_item(self.tcx, impl_def_id, + |_, _| ty::ReErased, + |_, _| self.next_ty_var()); - let region_placeholders = - impl_pty.generics.regions.map( - |_| ty::ReErased); // see erase_late_bound_regions() for an expl of why 'erased - - (impl_pty.ty, Substs::new(self.tcx, type_vars, region_placeholders)) + (impl_ty, substs) } /// Replace late-bound-regions bound by `value` with `'static` using diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index ae3378f41f936..d699bafed9a05 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -881,8 +881,7 @@ fn check_on_unimplemented<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, // `{Self}` is allowed Position::ArgumentNamed(s) if s == "Self" => (), // So is `{A}` if A is a type parameter - Position::ArgumentNamed(s) => match types.as_full_slice() - .iter().find(|t| { + Position::ArgumentNamed(s) => match types.iter().find(|t| { t.name.as_str() == s }) { Some(_) => (), @@ -1693,7 +1692,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { let mut ty = self.tcx.lookup_item_type(did).ty; if ty.is_fn() { // Tuple variants have fn type even in type namespace, extract true variant type from it - ty = self.tcx.no_late_bound_regions(&type_scheme.ty.fn_ret()).unwrap(); + ty = self.tcx.no_late_bound_regions(&ty.fn_ret()).unwrap(); } let type_predicates = self.tcx.lookup_predicates(did); let substs = AstConv::ast_path_substs_for_ty(self, self, @@ -3222,13 +3221,13 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { self.set_tainted_by_errors(); return None; } - Def::Variant(..) | Def::Struct(..) => { - Some(self.tcx.expect_variant_def(def)) + Def::Variant(type_did, _) | Def::Struct(type_did) => { + Some((type_did, self.tcx.expect_variant_def(def))) } - Def::TyAlias(did) | Def::AssociatedTy(_, did) => { + Def::TyAlias(did) => { if let Some(&ty::TyStruct(adt, _)) = self.tcx.opt_lookup_item_type(did) .map(|scheme| &scheme.ty.sty) { - Some(adt.struct_variant()) + Some((did, adt.struct_variant())) } else { None } @@ -3236,14 +3235,14 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { _ => None }; - if let Some(variant) = variant { + if let Some((def_id, variant)) = variant { if variant.kind == ty::VariantKind::Tuple && !self.tcx.sess.features.borrow().relaxed_adts { emit_feature_err(&self.tcx.sess.parse_sess.span_diagnostic, "relaxed_adts", span, GateIssue::Language, "tuple structs and variants in struct patterns are unstable"); } - let ty = self.instantiate_type_path(def.def_id(), path, node_id); + let ty = self.instantiate_type_path(def_id, path, node_id); Some((variant, ty)) } else { struct_span_err!(self.tcx.sess, path.span, E0071, @@ -4122,25 +4121,29 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { let mut fn_segment = None; match def { // Case 1 and 1b. Reference to a *type* or *enum variant*. - Def::SelfTy(..) | - Def::Struct(..) | - Def::Variant(..) | - Def::Enum(..) | - Def::TyAlias(..) | - Def::AssociatedTy(..) | - Def::Trait(..) | - Def::PrimTy(..) | - Def::TyParam(..) => { + Def::Struct(def_id) | + Def::Variant(_, def_id) | + Def::Enum(def_id) | + Def::TyAlias(def_id) | + Def::AssociatedTy(_, def_id) | + Def::Trait(def_id) => { // Everything but the final segment should have no // parameters at all. - type_segment = segments.last(); + let mut generics = self.tcx.lookup_generics(def_id); + if let Some(def_id) = generics.parent { + // Variant and struct constructors use the + // generics of their parent type definition. + generics = self.tcx.lookup_generics(def_id); + } + type_segment = Some((segments.last().unwrap(), generics)); } // Case 2. Reference to a top-level value. - Def::Fn(..) | - Def::Const(..) | - Def::Static(..) => { - fn_segment = segments.last(); + Def::Fn(def_id) | + Def::Const(def_id) | + Def::Static(def_id, _) => { + fn_segment = Some((segments.last().unwrap(), + self.tcx.lookup_generics(def_id))); } // Case 3. Reference to a method or associated const. @@ -4154,14 +4157,16 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { ty::ImplContainer(_) => {} } + let generics = self.tcx.lookup_generics(def_id); if segments.len() >= 2 { - type_segment = Some(&segments[segments.len() - 2]); + let parent_generics = self.tcx.lookup_generics(generics.parent.unwrap()); + type_segment = Some((&segments[segments.len() - 2], parent_generics)); } else { // `::assoc` will end up here, and so can `T::assoc`. let self_ty = opt_self_ty.expect("UFCS sugared assoc missing Self"); ufcs_associated = Some((container, self_ty)); } - fn_segment = segments.last(); + fn_segment = Some((segments.last().unwrap(), generics)); } // Other cases. Various nonsense that really shouldn't show up @@ -4169,6 +4174,9 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { // elsewhere. (I hope) Def::Mod(..) | Def::ForeignMod(..) | + Def::PrimTy(..) | + Def::SelfTy(..) | + Def::TyParam(..) | Def::Local(..) | Def::Label(..) | Def::Upvar(..) | @@ -4213,12 +4221,10 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { // a problem. self.check_path_parameter_count(subst::TypeSpace, span, - scheme.generics, !require_type_space, &mut type_segment); self.check_path_parameter_count(subst::FnSpace, span, - scheme.generics, true, &mut fn_segment); @@ -4228,7 +4234,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { subst::TypeSpace => type_segment, subst::FnSpace => fn_segment }; - let lifetimes = match segment.map(|s| &s.parameters) { + let lifetimes = match segment.map(|(s, _)| &s.parameters) { Some(&hir::AngleBracketedParameters(ref data)) => &data.lifetimes[..], Some(&hir::ParenthesizedParameters(_)) => bug!(), None => &[] @@ -4242,25 +4248,31 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { }, |def, substs| { let mut i = def.index as usize; let segment = match def.space { - subst::TypeSpace => type_segment, + subst::TypeSpace => { + // Handle Self first, so we can adjust the index to match the AST. + match (type_segment, fn_segment) { + (Some((_, generics)), _) | (_, Some((_, generics))) => { + if generics.has_self { + if i == 0 { + return opt_self_ty.unwrap_or_else(|| { + self.type_var_for_def(span, def, substs) + }); + } + i -= 1; + } + } + _ => {} + } + type_segment + } subst::FnSpace => fn_segment }; - let types = match segment.map(|s| &s.parameters) { + let types = match segment.map(|(s, _)| &s.parameters) { Some(&hir::AngleBracketedParameters(ref data)) => &data.types[..], Some(&hir::ParenthesizedParameters(_)) => bug!(), None => &[] }; - // Handle Self first, so we can adjust the index to match the AST. - if scheme.generics.has_self && def.space == subst::TypeSpace { - if i == 0 { - return opt_self_ty.unwrap_or_else(|| { - self.type_var_for_def(span, def, substs) - }); - } - i -= 1; - } - let can_omit = def.space != subst::TypeSpace || !require_type_space; let default = if can_omit && types.len() == 0 { def.default @@ -4306,9 +4318,9 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { // with the substituted impl type. let impl_scheme = self.tcx.lookup_item_type(impl_def_id); assert_eq!(substs.types.len(subst::TypeSpace), - impl_scheme.generics.types.len(subst::TypeSpace)); + impl_scheme.generics.types.len()); assert_eq!(substs.regions.len(subst::TypeSpace), - impl_scheme.generics.regions.len(subst::TypeSpace)); + impl_scheme.generics.regions.len()); let impl_ty = self.instantiate_type_scheme(span, &substs, &impl_scheme.ty); match self.sub_types(false, TypeOrigin::Misc(span), self_ty, impl_ty) { @@ -4339,10 +4351,9 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { fn check_path_parameter_count(&self, space: subst::ParamSpace, span: Span, - generics: &ty::Generics<'tcx>, can_omit: bool, - segment: &mut Option<&hir::PathSegment>) { - let (lifetimes, types, bindings) = match segment.map(|s| &s.parameters) { + segment: &mut Option<(&hir::PathSegment, &ty::Generics)>) { + let (lifetimes, types, bindings) = match segment.map(|(s, _)| &s.parameters) { Some(&hir::AngleBracketedParameters(ref data)) => { (&data.lifetimes[..], &data.types[..], &data.bindings[..]) } @@ -4357,7 +4368,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { }; // Check provided lifetime parameters. - let lifetime_defs = generics.regions.get_slice(space); + let lifetime_defs = segment.map_or(&[][..], |(_, generics)| &generics.regions); if lifetimes.len() > lifetime_defs.len() { let span = lifetimes[lifetime_defs.len()].span; span_err!(self.tcx.sess, span, E0088, @@ -4374,12 +4385,13 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { } // Check provided type parameters. - let type_defs = generics.types.get_slice(space); - let type_defs = if space == subst::TypeSpace { - &type_defs[generics.has_self as usize..] - } else { - type_defs - }; + let type_defs = segment.map_or(&[][..], |(_, generics)| { + if space == subst::TypeSpace { + &generics.types[generics.has_self as usize..] + } else { + &generics.types + } + }); let required_len = type_defs.iter() .take_while(|d| d.default.is_none()) .count(); diff --git a/src/librustc_typeck/check/wfcheck.rs b/src/librustc_typeck/check/wfcheck.rs index f2076895f0873..f793ce7acb7c7 100644 --- a/src/librustc_typeck/check/wfcheck.rs +++ b/src/librustc_typeck/check/wfcheck.rs @@ -523,10 +523,10 @@ impl<'ccx, 'gcx> CheckTypeWellFormedVisitor<'ccx, 'gcx> { } fn reject_shadowing_type_parameters(tcx: TyCtxt, span: Span, generics: &ty::Generics) { - let impl_params = generics.types.get_slice(subst::TypeSpace).iter() - .map(|tp| tp.name).collect::>(); + let parent = tcx.lookup_generics(generics.parent.unwrap()); + let impl_params: HashSet<_> = parent.types.iter().map(|tp| tp.name).collect(); - for method_param in generics.types.get_slice(subst::FnSpace) { + for method_param in &generics.types { if impl_params.contains(&method_param.name) { error_194(tcx, span, method_param.name); } diff --git a/src/librustc_typeck/collect.rs b/src/librustc_typeck/collect.rs index 8eef384f2cf9f..9e8fe710cc1cd 100644 --- a/src/librustc_typeck/collect.rs +++ b/src/librustc_typeck/collect.rs @@ -65,7 +65,7 @@ use middle::lang_items::SizedTraitLangItem; use middle::const_val::ConstVal; use rustc_const_eval::EvalHint::UncheckedExprHint; use rustc_const_eval::{eval_const_expr_partial, report_const_eval_err}; -use rustc::ty::subst::{Substs, FnSpace, ParamSpace, TypeSpace, VecPerParamSpace}; +use rustc::ty::subst::{Substs, FnSpace, ParamSpace, TypeSpace}; use rustc::ty::{ToPredicate, ImplContainer, ImplOrTraitItemContainer, TraitContainer}; use rustc::ty::{self, ToPolyTraitRef, Ty, TyCtxt, TypeScheme}; use rustc::ty::{VariantKind}; @@ -793,9 +793,11 @@ fn convert_item(ccx: &CrateCtxt, it: &hir::Item) { } if let hir::ImplItemKind::Const(ref ty, _) = impl_item.node { + let const_def_id = ccx.tcx.map.local_def_id(impl_item.id); + let ty_generics = generics_of_def_id(ccx, const_def_id); let ty = ccx.icx(&ty_predicates) .to_ty(&ExplicitRscope, &ty); - tcx.register_item_type(ccx.tcx.map.local_def_id(impl_item.id), + tcx.register_item_type(const_def_id, TypeScheme { generics: ty_generics, ty: ty, @@ -858,11 +860,13 @@ fn convert_item(ccx: &CrateCtxt, it: &hir::Item) { // Convert all the associated constants. for trait_item in trait_items { if let hir::ConstTraitItem(ref ty, ref default) = trait_item.node { + let const_def_id = ccx.tcx.map.local_def_id(trait_item.id); + let ty_generics = generics_of_def_id(ccx, const_def_id); let ty = ccx.icx(&trait_predicates) .to_ty(&ExplicitRscope, ty); - tcx.register_item_type(ccx.tcx.map.local_def_id(trait_item.id), + tcx.register_item_type(const_def_id, TypeScheme { - generics: trait_def.generics, + generics: ty_generics, ty: ty, }); convert_associated_const(ccx, @@ -957,7 +961,7 @@ fn convert_variant_ctor<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, predicates: ty::GenericPredicates<'tcx>) { let tcx = ccx.tcx; let def_id = tcx.map.local_def_id(ctor_id); - tcx.generics.borrow_mut().insert(def_id, scheme.generics); + generics_of_def_id(ccx, def_id); let ctor_ty = match variant.kind { VariantKind::Unit | VariantKind::Struct => scheme.ty, VariantKind::Tuple => { @@ -1389,24 +1393,35 @@ fn generics_of_def_id<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, use rustc::hir::map::*; use rustc::hir::*; + let node = tcx.map.get(node_id); + let parent_def_id = match node { + NodeImplItem(_) | + NodeTraitItem(_) | + NodeVariant(_) | + NodeStructCtor(_) => { + let parent_id = tcx.map.get_parent(node_id); + Some(tcx.map.local_def_id(parent_id)) + } + _ => None + }; + let mut opt_self = None; - let mut base_def_id = None; let mut allow_defaults = false; let no_generics = hir::Generics::empty(); - let (space, ast_generics) = match tcx.map.get(node_id) { - NodeImplItem(&ImplItem { node: ImplItemKind::Method(ref sig, _), .. }) | - NodeTraitItem(&TraitItem { node: MethodTraitItem(ref sig, _), .. }) => { - let parent_id = tcx.map.get_parent(node_id); - base_def_id = Some(tcx.map.local_def_id(parent_id)); - (FnSpace, &sig.generics) + let (space, ast_generics) = match node { + NodeTraitItem(item) => { + match item.node { + MethodTraitItem(ref sig, _) => (FnSpace, &sig.generics), + _ => (FnSpace, &no_generics) + } } - NodeImplItem(_) | - NodeTraitItem(_) => { - let parent_id = tcx.map.get_parent(node_id); - base_def_id = Some(tcx.map.local_def_id(parent_id)); - (FnSpace, &no_generics) + NodeImplItem(item) => { + match item.node { + ImplItemKind::Method(ref sig, _) => (FnSpace, &sig.generics), + _ => (FnSpace, &no_generics) + } } NodeItem(item) => { @@ -1457,9 +1472,16 @@ fn generics_of_def_id<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, _ => (TypeSpace, &no_generics) }; - let empty_generics = ty::Generics::empty(); - let base_generics = base_def_id.map_or(&empty_generics, |def_id| { - generics_of_def_id(ccx, def_id) + let has_self = opt_self.is_some(); + let mut parent_has_self = false; + let (parent_regions, parent_types) = parent_def_id.map_or((0, 0), |def_id| { + let generics = generics_of_def_id(ccx, def_id); + assert_eq!(generics.parent, None); + assert_eq!(generics.parent_regions, 0); + assert_eq!(generics.parent_types, 0); + assert_eq!(has_self, false); + parent_has_self = generics.has_self; + (generics.regions.len(), generics.types.len()) }); let early_lifetimes = early_bound_lifetimes_from_generics(ccx, ast_generics); @@ -1477,32 +1499,15 @@ fn generics_of_def_id<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, // Now create the real type parameters. let types = ast_generics.ty_params.iter().enumerate().map(|(i, p)| { - let i = opt_self.is_some() as u32 + i as u32; + let i = has_self as u32 + i as u32; get_or_create_type_parameter_def(ccx, ast_generics, space, i, p, allow_defaults) - }).collect(); - - let has_self = base_generics.has_self || opt_self.is_some(); - let (regions, types) = match space { - TypeSpace => { - assert_eq!(base_generics.regions.as_full_slice().len(), 0); - assert_eq!(base_generics.types.as_full_slice().len(), 0); - (VecPerParamSpace::new(regions, vec![]), - VecPerParamSpace::new(opt_self.into_iter().chain(types).collect(), vec![])) - } - FnSpace => { - assert_eq!(base_generics.regions.len(FnSpace), 0); - assert_eq!(base_generics.types.len(FnSpace), 0); - (VecPerParamSpace::new(base_generics.regions.get_slice(TypeSpace).to_vec(), - regions), - VecPerParamSpace::new(base_generics.types.get_slice(TypeSpace).to_vec(), - types)) - } - }; + }); + let types: Vec<_> = opt_self.into_iter().chain(types).collect(); // Debugging aid. if tcx.has_attr(def_id, "rustc_object_lifetime_default") { let object_lifetime_default_reprs: String = - types.as_full_slice().iter().map(|t| { + types.iter().map(|t| { match t.object_lifetime_default { ty::ObjectLifetimeDefault::Specific(r) => r.to_string(), d => format!("{:?}", d), @@ -1512,9 +1517,12 @@ fn generics_of_def_id<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, } tcx.alloc_generics(ty::Generics { + parent: parent_def_id, + parent_regions: parent_regions as u32, + parent_types: parent_types as u32, regions: regions, types: types, - has_self: has_self + has_self: has_self || parent_has_self }) }) } @@ -2148,7 +2156,7 @@ fn enforce_impl_params_are_constrained<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, &mut input_parameters); let ty_generics = generics_of_def_id(ccx, impl_def_id); - for (ty_param, param) in ty_generics.types.as_full_slice().iter().zip(&generics.ty_params) { + for (ty_param, param) in ty_generics.types.iter().zip(&generics.ty_params) { let param_ty = ty::ParamTy::for_def(ty_param); if !input_parameters.contains(&ctp::Parameter::Type(param_ty)) { report_unused_parameter(ccx, param.span, "type", ¶m_ty.to_string()); diff --git a/src/librustc_typeck/variance/constraints.rs b/src/librustc_typeck/variance/constraints.rs index 2b88689ff1295..95ddb59c0e28a 100644 --- a/src/librustc_typeck/variance/constraints.rs +++ b/src/librustc_typeck/variance/constraints.rs @@ -301,8 +301,8 @@ impl<'a, 'tcx> ConstraintContext<'a, 'tcx> { self.add_constraints_from_substs( generics, trait_ref.def_id, - trait_def.generics.types.as_full_slice(), - trait_def.generics.regions.as_full_slice(), + &trait_def.generics.types, + &trait_def.generics.regions, trait_ref.substs, variance); } @@ -359,16 +359,11 @@ impl<'a, 'tcx> ConstraintContext<'a, 'tcx> { // README.md for a discussion on dep-graph management. self.tcx().dep_graph.read(ItemVariances::to_dep_node(&def.did)); - // All type parameters on enums and structs should be - // in the TypeSpace. - assert!(item_type.generics.types.is_empty_in(subst::FnSpace)); - assert!(item_type.generics.regions.is_empty_in(subst::FnSpace)); - self.add_constraints_from_substs( generics, def.did, - item_type.generics.types.as_full_slice(), - item_type.generics.regions.as_full_slice(), + &item_type.generics.types, + &item_type.generics.regions, substs, variance); } @@ -385,8 +380,8 @@ impl<'a, 'tcx> ConstraintContext<'a, 'tcx> { self.add_constraints_from_substs( generics, trait_ref.def_id, - trait_def.generics.types.as_full_slice(), - trait_def.generics.regions.as_full_slice(), + &trait_def.generics.types, + &trait_def.generics.regions, trait_ref.substs, variance); } @@ -406,7 +401,9 @@ impl<'a, 'tcx> ConstraintContext<'a, 'tcx> { } ty::TyParam(ref data) => { - let def_id = generics.types.get(data.space, data.idx as usize).def_id; + assert_eq!(data.space, subst::TypeSpace); + assert_eq!(generics.parent, None); + let def_id = generics.types[data.idx as usize].def_id; let node_id = self.tcx().map.as_local_node_id(def_id).unwrap(); match self.terms_cx.inferred_map.get(&node_id) { Some(&index) => { @@ -493,8 +490,9 @@ impl<'a, 'tcx> ConstraintContext<'a, 'tcx> { variance: VarianceTermPtr<'a>) { match region { ty::ReEarlyBound(ref data) => { - let def_id = - generics.regions.get(data.space, data.index as usize).def_id; + assert_eq!(data.space, subst::TypeSpace); + assert_eq!(generics.parent, None); + let def_id = generics.regions[data.index as usize].def_id; let node_id = self.tcx().map.as_local_node_id(def_id).unwrap(); if self.is_to_be_inferred(node_id) { let index = self.inferred_index(node_id); diff --git a/src/librustdoc/clean/inline.rs b/src/librustdoc/clean/inline.rs index b4be201440ccf..427468069d04e 100644 --- a/src/librustdoc/clean/inline.rs +++ b/src/librustdoc/clean/inline.rs @@ -21,7 +21,6 @@ use rustc::hir::def::Def; use rustc::hir::def_id::DefId; use rustc::hir::print as pprust; use rustc::ty::{self, TyCtxt}; -use rustc::ty::subst; use rustc_const_eval::lookup_const_by_id; @@ -161,7 +160,7 @@ pub fn build_external_trait<'a, 'tcx>(cx: &DocContext, tcx: TyCtxt<'a, 'tcx, 'tc let def = tcx.lookup_trait_def(did); let trait_items = tcx.trait_items(did).clean(cx); let predicates = tcx.lookup_predicates(did); - let generics = (def.generics, &predicates, subst::TypeSpace).clean(cx); + let generics = (def.generics, &predicates).clean(cx); let generics = filter_non_trait_generics(did, generics); let (generics, supertrait_bounds) = separate_supertrait_bounds(generics); clean::Trait { @@ -189,7 +188,7 @@ fn build_external_function<'a, 'tcx>(cx: &DocContext, tcx: TyCtxt<'a, 'tcx, 'tcx let predicates = tcx.lookup_predicates(did); clean::Function { decl: decl, - generics: (t.generics, &predicates, subst::FnSpace).clean(cx), + generics: (t.generics, &predicates).clean(cx), unsafety: style, constness: constness, abi: abi, @@ -209,7 +208,7 @@ fn build_struct<'a, 'tcx>(cx: &DocContext, tcx: TyCtxt<'a, 'tcx, 'tcx>, &[..] if variant.kind == ty::VariantKind::Tuple => doctree::Tuple, _ => doctree::Plain, }, - generics: (t.generics, &predicates, subst::TypeSpace).clean(cx), + generics: (t.generics, &predicates).clean(cx), fields: variant.fields.clean(cx), fields_stripped: false, } @@ -222,7 +221,7 @@ fn build_type<'a, 'tcx>(cx: &DocContext, tcx: TyCtxt<'a, 'tcx, 'tcx>, match t.ty.sty { ty::TyEnum(edef, _) if !tcx.sess.cstore.is_typedef(did) => { return clean::EnumItem(clean::Enum { - generics: (t.generics, &predicates, subst::TypeSpace).clean(cx), + generics: (t.generics, &predicates).clean(cx), variants_stripped: false, variants: edef.variants.clean(cx), }) @@ -232,7 +231,7 @@ fn build_type<'a, 'tcx>(cx: &DocContext, tcx: TyCtxt<'a, 'tcx, 'tcx>, clean::TypedefItem(clean::Typedef { type_: t.ty.clean(cx), - generics: (t.generics, &predicates, subst::TypeSpace).clean(cx), + generics: (t.generics, &predicates).clean(cx), }, false) } @@ -393,9 +392,11 @@ pub fn build_impl<'a, 'tcx>(cx: &DocContext, // because an associated type won't have generics on the LHS let typedef = clean::Typedef { type_: assoc_ty.ty.unwrap().clean(cx), - generics: (&ty::Generics::empty(), - &ty::GenericPredicates::empty(), - subst::TypeSpace).clean(cx) + generics: clean::Generics { + lifetimes: vec![], + type_params: vec![], + where_predicates: vec![] + } }; Some(clean::Item { name: Some(assoc_ty.name.clean(cx)), @@ -434,7 +435,7 @@ pub fn build_impl<'a, 'tcx>(cx: &DocContext, provided_trait_methods: provided, trait_: trait_, for_: for_, - generics: (ty.generics, &predicates, subst::TypeSpace).clean(cx), + generics: (ty.generics, &predicates).clean(cx), items: trait_items, polarity: polarity.map(|p| { p.clean(cx) }), }), diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index 6fae7ddc24a89..07821a730ccf6 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -973,17 +973,16 @@ impl Clean for hir::Generics { } impl<'a, 'tcx> Clean for (&'a ty::Generics<'tcx>, - &'a ty::GenericPredicates<'tcx>, - subst::ParamSpace) { + &'a ty::GenericPredicates<'tcx>) { fn clean(&self, cx: &DocContext) -> Generics { use self::WherePredicate as WP; - let (gens, preds, space) = *self; + let (gens, preds) = *self; // Bounds in the type_params and lifetimes fields are repeated in the // predicates field (see rustc_typeck::collect::ty_generics), so remove // them. - let stripped_typarams = gens.types.get_slice(space).iter().filter_map(|tp| { + let stripped_typarams = gens.types.iter().filter_map(|tp| { if tp.name == keywords::SelfType.name() { assert_eq!(tp.index, 0); None @@ -991,7 +990,7 @@ impl<'a, 'tcx> Clean for (&'a ty::Generics<'tcx>, Some(tp.clean(cx)) } }).collect::>(); - let stripped_lifetimes = gens.regions.get_slice(space).iter().map(|rp| { + let stripped_lifetimes = gens.regions.iter().map(|rp| { let mut srp = rp.clone(); srp.bounds = Vec::new(); srp.clean(cx) @@ -1359,8 +1358,7 @@ impl<'tcx> Clean for ty::Method<'tcx> { predicates: self.predicates.predicates[method_start..].to_vec() }; - let generics = (self.generics, &method_predicates, - subst::FnSpace).clean(cx); + let generics = (self.generics, &method_predicates).clean(cx); let mut decl = (self.def_id, &self.fty.sig).clean(cx); match self.explicit_self { ty::ExplicitSelfCategory::ByValue => { @@ -2929,7 +2927,7 @@ impl<'tcx> Clean for ty::AssociatedType<'tcx> { // applied to this associated type in question. let def = cx.tcx().lookup_trait_def(did); let predicates = cx.tcx().lookup_predicates(did); - let generics = (def.generics, &predicates, subst::TypeSpace).clean(cx); + let generics = (def.generics, &predicates).clean(cx); generics.where_predicates.iter().filter_map(|pred| { let (name, self_type, trait_, bounds) = match *pred { WherePredicate::BoundPredicate { From 6f5e455c2de007a12ed632f84b986369ae43a504 Mon Sep 17 00:00:00 2001 From: Eduard Burtescu Date: Thu, 11 Aug 2016 09:19:42 +0300 Subject: [PATCH 11/12] rustc: split GenericPredicates of a method from its parent predicates. --- src/librustc/traits/select.rs | 26 ++- src/librustc/ty/mod.rs | 25 ++- src/librustc/ty/structural_impls.rs | 12 -- src/librustc_metadata/decoder.rs | 1 + src/librustc_metadata/encoder.rs | 3 + src/librustc_typeck/astconv.rs | 1 + src/librustc_typeck/check/compare_method.rs | 30 ++-- src/librustc_typeck/check/dropck.rs | 1 + src/librustc_typeck/check/mod.rs | 12 +- src/librustc_typeck/check/regionck.rs | 1 + src/librustc_typeck/check/wfcheck.rs | 1 + src/librustc_typeck/collect.rs | 158 +++++++++--------- src/librustdoc/clean/mod.rs | 12 +- .../associated-const-type-parameter-arrays.rs | 3 +- 14 files changed, 136 insertions(+), 150 deletions(-) diff --git a/src/librustc/traits/select.rs b/src/librustc/traits/select.rs index 9099d6cd740d1..bf6aad98db1a8 100644 --- a/src/librustc/traits/select.rs +++ b/src/librustc/traits/select.rs @@ -2897,20 +2897,18 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { // obligation will normalize to `<$0 as Iterator>::Item = $1` and // `$1: Copy`, so we must ensure the obligations are emitted in // that order. - let predicates = tcx - .lookup_predicates(def_id) - .predicates.iter() - .flat_map(|predicate| { - let predicate = - normalize_with_depth(self, cause.clone(), recursion_depth, - &predicate.subst(tcx, substs)); - predicate.obligations.into_iter().chain( - Some(Obligation { - cause: cause.clone(), - recursion_depth: recursion_depth, - predicate: predicate.value - })) - }).collect(); + let predicates = tcx.lookup_predicates(def_id); + assert_eq!(predicates.parent, None); + let predicates = predicates.predicates.iter().flat_map(|predicate| { + let predicate = normalize_with_depth(self, cause.clone(), recursion_depth, + &predicate.subst(tcx, substs)); + predicate.obligations.into_iter().chain( + Some(Obligation { + cause: cause.clone(), + recursion_depth: recursion_depth, + predicate: predicate.value + })) + }).collect(); self.infcx().plug_leaks(skol_map, snapshot, &predicates) } } diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs index 689f2ad02c94c..b2b8286be2fba 100644 --- a/src/librustc/ty/mod.rs +++ b/src/librustc/ty/mod.rs @@ -768,27 +768,38 @@ pub struct Generics<'tcx> { /// Bounds on generics. #[derive(Clone)] pub struct GenericPredicates<'tcx> { + pub parent: Option, pub predicates: Vec>, } impl<'a, 'gcx, 'tcx> GenericPredicates<'tcx> { - pub fn empty() -> GenericPredicates<'tcx> { - GenericPredicates { - predicates: vec![] - } - } - pub fn instantiate(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>, substs: &Substs<'tcx>) -> InstantiatedPredicates<'tcx> { + let mut instantiated = InstantiatedPredicates::empty(); + self.instantiate_into(tcx, &mut instantiated, substs); + instantiated + } + pub fn instantiate_own(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>, substs: &Substs<'tcx>) + -> InstantiatedPredicates<'tcx> { InstantiatedPredicates { - predicates: self.predicates.subst(tcx, substs), + predicates: self.predicates.subst(tcx, substs) + } + } + + fn instantiate_into(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>, + instantiated: &mut InstantiatedPredicates<'tcx>, + substs: &Substs<'tcx>) { + if let Some(def_id) = self.parent { + tcx.lookup_predicates(def_id).instantiate_into(tcx, instantiated, substs); } + instantiated.predicates.extend(self.predicates.iter().map(|p| p.subst(tcx, substs))) } pub fn instantiate_supertrait(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>, poly_trait_ref: &ty::PolyTraitRef<'tcx>) -> InstantiatedPredicates<'tcx> { + assert_eq!(self.parent, None); InstantiatedPredicates { predicates: self.predicates.iter().map(|pred| { pred.subst_supertrait(tcx, poly_trait_ref) diff --git a/src/librustc/ty/structural_impls.rs b/src/librustc/ty/structural_impls.rs index 248d5d9062d59..021ae820b87c5 100644 --- a/src/librustc/ty/structural_impls.rs +++ b/src/librustc/ty/structural_impls.rs @@ -832,18 +832,6 @@ impl<'tcx> TypeFoldable<'tcx> for ty::RegionParameterDef { } } -impl<'tcx> TypeFoldable<'tcx> for ty::GenericPredicates<'tcx> { - fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) -> Self { - ty::GenericPredicates { - predicates: self.predicates.fold_with(folder), - } - } - - fn super_visit_with>(&self, visitor: &mut V) -> bool { - self.predicates.visit_with(visitor) - } -} - impl<'tcx> TypeFoldable<'tcx> for ty::Predicate<'tcx> { fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) -> Self { match *self { diff --git a/src/librustc_metadata/decoder.rs b/src/librustc_metadata/decoder.rs index e42825ef1e549..5488f114db32f 100644 --- a/src/librustc_metadata/decoder.rs +++ b/src/librustc_metadata/decoder.rs @@ -1591,6 +1591,7 @@ fn doc_predicates<'a, 'tcx>(base_doc: rbml::Doc, let doc = reader::get_doc(base_doc, tag); ty::GenericPredicates { + parent: item_parent_item(cdata, doc), predicates: reader::tagged_docs(doc, tag_predicate).map(|predicate_doc| { doc_predicate(cdata, predicate_doc, tcx) }).collect() diff --git a/src/librustc_metadata/encoder.rs b/src/librustc_metadata/encoder.rs index 0cde9b48d6f88..320ba3c8d9dc8 100644 --- a/src/librustc_metadata/encoder.rs +++ b/src/librustc_metadata/encoder.rs @@ -525,6 +525,9 @@ fn encode_predicates<'a,'tcx>(rbml_w: &mut Encoder, tag: usize) { rbml_w.start_tag(tag); + if let Some(def_id) = predicates.parent { + rbml_w.wr_tagged_u64(tag_items_data_parent_item, def_to_u64(def_id)); + } for predicate in &predicates.predicates { rbml_w.wr_tagged_u32(tag_predicate, index.add_xref(XRef::Predicate(predicate.clone()))); diff --git a/src/librustc_typeck/astconv.rs b/src/librustc_typeck/astconv.rs index a452b55a7d33d..aec8f8245da5e 100644 --- a/src/librustc_typeck/astconv.rs +++ b/src/librustc_typeck/astconv.rs @@ -1726,6 +1726,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o { let predicates = bounds.predicates(tcx, ty); let predicates = tcx.lift_to_global(&predicates).unwrap(); tcx.predicates.borrow_mut().insert(def_id, ty::GenericPredicates { + parent: None, predicates: predicates }); diff --git a/src/librustc_typeck/check/compare_method.rs b/src/librustc_typeck/check/compare_method.rs index 5bfe58e78f112..4cbb2d7f09f02 100644 --- a/src/librustc_typeck/check/compare_method.rs +++ b/src/librustc_typeck/check/compare_method.rs @@ -211,29 +211,18 @@ pub fn compare_impl_method<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, return; } - // Depend on trait/impl predicates always being before method's own predicates, - // to be able to split method predicates into "inherited" and method-specific. - let trait_predicates = tcx.lookup_predicates(trait_m.container_id()).predicates; - let impl_predicates = tcx.lookup_predicates(impl_m.container_id()).predicates; - let trait_method_start = trait_predicates.len(); - let impl_method_start = impl_predicates.len(); - assert_eq!(&trait_predicates[..], &trait_m.predicates.predicates[..trait_method_start]); - assert_eq!(&impl_predicates[..], &impl_m.predicates.predicates[..impl_method_start]); - tcx.infer_ctxt(None, None, Reveal::NotSpecializable).enter(|mut infcx| { let mut fulfillment_cx = traits::FulfillmentContext::new(); - // Normalize the associated types in the trait_bounds. - let trait_bounds = trait_m.predicates.instantiate(tcx, trait_to_skol_substs); - // Create obligations for each predicate declared by the impl // definition in the context of the trait's parameter // environment. We can't just use `impl_env.caller_bounds`, // however, because we want to replace all late-bound regions with // region variables. - let impl_bounds = impl_m.predicates.instantiate(tcx, impl_to_skol_substs); + let impl_predicates = tcx.lookup_predicates(impl_m.predicates.parent.unwrap()); + let mut hybrid_preds = impl_predicates.instantiate(tcx, impl_to_skol_substs); - debug!("compare_impl_method: impl_bounds={:?}", impl_bounds); + debug!("compare_impl_method: impl_bounds={:?}", hybrid_preds); // This is the only tricky bit of the new way we check implementation methods // We need to build a set of predicates where only the FnSpace bounds @@ -242,14 +231,14 @@ pub fn compare_impl_method<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, // // We then register the obligations from the impl_m and check to see // if all constraints hold. - let hybrid_preds = impl_bounds.predicates[..impl_method_start].iter() - .chain(trait_bounds.predicates[trait_method_start..].iter()); + hybrid_preds.predicates.extend( + trait_m.predicates.instantiate_own(tcx, trait_to_skol_substs).predicates); // Construct trait parameter environment and then shift it into the skolemized viewpoint. // The key step here is to update the caller_bounds's predicates to be // the new hybrid bounds we computed. let normalize_cause = traits::ObligationCause::misc(impl_m_span, impl_m_body_id); - let trait_param_env = impl_param_env.with_caller_bounds(hybrid_preds.cloned().collect()); + let trait_param_env = impl_param_env.with_caller_bounds(hybrid_preds.predicates); let trait_param_env = traits::normalize_param_env_or_error(tcx, trait_param_env, normalize_cause.clone()); @@ -261,12 +250,13 @@ pub fn compare_impl_method<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, let mut selcx = traits::SelectionContext::new(&infcx); - let (impl_pred_fns, _) = + let impl_m_own_bounds = impl_m.predicates.instantiate_own(tcx, impl_to_skol_substs); + let (impl_m_own_bounds, _) = infcx.replace_late_bound_regions_with_fresh_var( impl_m_span, infer::HigherRankedType, - &ty::Binder(impl_bounds.predicates[impl_method_start..].to_vec())); - for predicate in impl_pred_fns { + &ty::Binder(impl_m_own_bounds.predicates)); + for predicate in impl_m_own_bounds { let traits::Normalized { value: predicate, .. } = traits::normalize(&mut selcx, normalize_cause.clone(), &predicate); diff --git a/src/librustc_typeck/check/dropck.rs b/src/librustc_typeck/check/dropck.rs index 7d79fc4fbf878..d1da95f39df40 100644 --- a/src/librustc_typeck/check/dropck.rs +++ b/src/librustc_typeck/check/dropck.rs @@ -184,6 +184,7 @@ fn ensure_drop_predicates_are_implied_by_item_defn<'a, 'tcx>( // 'a:'b and T:'b into region inference constraints. It is simpler // just to look for all the predicates directly. + assert_eq!(dtor_predicates.parent, None); for predicate in &dtor_predicates.predicates { // (We do not need to worry about deep analysis of type // expressions etc because the Drop impls are already forced diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index d699bafed9a05..8c4ec8453177e 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -1612,8 +1612,14 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { bounds: &ty::GenericPredicates<'tcx>) -> ty::InstantiatedPredicates<'tcx> { + let result = bounds.instantiate(self.tcx, substs); + let result = self.normalize_associated_types_in(span, &result.predicates); + debug!("instantiate_bounds(bounds={:?}, substs={:?}) = {:?}", + bounds, + substs, + result); ty::InstantiatedPredicates { - predicates: self.instantiate_type_scheme(span, substs, &bounds.predicates) + predicates: result } } @@ -4210,8 +4216,6 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { } _ => {} } - let scheme = self.tcx.lookup_item_type(def.def_id()); - let type_predicates = self.tcx.lookup_predicates(def.def_id()); // Now we have to compare the types that the user *actually* // provided against the types that were *expected*. If the user @@ -4296,6 +4300,8 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { // The things we are substituting into the type should not contain // escaping late-bound regions, and nor should the base type scheme. + let scheme = self.tcx.lookup_item_type(def.def_id()); + let type_predicates = self.tcx.lookup_predicates(def.def_id()); assert!(!substs.has_escaping_regions()); assert!(!scheme.ty.has_escaping_regions()); diff --git a/src/librustc_typeck/check/regionck.rs b/src/librustc_typeck/check/regionck.rs index 8e34b0b8c5559..f6ffbc60c2836 100644 --- a/src/librustc_typeck/check/regionck.rs +++ b/src/librustc_typeck/check/regionck.rs @@ -1754,6 +1754,7 @@ impl<'a, 'gcx, 'tcx> RegionCtxt<'a, 'gcx, 'tcx> { // // we can thus deduce that `>::SomeType : 'a`. let trait_predicates = self.tcx.lookup_predicates(projection_ty.trait_ref.def_id); + assert_eq!(trait_predicates.parent, None); let predicates = trait_predicates.predicates.as_slice().to_vec(); traits::elaborate_predicates(self.tcx, predicates) .filter_map(|predicate| { diff --git a/src/librustc_typeck/check/wfcheck.rs b/src/librustc_typeck/check/wfcheck.rs index f793ce7acb7c7..ef5e1a26f4150 100644 --- a/src/librustc_typeck/check/wfcheck.rs +++ b/src/librustc_typeck/check/wfcheck.rs @@ -454,6 +454,7 @@ impl<'ccx, 'gcx> CheckTypeWellFormedVisitor<'ccx, 'gcx> { let item_def_id = self.tcx().map.local_def_id(item.id); let ty_predicates = self.tcx().lookup_predicates(item_def_id); + assert_eq!(ty_predicates.parent, None); let variances = self.tcx().item_variances(item_def_id); let mut constrained_parameters: HashSet<_> = diff --git a/src/librustc_typeck/collect.rs b/src/librustc_typeck/collect.rs index 9e8fe710cc1cd..939f8ac50a6c6 100644 --- a/src/librustc_typeck/collect.rs +++ b/src/librustc_typeck/collect.rs @@ -459,35 +459,38 @@ impl<'tcx> GetTypeParameterBounds<'tcx> for () { impl<'tcx> GetTypeParameterBounds<'tcx> for ty::GenericPredicates<'tcx> { fn get_type_parameter_bounds(&self, astconv: &AstConv<'tcx, 'tcx>, - _span: Span, + span: Span, node_id: ast::NodeId) -> Vec> { let def = astconv.tcx().type_parameter_def(node_id); - self.predicates - .iter() - .filter(|predicate| { - match **predicate { - ty::Predicate::Trait(ref data) => { - data.skip_binder().self_ty().is_param(def.space, def.index) - } - ty::Predicate::TypeOutlives(ref data) => { - data.skip_binder().0.is_param(def.space, def.index) - } - ty::Predicate::Rfc1592(..) | - ty::Predicate::Equate(..) | - ty::Predicate::RegionOutlives(..) | - ty::Predicate::WellFormed(..) | - ty::Predicate::ObjectSafe(..) | - ty::Predicate::ClosureKind(..) | - ty::Predicate::Projection(..) => { - false - } + let mut results = self.parent.map_or(vec![], |def_id| { + let parent = astconv.tcx().lookup_predicates(def_id); + parent.get_type_parameter_bounds(astconv, span, node_id) + }); + + results.extend(self.predicates.iter().filter(|predicate| { + match **predicate { + ty::Predicate::Trait(ref data) => { + data.skip_binder().self_ty().is_param(def.space, def.index) + } + ty::Predicate::TypeOutlives(ref data) => { + data.skip_binder().0.is_param(def.space, def.index) } - }) - .cloned() - .collect() + ty::Predicate::Rfc1592(..) | + ty::Predicate::Equate(..) | + ty::Predicate::RegionOutlives(..) | + ty::Predicate::WellFormed(..) | + ty::Predicate::ObjectSafe(..) | + ty::Predicate::ClosureKind(..) | + ty::Predicate::Projection(..) => { + false + } + } + }).cloned()); + + results } } @@ -568,7 +571,7 @@ fn convert_method<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, let ty_generics = generics_of_def_id(ccx, def_id); let ty_generic_predicates = - ty_generic_predicates_for_fn(ccx, &sig.generics, rcvr_ty_predicates); + ty_generic_predicates(ccx, FnSpace, &sig.generics, ty_generics.parent, vec![], false); let (fty, explicit_self_category) = { let anon_scope = match container { @@ -634,8 +637,12 @@ fn convert_associated_const<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, ty: ty::Ty<'tcx>, has_value: bool) { + let predicates = ty::GenericPredicates { + parent: Some(container.id()), + predicates: vec![] + }; ccx.tcx.predicates.borrow_mut().insert(ccx.tcx.map.local_def_id(id), - ty::GenericPredicates::empty()); + predicates); write_ty_to_tcx(ccx, id, ty); @@ -744,7 +751,8 @@ fn convert_item(ccx: &CrateCtxt, it: &hir::Item) { debug!("convert: ast_generics={:?}", generics); let def_id = ccx.tcx.map.local_def_id(it.id); let ty_generics = generics_of_def_id(ccx, def_id); - let mut ty_predicates = ty_generic_predicates_for_type_or_impl(ccx, generics); + let mut ty_predicates = + ty_generic_predicates(ccx, TypeSpace, generics, None, vec![], false); debug!("convert: impl_bounds={:?}", ty_predicates); @@ -1187,6 +1195,7 @@ fn ensure_super_predicates_step(ccx: &CrateCtxt, // generic types: let trait_def = trait_def_of_item(ccx, item); let self_predicate = ty::GenericPredicates { + parent: None, predicates: vec![trait_def.trait_ref.to_predicate()] }; let scope = &(generics, &self_predicate); @@ -1209,6 +1218,7 @@ fn ensure_super_predicates_step(ccx: &CrateCtxt, // Combine the two lists to form the complete set of superbounds: let superbounds = superbounds1.into_iter().chain(superbounds2).collect(); let superpredicates = ty::GenericPredicates { + parent: None, predicates: superbounds }; debug!("superpredicates for trait {:?} = {:?}", @@ -1327,16 +1337,16 @@ fn convert_trait_predicates<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, it: &hir::Item) // but to get the full set of predicates on a trait we need to add // in the supertrait bounds and anything declared on the // associated types. - let mut base_predicates = super_predicates; + let mut base_predicates = super_predicates.predicates; // Add in a predicate that `Self:Trait` (where `Trait` is the // current trait). This is needed for builtin bounds. let self_predicate = trait_def.trait_ref.to_poly_trait_ref().to_predicate(); - base_predicates.predicates.push(self_predicate); + base_predicates.push(self_predicate); // add in the explicit where-clauses let mut trait_predicates = - ty_generic_predicates(ccx, TypeSpace, generics, &base_predicates, true); + ty_generic_predicates(ccx, TypeSpace, generics, None, base_predicates, true); let assoc_predicates = predicates_for_associated_types(ccx, generics, @@ -1619,32 +1629,17 @@ fn predicates_of_item<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, it: &hir::Item) -> ty::GenericPredicates<'tcx> { let def_id = ccx.tcx.map.local_def_id(it.id); - let predicates = match it.node { - hir::ItemStatic(..) | hir::ItemConst(..) => { - ty::GenericPredicates::empty() - } - hir::ItemFn(_, _, _, _, ref ast_generics, _) => { - ty_generic_predicates_for_fn(ccx, ast_generics, &ty::GenericPredicates::empty()) - } + + let no_generics = hir::Generics::empty(); + let (space, generics) = match it.node { + hir::ItemFn(_, _, _, _, ref generics, _) => (FnSpace, generics), hir::ItemTy(_, ref generics) | hir::ItemEnum(_, ref generics) | - hir::ItemStruct(_, ref generics) => { - ty_generic_predicates_for_type_or_impl(ccx, generics) - } - hir::ItemDefaultImpl(..) | - hir::ItemTrait(..) | - hir::ItemExternCrate(..) | - hir::ItemUse(..) | - hir::ItemImpl(..) | - hir::ItemMod(..) | - hir::ItemForeignMod(..) => { - span_bug!( - it.span, - "predicates_of_item: unexpected item type: {:?}", - it.node); - } + hir::ItemStruct(_, ref generics) => (TypeSpace, generics), + _ => (TypeSpace, &no_generics) }; + let predicates = ty_generic_predicates(ccx, space, generics, None, vec![], false); let prev_predicates = ccx.tcx.predicates.borrow_mut().insert(def_id, predicates.clone()); assert!(prev_predicates.is_none()); @@ -1662,34 +1657,17 @@ fn convert_foreign_item<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, let def_id = ccx.tcx.map.local_def_id(it.id); type_scheme_of_def_id(ccx, def_id); - let predicates = match it.node { - hir::ForeignItemFn(_, ref generics) => { - ty_generic_predicates_for_fn(ccx, generics, &ty::GenericPredicates::empty()) - } - hir::ForeignItemStatic(..) => { - ty::GenericPredicates::empty() - } + let no_generics = hir::Generics::empty(); + let (space, generics) = match it.node { + hir::ForeignItemFn(_, ref generics) => (FnSpace, generics), + hir::ForeignItemStatic(..) => (TypeSpace, &no_generics) }; + let predicates = ty_generic_predicates(ccx, space, generics, None, vec![], false); let prev_predicates = ccx.tcx.predicates.borrow_mut().insert(def_id, predicates); assert!(prev_predicates.is_none()); } -fn ty_generic_predicates_for_type_or_impl<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>, - generics: &hir::Generics) - -> ty::GenericPredicates<'tcx> -{ - ty_generic_predicates(ccx, TypeSpace, generics, &ty::GenericPredicates::empty(), false) -} - -fn ty_generic_predicates_for_fn<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>, - generics: &hir::Generics, - base_predicates: &ty::GenericPredicates<'tcx>) - -> ty::GenericPredicates<'tcx> -{ - ty_generic_predicates(ccx, FnSpace, generics, base_predicates, false) -} - // Add the Sized bound, unless the type parameter is marked as `?Sized`. fn add_unsized_bound<'gcx: 'tcx, 'tcx>(astconv: &AstConv<'gcx, 'tcx>, bounds: &mut ty::BuiltinBounds, @@ -1757,12 +1735,25 @@ fn early_bound_lifetimes_from_generics<'a, 'tcx, 'hir>( fn ty_generic_predicates<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>, space: ParamSpace, ast_generics: &hir::Generics, - base_predicates: &ty::GenericPredicates<'tcx>, + parent: Option, + super_predicates: Vec>, has_self: bool) -> ty::GenericPredicates<'tcx> { let tcx = ccx.tcx; - let mut result = base_predicates.clone(); + let ref base_predicates = match parent { + Some(def_id) => { + assert_eq!(super_predicates, vec![]); + tcx.lookup_predicates(def_id) + } + None => { + ty::GenericPredicates { + parent: None, + predicates: super_predicates.clone() + } + } + }; + let mut predicates = super_predicates; // Collect the predicates that were written inline by the user on each // type parameter (e.g., ``). @@ -1775,7 +1766,7 @@ fn ty_generic_predicates<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>, SizedByDefault::Yes, None, param.span); - result.predicates.extend(bounds.predicates(ccx.tcx, param_ty)); + predicates.extend(bounds.predicates(ccx.tcx, param_ty)); } // Collect the region predicates that were declared inline as @@ -1793,7 +1784,7 @@ fn ty_generic_predicates<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>, for bound in ¶m.bounds { let bound_region = ast_region_to_region(ccx.tcx, bound); let outlives = ty::Binder(ty::OutlivesPredicate(region, bound_region)); - result.predicates.push(outlives.to_predicate()); + predicates.push(outlives.to_predicate()); } } @@ -1819,17 +1810,17 @@ fn ty_generic_predicates<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>, ty, &mut projections); - result.predicates.push(trait_ref.to_predicate()); + predicates.push(trait_ref.to_predicate()); for projection in &projections { - result.predicates.push(projection.to_predicate()); + predicates.push(projection.to_predicate()); } } &hir::TyParamBound::RegionTyParamBound(ref lifetime) => { let region = ast_region_to_region(tcx, lifetime); let pred = ty::Binder(ty::OutlivesPredicate(ty, region)); - result.predicates.push(ty::Predicate::TypeOutlives(pred)) + predicates.push(ty::Predicate::TypeOutlives(pred)) } } } @@ -1840,7 +1831,7 @@ fn ty_generic_predicates<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>, for bound in ®ion_pred.bounds { let r2 = ast_region_to_region(tcx, bound); let pred = ty::Binder(ty::OutlivesPredicate(r1, r2)); - result.predicates.push(ty::Predicate::RegionOutlives(pred)) + predicates.push(ty::Predicate::RegionOutlives(pred)) } } @@ -1853,7 +1844,10 @@ fn ty_generic_predicates<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>, } } - result + ty::GenericPredicates { + parent: parent, + predicates: predicates + } } fn get_or_create_type_parameter_def<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>, diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index 07821a730ccf6..90288b17dfcce 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -1348,17 +1348,7 @@ impl Clean for hir::ImplItem { impl<'tcx> Clean for ty::Method<'tcx> { fn clean(&self, cx: &DocContext) -> Item { - // Depend on trait/impl predicates always being before method's own predicates, - // to be able to split method predicates into "inherited" and method-specific. - let outer_predicates = cx.tcx().lookup_predicates(self.container_id()).predicates; - let method_start = outer_predicates.len(); - assert_eq!(&outer_predicates[..], &self.predicates.predicates[..method_start]); - - let method_predicates = ty::GenericPredicates { - predicates: self.predicates.predicates[method_start..].to_vec() - }; - - let generics = (self.generics, &method_predicates).clean(cx); + let generics = (self.generics, &self.predicates).clean(cx); let mut decl = (self.def_id, &self.fty.sig).clean(cx); match self.explicit_self { ty::ExplicitSelfCategory::ByValue => { diff --git a/src/test/compile-fail/associated-const-type-parameter-arrays.rs b/src/test/compile-fail/associated-const-type-parameter-arrays.rs index 3d3b795b2291a..ddf16a2278e5b 100644 --- a/src/test/compile-fail/associated-const-type-parameter-arrays.rs +++ b/src/test/compile-fail/associated-const-type-parameter-arrays.rs @@ -25,7 +25,8 @@ impl Foo for Def { } pub fn test() { - let _array: [u32; ::Y]; //~ error: the parameter type + let _array: [u32; ::Y]; + //~^ ERROR the trait bound `A: Foo` is not satisfied } fn main() { From 9453d9b8ada9f6b651b10b3ad8131732fc70c61e Mon Sep 17 00:00:00 2001 From: Eduard Burtescu Date: Wed, 17 Aug 2016 06:32:00 +0300 Subject: [PATCH 12/12] rustc: remove ParamSpace from Substs. --- src/librustc/middle/dead.rs | 4 +- src/librustc/middle/resolve_lifetime.rs | 60 ++-- src/librustc/traits/error_reporting.rs | 6 +- src/librustc/traits/fulfill.rs | 2 +- src/librustc/traits/select.rs | 17 +- src/librustc/traits/specialize/mod.rs | 9 +- src/librustc/ty/context.rs | 9 +- src/librustc/ty/flags.rs | 4 +- src/librustc/ty/mod.rs | 32 +- src/librustc/ty/relate.rs | 49 +-- src/librustc/ty/structural_impls.rs | 14 +- src/librustc/ty/sty.rs | 36 +-- src/librustc/ty/subst.rs | 297 ++---------------- src/librustc/ty/util.rs | 5 +- src/librustc/ty/walk.rs | 8 +- src/librustc/ty/wf.rs | 1 - src/librustc/util/ppaux.rs | 80 ++--- .../borrowck/mir/elaborate_drops.rs | 2 +- src/librustc_driver/test.rs | 21 +- src/librustc_metadata/tydecode.rs | 53 +--- src/librustc_metadata/tyencode.rs | 51 ++- src/librustc_mir/build/scope.rs | 2 +- src/librustc_trans/back/symbol_names.rs | 2 +- src/librustc_trans/debuginfo/metadata.rs | 2 +- src/librustc_trans/debuginfo/mod.rs | 2 +- src/librustc_trans/debuginfo/type_names.rs | 2 +- src/librustc_trans/intrinsic.rs | 56 ++-- src/librustc_trans/monomorphize.rs | 2 +- src/librustc_trans/partitioning.rs | 3 +- src/librustc_trans/trans_item.rs | 6 +- src/librustc_trans/type_of.rs | 10 +- src/librustc_typeck/astconv.rs | 11 +- src/librustc_typeck/check/closure.rs | 3 +- src/librustc_typeck/check/compare_method.rs | 2 +- src/librustc_typeck/check/dropck.rs | 4 +- src/librustc_typeck/check/intrinsic.rs | 6 +- src/librustc_typeck/check/method/confirm.rs | 12 +- src/librustc_typeck/check/method/mod.rs | 3 +- src/librustc_typeck/check/method/probe.rs | 18 +- src/librustc_typeck/check/mod.rs | 88 +++--- src/librustc_typeck/check/regionck.rs | 10 +- src/librustc_typeck/check/wfcheck.rs | 18 +- src/librustc_typeck/check/writeback.rs | 3 +- src/librustc_typeck/coherence/mod.rs | 4 +- src/librustc_typeck/collect.rs | 96 +++--- src/librustc_typeck/variance/constraints.rs | 19 +- src/librustc_typeck/variance/solve.rs | 29 +- src/librustc_typeck/variance/terms.rs | 30 +- src/librustdoc/clean/inline.rs | 2 - src/librustdoc/clean/mod.rs | 24 +- .../compile-fail/variance-associated-types.rs | 4 +- .../compile-fail/variance-object-types.rs | 2 +- .../compile-fail/variance-region-bounds.rs | 4 +- .../compile-fail/variance-regions-direct.rs | 14 +- .../compile-fail/variance-regions-indirect.rs | 10 +- .../compile-fail/variance-trait-bounds.rs | 18 +- .../variance-trait-object-bound.rs | 2 +- .../compile-fail/variance-types-bounds.rs | 20 +- src/test/compile-fail/variance-types.rs | 12 +- src/test/mir-opt/storage_ranges.rs | 4 +- 60 files changed, 462 insertions(+), 857 deletions(-) diff --git a/src/librustc/middle/dead.rs b/src/librustc/middle/dead.rs index 20e281816b8b0..2a8594c59a837 100644 --- a/src/librustc/middle/dead.rs +++ b/src/librustc/middle/dead.rs @@ -18,7 +18,7 @@ use hir::{self, pat_util, PatKind}; use hir::intravisit::{self, Visitor}; use middle::privacy; -use ty::{self, subst, TyCtxt}; +use ty::{self, TyCtxt}; use hir::def::Def; use hir::def_id::{DefId}; use lint; @@ -95,7 +95,7 @@ impl<'a, 'tcx> MarkSymbolVisitor<'a, 'tcx> { 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::TypeSpace, 0).sty { + match substs.substs.types[0].sty { TyEnum(tyid, _) | TyStruct(tyid, _) => { self.check_def_id(tyid.did) } diff --git a/src/librustc/middle/resolve_lifetime.rs b/src/librustc/middle/resolve_lifetime.rs index 9ccca9e6a08f9..8369a6c39d54d 100644 --- a/src/librustc/middle/resolve_lifetime.rs +++ b/src/librustc/middle/resolve_lifetime.rs @@ -24,9 +24,7 @@ use session::Session; use hir::def::{Def, DefMap}; use hir::def_id::DefId; use middle::region; -use ty::subst; use ty; -use std::fmt; use std::mem::replace; use syntax::ast; use syntax::parse::token::keywords; @@ -41,8 +39,7 @@ use hir::intravisit::{self, Visitor, FnKind}; #[derive(Clone, Copy, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable, Debug)] pub enum DefRegion { DefStaticRegion, - DefEarlyBoundRegion(/* space */ subst::ParamSpace, - /* index */ u32, + DefEarlyBoundRegion(/* index */ u32, /* lifetime decl */ ast::NodeId), DefLateBoundRegion(ty::DebruijnIndex, /* lifetime decl */ ast::NodeId), @@ -90,10 +87,11 @@ struct LifetimeContext<'a, 'tcx: 'a> { labels_in_fn: Vec<(ast::Name, Span)>, } +#[derive(PartialEq, Debug)] enum ScopeChain<'a> { - /// EarlyScope(i, ['a, 'b, ...], s) extends s with early-bound - /// lifetimes, assigning indexes 'a => i, 'b => i+1, ... etc. - EarlyScope(subst::ParamSpace, &'a [hir::LifetimeDef], Scope<'a>), + /// EarlyScope(['a, 'b, ...], s) extends s with early-bound + /// lifetimes. + EarlyScope(&'a [hir::LifetimeDef], Scope<'a>), /// LateScope(['a, 'b, ...], s) extends s with late-bound /// lifetimes introduced by the declaration binder_id. LateScope(&'a [hir::LifetimeDef], Scope<'a>), @@ -159,8 +157,7 @@ impl<'a, 'tcx, 'v> Visitor<'v> for LifetimeContext<'a, 'tcx> { hir::ItemImpl(_, _, ref generics, _, _, _) => { // These kinds of items have only early bound lifetime parameters. let lifetimes = &generics.lifetimes; - let early_scope = EarlyScope(subst::TypeSpace, lifetimes, &ROOT_SCOPE); - this.with(early_scope, |old_scope, this| { + this.with(EarlyScope(lifetimes, &ROOT_SCOPE), |old_scope, this| { this.check_lifetime_defs(old_scope, lifetimes); intravisit::walk_item(this, item); }); @@ -181,11 +178,7 @@ impl<'a, 'tcx, 'v> Visitor<'v> for LifetimeContext<'a, 'tcx> { self.with(RootScope, |_, this| { match item.node { hir::ForeignItemFn(ref decl, ref generics) => { - this.visit_early_late(item.id, - subst::FnSpace, - decl, - generics, - |this| { + this.visit_early_late(item.id, decl, generics, |this| { intravisit::walk_foreign_item(this, item); }) } @@ -203,14 +196,13 @@ impl<'a, 'tcx, 'v> Visitor<'v> for LifetimeContext<'a, 'tcx> { b: &'v hir::Block, s: Span, fn_id: ast::NodeId) { match fk { FnKind::ItemFn(_, generics, _, _, _, _, _) => { - self.visit_early_late(fn_id, subst::FnSpace, decl, generics, |this| { + self.visit_early_late(fn_id,decl, generics, |this| { this.add_scope_and_walk_fn(fk, decl, b, s, fn_id) }) } FnKind::Method(_, sig, _, _) => { self.visit_early_late( fn_id, - subst::FnSpace, decl, &sig.generics, |this| this.add_scope_and_walk_fn(fk, decl, b, s, fn_id)); @@ -263,7 +255,7 @@ impl<'a, 'tcx, 'v> Visitor<'v> for LifetimeContext<'a, 'tcx> { if let hir::MethodTraitItem(ref sig, None) = trait_item.node { self.visit_early_late( - trait_item.id, subst::FnSpace, + trait_item.id, &sig.decl, &sig.generics, |this| intravisit::walk_trait_item(this, trait_item)) } else { @@ -469,7 +461,7 @@ fn extract_labels(ctxt: &mut LifetimeContext, b: &hir::Block) { FnScope { s, .. } => { scope = s; } RootScope => { return; } - EarlyScope(_, lifetimes, s) | + EarlyScope(lifetimes, s) | LateScope(lifetimes, s) => { for lifetime_def in lifetimes { // FIXME (#24278): non-hygienic comparison @@ -557,7 +549,6 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> { /// ordering is not important there. fn visit_early_late(&mut self, fn_id: ast::NodeId, - early_space: subst::ParamSpace, decl: &hir::FnDecl, generics: &hir::Generics, walk: F) where @@ -576,7 +567,7 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> { .partition(|l| self.map.late_bound.contains_key(&l.lifetime.id)); let this = self; - this.with(EarlyScope(early_space, &early, this.scope), move |old_scope, this| { + this.with(EarlyScope(&early, this.scope), move |old_scope, this| { this.with(LateScope(&late, this.scope), move |_, this| { this.check_lifetime_defs(old_scope, &generics.lifetimes); walk(this); @@ -606,11 +597,19 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> { break; } - EarlyScope(space, lifetimes, s) => { + EarlyScope(lifetimes, s) => { match search_lifetimes(lifetimes, lifetime_ref) { - Some((index, lifetime_def)) => { + Some((mut index, lifetime_def)) => { + // Adjust for nested early scopes, e.g. in methods. + let mut parent = s; + while let EarlyScope(lifetimes, s) = *parent { + index += lifetimes.len() as u32; + parent = s; + } + assert_eq!(*parent, RootScope); + let decl_id = lifetime_def.id; - let def = DefEarlyBoundRegion(space, index, decl_id); + let def = DefEarlyBoundRegion(index, decl_id); self.insert_lifetime(lifetime_ref, def); return; } @@ -672,7 +671,7 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> { break; } - EarlyScope(_, lifetimes, s) | + EarlyScope(lifetimes, s) | LateScope(lifetimes, s) => { search_result = search_lifetimes(lifetimes, lifetime_ref); if search_result.is_some() { @@ -768,7 +767,7 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> { return; } - EarlyScope(_, lifetimes, s) | + EarlyScope(lifetimes, s) | LateScope(lifetimes, s) => { if let Some((_, lifetime_def)) = search_lifetimes(lifetimes, lifetime) { signal_shadowing_problem( @@ -963,14 +962,3 @@ fn insert_late_bound_lifetimes(map: &mut NamedRegionMap, } } } - -impl<'a> fmt::Debug for ScopeChain<'a> { - fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { - match *self { - EarlyScope(space, defs, _) => write!(fmt, "EarlyScope({:?}, {:?})", space, defs), - LateScope(defs, _) => write!(fmt, "LateScope({:?})", defs), - FnScope { fn_id, body_id, s: _ } => write!(fmt, "FnScope({:?}, {:?})", fn_id, body_id), - RootScope => write!(fmt, "RootScope"), - } - } -} diff --git a/src/librustc/traits/error_reporting.rs b/src/librustc/traits/error_reporting.rs index 77d7d5115efbc..33db0053cda13 100644 --- a/src/librustc/traits/error_reporting.rs +++ b/src/librustc/traits/error_reporting.rs @@ -31,7 +31,7 @@ use ty::{self, ToPredicate, ToPolyTraitRef, Ty, TyCtxt, TypeFoldable}; use ty::error::ExpectedFound; use ty::fast_reject; use ty::fold::TypeFolder; -use ty::subst::{Subst, TypeSpace}; +use ty::subst::Subst; use util::nodemap::{FnvHashMap, FnvHashSet}; use std::cmp; @@ -232,8 +232,8 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { if let Ok(..) = self.can_equate(&trait_self_ty, &impl_self_ty) { self_match_impls.push(def_id); - if trait_ref.substs.types.get_slice(TypeSpace)[1..].iter() - .zip(&impl_trait_ref.substs.types.get_slice(TypeSpace)[1..]) + if trait_ref.substs.types[1..].iter() + .zip(&impl_trait_ref.substs.types[1..]) .all(|(u,v)| self.fuzzy_match_tys(u, v)) { fuzzy_match_impls.push(def_id); diff --git a/src/librustc/traits/fulfill.rs b/src/librustc/traits/fulfill.rs index 3698027dca887..837e33b3e7fc2 100644 --- a/src/librustc/traits/fulfill.rs +++ b/src/librustc/traits/fulfill.rs @@ -142,7 +142,7 @@ impl<'a, 'gcx, 'tcx> DeferredObligation<'tcx> { // Auto trait obligations on `impl Trait`. if tcx.trait_has_default_impl(predicate.def_id()) { let substs = predicate.skip_binder().trait_ref.substs; - if substs.types.as_full_slice().len() == 1 && substs.regions.is_empty() { + if substs.types.len() == 1 && substs.regions.is_empty() { if let ty::TyAnon(..) = predicate.skip_binder().self_ty().sty { return true; } diff --git a/src/librustc/traits/select.rs b/src/librustc/traits/select.rs index bf6aad98db1a8..9ea738bd326eb 100644 --- a/src/librustc/traits/select.rs +++ b/src/librustc/traits/select.rs @@ -36,7 +36,7 @@ use super::util; use hir::def_id::DefId; use infer; use infer::{InferCtxt, InferOk, TypeFreshener, TypeOrigin}; -use ty::subst::{Subst, Substs, TypeSpace}; +use ty::subst::{Subst, Substs}; use ty::{self, ToPredicate, ToPolyTraitRef, Ty, TyCtxt, TypeFoldable}; use traits; use ty::fast_reject; @@ -1936,7 +1936,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { // for `PhantomData`, we pass `T` ty::TyStruct(def, substs) if def.is_phantom_data() => { - substs.types.as_full_slice().to_vec() + substs.types.to_vec() } ty::TyStruct(def, substs) | ty::TyEnum(def, substs) => { @@ -2585,11 +2585,10 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { } else { return Err(Unimplemented); }; - let mut ty_params = BitVector::new(substs_a.types.len(TypeSpace)); + let mut ty_params = BitVector::new(substs_a.types.len()); let mut found = false; for ty in field.walk() { if let ty::TyParam(p) = ty.sty { - assert!(p.space == TypeSpace); ty_params.insert(p.idx as usize); found = true; } @@ -2602,13 +2601,13 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { // 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 types = substs_a.types.map_enumerated(|(_, i, ty)| { + let types = substs_a.types.iter().enumerate().map(|(i, ty)| { if ty_params.contains(i) { tcx.types.err } else { ty } - }); + }).collect(); let substs = Substs::new(tcx, types, substs_a.regions.clone()); for &ty in fields.split_last().unwrap().1 { if ty.subst(tcx, substs).references_error() { @@ -2622,13 +2621,13 @@ 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. - let types = substs_a.types.map_enumerated(|(_, i, ty)| { + let types = substs_a.types.iter().enumerate().map(|(i, ty)| { if ty_params.contains(i) { - *substs_b.types.get(TypeSpace, i) + substs_b.types[i] } else { ty } - }); + }).collect(); 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); diff --git a/src/librustc/traits/specialize/mod.rs b/src/librustc/traits/specialize/mod.rs index 42865ca927de3..9acfe2754820c 100644 --- a/src/librustc/traits/specialize/mod.rs +++ b/src/librustc/traits/specialize/mod.rs @@ -44,11 +44,10 @@ pub struct OverlapError { /// When we have selected one impl, but are actually using item definitions from /// a parent impl providing a default, we need a way to translate between the /// type parameters of the two impls. Here the `source_impl` is the one we've -/// selected, and `source_substs` is a substitution of its generics (and -/// possibly some relevant `FnSpace` variables as well). And `target_node` is -/// the impl/trait we're actually going to get the definition from. The resulting -/// substitution will map from `target_node`'s generics to `source_impl`'s -/// generics as instantiated by `source_subst`. +/// selected, and `source_substs` is a substitution of its generics. +/// And `target_node` is the impl/trait we're actually going to get the +/// definition from. The resulting substitution will map from `target_node`'s +/// generics to `source_impl`'s generics as instantiated by `source_subst`. /// /// For example, consider the following scenario: /// diff --git a/src/librustc/ty/context.rs b/src/librustc/ty/context.rs index c2daa81ca7dab..3501dd4846087 100644 --- a/src/librustc/ty/context.rs +++ b/src/librustc/ty/context.rs @@ -23,7 +23,7 @@ use middle::free_region::FreeRegionMap; use middle::region::RegionMaps; use middle::resolve_lifetime; use middle::stability; -use ty::subst::{self, Substs}; +use ty::subst::Substs; use traits; use ty::{self, TraitRef, Ty, TypeAndMut}; use ty::{TyS, TypeVariants}; @@ -1346,18 +1346,17 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { } pub fn mk_param(self, - space: subst::ParamSpace, index: u32, name: Name) -> Ty<'tcx> { - self.mk_ty(TyParam(ParamTy { space: space, idx: index, name: name })) + self.mk_ty(TyParam(ParamTy { idx: index, name: name })) } pub fn mk_self_type(self) -> Ty<'tcx> { - self.mk_param(subst::TypeSpace, 0, keywords::SelfType.name()) + self.mk_param(0, keywords::SelfType.name()) } pub fn mk_param_from_def(self, def: &ty::TypeParameterDef) -> Ty<'tcx> { - self.mk_param(def.space, def.index, def.name) + self.mk_param(def.index, def.name) } pub fn mk_anon(self, def_id: DefId, substs: &'tcx Substs<'tcx>) -> Ty<'tcx> { diff --git a/src/librustc/ty/flags.rs b/src/librustc/ty/flags.rs index 900e1841fb592..c6c37296e9e12 100644 --- a/src/librustc/ty/flags.rs +++ b/src/librustc/ty/flags.rs @@ -208,8 +208,8 @@ impl FlagComputation { } fn add_substs(&mut self, substs: &Substs) { - self.add_tys(substs.types.as_full_slice()); - for &r in substs.regions.as_full_slice() { + self.add_tys(&substs.types); + for &r in &substs.regions { self.add_region(r); } } diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs index b2b8286be2fba..1f747ddfb2959 100644 --- a/src/librustc/ty/mod.rs +++ b/src/librustc/ty/mod.rs @@ -28,7 +28,7 @@ use middle::lang_items::{FnTraitLangItem, FnMutTraitLangItem, FnOnceTraitLangIte use middle::region::{CodeExtent, ROOT_CODE_EXTENT}; use traits; use ty; -use ty::subst::{Subst, Substs, VecPerParamSpace}; +use ty::subst::{Subst, Substs}; use ty::walk::TypeWalker; use util::common::MemoizationMap; use util::nodemap::NodeSet; @@ -426,15 +426,15 @@ pub struct AssociatedType<'tcx> { #[derive(Clone, PartialEq, RustcDecodable, RustcEncodable)] pub struct ItemVariances { - pub types: VecPerParamSpace, - pub regions: VecPerParamSpace, + pub types: Vec, + pub regions: Vec, } impl ItemVariances { pub fn empty() -> ItemVariances { ItemVariances { - types: VecPerParamSpace::empty(), - regions: VecPerParamSpace::empty(), + types: vec![], + regions: vec![], } } } @@ -723,7 +723,6 @@ pub enum ObjectLifetimeDefault { pub struct TypeParameterDef<'tcx> { pub name: Name, pub def_id: DefId, - pub space: subst::ParamSpace, pub index: u32, pub default_def_id: DefId, // for use in error reporing about defaults pub default: Option>, @@ -734,7 +733,6 @@ pub struct TypeParameterDef<'tcx> { pub struct RegionParameterDef { pub name: Name, pub def_id: DefId, - pub space: subst::ParamSpace, pub index: u32, pub bounds: Vec, } @@ -742,7 +740,6 @@ pub struct RegionParameterDef { impl RegionParameterDef { pub fn to_early_bound_region(&self) -> ty::Region { ty::ReEarlyBound(ty::EarlyBoundRegion { - space: self.space, index: self.index, name: self.name, }) @@ -812,7 +809,7 @@ impl<'a, 'gcx, 'tcx> GenericPredicates<'tcx> { pub enum Predicate<'tcx> { /// Corresponds to `where Foo : Bar`. `Foo` here would be /// the `Self` type of the trait reference and `A`, `B`, and `C` - /// would be the parameters in the `TypeSpace`. + /// would be the type parameters. Trait(PolyTraitPredicate<'tcx>), /// A predicate created by RFC1592 @@ -837,9 +834,9 @@ pub enum Predicate<'tcx> { /// trait must be object-safe ObjectSafe(DefId), - /// No direct syntax. May be thought of as `where T : FnFoo<...>` for some 'TypeSpace' - /// substitutions `...` and T being a closure type. Satisfied (or refuted) once we know the - /// closure's kind. + /// No direct syntax. May be thought of as `where T : FnFoo<...>` + /// for some substitutions `...` and T being a closure type. + /// Satisfied (or refuted) once we know the closure's kind. ClosureKind(DefId, ClosureKind), } @@ -975,7 +972,7 @@ impl<'tcx> TraitPredicate<'tcx> { } pub fn input_types(&self) -> &[Ty<'tcx>] { - self.trait_ref.substs.types.as_full_slice() + &self.trait_ref.substs.types } pub fn self_ty(&self) -> Ty<'tcx> { @@ -1117,7 +1114,7 @@ impl<'tcx> Predicate<'tcx> { pub fn walk_tys(&self) -> IntoIter> { let vec: Vec<_> = match *self { ty::Predicate::Trait(ref data) => { - data.0.trait_ref.substs.types.as_full_slice().to_vec() + data.0.trait_ref.input_types().to_vec() } ty::Predicate::Rfc1592(ref data) => { return data.walk_tys() @@ -1132,8 +1129,7 @@ impl<'tcx> Predicate<'tcx> { vec![] } ty::Predicate::Projection(ref data) => { - let trait_inputs = data.0.projection_ty.trait_ref.substs - .types.as_full_slice(); + let trait_inputs = data.0.projection_ty.trait_ref.input_types(); trait_inputs.iter() .cloned() .chain(Some(data.0.ty)) @@ -1217,7 +1213,7 @@ impl<'tcx> TraitRef<'tcx> { } pub fn self_ty(&self) -> Ty<'tcx> { - *self.substs.types.get(subst::TypeSpace, 0) + self.substs.types[0] } pub fn input_types(&self) -> &[Ty<'tcx>] { @@ -1225,7 +1221,7 @@ impl<'tcx> TraitRef<'tcx> { // now this is all the types that appear in the // trait-reference, but it should eventually exclude // associated types. - self.substs.types.as_full_slice() + &self.substs.types } } diff --git a/src/librustc/ty/relate.rs b/src/librustc/ty/relate.rs index 388e8926403fd..abf863f953664 100644 --- a/src/librustc/ty/relate.rs +++ b/src/librustc/ty/relate.rs @@ -146,41 +146,18 @@ pub fn relate_substs<'a, 'gcx, 'tcx, R>(relation: &mut R, where R: TypeRelation<'a, 'gcx, 'tcx>, 'gcx: 'a+'tcx, 'tcx: 'a { let tcx = relation.tcx(); - let mut result = Ok(()); - - let types = a_subst.types.map_enumerated(|(space, i, a_ty)| { - if result.is_err() { return tcx.types.err; } - - let b_ty = b_subst.types.get(space, i); - let variance = variances.map_or(ty::Invariant, |v| { - *v.types.get(space, i) - }); - match relation.relate_with_variance(variance, a_ty, b_ty) { - Ok(ty) => ty, - Err(e) => { - result = Err(e); - tcx.types.err - } - } - }); - result?; - - let regions = a_subst.regions.map_enumerated(|(space, i, a_r)| { - if result.is_err() { return ty::ReStatic; } - - let b_r = b_subst.regions.get(space, i); - let variance = variances.map_or(ty::Invariant, |v| { - *v.regions.get(space, i) - }); - match relation.relate_with_variance(variance, a_r, b_r) { - Ok(r) => r, - Err(e) => { - result = Err(e); - ty::ReStatic - } - } - }); - result?; + + let types = a_subst.types.iter().enumerate().map(|(i, a_ty)| { + let b_ty = &b_subst.types[i]; + let variance = variances.map_or(ty::Invariant, |v| v.types[i]); + relation.relate_with_variance(variance, a_ty, b_ty) + }).collect()?; + + let regions = a_subst.regions.iter().enumerate().map(|(i, a_r)| { + let b_r = &b_subst.regions[i]; + let variance = variances.map_or(ty::Invariant, |v| v.regions[i]); + relation.relate_with_variance(variance, a_r, b_r) + }).collect()?; Ok(Substs::new(tcx, types, regions)) } @@ -433,7 +410,7 @@ pub fn super_relate_tys<'a, 'gcx, 'tcx, R>(relation: &mut R, } (&ty::TyParam(ref a_p), &ty::TyParam(ref b_p)) - if a_p.idx == b_p.idx && a_p.space == b_p.space => + if a_p.idx == b_p.idx => { Ok(a) } diff --git a/src/librustc/ty/structural_impls.rs b/src/librustc/ty/structural_impls.rs index 021ae820b87c5..f7c4b9938c279 100644 --- a/src/librustc/ty/structural_impls.rs +++ b/src/librustc/ty/structural_impls.rs @@ -9,7 +9,7 @@ // except according to those terms. use infer::type_variable; -use ty::subst::{Substs, VecPerParamSpace}; +use ty::subst::Substs; use ty::{self, Lift, Ty, TyCtxt}; use ty::fold::{TypeFoldable, TypeFolder, TypeVisitor}; @@ -450,16 +450,6 @@ impl<'tcx, T: TypeFoldable<'tcx>> TypeFoldable<'tcx> for P<[T]> { } } -impl<'tcx, T: TypeFoldable<'tcx>> TypeFoldable<'tcx> for VecPerParamSpace { - fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) -> Self { - self.map(|elem| elem.fold_with(folder)) - } - - fn super_visit_with>(&self, visitor: &mut V) -> bool { - self.as_full_slice().iter().any(|elem| elem.visit_with(visitor)) - } -} - impl<'tcx> TypeFoldable<'tcx> for ty::TraitObject<'tcx> { fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) -> Self { ty::TraitObject { @@ -780,7 +770,6 @@ impl<'tcx> TypeFoldable<'tcx> for ty::TypeParameterDef<'tcx> { ty::TypeParameterDef { name: self.name, def_id: self.def_id, - space: self.space, index: self.index, default: self.default.fold_with(folder), default_def_id: self.default_def_id, @@ -821,7 +810,6 @@ impl<'tcx> TypeFoldable<'tcx> for ty::RegionParameterDef { ty::RegionParameterDef { name: self.name, def_id: self.def_id, - space: self.space, index: self.index, bounds: self.bounds.fold_with(folder), } diff --git a/src/librustc/ty/sty.rs b/src/librustc/ty/sty.rs index 8786e2d16d22a..8aa81cc4743c9 100644 --- a/src/librustc/ty/sty.rs +++ b/src/librustc/ty/sty.rs @@ -13,7 +13,7 @@ use middle::cstore; use hir::def_id::DefId; use middle::region; -use ty::subst::{self, Substs}; +use ty::subst::Substs; use ty::{self, AdtDef, ToPredicate, TypeFlags, Ty, TyCtxt, TyS, TypeFoldable}; use util::common::ErrorReported; @@ -304,8 +304,8 @@ pub struct TraitObject<'tcx> { /// T : Foo /// /// This would be represented by a trait-reference where the def-id is the -/// def-id for the trait `Foo` and the substs defines `T` as parameter 0 in the -/// `TypeSpace` and `U` as parameter 1 in the `TypeSpace`. +/// def-id for the trait `Foo` and the substs define `T` as parameter 0, +/// and `U` as parameter 1. /// /// Trait references also appear in object types like `Foo`, but in /// that case the `Self` parameter is absent from the substitutions. @@ -365,7 +365,7 @@ impl<'tcx> ExistentialTraitRef<'tcx> { // now this is all the types that appear in the // trait-reference, but it should eventually exclude // associated types. - self.substs.types.as_full_slice() + &self.substs.types } } @@ -498,34 +498,29 @@ impl<'tcx> PolyFnSig<'tcx> { #[derive(Clone, Copy, PartialEq, Eq, Hash)] pub struct ParamTy { - pub space: subst::ParamSpace, pub idx: u32, pub name: Name, } impl<'a, 'gcx, 'tcx> ParamTy { - pub fn new(space: subst::ParamSpace, - index: u32, - name: Name) - -> ParamTy { - ParamTy { space: space, idx: index, name: name } + pub fn new(index: u32, name: Name) -> ParamTy { + ParamTy { idx: index, name: name } } pub fn for_self() -> ParamTy { - ParamTy::new(subst::TypeSpace, 0, keywords::SelfType.name()) + ParamTy::new(0, keywords::SelfType.name()) } pub fn for_def(def: &ty::TypeParameterDef) -> ParamTy { - ParamTy::new(def.space, def.index, def.name) + ParamTy::new(def.index, def.name) } pub fn to_ty(self, tcx: TyCtxt<'a, 'gcx, 'tcx>) -> Ty<'tcx> { - tcx.mk_param(self.space, self.idx, self.name) + tcx.mk_param(self.idx, self.name) } pub fn is_self(&self) -> bool { if self.name == keywords::SelfType.name() { - assert_eq!(self.space, subst::TypeSpace); assert_eq!(self.idx, 0); true } else { @@ -682,7 +677,6 @@ pub enum Region { #[derive(Copy, Clone, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable, Debug)] pub struct EarlyBoundRegion { - pub space: subst::ParamSpace, pub index: u32, pub name: Name, } @@ -951,9 +945,9 @@ impl<'a, 'gcx, 'tcx> TyS<'tcx> { pub fn is_bool(&self) -> bool { self.sty == TyBool } - pub fn is_param(&self, space: subst::ParamSpace, index: u32) -> bool { + pub fn is_param(&self, index: u32) -> bool { match self.sty { - ty::TyParam(ref data) => data.space == space && data.idx == index, + ty::TyParam(ref data) => data.idx == index, _ => false, } } @@ -1219,19 +1213,19 @@ impl<'a, 'gcx, 'tcx> TyS<'tcx> { } TyTrait(ref obj) => { let mut v = vec![obj.region_bound]; - v.extend_from_slice(obj.principal.skip_binder().substs.regions.as_full_slice()); + v.extend_from_slice(&obj.principal.skip_binder().substs.regions); v } TyEnum(_, substs) | TyStruct(_, substs) | TyAnon(_, substs) => { - substs.regions.as_full_slice().to_vec() + substs.regions.to_vec() } TyClosure(_, ref substs) => { - substs.func_substs.regions.as_full_slice().to_vec() + substs.func_substs.regions.to_vec() } TyProjection(ref data) => { - data.trait_ref.substs.regions.as_full_slice().to_vec() + data.trait_ref.substs.regions.to_vec() } TyFnDef(..) | TyFnPtr(_) | diff --git a/src/librustc/ty/subst.rs b/src/librustc/ty/subst.rs index 594d15ad5f734..e1a19a7b7992e 100644 --- a/src/librustc/ty/subst.rs +++ b/src/librustc/ty/subst.rs @@ -10,56 +10,32 @@ // Type substitutions. -pub use self::ParamSpace::*; - use middle::cstore; use hir::def_id::DefId; use ty::{self, Ty, TyCtxt}; use ty::fold::{TypeFoldable, TypeFolder}; use serialize::{Encodable, Encoder, Decodable, Decoder}; -use std::fmt; use syntax_pos::{Span, DUMMY_SP}; /////////////////////////////////////////////////////////////////////////// -/// A substitution mapping type/region parameters to new values. We -/// identify each in-scope parameter by an *index* and a *parameter -/// space* (which indices where the parameter is defined; see -/// `ParamSpace`). +/// A substitution mapping type/region parameters to new values. #[derive(Clone, PartialEq, Eq, Hash)] pub struct Substs<'tcx> { - pub types: VecPerParamSpace>, - pub regions: VecPerParamSpace, + pub types: Vec>, + pub regions: Vec, } impl<'a, 'gcx, 'tcx> Substs<'tcx> { pub fn new(tcx: TyCtxt<'a, 'gcx, 'tcx>, - t: VecPerParamSpace>, - r: VecPerParamSpace) + t: Vec>, + r: Vec) -> &'tcx Substs<'tcx> { tcx.mk_substs(Substs { types: t, regions: r }) } - pub fn new_fn(tcx: TyCtxt<'a, 'gcx, 'tcx>, - t: Vec>, - r: Vec) - -> &'tcx Substs<'tcx> - { - Substs::new(tcx, VecPerParamSpace::new(vec![], t), - VecPerParamSpace::new(vec![], r)) - } - - pub fn new_type(tcx: TyCtxt<'a, 'gcx, 'tcx>, - t: Vec>, - r: Vec) - -> &'tcx Substs<'tcx> - { - Substs::new(tcx, VecPerParamSpace::new(t, vec![]), - VecPerParamSpace::new(r, vec![])) - } - pub fn new_trait(tcx: TyCtxt<'a, 'gcx, 'tcx>, mut t: Vec>, r: Vec, @@ -67,13 +43,11 @@ impl<'a, 'gcx, 'tcx> Substs<'tcx> { -> &'tcx Substs<'tcx> { t.insert(0, s); - Substs::new(tcx, VecPerParamSpace::new(t, vec![]), - VecPerParamSpace::new(r, vec![])) + Substs::new(tcx, t, r) } pub fn empty(tcx: TyCtxt<'a, 'gcx, 'tcx>) -> &'tcx Substs<'tcx> { - Substs::new(tcx, VecPerParamSpace::empty(), - VecPerParamSpace::empty()) + Substs::new(tcx, vec![], vec![]) } /// Creates a Substs for generic parameter definitions, @@ -92,14 +66,8 @@ impl<'a, 'gcx, 'tcx> Substs<'tcx> { let num_regions = defs.parent_regions as usize + defs.regions.len(); let num_types = defs.parent_types as usize + defs.types.len(); let mut substs = Substs { - regions: VecPerParamSpace { - type_limit: 0, - content: Vec::with_capacity(num_regions) - }, - types: VecPerParamSpace { - type_limit: 0, - content: Vec::with_capacity(num_types) - } + regions: Vec::with_capacity(num_regions), + types: Vec::with_capacity(num_types) }; substs.fill_item(tcx, defs, &mut mk_region, &mut mk_type); @@ -121,22 +89,14 @@ impl<'a, 'gcx, 'tcx> Substs<'tcx> { for def in &defs.regions { let region = mk_region(def, self); - self.regions.content.push(region); - - if def.space == TypeSpace { - self.regions.type_limit += 1; - assert_eq!(self.regions.content.len(), self.regions.type_limit); - } + assert_eq!(def.index as usize, self.regions.len()); + self.regions.push(region); } for def in &defs.types { let ty = mk_type(def, self); - self.types.content.push(ty); - - if def.space == TypeSpace { - self.types.type_limit += 1; - assert_eq!(self.types.content.len(), self.types.type_limit); - } + assert_eq!(def.index as usize, self.types.len()); + self.types.push(ty); } } @@ -145,11 +105,11 @@ impl<'a, 'gcx, 'tcx> Substs<'tcx> { } pub fn type_for_def(&self, ty_param_def: &ty::TypeParameterDef) -> Ty<'tcx> { - *self.types.get(ty_param_def.space, ty_param_def.index as usize) + self.types[ty_param_def.index as usize] } pub fn region_for_def(&self, def: &ty::RegionParameterDef) -> ty::Region { - *self.regions.get(def.space, def.index as usize) + self.regions[def.index as usize] } /// Transform from substitutions for a child of `source_ancestor` @@ -162,14 +122,10 @@ impl<'a, 'gcx, 'tcx> Substs<'tcx> { target_substs: &Substs<'tcx>) -> &'tcx Substs<'tcx> { let defs = tcx.lookup_generics(source_ancestor); - assert_eq!(self.types.len(TypeSpace), defs.types.len()); - assert_eq!(target_substs.types.len(FnSpace), 0); - assert_eq!(self.regions.len(TypeSpace), defs.regions.len()); - assert_eq!(target_substs.regions.len(FnSpace), 0); - - let Substs { mut types, mut regions } = target_substs.clone(); - types.content.extend(&self.types.as_full_slice()[defs.types.len()..]); - regions.content.extend(&self.regions.as_full_slice()[defs.regions.len()..]); + let regions = target_substs.regions.iter() + .chain(&self.regions[defs.regions.len()..]).cloned().collect(); + let types = target_substs.types.iter() + .chain(&self.types[defs.types.len()..]).cloned().collect(); Substs::new(tcx, types, regions) } } @@ -193,200 +149,6 @@ impl<'tcx> Decodable for &'tcx Substs<'tcx> { } } -/////////////////////////////////////////////////////////////////////////// -// ParamSpace - -#[derive(PartialOrd, Ord, PartialEq, Eq, Copy, - Clone, Hash, RustcEncodable, RustcDecodable, Debug)] -pub enum ParamSpace { - TypeSpace, // Type parameters attached to a type definition, trait, or impl - FnSpace, // Type parameters attached to a method or fn -} - -impl ParamSpace { - pub fn all() -> [ParamSpace; 2] { - [TypeSpace, FnSpace] - } - - pub fn to_uint(self) -> usize { - match self { - TypeSpace => 0, - FnSpace => 1, - } - } - - pub fn from_uint(u: usize) -> ParamSpace { - match u { - 0 => TypeSpace, - 1 => FnSpace, - _ => bug!("Invalid ParamSpace: {}", u) - } - } -} - -/// Vector of things sorted by param space. Used to keep -/// the set of things declared on the type, self, or method -/// distinct. -#[derive(PartialEq, Eq, Clone, Hash, RustcEncodable, RustcDecodable)] -pub struct VecPerParamSpace { - // This was originally represented as a tuple with one Vec for - // each variant of ParamSpace, and that remains the abstraction - // that it provides to its clients. - // - // Here is how the representation corresponds to the abstraction - // i.e. the "abstraction function" AF: - // - // AF(self) = (self.content[..self.type_limit], - // self.content[self.type_limit..]) - type_limit: usize, - content: Vec, -} - -impl fmt::Debug for VecPerParamSpace { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!(f, "[{:?};{:?}]", - self.get_slice(TypeSpace), - self.get_slice(FnSpace)) - } -} - -impl VecPerParamSpace { - fn limits(&self, space: ParamSpace) -> (usize, usize) { - match space { - TypeSpace => (0, self.type_limit), - FnSpace => (self.type_limit, self.content.len()), - } - } - - pub fn empty() -> VecPerParamSpace { - VecPerParamSpace { - type_limit: 0, - content: Vec::new() - } - } - - /// `t` is the type space. - /// `f` is the fn space. - pub fn new(t: Vec, f: Vec) -> VecPerParamSpace { - let type_limit = t.len(); - - let mut content = t; - content.extend(f); - - VecPerParamSpace { - type_limit: type_limit, - content: content, - } - } - - fn new_internal(content: Vec, type_limit: usize) -> VecPerParamSpace { - VecPerParamSpace { - type_limit: type_limit, - content: content, - } - } - - pub fn len(&self, space: ParamSpace) -> usize { - self.get_slice(space).len() - } - - pub fn is_empty_in(&self, space: ParamSpace) -> bool { - self.len(space) == 0 - } - - pub fn get_slice<'a>(&'a self, space: ParamSpace) -> &'a [T] { - let (start, limit) = self.limits(space); - &self.content[start.. limit] - } - - pub fn get<'a>(&'a self, space: ParamSpace, index: usize) -> &'a T { - &self.get_slice(space)[index] - } - - pub fn iter_enumerated<'a>(&'a self) -> EnumeratedItems<'a,T> { - EnumeratedItems::new(self) - } - - pub fn as_full_slice(&self) -> &[T] { - &self.content - } - - pub fn all

(&self, pred: P) -> bool where P: FnMut(&T) -> bool { - self.as_full_slice().iter().all(pred) - } - - pub fn any

(&self, pred: P) -> bool where P: FnMut(&T) -> bool { - self.as_full_slice().iter().any(pred) - } - - pub fn is_empty(&self) -> bool { - self.content.is_empty() - } - - pub fn map(&self, pred: P) -> VecPerParamSpace where P: FnMut(&T) -> U { - let result = self.as_full_slice().iter().map(pred).collect(); - VecPerParamSpace::new_internal(result, self.type_limit) - } - - pub fn map_enumerated(&self, pred: P) -> VecPerParamSpace where - P: FnMut((ParamSpace, usize, &T)) -> U, - { - let result = self.iter_enumerated().map(pred).collect(); - VecPerParamSpace::new_internal(result, self.type_limit) - } -} - -#[derive(Clone)] -pub struct EnumeratedItems<'a,T:'a> { - vec: &'a VecPerParamSpace, - space_index: usize, - elem_index: usize -} - -impl<'a,T> EnumeratedItems<'a,T> { - fn new(v: &'a VecPerParamSpace) -> EnumeratedItems<'a,T> { - let mut result = EnumeratedItems { vec: v, space_index: 0, elem_index: 0 }; - result.adjust_space(); - result - } - - fn adjust_space(&mut self) { - let spaces = ParamSpace::all(); - while - self.space_index < spaces.len() && - self.elem_index >= self.vec.len(spaces[self.space_index]) - { - self.space_index += 1; - self.elem_index = 0; - } - } -} - -impl<'a,T> Iterator for EnumeratedItems<'a,T> { - type Item = (ParamSpace, usize, &'a T); - - fn next(&mut self) -> Option<(ParamSpace, usize, &'a T)> { - let spaces = ParamSpace::all(); - if self.space_index < spaces.len() { - let space = spaces[self.space_index]; - let index = self.elem_index; - let item = self.vec.get(space, index); - - self.elem_index += 1; - self.adjust_space(); - - Some((space, index, item)) - } else { - None - } - } - - fn size_hint(&self) -> (usize, Option) { - let size = self.vec.as_full_slice().len(); - (size, Some(size)) - } -} - /////////////////////////////////////////////////////////////////////////// // Public trait `Subst` @@ -461,7 +223,7 @@ impl<'a, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for SubstFolder<'a, 'gcx, 'tcx> { // the specialized routine `ty::replace_late_regions()`. match r { ty::ReEarlyBound(data) => { - match self.substs.regions.get_slice(data.space).get(data.index as usize) { + match self.substs.regions.get(data.index as usize) { Some(&r) => { self.shift_region_through_binders(r) } @@ -471,10 +233,9 @@ impl<'a, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for SubstFolder<'a, 'gcx, 'tcx> { span, "Region parameter out of range \ when substituting in region {} (root type={:?}) \ - (space={:?}, index={})", + (index={})", data.name, self.root_ty, - data.space, data.index); } } @@ -517,18 +278,17 @@ impl<'a, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for SubstFolder<'a, 'gcx, 'tcx> { impl<'a, 'gcx, 'tcx> SubstFolder<'a, 'gcx, 'tcx> { fn ty_for_param(&self, p: ty::ParamTy, source_ty: Ty<'tcx>) -> Ty<'tcx> { // Look up the type in the substitutions. It really should be in there. - let opt_ty = self.substs.types.get_slice(p.space).get(p.idx as usize); + let opt_ty = self.substs.types.get(p.idx as usize); let ty = match opt_ty { Some(t) => *t, None => { let span = self.span.unwrap_or(DUMMY_SP); span_bug!( span, - "Type parameter `{:?}` ({:?}/{:?}/{}) out of range \ + "Type parameter `{:?}` ({:?}/{}) out of range \ when substituting (root type={:?}) substs={:?}", p, source_ty, - p.space, p.idx, self.root_ty, self.substs); @@ -606,10 +366,9 @@ impl<'a, 'gcx, 'tcx> ty::TraitRef<'tcx> { trait_id: DefId, substs: &Substs<'tcx>) -> ty::TraitRef<'tcx> { - let Substs { mut types, mut regions } = substs.clone(); let defs = tcx.lookup_generics(trait_id); - types.content.truncate(defs.types.len()); - regions.content.truncate(defs.regions.len()); + let regions = substs.regions[..defs.regions.len()].to_vec(); + let types = substs.types[..defs.types.len()].to_vec(); ty::TraitRef { def_id: trait_id, @@ -624,8 +383,7 @@ impl<'a, 'gcx, 'tcx> ty::ExistentialTraitRef<'tcx> { -> ty::ExistentialTraitRef<'tcx> { let Substs { mut types, regions } = trait_ref.substs.clone(); - types.type_limit -= 1; - types.content.remove(0); + types.remove(0); ty::ExistentialTraitRef { def_id: trait_ref.def_id, @@ -648,8 +406,7 @@ impl<'a, 'gcx, 'tcx> ty::PolyExistentialTraitRef<'tcx> { self.map_bound(|trait_ref| { let Substs { mut types, regions } = trait_ref.substs.clone(); - types.type_limit += 1; - types.content.insert(0, self_ty); + types.insert(0, self_ty); ty::TraitRef { def_id: trait_ref.def_id, diff --git a/src/librustc/ty/util.rs b/src/librustc/ty/util.rs index 5a73439beac6e..51710c13a7dea 100644 --- a/src/librustc/ty/util.rs +++ b/src/librustc/ty/util.rs @@ -476,7 +476,6 @@ impl<'a, 'gcx, 'tcx> TypeVisitor<'tcx> for TypeIdHasher<'a, 'gcx, 'tcx> { self.hash(tys.len()); } TyParam(p) => { - self.hash(p.space); self.hash(p.idx); self.hash(p.name.as_str()); } @@ -694,8 +693,8 @@ impl<'a, 'tcx> ty::TyS<'tcx> { return false; } - let types_a = substs_a.types.as_full_slice(); - let types_b = substs_b.types.as_full_slice(); + let types_a = &substs_a.types; + let types_b = &substs_b.types; types_a.iter().zip(types_b).all(|(&a, &b)| same_type(a, b)) } diff --git a/src/librustc/ty/walk.rs b/src/librustc/ty/walk.rs index 3bf539245571e..8a9ee45351dfc 100644 --- a/src/librustc/ty/walk.rs +++ b/src/librustc/ty/walk.rs @@ -79,7 +79,7 @@ fn push_subtypes<'tcx>(stack: &mut Vec>, parent_ty: Ty<'tcx>) { stack.push(mt.ty); } ty::TyProjection(ref data) => { - push_reversed(stack, data.trait_ref.substs.types.as_full_slice()); + push_reversed(stack, &data.trait_ref.substs.types); } ty::TyTrait(ref obj) => { push_reversed(stack, obj.principal.input_types()); @@ -90,17 +90,17 @@ fn push_subtypes<'tcx>(stack: &mut Vec>, parent_ty: Ty<'tcx>) { ty::TyEnum(_, ref substs) | ty::TyStruct(_, ref substs) | ty::TyAnon(_, ref substs) => { - push_reversed(stack, substs.types.as_full_slice()); + push_reversed(stack, &substs.types); } ty::TyClosure(_, ref substs) => { - push_reversed(stack, substs.func_substs.types.as_full_slice()); + push_reversed(stack, &substs.func_substs.types); push_reversed(stack, &substs.upvar_tys); } ty::TyTuple(ref ts) => { push_reversed(stack, ts); } ty::TyFnDef(_, substs, ref ft) => { - push_reversed(stack, substs.types.as_full_slice()); + push_reversed(stack, &substs.types); push_sig_subtypes(stack, &ft.sig); } ty::TyFnPtr(ref ft) => { diff --git a/src/librustc/ty/wf.rs b/src/librustc/ty/wf.rs index 77d0835bf6bc1..54b19362b1d86 100644 --- a/src/librustc/ty/wf.rs +++ b/src/librustc/ty/wf.rs @@ -261,7 +261,6 @@ impl<'a, 'gcx, 'tcx> WfPredicates<'a, 'gcx, 'tcx> { let cause = self.cause(traits::MiscObligation); self.out.extend( trait_ref.substs.types - .as_full_slice() .iter() .filter(|ty| !ty.has_escaping_regions()) .map(|ty| traits::Obligation::new(cause.clone(), diff --git a/src/librustc/util/ppaux.rs b/src/librustc/util/ppaux.rs index a62ee37613e50..02ad8fb7033ed 100644 --- a/src/librustc/util/ppaux.rs +++ b/src/librustc/util/ppaux.rs @@ -56,7 +56,7 @@ fn fn_sig(f: &mut fmt::Formatter, } /// Namespace of the path given to parameterized to print. -#[derive(Copy, Clone, PartialEq)] +#[derive(Copy, Clone, PartialEq, Debug)] pub enum Ns { Type, Value @@ -71,16 +71,43 @@ pub fn parameterized(f: &mut fmt::Formatter, let mut verbose = false; let mut num_supplied_defaults = 0; let mut has_self = false; - let (fn_trait_kind, item_name) = ty::tls::with(|tcx| { - verbose = tcx.sess.verbose(); + let mut num_regions = 0; + let mut num_types = 0; + let mut item_name = None; + let fn_trait_kind = ty::tls::with(|tcx| { let mut generics = tcx.lookup_generics(did); + let mut path_def_id = did; + verbose = tcx.sess.verbose(); + has_self = generics.has_self; + if let Some(def_id) = generics.parent { + // Methods. + assert_eq!(ns, Ns::Value); generics = tcx.lookup_generics(def_id); + num_regions = generics.regions.len(); + num_types = generics.types.len(); + + if has_self { + write!(f, "<{} as ", substs.types[0])?; + } + + item_name = Some(tcx.item_name(did)); + path_def_id = def_id; + } else { + if ns == Ns::Value { + // Functions. + assert_eq!(has_self, false); + } else { + // Types and traits. + num_regions = generics.regions.len(); + num_types = generics.types.len(); + } } + if !verbose { if generics.types.last().map_or(false, |def| def.default.is_some()) { if let Some(substs) = tcx.lift(&substs) { - let tps = substs.types.get_slice(subst::TypeSpace); + let tps = &substs.types[..num_types]; for (def, actual) in generics.types.iter().zip(tps).rev() { if def.default.subst(tcx, substs) != Some(actual) { break; @@ -91,31 +118,13 @@ pub fn parameterized(f: &mut fmt::Formatter, } } - has_self = generics.has_self; - if ns == Ns::Value && has_self { - write!(f, "<{} as ", substs.types.get(subst::TypeSpace, 0))?; - } - - let (did, item_name) = if ns == Ns::Value { - // Try to get the impl/trait parent, if this is an - // associated value item (method or constant). - tcx.trait_of_item(did).or_else(|| { - // An impl could be a trait impl or an inherent one. - tcx.impl_of_method(did).map(|impl_def_id| { - tcx.trait_id_of_impl(impl_def_id) - .unwrap_or(impl_def_id) - }) - }).map_or((did, None), |parent| (parent, Some(tcx.item_name(did)))) - } else { - (did, None) - }; - write!(f, "{}", tcx.item_path_str(did))?; - Ok((tcx.lang_items.fn_trait_kind(did), item_name)) + write!(f, "{}", tcx.item_path_str(path_def_id))?; + Ok(tcx.lang_items.fn_trait_kind(path_def_id)) })?; if !verbose && fn_trait_kind.is_some() && projections.len() == 1 { let projection_ty = projections[0].ty; - if let TyTuple(ref args) = substs.types.get(subst::TypeSpace, 1).sty { + if let TyTuple(ref args) = substs.types[1].sty { return fn_sig(f, args, false, projection_ty); } } @@ -158,9 +167,9 @@ pub fn parameterized(f: &mut fmt::Formatter, Ok(()) }; - print_regions(f, "<", substs.regions.get_slice(subst::TypeSpace))?; + print_regions(f, "<", &substs.regions[..num_regions])?; - let tps = substs.types.get_slice(subst::TypeSpace); + let tps = &substs.types[..num_types]; for &ty in &tps[has_self as usize..tps.len() - num_supplied_defaults] { start_or_continue(f, "<", ", ")?; @@ -188,10 +197,10 @@ pub fn parameterized(f: &mut fmt::Formatter, write!(f, "::{}", item_name)?; } - print_regions(f, "::<", substs.regions.get_slice(subst::FnSpace))?; + print_regions(f, "::<", &substs.regions[num_regions..])?; // FIXME: consider being smart with defaults here too - for ty in substs.types.get_slice(subst::FnSpace) { + for ty in &substs.types[num_types..] { start_or_continue(f, "::<", ", ")?; write!(f, "{}", ty)?; } @@ -328,19 +337,19 @@ impl<'tcx> fmt::Display for ty::TraitObject<'tcx> { impl<'tcx> fmt::Debug for ty::TypeParameterDef<'tcx> { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!(f, "TypeParameterDef({}, {:?}, {:?}/{})", + write!(f, "TypeParameterDef({}, {:?}, {})", self.name, self.def_id, - self.space, self.index) + self.index) } } impl fmt::Debug for ty::RegionParameterDef { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!(f, "RegionParameterDef({}, {:?}, {:?}/{}, {:?})", + write!(f, "RegionParameterDef({}, {:?}, {}, {:?})", self.name, self.def_id, - self.space, self.index, + self.index, self.bounds) } } @@ -526,8 +535,7 @@ impl fmt::Debug for ty::Region { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match *self { ty::ReEarlyBound(ref data) => { - write!(f, "ReEarlyBound({:?}, {}, {})", - data.space, + write!(f, "ReEarlyBound({}, {})", data.index, data.name) } @@ -1011,7 +1019,7 @@ impl fmt::Display for ty::ParamTy { impl fmt::Debug for ty::ParamTy { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!(f, "{}/{:?}.{}", self, self.space, self.idx) + write!(f, "{}/#{}", self, self.idx) } } diff --git a/src/librustc_borrowck/borrowck/mir/elaborate_drops.rs b/src/librustc_borrowck/borrowck/mir/elaborate_drops.rs index 9f300b5b29ba8..111646912ade3 100644 --- a/src/librustc_borrowck/borrowck/mir/elaborate_drops.rs +++ b/src/librustc_borrowck/borrowck/mir/elaborate_drops.rs @@ -859,7 +859,7 @@ impl<'b, 'tcx> ElaborateDropsCtxt<'b, 'tcx> { let unit_temp = Lvalue::Temp(self.patch.new_temp(tcx.mk_nil())); let free_func = tcx.lang_items.require(lang_items::BoxFreeFnLangItem) .unwrap_or_else(|e| tcx.sess.fatal(&e)); - let substs = Substs::new_fn(tcx, vec![ty], vec![]); + let substs = Substs::new(tcx, vec![ty], vec![]); let fty = tcx.lookup_item_type(free_func).ty.subst(tcx, substs); self.patch.new_block(BasicBlockData { diff --git a/src/librustc_driver/test.rs b/src/librustc_driver/test.rs index c84b195dd4b30..32d0bbbfdb6b7 100644 --- a/src/librustc_driver/test.rs +++ b/src/librustc_driver/test.rs @@ -20,7 +20,6 @@ use rustc::middle::region::{self, CodeExtent}; use rustc::middle::region::CodeExtentData; use rustc::middle::resolve_lifetime; use rustc::middle::stability; -use rustc::ty::subst; use rustc::ty::subst::{Subst, Substs}; use rustc::traits::Reveal; use rustc::ty::{self, Ty, TyCtxt, TypeFoldable}; @@ -276,19 +275,17 @@ impl<'a, 'gcx, 'tcx> Env<'a, 'gcx, 'tcx> { self.infcx.tcx.mk_tup(vec![ty1, ty2]) } - pub fn t_param(&self, space: subst::ParamSpace, index: u32) -> Ty<'tcx> { + pub fn t_param(&self, index: u32) -> Ty<'tcx> { let name = format!("T{}", index); - self.infcx.tcx.mk_param(space, index, token::intern(&name[..])) + self.infcx.tcx.mk_param(index, token::intern(&name[..])) } pub fn re_early_bound(&self, - space: subst::ParamSpace, index: u32, name: &'static str) -> ty::Region { let name = token::intern(name); ty::ReEarlyBound(ty::EarlyBoundRegion { - space: space, index: index, name: name, }) @@ -674,11 +671,11 @@ fn subst_ty_renumber_bound() { // t_source = fn(A) let t_source = { - let t_param = env.t_param(subst::TypeSpace, 0); + let t_param = env.t_param(0); env.t_fn(&[t_param], env.t_nil()) }; - let substs = Substs::new_type(env.infcx.tcx, vec![t_rptr_bound1], vec![]); + let substs = Substs::new(env.infcx.tcx, vec![t_rptr_bound1], vec![]); let t_substituted = t_source.subst(env.infcx.tcx, substs); // t_expected = fn(&'a isize) @@ -709,11 +706,11 @@ fn subst_ty_renumber_some_bounds() { // t_source = (A, fn(A)) let t_source = { - let t_param = env.t_param(subst::TypeSpace, 0); + let t_param = env.t_param(0); env.t_pair(t_param, env.t_fn(&[t_param], env.t_nil())) }; - let substs = Substs::new_type(env.infcx.tcx, vec![t_rptr_bound1], vec![]); + let substs = Substs::new(env.infcx.tcx, vec![t_rptr_bound1], vec![]); let t_substituted = t_source.subst(env.infcx.tcx, substs); // t_expected = (&'a isize, fn(&'a isize)) @@ -755,7 +752,7 @@ fn escaping() { assert!(t_rptr_bound2.has_escaping_regions()); // t_fn = fn(A) - let t_param = env.t_param(subst::TypeSpace, 0); + let t_param = env.t_param(0); assert!(!t_param.has_escaping_regions()); let t_fn = env.t_fn(&[t_param], env.t_nil()); assert!(!t_fn.has_escaping_regions()); @@ -771,11 +768,11 @@ fn subst_region_renumber_region() { // type t_source<'a> = fn(&'a isize) let t_source = { - let re_early = env.re_early_bound(subst::TypeSpace, 0, "'a"); + let re_early = env.re_early_bound(0, "'a"); env.t_fn(&[env.t_rptr(re_early)], env.t_nil()) }; - let substs = Substs::new_type(env.infcx.tcx, vec![], vec![re_bound1]); + let substs = Substs::new(env.infcx.tcx, vec![], vec![re_bound1]); let t_substituted = t_source.subst(env.infcx.tcx, substs); // t_expected = fn(&'a isize) diff --git a/src/librustc_metadata/tydecode.rs b/src/librustc_metadata/tydecode.rs index e8e3679a60ca2..c76cf23639237 100644 --- a/src/librustc_metadata/tydecode.rs +++ b/src/librustc_metadata/tydecode.rs @@ -20,7 +20,7 @@ use rustc::hir; use rustc::hir::def_id::{DefId, DefIndex}; use middle::region; -use rustc::ty::subst::{self, Substs, VecPerParamSpace}; +use rustc::ty::subst::Substs; use rustc::ty::{self, ToPredicate, Ty, TyCtxt, TypeFoldable}; use rbml; @@ -128,23 +128,19 @@ impl<'a,'tcx> TyDecoder<'a,'tcx> { } } - fn parse_vec_per_param_space(&mut self, mut f: F) -> VecPerParamSpace where - F: FnMut(&mut TyDecoder<'a, 'tcx>) -> T, - { - let (mut a, mut b) = (vec![], vec![]); - for r in &mut [&mut a, &mut b] { - assert_eq!(self.next(), '['); - while self.peek() != ']' { - r.push(f(self)); - } - assert_eq!(self.next(), ']'); + pub fn parse_substs(&mut self) -> &'tcx Substs<'tcx> { + let mut regions = vec![]; + let mut types = vec![]; + assert_eq!(self.next(), '['); + while self.peek() != '|' { + regions.push(self.parse_region()); } - VecPerParamSpace::new(a, b) - } + assert_eq!(self.next(), '|'); + while self.peek() != ']' { + types.push(self.parse_ty()); + } + assert_eq!(self.next(), ']'); - pub fn parse_substs(&mut self) -> &'tcx Substs<'tcx> { - let regions = self.parse_vec_per_param_space(|this| this.parse_region()); - let types = self.parse_vec_per_param_space(|this| this.parse_ty()); Substs::new(self.tcx, types, regions) } @@ -155,14 +151,12 @@ impl<'a,'tcx> TyDecoder<'a,'tcx> { let parent_types = self.parse_u32(); let mut regions = vec![]; + let mut types = vec![]; assert_eq!(self.next(), '['); - while self.peek() != ']' { + while self.peek() != '|' { regions.push(self.parse_region_param_def()); } - assert_eq!(self.next(), ']'); - - let mut types = vec![]; - assert_eq!(self.next(), '['); + assert_eq!(self.next(), '|'); while self.peek() != ']' { types.push(self.parse_type_param_def()); } @@ -225,13 +219,10 @@ impl<'a,'tcx> TyDecoder<'a,'tcx> { } 'B' => { assert_eq!(self.next(), '['); - let space = self.parse_param_space(); - assert_eq!(self.next(), '|'); let index = self.parse_u32(); assert_eq!(self.next(), '|'); let name = token::intern(&self.parse_str(']')); ty::ReEarlyBound(ty::EarlyBoundRegion { - space: space, index: index, name: name }) @@ -406,10 +397,8 @@ impl<'a,'tcx> TyDecoder<'a,'tcx> { assert_eq!(self.next(), '['); let index = self.parse_u32(); assert_eq!(self.next(), '|'); - let space = self.parse_param_space(); - assert_eq!(self.next(), '|'); let name = token::intern(&self.parse_str(']')); - return tcx.mk_param(space, index, name); + return tcx.mk_param(index, name); } '~' => return tcx.mk_box(self.parse_ty()), '*' => return tcx.mk_ptr(self.parse_mt()), @@ -552,10 +541,6 @@ impl<'a,'tcx> TyDecoder<'a,'tcx> { m } - fn parse_param_space(&mut self) -> subst::ParamSpace { - subst::ParamSpace::from_uint(self.parse_uint()) - } - fn parse_abi_set(&mut self) -> abi::Abi { assert_eq!(self.next(), '['); let bytes = self.scan(|c| c == ']'); @@ -656,8 +641,6 @@ impl<'a,'tcx> TyDecoder<'a,'tcx> { fn parse_type_param_def(&mut self) -> ty::TypeParameterDef<'tcx> { let name = self.parse_name(':'); let def_id = self.parse_def(); - let space = self.parse_param_space(); - assert_eq!(self.next(), '|'); let index = self.parse_u32(); assert_eq!(self.next(), '|'); let default_def_id = self.parse_def(); @@ -667,7 +650,6 @@ impl<'a,'tcx> TyDecoder<'a,'tcx> { ty::TypeParameterDef { name: name, def_id: def_id, - space: space, index: index, default_def_id: default_def_id, default: default, @@ -678,8 +660,6 @@ impl<'a,'tcx> TyDecoder<'a,'tcx> { fn parse_region_param_def(&mut self) -> ty::RegionParameterDef { let name = self.parse_name(':'); let def_id = self.parse_def(); - let space = self.parse_param_space(); - assert_eq!(self.next(), '|'); let index = self.parse_u32(); assert_eq!(self.next(), '|'); let mut bounds = vec![]; @@ -695,7 +675,6 @@ impl<'a,'tcx> TyDecoder<'a,'tcx> { ty::RegionParameterDef { name: name, def_id: def_id, - space: space, index: index, bounds: bounds, } diff --git a/src/librustc_metadata/tyencode.rs b/src/librustc_metadata/tyencode.rs index 27907596ca788..90fd8a0eb2f65 100644 --- a/src/librustc_metadata/tyencode.rs +++ b/src/librustc_metadata/tyencode.rs @@ -19,8 +19,7 @@ use std::io::prelude::*; use rustc::hir::def_id::DefId; use middle::region; -use rustc::ty::subst::{self, Substs, VecPerParamSpace}; -use rustc::ty::ParamTy; +use rustc::ty::subst::Substs; use rustc::ty::{self, Ty, TyCtxt}; use rustc::util::nodemap::FnvHashMap; @@ -163,8 +162,8 @@ pub fn enc_ty<'a, 'tcx>(w: &mut Cursor>, cx: &ctxt<'a, 'tcx>, t: Ty<'tcx ty::TyInfer(_) => { bug!("cannot encode inference variable types"); } - ty::TyParam(ParamTy {space, idx, name}) => { - write!(w, "p[{}|{}|{}]", idx, space.to_uint(), name); + ty::TyParam(p) => { + write!(w, "p[{}|{}]", p.idx, p.name); } ty::TyStruct(def, substs) => { write!(w, "a[{}|", (cx.ds)(cx.tcx, def.did)); @@ -249,27 +248,17 @@ fn enc_opt(w: &mut Cursor>, t: Option, enc_f: F) where } } -fn enc_vec_per_param_space<'a, 'tcx, T, F>(w: &mut Cursor>, - cx: &ctxt<'a, 'tcx>, - v: &VecPerParamSpace, - mut op: F) where - F: FnMut(&mut Cursor>, &ctxt<'a, 'tcx>, &T), -{ - for &space in &subst::ParamSpace::all() { - write!(w, "["); - for t in v.get_slice(space) { - op(w, cx, t); - } - write!(w, "]"); - } -} - pub fn enc_substs<'a, 'tcx>(w: &mut Cursor>, cx: &ctxt<'a, 'tcx>, substs: &Substs<'tcx>) { - enc_vec_per_param_space(w, cx, &substs.regions, - |w, cx, &r| enc_region(w, cx, r)); - enc_vec_per_param_space(w, cx, &substs.types, - |w, cx, &ty| enc_ty(w, cx, ty)); + write!(w, "["); + for &r in &substs.regions { + enc_region(w, cx, r); + } + write!(w, "|"); + for &ty in &substs.types { + enc_ty(w, cx, ty); + } + write!(w, "]"); } pub fn enc_generics<'a, 'tcx>(w: &mut Cursor>, cx: &ctxt<'a, 'tcx>, @@ -284,7 +273,7 @@ pub fn enc_generics<'a, 'tcx>(w: &mut Cursor>, cx: &ctxt<'a, 'tcx>, for r in &generics.regions { enc_region_param_def(w, cx, r) } - write!(w, "]["); + write!(w, "|"); for t in &generics.types { enc_type_param_def(w, cx, t); } @@ -305,8 +294,7 @@ pub fn enc_region(w: &mut Cursor>, cx: &ctxt, r: ty::Region) { write!(w, "]"); } ty::ReEarlyBound(ref data) => { - write!(w, "B[{}|{}|{}]", - data.space.to_uint(), + write!(w, "B[{}|{}]", data.index, data.name); } @@ -446,18 +434,17 @@ fn enc_builtin_bounds(w: &mut Cursor>, _cx: &ctxt, bs: &ty::BuiltinBound fn enc_type_param_def<'a, 'tcx>(w: &mut Cursor>, cx: &ctxt<'a, 'tcx>, v: &ty::TypeParameterDef<'tcx>) { - write!(w, "{}:{}|{}|{}|{}|", - v.name, (cx.ds)(cx.tcx, v.def_id), - v.space.to_uint(), v.index, (cx.ds)(cx.tcx, v.default_def_id)); + write!(w, "{}:{}|{}|{}|", + v.name, (cx.ds)(cx.tcx, v.def_id), + v.index, (cx.ds)(cx.tcx, v.default_def_id)); enc_opt(w, v.default, |w, t| enc_ty(w, cx, t)); enc_object_lifetime_default(w, cx, v.object_lifetime_default); } fn enc_region_param_def(w: &mut Cursor>, cx: &ctxt, v: &ty::RegionParameterDef) { - write!(w, "{}:{}|{}|{}|", - v.name, (cx.ds)(cx.tcx, v.def_id), - v.space.to_uint(), v.index); + write!(w, "{}:{}|{}|", + v.name, (cx.ds)(cx.tcx, v.def_id), v.index); for &r in &v.bounds { write!(w, "R"); enc_region(w, cx, r); diff --git a/src/librustc_mir/build/scope.rs b/src/librustc_mir/build/scope.rs index 229890483882c..5e4053a82ad8a 100644 --- a/src/librustc_mir/build/scope.rs +++ b/src/librustc_mir/build/scope.rs @@ -750,7 +750,7 @@ fn build_free<'a, 'gcx, 'tcx>(tcx: TyCtxt<'a, 'gcx, 'tcx>, -> TerminatorKind<'tcx> { let free_func = tcx.lang_items.require(lang_items::BoxFreeFnLangItem) .unwrap_or_else(|e| tcx.sess.fatal(&e)); - let substs = Substs::new_fn(tcx, vec![data.item_ty], vec![]); + let substs = Substs::new(tcx, vec![data.item_ty], vec![]); TerminatorKind::Call { func: Operand::Constant(Constant { span: data.span, diff --git a/src/librustc_trans/back/symbol_names.rs b/src/librustc_trans/back/symbol_names.rs index bb27a308f71f7..25a1479c28948 100644 --- a/src/librustc_trans/back/symbol_names.rs +++ b/src/librustc_trans/back/symbol_names.rs @@ -252,7 +252,7 @@ impl<'a, 'tcx> Instance<'tcx> { // and should not matter anyhow. let instance_ty = scx.tcx().erase_regions(&instance_ty.ty); - let hash = get_symbol_hash(scx, &def_path, instance_ty, substs.types.as_full_slice()); + let hash = get_symbol_hash(scx, &def_path, instance_ty, &substs.types); let mut buffer = SymbolPathBuffer { names: Vec::with_capacity(def_path.data.len()) diff --git a/src/librustc_trans/debuginfo/metadata.rs b/src/librustc_trans/debuginfo/metadata.rs index e80dd28c5e502..f505efb1ab2f9 100644 --- a/src/librustc_trans/debuginfo/metadata.rs +++ b/src/librustc_trans/debuginfo/metadata.rs @@ -346,7 +346,7 @@ impl<'tcx> TypeMap<'tcx> { // Add the def-index as the second part output.push_str(&format!("{:x}", def_id.index.as_usize())); - let tps = substs.types.as_full_slice(); + let tps = &substs.types; if !tps.is_empty() { output.push('<'); diff --git a/src/librustc_trans/debuginfo/mod.rs b/src/librustc_trans/debuginfo/mod.rs index 684628e9a40fb..1ee000992b9c5 100644 --- a/src/librustc_trans/debuginfo/mod.rs +++ b/src/librustc_trans/debuginfo/mod.rs @@ -358,7 +358,7 @@ pub fn create_function_debug_context<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, name_to_append_suffix_to: &mut String) -> DIArray { - let actual_types = param_substs.types.as_full_slice(); + let actual_types = ¶m_substs.types; if actual_types.is_empty() { return create_DIArray(DIB(cx), &[]); diff --git a/src/librustc_trans/debuginfo/type_names.rs b/src/librustc_trans/debuginfo/type_names.rs index 20dbc8ac78eaf..2a996ca75a37e 100644 --- a/src/librustc_trans/debuginfo/type_names.rs +++ b/src/librustc_trans/debuginfo/type_names.rs @@ -181,7 +181,7 @@ pub fn push_debuginfo_type_name<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, output.push('<'); - for &type_parameter in substs.types.as_full_slice() { + for &type_parameter in &substs.types { push_debuginfo_type_name(cx, type_parameter, true, output); output.push_str(", "); } diff --git a/src/librustc_trans/intrinsic.rs b/src/librustc_trans/intrinsic.rs index 133a98a2470f0..ecee470551059 100644 --- a/src/librustc_trans/intrinsic.rs +++ b/src/librustc_trans/intrinsic.rs @@ -15,7 +15,7 @@ use intrinsics::{self, Intrinsic}; use libc; use llvm; use llvm::{ValueRef, TypeKind}; -use rustc::ty::subst::{FnSpace, Substs}; +use rustc::ty::subst::Substs; use abi::{Abi, FnType}; use adt; use base::*; @@ -136,8 +136,8 @@ pub fn trans_intrinsic_call<'a, 'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>, callee::ArgExprs(arg_exprs) => { assert_eq!(arg_exprs.len(), 1); - let (in_type, out_type) = (*substs.types.get(FnSpace, 0), - *substs.types.get(FnSpace, 1)); + let (in_type, out_type) = (substs.types[0], + substs.types[1]); let llintype = type_of::type_of(ccx, in_type); let llouttype = type_of::type_of(ccx, out_type); @@ -346,12 +346,12 @@ pub fn trans_intrinsic_call<'a, 'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>, Call(bcx, llfn, &[], call_debug_location) } (_, "size_of") => { - let tp_ty = *substs.types.get(FnSpace, 0); + let tp_ty = substs.types[0]; let lltp_ty = type_of::type_of(ccx, tp_ty); C_uint(ccx, machine::llsize_of_alloc(ccx, lltp_ty)) } (_, "size_of_val") => { - let tp_ty = *substs.types.get(FnSpace, 0); + let tp_ty = substs.types[0]; if !type_is_sized(tcx, tp_ty) { let (llsize, _) = glue::size_and_align_of_dst(&bcx.build(), tp_ty, llargs[1]); @@ -362,11 +362,11 @@ pub fn trans_intrinsic_call<'a, 'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>, } } (_, "min_align_of") => { - let tp_ty = *substs.types.get(FnSpace, 0); + let tp_ty = substs.types[0]; C_uint(ccx, type_of::align_of(ccx, tp_ty)) } (_, "min_align_of_val") => { - let tp_ty = *substs.types.get(FnSpace, 0); + let tp_ty = substs.types[0]; if !type_is_sized(tcx, tp_ty) { let (_, llalign) = glue::size_and_align_of_dst(&bcx.build(), tp_ty, llargs[1]); @@ -376,12 +376,12 @@ pub fn trans_intrinsic_call<'a, 'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>, } } (_, "pref_align_of") => { - let tp_ty = *substs.types.get(FnSpace, 0); + let tp_ty = substs.types[0]; let lltp_ty = type_of::type_of(ccx, tp_ty); C_uint(ccx, machine::llalign_of_pref(ccx, lltp_ty)) } (_, "drop_in_place") => { - let tp_ty = *substs.types.get(FnSpace, 0); + let tp_ty = substs.types[0]; let ptr = if type_is_sized(tcx, tp_ty) { llargs[0] } else { @@ -395,22 +395,22 @@ pub fn trans_intrinsic_call<'a, 'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>, C_nil(ccx) } (_, "type_name") => { - let tp_ty = *substs.types.get(FnSpace, 0); + let tp_ty = substs.types[0]; let ty_name = token::intern_and_get_ident(&tp_ty.to_string()); C_str_slice(ccx, ty_name) } (_, "type_id") => { - C_u64(ccx, ccx.tcx().type_id_hash(*substs.types.get(FnSpace, 0))) + C_u64(ccx, ccx.tcx().type_id_hash(substs.types[0])) } (_, "init_dropped") => { - let tp_ty = *substs.types.get(FnSpace, 0); + let tp_ty = substs.types[0]; if !type_is_zero_size(ccx, tp_ty) { drop_done_fill_mem(bcx, llresult, tp_ty); } C_nil(ccx) } (_, "init") => { - let tp_ty = *substs.types.get(FnSpace, 0); + let tp_ty = substs.types[0]; if !type_is_zero_size(ccx, tp_ty) { // Just zero out the stack slot. (See comment on base::memzero for explanation) init_zero_mem(bcx, llresult, tp_ty); @@ -422,7 +422,7 @@ pub fn trans_intrinsic_call<'a, 'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>, C_nil(ccx) } (_, "needs_drop") => { - let tp_ty = *substs.types.get(FnSpace, 0); + let tp_ty = substs.types[0]; C_bool(ccx, bcx.fcx.type_needs_drop(tp_ty)) } @@ -441,7 +441,7 @@ pub fn trans_intrinsic_call<'a, 'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>, copy_intrinsic(bcx, false, false, - *substs.types.get(FnSpace, 0), + substs.types[0], llargs[1], llargs[0], llargs[2], @@ -451,7 +451,7 @@ pub fn trans_intrinsic_call<'a, 'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>, copy_intrinsic(bcx, true, false, - *substs.types.get(FnSpace, 0), + substs.types[0], llargs[1], llargs[0], llargs[2], @@ -460,7 +460,7 @@ pub fn trans_intrinsic_call<'a, 'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>, (_, "write_bytes") => { memset_intrinsic(bcx, false, - *substs.types.get(FnSpace, 0), + substs.types[0], llargs[0], llargs[1], llargs[2], @@ -471,7 +471,7 @@ pub fn trans_intrinsic_call<'a, 'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>, copy_intrinsic(bcx, false, true, - *substs.types.get(FnSpace, 0), + substs.types[0], llargs[0], llargs[1], llargs[2], @@ -481,7 +481,7 @@ pub fn trans_intrinsic_call<'a, 'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>, copy_intrinsic(bcx, true, true, - *substs.types.get(FnSpace, 0), + substs.types[0], llargs[0], llargs[1], llargs[2], @@ -490,14 +490,14 @@ pub fn trans_intrinsic_call<'a, 'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>, (_, "volatile_set_memory") => { memset_intrinsic(bcx, true, - *substs.types.get(FnSpace, 0), + substs.types[0], llargs[0], llargs[1], llargs[2], call_debug_location) } (_, "volatile_load") => { - let tp_ty = *substs.types.get(FnSpace, 0); + let tp_ty = substs.types[0]; let mut ptr = llargs[0]; if let Some(ty) = fn_ty.ret.cast { ptr = PointerCast(bcx, ptr, ty.ptr_to()); @@ -509,7 +509,7 @@ pub fn trans_intrinsic_call<'a, 'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>, to_immediate(bcx, load, tp_ty) }, (_, "volatile_store") => { - let tp_ty = *substs.types.get(FnSpace, 0); + let tp_ty = substs.types[0]; if type_is_fat_ptr(bcx.tcx(), tp_ty) { VolatileStore(bcx, llargs[1], expr::get_dataptr(bcx, llargs[0])); VolatileStore(bcx, llargs[2], expr::get_meta(bcx, llargs[0])); @@ -609,10 +609,10 @@ pub fn trans_intrinsic_call<'a, 'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>, }, (_, "discriminant_value") => { - let val_ty = substs.types.get(FnSpace, 0); + let val_ty = substs.types[0]; match val_ty.sty { ty::TyEnum(..) => { - let repr = adt::represent_type(ccx, *val_ty); + let repr = adt::represent_type(ccx, val_ty); adt::trans_get_discr(bcx, &repr, llargs[0], Some(llret_ty), true) } @@ -663,7 +663,7 @@ pub fn trans_intrinsic_call<'a, 'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>, match split[1] { "cxchg" | "cxchgweak" => { - let sty = &substs.types.get(FnSpace, 0).sty; + let sty = &substs.types[0].sty; if int_type_width_signed(sty, ccx).is_some() { let weak = if split[1] == "cxchgweak" { llvm::True } else { llvm::False }; let val = AtomicCmpXchg(bcx, llargs[0], llargs[1], llargs[2], @@ -682,7 +682,7 @@ pub fn trans_intrinsic_call<'a, 'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>, } "load" => { - let sty = &substs.types.get(FnSpace, 0).sty; + let sty = &substs.types[0].sty; if int_type_width_signed(sty, ccx).is_some() { AtomicLoad(bcx, llargs[0], order) } else { @@ -695,7 +695,7 @@ pub fn trans_intrinsic_call<'a, 'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>, } "store" => { - let sty = &substs.types.get(FnSpace, 0).sty; + let sty = &substs.types[0].sty; if int_type_width_signed(sty, ccx).is_some() { AtomicStore(bcx, llargs[1], llargs[0], order); } else { @@ -734,7 +734,7 @@ pub fn trans_intrinsic_call<'a, 'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>, _ => ccx.sess().fatal("unknown atomic operation") }; - let sty = &substs.types.get(FnSpace, 0).sty; + let sty = &substs.types[0].sty; if int_type_width_signed(sty, ccx).is_some() { AtomicRMW(bcx, atom_op, llargs[0], llargs[1], order) } else { diff --git a/src/librustc_trans/monomorphize.rs b/src/librustc_trans/monomorphize.rs index 26278e886c29a..d1837883aaeb0 100644 --- a/src/librustc_trans/monomorphize.rs +++ b/src/librustc_trans/monomorphize.rs @@ -180,7 +180,7 @@ impl<'tcx> fmt::Display for Instance<'tcx> { impl<'tcx> Instance<'tcx> { pub fn new(def_id: DefId, substs: &'tcx Substs<'tcx>) -> Instance<'tcx> { - assert!(substs.regions.as_full_slice().iter().all(|&r| r == ty::ReErased)); + assert!(substs.regions.iter().all(|&r| r == ty::ReErased)); Instance { def: def_id, substs: substs } } pub fn mono<'a>(scx: &SharedCrateContext<'a, 'tcx>, def_id: DefId) -> Instance<'tcx> { diff --git a/src/librustc_trans/partitioning.rs b/src/librustc_trans/partitioning.rs index 1e90f273301ff..87d0ea0fe81f3 100644 --- a/src/librustc_trans/partitioning.rs +++ b/src/librustc_trans/partitioning.rs @@ -125,7 +125,6 @@ use rustc::hir::map::DefPathData; use rustc::session::config::NUMBERED_CODEGEN_UNIT_MARKER; use rustc::ty::TyCtxt; use rustc::ty::item_path::characteristic_def_id_of_type; -use rustc::ty::subst; use std::cmp::Ordering; use std::hash::{Hash, Hasher, SipHasher}; use std::sync::Arc; @@ -488,7 +487,7 @@ fn characteristic_def_id_of_trans_item<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, // DefId, we use the location of the impl after all. if tcx.trait_of_item(instance.def).is_some() { - let self_ty = *instance.substs.types.get(subst::TypeSpace, 0); + let self_ty = instance.substs.types[0]; // This is an implementation of a trait method. return characteristic_def_id_of_type(self_ty).or(Some(instance.def)); } diff --git a/src/librustc_trans/trans_item.rs b/src/librustc_trans/trans_item.rs index ebd4a80deb9ab..580882e31dd60 100644 --- a/src/librustc_trans/trans_item.rs +++ b/src/librustc_trans/trans_item.rs @@ -28,7 +28,7 @@ use rustc::hir; use rustc::hir::map as hir_map; use rustc::hir::def_id::DefId; use rustc::ty::{self, Ty, TyCtxt, TypeFoldable}; -use rustc::ty::subst::{Substs, VecPerParamSpace}; +use rustc::ty::subst::Substs; use rustc_const_eval::fatal_const_eval_err; use std::hash::{Hash, Hasher}; use syntax::ast::{self, NodeId}; @@ -560,7 +560,7 @@ fn push_item_name(tcx: TyCtxt, } fn push_type_params<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, - types: &'tcx VecPerParamSpace>, + types: &[Ty<'tcx>], projections: &[ty::PolyExistentialProjection<'tcx>], output: &mut String) { if types.is_empty() && projections.is_empty() { @@ -569,7 +569,7 @@ fn push_type_params<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, output.push('<'); - for &type_parameter in types.as_full_slice() { + for &type_parameter in types { push_unique_type_name(tcx, type_parameter, output); output.push_str(", "); } diff --git a/src/librustc_trans/type_of.rs b/src/librustc_trans/type_of.rs index 7e592d1b74d7c..6862002ed83b2 100644 --- a/src/librustc_trans/type_of.rs +++ b/src/librustc_trans/type_of.rs @@ -256,18 +256,13 @@ pub fn in_memory_type_of<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, t: Ty<'tcx>) -> // avoids creating more than one copy of the enum when one // of the enum's variants refers to the enum itself. let repr = adt::represent_type(cx, t); - let tps = substs.types.as_full_slice(); - let name = llvm_type_name(cx, def.did, tps); + let name = llvm_type_name(cx, def.did, &substs.types); adt::incomplete_type_of(cx, &repr, &name[..]) } ty::TyClosure(..) => { // Only create the named struct, but don't fill it in. We // fill it in *after* placing it into the type cache. let repr = adt::represent_type(cx, t); - // Unboxed closures can have substitutions in all spaces - // inherited from their environment, so we use entire - // contents of the VecPerParamSpace to construct the llvm - // name adt::incomplete_type_of(cx, &repr, "closure") } @@ -335,8 +330,7 @@ pub fn in_memory_type_of<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, t: Ty<'tcx>) -> // in *after* placing it into the type cache. This prevents // infinite recursion with recursive struct types. let repr = adt::represent_type(cx, t); - let tps = substs.types.as_full_slice(); - let name = llvm_type_name(cx, def.did, tps); + let name = llvm_type_name(cx, def.did, &substs.types); adt::incomplete_type_of(cx, &repr, &name[..]) } } diff --git a/src/librustc_typeck/astconv.rs b/src/librustc_typeck/astconv.rs index aec8f8245da5e..f6984f42cab34 100644 --- a/src/librustc_typeck/astconv.rs +++ b/src/librustc_typeck/astconv.rs @@ -55,7 +55,7 @@ use hir::def_id::DefId; use hir::print as pprust; use middle::resolve_lifetime as rl; use rustc::lint; -use rustc::ty::subst::{TypeSpace, Subst, Substs}; +use rustc::ty::subst::{Subst, Substs}; use rustc::traits; use rustc::ty::{self, Ty, TyCtxt, ToPredicate, TypeFoldable}; use rustc::ty::wf::object_region_bounds; @@ -207,9 +207,8 @@ pub fn ast_region_to_region(tcx: TyCtxt, lifetime: &hir::Lifetime) issue_32330)) } - Some(&rl::DefEarlyBoundRegion(space, index, _)) => { + Some(&rl::DefEarlyBoundRegion(index, _)) => { ty::ReEarlyBound(ty::EarlyBoundRegion { - space: space, index: index, name: lifetime.name }) @@ -473,10 +472,8 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o { let mut output_assoc_binding = None; let substs = Substs::for_item(tcx, def_id, |def, _| { - assert_eq!(def.space, TypeSpace); regions[def.index as usize] }, |def, substs| { - assert!(def.space == TypeSpace); let i = def.index as usize; // Handle Self first, so we can adjust the index to match the AST. @@ -940,8 +937,8 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o { // FIXME(#12938): This is a hack until we have full support for DST. if Some(did) == self.tcx().lang_items.owned_box() { - assert_eq!(substs.types.len(TypeSpace), 1); - return self.tcx().mk_box(*substs.types.get(TypeSpace, 0)); + assert_eq!(substs.types.len(), 1); + return self.tcx().mk_box(substs.types[0]); } decl_ty.subst(self.tcx(), substs) diff --git a/src/librustc_typeck/check/closure.rs b/src/librustc_typeck/check/closure.rs index 087549a2f1c4c..377ca5eaebe30 100644 --- a/src/librustc_typeck/check/closure.rs +++ b/src/librustc_typeck/check/closure.rs @@ -13,7 +13,6 @@ use super::{check_fn, Expectation, FnCtxt}; use astconv::AstConv; -use rustc::ty::subst; use rustc::ty::{self, ToPolyTraitRef, Ty}; use std::cmp; use syntax::abi::Abi; @@ -204,7 +203,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { return None; } - let arg_param_ty = *trait_ref.substs().types.get(subst::TypeSpace, 1); + let arg_param_ty = trait_ref.substs().types[1]; let arg_param_ty = self.resolve_type_vars_if_possible(&arg_param_ty); debug!("deduce_sig_from_projection: arg_param_ty {:?}", arg_param_ty); diff --git a/src/librustc_typeck/check/compare_method.rs b/src/librustc_typeck/check/compare_method.rs index 4cbb2d7f09f02..6bcf21563cb98 100644 --- a/src/librustc_typeck/check/compare_method.rs +++ b/src/librustc_typeck/check/compare_method.rs @@ -225,7 +225,7 @@ pub fn compare_impl_method<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, debug!("compare_impl_method: impl_bounds={:?}", hybrid_preds); // This is the only tricky bit of the new way we check implementation methods - // We need to build a set of predicates where only the FnSpace bounds + // We need to build a set of predicates where only the method-level bounds // are from the trait and we assume all other bounds from the implementation // to be previously satisfied. // diff --git a/src/librustc_typeck/check/dropck.rs b/src/librustc_typeck/check/dropck.rs index d1da95f39df40..82545d564a20c 100644 --- a/src/librustc_typeck/check/dropck.rs +++ b/src/librustc_typeck/check/dropck.rs @@ -15,7 +15,7 @@ use hir::def_id::DefId; use middle::free_region::FreeRegionMap; use rustc::infer; use middle::region; -use rustc::ty::subst::{self, Subst, Substs}; +use rustc::ty::subst::{Subst, Substs}; use rustc::ty::{self, Ty, TyCtxt}; use rustc::traits::{self, Reveal}; use util::nodemap::FnvHashSet; @@ -438,7 +438,7 @@ fn iterate_over_potentially_unsafe_regions_in_type<'a, 'b, 'gcx, 'tcx>( ty::TyStruct(def, substs) if def.is_phantom_data() => { // PhantomData - behaves identically to T - let ity = *substs.types.get(subst::TypeSpace, 0); + let ity = substs.types[0]; iterate_over_potentially_unsafe_regions_in_type( cx, context, ity, depth+1) } diff --git a/src/librustc_typeck/check/intrinsic.rs b/src/librustc_typeck/check/intrinsic.rs index b2af51c12e6bb..b2873bf686578 100644 --- a/src/librustc_typeck/check/intrinsic.rs +++ b/src/librustc_typeck/check/intrinsic.rs @@ -13,7 +13,7 @@ use intrinsics; use rustc::infer::TypeOrigin; -use rustc::ty::subst::{self, Substs}; +use rustc::ty::subst::Substs; use rustc::ty::FnSig; use rustc::ty::{self, Ty}; use {CrateCtxt, require_same_types}; @@ -70,7 +70,7 @@ fn equate_intrinsic_type<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, pub fn check_intrinsic_type(ccx: &CrateCtxt, it: &hir::ForeignItem) { fn param<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, n: u32) -> Ty<'tcx> { let name = token::intern(&format!("P{}", n)); - ccx.tcx.mk_param(subst::FnSpace, n, name) + ccx.tcx.mk_param(n, name) } let tcx = ccx.tcx; @@ -316,7 +316,7 @@ pub fn check_platform_intrinsic_type(ccx: &CrateCtxt, it: &hir::ForeignItem) { let param = |n| { let name = token::intern(&format!("P{}", n)); - ccx.tcx.mk_param(subst::FnSpace, n, name) + ccx.tcx.mk_param(n, name) }; let tcx = ccx.tcx; diff --git a/src/librustc_typeck/check/method/confirm.rs b/src/librustc_typeck/check/method/confirm.rs index 8aa4ad56aea88..9e0b38fd9fe51 100644 --- a/src/librustc_typeck/check/method/confirm.rs +++ b/src/librustc_typeck/check/method/confirm.rs @@ -12,7 +12,7 @@ use super::probe; use check::{FnCtxt, callee}; use hir::def_id::DefId; -use rustc::ty::subst::{self, Substs}; +use rustc::ty::subst::Substs; use rustc::traits; use rustc::ty::{self, LvaluePreference, NoPreference, PreferMutLvalue, Ty}; use rustc::ty::adjustment::{AdjustDerefRef, AutoDerefRef, AutoPtr}; @@ -328,18 +328,18 @@ impl<'a, 'gcx, 'tcx> ConfirmContext<'a, 'gcx, 'tcx> { // // FIXME -- permit users to manually specify lifetimes Substs::for_item(self.tcx, method.def_id, |def, _| { - if def.space != subst::FnSpace { - substs.region_for_def(def) + if let Some(&r) = substs.regions.get(def.index as usize) { + r } else { self.region_var_for_def(self.span, def) } }, |def, cur_substs| { - if def.space != subst::FnSpace { - substs.type_for_def(def) + if let Some(&ty) = substs.types.get(def.index as usize) { + ty } else if supplied_method_types.is_empty() { self.type_var_for_def(self.span, def, cur_substs) } else { - supplied_method_types[def.index as usize] + supplied_method_types[def.index as usize - substs.types.len()] } }) } diff --git a/src/librustc_typeck/check/method/mod.rs b/src/librustc_typeck/check/method/mod.rs index b057ad3150b51..bcb410e1b8d01 100644 --- a/src/librustc_typeck/check/method/mod.rs +++ b/src/librustc_typeck/check/method/mod.rs @@ -13,7 +13,7 @@ use check::FnCtxt; use hir::def::Def; use hir::def_id::DefId; -use rustc::ty::subst::{self, Substs}; +use rustc::ty::subst::Substs; use rustc::traits; use rustc::ty::{self, ToPredicate, ToPolyTraitRef, TraitRef, TypeFoldable}; use rustc::ty::adjustment::{AdjustDerefRef, AutoDerefRef, AutoPtr}; @@ -191,7 +191,6 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { let substs = Substs::for_item(self.tcx, trait_def_id, |def, _| { self.region_var_for_def(span, def) }, |def, substs| { - assert_eq!(def.space, subst::TypeSpace); if def.index == 0 { self_ty } else if let Some(ref input_types) = opt_input_types { diff --git a/src/librustc_typeck/check/method/probe.rs b/src/librustc_typeck/check/method/probe.rs index c52bb36911a2a..c306463ec1de0 100644 --- a/src/librustc_typeck/check/method/probe.rs +++ b/src/librustc_typeck/check/method/probe.rs @@ -16,7 +16,7 @@ use super::suggest; use check::{FnCtxt}; use hir::def_id::DefId; use hir::def::Def; -use rustc::ty::subst::{self, Subst, Substs}; +use rustc::ty::subst::{Subst, Substs}; use rustc::traits; use rustc::ty::{self, Ty, ToPolyTraitRef, TraitRef, TypeFoldable}; use rustc::infer::{InferOk, TypeOrigin}; @@ -519,9 +519,9 @@ impl<'a, 'gcx, 'tcx> ProbeContext<'a, 'gcx, 'tcx> { trait_ref.substs, m); assert_eq!(m.generics.parent_types as usize, - trait_ref.substs.types.len(subst::TypeSpace)); + trait_ref.substs.types.len()); assert_eq!(m.generics.parent_regions as usize, - trait_ref.substs.regions.len(subst::TypeSpace)); + trait_ref.substs.regions.len()); } // Because this trait derives from a where-clause, it @@ -1220,8 +1220,8 @@ impl<'a, 'gcx, 'tcx> ProbeContext<'a, 'gcx, 'tcx> { // are given do not include type/lifetime parameters for the // method yet. So create fresh variables here for those too, // if there are any. - assert_eq!(substs.types.len(subst::FnSpace), 0); - assert_eq!(substs.regions.len(subst::FnSpace), 0); + assert_eq!(substs.types.len(), method.generics.parent_types as usize); + assert_eq!(substs.regions.len(), method.generics.parent_regions as usize); if self.mode == Mode::Path { return impl_ty; @@ -1236,16 +1236,16 @@ impl<'a, 'gcx, 'tcx> ProbeContext<'a, 'gcx, 'tcx> { xform_self_ty.subst(self.tcx, substs) } else { let substs = Substs::for_item(self.tcx, method.def_id, |def, _| { - if def.space != subst::FnSpace { - substs.region_for_def(def) + if let Some(&r) = substs.regions.get(def.index as usize) { + r } else { // In general, during probe we erase regions. See // `impl_self_ty()` for an explanation. ty::ReErased } }, |def, cur_substs| { - if def.space != subst::FnSpace { - substs.type_for_def(def) + if let Some(&ty) = substs.types.get(def.index as usize) { + ty } else { self.type_var_for_def(self.span, def, cur_substs) } diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index 8c4ec8453177e..e573655b8c984 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -88,7 +88,7 @@ use hir::def::{Def, PathResolution}; use hir::def_id::DefId; use hir::pat_util; use rustc::infer::{self, InferCtxt, InferOk, TypeOrigin, TypeTrace, type_variable}; -use rustc::ty::subst::{self, Subst, Substs}; +use rustc::ty::subst::{Subst, Substs}; use rustc::traits::{self, Reveal}; use rustc::ty::{ParamTy, ParameterEnvironment}; use rustc::ty::{LvaluePreference, NoPreference, PreferMutLvalue}; @@ -1333,7 +1333,7 @@ impl<'a, 'gcx, 'tcx> AstConv<'gcx, 'tcx> for FnCtxt<'a, 'gcx, 'tcx> { .filter_map(|predicate| { match *predicate { ty::Predicate::Trait(ref data) => { - if data.0.self_ty().is_param(def.space, def.index) { + if data.0.self_ty().is_param(def.index) { Some(data.to_poly_trait_ref()) } else { None @@ -1887,7 +1887,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { /// Registers obligations that all types appearing in `substs` are well-formed. pub fn add_wf_bounds(&self, substs: &Substs<'tcx>, expr: &hir::Expr) { - for &ty in substs.types.as_full_slice() { + for &ty in &substs.types { self.register_wf_obligation(ty, expr.span, traits::MiscObligation); } } @@ -4223,20 +4223,22 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { // variables. If the user provided some types, we may still need // to add defaults. If the user provided *too many* types, that's // a problem. - self.check_path_parameter_count(subst::TypeSpace, - span, - !require_type_space, - &mut type_segment); - self.check_path_parameter_count(subst::FnSpace, - span, - true, - &mut fn_segment); + self.check_path_parameter_count(span, !require_type_space, &mut type_segment); + self.check_path_parameter_count(span, true, &mut fn_segment); let substs = Substs::for_item(self.tcx, def.def_id(), |def, _| { - let i = def.index as usize; - let segment = match def.space { - subst::TypeSpace => type_segment, - subst::FnSpace => fn_segment + let mut i = def.index as usize; + let type_regions = match (type_segment, fn_segment) { + (_, Some((_, generics))) => generics.parent_regions as usize, + (Some((_, generics)), None) => generics.regions.len(), + (None, None) => 0 + }; + + let segment = if i < type_regions { + type_segment + } else { + i -= type_regions; + fn_segment }; let lifetimes = match segment.map(|(s, _)| &s.parameters) { Some(&hir::AngleBracketedParameters(ref data)) => &data.lifetimes[..], @@ -4251,25 +4253,29 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { } }, |def, substs| { let mut i = def.index as usize; - let segment = match def.space { - subst::TypeSpace => { - // Handle Self first, so we can adjust the index to match the AST. - match (type_segment, fn_segment) { - (Some((_, generics)), _) | (_, Some((_, generics))) => { - if generics.has_self { - if i == 0 { - return opt_self_ty.unwrap_or_else(|| { - self.type_var_for_def(span, def, substs) - }); - } - i -= 1; - } - } - _ => {} - } - type_segment + let (type_types, has_self) = match (type_segment, fn_segment) { + (_, Some((_, generics))) => { + (generics.parent_types as usize, generics.has_self) } - subst::FnSpace => fn_segment + (Some((_, generics)), None) => { + (generics.types.len(), generics.has_self) + } + (None, None) => (0, false) + }; + + let can_omit = i >= type_types || !require_type_space; + let segment = if i < type_types { + // Handle Self first, so we can adjust the index to match the AST. + if has_self && i == 0 { + return opt_self_ty.unwrap_or_else(|| { + self.type_var_for_def(span, def, substs) + }); + } + i -= has_self as usize; + type_segment + } else { + i -= type_types; + fn_segment }; let types = match segment.map(|(s, _)| &s.parameters) { Some(&hir::AngleBracketedParameters(ref data)) => &data.types[..], @@ -4277,16 +4283,11 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { None => &[] }; - let can_omit = def.space != subst::TypeSpace || !require_type_space; - let default = if can_omit && types.len() == 0 { - def.default - } else { - None - }; + let omitted = can_omit && types.is_empty(); if let Some(ast_ty) = types.get(i) { // A provided type parameter. self.to_ty(ast_ty) - } else if let Some(default) = default { + } else if let (false, Some(default)) = (omitted, def.default) { // No type parameter provided, but a default exists. default.subst_spanned(self.tcx, substs, Some(span)) } else { @@ -4323,10 +4324,6 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { // type parameters, which we can infer by unifying the provided `Self` // with the substituted impl type. let impl_scheme = self.tcx.lookup_item_type(impl_def_id); - assert_eq!(substs.types.len(subst::TypeSpace), - impl_scheme.generics.types.len()); - assert_eq!(substs.regions.len(subst::TypeSpace), - impl_scheme.generics.regions.len()); let impl_ty = self.instantiate_type_scheme(span, &substs, &impl_scheme.ty); match self.sub_types(false, TypeOrigin::Misc(span), self_ty, impl_ty) { @@ -4355,7 +4352,6 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { /// Report errors if the provided parameters are too few or too many. fn check_path_parameter_count(&self, - space: subst::ParamSpace, span: Span, can_omit: bool, segment: &mut Option<(&hir::PathSegment, &ty::Generics)>) { @@ -4392,7 +4388,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { // Check provided type parameters. let type_defs = segment.map_or(&[][..], |(_, generics)| { - if space == subst::TypeSpace { + if generics.parent.is_none() { &generics.types[generics.has_self as usize..] } else { &generics.types diff --git a/src/librustc_typeck/check/regionck.rs b/src/librustc_typeck/check/regionck.rs index f6ffbc60c2836..859d5ff0543d0 100644 --- a/src/librustc_typeck/check/regionck.rs +++ b/src/librustc_typeck/check/regionck.rs @@ -1445,11 +1445,11 @@ impl<'a, 'gcx, 'tcx> RegionCtxt<'a, 'gcx, 'tcx> { let origin = infer::ParameterInScope(origin, expr_span); - for ®ion in substs.regions.as_full_slice() { + for ®ion in &substs.regions { self.sub_regions(origin.clone(), expr_region, region); } - for &ty in substs.types.as_full_slice() { + for &ty in &substs.types { let ty = self.resolve_type(ty); self.type_must_outlive(origin.clone(), ty, expr_region); } @@ -1575,11 +1575,11 @@ impl<'a, 'gcx, 'tcx> RegionCtxt<'a, 'gcx, 'tcx> { if env_bounds.is_empty() && needs_infer { debug!("projection_must_outlive: no declared bounds"); - for &component_ty in projection_ty.trait_ref.substs.types.as_full_slice() { + for &component_ty in &projection_ty.trait_ref.substs.types { self.type_must_outlive(origin.clone(), component_ty, region); } - for &r in projection_ty.trait_ref.substs.regions.as_full_slice() { + for &r in &projection_ty.trait_ref.substs.regions { self.sub_regions(origin.clone(), region, r); } @@ -1597,7 +1597,7 @@ impl<'a, 'gcx, 'tcx> RegionCtxt<'a, 'gcx, 'tcx> { if !env_bounds.is_empty() && env_bounds[1..].iter().all(|b| *b == env_bounds[0]) { let unique_bound = env_bounds[0]; debug!("projection_must_outlive: unique declared bound = {:?}", unique_bound); - if projection_ty.trait_ref.substs.regions.as_full_slice() + if projection_ty.trait_ref.substs.regions .iter() .any(|r| env_bounds.contains(r)) { diff --git a/src/librustc_typeck/check/wfcheck.rs b/src/librustc_typeck/check/wfcheck.rs index ef5e1a26f4150..7ed4b2bcb1918 100644 --- a/src/librustc_typeck/check/wfcheck.rs +++ b/src/librustc_typeck/check/wfcheck.rs @@ -14,7 +14,6 @@ use CrateCtxt; use hir::def_id::DefId; use middle::region::{CodeExtent}; use rustc::infer::TypeOrigin; -use rustc::ty::subst; use rustc::traits; use rustc::ty::{self, Ty, TyCtxt}; @@ -459,9 +458,9 @@ impl<'ccx, 'gcx> CheckTypeWellFormedVisitor<'ccx, 'gcx> { let mut constrained_parameters: HashSet<_> = variances.types - .iter_enumerated() - .filter(|&(_, _, &variance)| variance != ty::Bivariant) - .map(|(_, index, _)| self.param_ty(ast_generics, index)) + .iter().enumerate() + .filter(|&(_, &variance)| variance != ty::Bivariant) + .map(|(index, _)| self.param_ty(ast_generics, index)) .map(|p| Parameter::Type(p)) .collect(); @@ -469,9 +468,7 @@ impl<'ccx, 'gcx> CheckTypeWellFormedVisitor<'ccx, 'gcx> { None, &mut constrained_parameters); - for (space, index, _) in variances.types.iter_enumerated() { - assert_eq!(space, subst::TypeSpace); - + for (index, _) in variances.types.iter().enumerate() { let param_ty = self.param_ty(ast_generics, index); if constrained_parameters.contains(&Parameter::Type(param_ty)) { continue; @@ -480,9 +477,7 @@ impl<'ccx, 'gcx> CheckTypeWellFormedVisitor<'ccx, 'gcx> { self.report_bivariance(span, param_ty.name); } - for (space, index, &variance) in variances.regions.iter_enumerated() { - assert_eq!(space, subst::TypeSpace); - + for (index, &variance) in variances.regions.iter().enumerate() { if variance != ty::Bivariant { continue; } @@ -495,7 +490,6 @@ impl<'ccx, 'gcx> CheckTypeWellFormedVisitor<'ccx, 'gcx> { fn param_ty(&self, ast_generics: &hir::Generics, index: usize) -> ty::ParamTy { ty::ParamTy { - space: subst::TypeSpace, idx: index as u32, name: ast_generics.ty_params[index].name } @@ -603,7 +597,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { // Trait impl: take implied bounds from all types that // appear in the trait reference. let trait_ref = self.instantiate_type_scheme(span, free_substs, trait_ref); - trait_ref.substs.types.as_full_slice().to_vec() + trait_ref.substs.types.to_vec() } None => { diff --git a/src/librustc_typeck/check/writeback.rs b/src/librustc_typeck/check/writeback.rs index 6a475864f3b7d..cfc1292c34b78 100644 --- a/src/librustc_typeck/check/writeback.rs +++ b/src/librustc_typeck/check/writeback.rs @@ -103,13 +103,12 @@ impl<'cx, 'gcx, 'tcx> WritebackCx<'cx, 'gcx, 'tcx> { } let free_substs = fcx.parameter_environment.free_substs; - for (space, i, r) in free_substs.regions.iter_enumerated() { + for (i, r) in free_substs.regions.iter().enumerate() { match *r { ty::ReFree(ty::FreeRegion { bound_region: ty::BoundRegion::BrNamed(def_id, name, _), .. }) => { let bound_region = ty::ReEarlyBound(ty::EarlyBoundRegion { - space: space, index: i as u32, name: name, }); diff --git a/src/librustc_typeck/coherence/mod.rs b/src/librustc_typeck/coherence/mod.rs index 17a84e98e61e2..4a1e401f9820f 100644 --- a/src/librustc_typeck/coherence/mod.rs +++ b/src/librustc_typeck/coherence/mod.rs @@ -17,7 +17,7 @@ use hir::def_id::DefId; use middle::lang_items::UnsizeTraitLangItem; -use rustc::ty::subst::{self, Subst}; +use rustc::ty::subst::Subst; use rustc::ty::{self, TyCtxt, TypeFoldable}; use rustc::traits::{self, Reveal}; use rustc::ty::{ImplOrTraitItemId, ConstTraitItemId}; @@ -386,7 +386,7 @@ impl<'a, 'gcx, 'tcx> CoherenceChecker<'a, 'gcx, 'tcx> { let source = tcx.lookup_item_type(impl_did).ty; let trait_ref = self.crate_context.tcx.impl_trait_ref(impl_did).unwrap(); - let target = *trait_ref.substs.types.get(subst::TypeSpace, 1); + let target = trait_ref.substs.types[1]; debug!("check_implementations_of_coerce_unsized: {:?} -> {:?} (bound)", source, target); diff --git a/src/librustc_typeck/collect.rs b/src/librustc_typeck/collect.rs index 939f8ac50a6c6..ed406b9379e35 100644 --- a/src/librustc_typeck/collect.rs +++ b/src/librustc_typeck/collect.rs @@ -65,7 +65,7 @@ use middle::lang_items::SizedTraitLangItem; use middle::const_val::ConstVal; use rustc_const_eval::EvalHint::UncheckedExprHint; use rustc_const_eval::{eval_const_expr_partial, report_const_eval_err}; -use rustc::ty::subst::{Substs, FnSpace, ParamSpace, TypeSpace}; +use rustc::ty::subst::Substs; use rustc::ty::{ToPredicate, ImplContainer, ImplOrTraitItemContainer, TraitContainer}; use rustc::ty::{self, ToPolyTraitRef, Ty, TyCtxt, TypeScheme}; use rustc::ty::{VariantKind}; @@ -473,10 +473,10 @@ impl<'tcx> GetTypeParameterBounds<'tcx> for ty::GenericPredicates<'tcx> { results.extend(self.predicates.iter().filter(|predicate| { match **predicate { ty::Predicate::Trait(ref data) => { - data.skip_binder().self_ty().is_param(def.space, def.index) + data.skip_binder().self_ty().is_param(def.index) } ty::Predicate::TypeOutlives(ref data) => { - data.skip_binder().0.is_param(def.space, def.index) + data.skip_binder().0.is_param(def.index) } ty::Predicate::Rfc1592(..) | ty::Predicate::Equate(..) | @@ -571,7 +571,7 @@ fn convert_method<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, let ty_generics = generics_of_def_id(ccx, def_id); let ty_generic_predicates = - ty_generic_predicates(ccx, FnSpace, &sig.generics, ty_generics.parent, vec![], false); + ty_generic_predicates(ccx, &sig.generics, ty_generics.parent, vec![], false); let (fty, explicit_self_category) = { let anon_scope = match container { @@ -752,7 +752,7 @@ fn convert_item(ccx: &CrateCtxt, it: &hir::Item) { let def_id = ccx.tcx.map.local_def_id(it.id); let ty_generics = generics_of_def_id(ccx, def_id); let mut ty_predicates = - ty_generic_predicates(ccx, TypeSpace, generics, None, vec![], false); + ty_generic_predicates(ccx, generics, None, vec![], false); debug!("convert: impl_bounds={:?}", ty_predicates); @@ -1346,7 +1346,7 @@ fn convert_trait_predicates<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, it: &hir::Item) // add in the explicit where-clauses let mut trait_predicates = - ty_generic_predicates(ccx, TypeSpace, generics, None, base_predicates, true); + ty_generic_predicates(ccx, generics, None, base_predicates, true); let assoc_predicates = predicates_for_associated_types(ccx, generics, @@ -1419,31 +1419,33 @@ fn generics_of_def_id<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, let mut allow_defaults = false; let no_generics = hir::Generics::empty(); - let (space, ast_generics) = match node { + let ast_generics = match node { NodeTraitItem(item) => { match item.node { - MethodTraitItem(ref sig, _) => (FnSpace, &sig.generics), - _ => (FnSpace, &no_generics) + MethodTraitItem(ref sig, _) => &sig.generics, + _ => &no_generics } } NodeImplItem(item) => { match item.node { - ImplItemKind::Method(ref sig, _) => (FnSpace, &sig.generics), - _ => (FnSpace, &no_generics) + ImplItemKind::Method(ref sig, _) => &sig.generics, + _ => &no_generics } } NodeItem(item) => { match item.node { - ItemFn(_, _, _, _, ref generics, _) => (FnSpace, generics), - ItemImpl(_, _, ref generics, _, _, _) => (TypeSpace, generics), + ItemFn(_, _, _, _, ref generics, _) | + ItemImpl(_, _, ref generics, _, _, _) => generics, + ItemTy(_, ref generics) | ItemEnum(_, ref generics) | ItemStruct(_, ref generics) => { allow_defaults = true; - (TypeSpace, generics) + generics } + ItemTrait(_, ref generics, _, _) => { // Add in the self type parameter. // @@ -1454,7 +1456,6 @@ fn generics_of_def_id<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, let parent = ccx.tcx.map.get_parent(param_id); let def = ty::TypeParameterDef { - space: TypeSpace, index: 0, name: keywords::SelfType.name(), def_id: tcx.map.local_def_id(param_id), @@ -1466,20 +1467,21 @@ fn generics_of_def_id<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, opt_self = Some(def); allow_defaults = true; - (TypeSpace, generics) + generics } - _ => (TypeSpace, &no_generics) + + _ => &no_generics } } NodeForeignItem(item) => { match item.node { - ForeignItemStatic(..) => (TypeSpace, &no_generics), - ForeignItemFn(_, ref generics) => (FnSpace, generics) + ForeignItemStatic(..) => &no_generics, + ForeignItemFn(_, ref generics) => generics } } - _ => (TypeSpace, &no_generics) + _ => &no_generics }; let has_self = opt_self.is_some(); @@ -1491,15 +1493,14 @@ fn generics_of_def_id<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, assert_eq!(generics.parent_types, 0); assert_eq!(has_self, false); parent_has_self = generics.has_self; - (generics.regions.len(), generics.types.len()) + (generics.regions.len() as u32, generics.types.len() as u32) }); let early_lifetimes = early_bound_lifetimes_from_generics(ccx, ast_generics); let regions = early_lifetimes.iter().enumerate().map(|(i, l)| { ty::RegionParameterDef { name: l.lifetime.name, - space: space, - index: i as u32, + index: parent_regions + i as u32, def_id: tcx.map.local_def_id(l.lifetime.id), bounds: l.bounds.iter().map(|l| { ast_region_to_region(tcx, l) @@ -1509,8 +1510,8 @@ fn generics_of_def_id<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, // Now create the real type parameters. let types = ast_generics.ty_params.iter().enumerate().map(|(i, p)| { - let i = has_self as u32 + i as u32; - get_or_create_type_parameter_def(ccx, ast_generics, space, i, p, allow_defaults) + let i = parent_types + has_self as u32 + i as u32; + get_or_create_type_parameter_def(ccx, ast_generics, i, p, allow_defaults) }); let types: Vec<_> = opt_self.into_iter().chain(types).collect(); @@ -1631,15 +1632,15 @@ fn predicates_of_item<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, let def_id = ccx.tcx.map.local_def_id(it.id); let no_generics = hir::Generics::empty(); - let (space, generics) = match it.node { - hir::ItemFn(_, _, _, _, ref generics, _) => (FnSpace, generics), + let generics = match it.node { + hir::ItemFn(_, _, _, _, ref generics, _) | hir::ItemTy(_, ref generics) | hir::ItemEnum(_, ref generics) | - hir::ItemStruct(_, ref generics) => (TypeSpace, generics), - _ => (TypeSpace, &no_generics) + hir::ItemStruct(_, ref generics) => generics, + _ => &no_generics }; - let predicates = ty_generic_predicates(ccx, space, generics, None, vec![], false); + let predicates = ty_generic_predicates(ccx, generics, None, vec![], false); let prev_predicates = ccx.tcx.predicates.borrow_mut().insert(def_id, predicates.clone()); assert!(prev_predicates.is_none()); @@ -1658,12 +1659,12 @@ fn convert_foreign_item<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, type_scheme_of_def_id(ccx, def_id); let no_generics = hir::Generics::empty(); - let (space, generics) = match it.node { - hir::ForeignItemFn(_, ref generics) => (FnSpace, generics), - hir::ForeignItemStatic(..) => (TypeSpace, &no_generics) + let generics = match it.node { + hir::ForeignItemFn(_, ref generics) => generics, + hir::ForeignItemStatic(..) => &no_generics }; - let predicates = ty_generic_predicates(ccx, space, generics, None, vec![], false); + let predicates = ty_generic_predicates(ccx, generics, None, vec![], false); let prev_predicates = ccx.tcx.predicates.borrow_mut().insert(def_id, predicates); assert!(prev_predicates.is_none()); } @@ -1733,7 +1734,6 @@ fn early_bound_lifetimes_from_generics<'a, 'tcx, 'hir>( } fn ty_generic_predicates<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>, - space: ParamSpace, ast_generics: &hir::Generics, parent: Option, super_predicates: Vec>, @@ -1741,6 +1741,13 @@ fn ty_generic_predicates<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>, -> ty::GenericPredicates<'tcx> { let tcx = ccx.tcx; + let (parent_regions, parent_types) = parent.map_or((0, 0), |def_id| { + let generics = generics_of_def_id(ccx, def_id); + assert_eq!(generics.parent, None); + assert_eq!(generics.parent_regions, 0); + assert_eq!(generics.parent_types, 0); + (generics.regions.len() as u32, generics.types.len() as u32) + }); let ref base_predicates = match parent { Some(def_id) => { assert_eq!(super_predicates, vec![]); @@ -1758,8 +1765,8 @@ fn ty_generic_predicates<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>, // Collect the predicates that were written inline by the user on each // type parameter (e.g., ``). for (index, param) in ast_generics.ty_params.iter().enumerate() { - let index = has_self as u32 + index as u32; - let param_ty = ty::ParamTy::new(space, index, param.name).to_ty(ccx.tcx); + let index = parent_types + has_self as u32 + index as u32; + let param_ty = ty::ParamTy::new(index, param.name).to_ty(ccx.tcx); let bounds = compute_bounds(&ccx.icx(&(base_predicates, ast_generics)), param_ty, ¶m.bounds, @@ -1774,10 +1781,9 @@ fn ty_generic_predicates<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>, // have to be careful to only iterate over early-bound regions. let early_lifetimes = early_bound_lifetimes_from_generics(ccx, ast_generics); for (index, param) in early_lifetimes.iter().enumerate() { - let index = index as u32; + let index = parent_regions + index as u32; let region = ty::ReEarlyBound(ty::EarlyBoundRegion { - space: space, index: index, name: param.lifetime.name }); @@ -1852,7 +1858,6 @@ fn ty_generic_predicates<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>, fn get_or_create_type_parameter_def<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>, ast_generics: &hir::Generics, - space: ParamSpace, index: u32, param: &hir::TyParam, allow_defaults: bool) @@ -1885,7 +1890,6 @@ fn get_or_create_type_parameter_def<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>, } let def = ty::TypeParameterDef { - space: space, index: index, name: param.name, def_id: ccx.tcx.map.local_def_id(param.id), @@ -1900,8 +1904,7 @@ fn get_or_create_type_parameter_def<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>, tcx.ty_param_defs.borrow_mut().insert(param.id, def.clone()); - debug!("get_or_create_type_parameter_def: def for type param: {:?}, {:?}", - def, space); + debug!("get_or_create_type_parameter_def: def for type param: {:?}", def); def } @@ -2190,9 +2193,10 @@ fn enforce_impl_lifetimes_are_constrained<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, .collect(); for (index, lifetime_def) in ast_generics.lifetimes.iter().enumerate() { - let region = ty::EarlyBoundRegion { space: TypeSpace, - index: index as u32, - name: lifetime_def.lifetime.name }; + let region = ty::EarlyBoundRegion { + index: index as u32, + name: lifetime_def.lifetime.name + }; if lifetimes_in_associated_types.contains(®ion) && // (*) !input_parameters.contains(&ctp::Parameter::Region(region)) diff --git a/src/librustc_typeck/variance/constraints.rs b/src/librustc_typeck/variance/constraints.rs index 95ddb59c0e28a..536fa629fd611 100644 --- a/src/librustc_typeck/variance/constraints.rs +++ b/src/librustc_typeck/variance/constraints.rs @@ -16,7 +16,7 @@ use dep_graph::DepTrackingMapConfig; use hir::def_id::DefId; use middle::resolve_lifetime as rl; -use rustc::ty::subst::{self, ParamSpace, Substs}; +use rustc::ty::subst::Substs; use rustc::ty::{self, Ty, TyCtxt}; use rustc::ty::maps::ItemVariances; use rustc::hir::map as hir_map; @@ -144,7 +144,7 @@ impl<'a, 'tcx> ConstraintContext<'a, 'tcx> { let tcx = self.terms_cx.tcx; assert!(is_lifetime(&tcx.map, param_id)); match tcx.named_region_map.defs.get(¶m_id) { - Some(&rl::DefEarlyBoundRegion(_, _, lifetime_decl_id)) + Some(&rl::DefEarlyBoundRegion(_, lifetime_decl_id)) => lifetime_decl_id, Some(_) => bug!("should not encounter non early-bound cases"), @@ -210,7 +210,6 @@ impl<'a, 'tcx> ConstraintContext<'a, 'tcx> { param_def_id: DefId, item_def_id: DefId, kind: ParamKind, - space: ParamSpace, index: usize) -> VarianceTermPtr<'a> { assert_eq!(param_def_id.krate, item_def_id.krate); @@ -226,8 +225,8 @@ impl<'a, 'tcx> ConstraintContext<'a, 'tcx> { // variance already inferred, just look it up. let variances = self.tcx().item_variances(item_def_id); let variance = match kind { - TypeParam => *variances.types.get(space, index), - RegionParam => *variances.regions.get(space, index), + TypeParam => variances.types[index], + RegionParam => variances.regions[index], }; self.constant_term(variance) } @@ -401,8 +400,8 @@ impl<'a, 'tcx> ConstraintContext<'a, 'tcx> { } ty::TyParam(ref data) => { - assert_eq!(data.space, subst::TypeSpace); assert_eq!(generics.parent, None); + assert!((data.idx as usize) < generics.types.len()); let def_id = generics.types[data.idx as usize].def_id; let node_id = self.tcx().map.as_local_node_id(def_id).unwrap(); match self.terms_cx.inferred_map.get(&node_id) { @@ -450,8 +449,7 @@ impl<'a, 'tcx> ConstraintContext<'a, 'tcx> { for p in type_param_defs { let variance_decl = - self.declared_variance(p.def_id, def_id, TypeParam, - p.space, p.index as usize); + self.declared_variance(p.def_id, def_id, TypeParam, p.index as usize); let variance_i = self.xform(variance, variance_decl); let substs_ty = substs.type_for_def(p); debug!("add_constraints_from_substs: variance_decl={:?} variance_i={:?}", @@ -461,8 +459,7 @@ impl<'a, 'tcx> ConstraintContext<'a, 'tcx> { for p in region_param_defs { let variance_decl = - self.declared_variance(p.def_id, def_id, - RegionParam, p.space, p.index as usize); + self.declared_variance(p.def_id, def_id, RegionParam, p.index as usize); let variance_i = self.xform(variance, variance_decl); let substs_r = substs.region_for_def(p); self.add_constraints_from_region(generics, substs_r, variance_i); @@ -490,8 +487,8 @@ impl<'a, 'tcx> ConstraintContext<'a, 'tcx> { variance: VarianceTermPtr<'a>) { match region { ty::ReEarlyBound(ref data) => { - assert_eq!(data.space, subst::TypeSpace); assert_eq!(generics.parent, None); + assert!((data.index as usize) < generics.regions.len()); let def_id = generics.regions[data.index as usize].def_id; let node_id = self.tcx().map.as_local_node_id(def_id).unwrap(); if self.is_to_be_inferred(node_id) { diff --git a/src/librustc_typeck/variance/solve.rs b/src/librustc_typeck/variance/solve.rs index 9048d892b09d2..d3b63119bcb32 100644 --- a/src/librustc_typeck/variance/solve.rs +++ b/src/librustc_typeck/variance/solve.rs @@ -16,7 +16,6 @@ //! inferred is then written into the `variance_map` in the tcx. use rustc::ty; -use rustc::ty::subst; use std::rc::Rc; use super::constraints::*; @@ -110,41 +109,27 @@ impl<'a, 'tcx> SolveContext<'a, 'tcx> { while index < num_inferred { let item_id = inferred_infos[index].item_id; - let (mut rt, mut rf) = (vec![], vec![]); - let (mut tt, mut tf) = (vec![], vec![]); + let mut item_variances = ty::ItemVariances::empty(); while index < num_inferred && inferred_infos[index].item_id == item_id { let info = &inferred_infos[index]; let variance = solutions[index]; - debug!("Index {} Info {} / {:?} / {:?} Variance {:?}", - index, info.index, info.kind, info.space, variance); + debug!("Index {} Info {} / {:?} Variance {:?}", + index, info.index, info.kind, variance); match info.kind { TypeParam => { - let types = match info.space { - subst::TypeSpace => &mut tt, - subst::FnSpace => &mut tf - }; - assert_eq!(types.len(), info.index); - types.push(variance); + assert_eq!(item_variances.types.len(), info.index); + item_variances.types.push(variance); } RegionParam => { - let regions = match info.space { - subst::TypeSpace => &mut rt, - subst::FnSpace => &mut rf - }; - assert_eq!(regions.len(), info.index); - regions.push(variance); + assert_eq!(item_variances.regions.len(), info.index); + item_variances.regions.push(variance); } } index += 1; } - let item_variances = ty::ItemVariances { - regions: subst::VecPerParamSpace::new(rt, rf), - types: subst::VecPerParamSpace::new(tt, tf) - }; - debug!("item_id={} item_variances={:?}", item_id, item_variances); diff --git a/src/librustc_typeck/variance/terms.rs b/src/librustc_typeck/variance/terms.rs index 9dc38bb195c14..d30cbc8f117cf 100644 --- a/src/librustc_typeck/variance/terms.rs +++ b/src/librustc_typeck/variance/terms.rs @@ -21,7 +21,6 @@ use arena::TypedArena; use dep_graph::DepTrackingMapConfig; -use rustc::ty::subst::{ParamSpace, FnSpace, TypeSpace}; use rustc::ty::{self, TyCtxt}; use rustc::ty::maps::ItemVariances; use std::fmt; @@ -86,7 +85,6 @@ pub enum ParamKind { pub struct InferredInfo<'a> { pub item_id: ast::NodeId, pub kind: ParamKind, - pub space: ParamSpace, pub index: usize, pub param_id: ast::NodeId, pub term: VarianceTermPtr<'a>, @@ -166,15 +164,15 @@ impl<'a, 'tcx> TermsContext<'a, 'tcx> { for (i, p) in generics.lifetimes.iter().enumerate() { let id = p.lifetime.id; - self.add_inferred(item_id, RegionParam, TypeSpace, i, id); + self.add_inferred(item_id, RegionParam, i, id); } if has_self { - self.add_inferred(item_id, TypeParam, TypeSpace, 0, item_id); + self.add_inferred(item_id, TypeParam, 0, item_id); } for (i, p) in generics.ty_params.iter().enumerate() { let i = has_self as usize + i; - self.add_inferred(item_id, TypeParam, TypeSpace, i, p.id); + self.add_inferred(item_id, TypeParam, i, p.id); } // If this item has no type or lifetime parameters, @@ -197,15 +195,13 @@ impl<'a, 'tcx> TermsContext<'a, 'tcx> { fn add_inferred(&mut self, item_id: ast::NodeId, kind: ParamKind, - space: ParamSpace, index: usize, param_id: ast::NodeId) { let inf_index = InferredIndex(self.inferred_infos.len()); let term = self.arena.alloc(InferredTerm(inf_index)); - let initial_variance = self.pick_initial_variance(item_id, space, index); + let initial_variance = self.pick_initial_variance(item_id, index); self.inferred_infos.push(InferredInfo { item_id: item_id, kind: kind, - space: space, index: index, param_id: param_id, term: term, @@ -216,33 +212,23 @@ impl<'a, 'tcx> TermsContext<'a, 'tcx> { debug!("add_inferred(item_path={}, \ item_id={}, \ kind={:?}, \ - space={:?}, \ index={}, \ param_id={}, \ inf_index={:?}, \ initial_variance={:?})", self.tcx.item_path_str(self.tcx.map.local_def_id(item_id)), - item_id, kind, space, index, param_id, inf_index, + item_id, kind, index, param_id, inf_index, initial_variance); } fn pick_initial_variance(&self, item_id: ast::NodeId, - space: ParamSpace, index: usize) -> ty::Variance { - match space { - FnSpace => { - ty::Bivariant - } - - TypeSpace => { - match self.lang_items.iter().find(|&&(n, _)| n == item_id) { - Some(&(_, ref variances)) => variances[index], - None => ty::Bivariant - } - } + match self.lang_items.iter().find(|&&(n, _)| n == item_id) { + Some(&(_, ref variances)) => variances[index], + None => ty::Bivariant } } diff --git a/src/librustdoc/clean/inline.rs b/src/librustdoc/clean/inline.rs index 427468069d04e..013433336a1d5 100644 --- a/src/librustdoc/clean/inline.rs +++ b/src/librustdoc/clean/inline.rs @@ -388,8 +388,6 @@ pub fn build_impl<'a, 'tcx>(cx: &DocContext, } ty::TypeTraitItem(ref assoc_ty) => { let did = assoc_ty.def_id; - // Not sure the choice of ParamSpace actually matters here, - // because an associated type won't have generics on the LHS let typedef = clean::Typedef { type_: assoc_ty.ty.unwrap().clean(cx), generics: clean::Generics { diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index 90288b17dfcce..75d21399f05e6 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -41,7 +41,7 @@ use rustc::hir::def::Def; use rustc::hir::def_id::{DefId, DefIndex, CRATE_DEF_INDEX}; use rustc::hir::fold::Folder; use rustc::hir::print as pprust; -use rustc::ty::subst::{self, Substs, VecPerParamSpace}; +use rustc::ty::subst::Substs; use rustc::ty; use rustc::middle::stability; @@ -82,12 +82,6 @@ impl, U> Clean> for [T] { } } -impl, U> Clean> for VecPerParamSpace { - fn clean(&self, cx: &DocContext) -> VecPerParamSpace { - self.map(|x| x.clean(cx)) - } -} - impl, U> Clean for P { fn clean(&self, cx: &DocContext) -> U { (**self).clean(cx) @@ -632,12 +626,8 @@ impl Clean for hir::TyParamBound { fn external_path_params(cx: &DocContext, trait_did: Option, has_self: bool, bindings: Vec, substs: &Substs) -> PathParameters { - let lifetimes = substs.regions.get_slice(subst::TypeSpace) - .iter() - .filter_map(|v| v.clean(cx)) - .collect(); - let types = substs.types.get_slice(subst::TypeSpace); - let types = types[has_self as usize..].to_vec(); + let lifetimes = substs.regions.iter().filter_map(|v| v.clean(cx)).collect(); + let types = substs.types[has_self as usize..].to_vec(); match (trait_did, cx.tcx_opt()) { // Attempt to sugar an external path like Fn<(A, B,), C> to Fn(A, B) -> C @@ -731,7 +721,7 @@ impl<'tcx> Clean for ty::TraitRef<'tcx> { let path = external_path(cx, &tcx.item_name(self.def_id).as_str(), Some(self.def_id), true, vec![], self.substs); - debug!("ty::TraitRef\n substs.types(TypeSpace): {:?}\n", + debug!("ty::TraitRef\n substs.types: {:?}\n", &self.input_types()[1..]); // collect any late bound regions @@ -769,9 +759,9 @@ impl<'tcx> Clean for ty::TraitRef<'tcx> { impl<'tcx> Clean>> for Substs<'tcx> { fn clean(&self, cx: &DocContext) -> Option> { let mut v = Vec::new(); - v.extend(self.regions.as_full_slice().iter().filter_map(|r| r.clean(cx)) + v.extend(self.regions.iter().filter_map(|r| r.clean(cx)) .map(RegionBound)); - v.extend(self.types.as_full_slice().iter().map(|t| TraitBound(PolyTrait { + v.extend(self.types.iter().map(|t| TraitBound(PolyTrait { trait_: t.clean(cx), lifetimes: vec![] }, hir::TraitBoundModifier::None))); @@ -1637,7 +1627,7 @@ impl<'a, 'tcx: 'a, 'b: 'tcx> Folder for SubstAlias<'a, 'tcx> { fn fold_lifetime(&mut self, lt: hir::Lifetime) -> hir::Lifetime { let def = self.tcx.named_region_map.defs.get(<.id).cloned(); match def { - Some(DefEarlyBoundRegion(_, _, node_id)) | + Some(DefEarlyBoundRegion(_, node_id)) | Some(DefLateBoundRegion(_, node_id)) | Some(DefFreeRegion(_, node_id)) => { if let Some(lt) = self.lt_substs.get(&node_id).cloned() { diff --git a/src/test/compile-fail/variance-associated-types.rs b/src/test/compile-fail/variance-associated-types.rs index 9aa4d29c4ecf7..5539a26d2a170 100644 --- a/src/test/compile-fail/variance-associated-types.rs +++ b/src/test/compile-fail/variance-associated-types.rs @@ -20,12 +20,12 @@ trait Trait<'a> { } #[rustc_variance] -struct Foo<'a, T : Trait<'a>> { //~ ERROR ItemVariances(types=[[+];[]], regions=[[-];[]]) +struct Foo<'a, T : Trait<'a>> { //~ ERROR ItemVariances(types=[+], regions=[-]) field: (T, &'a ()) } #[rustc_variance] -struct Bar<'a, T : Trait<'a>> { //~ ERROR ItemVariances(types=[[o];[]], regions=[[o];[]]) +struct Bar<'a, T : Trait<'a>> { //~ ERROR ItemVariances(types=[o], regions=[o]) field: >::Type } diff --git a/src/test/compile-fail/variance-object-types.rs b/src/test/compile-fail/variance-object-types.rs index 3c8b27f965a61..2f422bfd38cc7 100644 --- a/src/test/compile-fail/variance-object-types.rs +++ b/src/test/compile-fail/variance-object-types.rs @@ -18,7 +18,7 @@ use std::cell::Cell; // For better or worse, associated types are invariant, and hence we // get an invariant result for `'a`. #[rustc_variance] -struct Foo<'a> { //~ ERROR regions=[[o];[]] +struct Foo<'a> { //~ ERROR regions=[o] x: Box &'a i32 + 'static> } diff --git a/src/test/compile-fail/variance-region-bounds.rs b/src/test/compile-fail/variance-region-bounds.rs index ae5a8674f446c..99416057b2540 100644 --- a/src/test/compile-fail/variance-region-bounds.rs +++ b/src/test/compile-fail/variance-region-bounds.rs @@ -13,11 +13,11 @@ #![feature(rustc_attrs)] #[rustc_variance] -trait Foo: 'static { //~ ERROR types=[[o];[]] +trait Foo: 'static { //~ ERROR types=[o] } #[rustc_variance] -trait Bar { //~ ERROR types=[[o, o];[]] +trait Bar { //~ ERROR types=[o, o] fn do_it(&self) where T: 'static; } diff --git a/src/test/compile-fail/variance-regions-direct.rs b/src/test/compile-fail/variance-regions-direct.rs index 93d3d2773149e..78591063de8ab 100644 --- a/src/test/compile-fail/variance-regions-direct.rs +++ b/src/test/compile-fail/variance-regions-direct.rs @@ -16,7 +16,7 @@ // Regions that just appear in normal spots are contravariant: #[rustc_variance] -struct Test2<'a, 'b, 'c> { //~ ERROR regions=[[-, -, -];[]] +struct Test2<'a, 'b, 'c> { //~ ERROR regions=[-, -, -] x: &'a isize, y: &'b [isize], c: &'c str @@ -25,7 +25,7 @@ struct Test2<'a, 'b, 'c> { //~ ERROR regions=[[-, -, -];[]] // Those same annotations in function arguments become covariant: #[rustc_variance] -struct Test3<'a, 'b, 'c> { //~ ERROR regions=[[+, +, +];[]] +struct Test3<'a, 'b, 'c> { //~ ERROR regions=[+, +, +] x: extern "Rust" fn(&'a isize), y: extern "Rust" fn(&'b [isize]), c: extern "Rust" fn(&'c str), @@ -34,7 +34,7 @@ struct Test3<'a, 'b, 'c> { //~ ERROR regions=[[+, +, +];[]] // Mutability induces invariance: #[rustc_variance] -struct Test4<'a, 'b:'a> { //~ ERROR regions=[[-, o];[]] +struct Test4<'a, 'b:'a> { //~ ERROR regions=[-, o] x: &'a mut &'b isize, } @@ -42,7 +42,7 @@ struct Test4<'a, 'b:'a> { //~ ERROR regions=[[-, o];[]] // contravariant context: #[rustc_variance] -struct Test5<'a, 'b:'a> { //~ ERROR regions=[[+, o];[]] +struct Test5<'a, 'b:'a> { //~ ERROR regions=[+, o] x: extern "Rust" fn(&'a mut &'b isize), } @@ -52,14 +52,14 @@ struct Test5<'a, 'b:'a> { //~ ERROR regions=[[+, o];[]] // argument list occurs in an invariant context. #[rustc_variance] -struct Test6<'a, 'b:'a> { //~ ERROR regions=[[-, o];[]] +struct Test6<'a, 'b:'a> { //~ ERROR regions=[-, o] x: &'a mut extern "Rust" fn(&'b isize), } // No uses at all is bivariant: #[rustc_variance] -struct Test7<'a> { //~ ERROR regions=[[*];[]] +struct Test7<'a> { //~ ERROR regions=[*] //~^ ERROR parameter `'a` is never used x: isize } @@ -67,7 +67,7 @@ struct Test7<'a> { //~ ERROR regions=[[*];[]] // Try enums too. #[rustc_variance] -enum Test8<'a, 'b, 'c:'b> { //~ ERROR regions=[[+, -, o];[]] +enum Test8<'a, 'b, 'c:'b> { //~ ERROR regions=[+, -, o] Test8A(extern "Rust" fn(&'a isize)), Test8B(&'b [isize]), Test8C(&'b mut &'c str), diff --git a/src/test/compile-fail/variance-regions-indirect.rs b/src/test/compile-fail/variance-regions-indirect.rs index eeb981b707e31..d8af30da163bf 100644 --- a/src/test/compile-fail/variance-regions-indirect.rs +++ b/src/test/compile-fail/variance-regions-indirect.rs @@ -15,7 +15,7 @@ #![feature(rustc_attrs)] #[rustc_variance] -enum Base<'a, 'b, 'c:'b, 'd> { //~ ERROR regions=[[+, -, o, *];[]] +enum Base<'a, 'b, 'c:'b, 'd> { //~ ERROR regions=[+, -, o, *] //~^ ERROR parameter `'d` is never used Test8A(extern "Rust" fn(&'a isize)), Test8B(&'b [isize]), @@ -23,25 +23,25 @@ enum Base<'a, 'b, 'c:'b, 'd> { //~ ERROR regions=[[+, -, o, *];[]] } #[rustc_variance] -struct Derived1<'w, 'x:'y, 'y, 'z> { //~ ERROR regions=[[*, o, -, +];[]] +struct Derived1<'w, 'x:'y, 'y, 'z> { //~ ERROR regions=[*, o, -, +] //~^ ERROR parameter `'w` is never used f: Base<'z, 'y, 'x, 'w> } #[rustc_variance] // Combine - and + to yield o -struct Derived2<'a, 'b:'a, 'c> { //~ ERROR regions=[[o, o, *];[]] +struct Derived2<'a, 'b:'a, 'c> { //~ ERROR regions=[o, o, *] //~^ ERROR parameter `'c` is never used f: Base<'a, 'a, 'b, 'c> } #[rustc_variance] // Combine + and o to yield o (just pay attention to 'a here) -struct Derived3<'a:'b, 'b, 'c> { //~ ERROR regions=[[o, -, *];[]] +struct Derived3<'a:'b, 'b, 'c> { //~ ERROR regions=[o, -, *] //~^ ERROR parameter `'c` is never used f: Base<'a, 'b, 'a, 'c> } #[rustc_variance] // Combine + and * to yield + (just pay attention to 'a here) -struct Derived4<'a, 'b, 'c:'b> { //~ ERROR regions=[[+, -, o];[]] +struct Derived4<'a, 'b, 'c:'b> { //~ ERROR regions=[+, -, o] f: Base<'a, 'b, 'c, 'a> } diff --git a/src/test/compile-fail/variance-trait-bounds.rs b/src/test/compile-fail/variance-trait-bounds.rs index 860dd6deefd5b..150a1aa56fe72 100644 --- a/src/test/compile-fail/variance-trait-bounds.rs +++ b/src/test/compile-fail/variance-trait-bounds.rs @@ -15,48 +15,48 @@ // influence variance. #[rustc_variance] -trait Getter { //~ ERROR types=[[o, o];[]] +trait Getter { //~ ERROR types=[o, o] fn get(&self) -> T; } #[rustc_variance] -trait Setter { //~ ERROR types=[[o, o];[]] +trait Setter { //~ ERROR types=[o, o] fn get(&self, T); } #[rustc_variance] -struct TestStruct> { //~ ERROR types=[[+, +];[]] +struct TestStruct> { //~ ERROR types=[+, +] t: T, u: U } #[rustc_variance] -enum TestEnum> {//~ ERROR types=[[*, +];[]] +enum TestEnum> {//~ ERROR types=[*, +] //~^ ERROR parameter `U` is never used Foo(T) } #[rustc_variance] -trait TestTrait> { //~ ERROR types=[[o, o, o];[]] +trait TestTrait> { //~ ERROR types=[o, o, o] fn getter(&self, u: U) -> T; } #[rustc_variance] -trait TestTrait2 : Getter { //~ ERROR types=[[o, o];[]] +trait TestTrait2 : Getter { //~ ERROR types=[o, o] } #[rustc_variance] -trait TestTrait3 { //~ ERROR types=[[o, o];[]] +trait TestTrait3 { //~ ERROR types=[o, o] fn getter>(&self); } #[rustc_variance] -struct TestContraStruct> { //~ ERROR types=[[*, +];[]] +struct TestContraStruct> { //~ ERROR types=[*, +] //~^ ERROR parameter `U` is never used t: T } #[rustc_variance] -struct TestBox+Setter> { //~ ERROR types=[[*, +];[]] +struct TestBox+Setter> { //~ ERROR types=[*, +] //~^ ERROR parameter `U` is never used t: T } diff --git a/src/test/compile-fail/variance-trait-object-bound.rs b/src/test/compile-fail/variance-trait-object-bound.rs index b37007a6d34e4..4244b0e1d8b8b 100644 --- a/src/test/compile-fail/variance-trait-object-bound.rs +++ b/src/test/compile-fail/variance-trait-object-bound.rs @@ -21,7 +21,7 @@ use std::mem; trait T { fn foo(&self); } #[rustc_variance] -struct TOption<'a> { //~ ERROR regions=[[-];[]] +struct TOption<'a> { //~ ERROR regions=[-] v: Option>, } diff --git a/src/test/compile-fail/variance-types-bounds.rs b/src/test/compile-fail/variance-types-bounds.rs index 8eb96814fa8f0..c47710d6d376d 100644 --- a/src/test/compile-fail/variance-types-bounds.rs +++ b/src/test/compile-fail/variance-types-bounds.rs @@ -14,46 +14,46 @@ #![feature(rustc_attrs)] #[rustc_variance] -struct TestImm { //~ ERROR types=[[+, +];[]] +struct TestImm { //~ ERROR types=[+, +] x: A, y: B, } #[rustc_variance] -struct TestMut { //~ ERROR types=[[+, o];[]] +struct TestMut { //~ ERROR types=[+, o] x: A, y: &'static mut B, } #[rustc_variance] -struct TestIndirect { //~ ERROR types=[[+, o];[]] +struct TestIndirect { //~ ERROR types=[+, o] m: TestMut } #[rustc_variance] -struct TestIndirect2 { //~ ERROR types=[[o, o];[]] +struct TestIndirect2 { //~ ERROR types=[o, o] n: TestMut, m: TestMut } #[rustc_variance] -trait Getter { //~ ERROR types=[[o, o];[]] +trait Getter { //~ ERROR types=[o, o] fn get(&self) -> A; } #[rustc_variance] -trait Setter { //~ ERROR types=[[o, o];[]] +trait Setter { //~ ERROR types=[o, o] fn set(&mut self, a: A); } #[rustc_variance] -trait GetterSetter { //~ ERROR types=[[o, o];[]] +trait GetterSetter { //~ ERROR types=[o, o] fn get(&self) -> A; fn set(&mut self, a: A); } #[rustc_variance] -trait GetterInTypeBound { //~ ERROR types=[[o, o];[]] +trait GetterInTypeBound { //~ ERROR types=[o, o] // Here, the use of `A` in the method bound *does* affect // variance. Think of it as if the method requested a dictionary // for `T:Getter`. Since this dictionary is an input, it is @@ -63,12 +63,12 @@ trait GetterInTypeBound { //~ ERROR types=[[o, o];[]] } #[rustc_variance] -trait SetterInTypeBound { //~ ERROR types=[[o, o];[]] +trait SetterInTypeBound { //~ ERROR types=[o, o] fn do_it>(&self); } #[rustc_variance] -struct TestObject { //~ ERROR types=[[o, o];[]] +struct TestObject { //~ ERROR types=[o, o] n: Box+Send>, m: Box+Send>, } diff --git a/src/test/compile-fail/variance-types.rs b/src/test/compile-fail/variance-types.rs index 791b56caea02b..d5164412358fc 100644 --- a/src/test/compile-fail/variance-types.rs +++ b/src/test/compile-fail/variance-types.rs @@ -17,32 +17,32 @@ use std::cell::Cell; // not considered bivariant. #[rustc_variance] -struct InvariantMut<'a,A:'a,B:'a> { //~ ERROR types=[[o, o];[]], regions=[[-];[]] +struct InvariantMut<'a,A:'a,B:'a> { //~ ERROR types=[o, o], regions=[-] t: &'a mut (A,B) } #[rustc_variance] -struct InvariantCell { //~ ERROR types=[[o];[]] +struct InvariantCell { //~ ERROR types=[o] t: Cell } #[rustc_variance] -struct InvariantIndirect { //~ ERROR types=[[o];[]] +struct InvariantIndirect { //~ ERROR types=[o] t: InvariantCell } #[rustc_variance] -struct Covariant { //~ ERROR types=[[+];[]] +struct Covariant { //~ ERROR types=[+] t: A, u: fn() -> A } #[rustc_variance] -struct Contravariant { //~ ERROR types=[[-];[]] +struct Contravariant { //~ ERROR types=[-] t: fn(A) } #[rustc_variance] -enum Enum { //~ ERROR types=[[+, -, o];[]] +enum Enum { //~ ERROR types=[+, -, o] Foo(Covariant), Bar(Contravariant), Zed(Covariant,Contravariant) diff --git a/src/test/mir-opt/storage_ranges.rs b/src/test/mir-opt/storage_ranges.rs index b116d9c3c41cf..f93447b642a20 100644 --- a/src/test/mir-opt/storage_ranges.rs +++ b/src/test/mir-opt/storage_ranges.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// ignore-tidy-linelength + fn main() { let a = 0; { @@ -25,7 +27,7 @@ fn main() { // StorageLive(tmp1); // scope 1 at storage_ranges.rs:14:18: 14:25 // StorageLive(tmp2); // scope 1 at storage_ranges.rs:14:23: 14:24 // tmp2 = var0; // scope 1 at storage_ranges.rs:14:23: 14:24 -// tmp1 = std::prelude::v1::Some(tmp2,); // scope 1 at storage_ranges.rs:14:18: 14:25 +// tmp1 = std::option::Option::Some(tmp2,); // scope 1 at storage_ranges.rs:14:18: 14:25 // var1 = &tmp1; // scope 1 at storage_ranges.rs:14:17: 14:25 // StorageDead(tmp2); // scope 1 at storage_ranges.rs:14:23: 14:24 // tmp0 = (); // scope 2 at storage_ranges.rs:13:5: 15:6