diff options
| author | varkor <github@varkor.com> | 2018-05-14 18:27:13 +0100 |
|---|---|---|
| committer | varkor <github@varkor.com> | 2018-05-15 14:22:11 +0100 |
| commit | d9190da9825b729ce63becf727b2cfdad3e8561a (patch) | |
| tree | 1bffa6455bfc02acbcd9963f47823469d8e22987 | |
| parent | 030f10f752b6584e4f1974c104dd644dfffd80ad (diff) | |
| download | rust-d9190da9825b729ce63becf727b2cfdad3e8561a.tar.gz rust-d9190da9825b729ce63becf727b2cfdad3e8561a.zip | |
Refactor Substs methods on generic parameters
| -rw-r--r-- | src/librustc/infer/mod.rs | 17 | ||||
| -rw-r--r-- | src/librustc/traits/mod.rs | 18 | ||||
| -rw-r--r-- | src/librustc/ty/context.rs | 27 | ||||
| -rw-r--r-- | src/librustc/ty/subst.rs | 82 | ||||
| -rw-r--r-- | src/librustc/ty/util.rs | 17 | ||||
| -rw-r--r-- | src/librustc_mir/monomorphize/collector.rs | 18 | ||||
| -rw-r--r-- | src/librustc_mir/shim.rs | 16 | ||||
| -rw-r--r-- | src/librustc_typeck/astconv.rs | 144 | ||||
| -rw-r--r-- | src/librustc_typeck/check/closure.rs | 24 | ||||
| -rw-r--r-- | src/librustc_typeck/check/method/confirm.rs | 59 | ||||
| -rw-r--r-- | src/librustc_typeck/check/method/mod.rs | 28 | ||||
| -rw-r--r-- | src/librustc_typeck/check/method/probe.rs | 58 | ||||
| -rw-r--r-- | src/librustc_typeck/check/mod.rs | 129 | ||||
| -rw-r--r-- | src/librustc_typeck/check/wfcheck.rs | 39 | ||||
| -rw-r--r-- | src/librustc_typeck/collect.rs | 23 |
15 files changed, 393 insertions, 306 deletions
diff --git a/src/librustc/infer/mod.rs b/src/librustc/infer/mod.rs index 8dd661d0403..d90ba51fffc 100644 --- a/src/librustc/infer/mod.rs +++ b/src/librustc/infer/mod.rs @@ -21,9 +21,9 @@ use hir::def_id::DefId; use middle::free_region::RegionRelations; use middle::region; use middle::lang_items; -use ty::subst::Substs; +use ty::subst::{UnpackedKind, Substs}; use ty::{TyVid, IntVid, FloatVid}; -use ty::{self, Ty, TyCtxt}; +use ty::{self, Ty, TyCtxt, GenericParamDefKind}; use ty::error::{ExpectedFound, TypeError, UnconstrainedNumeric}; use ty::fold::TypeFoldable; use ty::relate::RelateResult; @@ -941,10 +941,15 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { span: Span, def_id: DefId) -> &'tcx Substs<'tcx> { - Substs::for_item(self.tcx, def_id, |def, _| { - self.region_var_for_def(span, def) - }, |def, _| { - self.type_var_for_def(span, def) + Substs::for_item(self.tcx, def_id, |param, _| { + match param.kind { + GenericParamDefKind::Lifetime => { + UnpackedKind::Lifetime(self.region_var_for_def(span, param)) + } + GenericParamDefKind::Type(_) => { + UnpackedKind::Type(self.type_var_for_def(span, param)) + } + } }) } diff --git a/src/librustc/traits/mod.rs b/src/librustc/traits/mod.rs index a765ffe2396..4b5c767b031 100644 --- a/src/librustc/traits/mod.rs +++ b/src/librustc/traits/mod.rs @@ -22,8 +22,8 @@ use hir::def_id::DefId; use infer::outlives::env::OutlivesEnvironment; use middle::region; use middle::const_val::ConstEvalErr; -use ty::subst::Substs; -use ty::{self, AdtKind, Slice, Ty, TyCtxt, TypeFoldable, ToPredicate}; +use ty::subst::{UnpackedKind, Substs}; +use ty::{self, AdtKind, Slice, Ty, TyCtxt, GenericParamDefKind, TypeFoldable, ToPredicate}; use ty::error::{ExpectedFound, TypeError}; use infer::{InferCtxt}; @@ -841,10 +841,16 @@ fn vtable_methods<'a, 'tcx>( // the method may have some early-bound lifetimes, add // regions for those let substs = trait_ref.map_bound(|trait_ref| { - Substs::for_item( - tcx, def_id, - |_, _| tcx.types.re_erased, - |def, _| trait_ref.substs.type_for_def(def)) + Substs::for_item(tcx, def_id, |param, _| { + match param.kind { + GenericParamDefKind::Lifetime => { + UnpackedKind::Lifetime(tcx.types.re_erased) + } + GenericParamDefKind::Type(_) => { + UnpackedKind::Type(trait_ref.substs.type_for_def(param)) + } + } + }) }); // the trait type may have higher-ranked lifetimes in it; diff --git a/src/librustc/ty/context.rs b/src/librustc/ty/context.rs index 995d6c55767..924271ea3d4 100644 --- a/src/librustc/ty/context.rs +++ b/src/librustc/ty/context.rs @@ -32,7 +32,7 @@ use middle::lang_items; use middle::resolve_lifetime::{self, ObjectLifetimeDefault}; use middle::stability; use mir::{self, Mir, interpret}; -use ty::subst::{Kind, Substs, Subst}; +use ty::subst::{Kind, UnpackedKind, Substs, Subst}; use ty::ReprOptions; use ty::Instance; use traits; @@ -44,6 +44,7 @@ use ty::{PolyFnSig, InferTy, ParamTy, ProjectionTy, ExistentialPredicate, Predic use ty::RegionKind; use ty::{TyVar, TyVid, IntVar, IntVid, FloatVar, FloatVid}; use ty::TypeVariants::*; +use ty::GenericParamDefKind; use ty::layout::{LayoutDetails, TargetDataLayout}; use ty::maps; use ty::steal::Steal; @@ -2325,16 +2326,22 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { pub fn mk_box(self, ty: Ty<'tcx>) -> Ty<'tcx> { let def_id = self.require_lang_item(lang_items::OwnedBoxLangItem); let adt_def = self.adt_def(def_id); - let substs = Substs::for_item(self, def_id, |_, _| bug!(), |def, substs| { - if def.index == 0 { - ty - } else { - match def.kind { - ty::GenericParamDefKind::Type(ty_param) => { - assert!(ty_param.has_default); - self.type_of(def.def_id).subst(self, substs) + let substs = Substs::for_item(self, def_id, |param, substs| { + match param.kind { + GenericParamDefKind::Lifetime => bug!(), + GenericParamDefKind::Type(_) => { + if param.index == 0 { + UnpackedKind::Type(ty) + } else { + match param.kind { + ty::GenericParamDefKind::Type(ty_param) => { + assert!(ty_param.has_default); + UnpackedKind::Type( + self.type_of(param.def_id).subst(self, substs)) + } + _ => unreachable!() + } } - _ => unreachable!() } } }); diff --git a/src/librustc/ty/subst.rs b/src/librustc/ty/subst.rs index d4db2ae481a..5c2b5c5cd45 100644 --- a/src/librustc/ty/subst.rs +++ b/src/librustc/ty/subst.rs @@ -11,7 +11,7 @@ // Type substitutions. use hir::def_id::DefId; -use ty::{self, Lift, Slice, Region, Ty, TyCtxt}; +use ty::{self, Lift, Slice, Region, Ty, TyCtxt, GenericParamDefKind}; use ty::fold::{TypeFoldable, TypeFolder, TypeVisitor}; use serialize::{self, Encodable, Encoder, Decodable, Decoder}; @@ -174,80 +174,80 @@ impl<'tcx> Decodable for Kind<'tcx> { } } -/// A substitution mapping type/region parameters to new values. +/// A substitution mapping generic parameters to new values. pub type Substs<'tcx> = Slice<Kind<'tcx>>; impl<'a, 'gcx, 'tcx> Substs<'tcx> { /// Creates a Substs that maps each generic parameter to itself. pub fn identity_for_item(tcx: TyCtxt<'a, 'gcx, 'tcx>, def_id: DefId) -> &'tcx Substs<'tcx> { - Substs::for_item(tcx, def_id, |def, _| { - tcx.mk_region(ty::ReEarlyBound(def.to_early_bound_region_data())) - }, |def, _| tcx.mk_ty_param_from_def(def)) + Substs::for_item(tcx, def_id, |param, _| { + match param.kind { + GenericParamDefKind::Lifetime => { + UnpackedKind::Lifetime( + tcx.mk_region(ty::ReEarlyBound(param.to_early_bound_region_data()))) + } + GenericParamDefKind::Type(_) => { + UnpackedKind::Type(tcx.mk_ty_param_from_def(param)) + } + } + }) } /// Creates a Substs for generic parameter definitions, - /// by calling closures to obtain each region and type. + /// by calling closures to obtain each kind. /// 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 for_item<FR, FT>(tcx: TyCtxt<'a, 'gcx, 'tcx>, - def_id: DefId, - mut mk_region: FR, - mut mk_type: FT) - -> &'tcx Substs<'tcx> - where FR: FnMut(&ty::GenericParamDef, &[Kind<'tcx>]) -> ty::Region<'tcx>, - FT: FnMut(&ty::GenericParamDef, &[Kind<'tcx>]) -> Ty<'tcx> { + /// substitute defaults of generic parameters. + pub fn for_item<F>(tcx: TyCtxt<'a, 'gcx, 'tcx>, + def_id: DefId, + mut mk_kind: F) + -> &'tcx Substs<'tcx> + where F: FnMut(&ty::GenericParamDef, &[Kind<'tcx>]) -> UnpackedKind<'tcx> + { let defs = tcx.generics_of(def_id); let mut substs = Vec::with_capacity(defs.count()); - Substs::fill_item(&mut substs, tcx, defs, &mut mk_region, &mut mk_type); + Substs::fill_item(&mut substs, tcx, defs, &mut mk_kind); tcx.intern_substs(&substs) } - pub fn extend_to<FR, FT>(&self, - tcx: TyCtxt<'a, 'gcx, 'tcx>, - def_id: DefId, - mut mk_region: FR, - mut mk_type: FT) - -> &'tcx Substs<'tcx> - where FR: FnMut(&ty::GenericParamDef, &[Kind<'tcx>]) -> ty::Region<'tcx>, - FT: FnMut(&ty::GenericParamDef, &[Kind<'tcx>]) -> Ty<'tcx> + pub fn extend_to<F>(&self, + tcx: TyCtxt<'a, 'gcx, 'tcx>, + def_id: DefId, + mut mk_kind: F) + -> &'tcx Substs<'tcx> + where F: FnMut(&ty::GenericParamDef, &[Kind<'tcx>]) -> UnpackedKind<'tcx> { let defs = tcx.generics_of(def_id); let mut result = Vec::with_capacity(defs.count()); result.extend(self[..].iter().cloned()); - Substs::fill_single(&mut result, defs, &mut mk_region, &mut mk_type); + Substs::fill_single(&mut result, defs, &mut mk_kind); tcx.intern_substs(&result) } - pub fn fill_item<FR, FT>(substs: &mut Vec<Kind<'tcx>>, + pub fn fill_item<F>(substs: &mut Vec<Kind<'tcx>>, tcx: TyCtxt<'a, 'gcx, 'tcx>, defs: &ty::Generics, - mk_region: &mut FR, - mk_type: &mut FT) - where FR: FnMut(&ty::GenericParamDef, &[Kind<'tcx>]) -> ty::Region<'tcx>, - FT: FnMut(&ty::GenericParamDef, &[Kind<'tcx>]) -> Ty<'tcx> { + mk_kind: &mut F) + where F: FnMut(&ty::GenericParamDef, &[Kind<'tcx>]) -> UnpackedKind<'tcx> + { if let Some(def_id) = defs.parent { let parent_defs = tcx.generics_of(def_id); - Substs::fill_item(substs, tcx, parent_defs, mk_region, mk_type); + Substs::fill_item(substs, tcx, parent_defs, mk_kind); } - Substs::fill_single(substs, defs, mk_region, mk_type) + Substs::fill_single(substs, defs, mk_kind) } - fn fill_single<FR, FT>(substs: &mut Vec<Kind<'tcx>>, + fn fill_single<F>(substs: &mut Vec<Kind<'tcx>>, defs: &ty::Generics, - mk_region: &mut FR, - mk_type: &mut FT) - where FR: FnMut(&ty::GenericParamDef, &[Kind<'tcx>]) -> ty::Region<'tcx>, - FT: FnMut(&ty::GenericParamDef, &[Kind<'tcx>]) -> Ty<'tcx> { + mk_kind: &mut F) + where F: FnMut(&ty::GenericParamDef, &[Kind<'tcx>]) -> UnpackedKind<'tcx> + { for param in &defs.params { - let kind = match param.kind { - ty::GenericParamDefKind::Lifetime => mk_region(param, substs).into(), - ty::GenericParamDefKind::Type(_) => mk_type(param, substs).into(), - }; + let kind = mk_kind(param, substs); assert_eq!(param.index as usize, substs.len()); - substs.push(kind); + substs.push(kind.pack()); } } diff --git a/src/librustc/ty/util.rs b/src/librustc/ty/util.rs index fdd0754730f..91280e5b8a3 100644 --- a/src/librustc/ty/util.rs +++ b/src/librustc/ty/util.rs @@ -17,9 +17,9 @@ use hir; use ich::NodeIdHashingMode; use middle::const_val::ConstVal; use traits::{self, ObligationCause}; -use ty::{self, Ty, TyCtxt, TypeFoldable}; +use ty::{self, Ty, TyCtxt, GenericParamDefKind, TypeFoldable}; use ty::fold::TypeVisitor; -use ty::subst::UnpackedKind; +use ty::subst::{Substs, UnpackedKind}; use ty::maps::TyCtxtAt; use ty::TypeVariants::*; use ty::layout::{Integer, IntegerExt}; @@ -573,11 +573,14 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, '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 ty::Substs<'tcx> { - ty::Substs::for_item(self, item_def_id, - |_, _| self.types.re_erased, - |_, _| { - bug!("empty_substs_for_def_id: {:?} has type parameters", item_def_id) + pub fn empty_substs_for_def_id(self, item_def_id: DefId) -> &'tcx Substs<'tcx> { + Substs::for_item(self, item_def_id, |param, _| { + match param.kind { + GenericParamDefKind::Lifetime => UnpackedKind::Lifetime(self.types.re_erased), + GenericParamDefKind::Type(_) => { + bug!("empty_substs_for_def_id: {:?} has type parameters", item_def_id) + } + } }) } diff --git a/src/librustc_mir/monomorphize/collector.rs b/src/librustc_mir/monomorphize/collector.rs index f8f6bec33a2..c8d4ccaf0bb 100644 --- a/src/librustc_mir/monomorphize/collector.rs +++ b/src/librustc_mir/monomorphize/collector.rs @@ -196,8 +196,8 @@ use rustc::hir::def_id::DefId; use rustc::middle::const_val::ConstVal; use rustc::mir::interpret::{AllocId, ConstValue}; use rustc::middle::lang_items::{ExchangeMallocFnLangItem, StartFnLangItem}; -use rustc::ty::subst::{Substs, Kind}; -use rustc::ty::{self, TypeFoldable, Ty, TyCtxt}; +use rustc::ty::subst::{Substs, Kind, UnpackedKind}; +use rustc::ty::{self, TypeFoldable, Ty, TyCtxt, GenericParamDefKind}; use rustc::ty::adjustment::CustomCoerceUnsized; use rustc::session::config; use rustc::mir::{self, Location, Promoted}; @@ -1112,10 +1112,16 @@ fn create_mono_items_for_default_impls<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, continue; } - let substs = Substs::for_item(tcx, - method.def_id, - |_, _| tcx.types.re_erased, - |def, _| trait_ref.substs.type_for_def(def)); + let substs = Substs::for_item(tcx, method.def_id, |param, _| { + match param.kind { + GenericParamDefKind::Lifetime => { + UnpackedKind::Lifetime(tcx.types.re_erased) + } + GenericParamDefKind::Type(_) => { + UnpackedKind::Type(trait_ref.substs.type_for_def(param)) + } + } + }); let instance = ty::Instance::resolve(tcx, ty::ParamEnv::reveal_all(), diff --git a/src/librustc_mir/shim.rs b/src/librustc_mir/shim.rs index 5b2f3a8b8aa..8596d546b09 100644 --- a/src/librustc_mir/shim.rs +++ b/src/librustc_mir/shim.rs @@ -12,8 +12,8 @@ use rustc::hir; use rustc::hir::def_id::DefId; use rustc::infer; use rustc::mir::*; -use rustc::ty::{self, Ty, TyCtxt}; -use rustc::ty::subst::{Kind, Subst, Substs}; +use rustc::ty::{self, Ty, TyCtxt, GenericParamDefKind}; +use rustc::ty::subst::{Kind, UnpackedKind, Subst, Substs}; use rustc::ty::maps::Providers; use rustc_data_structures::indexed_vec::{IndexVec, Idx}; @@ -427,12 +427,12 @@ impl<'a, 'tcx> CloneShimBuilder<'a, 'tcx> { ) { let tcx = self.tcx; - let substs = Substs::for_item( - tcx, - self.def_id, - |_, _| tcx.types.re_erased, - |_, _| ty - ); + let substs = Substs::for_item(tcx, self.def_id, |param, _| { + match param.kind { + GenericParamDefKind::Lifetime => UnpackedKind::Lifetime(tcx.types.re_erased), + GenericParamDefKind::Type(_) => UnpackedKind::Type(ty), + } + }); // `func == Clone::clone(&ty) -> ty` let func_ty = tcx.mk_fn_def(self.def_id, substs); diff --git a/src/librustc_typeck/astconv.rs b/src/librustc_typeck/astconv.rs index 12e1bfde224..f60c78702b6 100644 --- a/src/librustc_typeck/astconv.rs +++ b/src/librustc_typeck/astconv.rs @@ -20,7 +20,8 @@ use middle::resolve_lifetime as rl; use namespace::Namespace; use rustc::ty::subst::{Kind, UnpackedKind, Subst, Substs}; use rustc::traits; -use rustc::ty::{self, RegionKind, Ty, TyCtxt, GenericParamDefKind, ToPredicate, TypeFoldable}; +use rustc::ty::{self, RegionKind, Ty, TyCtxt, ToPredicate, TypeFoldable}; +use rustc::ty::GenericParamDefKind; use rustc::ty::wf::object_region_bounds; use rustc_target::spec::abi; use std::slice; @@ -264,66 +265,76 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o { }; let own_self = self_ty.is_some() as usize; - let substs = Substs::for_item(tcx, def_id, |def, _| { - let i = def.index as usize - own_self; - if let Some(lifetime) = parameters.lifetimes.get(i) { - self.ast_region_to_region(lifetime, Some(def)) - } else { - tcx.types.re_static - } - }, |def, substs| { - let i = def.index as usize; - - // Handle Self first, so we can adjust the index to match the AST. - if let (0, Some(ty)) = (i, self_ty) { - return ty; - } + let substs = Substs::for_item(tcx, def_id, |param, substs| { + match param.kind { + GenericParamDefKind::Lifetime => { + let i = param.index as usize - own_self; + let lt = if let Some(lifetime) = parameters.lifetimes.get(i) { + self.ast_region_to_region(lifetime, Some(param)) + } else { + tcx.types.re_static + }; + UnpackedKind::Lifetime(lt) + } + GenericParamDefKind::Type(_) => { + let i = param.index as usize; - let has_default = match def.kind { - GenericParamDefKind::Type(ty) => ty.has_default, - _ => unreachable!() - }; + // Handle Self first, so we can adjust the index to match the AST. + if let (0, Some(ty)) = (i, self_ty) { + return UnpackedKind::Type(ty); + } - let i = i - (lt_accepted + own_self); - if i < ty_provided { - // A provided type parameter. - self.ast_ty_to_ty(¶meters.types[i]) - } else if infer_types { - // No type parameters were provided, we can infer all. - let ty_var = if !default_needs_object_self(def) { - self.ty_infer_for_def(def, span) - } else { - self.ty_infer(span) - }; - ty_var - } else if has_default { - // No type parameter provided, but a default exists. - - // 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 default_needs_object_self(def) { - struct_span_err!(tcx.sess, span, E0393, - "the type parameter `{}` must be explicitly specified", - def.name) - .span_label(span, format!("missing reference to `{}`", def.name)) - .note(&format!("because of the default `Self` reference, \ - type parameters must be specified on object types")) - .emit(); - tcx.types.err - } else { - // This is a default type parameter. - self.normalize_ty( - span, - tcx.at(span).type_of(def.def_id) - .subst_spanned(tcx, substs, Some(span)) - ) + let has_default = match param.kind { + GenericParamDefKind::Type(ty) => ty.has_default, + _ => unreachable!() + }; + + let i = i - (lt_accepted + own_self); + let ty = if i < ty_provided { + // A provided type parameter. + self.ast_ty_to_ty(¶meters.types[i]) + } else if infer_types { + // No type parameters were provided, we can infer all. + let ty_var = if !default_needs_object_self(param) { + self.ty_infer_for_def(param, span) + } else { + self.ty_infer(span) + }; + ty_var + } else if has_default { + // No type parameter provided, but a default exists. + + // 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 default_needs_object_self(param) { + struct_span_err!(tcx.sess, span, E0393, + "the type parameter `{}` must be explicitly \ + specified", + param.name) + .span_label(span, + format!("missing reference to `{}`", param.name)) + .note(&format!("because of the default `Self` reference, \ + type parameters must be specified on object \ + types")) + .emit(); + tcx.types.err + } else { + // This is a default type parameter. + self.normalize_ty( + span, + tcx.at(span).type_of(param.def_id) + .subst_spanned(tcx, substs, Some(span)) + ) + } + } else { + // We've already errored above about the mismatch. + tcx.types.err + }; + UnpackedKind::Type(ty) } - } else { - // We've already errored above about the mismatch. - tcx.types.err } }); @@ -1154,12 +1165,17 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o { let mut substs = Vec::with_capacity(generics.count()); if let Some(parent_id) = generics.parent { let parent_generics = tcx.generics_of(parent_id); - Substs::fill_item( - &mut substs, tcx, parent_generics, - &mut |def, _| tcx.mk_region( - ty::ReEarlyBound(def.to_early_bound_region_data())), - &mut |def, _| tcx.mk_ty_param_from_def(def) - ); + Substs::fill_item(&mut substs, tcx, parent_generics, &mut |param, _| { + match param.kind { + GenericParamDefKind::Lifetime => { + UnpackedKind::Lifetime( + tcx.mk_region(ty::ReEarlyBound(param.to_early_bound_region_data()))) + } + GenericParamDefKind::Type(_) => { + UnpackedKind::Type(tcx.mk_ty_param_from_def(param)) + } + } + }); // Replace all lifetimes with 'static for subst in &mut substs { diff --git a/src/librustc_typeck/check/closure.rs b/src/librustc_typeck/check/closure.rs index 94ef040d80a..152f020c476 100644 --- a/src/librustc_typeck/check/closure.rs +++ b/src/librustc_typeck/check/closure.rs @@ -18,8 +18,8 @@ use rustc::infer::{InferOk, InferResult}; use rustc::infer::LateBoundRegionConversionTime; use rustc::infer::type_variable::TypeVariableOrigin; use rustc::traits::error_reporting::ArgKind; -use rustc::ty::{self, ToPolyTraitRef, Ty}; -use rustc::ty::subst::Substs; +use rustc::ty::{self, ToPolyTraitRef, Ty, GenericParamDefKind}; +use rustc::ty::subst::{UnpackedKind, Substs}; use rustc::ty::TypeFoldable; use std::cmp; use std::iter; @@ -104,15 +104,17 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { // inference phase (`upvar.rs`). let base_substs = Substs::identity_for_item(self.tcx, self.tcx.closure_base_def_id(expr_def_id)); - let substs = base_substs.extend_to( - self.tcx, - expr_def_id, - |_, _| span_bug!(expr.span, "closure has region param"), - |_, _| { - self.infcx - .next_ty_var(TypeVariableOrigin::ClosureSynthetic(expr.span)) - }, - ); + let substs = base_substs.extend_to(self.tcx,expr_def_id, |param, _| { + match param.kind { + GenericParamDefKind::Lifetime => { + span_bug!(expr.span, "closure has region param") + } + GenericParamDefKind::Type(_) => { + UnpackedKind::Type(self.infcx + .next_ty_var(TypeVariableOrigin::ClosureSynthetic(expr.span))) + } + } + }); if let Some(GeneratorTypes { yield_ty, interior, movability }) = generator_types { let substs = ty::GeneratorSubsts { substs }; self.demand_eqtype( diff --git a/src/librustc_typeck/check/method/confirm.rs b/src/librustc_typeck/check/method/confirm.rs index 9928ef549ff..c208e0fae64 100644 --- a/src/librustc_typeck/check/method/confirm.rs +++ b/src/librustc_typeck/check/method/confirm.rs @@ -15,8 +15,8 @@ use check::{FnCtxt, PlaceOp, callee, Needs}; use hir::def_id::DefId; use rustc::ty::subst::Substs; use rustc::traits; -use rustc::ty::{self, Ty}; -use rustc::ty::subst::Subst; +use rustc::ty::{self, Ty, GenericParamDefKind}; +use rustc::ty::subst::{UnpackedKind, Subst}; use rustc::ty::adjustment::{Adjustment, Adjust, OverloadedDeref}; use rustc::ty::adjustment::{AllowTwoPhase, AutoBorrow, AutoBorrowMutability}; use rustc::ty::fold::TypeFoldable; @@ -317,30 +317,37 @@ impl<'a, 'gcx, 'tcx> ConfirmContext<'a, 'gcx, 'tcx> { assert_eq!(method_generics.parent_count, parent_substs.len()); let provided = &segment.parameters; let own_counts = method_generics.own_counts(); - Substs::for_item(self.tcx, pick.item.def_id, |def, _| { - let i = def.index as usize; - if i < parent_substs.len() { - parent_substs.region_at(i) - } else if let Some(lifetime) - = provided.as_ref().and_then(|p| p.lifetimes.get(i - parent_substs.len())) { - AstConv::ast_region_to_region(self.fcx, lifetime, Some(def)) - } else { - self.region_var_for_def(self.span, def) - } - }, |def, _cur_substs| { - let i = def.index as usize; - if i < parent_substs.len() { - parent_substs.type_at(i) - } else if let Some(ast_ty) - = provided.as_ref().and_then(|p| { - let idx = - i - parent_substs.len() - own_counts.lifetimes; - p.types.get(idx) - }) - { - self.to_ty(ast_ty) - } else { - self.type_var_for_def(self.span, def) + Substs::for_item(self.tcx, pick.item.def_id, |param, _| { + match param.kind { + GenericParamDefKind::Lifetime => { + let i = param.index as usize; + let lt = if i < parent_substs.len() { + parent_substs.region_at(i) + } else if let Some(lifetime) + = provided.as_ref().and_then(|p| p.lifetimes.get(i - parent_substs.len())) { + AstConv::ast_region_to_region(self.fcx, lifetime, Some(param)) + } else { + self.region_var_for_def(self.span, param) + }; + UnpackedKind::Lifetime(lt) + } + GenericParamDefKind::Type(_) => { + let i = param.index as usize; + let ty = if i < parent_substs.len() { + parent_substs.type_at(i) + } else if let Some(ast_ty) + = provided.as_ref().and_then(|p| { + let idx = + i - parent_substs.len() - own_counts.lifetimes; + p.types.get(idx) + }) + { + self.to_ty(ast_ty) + } else { + self.type_var_for_def(self.span, param) + }; + UnpackedKind::Type(ty) + } } }) } diff --git a/src/librustc_typeck/check/method/mod.rs b/src/librustc_typeck/check/method/mod.rs index 83f132d8869..298b8548e36 100644 --- a/src/librustc_typeck/check/method/mod.rs +++ b/src/librustc_typeck/check/method/mod.rs @@ -19,7 +19,8 @@ use namespace::Namespace; use rustc::ty::subst::Substs; use rustc::traits; use rustc::ty::{self, Ty, ToPredicate, ToPolyTraitRef, TraitRef, TypeFoldable}; -use rustc::ty::subst::Subst; +use rustc::ty::GenericParamDefKind; +use rustc::ty::subst::{UnpackedKind, Subst}; use rustc::infer::{self, InferOk}; use syntax::ast; @@ -253,16 +254,21 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { trait_def_id); // Construct a trait-reference `self_ty : Trait<input_tys>` - let substs = Substs::for_item(self.tcx, - trait_def_id, - |def, _| self.region_var_for_def(span, def), - |def, _substs| { - if def.index == 0 { - self_ty - } else if let Some(ref input_types) = opt_input_types { - input_types[def.index as usize - 1] - } else { - self.type_var_for_def(span, def) + let substs = Substs::for_item(self.tcx, trait_def_id, |param, _| { + match param.kind { + GenericParamDefKind::Lifetime => { + UnpackedKind::Lifetime(self.region_var_for_def(span, param)) + } + GenericParamDefKind::Type(_) => { + let ty = if param.index == 0 { + self_ty + } else if let Some(ref input_types) = opt_input_types { + input_types[param.index as usize - 1] + } else { + self.type_var_for_def(span, param) + }; + UnpackedKind::Type(ty) + } } }); diff --git a/src/librustc_typeck/check/method/probe.rs b/src/librustc_typeck/check/method/probe.rs index 9d762ca3834..a96796bb148 100644 --- a/src/librustc_typeck/check/method/probe.rs +++ b/src/librustc_typeck/check/method/probe.rs @@ -17,9 +17,10 @@ use check::FnCtxt; use hir::def_id::DefId; use hir::def::Def; use namespace::Namespace; -use rustc::ty::subst::{Subst, Substs}; +use rustc::ty::subst::{UnpackedKind, Subst, Substs}; use rustc::traits::{self, ObligationCause}; use rustc::ty::{self, Ty, ToPolyTraitRef, ToPredicate, TraitRef, TypeFoldable}; +use rustc::ty::GenericParamDefKind; use rustc::infer::type_variable::TypeVariableOrigin; use rustc::util::nodemap::FxHashSet; use rustc::infer::{self, InferOk}; @@ -1387,21 +1388,28 @@ impl<'a, 'gcx, 'tcx> ProbeContext<'a, 'gcx, 'tcx> { if generics.params.is_empty() { xform_fn_sig.subst(self.tcx, substs) } else { - let substs = Substs::for_item(self.tcx, method, |def, _| { - let i = def.index as usize; - if i < substs.len() { - substs.region_at(i) - } else { - // In general, during probe we erase regions. See - // `impl_self_ty()` for an explanation. - self.tcx.types.re_erased - } - }, |def, _cur_substs| { - let i = def.index as usize; - if i < substs.len() { - substs.type_at(i) - } else { - self.type_var_for_def(self.span, def) + let substs = Substs::for_item(self.tcx, method, |param, _| { + match param.kind { + GenericParamDefKind::Lifetime => { + let i = param.index as usize; + let lt = if i < substs.len() { + substs.region_at(i) + } else { + // In general, during probe we erase regions. See + // `impl_self_ty()` for an explanation. + self.tcx.types.re_erased + }; + UnpackedKind::Lifetime(lt) + } + GenericParamDefKind::Type(_) => { + let i = param.index as usize; + let ty = if i < substs.len() { + substs.type_at(i) + } else { + self.type_var_for_def(self.span, param) + }; + UnpackedKind::Type(ty) + } } }); xform_fn_sig.subst(self.tcx, substs) @@ -1414,12 +1422,18 @@ impl<'a, 'gcx, 'tcx> ProbeContext<'a, 'gcx, 'tcx> { } fn fresh_item_substs(&self, def_id: DefId) -> &'tcx Substs<'tcx> { - Substs::for_item(self.tcx, - def_id, - |_, _| self.tcx.types.re_erased, - |_, _| self.next_ty_var( - TypeVariableOrigin::SubstitutionPlaceholder( - self.tcx.def_span(def_id)))) + Substs::for_item(self.tcx, def_id, |param, _| { + match param.kind { + GenericParamDefKind::Lifetime => { + UnpackedKind::Lifetime(self.tcx.types.re_erased) + } + GenericParamDefKind::Type(_) => { + UnpackedKind::Type(self.next_ty_var( + TypeVariableOrigin::SubstitutionPlaceholder( + self.tcx.def_span(def_id)))) + } + } + }) } /// 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 7e33bf9722f..99e47f92daf 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -94,7 +94,7 @@ use rustc::infer::anon_types::AnonTypeDecl; use rustc::infer::type_variable::{TypeVariableOrigin}; use rustc::middle::region; use rustc::mir::interpret::{GlobalId}; -use rustc::ty::subst::{Kind, Subst, Substs}; +use rustc::ty::subst::{Kind, UnpackedKind, Subst, Substs}; use rustc::traits::{self, ObligationCause, ObligationCauseCode, TraitEngine}; use rustc::ty::{self, Ty, TyCtxt, GenericParamDefKind, Visibility, ToPredicate}; use rustc::ty::adjustment::{Adjust, Adjustment, AllowTwoPhase, AutoBorrow, AutoBorrowMutability}; @@ -4758,71 +4758,78 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { } (None, None) => (0, false) }; - let substs = Substs::for_item(self.tcx, def.def_id(), |def, _| { - let mut i = def.index as usize; - - let segment = if i < fn_start { - i -= has_self as usize; - type_segment - } else { - i -= fn_start; - fn_segment - }; - let lifetimes = segment.map_or(&[][..], |(s, _)| { - s.parameters.as_ref().map_or(&[][..], |p| &p.lifetimes[..]) - }); - - if let Some(lifetime) = lifetimes.get(i) { - AstConv::ast_region_to_region(self, lifetime, Some(def)) - } else { - self.re_infer(span, Some(def)).unwrap() - } - }, |def, substs| { - let mut i = def.index as usize; - - let segment = if i < fn_start { - // 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) + let substs = Substs::for_item(self.tcx, def.def_id(), |param, substs| { + match param.kind { + GenericParamDefKind::Lifetime => { + let mut i = param.index as usize; + + let segment = if i < fn_start { + i -= has_self as usize; + type_segment + } else { + i -= fn_start; + fn_segment + }; + let lifetimes = segment.map_or(&[][..], |(s, _)| { + s.parameters.as_ref().map_or(&[][..], |p| &p.lifetimes[..]) }); + + let lt = if let Some(lifetime) = lifetimes.get(i) { + AstConv::ast_region_to_region(self, lifetime, Some(param)) + } else { + self.re_infer(span, Some(param)).unwrap() + }; + UnpackedKind::Lifetime(lt) } - i -= has_self as usize; - type_segment - } else { - i -= fn_start; - fn_segment - }; - let (types, infer_types) = segment.map_or((&[][..], true), |(s, _)| { - (s.parameters.as_ref().map_or(&[][..], |p| &p.types[..]), s.infer_types) - }); + GenericParamDefKind::Type(_) => { + let mut i = param.index as usize; + + let segment = if i < fn_start { + // Handle Self first, so we can adjust the index to match the AST. + if has_self && i == 0 { + return UnpackedKind::Type(opt_self_ty.unwrap_or_else(|| { + self.type_var_for_def(span, param) + })); + } + i -= has_self as usize; + type_segment + } else { + i -= fn_start; + fn_segment + }; + let (types, infer_types) = segment.map_or((&[][..], true), |(s, _)| { + (s.parameters.as_ref().map_or(&[][..], |p| &p.types[..]), s.infer_types) + }); - // Skip over the lifetimes in the same segment. - if let Some((_, generics)) = segment { - i -= generics.own_counts().lifetimes; - } + // Skip over the lifetimes in the same segment. + if let Some((_, generics)) = segment { + i -= generics.own_counts().lifetimes; + } - let has_default = match def.kind { - GenericParamDefKind::Type(ty) => ty.has_default, - _ => unreachable!() - }; + let has_default = match param.kind { + GenericParamDefKind::Type(ty) => ty.has_default, + _ => unreachable!() + }; - if let Some(ast_ty) = types.get(i) { - // A provided type parameter. - self.to_ty(ast_ty) - } else if !infer_types && has_default { - // No type parameter provided, but a default exists. - let default = self.tcx.type_of(def.def_id); - self.normalize_ty( - span, - 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) + let ty = if let Some(ast_ty) = types.get(i) { + // A provided type parameter. + self.to_ty(ast_ty) + } else if !infer_types && has_default { + // No type parameter provided, but a default exists. + let default = self.tcx.type_of(param.def_id); + self.normalize_ty( + span, + 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, param) + }; + UnpackedKind::Type(ty) + } } }); diff --git a/src/librustc_typeck/check/wfcheck.rs b/src/librustc_typeck/check/wfcheck.rs index a37137c68cb..5c6a78de313 100644 --- a/src/librustc_typeck/check/wfcheck.rs +++ b/src/librustc_typeck/check/wfcheck.rs @@ -11,11 +11,10 @@ use check::{Inherited, FnCtxt}; use constrained_type_params::{identify_constrained_type_params, Parameter}; -use ty::GenericParamDefKind; - use hir::def_id::DefId; use rustc::traits::{self, ObligationCauseCode}; -use rustc::ty::{self, Lift, Ty, TyCtxt}; +use rustc::ty::{self, Lift, Ty, TyCtxt, GenericParamDefKind}; +use rustc::ty::subst::{UnpackedKind, Substs}; use rustc::ty::util::ExplicitSelf; use rustc::util::nodemap::{FxHashSet, FxHashMap}; use rustc::middle::lang_items; @@ -406,22 +405,28 @@ fn check_where_clauses<'a, 'gcx, 'fcx, 'tcx>(tcx: TyCtxt<'a, 'gcx, 'gcx>, // For more examples see tests `defaults-well-formedness.rs` and `type-check-defaults.rs`. // // First we build the defaulted substitution. - let substs = ty::subst::Substs::for_item(fcx.tcx, def_id, |def, _| { - // All regions are identity. - fcx.tcx.mk_region(ty::ReEarlyBound(def.to_early_bound_region_data())) - }, |def, _| { - // If the param has a default, - if is_our_default(def) { - let default_ty = fcx.tcx.type_of(def.def_id); - // and it's not a dependent default - if !default_ty.needs_subst() { - // then substitute with the default. - return default_ty; + let substs = Substs::for_item(fcx.tcx, def_id, |param, _| { + match param.kind { + GenericParamDefKind::Lifetime => { + // All regions are identity. + UnpackedKind::Lifetime( + fcx.tcx.mk_region(ty::ReEarlyBound(param.to_early_bound_region_data()))) + } + GenericParamDefKind::Type(_) => { + // If the param has a default, + if is_our_default(param) { + let default_ty = fcx.tcx.type_of(param.def_id); + // and it's not a dependent default + if !default_ty.needs_subst() { + // then substitute with the default. + return UnpackedKind::Type(default_ty); + } } + // Mark unwanted params as err. + UnpackedKind::Type(fcx.tcx.types.err) } - // Mark unwanted params as err. - fcx.tcx.types.err - }); + } + }); // Now we build the substituted predicates. for &pred in predicates.predicates.iter() { struct CountParams { params: FxHashSet<u32> } diff --git a/src/librustc_typeck/collect.rs b/src/librustc_typeck/collect.rs index d4f9fb948fe..1a2480bf45e 100644 --- a/src/librustc_typeck/collect.rs +++ b/src/librustc_typeck/collect.rs @@ -30,7 +30,8 @@ use constrained_type_params as ctp; use middle::lang_items::SizedTraitLangItem; use middle::resolve_lifetime as rl; use rustc::mir::mono::Linkage; -use rustc::ty::subst::Substs; +use rustc::ty::subst::{UnpackedKind, Substs}; +use rustc::ty::GenericParamDefKind; use rustc::ty::{ToPredicate, ReprOptions}; use rustc::ty::{self, AdtKind, ToPolyTraitRef, Ty, TyCtxt}; use rustc::ty::maps::Providers; @@ -1096,15 +1097,17 @@ fn type_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, } let substs = ty::ClosureSubsts { - substs: Substs::for_item( - tcx, - def_id, - |def, _| { - let region = def.to_early_bound_region_data(); - tcx.mk_region(ty::ReEarlyBound(region)) - }, - |def, _| tcx.mk_ty_param_from_def(def) - ) + substs: Substs::for_item(tcx, def_id, |param, _| { + match param.kind { + GenericParamDefKind::Lifetime => { + let region = param.to_early_bound_region_data(); + UnpackedKind::Lifetime(tcx.mk_region(ty::ReEarlyBound(region))) + } + GenericParamDefKind::Type(_) => { + UnpackedKind::Type(tcx.mk_ty_param_from_def(param)) + } + } + }) }; tcx.mk_closure(def_id, substs) |
