Handle generic parameters.
This commit is contained in:
parent
cdf78073c5
commit
05812df603
@ -252,11 +252,10 @@ enum ImplTraitContext {
|
||||
ReturnPositionOpaqueTy {
|
||||
/// Origin: Either OpaqueTyOrigin::FnReturn or OpaqueTyOrigin::AsyncFn,
|
||||
origin: hir::OpaqueTyOrigin,
|
||||
in_trait: bool,
|
||||
},
|
||||
/// Impl trait in type aliases.
|
||||
TypeAliasesOpaqueTy,
|
||||
/// Return-position `impl Trait` in trait definition
|
||||
InTrait,
|
||||
/// `impl Trait` is not accepted in this position.
|
||||
Disallowed(ImplTraitPosition),
|
||||
}
|
||||
@ -1343,9 +1342,15 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
||||
TyKind::ImplTrait(def_node_id, ref bounds) => {
|
||||
let span = t.span;
|
||||
match itctx {
|
||||
ImplTraitContext::ReturnPositionOpaqueTy { origin } => {
|
||||
self.lower_opaque_impl_trait(span, *origin, def_node_id, bounds, itctx)
|
||||
}
|
||||
ImplTraitContext::ReturnPositionOpaqueTy { origin, in_trait } => self
|
||||
.lower_opaque_impl_trait(
|
||||
span,
|
||||
*origin,
|
||||
def_node_id,
|
||||
bounds,
|
||||
*in_trait,
|
||||
itctx,
|
||||
),
|
||||
ImplTraitContext::TypeAliasesOpaqueTy => {
|
||||
let mut nested_itctx = ImplTraitContext::TypeAliasesOpaqueTy;
|
||||
self.lower_opaque_impl_trait(
|
||||
@ -1353,14 +1358,10 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
||||
hir::OpaqueTyOrigin::TyAlias,
|
||||
def_node_id,
|
||||
bounds,
|
||||
&mut nested_itctx,
|
||||
false,
|
||||
nested_itctx,
|
||||
)
|
||||
}
|
||||
ImplTraitContext::InTrait => {
|
||||
self.lower_impl_trait_in_trait(span, def_node_id, |lctx| {
|
||||
lctx.lower_param_bounds(bounds, ImplTraitContext::InTrait)
|
||||
})
|
||||
}
|
||||
ImplTraitContext::Universal => {
|
||||
let span = t.span;
|
||||
let ident = Ident::from_str_and_span(&pprust::ty_to_string(t), span);
|
||||
@ -1430,6 +1431,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
||||
origin: hir::OpaqueTyOrigin,
|
||||
opaque_ty_node_id: NodeId,
|
||||
bounds: &GenericBounds,
|
||||
in_trait: bool,
|
||||
itctx: &mut ImplTraitContext,
|
||||
) -> hir::TyKind<'hir> {
|
||||
// Make sure we know that some funky desugaring has been going on here.
|
||||
@ -1518,6 +1520,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
||||
}),
|
||||
bounds: hir_bounds,
|
||||
origin,
|
||||
in_trait,
|
||||
};
|
||||
debug!(?opaque_ty_item);
|
||||
|
||||
@ -1544,30 +1547,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
||||
debug!(?lifetimes);
|
||||
|
||||
// `impl Trait` now just becomes `Foo<'a, 'b, ..>`.
|
||||
hir::TyKind::OpaqueDef(hir::ItemId { def_id: opaque_ty_def_id }, lifetimes)
|
||||
}
|
||||
|
||||
#[instrument(level = "debug", skip(self, lower_bounds))]
|
||||
fn lower_impl_trait_in_trait(
|
||||
&mut self,
|
||||
span: Span,
|
||||
opaque_ty_node_id: NodeId,
|
||||
lower_bounds: impl FnOnce(&mut Self) -> hir::GenericBounds<'hir>,
|
||||
) -> hir::TyKind<'hir> {
|
||||
let opaque_ty_def_id = self.local_def_id(opaque_ty_node_id);
|
||||
self.with_hir_id_owner(opaque_ty_node_id, |lctx| {
|
||||
let hir_bounds = lower_bounds(lctx);
|
||||
let rpitit_placeholder = hir::ImplTraitPlaceholder { bounds: hir_bounds };
|
||||
let rpitit_item = hir::Item {
|
||||
def_id: opaque_ty_def_id,
|
||||
ident: Ident::empty(),
|
||||
kind: hir::ItemKind::ImplTraitPlaceholder(rpitit_placeholder),
|
||||
span: lctx.lower_span(span),
|
||||
vis_span: lctx.lower_span(span.shrink_to_lo()),
|
||||
};
|
||||
hir::OwnerNode::Item(lctx.arena.alloc(rpitit_item))
|
||||
});
|
||||
hir::TyKind::ImplTraitInTrait(hir::ItemId { def_id: opaque_ty_def_id })
|
||||
hir::TyKind::OpaqueDef(hir::ItemId { def_id: opaque_ty_def_id }, lifetimes, in_trait)
|
||||
}
|
||||
|
||||
/// Registers a new opaque type with the proper `NodeId`s and
|
||||
@ -1728,30 +1708,28 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
||||
)
|
||||
.emit();
|
||||
}
|
||||
self.lower_async_fn_ret_ty_in_trait(
|
||||
self.lower_async_fn_ret_ty(
|
||||
&decl.output,
|
||||
fn_node_id.expect("`make_ret_async` but no `fn_def_id`"),
|
||||
ret_id,
|
||||
true,
|
||||
)
|
||||
}
|
||||
_ => {
|
||||
if !kind.impl_trait_return_allowed(self.tcx) {
|
||||
if kind == FnDeclKind::Impl {
|
||||
self.tcx
|
||||
.sess
|
||||
.create_feature_err(
|
||||
TraitFnAsync { fn_span, span },
|
||||
sym::return_position_impl_trait_in_trait,
|
||||
)
|
||||
.emit();
|
||||
} else {
|
||||
self.tcx.sess.emit_err(TraitFnAsync { fn_span, span });
|
||||
}
|
||||
self.tcx
|
||||
.sess
|
||||
.create_feature_err(
|
||||
TraitFnAsync { fn_span, span },
|
||||
sym::return_position_impl_trait_in_trait,
|
||||
)
|
||||
.emit();
|
||||
}
|
||||
self.lower_async_fn_ret_ty(
|
||||
&decl.output,
|
||||
fn_node_id.expect("`make_ret_async` but no `fn_def_id`"),
|
||||
ret_id,
|
||||
false,
|
||||
)
|
||||
}
|
||||
}
|
||||
@ -1763,10 +1741,15 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
||||
let fn_def_id = self.local_def_id(fn_node_id);
|
||||
ImplTraitContext::ReturnPositionOpaqueTy {
|
||||
origin: hir::OpaqueTyOrigin::FnReturn(fn_def_id),
|
||||
in_trait: false,
|
||||
}
|
||||
}
|
||||
Some(_) if kind.impl_trait_in_trait_allowed(self.tcx) => {
|
||||
ImplTraitContext::InTrait
|
||||
Some(fn_node_id) if kind.impl_trait_in_trait_allowed(self.tcx) => {
|
||||
let fn_def_id = self.local_def_id(fn_node_id);
|
||||
ImplTraitContext::ReturnPositionOpaqueTy {
|
||||
origin: hir::OpaqueTyOrigin::FnReturn(fn_def_id),
|
||||
in_trait: true,
|
||||
}
|
||||
}
|
||||
_ => ImplTraitContext::Disallowed(match kind {
|
||||
FnDeclKind::Fn | FnDeclKind::Inherent => {
|
||||
@ -1829,6 +1812,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
||||
output: &FnRetTy,
|
||||
fn_node_id: NodeId,
|
||||
opaque_ty_node_id: NodeId,
|
||||
in_trait: bool,
|
||||
) -> hir::FnRetTy<'hir> {
|
||||
let span = output.span();
|
||||
|
||||
@ -1960,6 +1944,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
||||
span,
|
||||
ImplTraitContext::ReturnPositionOpaqueTy {
|
||||
origin: hir::OpaqueTyOrigin::FnReturn(fn_def_id),
|
||||
in_trait,
|
||||
},
|
||||
);
|
||||
|
||||
@ -1999,6 +1984,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
||||
}),
|
||||
bounds: arena_vec![this; future_bound],
|
||||
origin: hir::OpaqueTyOrigin::AsyncFn(fn_def_id),
|
||||
in_trait,
|
||||
};
|
||||
|
||||
trace!("exist ty from async fn def id: {:#?}", opaque_ty_def_id);
|
||||
@ -2043,41 +2029,15 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
||||
// Foo = impl Trait` is, internally, created as a child of the
|
||||
// async fn, so the *type parameters* are inherited. It's
|
||||
// only the lifetime parameters that we must supply.
|
||||
let opaque_ty_ref =
|
||||
hir::TyKind::OpaqueDef(hir::ItemId { def_id: opaque_ty_def_id }, generic_args);
|
||||
let opaque_ty_ref = hir::TyKind::OpaqueDef(
|
||||
hir::ItemId { def_id: opaque_ty_def_id },
|
||||
generic_args,
|
||||
in_trait,
|
||||
);
|
||||
let opaque_ty = self.ty(opaque_ty_span, opaque_ty_ref);
|
||||
hir::FnRetTy::Return(self.arena.alloc(opaque_ty))
|
||||
}
|
||||
|
||||
// Transforms `-> T` for `async fn` into `-> OpaqueTy { .. }`
|
||||
// combined with the following definition of `OpaqueTy`:
|
||||
//
|
||||
// type OpaqueTy<generics_from_parent_fn> = impl Future<Output = T>;
|
||||
//
|
||||
// `output`: unlowered output type (`T` in `-> T`)
|
||||
// `fn_def_id`: `DefId` of the parent function (used to create child impl trait definition)
|
||||
// `opaque_ty_node_id`: `NodeId` of the opaque `impl Trait` type that should be created
|
||||
#[instrument(level = "debug", skip(self))]
|
||||
fn lower_async_fn_ret_ty_in_trait(
|
||||
&mut self,
|
||||
output: &FnRetTy,
|
||||
fn_node_id: NodeId,
|
||||
opaque_ty_node_id: NodeId,
|
||||
) -> hir::FnRetTy<'hir> {
|
||||
let kind = self.lower_impl_trait_in_trait(output.span(), opaque_ty_node_id, |lctx| {
|
||||
let bound = lctx.lower_async_fn_output_type_to_future_bound(
|
||||
output,
|
||||
output.span(),
|
||||
ImplTraitContext::InTrait,
|
||||
);
|
||||
arena_vec![lctx; bound]
|
||||
});
|
||||
|
||||
let opaque_ty_span = self.mark_span_with_reason(DesugaringKind::Async, output.span(), None);
|
||||
let opaque_ty = self.ty(opaque_ty_span, kind);
|
||||
hir::FnRetTy::Return(self.arena.alloc(opaque_ty))
|
||||
}
|
||||
|
||||
/// Transforms `-> T` into `Future<Output = T>`.
|
||||
fn lower_async_fn_output_type_to_future_bound(
|
||||
&mut self,
|
||||
|
@ -772,7 +772,7 @@ impl<'tcx> MirBorrowckCtxt<'_, 'tcx> {
|
||||
fn get_future_inner_return_ty(&self, hir_ty: &'tcx hir::Ty<'tcx>) -> &'tcx hir::Ty<'tcx> {
|
||||
let hir = self.infcx.tcx.hir();
|
||||
|
||||
let hir::TyKind::OpaqueDef(id, _) = hir_ty.kind else {
|
||||
let hir::TyKind::OpaqueDef(id, _, _) = hir_ty.kind else {
|
||||
span_bug!(
|
||||
hir_ty.span,
|
||||
"lowered return type of async fn is not OpaqueDef: {:?}",
|
||||
|
@ -2505,6 +2505,7 @@ pub struct OpaqueTy<'hir> {
|
||||
pub generics: &'hir Generics<'hir>,
|
||||
pub bounds: GenericBounds<'hir>,
|
||||
pub origin: OpaqueTyOrigin,
|
||||
pub in_trait: bool,
|
||||
}
|
||||
|
||||
/// From whence the opaque type came.
|
||||
@ -2518,12 +2519,6 @@ pub enum OpaqueTyOrigin {
|
||||
TyAlias,
|
||||
}
|
||||
|
||||
/// Placeholder representation of an `impl Trait` in a trait. Since this never gets lowered into a `ty::Opaque` of its own, we just keep this as
|
||||
#[derive(Debug, HashStable_Generic)]
|
||||
pub struct ImplTraitPlaceholder<'hir> {
|
||||
pub bounds: GenericBounds<'hir>,
|
||||
}
|
||||
|
||||
/// The various kinds of types recognized by the compiler.
|
||||
#[derive(Debug, HashStable_Generic)]
|
||||
pub enum TyKind<'hir> {
|
||||
@ -2550,12 +2545,9 @@ pub enum TyKind<'hir> {
|
||||
///
|
||||
/// The generic argument list contains the lifetimes (and in the future
|
||||
/// possibly parameters) that are actually bound on the `impl Trait`.
|
||||
OpaqueDef(ItemId, &'hir [GenericArg<'hir>]),
|
||||
/// A type that represents an `impl Trait` in a trait function. This is
|
||||
/// not an opaque type, since it acts more like an associated type than
|
||||
/// an opaque, and since it needs no generics since it inherits those
|
||||
/// from the item's parent.
|
||||
ImplTraitInTrait(ItemId),
|
||||
///
|
||||
/// The last parameter specifies whether this opaque appears in a trait definition.
|
||||
OpaqueDef(ItemId, &'hir [GenericArg<'hir>], bool),
|
||||
/// A trait object type `Bound1 + Bound2 + Bound3`
|
||||
/// where `Bound` is a trait or a lifetime.
|
||||
TraitObject(&'hir [PolyTraitRef<'hir>], &'hir Lifetime, TraitObjectSyntax),
|
||||
@ -3011,8 +3003,6 @@ pub enum ItemKind<'hir> {
|
||||
TyAlias(&'hir Ty<'hir>, &'hir Generics<'hir>),
|
||||
/// An opaque `impl Trait` type alias, e.g., `type Foo = impl Bar;`.
|
||||
OpaqueTy(OpaqueTy<'hir>),
|
||||
/// An `impl Trait` in a trait
|
||||
ImplTraitPlaceholder(ImplTraitPlaceholder<'hir>),
|
||||
/// An enum definition, e.g., `enum Foo<A, B> {C<A>, D<B>}`.
|
||||
Enum(EnumDef<'hir>, &'hir Generics<'hir>),
|
||||
/// A struct definition, e.g., `struct Foo<A> {x: A}`.
|
||||
@ -3081,7 +3071,6 @@ impl ItemKind<'_> {
|
||||
ItemKind::Trait(..) => "trait",
|
||||
ItemKind::TraitAlias(..) => "trait alias",
|
||||
ItemKind::Impl(..) => "implementation",
|
||||
ItemKind::ImplTraitPlaceholder(..) => "opaque type in trait",
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -562,10 +562,6 @@ pub fn walk_item<'v, V: Visitor<'v>>(visitor: &mut V, item: &'v Item<'v>) {
|
||||
walk_generics(visitor, generics);
|
||||
walk_list!(visitor, visit_param_bound, bounds);
|
||||
}
|
||||
ItemKind::ImplTraitPlaceholder(ImplTraitPlaceholder { bounds }) => {
|
||||
visitor.visit_id(item.hir_id());
|
||||
walk_list!(visitor, visit_param_bound, bounds);
|
||||
}
|
||||
ItemKind::Enum(ref enum_definition, ref generics) => {
|
||||
visitor.visit_generics(generics);
|
||||
// `visit_enum_def()` takes care of visiting the `Item`'s `HirId`.
|
||||
@ -674,13 +670,10 @@ pub fn walk_ty<'v, V: Visitor<'v>>(visitor: &mut V, typ: &'v Ty<'v>) {
|
||||
TyKind::Path(ref qpath) => {
|
||||
visitor.visit_qpath(qpath, typ.hir_id, typ.span);
|
||||
}
|
||||
TyKind::OpaqueDef(item_id, lifetimes) => {
|
||||
TyKind::OpaqueDef(item_id, lifetimes, _in_trait) => {
|
||||
visitor.visit_nested_item(item_id);
|
||||
walk_list!(visitor, visit_generic_arg, lifetimes);
|
||||
}
|
||||
TyKind::ImplTraitInTrait(item_id) => {
|
||||
visitor.visit_nested_item(item_id);
|
||||
}
|
||||
TyKind::Array(ref ty, ref length) => {
|
||||
visitor.visit_ty(ty);
|
||||
visitor.visit_array_length(length)
|
||||
|
@ -80,8 +80,13 @@ impl Target {
|
||||
ItemKind::ForeignMod { .. } => Target::ForeignMod,
|
||||
ItemKind::GlobalAsm(..) => Target::GlobalAsm,
|
||||
ItemKind::TyAlias(..) => Target::TyAlias,
|
||||
ItemKind::OpaqueTy(..) => Target::OpaqueTy,
|
||||
ItemKind::ImplTraitPlaceholder(..) => Target::ImplTraitPlaceholder,
|
||||
ItemKind::OpaqueTy(ref opaque) => {
|
||||
if opaque.in_trait {
|
||||
Target::ImplTraitPlaceholder
|
||||
} else {
|
||||
Target::OpaqueTy
|
||||
}
|
||||
}
|
||||
ItemKind::Enum(..) => Target::Enum,
|
||||
ItemKind::Struct(..) => Target::Struct,
|
||||
ItemKind::Union(..) => Target::Union,
|
||||
|
@ -327,7 +327,6 @@ impl<'a> State<'a> {
|
||||
self.print_ty_fn(f.abi, f.unsafety, f.decl, None, f.generic_params, f.param_names);
|
||||
}
|
||||
hir::TyKind::OpaqueDef(..) => self.word("/*impl Trait*/"),
|
||||
hir::TyKind::ImplTraitInTrait(..) => self.word("/*impl Trait*/"),
|
||||
hir::TyKind::Path(ref qpath) => self.print_qpath(qpath, false),
|
||||
hir::TyKind::TraitObject(bounds, ref lifetime, syntax) => {
|
||||
if syntax == ast::TraitObjectSyntax::Dyn {
|
||||
@ -609,9 +608,6 @@ impl<'a> State<'a> {
|
||||
state.print_bounds("= impl", real_bounds);
|
||||
});
|
||||
}
|
||||
hir::ItemKind::ImplTraitPlaceholder(..) => {
|
||||
unreachable!("FIXME(RPITIT): I don't think this ever gets called here...");
|
||||
}
|
||||
hir::ItemKind::Enum(ref enum_definition, params) => {
|
||||
self.print_enum_def(enum_definition, params, item.ident.name, item.span);
|
||||
}
|
||||
|
@ -300,7 +300,7 @@ pub fn suggest_new_region_bound(
|
||||
continue;
|
||||
}
|
||||
match fn_return.kind {
|
||||
TyKind::OpaqueDef(item_id, _) => {
|
||||
TyKind::OpaqueDef(item_id, _, _) => {
|
||||
let item = tcx.hir().item(item_id);
|
||||
let ItemKind::OpaqueTy(opaque) = &item.kind else {
|
||||
return;
|
||||
|
@ -1500,9 +1500,6 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
|
||||
hir::ItemKind::OpaqueTy(..) => {
|
||||
self.encode_explicit_item_bounds(def_id);
|
||||
}
|
||||
hir::ItemKind::ImplTraitPlaceholder(..) => {
|
||||
self.encode_explicit_item_bounds(def_id);
|
||||
}
|
||||
hir::ItemKind::Enum(..) => {
|
||||
let adt_def = self.tcx.adt_def(def_id);
|
||||
record!(self.tables.repr_options[def_id] <- adt_def.repr());
|
||||
|
@ -212,8 +212,13 @@ impl<'hir> Map<'hir> {
|
||||
ItemKind::Fn(..) => DefKind::Fn,
|
||||
ItemKind::Macro(_, macro_kind) => DefKind::Macro(macro_kind),
|
||||
ItemKind::Mod(..) => DefKind::Mod,
|
||||
ItemKind::OpaqueTy(..) => DefKind::OpaqueTy,
|
||||
ItemKind::ImplTraitPlaceholder(..) => DefKind::ImplTraitPlaceholder,
|
||||
ItemKind::OpaqueTy(ref opaque) => {
|
||||
if opaque.in_trait {
|
||||
DefKind::ImplTraitPlaceholder
|
||||
} else {
|
||||
DefKind::OpaqueTy
|
||||
}
|
||||
}
|
||||
ItemKind::TyAlias(..) => DefKind::TyAlias,
|
||||
ItemKind::Enum(..) => DefKind::Enum,
|
||||
ItemKind::Struct(..) => DefKind::Struct,
|
||||
@ -1188,8 +1193,13 @@ fn hir_id_to_string(map: Map<'_>, id: HirId) -> String {
|
||||
ItemKind::ForeignMod { .. } => "foreign mod",
|
||||
ItemKind::GlobalAsm(..) => "global asm",
|
||||
ItemKind::TyAlias(..) => "ty",
|
||||
ItemKind::OpaqueTy(..) => "opaque type",
|
||||
ItemKind::ImplTraitPlaceholder(..) => "opaque type in trait",
|
||||
ItemKind::OpaqueTy(ref opaque) => {
|
||||
if opaque.in_trait {
|
||||
"opaque type in trait"
|
||||
} else {
|
||||
"opaque type"
|
||||
}
|
||||
}
|
||||
ItemKind::Enum(..) => "enum",
|
||||
ItemKind::Struct(..) => "struct",
|
||||
ItemKind::Union(..) => "union",
|
||||
|
@ -408,7 +408,7 @@ impl<'v> hir::intravisit::Visitor<'v> for TraitObjectVisitor<'v> {
|
||||
) => {
|
||||
self.0.push(ty);
|
||||
}
|
||||
hir::TyKind::OpaqueDef(item_id, _) => {
|
||||
hir::TyKind::OpaqueDef(item_id, _, _) => {
|
||||
self.0.push(ty);
|
||||
let item = self.1.item(item_id);
|
||||
hir::intravisit::walk_item(self, item);
|
||||
|
@ -447,7 +447,7 @@ impl<'tcx> Visitor<'tcx> for MarkSymbolVisitor<'tcx> {
|
||||
}
|
||||
|
||||
fn visit_ty(&mut self, ty: &'tcx hir::Ty<'tcx>) {
|
||||
if let TyKind::OpaqueDef(item_id, _) = ty.kind {
|
||||
if let TyKind::OpaqueDef(item_id, _, _) = ty.kind {
|
||||
let item = self.tcx.hir().item(item_id);
|
||||
intravisit::walk_item(self, item);
|
||||
}
|
||||
|
@ -235,7 +235,6 @@ impl<'tcx> ReachableContext<'tcx> {
|
||||
hir::ItemKind::ExternCrate(_)
|
||||
| hir::ItemKind::Use(..)
|
||||
| hir::ItemKind::OpaqueTy(..)
|
||||
| hir::ItemKind::ImplTraitPlaceholder(..)
|
||||
| hir::ItemKind::TyAlias(..)
|
||||
| hir::ItemKind::Macro(..)
|
||||
| hir::ItemKind::Mod(..)
|
||||
|
@ -686,7 +686,6 @@ impl<'tcx> Visitor<'tcx> for EmbargoVisitor<'tcx> {
|
||||
}
|
||||
|
||||
hir::ItemKind::OpaqueTy(..)
|
||||
| hir::ItemKind::ImplTraitPlaceholder(..)
|
||||
| hir::ItemKind::Use(..)
|
||||
| hir::ItemKind::Static(..)
|
||||
| hir::ItemKind::Const(..)
|
||||
@ -708,12 +707,12 @@ impl<'tcx> Visitor<'tcx> for EmbargoVisitor<'tcx> {
|
||||
hir::ItemKind::Use(..) => {}
|
||||
// The interface is empty.
|
||||
hir::ItemKind::GlobalAsm(..) => {}
|
||||
hir::ItemKind::OpaqueTy(..) => {
|
||||
hir::ItemKind::OpaqueTy(ref opaque) => {
|
||||
// HACK(jynelson): trying to infer the type of `impl trait` breaks `async-std` (and `pub async fn` in general)
|
||||
// Since rustdoc never needs to do codegen and doesn't care about link-time reachability,
|
||||
// mark this as unreachable.
|
||||
// See https://github.com/rust-lang/rust/issues/75100
|
||||
if !self.tcx.sess.opts.actually_rustdoc {
|
||||
if !opaque.in_trait && !self.tcx.sess.opts.actually_rustdoc {
|
||||
// FIXME: This is some serious pessimization intended to workaround deficiencies
|
||||
// in the reachability pass (`middle/reachable.rs`). Types are marked as link-time
|
||||
// reachable if they are returned via `impl Trait`, even from private functions.
|
||||
@ -722,9 +721,6 @@ impl<'tcx> Visitor<'tcx> for EmbargoVisitor<'tcx> {
|
||||
self.reach(item.def_id, exist_level).generics().predicates().ty();
|
||||
}
|
||||
}
|
||||
hir::ItemKind::ImplTraitPlaceholder(..) => {
|
||||
// FIXME(RPITIT): Do we need to do anything here?
|
||||
}
|
||||
// Visit everything.
|
||||
hir::ItemKind::Const(..)
|
||||
| hir::ItemKind::Static(..)
|
||||
@ -2039,8 +2035,7 @@ fn local_visibility(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Visibility {
|
||||
// query failing on some items, we provide it for opaque types as well.
|
||||
| Node::Item(hir::Item {
|
||||
kind: hir::ItemKind::Use(_, hir::UseKind::ListStem)
|
||||
| hir::ItemKind::OpaqueTy(..)
|
||||
| hir::ItemKind::ImplTraitPlaceholder(..),
|
||||
| hir::ItemKind::OpaqueTy(..),
|
||||
..
|
||||
}) => ty::Visibility::Restricted(tcx.parent_module(hir_id)),
|
||||
// Visibilities of trait impl items are inherited from their traits
|
||||
|
@ -596,10 +596,6 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
|
||||
}
|
||||
}
|
||||
}
|
||||
hir::ItemKind::ImplTraitPlaceholder(..) => {
|
||||
// FIXME(RPITIT): We don't need to do anything special here, right?
|
||||
intravisit::walk_item(self, item);
|
||||
}
|
||||
hir::ItemKind::TyAlias(_, ref generics)
|
||||
| hir::ItemKind::Enum(_, ref generics)
|
||||
| hir::ItemKind::Struct(_, ref generics)
|
||||
@ -719,7 +715,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
|
||||
};
|
||||
self.with(scope, |this| this.visit_ty(&mt.ty));
|
||||
}
|
||||
hir::TyKind::OpaqueDef(item_id, lifetimes) => {
|
||||
hir::TyKind::OpaqueDef(item_id, lifetimes, _in_trait) => {
|
||||
// Resolve the lifetimes in the bounds to the lifetime defs in the generics.
|
||||
// `fn foo<'a>() -> impl MyTrait<'a> { ... }` desugars to
|
||||
// `type MyAnonTy<'b> = impl MyTrait<'b>;`
|
||||
|
@ -1321,7 +1321,7 @@ impl<'tcx> Visitor<'tcx> for DumpVisitor<'tcx> {
|
||||
}),
|
||||
}
|
||||
}
|
||||
hir::TyKind::OpaqueDef(item_id, _) => {
|
||||
hir::TyKind::OpaqueDef(item_id, _, _) => {
|
||||
let item = self.tcx.hir().item(item_id);
|
||||
self.nest_typeck_results(item_id.def_id, |v| v.visit_item(item));
|
||||
}
|
||||
|
@ -316,11 +316,7 @@ impl<'hir> Sig for hir::Ty<'hir> {
|
||||
let text = format!("[{}; {}]", nested_ty.text, expr);
|
||||
Ok(replace_text(nested_ty, text))
|
||||
}
|
||||
hir::TyKind::OpaqueDef(item_id, _) => {
|
||||
let item = scx.tcx.hir().item(item_id);
|
||||
item.make(offset, Some(item_id.hir_id()), scx)
|
||||
}
|
||||
hir::TyKind::ImplTraitInTrait(item_id) => {
|
||||
hir::TyKind::OpaqueDef(item_id, _, _) => {
|
||||
let item = scx.tcx.hir().item(item_id);
|
||||
item.make(offset, Some(item_id.hir_id()), scx)
|
||||
}
|
||||
@ -565,8 +561,13 @@ impl<'hir> Sig for hir::Item<'hir> {
|
||||
hir::ItemKind::ForeignMod { .. } => Err("extern mod"),
|
||||
hir::ItemKind::GlobalAsm(_) => Err("global asm"),
|
||||
hir::ItemKind::ExternCrate(_) => Err("extern crate"),
|
||||
hir::ItemKind::OpaqueTy(..) => Err("opaque type"),
|
||||
hir::ItemKind::ImplTraitPlaceholder(..) => Err("opaque type in trait"),
|
||||
hir::ItemKind::OpaqueTy(ref opaque) => {
|
||||
if opaque.in_trait {
|
||||
Err("opaque type in trait")
|
||||
} else {
|
||||
Err("opaque type")
|
||||
}
|
||||
}
|
||||
// FIXME should implement this (e.g., pub use).
|
||||
hir::ItemKind::Use(..) => Err("import"),
|
||||
}
|
||||
|
@ -2165,7 +2165,7 @@ fn confirm_impl_trait_in_trait_candidate<'tcx>(
|
||||
let tcx = selcx.tcx();
|
||||
let mut obligations = data.nested;
|
||||
|
||||
let trait_fn_def_id = tcx.parent(obligation.predicate.item_def_id);
|
||||
let trait_fn_def_id = tcx.impl_trait_in_trait_parent(obligation.predicate.item_def_id);
|
||||
let Ok(leaf_def) = assoc_def(selcx, data.impl_def_id, trait_fn_def_id) else {
|
||||
return Progress { term: tcx.ty_error().into(), obligations };
|
||||
};
|
||||
|
@ -2360,7 +2360,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
|
||||
|
||||
let span = path.span;
|
||||
match path.res {
|
||||
Res::Def(DefKind::OpaqueTy, did) => {
|
||||
Res::Def(DefKind::OpaqueTy | DefKind::ImplTraitPlaceholder, did) => {
|
||||
// Check for desugared `impl Trait`.
|
||||
assert!(ty::is_impl_trait_defn(tcx, did).is_none());
|
||||
let item_segment = path.segments.split_last().unwrap();
|
||||
@ -2627,21 +2627,17 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
|
||||
let opt_self_ty = maybe_qself.as_ref().map(|qself| self.ast_ty_to_ty(qself));
|
||||
self.res_to_ty(opt_self_ty, path, false)
|
||||
}
|
||||
hir::TyKind::OpaqueDef(item_id, lifetimes) => {
|
||||
hir::TyKind::OpaqueDef(item_id, lifetimes, in_trait) => {
|
||||
let opaque_ty = tcx.hir().item(item_id);
|
||||
let def_id = item_id.def_id.to_def_id();
|
||||
|
||||
match opaque_ty.kind {
|
||||
hir::ItemKind::OpaqueTy(hir::OpaqueTy { origin, .. }) => {
|
||||
self.impl_trait_ty_to_ty(def_id, lifetimes, origin)
|
||||
self.impl_trait_ty_to_ty(def_id, lifetimes, origin, in_trait)
|
||||
}
|
||||
ref i => bug!("`impl Trait` pointed to non-opaque type?? {:#?}", i),
|
||||
}
|
||||
}
|
||||
hir::TyKind::ImplTraitInTrait(item_id) => {
|
||||
let def_id = item_id.def_id.to_def_id();
|
||||
tcx.mk_projection(def_id, InternalSubsts::identity_for_item(tcx, def_id))
|
||||
}
|
||||
hir::TyKind::Path(hir::QPath::TypeRelative(ref qself, ref segment)) => {
|
||||
debug!(?qself, ?segment);
|
||||
let ty = self.ast_ty_to_ty_inner(qself, false, true);
|
||||
@ -2707,6 +2703,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
|
||||
def_id: DefId,
|
||||
lifetimes: &[hir::GenericArg<'_>],
|
||||
origin: OpaqueTyOrigin,
|
||||
in_trait: bool,
|
||||
) -> Ty<'tcx> {
|
||||
debug!("impl_trait_ty_to_ty(def_id={:?}, lifetimes={:?})", def_id, lifetimes);
|
||||
let tcx = self.tcx();
|
||||
@ -2750,7 +2747,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
|
||||
});
|
||||
debug!("impl_trait_ty_to_ty: substs={:?}", substs);
|
||||
|
||||
tcx.mk_opaque(def_id, substs)
|
||||
if in_trait { tcx.mk_projection(def_id, substs) } else { tcx.mk_opaque(def_id, substs) }
|
||||
}
|
||||
|
||||
pub fn ty_of_arg(&self, ty: &hir::Ty<'_>, expected_ty: Option<Ty<'tcx>>) -> Ty<'tcx> {
|
||||
|
@ -423,9 +423,28 @@ pub(super) fn compare_predicates_and_trait_impl_trait_tys<'tcx>(
|
||||
);
|
||||
|
||||
let mut collected_tys = FxHashMap::default();
|
||||
for (def_id, ty) in collector.types {
|
||||
for (def_id, (ty, substs)) in collector.types {
|
||||
match infcx.fully_resolve(ty) {
|
||||
Ok(ty) => {
|
||||
// `ty` contains free regions that we created earlier while liberating the
|
||||
// trait fn signature. However, projection normalization expects `ty` to
|
||||
// contains `def_id`'s early-bound regions.
|
||||
let id_substs = InternalSubsts::identity_for_item(tcx, def_id);
|
||||
debug!(?id_substs, ?substs);
|
||||
let map: FxHashMap<ty::GenericArg<'tcx>, ty::GenericArg<'tcx>> = substs
|
||||
.iter()
|
||||
.enumerate()
|
||||
.map(|(index, arg)| (arg, id_substs[index]))
|
||||
.collect();
|
||||
debug!(?map);
|
||||
|
||||
let ty = tcx.fold_regions(ty, |region, _| {
|
||||
if let ty::ReFree(_) = region.kind() {
|
||||
map[®ion.into()].expect_region()
|
||||
} else {
|
||||
region
|
||||
}
|
||||
});
|
||||
collected_tys.insert(def_id, ty);
|
||||
}
|
||||
Err(err) => {
|
||||
@ -444,7 +463,7 @@ pub(super) fn compare_predicates_and_trait_impl_trait_tys<'tcx>(
|
||||
|
||||
struct ImplTraitInTraitCollector<'a, 'tcx> {
|
||||
ocx: &'a ObligationCtxt<'a, 'tcx>,
|
||||
types: FxHashMap<DefId, Ty<'tcx>>,
|
||||
types: FxHashMap<DefId, (Ty<'tcx>, ty::SubstsRef<'tcx>)>,
|
||||
span: Span,
|
||||
param_env: ty::ParamEnv<'tcx>,
|
||||
body_id: hir::HirId,
|
||||
@ -470,7 +489,7 @@ impl<'tcx> TypeFolder<'tcx> for ImplTraitInTraitCollector<'_, 'tcx> {
|
||||
if let ty::Projection(proj) = ty.kind()
|
||||
&& self.tcx().def_kind(proj.item_def_id) == DefKind::ImplTraitPlaceholder
|
||||
{
|
||||
if let Some(ty) = self.types.get(&proj.item_def_id) {
|
||||
if let Some((ty, _)) = self.types.get(&proj.item_def_id) {
|
||||
return *ty;
|
||||
}
|
||||
//FIXME(RPITIT): Deny nested RPITIT in substs too
|
||||
@ -482,7 +501,7 @@ impl<'tcx> TypeFolder<'tcx> for ImplTraitInTraitCollector<'_, 'tcx> {
|
||||
span: self.span,
|
||||
kind: TypeVariableOriginKind::MiscVariable,
|
||||
});
|
||||
self.types.insert(proj.item_def_id, infer_ty);
|
||||
self.types.insert(proj.item_def_id, (infer_ty, proj.substs));
|
||||
// Recurse into bounds
|
||||
for pred in self.tcx().bound_explicit_item_bounds(proj.item_def_id).transpose_iter() {
|
||||
let pred_span = pred.0.1;
|
||||
|
@ -815,11 +815,6 @@ fn convert_item(tcx: TyCtxt<'_>, item_id: hir::ItemId) {
|
||||
tcx.ensure().predicates_of(def_id);
|
||||
tcx.ensure().explicit_item_bounds(def_id);
|
||||
}
|
||||
hir::ItemKind::ImplTraitPlaceholder(..) => {
|
||||
tcx.ensure().generics_of(def_id);
|
||||
tcx.ensure().predicates_of(def_id);
|
||||
tcx.ensure().explicit_item_bounds(def_id);
|
||||
}
|
||||
hir::ItemKind::TyAlias(..)
|
||||
| hir::ItemKind::Static(..)
|
||||
| hir::ItemKind::Const(..)
|
||||
@ -1590,8 +1585,16 @@ fn generics_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::Generics {
|
||||
ItemKind::OpaqueTy(hir::OpaqueTy {
|
||||
origin:
|
||||
hir::OpaqueTyOrigin::FnReturn(fn_def_id) | hir::OpaqueTyOrigin::AsyncFn(fn_def_id),
|
||||
in_trait,
|
||||
..
|
||||
}) => Some(fn_def_id.to_def_id()),
|
||||
}) => {
|
||||
if in_trait {
|
||||
assert!(matches!(tcx.def_kind(fn_def_id), DefKind::AssocFn))
|
||||
} else {
|
||||
assert!(matches!(tcx.def_kind(fn_def_id), DefKind::AssocFn | DefKind::Fn))
|
||||
}
|
||||
Some(fn_def_id.to_def_id())
|
||||
}
|
||||
ItemKind::OpaqueTy(hir::OpaqueTy { origin: hir::OpaqueTyOrigin::TyAlias, .. }) => {
|
||||
let parent_id = tcx.hir().get_parent_item(hir_id);
|
||||
assert_ne!(parent_id, CRATE_DEF_ID);
|
||||
@ -1600,14 +1603,6 @@ fn generics_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::Generics {
|
||||
// inherit the generics of the item.
|
||||
Some(parent_id.to_def_id())
|
||||
}
|
||||
ItemKind::ImplTraitPlaceholder(_) => {
|
||||
let parent_id = tcx.hir().get_parent_item(hir_id).to_def_id();
|
||||
assert!(matches!(
|
||||
tcx.def_kind(parent_id),
|
||||
DefKind::AssocFn | DefKind::ImplTraitPlaceholder
|
||||
));
|
||||
Some(parent_id)
|
||||
}
|
||||
_ => None,
|
||||
},
|
||||
_ => None,
|
||||
@ -1800,7 +1795,7 @@ fn is_suggestable_infer_ty(ty: &hir::Ty<'_>) -> bool {
|
||||
}
|
||||
Tup(tys) => tys.iter().any(is_suggestable_infer_ty),
|
||||
Ptr(mut_ty) | Rptr(_, mut_ty) => is_suggestable_infer_ty(mut_ty.ty),
|
||||
OpaqueDef(_, generic_args) => are_suggestable_generic_args(generic_args),
|
||||
OpaqueDef(_, generic_args, _) => are_suggestable_generic_args(generic_args),
|
||||
Path(hir::QPath::TypeRelative(ty, segment)) => {
|
||||
is_suggestable_infer_ty(ty) || are_suggestable_generic_args(segment.args().args)
|
||||
}
|
||||
|
@ -59,10 +59,15 @@ fn opaque_type_bounds<'tcx>(
|
||||
opaque_def_id: DefId,
|
||||
ast_bounds: &'tcx [hir::GenericBound<'tcx>],
|
||||
span: Span,
|
||||
in_trait: bool,
|
||||
) -> &'tcx [(ty::Predicate<'tcx>, Span)] {
|
||||
ty::print::with_no_queries!({
|
||||
let item_ty =
|
||||
tcx.mk_opaque(opaque_def_id, InternalSubsts::identity_for_item(tcx, opaque_def_id));
|
||||
let substs = InternalSubsts::identity_for_item(tcx, opaque_def_id);
|
||||
let item_ty = if in_trait {
|
||||
tcx.mk_projection(opaque_def_id, substs)
|
||||
} else {
|
||||
tcx.mk_opaque(opaque_def_id, substs)
|
||||
};
|
||||
|
||||
let icx = ItemCtxt::new(tcx, opaque_def_id);
|
||||
let mut bounds = <dyn AstConv<'_>>::compute_bounds(&icx, item_ty, ast_bounds);
|
||||
@ -74,29 +79,6 @@ fn opaque_type_bounds<'tcx>(
|
||||
})
|
||||
}
|
||||
|
||||
/// Opaque types don't inherit bounds from their parent: for return position
|
||||
/// impl trait it isn't possible to write a suitable predicate on the
|
||||
/// containing function and for type-alias impl trait we don't have a backwards
|
||||
/// compatibility issue.
|
||||
fn impl_trait_in_trait_item_bounds<'tcx>(
|
||||
tcx: TyCtxt<'tcx>,
|
||||
opaque_def_id: DefId,
|
||||
ast_bounds: &'tcx [hir::GenericBound<'tcx>],
|
||||
span: Span,
|
||||
) -> &'tcx [(ty::Predicate<'tcx>, Span)] {
|
||||
ty::print::with_no_queries!({
|
||||
// FIXME(RPITIT): DRY-er code please
|
||||
let item_ty =
|
||||
tcx.mk_projection(opaque_def_id, InternalSubsts::identity_for_item(tcx, opaque_def_id));
|
||||
|
||||
let icx = ItemCtxt::new(tcx, opaque_def_id);
|
||||
let mut bounds = <dyn AstConv<'_>>::compute_bounds(&icx, item_ty, ast_bounds);
|
||||
// RPITITs are implicitly sized unless a `?Sized` bound is found
|
||||
<dyn AstConv<'_>>::add_implicitly_sized(&icx, &mut bounds, ast_bounds, None, span);
|
||||
tcx.arena.alloc_from_iter(bounds.predicates(tcx, item_ty))
|
||||
})
|
||||
}
|
||||
|
||||
pub(super) fn explicit_item_bounds(
|
||||
tcx: TyCtxt<'_>,
|
||||
def_id: DefId,
|
||||
@ -109,15 +91,10 @@ pub(super) fn explicit_item_bounds(
|
||||
..
|
||||
}) => associated_type_bounds(tcx, def_id, bounds, *span),
|
||||
hir::Node::Item(hir::Item {
|
||||
kind: hir::ItemKind::OpaqueTy(hir::OpaqueTy { bounds, .. }),
|
||||
kind: hir::ItemKind::OpaqueTy(hir::OpaqueTy { bounds, in_trait, .. }),
|
||||
span,
|
||||
..
|
||||
}) => opaque_type_bounds(tcx, def_id, bounds, *span),
|
||||
hir::Node::Item(hir::Item {
|
||||
kind: hir::ItemKind::ImplTraitPlaceholder(hir::ImplTraitPlaceholder { bounds }),
|
||||
span,
|
||||
..
|
||||
}) => impl_trait_in_trait_item_bounds(tcx, def_id, bounds, *span),
|
||||
}) => opaque_type_bounds(tcx, def_id, bounds, *span, *in_trait),
|
||||
_ => bug!("item_bounds called on {:?}", def_id),
|
||||
}
|
||||
}
|
||||
|
@ -333,11 +333,12 @@ pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: DefId) -> Ty<'_> {
|
||||
find_opaque_ty_constraints_for_tait(tcx, def_id)
|
||||
}
|
||||
// Opaque types desugared from `impl Trait`.
|
||||
ItemKind::OpaqueTy(OpaqueTy { origin: hir::OpaqueTyOrigin::FnReturn(owner) | hir::OpaqueTyOrigin::AsyncFn(owner), .. }) => {
|
||||
find_opaque_ty_constraints_for_rpit(tcx, def_id, owner)
|
||||
}
|
||||
ItemKind::ImplTraitPlaceholder(..) => {
|
||||
span_bug!(item.span, "not yet implemented")
|
||||
ItemKind::OpaqueTy(OpaqueTy { origin: hir::OpaqueTyOrigin::FnReturn(owner) | hir::OpaqueTyOrigin::AsyncFn(owner), in_trait, .. }) => {
|
||||
if in_trait {
|
||||
span_bug!(item.span, "impl-trait in trait has no default")
|
||||
} else {
|
||||
find_opaque_ty_constraints_for_rpit(tcx, def_id, owner)
|
||||
}
|
||||
}
|
||||
ItemKind::Trait(..)
|
||||
| ItemKind::TraitAlias(..)
|
||||
|
@ -1492,7 +1492,7 @@ pub(crate) fn clean_ty<'tcx>(ty: &hir::Ty<'tcx>, cx: &mut DocContext<'tcx>) -> T
|
||||
Array(Box::new(clean_ty(ty, cx)), length)
|
||||
}
|
||||
TyKind::Tup(tys) => Tuple(tys.iter().map(|ty| clean_ty(ty, cx)).collect()),
|
||||
TyKind::OpaqueDef(item_id, _) => {
|
||||
TyKind::OpaqueDef(item_id, _, _) => {
|
||||
let item = cx.tcx.hir().item(item_id);
|
||||
if let hir::ItemKind::OpaqueTy(ref ty) = item.kind {
|
||||
ImplTrait(ty.bounds.iter().filter_map(|x| clean_generic_bound(x, cx)).collect())
|
||||
@ -1500,16 +1500,6 @@ pub(crate) fn clean_ty<'tcx>(ty: &hir::Ty<'tcx>, cx: &mut DocContext<'tcx>) -> T
|
||||
unreachable!()
|
||||
}
|
||||
}
|
||||
TyKind::ImplTraitInTrait(item_id) => {
|
||||
let item = cx.tcx.hir().item(item_id);
|
||||
if let hir::ItemKind::ImplTraitPlaceholder(hir::ImplTraitPlaceholder { bounds }) =
|
||||
item.kind
|
||||
{
|
||||
ImplTrait(bounds.iter().filter_map(|x| clean_generic_bound(x, cx)).collect())
|
||||
} else {
|
||||
unreachable!()
|
||||
}
|
||||
}
|
||||
TyKind::Path(_) => clean_qpath(ty, cx),
|
||||
TyKind::TraitObject(bounds, ref lifetime, _) => {
|
||||
let bounds = bounds.iter().map(|bound| clean_poly_trait_ref(bound, cx)).collect();
|
||||
|
@ -362,7 +362,6 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
|
||||
| hir::ItemKind::Union(..)
|
||||
| hir::ItemKind::TyAlias(..)
|
||||
| hir::ItemKind::OpaqueTy(..)
|
||||
| hir::ItemKind::ImplTraitPlaceholder(..)
|
||||
| hir::ItemKind::Static(..)
|
||||
| hir::ItemKind::Trait(..)
|
||||
| hir::ItemKind::TraitAlias(..) => om.items.push((item, renamed)),
|
||||
|
@ -3,18 +3,46 @@
|
||||
#![feature(return_position_impl_trait_in_trait)]
|
||||
#![allow(incomplete_features)]
|
||||
|
||||
use std::fmt::Display;
|
||||
use std::fmt::Debug;
|
||||
|
||||
trait Foo {
|
||||
fn bar(&self) -> impl Display;
|
||||
fn foo(&self) -> impl Debug;
|
||||
}
|
||||
|
||||
impl Foo for () {
|
||||
fn bar(&self) -> impl Display {
|
||||
fn foo(&self) -> impl Debug {
|
||||
"Hello, world"
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {
|
||||
println!("{}", ().bar());
|
||||
impl<T: Default + Debug> Foo for std::marker::PhantomData<T> {
|
||||
fn foo(&self) -> impl Debug {
|
||||
T::default()
|
||||
}
|
||||
}
|
||||
|
||||
trait Bar {
|
||||
fn bar<T>(&self) -> impl Debug;
|
||||
}
|
||||
|
||||
impl Bar for () {
|
||||
fn bar<T>(&self) -> impl Debug {
|
||||
format!("Hello with generic {}", std::any::type_name::<T>())
|
||||
}
|
||||
}
|
||||
|
||||
trait Baz {
|
||||
fn baz(&self) -> impl Debug + '_;
|
||||
}
|
||||
|
||||
impl Baz for String {
|
||||
fn baz(&self) -> impl Debug + '_ {
|
||||
(self,)
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {
|
||||
println!("{:?}", ().foo());
|
||||
println!("{:?}", ().bar::<u64>());
|
||||
println!("{:?}", "hi".to_string().baz());
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user