diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs index 759dc30037210..4b2af26bb8d99 100644 --- a/src/librustc/ty/mod.rs +++ b/src/librustc/ty/mod.rs @@ -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) diff --git a/src/librustc_typeck/check/wfcheck.rs b/src/librustc_typeck/check/wfcheck.rs index 6b6a688bf1d18..e90b0ad32c9a2 100644 --- a/src/librustc_typeck/check/wfcheck.rs +++ b/src/librustc_typeck/check/wfcheck.rs @@ -457,44 +457,31 @@ impl<'ccx, 'gcx> CheckTypeWellFormedVisitor<'ccx, 'gcx> { 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) diff --git a/src/librustc_typeck/collect.rs b/src/librustc_typeck/collect.rs index 30b9d15587069..0097991210d83 100644 --- a/src/librustc_typeck/collect.rs +++ b/src/librustc_typeck/collect.rs @@ -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", ¶m_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(®ion) && // (*) - !input_parameters.contains(&ctp::Parameter::Region(region)) + lifetimes_in_associated_types.contains(¶m) && // (*) + !input_parameters.contains(¶m) { - report_unused_parameter(ccx, lifetime_def.lifetime.span, - "lifetime", ®ion.name.to_string()); + report_unused_parameter(ccx, lifetime.lifetime.span, + "lifetime", &lifetime.lifetime.name.to_string()); } } diff --git a/src/librustc_typeck/constrained_type_params.rs b/src/librustc_typeck/constrained_type_params.rs index 9e5c3a5d575bf..39f9e4316b9c7 100644 --- a/src/librustc_typeck/constrained_type_params.rs +++ b/src/librustc_typeck/constrained_type_params.rs @@ -13,9 +13,14 @@ use rustc::ty::fold::{TypeFoldable, TypeVisitor}; 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 for Parameter { + fn from(param: ty::ParamTy) -> Self { Parameter(param.idx) } +} + +impl From 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 @@ impl<'tcx> TypeVisitor<'tcx> for ParameterCollector { // 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 @@ impl<'tcx> TypeVisitor<'tcx> for ParameterCollector { 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> // * ::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 index 0000000000000..fe399e10c1c3f --- /dev/null +++ b/src/test/run-pass/issue-36075.rs @@ -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 or the MIT license +// , 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 +{ + input: &'i (), + parser: P +} + +fn main() {}