From 3ae2468261dca097ecfa81a74654fed32b60f8ce Mon Sep 17 00:00:00 2001 From: varkor Date: Mon, 14 May 2018 19:57:59 +0100 Subject: [PATCH] Clean up shared subst code --- src/librustc/infer/mod.rs | 63 +++++++++------------ src/librustc/ty/context.rs | 12 +--- src/librustc_typeck/astconv.rs | 14 ++--- src/librustc_typeck/check/method/confirm.rs | 50 +++++++--------- src/librustc_typeck/check/method/mod.rs | 16 ++---- src/librustc_typeck/check/method/probe.rs | 27 +++------ src/librustc_typeck/check/mod.rs | 61 ++++++++++---------- 7 files changed, 100 insertions(+), 143 deletions(-) diff --git a/src/librustc/infer/mod.rs b/src/librustc/infer/mod.rs index d90ba51fffc2..7a1e255dc5d0 100644 --- a/src/librustc/infer/mod.rs +++ b/src/librustc/infer/mod.rs @@ -905,34 +905,34 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { self.next_region_var(RegionVariableOrigin::NLL(origin)) } - /// Create a region inference variable for the given - /// region parameter definition. - pub fn region_var_for_def(&self, - span: Span, - def: &ty::GenericParamDef) - -> ty::Region<'tcx> { - self.next_region_var(EarlyBoundRegion(span, def.name)) - } + pub fn var_for_def(&self, + span: Span, + param: &ty::GenericParamDef) + -> UnpackedKind<'tcx> { + match param.kind { + GenericParamDefKind::Lifetime => { + // Create a region inference variable for the given + // region parameter definition. + UnpackedKind::Lifetime(self.next_region_var(EarlyBoundRegion(span, param.name))) + } + GenericParamDefKind::Type(_) => { + // 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)`. + let ty_var_id = self.type_variables + .borrow_mut() + .new_var(self.universe(), + false, + TypeVariableOrigin::TypeParameterDefinition(span, param.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::GenericParamDef) - -> Ty<'tcx> { - let ty_var_id = self.type_variables - .borrow_mut() - .new_var(self.universe(), - false, - TypeVariableOrigin::TypeParameterDefinition(span, def.name)); - - self.tcx.mk_var(ty_var_id) + UnpackedKind::Type(self.tcx.mk_var(ty_var_id)) + } + } } /// Given a set of generics defined on a type or impl, returns a substitution mapping each @@ -942,14 +942,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { def_id: DefId) -> &'tcx Substs<'tcx> { 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)) - } - } + self.var_for_def(span, param) }) } diff --git a/src/librustc/ty/context.rs b/src/librustc/ty/context.rs index 924271ea3d47..66c451e81931 100644 --- a/src/librustc/ty/context.rs +++ b/src/librustc/ty/context.rs @@ -2329,18 +2329,12 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { let substs = Substs::for_item(self, def_id, |param, substs| { match param.kind { GenericParamDefKind::Lifetime => bug!(), - GenericParamDefKind::Type(_) => { + GenericParamDefKind::Type(ty_param) => { 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!() - } + assert!(ty_param.has_default); + UnpackedKind::Type(self.type_of(param.def_id).subst(self, substs)) } } } diff --git a/src/librustc_typeck/astconv.rs b/src/librustc_typeck/astconv.rs index f60c78702b6f..32ea9938ff55 100644 --- a/src/librustc_typeck/astconv.rs +++ b/src/librustc_typeck/astconv.rs @@ -276,7 +276,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o { }; UnpackedKind::Lifetime(lt) } - GenericParamDefKind::Type(_) => { + GenericParamDefKind::Type(ty) => { let i = param.index as usize; // Handle Self first, so we can adjust the index to match the AST. @@ -284,24 +284,18 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o { return UnpackedKind::Type(ty); } - 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) { + if !default_needs_object_self(param) { self.ty_infer_for_def(param, span) } else { self.ty_infer(span) - }; - ty_var - } else if has_default { + } + } else if ty.has_default { // No type parameter provided, but a default exists. // If we are converting an object type, then the diff --git a/src/librustc_typeck/check/method/confirm.rs b/src/librustc_typeck/check/method/confirm.rs index c208e0fae642..e2b4380fda2a 100644 --- a/src/librustc_typeck/check/method/confirm.rs +++ b/src/librustc_typeck/check/method/confirm.rs @@ -318,36 +318,28 @@ impl<'a, 'gcx, 'tcx> ConfirmContext<'a, 'gcx, 'tcx> { let provided = &segment.parameters; let own_counts = method_generics.own_counts(); 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) + let i = param.index as usize; + if i < parent_substs.len() { + parent_substs[i].unpack() + } else { + match param.kind { + GenericParamDefKind::Lifetime => { + if let Some(lifetime) = provided.as_ref().and_then(|p| { + p.lifetimes.get(i - parent_substs.len()) + }) { + return UnpackedKind::Lifetime( + AstConv::ast_region_to_region(self.fcx, lifetime, Some(param))); + } + } + GenericParamDefKind::Type(_) => { + if let Some(ast_ty) = provided.as_ref().and_then(|p| { + p.types.get(i - parent_substs.len() - own_counts.lifetimes) + }) { + return UnpackedKind::Type(self.to_ty(ast_ty)); + } + } } + self.var_for_def(self.span, param) } }) } diff --git a/src/librustc_typeck/check/method/mod.rs b/src/librustc_typeck/check/method/mod.rs index 298b8548e36e..f02f70caef9b 100644 --- a/src/librustc_typeck/check/method/mod.rs +++ b/src/librustc_typeck/check/method/mod.rs @@ -256,20 +256,16 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { // Construct a trait-reference `self_ty : Trait` 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::Lifetime => {} GenericParamDefKind::Type(_) => { - let ty = if param.index == 0 { - self_ty + if param.index == 0 { + return UnpackedKind::Type(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) + return UnpackedKind::Type(input_types[param.index as usize - 1]); + } } } + self.var_for_def(span, param) }); let trait_ref = ty::TraitRef::new(trait_def_id, substs); diff --git a/src/librustc_typeck/check/method/probe.rs b/src/librustc_typeck/check/method/probe.rs index a96796bb148c..54fea4ab00a6 100644 --- a/src/librustc_typeck/check/method/probe.rs +++ b/src/librustc_typeck/check/method/probe.rs @@ -1389,26 +1389,17 @@ impl<'a, 'gcx, 'tcx> ProbeContext<'a, 'gcx, 'tcx> { xform_fn_sig.subst(self.tcx, substs) } else { 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 { + let i = param.index as usize; + if i < substs.len() { + substs[i].unpack() + } else { + match param.kind { + GenericParamDefKind::Lifetime => { // 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) + UnpackedKind::Lifetime(self.tcx.types.re_erased) + } + GenericParamDefKind::Type(_) => self.var_for_def(self.span, param), } } }); diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index 99e47f92daf0..0b0659729ef8 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -1746,7 +1746,11 @@ impl<'a, 'gcx, 'tcx> AstConv<'gcx, 'tcx> for FnCtxt<'a, 'gcx, 'tcx> { fn ty_infer_for_def(&self, ty_param_def: &ty::GenericParamDef, span: Span) -> Ty<'tcx> { - self.type_var_for_def(span, ty_param_def) + if let UnpackedKind::Type(ty) = self.var_for_def(span, ty_param_def) { + ty + } else { + unreachable!() + } } fn projected_ty_from_poly_trait_ref(&self, @@ -4759,17 +4763,26 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { (None, None) => (0, false) }; let substs = Substs::for_item(self.tcx, def.def_id(), |param, substs| { + let mut i = param.index as usize; + + let segment = if i < fn_start { + if let GenericParamDefKind::Type(_) = param.kind { + // Handle Self first, so we can adjust the index to match the AST. + if has_self && i == 0 { + return opt_self_ty.map(|ty| UnpackedKind::Type(ty)).unwrap_or_else(|| { + self.var_for_def(span, param) + }); + } + } + i -= has_self as usize; + type_segment + } else { + i -= fn_start; + fn_segment + }; + 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[..]) }); @@ -4782,21 +4795,6 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { UnpackedKind::Lifetime(lt) } 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) }); @@ -4811,24 +4809,23 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { _ => unreachable!() }; - let ty = 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) + UnpackedKind::Type(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( + UnpackedKind::Type(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) + self.var_for_def(span, param) + } } } });