Addressed points raised in review.
This commit is contained in:
parent
5bf5994d92
commit
f472cd9c02
10 changed files with 172 additions and 69 deletions
|
@ -626,9 +626,6 @@ pub fn walk_ty<'v, V: Visitor<'v>>(visitor: &mut V, typ: &'v Ty) {
|
||||||
TyKind::CVarArgs(ref lt) => {
|
TyKind::CVarArgs(ref lt) => {
|
||||||
visitor.visit_lifetime(lt)
|
visitor.visit_lifetime(lt)
|
||||||
}
|
}
|
||||||
TyKind::AssocTyExistential(ref bounds) => {
|
|
||||||
walk_list!(visitor, visit_param_bound, bounds);
|
|
||||||
}
|
|
||||||
TyKind::Infer | TyKind::Err => {}
|
TyKind::Infer | TyKind::Err => {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -677,7 +674,14 @@ pub fn walk_assoc_type_binding<'v, V: Visitor<'v>>(visitor: &mut V,
|
||||||
type_binding: &'v TypeBinding) {
|
type_binding: &'v TypeBinding) {
|
||||||
visitor.visit_id(type_binding.hir_id);
|
visitor.visit_id(type_binding.hir_id);
|
||||||
visitor.visit_ident(type_binding.ident);
|
visitor.visit_ident(type_binding.ident);
|
||||||
visitor.visit_ty(&type_binding.ty);
|
match type_binding.kind {
|
||||||
|
TypeBindingKind::Equality { ref ty } => {
|
||||||
|
visitor.visit_ty(ty);
|
||||||
|
}
|
||||||
|
TypeBindingKind::Constraint { ref bounds } => {
|
||||||
|
walk_list!(visitor, visit_param_bound, bounds);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn walk_pat<'v, V: Visitor<'v>>(visitor: &mut V, pattern: &'v Pat) {
|
pub fn walk_pat<'v, V: Visitor<'v>>(visitor: &mut V, pattern: &'v Pat) {
|
||||||
|
|
|
@ -1377,9 +1377,10 @@ impl<'a> LoweringContext<'a> {
|
||||||
-> hir::TypeBinding {
|
-> hir::TypeBinding {
|
||||||
debug!("lower_assoc_ty_constraint(constraint={:?}, itctx={:?})", c, itctx);
|
debug!("lower_assoc_ty_constraint(constraint={:?}, itctx={:?})", c, itctx);
|
||||||
|
|
||||||
// Convert to a type representing the `T::Item` value.
|
let kind = match c.kind {
|
||||||
let ty = match c.kind {
|
AssocTyConstraintKind::Equality { ref ty } => hir::TypeBindingKind::Equality {
|
||||||
AssocTyConstraintKind::Equality { ref ty } => self.lower_ty(ty, itctx),
|
ty: self.lower_ty(ty, itctx)
|
||||||
|
},
|
||||||
AssocTyConstraintKind::Bound { ref bounds } => {
|
AssocTyConstraintKind::Bound { ref bounds } => {
|
||||||
// Piggy-back on the `impl Trait` context to figure out the correct behavior.
|
// Piggy-back on the `impl Trait` context to figure out the correct behavior.
|
||||||
let (desugar_to_impl_trait, itctx) = match itctx {
|
let (desugar_to_impl_trait, itctx) = match itctx {
|
||||||
|
@ -1422,7 +1423,7 @@ impl<'a> LoweringContext<'a> {
|
||||||
|
|
||||||
if desugar_to_impl_trait {
|
if desugar_to_impl_trait {
|
||||||
// Desugar `AssocTy: Bounds` into `AssocTy = impl Bounds`. We do this by
|
// Desugar `AssocTy: Bounds` into `AssocTy = impl Bounds`. We do this by
|
||||||
// constructing the HIR for "impl bounds" and then lowering that.
|
// constructing the HIR for `impl bounds...` and then lowering that.
|
||||||
|
|
||||||
let impl_trait_node_id = self.sess.next_node_id();
|
let impl_trait_node_id = self.sess.next_node_id();
|
||||||
let parent_def_index = self.current_hir_id_owner.last().unwrap().0;
|
let parent_def_index = self.current_hir_id_owner.last().unwrap().0;
|
||||||
|
@ -1436,27 +1437,27 @@ impl<'a> LoweringContext<'a> {
|
||||||
);
|
);
|
||||||
|
|
||||||
self.with_dyn_type_scope(false, |this| {
|
self.with_dyn_type_scope(false, |this| {
|
||||||
this.lower_ty(
|
let ty = this.lower_ty(
|
||||||
&Ty {
|
&Ty {
|
||||||
id: this.sess.next_node_id(),
|
id: this.sess.next_node_id(),
|
||||||
node: TyKind::ImplTrait(impl_trait_node_id, bounds.clone()),
|
node: TyKind::ImplTrait(impl_trait_node_id, bounds.clone()),
|
||||||
span: DUMMY_SP,
|
span: DUMMY_SP,
|
||||||
},
|
},
|
||||||
itctx,
|
itctx,
|
||||||
)
|
);
|
||||||
|
|
||||||
|
hir::TypeBindingKind::Equality {
|
||||||
|
ty
|
||||||
|
}
|
||||||
})
|
})
|
||||||
} else {
|
} else {
|
||||||
// Desugar `AssocTy: Bounds` into `AssocTy = ∃ T (T: Bounds)`, where the
|
// Desugar `AssocTy: Bounds` into a type binding where the
|
||||||
// "false existential" later desugars into a trait predicate.
|
// later desugars into a trait predicate.
|
||||||
|
|
||||||
let bounds = self.lower_param_bounds(bounds, itctx);
|
let bounds = self.lower_param_bounds(bounds, itctx);
|
||||||
|
|
||||||
let id = self.sess.next_node_id();
|
hir::TypeBindingKind::Constraint {
|
||||||
P(hir::Ty {
|
bounds
|
||||||
hir_id: self.lower_node_id(id),
|
}
|
||||||
node: hir::TyKind::AssocTyExistential(bounds),
|
|
||||||
span: DUMMY_SP,
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -1464,7 +1465,7 @@ impl<'a> LoweringContext<'a> {
|
||||||
hir::TypeBinding {
|
hir::TypeBinding {
|
||||||
hir_id: self.lower_node_id(c.id),
|
hir_id: self.lower_node_id(c.id),
|
||||||
ident: c.ident,
|
ident: c.ident,
|
||||||
ty,
|
kind,
|
||||||
span: c.span,
|
span: c.span,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2359,10 +2360,17 @@ impl<'a> LoweringContext<'a> {
|
||||||
hir::TypeBinding {
|
hir::TypeBinding {
|
||||||
hir_id: this.next_id(),
|
hir_id: this.next_id(),
|
||||||
ident: Ident::with_empty_ctxt(FN_OUTPUT_NAME),
|
ident: Ident::with_empty_ctxt(FN_OUTPUT_NAME),
|
||||||
ty: output
|
kind: hir::TypeBindingKind::Equality {
|
||||||
.as_ref()
|
ty: output
|
||||||
.map(|ty| this.lower_ty(&ty, ImplTraitContext::disallowed()))
|
.as_ref()
|
||||||
.unwrap_or_else(|| P(mk_tup(this, hir::HirVec::new(), span))),
|
.map(|ty| this.lower_ty(
|
||||||
|
&ty,
|
||||||
|
ImplTraitContext::disallowed()
|
||||||
|
))
|
||||||
|
.unwrap_or_else(||
|
||||||
|
P(mk_tup(this, hir::HirVec::new(), span))
|
||||||
|
),
|
||||||
|
},
|
||||||
span: output.as_ref().map_or(span, |ty| ty.span),
|
span: output.as_ref().map_or(span, |ty| ty.span),
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
|
@ -2666,7 +2674,9 @@ impl<'a> LoweringContext<'a> {
|
||||||
args: hir_vec![],
|
args: hir_vec![],
|
||||||
bindings: hir_vec![hir::TypeBinding {
|
bindings: hir_vec![hir::TypeBinding {
|
||||||
ident: Ident::with_empty_ctxt(FN_OUTPUT_NAME),
|
ident: Ident::with_empty_ctxt(FN_OUTPUT_NAME),
|
||||||
ty: output_ty,
|
kind: hir::TypeBindingKind::Equality {
|
||||||
|
ty: output_ty,
|
||||||
|
},
|
||||||
hir_id: self.next_id(),
|
hir_id: self.next_id(),
|
||||||
span,
|
span,
|
||||||
}],
|
}],
|
||||||
|
|
|
@ -1780,7 +1780,7 @@ pub struct ImplItem {
|
||||||
pub span: Span,
|
pub span: Span,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Represents different contents within `impl`s.
|
/// Represents various kinds of content within an `impl`.
|
||||||
#[derive(Clone, RustcEncodable, RustcDecodable, Debug, HashStable)]
|
#[derive(Clone, RustcEncodable, RustcDecodable, Debug, HashStable)]
|
||||||
pub enum ImplItemKind {
|
pub enum ImplItemKind {
|
||||||
/// An associated constant of the given type, set to the constant result
|
/// An associated constant of the given type, set to the constant result
|
||||||
|
@ -1794,16 +1794,51 @@ pub enum ImplItemKind {
|
||||||
Existential(GenericBounds),
|
Existential(GenericBounds),
|
||||||
}
|
}
|
||||||
|
|
||||||
// Bind a type to an associated type (`A = Foo`).
|
/// Bind a type to an associated type (i.e., `A = Foo`).
|
||||||
|
///
|
||||||
|
/// Bindings like `A: Debug` are represented as a special type `A =
|
||||||
|
/// $::Debug` that is understood by the astconv code.
|
||||||
|
///
|
||||||
|
/// FIXME(alexreg) -- why have a separate type for the binding case,
|
||||||
|
/// wouldn't it be better to make the `ty` field an enum like:
|
||||||
|
///
|
||||||
|
/// ```
|
||||||
|
/// enum TypeBindingKind {
|
||||||
|
/// Equals(...),
|
||||||
|
/// Binding(...),
|
||||||
|
/// }
|
||||||
|
/// ```
|
||||||
#[derive(Clone, RustcEncodable, RustcDecodable, Debug, HashStable)]
|
#[derive(Clone, RustcEncodable, RustcDecodable, Debug, HashStable)]
|
||||||
pub struct TypeBinding {
|
pub struct TypeBinding {
|
||||||
pub hir_id: HirId,
|
pub hir_id: HirId,
|
||||||
#[stable_hasher(project(name))]
|
#[stable_hasher(project(name))]
|
||||||
pub ident: Ident,
|
pub ident: Ident,
|
||||||
pub ty: P<Ty>,
|
pub kind: TypeBindingKind,
|
||||||
pub span: Span,
|
pub span: Span,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Represents the two kinds of type bindings.
|
||||||
|
#[derive(Clone, RustcEncodable, RustcDecodable, Debug, HashStable)]
|
||||||
|
pub enum TypeBindingKind {
|
||||||
|
/// E.g., `Foo<Bar: Send>`.
|
||||||
|
Constraint {
|
||||||
|
bounds: HirVec<GenericBound>,
|
||||||
|
},
|
||||||
|
/// E.g., `Foo<Bar = ()>`.
|
||||||
|
Equality {
|
||||||
|
ty: P<Ty>,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
impl TypeBinding {
|
||||||
|
pub fn ty(&self) -> &Ty {
|
||||||
|
match self.kind {
|
||||||
|
TypeBindingKind::Equality { ref ty } => ty,
|
||||||
|
_ => bug!("expected equality type binding for parenthesized generic args"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Clone, RustcEncodable, RustcDecodable)]
|
#[derive(Clone, RustcEncodable, RustcDecodable)]
|
||||||
pub struct Ty {
|
pub struct Ty {
|
||||||
pub hir_id: HirId,
|
pub hir_id: HirId,
|
||||||
|
@ -1898,8 +1933,6 @@ pub enum TyKind {
|
||||||
/// Placeholder for C-variadic arguments. We "spoof" the `VaList` created
|
/// Placeholder for C-variadic arguments. We "spoof" the `VaList` created
|
||||||
/// from the variadic arguments. This type is only valid up to typeck.
|
/// from the variadic arguments. This type is only valid up to typeck.
|
||||||
CVarArgs(Lifetime),
|
CVarArgs(Lifetime),
|
||||||
/// The existential type (i.e., `impl Trait`) that constrains an associated type.
|
|
||||||
AssocTyExistential(HirVec<GenericBound>),
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, RustcEncodable, RustcDecodable, Debug, HashStable)]
|
#[derive(Clone, RustcEncodable, RustcDecodable, Debug, HashStable)]
|
||||||
|
@ -2236,18 +2269,18 @@ impl StructField {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Fields and constructor ids of enum variants and structs
|
/// Fields and constructor IDs of enum variants and structs.
|
||||||
#[derive(Clone, RustcEncodable, RustcDecodable, Debug, HashStable)]
|
#[derive(Clone, RustcEncodable, RustcDecodable, Debug, HashStable)]
|
||||||
pub enum VariantData {
|
pub enum VariantData {
|
||||||
/// Struct variant.
|
/// A struct variant.
|
||||||
///
|
///
|
||||||
/// e.g., `Bar { .. }` as in `enum Foo { Bar { .. } }`.
|
/// E.g., `Bar { .. }` as in `enum Foo { Bar { .. } }`.
|
||||||
Struct(HirVec<StructField>, /* recovered */ bool),
|
Struct(HirVec<StructField>, /* recovered */ bool),
|
||||||
/// Tuple variant.
|
/// A tuple variant.
|
||||||
///
|
///
|
||||||
/// E.g., `Bar(..)` as in `enum Foo { Bar(..) }`.
|
/// E.g., `Bar(..)` as in `enum Foo { Bar(..) }`.
|
||||||
Tuple(HirVec<StructField>, HirId),
|
Tuple(HirVec<StructField>, HirId),
|
||||||
/// Unit variant.
|
/// A unit variant.
|
||||||
///
|
///
|
||||||
/// E.g., `Bar = ..` as in `enum Foo { Bar = .. }`.
|
/// E.g., `Bar = ..` as in `enum Foo { Bar = .. }`.
|
||||||
Unit(HirId),
|
Unit(HirId),
|
||||||
|
|
|
@ -409,9 +409,6 @@ impl<'a> State<'a> {
|
||||||
hir::TyKind::CVarArgs(_) => {
|
hir::TyKind::CVarArgs(_) => {
|
||||||
self.s.word("...")?;
|
self.s.word("...")?;
|
||||||
}
|
}
|
||||||
hir::TyKind::AssocTyExistential(ref bounds) => {
|
|
||||||
self.print_bounds(":", bounds)?;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
self.end()
|
self.end()
|
||||||
}
|
}
|
||||||
|
@ -1648,7 +1645,7 @@ impl<'a> State<'a> {
|
||||||
|
|
||||||
self.space_if_not_bol()?;
|
self.space_if_not_bol()?;
|
||||||
self.word_space("->")?;
|
self.word_space("->")?;
|
||||||
self.print_type(&generic_args.bindings[0].ty)?;
|
self.print_type(generic_args.bindings[0].ty())?;
|
||||||
} else {
|
} else {
|
||||||
let start = if colons_before_params { "::<" } else { "<" };
|
let start = if colons_before_params { "::<" } else { "<" };
|
||||||
let empty = Cell::new(true);
|
let empty = Cell::new(true);
|
||||||
|
@ -1693,8 +1690,15 @@ impl<'a> State<'a> {
|
||||||
start_or_comma(self)?;
|
start_or_comma(self)?;
|
||||||
self.print_ident(binding.ident)?;
|
self.print_ident(binding.ident)?;
|
||||||
self.s.space()?;
|
self.s.space()?;
|
||||||
self.word_space("=")?;
|
match generic_args.bindings[0].kind {
|
||||||
self.print_type(&binding.ty)?;
|
hir::TypeBindingKind::Equality { ref ty } => {
|
||||||
|
self.word_space("=")?;
|
||||||
|
self.print_type(ty)?;
|
||||||
|
}
|
||||||
|
hir::TypeBindingKind::Constraint { ref bounds } => {
|
||||||
|
self.print_bounds(":", bounds)?;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if !empty.get() {
|
if !empty.get() {
|
||||||
|
|
|
@ -923,7 +923,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
|
||||||
fn visit_fn_decl(&mut self, fd: &'tcx hir::FnDecl) {
|
fn visit_fn_decl(&mut self, fd: &'tcx hir::FnDecl) {
|
||||||
let output = match fd.output {
|
let output = match fd.output {
|
||||||
hir::DefaultReturn(_) => None,
|
hir::DefaultReturn(_) => None,
|
||||||
hir::Return(ref ty) => Some(ty),
|
hir::Return(ref ty) => Some(&**ty),
|
||||||
};
|
};
|
||||||
self.visit_fn_like_elision(&fd.inputs, output);
|
self.visit_fn_like_elision(&fd.inputs, output);
|
||||||
}
|
}
|
||||||
|
@ -1884,7 +1884,7 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
|
||||||
if generic_args.parenthesized {
|
if generic_args.parenthesized {
|
||||||
let was_in_fn_syntax = self.is_in_fn_syntax;
|
let was_in_fn_syntax = self.is_in_fn_syntax;
|
||||||
self.is_in_fn_syntax = true;
|
self.is_in_fn_syntax = true;
|
||||||
self.visit_fn_like_elision(generic_args.inputs(), Some(&generic_args.bindings[0].ty));
|
self.visit_fn_like_elision(generic_args.inputs(), Some(generic_args.bindings[0].ty()));
|
||||||
self.is_in_fn_syntax = was_in_fn_syntax;
|
self.is_in_fn_syntax = was_in_fn_syntax;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -2020,7 +2020,7 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn visit_fn_like_elision(&mut self, inputs: &'tcx [hir::Ty], output: Option<&'tcx P<hir::Ty>>) {
|
fn visit_fn_like_elision(&mut self, inputs: &'tcx [hir::Ty], output: Option<&'tcx hir::Ty>) {
|
||||||
debug!("visit_fn_like_elision: enter");
|
debug!("visit_fn_like_elision: enter");
|
||||||
let mut arg_elide = Elide::FreshLateAnon(Cell::new(0));
|
let mut arg_elide = Elide::FreshLateAnon(Cell::new(0));
|
||||||
let arg_scope = Scope::Elision {
|
let arg_scope = Scope::Elision {
|
||||||
|
|
|
@ -710,10 +710,11 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx> + 'o {
|
||||||
// back separately.
|
// back separately.
|
||||||
let assoc_bindings = generic_args.bindings.iter()
|
let assoc_bindings = generic_args.bindings.iter()
|
||||||
.map(|binding| {
|
.map(|binding| {
|
||||||
let kind = if let hir::TyKind::AssocTyExistential(ref bounds) = binding.ty.node {
|
let kind = match binding.kind {
|
||||||
ConvertedBindingKind::Constraint(bounds.clone())
|
hir::TypeBindingKind::Equality { ref ty } =>
|
||||||
} else {
|
ConvertedBindingKind::Equality(self.ast_ty_to_ty(ty)),
|
||||||
ConvertedBindingKind::Equality(self.ast_ty_to_ty(&binding.ty))
|
hir::TypeBindingKind::Constraint { ref bounds } =>
|
||||||
|
ConvertedBindingKind::Constraint(bounds.clone()),
|
||||||
};
|
};
|
||||||
ConvertedBinding {
|
ConvertedBinding {
|
||||||
item_name: binding.ident,
|
item_name: binding.ident,
|
||||||
|
@ -2060,10 +2061,6 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx> + 'o {
|
||||||
let region = self.ast_region_to_region(<, None);
|
let region = self.ast_region_to_region(<, None);
|
||||||
tcx.type_of(va_list_did).subst(tcx, &[region.into()])
|
tcx.type_of(va_list_did).subst(tcx, &[region.into()])
|
||||||
}
|
}
|
||||||
hir::TyKind::AssocTyExistential(..) => {
|
|
||||||
// Type is never actually used.
|
|
||||||
tcx.types.err
|
|
||||||
}
|
|
||||||
hir::TyKind::Err => {
|
hir::TyKind::Err => {
|
||||||
tcx.types.err
|
tcx.types.err
|
||||||
}
|
}
|
||||||
|
|
|
@ -626,7 +626,9 @@ impl<'a, 'tcx> AutoTraitFinder<'a, 'tcx> {
|
||||||
} => {
|
} => {
|
||||||
bindings.push(TypeBinding {
|
bindings.push(TypeBinding {
|
||||||
name: left_name.clone(),
|
name: left_name.clone(),
|
||||||
ty: rhs,
|
kind: TypeBindingKind::Equality {
|
||||||
|
ty: rhs,
|
||||||
|
},
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
&mut GenericArgs::Parenthesized { .. } => {
|
&mut GenericArgs::Parenthesized { .. } => {
|
||||||
|
|
|
@ -1979,7 +1979,7 @@ impl FnDecl {
|
||||||
match &bounds[0] {
|
match &bounds[0] {
|
||||||
GenericBound::TraitBound(PolyTrait { trait_, .. }, ..) => {
|
GenericBound::TraitBound(PolyTrait { trait_, .. }, ..) => {
|
||||||
let bindings = trait_.bindings().unwrap();
|
let bindings = trait_.bindings().unwrap();
|
||||||
FunctionRetTy::Return(bindings[0].ty.clone())
|
FunctionRetTy::Return(bindings[0].ty().clone())
|
||||||
}
|
}
|
||||||
_ => panic!("unexpected desugaring of async function"),
|
_ => panic!("unexpected desugaring of async function"),
|
||||||
}
|
}
|
||||||
|
@ -2937,11 +2937,8 @@ impl Clean<Type> for hir::Ty {
|
||||||
}
|
}
|
||||||
TyKind::BareFn(ref barefn) => BareFunction(box barefn.clean(cx)),
|
TyKind::BareFn(ref barefn) => BareFunction(box barefn.clean(cx)),
|
||||||
TyKind::Infer | TyKind::Err => Infer,
|
TyKind::Infer | TyKind::Err => Infer,
|
||||||
TyKind::Typeof(..) => panic!("Unimplemented type {:?}", self.node),
|
TyKind::Typeof(..) => panic!("unimplemented type {:?}", self.node),
|
||||||
TyKind::CVarArgs(_) => CVarArgs,
|
TyKind::CVarArgs(_) => CVarArgs,
|
||||||
TyKind::AssocTyExistential(ref bounds) => {
|
|
||||||
ImplTrait(bounds.into_iter().map(|b| b.clean(cx)).collect())
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3057,7 +3054,9 @@ impl<'tcx> Clean<Type> for Ty<'tcx> {
|
||||||
for pb in obj.projection_bounds() {
|
for pb in obj.projection_bounds() {
|
||||||
bindings.push(TypeBinding {
|
bindings.push(TypeBinding {
|
||||||
name: cx.tcx.associated_item(pb.item_def_id()).ident.name.clean(cx),
|
name: cx.tcx.associated_item(pb.item_def_id()).ident.name.clean(cx),
|
||||||
ty: pb.skip_binder().ty.clean(cx)
|
kind: TypeBindingKind::Equality {
|
||||||
|
ty: pb.skip_binder().ty.clean(cx)
|
||||||
|
},
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3113,7 +3112,9 @@ impl<'tcx> Clean<Type> for Ty<'tcx> {
|
||||||
Some(TypeBinding {
|
Some(TypeBinding {
|
||||||
name: cx.tcx.associated_item(proj.projection_ty.item_def_id)
|
name: cx.tcx.associated_item(proj.projection_ty.item_def_id)
|
||||||
.ident.name.clean(cx),
|
.ident.name.clean(cx),
|
||||||
ty: proj.ty.clean(cx),
|
kind: TypeBindingKind::Equality {
|
||||||
|
ty: proj.ty.clean(cx),
|
||||||
|
},
|
||||||
})
|
})
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
|
@ -3498,7 +3499,7 @@ pub enum GenericArgs {
|
||||||
impl Clean<GenericArgs> for hir::GenericArgs {
|
impl Clean<GenericArgs> for hir::GenericArgs {
|
||||||
fn clean(&self, cx: &DocContext<'_>) -> GenericArgs {
|
fn clean(&self, cx: &DocContext<'_>) -> GenericArgs {
|
||||||
if self.parenthesized {
|
if self.parenthesized {
|
||||||
let output = self.bindings[0].ty.clean(cx);
|
let output = self.bindings[0].ty().clean(cx);
|
||||||
GenericArgs::Parenthesized {
|
GenericArgs::Parenthesized {
|
||||||
inputs: self.inputs().clean(cx),
|
inputs: self.inputs().clean(cx),
|
||||||
output: if output != Type::Tuple(Vec::new()) { Some(output) } else { None }
|
output: if output != Type::Tuple(Vec::new()) { Some(output) } else { None }
|
||||||
|
@ -4346,18 +4347,53 @@ impl Clean<Deprecation> for attr::Deprecation {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// An equality constraint on an associated type, e.g., `A = Bar` in `Foo<A = Bar>`
|
/// An type binding on an associated type (e.g., `A = Bar` in `Foo<A = Bar>` or
|
||||||
|
/// `A: Send + Sync` in `Foo<A: Send + Sync>`).
|
||||||
#[derive(Clone, PartialEq, Eq, RustcDecodable, RustcEncodable, Debug, Hash)]
|
#[derive(Clone, PartialEq, Eq, RustcDecodable, RustcEncodable, Debug, Hash)]
|
||||||
pub struct TypeBinding {
|
pub struct TypeBinding {
|
||||||
pub name: String,
|
pub name: String,
|
||||||
pub ty: Type
|
pub kind: TypeBindingKind,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, PartialEq, Eq, RustcDecodable, RustcEncodable, Debug, Hash)]
|
||||||
|
pub enum TypeBindingKind {
|
||||||
|
Equality {
|
||||||
|
ty: Type,
|
||||||
|
},
|
||||||
|
Constraint {
|
||||||
|
bounds: Vec<GenericBound>,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
impl TypeBinding {
|
||||||
|
pub fn ty(&self) -> &Type {
|
||||||
|
match self.kind {
|
||||||
|
TypeBindingKind::Equality { ref ty } => ty,
|
||||||
|
_ => panic!("expected equality type binding for parenthesized generic args"),
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Clean<TypeBinding> for hir::TypeBinding {
|
impl Clean<TypeBinding> for hir::TypeBinding {
|
||||||
fn clean(&self, cx: &DocContext<'_>) -> TypeBinding {
|
fn clean(&self, cx: &DocContext<'_>) -> TypeBinding {
|
||||||
TypeBinding {
|
TypeBinding {
|
||||||
name: self.ident.name.clean(cx),
|
name: self.ident.name.clean(cx),
|
||||||
ty: self.ty.clean(cx)
|
kind: self.kind.clean(cx),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Clean<TypeBindingKind> for hir::TypeBindingKind {
|
||||||
|
fn clean(&self, cx: &DocContext<'_>) -> TypeBindingKind {
|
||||||
|
match *self {
|
||||||
|
hir::TypeBindingKind::Equality { ref ty } =>
|
||||||
|
TypeBindingKind::Equality {
|
||||||
|
ty: ty.clean(cx),
|
||||||
|
},
|
||||||
|
hir::TypeBindingKind::Constraint { ref bounds } =>
|
||||||
|
TypeBindingKind::Constraint {
|
||||||
|
bounds: bounds.into_iter().map(|b| b.clean(cx)).collect(),
|
||||||
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -91,7 +91,9 @@ pub fn where_clauses(cx: &DocContext<'_>, clauses: Vec<WP>) -> Vec<WP> {
|
||||||
PP::AngleBracketed { ref mut bindings, .. } => {
|
PP::AngleBracketed { ref mut bindings, .. } => {
|
||||||
bindings.push(clean::TypeBinding {
|
bindings.push(clean::TypeBinding {
|
||||||
name: name.clone(),
|
name: name.clone(),
|
||||||
ty: rhs.clone(),
|
kind: clean::TypeBindingKind::Equality {
|
||||||
|
ty: rhs.clone(),
|
||||||
|
},
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
PP::Parenthesized { ref mut output, .. } => {
|
PP::Parenthesized { ref mut output, .. } => {
|
||||||
|
|
|
@ -1019,11 +1019,26 @@ impl fmt::Display for clean::ImportSource {
|
||||||
|
|
||||||
impl fmt::Display for clean::TypeBinding {
|
impl fmt::Display for clean::TypeBinding {
|
||||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
if f.alternate() {
|
f.write_str(&self.name)?;
|
||||||
write!(f, "{} = {:#}", self.name, self.ty)
|
match self.kind {
|
||||||
} else {
|
clean::TypeBindingKind::Equality { ref ty } => {
|
||||||
write!(f, "{} = {}", self.name, self.ty)
|
if f.alternate() {
|
||||||
|
write!(f, " = {:#}", ty)?;
|
||||||
|
} else {
|
||||||
|
write!(f, " = {}", ty)?;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
clean::TypeBindingKind::Constraint { ref bounds } => {
|
||||||
|
if !bounds.is_empty() {
|
||||||
|
if f.alternate() {
|
||||||
|
write!(f, ": {:#}", GenericBounds(bounds))?;
|
||||||
|
} else {
|
||||||
|
write!(f, ": {}", GenericBounds(bounds))?;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue