]> git.lizzy.rs Git - rust.git/commitdiff
fix broken type parameter indexing logic in wfcheck
authorAriel Ben-Yehuda <ariel.byd@gmail.com>
Mon, 29 Aug 2016 21:03:29 +0000 (00:03 +0300)
committerAriel Ben-Yehuda <ariel.byd@gmail.com>
Tue, 30 Aug 2016 18:27:03 +0000 (21:27 +0300)
Fixes #36075

src/librustc/ty/mod.rs
src/librustc_typeck/check/wfcheck.rs
src/librustc_typeck/collect.rs
src/librustc_typeck/constrained_type_params.rs
src/test/run-pass/issue-36075.rs [new file with mode: 0644]

index 759dc30037210166b0729595a1123786a68e2b21..4b2af26bb8d99fd516272158f45fe276442e6166 100644 (file)
@@ -717,11 +717,16 @@ pub struct RegionParameterDef<'tcx> {
 
 impl<'tcx> RegionParameterDef<'tcx> {
     pub fn to_early_bound_region(&self) -> ty::Region {
-        ty::ReEarlyBound(ty::EarlyBoundRegion {
+        ty::ReEarlyBound(self.to_early_bound_region_data())
+    }
+
+    pub fn to_early_bound_region_data(&self) -> ty::EarlyBoundRegion {
+        ty::EarlyBoundRegion {
             index: self.index,
             name: self.name,
-        })
+        }
     }
+
     pub fn to_bound_region(&self) -> ty::BoundRegion {
         // this is an early bound region, so unaffected by #32330
         ty::BoundRegion::BrNamed(self.def_id, self.name, Issue32330::WontChange)
index 6b6a688bf1d18779e31057a9835d2e09baa1496a..e90b0ad32c9a28470689e8bb9f9356a7d3d1b1f3 100644 (file)
@@ -457,44 +457,31 @@ fn check_variances_for_type_defn(&self,
         let variances = self.tcx().item_variances(item_def_id);
 
         let mut constrained_parameters: FnvHashSet<_> =
-            variances[ast_generics.lifetimes.len()..]
-                     .iter().enumerate()
+            variances.iter().enumerate()
                      .filter(|&(_, &variance)| variance != ty::Bivariant)
-                     .map(|(index, _)| self.param_ty(ast_generics, index))
-                     .map(|p| Parameter::Type(p))
+                     .map(|(index, _)| Parameter(index as u32))
                      .collect();
 
         identify_constrained_type_params(ty_predicates.predicates.as_slice(),
                                          None,
                                          &mut constrained_parameters);
 
-        for (index, &variance) in variances.iter().enumerate() {
-            let (span, name) = if index < ast_generics.lifetimes.len() {
-                if variance != ty::Bivariant {
-                    continue;
-                }
+        for (index, _) in variances.iter().enumerate() {
+            if constrained_parameters.contains(&Parameter(index as u32)) {
+                continue;
+            }
 
+            let (span, name) = if index < ast_generics.lifetimes.len() {
                 (ast_generics.lifetimes[index].lifetime.span,
                  ast_generics.lifetimes[index].lifetime.name)
             } else {
-                let index = index - ast_generics.lifetimes.len();
-                let param_ty = self.param_ty(ast_generics, index);
-                if constrained_parameters.contains(&Parameter::Type(param_ty)) {
-                    continue;
-                }
-                (ast_generics.ty_params[index].span, param_ty.name)
+                (ast_generics.ty_params[index].span,
+                 ast_generics.ty_params[index].name)
             };
             self.report_bivariance(span, name);
         }
     }
 
-    fn param_ty(&self, ast_generics: &hir::Generics, index: usize) -> ty::ParamTy {
-        ty::ParamTy {
-            idx: index as u32,
-            name: ast_generics.ty_params[index].name
-        }
-    }
-
     fn report_bivariance(&self,
                          span: Span,
                          param_name: ast::Name)
index 30b9d15587069e704361635dfe35175a59410cd1..0097991210d830638ed6f9ed5daf550f6e8f37f3 100644 (file)
@@ -2158,7 +2158,7 @@ fn enforce_impl_params_are_constrained<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
     let ty_generics = generics_of_def_id(ccx, impl_def_id);
     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)) {
+        if !input_parameters.contains(&ctp::Parameter::from(param_ty)) {
             report_unused_parameter(ccx, param.span, "type", &param_ty.to_string());
         }
     }
@@ -2189,23 +2189,19 @@ fn enforce_impl_lifetimes_are_constrained<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
             ty::ConstTraitItem(..) | ty::MethodTraitItem(..) => None
         })
         .flat_map(|ty| ctp::parameters_for(&ty, true))
-        .filter_map(|p| match p {
-            ctp::Parameter::Type(_) => None,
-            ctp::Parameter::Region(r) => Some(r),
-        })
         .collect();
 
-    for (index, lifetime_def) in ast_generics.lifetimes.iter().enumerate() {
-        let region = ty::EarlyBoundRegion {
-            index: index as u32,
-            name: lifetime_def.lifetime.name
-        };
+    for (ty_lifetime, lifetime) in impl_scheme.generics.regions.iter()
+        .zip(&ast_generics.lifetimes)
+    {
+        let param = ctp::Parameter::from(ty_lifetime.to_early_bound_region_data());
+
         if
-            lifetimes_in_associated_types.contains(&region) && // (*)
-            !input_parameters.contains(&ctp::Parameter::Region(region))
+            lifetimes_in_associated_types.contains(&param) && // (*)
+            !input_parameters.contains(&param)
         {
-            report_unused_parameter(ccx, lifetime_def.lifetime.span,
-                                    "lifetime", &region.name.to_string());
+            report_unused_parameter(ccx, lifetime.lifetime.span,
+                                    "lifetime", &lifetime.lifetime.name.to_string());
         }
     }
 
index 9e5c3a5d575bff6988c30b44ee6b1a0aaea11717..39f9e4316b9c7c150668e9c72f44699359e6ce79 100644 (file)
 use rustc::util::nodemap::FnvHashSet;
 
 #[derive(Clone, PartialEq, Eq, Hash, Debug)]
-pub enum Parameter {
-    Type(ty::ParamTy),
-    Region(ty::EarlyBoundRegion),
+pub struct Parameter(pub u32);
+
+impl From<ty::ParamTy> for Parameter {
+    fn from(param: ty::ParamTy) -> Self { Parameter(param.idx) }
+}
+
+impl From<ty::EarlyBoundRegion> for Parameter {
+    fn from(param: ty::EarlyBoundRegion) -> Self { Parameter(param.index) }
 }
 
 /// If `include_projections` is false, returns the list of parameters that are
@@ -49,8 +54,8 @@ fn visit_ty(&mut self, t: Ty<'tcx>) -> bool {
                 // projections are not injective
                 return false;
             }
-            ty::TyParam(ref d) => {
-                self.parameters.push(Parameter::Type(d.clone()));
+            ty::TyParam(data) => {
+                self.parameters.push(Parameter::from(data));
             }
             _ => {}
         }
@@ -61,7 +66,7 @@ fn visit_ty(&mut self, t: Ty<'tcx>) -> bool {
     fn visit_region(&mut self, r: &'tcx ty::Region) -> bool {
         match *r {
             ty::ReEarlyBound(data) => {
-                self.parameters.push(Parameter::Region(data));
+                self.parameters.push(Parameter::from(data));
             }
             _ => {}
         }
@@ -141,13 +146,15 @@ pub fn setup_constraining_predicates<'tcx>(predicates: &mut [ty::Predicate<'tcx>
     //   * <U as Iterator>::Item = T
     //   * T: Debug
     //   * U: Iterator
+    debug!("setup_constraining_predicates: predicates={:?} \
+            impl_trait_ref={:?} input_parameters={:?}",
+           predicates, impl_trait_ref, input_parameters);
     let mut i = 0;
     let mut changed = true;
     while changed {
         changed = false;
 
         for j in i..predicates.len() {
-
             if let ty::Predicate::Projection(ref poly_projection) = predicates[j] {
                 // Note that we can skip binder here because the impl
                 // trait ref never contains any late-bound regions.
@@ -181,5 +188,8 @@ pub fn setup_constraining_predicates<'tcx>(predicates: &mut [ty::Predicate<'tcx>
             i += 1;
             changed = true;
         }
+        debug!("setup_constraining_predicates: predicates={:?} \
+                i={} impl_trait_ref={:?} input_parameters={:?}",
+           predicates, i, impl_trait_ref, input_parameters);
     }
 }
diff --git a/src/test/run-pass/issue-36075.rs b/src/test/run-pass/issue-36075.rs
new file mode 100644 (file)
index 0000000..fe399e1
--- /dev/null
@@ -0,0 +1,22 @@
+// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+trait DeclarationParser {
+    type Declaration;
+}
+
+struct DeclarationListParser<'i, I, P>
+    where P: DeclarationParser<Declaration = I>
+{
+    input: &'i (),
+    parser: P
+}
+
+fn main() {}