+ // Returns `true` if a bounds list includes `?Sized`.
+ pub fn is_unsized(&self, ast_bounds: &[hir::GenericBound], span: Span) -> bool {
+ let tcx = self.tcx();
+
+ // Try to find an unbound in bounds.
+ let mut unbound = None;
+ for ab in ast_bounds {
+ if let &hir::GenericBound::Trait(ref ptr, hir::TraitBoundModifier::Maybe) = ab {
+ if unbound.is_none() {
+ unbound = Some(ptr.trait_ref.clone());
+ } else {
+ span_err!(
+ tcx.sess,
+ span,
+ E0203,
+ "type parameter has more than one relaxed default \
+ bound, only one is supported"
+ );
+ }
+ }
+ }
+
+ let kind_id = tcx.lang_items().require(SizedTraitLangItem);
+ match unbound {
+ Some(ref tpb) => {
+ // FIXME(#8559) currently requires the unbound to be built-in.
+ if let Ok(kind_id) = kind_id {
+ if tpb.path.res != Res::Def(DefKind::Trait, kind_id) {
+ tcx.sess.span_warn(
+ span,
+ "default bound relaxed for a type parameter, but \
+ this does nothing because the given bound is not \
+ a default. Only `?Sized` is supported",
+ );
+ }
+ }
+ }
+ _ if kind_id.is_ok() => {
+ return false;
+ }
+ // No lang item for `Sized`, so we can't add it as a bound.
+ None => {}
+ }
+
+ true
+ }
+
+ /// This helper takes a *converted* parameter type (`param_ty`)
+ /// and an *unconverted* list of bounds:
+ ///
+ /// ```
+ /// fn foo<T: Debug>
+ /// ^ ^^^^^ `ast_bounds` parameter, in HIR form
+ /// |
+ /// `param_ty`, in ty form
+ /// ```
+ ///
+ /// It adds these `ast_bounds` into the `bounds` structure.
+ ///
+ /// **A note on binders:** there is an implied binder around
+ /// `param_ty` and `ast_bounds`. See `instantiate_poly_trait_ref`
+ /// for more details.
+ fn add_bounds(&self,
+ param_ty: Ty<'tcx>,
+ ast_bounds: &[hir::GenericBound],
+ bounds: &mut Bounds<'tcx>,
+ ) {
+ let mut trait_bounds = Vec::new();
+ let mut region_bounds = Vec::new();
+
+ for ast_bound in ast_bounds {
+ match *ast_bound {
+ hir::GenericBound::Trait(ref b, hir::TraitBoundModifier::None) =>
+ trait_bounds.push(b),
+ hir::GenericBound::Trait(_, hir::TraitBoundModifier::Maybe) => {}
+ hir::GenericBound::Outlives(ref l) =>
+ region_bounds.push(l),
+ }
+ }
+
+ for bound in trait_bounds {
+ let (poly_trait_ref, _) = self.instantiate_poly_trait_ref(
+ bound,
+ param_ty,
+ bounds,
+ );
+ bounds.trait_bounds.push((poly_trait_ref, bound.span))
+ }
+
+ bounds.region_bounds.extend(region_bounds
+ .into_iter()
+ .map(|r| (self.ast_region_to_region(r, None), r.span))
+ );
+ }
+
+ /// Translates a list of bounds from the HIR into the `Bounds` data structure.
+ /// The self-type for the bounds is given by `param_ty`.
+ ///
+ /// Example:
+ ///
+ /// ```
+ /// fn foo<T: Bar + Baz>() { }
+ /// ^ ^^^^^^^^^ ast_bounds
+ /// param_ty
+ /// ```
+ ///
+ /// The `sized_by_default` parameter indicates if, in this context, the `param_ty` should be
+ /// considered `Sized` unless there is an explicit `?Sized` bound. This would be true in the
+ /// example above, but is not true in supertrait listings like `trait Foo: Bar + Baz`.
+ ///
+ /// `span` should be the declaration size of the parameter.
+ pub fn compute_bounds(&self,
+ param_ty: Ty<'tcx>,
+ ast_bounds: &[hir::GenericBound],
+ sized_by_default: SizedByDefault,
+ span: Span,
+ ) -> Bounds<'tcx> {
+ let mut bounds = Bounds::default();
+
+ self.add_bounds(param_ty, ast_bounds, &mut bounds);
+ bounds.trait_bounds.sort_by_key(|(t, _)| t.def_id());
+
+ bounds.implicitly_sized = if let SizedByDefault::Yes = sized_by_default {
+ if !self.is_unsized(ast_bounds, span) {
+ Some(span)
+ } else {
+ None
+ }
+ } else {
+ None
+ };
+
+ bounds
+ }
+
+ /// Given an HIR binding like `Item = Foo` or `Item: Foo`, pushes the corresponding predicates
+ /// onto `bounds`.
+ ///
+ /// **A note on binders:** given something like `T: for<'a> Iterator<Item = &'a u32>`, the
+ /// `trait_ref` here will be `for<'a> T: Iterator`. The `binding` data however is from *inside*
+ /// the binder (e.g., `&'a u32`) and hence may reference bound regions.
+ fn add_predicates_for_ast_type_binding(