]> git.lizzy.rs Git - rust.git/blob - src/librustc_typeck/constrained_type_params.rs
Auto merge of #22541 - Manishearth:rollup, r=Gankro
[rust.git] / src / librustc_typeck / constrained_type_params.rs
1 // Copyright 2015 The Rust Project Developers. See the COPYRIGHT
2 // file at the top-level directory of this distribution and at
3 // http://rust-lang.org/COPYRIGHT.
4 //
5 // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6 // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7 // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8 // option. This file may not be copied, modified, or distributed
9 // except according to those terms.
10
11 use middle::ty::{self};
12
13 use std::collections::HashSet;
14 use std::rc::Rc;
15
16 pub fn identify_constrained_type_params<'tcx>(_tcx: &ty::ctxt<'tcx>,
17                                               predicates: &[ty::Predicate<'tcx>],
18                                               impl_trait_ref: Option<Rc<ty::TraitRef<'tcx>>>,
19                                               input_parameters: &mut HashSet<ty::ParamTy>)
20 {
21     loop {
22         let num_inputs = input_parameters.len();
23
24         let projection_predicates =
25             predicates.iter()
26                       .filter_map(|predicate| {
27                           match *predicate {
28                               // Ignore higher-ranked binders. For the purposes
29                               // of this check, they don't matter because they
30                               // only affect named regions, and we're just
31                               // concerned about type parameters here.
32                               ty::Predicate::Projection(ref data) => Some(data.0.clone()),
33                               _ => None,
34                           }
35                       });
36
37         for projection in projection_predicates {
38             // Special case: watch out for some kind of sneaky attempt
39             // to project out an associated type defined by this very trait.
40             if Some(projection.projection_ty.trait_ref.clone()) == impl_trait_ref {
41                 continue;
42             }
43
44             let relies_only_on_inputs =
45                 projection.projection_ty.trait_ref.input_types()
46                                                   .iter()
47                                                   .flat_map(|t| t.walk())
48                                                   .filter_map(|t| t.as_opt_param_ty())
49                                                   .all(|t| input_parameters.contains(&t));
50
51             if relies_only_on_inputs {
52                 input_parameters.extend(
53                     projection.ty.walk().filter_map(|t| t.as_opt_param_ty()));
54             }
55         }
56
57         if input_parameters.len() == num_inputs {
58             break;
59         }
60     }
61 }