Skip to content

Commit

Permalink
Auto merge of #101224 - compiler-errors:rpitit, r=oli-obk
Browse files Browse the repository at this point in the history
Initial implementation of return-position `impl Trait` in traits

* Create a new item kind, called `ImplTraitPlaceholder`, which is used to lower `ast::TyKind::ImplTrait` in trait method returns.
    * This item is the child of the trait method, which simplifies the way we calculate bounds and stuff.
* Use the def-id of this type to construct a projection type that we use during astconv for the return type of the trait method signature.
* Implement logic to normalize this `ImplTraitPlaceholder` projection type when we know its concrete impl (this is pretty limited currently, but really there are no other selection candidates that make sense -- for now!)
* Check that the `impl Trait`'s bounds are satisfied on the concrete type provided in the impl.

This is obviously nowhere near complete, but I wanted to at least get some initial support landed so we can start playing around with it.

What works:
* async fn in trait and RPITIT, including multiple `impl Trait`s and `impl Trait` nested in associated type bindings, like `impl Future<Output = impl Sized>`
  • Loading branch information
bors committed Sep 9, 2022
2 parents 7200da0 + 6876c94 commit ab32548
Show file tree
Hide file tree
Showing 80 changed files with 1,078 additions and 304 deletions.
4 changes: 2 additions & 2 deletions compiler/rustc_ast/src/ast.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2367,9 +2367,9 @@ impl Async {
}

/// In this case this is an `async` return, the `NodeId` for the generated `impl Trait` item.
pub fn opt_return_id(self) -> Option<NodeId> {
pub fn opt_return_id(self) -> Option<(NodeId, Span)> {
match self {
Async::Yes { return_impl_trait_id, .. } => Some(return_impl_trait_id),
Async::Yes { return_impl_trait_id, span, .. } => Some((return_impl_trait_id, span)),
Async::No => None,
}
}
Expand Down
11 changes: 11 additions & 0 deletions compiler/rustc_ast_lowering/src/errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -334,3 +334,14 @@ pub struct InclusiveRangeWithNoEnd {
#[primary_span]
pub span: Span,
}

#[derive(SessionDiagnostic, Clone, Copy)]
#[diag(ast_lowering::trait_fn_async, code = "E0706")]
#[note]
#[note(ast_lowering::note2)]
pub struct TraitFnAsync {
#[primary_span]
pub fn_span: Span,
#[label]
pub span: Span,
}
5 changes: 3 additions & 2 deletions compiler/rustc_ast_lowering/src/expr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -851,7 +851,7 @@ impl<'hir> LoweringContext<'_, 'hir> {

self.lower_lifetime_binder(closure_id, generic_params, |lctx, bound_generic_params| {
// Lower outside new scope to preserve `is_in_loop_condition`.
let fn_decl = lctx.lower_fn_decl(decl, None, FnDeclKind::Closure, None);
let fn_decl = lctx.lower_fn_decl(decl, None, fn_decl_span, FnDeclKind::Closure, None);

let c = lctx.arena.alloc(hir::Closure {
binder: binder_clause,
Expand Down Expand Up @@ -955,7 +955,8 @@ impl<'hir> LoweringContext<'_, 'hir> {
// We need to lower the declaration outside the new scope, because we
// have to conserve the state of being inside a loop condition for the
// closure argument types.
let fn_decl = lctx.lower_fn_decl(&outer_decl, None, FnDeclKind::Closure, None);
let fn_decl =
lctx.lower_fn_decl(&outer_decl, None, fn_decl_span, FnDeclKind::Closure, None);

let c = lctx.arena.alloc(hir::Closure {
binder: binder_clause,
Expand Down
24 changes: 18 additions & 6 deletions compiler/rustc_ast_lowering/src/item.rs
Original file line number Diff line number Diff line change
Expand Up @@ -269,7 +269,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
let mut itctx = ImplTraitContext::Universal;
let (generics, decl) = this.lower_generics(generics, id, &mut itctx, |this| {
let ret_id = asyncness.opt_return_id();
this.lower_fn_decl(&decl, Some(id), FnDeclKind::Fn, ret_id)
this.lower_fn_decl(&decl, Some(id), fn_sig_span, FnDeclKind::Fn, ret_id)
});
let sig = hir::FnSig {
decl,
Expand Down Expand Up @@ -661,7 +661,13 @@ impl<'hir> LoweringContext<'_, 'hir> {
self.lower_generics(generics, i.id, &mut itctx, |this| {
(
// Disallow `impl Trait` in foreign items.
this.lower_fn_decl(fdec, None, FnDeclKind::ExternFn, None),
this.lower_fn_decl(
fdec,
None,
sig.span,
FnDeclKind::ExternFn,
None,
),
this.lower_fn_params_to_names(fdec),
)
});
Expand Down Expand Up @@ -771,9 +777,15 @@ impl<'hir> LoweringContext<'_, 'hir> {
(hir::Generics::empty(), hir::TraitItemKind::Const(ty, body), body.is_some())
}
AssocItemKind::Fn(box Fn { ref sig, ref generics, body: None, .. }) => {
let asyncness = sig.header.asyncness;
let names = self.lower_fn_params_to_names(&sig.decl);
let (generics, sig) =
self.lower_method_sig(generics, sig, i.id, FnDeclKind::Trait, None);
let (generics, sig) = self.lower_method_sig(
generics,
sig,
i.id,
FnDeclKind::Trait,
asyncness.opt_return_id(),
);
(generics, hir::TraitItemKind::Fn(sig, hir::TraitFn::Required(names)), false)
}
AssocItemKind::Fn(box Fn { ref sig, ref generics, body: Some(ref body), .. }) => {
Expand Down Expand Up @@ -1240,12 +1252,12 @@ impl<'hir> LoweringContext<'_, 'hir> {
sig: &FnSig,
id: NodeId,
kind: FnDeclKind,
is_async: Option<NodeId>,
is_async: Option<(NodeId, Span)>,
) -> (&'hir hir::Generics<'hir>, hir::FnSig<'hir>) {
let header = self.lower_fn_header(sig.header);
let mut itctx = ImplTraitContext::Universal;
let (generics, decl) = self.lower_generics(generics, id, &mut itctx, |this| {
this.lower_fn_decl(&sig.decl, Some(id), kind, is_async)
this.lower_fn_decl(&sig.decl, Some(id), sig.span, kind, is_async)
});
(generics, hir::FnSig { header, decl, span: self.lower_span(sig.span) })
}
Expand Down
Loading

0 comments on commit ab32548

Please sign in to comment.