From a65a9d77f3c4e0a573f9c43b51f9076e96201edc Mon Sep 17 00:00:00 2001 From: varkor Date: Fri, 15 Jun 2018 10:51:44 +0100 Subject: [PATCH] Fix accidental quadratic loops --- src/librustc_typeck/astconv.rs | 41 +++++++++------------- src/librustc_typeck/check/mod.rs | 59 +++++++++++++++++++------------- 2 files changed, 52 insertions(+), 48 deletions(-) diff --git a/src/librustc_typeck/astconv.rs b/src/librustc_typeck/astconv.rs index 48c5353a400..d0cd1cf61ff 100644 --- a/src/librustc_typeck/astconv.rs +++ b/src/librustc_typeck/astconv.rs @@ -271,22 +271,24 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o { }; let own_self = self_ty.is_some() as usize; + // FIXME(varkor): Separating out the parameters is messy. + let lifetimes: Vec<_> = generic_args.args.iter().filter_map(|arg| match arg { + GenericArg::Lifetime(lt) => Some(lt), + _ => None, + }).collect(); + let types: Vec<_> = generic_args.args.iter().filter_map(|arg| match arg { + GenericArg::Type(ty) => Some(ty), + _ => None, + }).collect(); let substs = Substs::for_item(tcx, def_id, |param, substs| { match param.kind { GenericParamDefKind::Lifetime => { - let mut i = param.index as usize - own_self; - for arg in &generic_args.args { - match arg { - GenericArg::Lifetime(lt) => { - if i == 0 { - return self.ast_region_to_region(lt, Some(param)).into(); - } - i -= 1; - } - _ => {} - } + let i = param.index as usize - own_self; + if let Some(lt) = lifetimes.get(i) { + self.ast_region_to_region(lt, Some(param)).into() + } else { + tcx.types.re_static.into() } - tcx.types.re_static.into() } GenericParamDefKind::Type { has_default, .. } => { let i = param.index as usize; @@ -296,21 +298,10 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o { return ty.into(); } - let mut i = i - (lt_accepted + own_self); + let i = i - (lt_accepted + own_self); if i < ty_provided { // A provided type parameter. - for arg in &generic_args.args { - match arg { - GenericArg::Type(ty) => { - if i == 0 { - return self.ast_ty_to_ty(ty).into(); - } - i -= 1; - } - _ => {} - } - } - bug!() + self.ast_ty_to_ty(&types[i]).into() } else if infer_types { // No type parameters were provided, we can infer all. if !default_needs_object_self(param) { diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index bececfc08ac..93739fbada2 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -4813,11 +4813,42 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { } (None, None) => (0, false) }; + // FIXME(varkor): Separating out the parameters is messy. + let mut lifetimes_type_seg = vec![]; + let mut types_type_seg = vec![]; + let mut infer_types_type_seg = true; + if let Some((seg, _)) = type_segment { + if let Some(ref data) = seg.args { + for arg in &data.args { + match arg { + GenericArg::Lifetime(lt) => lifetimes_type_seg.push(lt), + GenericArg::Type(ty) => types_type_seg.push(ty), + } + } + } + infer_types_type_seg = seg.infer_types; + } + + let mut lifetimes_fn_seg = vec![]; + let mut types_fn_seg = vec![]; + let mut infer_types_fn_seg = true; + if let Some((seg, _)) = fn_segment { + if let Some(ref data) = seg.args { + for arg in &data.args { + match arg { + GenericArg::Lifetime(lt) => lifetimes_fn_seg.push(lt), + GenericArg::Type(ty) => types_fn_seg.push(ty), + } + } + } + infer_types_fn_seg = seg.infer_types; + } + 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 { + let (segment, lifetimes, types, infer_types) = 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| ty.into()).unwrap_or_else(|| { @@ -4826,39 +4857,21 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { } } i -= has_self as usize; - type_segment + (type_segment, &lifetimes_type_seg, &types_type_seg, infer_types_type_seg) } else { i -= fn_start; - fn_segment + (fn_segment, &lifetimes_fn_seg, &types_fn_seg, infer_types_fn_seg) }; match param.kind { GenericParamDefKind::Lifetime => { - let lifetimes = segment.map_or(vec![], |(s, _)| { - s.args.as_ref().map_or(vec![], |data| { - data.args.iter().filter_map(|arg| match arg { - GenericArg::Lifetime(lt) => Some(lt), - _ => None, - }).collect() - }) - }); - if let Some(lifetime) = lifetimes.get(i) { AstConv::ast_region_to_region(self, lifetime, Some(param)).into() } else { self.re_infer(span, Some(param)).unwrap().into() } } - GenericParamDefKind::Type {..} => { - let (types, infer_types) = segment.map_or((vec![], true), |(s, _)| { - (s.args.as_ref().map_or(vec![], |data| { - data.args.iter().filter_map(|arg| match arg { - GenericArg::Type(ty) => Some(ty), - _ => None, - }).collect() - }), s.infer_types) - }); - + GenericParamDefKind::Type { .. } => { // Skip over the lifetimes in the same segment. if let Some((_, generics)) = segment { i -= generics.own_counts().lifetimes;