diff --git a/compiler/rustc_ast/src/ast.rs b/compiler/rustc_ast/src/ast.rs index e38572f609b31..c07ba88ae204d 100644 --- a/compiler/rustc_ast/src/ast.rs +++ b/compiler/rustc_ast/src/ast.rs @@ -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 { + 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, } } diff --git a/compiler/rustc_ast_lowering/src/errors.rs b/compiler/rustc_ast_lowering/src/errors.rs index 4adeaef9bbfa8..c87d0ca96570e 100644 --- a/compiler/rustc_ast_lowering/src/errors.rs +++ b/compiler/rustc_ast_lowering/src/errors.rs @@ -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, +} diff --git a/compiler/rustc_ast_lowering/src/expr.rs b/compiler/rustc_ast_lowering/src/expr.rs index 5346f1ced8294..f929549d70448 100644 --- a/compiler/rustc_ast_lowering/src/expr.rs +++ b/compiler/rustc_ast_lowering/src/expr.rs @@ -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, @@ -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, diff --git a/compiler/rustc_ast_lowering/src/item.rs b/compiler/rustc_ast_lowering/src/item.rs index 9e05fbbdc1976..52273778dcc00 100644 --- a/compiler/rustc_ast_lowering/src/item.rs +++ b/compiler/rustc_ast_lowering/src/item.rs @@ -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, @@ -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), ) }); @@ -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), .. }) => { @@ -1240,12 +1252,12 @@ impl<'hir> LoweringContext<'_, 'hir> { sig: &FnSig, id: NodeId, kind: FnDeclKind, - is_async: Option, + 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) }) } diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs index f57c92fd70c27..0720f23ed756d 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs @@ -42,7 +42,7 @@ #[macro_use] extern crate tracing; -use crate::errors::{AssocTyParentheses, AssocTyParenthesesSub, MisplacedImplTrait}; +use crate::errors::{AssocTyParentheses, AssocTyParenthesesSub, MisplacedImplTrait, TraitFnAsync}; use rustc_arena::declare_arena; use rustc_ast::ptr::P; @@ -252,6 +252,7 @@ enum ImplTraitContext { ReturnPositionOpaqueTy { /// Origin: Either OpaqueTyOrigin::FnReturn or OpaqueTyOrigin::AsyncFn, origin: hir::OpaqueTyOrigin, + in_trait: bool, }, /// Impl trait in type aliases. TypeAliasesOpaqueTy, @@ -311,7 +312,7 @@ impl std::fmt::Display for ImplTraitPosition { } } -#[derive(Debug)] +#[derive(Debug, PartialEq, Eq)] enum FnDeclKind { Fn, Inherent, @@ -323,9 +324,17 @@ enum FnDeclKind { } impl FnDeclKind { - fn impl_trait_return_allowed(&self) -> bool { + fn impl_trait_return_allowed(&self, tcx: TyCtxt<'_>) -> bool { match self { FnDeclKind::Fn | FnDeclKind::Inherent => true, + FnDeclKind::Impl if tcx.features().return_position_impl_trait_in_trait => true, + _ => false, + } + } + + fn impl_trait_in_trait_allowed(&self, tcx: TyCtxt<'_>) -> bool { + match self { + FnDeclKind::Trait if tcx.features().return_position_impl_trait_in_trait => true, _ => false, } } @@ -1264,7 +1273,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { generic_params, unsafety: lctx.lower_unsafety(f.unsafety), abi: lctx.lower_extern(f.ext), - decl: lctx.lower_fn_decl(&f.decl, None, FnDeclKind::Pointer, None), + decl: lctx.lower_fn_decl(&f.decl, None, t.span, FnDeclKind::Pointer, None), param_names: lctx.lower_fn_params_to_names(&f.decl), })) }) @@ -1333,19 +1342,23 @@ 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::TypeAliasesOpaqueTy => { - let mut nested_itctx = ImplTraitContext::TypeAliasesOpaqueTy; - self.lower_opaque_impl_trait( + ImplTraitContext::ReturnPositionOpaqueTy { origin, in_trait } => self + .lower_opaque_impl_trait( span, - hir::OpaqueTyOrigin::TyAlias, + *origin, def_node_id, bounds, - &mut nested_itctx, - ) - } + *in_trait, + itctx, + ), + ImplTraitContext::TypeAliasesOpaqueTy => self.lower_opaque_impl_trait( + span, + hir::OpaqueTyOrigin::TyAlias, + def_node_id, + bounds, + false, + &mut ImplTraitContext::TypeAliasesOpaqueTy, + ), ImplTraitContext::Universal => { let span = t.span; let ident = Ident::from_str_and_span(&pprust::ty_to_string(t), span); @@ -1357,6 +1370,21 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { } path } + ImplTraitContext::Disallowed( + position @ (ImplTraitPosition::TraitReturn | ImplTraitPosition::ImplReturn), + ) => { + self.tcx + .sess + .create_feature_err( + MisplacedImplTrait { + span: t.span, + position: DiagnosticArgFromDisplay(&position), + }, + sym::return_position_impl_trait_in_trait, + ) + .emit(); + hir::TyKind::Err + } ImplTraitContext::Disallowed(position) => { self.tcx.sess.emit_err(MisplacedImplTrait { span: t.span, @@ -1415,6 +1443,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. @@ -1503,6 +1532,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { }), bounds: hir_bounds, origin, + in_trait, }; debug!(?opaque_ty_item); @@ -1529,7 +1559,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) + 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 @@ -1637,19 +1667,17 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { // `fn_def_id`: if `Some`, impl Trait arguments are lowered into generic parameters on the // given DefId, otherwise impl Trait is disallowed. Must be `Some` if // `make_ret_async` is also `Some`. - // `impl_trait_return_allow`: determines whether `impl Trait` can be used in return position. - // This guards against trait declarations and implementations where `impl Trait` is - // disallowed. // `make_ret_async`: if `Some`, converts `-> T` into `-> impl Future` in the // return type. This is used for `async fn` declarations. The `NodeId` is the ID of the - // return type `impl Trait` item. + // return type `impl Trait` item, and the `Span` points to the `async` keyword. #[instrument(level = "debug", skip(self))] fn lower_fn_decl( &mut self, decl: &FnDecl, fn_node_id: Option, + fn_span: Span, kind: FnDeclKind, - make_ret_async: Option, + make_ret_async: Option<(NodeId, Span)>, ) -> &'hir hir::FnDecl<'hir> { let c_variadic = decl.c_variadic(); @@ -1680,20 +1708,63 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { } })); - let output = if let Some(ret_id) = make_ret_async { - self.lower_async_fn_ret_ty( - &decl.output, - fn_node_id.expect("`make_ret_async` but no `fn_def_id`"), - ret_id, - ) + let output = if let Some((ret_id, span)) = make_ret_async { + match kind { + FnDeclKind::Trait => { + if !kind.impl_trait_in_trait_allowed(self.tcx) { + 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, + 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.lower_async_fn_ret_ty( + &decl.output, + fn_node_id.expect("`make_ret_async` but no `fn_def_id`"), + ret_id, + false, + ) + } + } } else { match decl.output { FnRetTy::Ty(ref ty) => { let mut context = match fn_node_id { - Some(fn_node_id) if kind.impl_trait_return_allowed() => { + Some(fn_node_id) if kind.impl_trait_return_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: false, + } + } + 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 { @@ -1757,6 +1828,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(); @@ -1883,8 +1955,14 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { // // Then, we will create `fn foo(..) -> Foo<'_, '_>`, and // hence the elision takes place at the fn site. - let future_bound = - this.lower_async_fn_output_type_to_future_bound(output, fn_def_id, span); + let future_bound = this.lower_async_fn_output_type_to_future_bound( + output, + span, + ImplTraitContext::ReturnPositionOpaqueTy { + origin: hir::OpaqueTyOrigin::FnReturn(fn_def_id), + in_trait, + }, + ); let generic_params = this.arena.alloc_from_iter(collected_lifetimes.iter().map( |&(new_node_id, lifetime, _)| { @@ -1922,6 +2000,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); @@ -1966,8 +2045,11 @@ 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)) } @@ -1976,8 +2058,8 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { fn lower_async_fn_output_type_to_future_bound( &mut self, output: &FnRetTy, - fn_def_id: LocalDefId, span: Span, + mut nested_impl_trait_context: ImplTraitContext, ) -> hir::GenericBound<'hir> { // Compute the `T` in `Future` from the return type. let output_ty = match output { @@ -1985,10 +2067,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { // Not `OpaqueTyOrigin::AsyncFn`: that's only used for the // `impl Future` opaque type that `async fn` implicitly // generates. - let mut context = ImplTraitContext::ReturnPositionOpaqueTy { - origin: hir::OpaqueTyOrigin::FnReturn(fn_def_id), - }; - self.lower_ty(ty, &mut context) + self.lower_ty(ty, &mut nested_impl_trait_context) } FnRetTy::Default(ret_ty_span) => self.arena.alloc(self.ty_tup(*ret_ty_span, &[])), }; diff --git a/compiler/rustc_ast_passes/src/ast_validation.rs b/compiler/rustc_ast_passes/src/ast_validation.rs index d6d8881a53a14..6c754f38d144b 100644 --- a/compiler/rustc_ast_passes/src/ast_validation.rs +++ b/compiler/rustc_ast_passes/src/ast_validation.rs @@ -290,12 +290,6 @@ impl<'a> AstValidator<'a> { } } - fn check_trait_fn_not_async(&self, fn_span: Span, asyncness: Async) { - if let Async::Yes { span, .. } = asyncness { - self.session.emit_err(TraitFnAsync { fn_span, span }); - } - } - fn check_trait_fn_not_const(&self, constness: Const) { if let Const::Yes(span) = constness { self.session.emit_err(TraitFnConst { span }); @@ -1596,7 +1590,6 @@ impl<'a> Visitor<'a> for AstValidator<'a> { self.invalid_visibility(&item.vis, None); if let AssocItemKind::Fn(box Fn { sig, .. }) = &item.kind { self.check_trait_fn_not_const(sig.header.constness); - self.check_trait_fn_not_async(item.span, sig.header.asyncness); } } diff --git a/compiler/rustc_ast_passes/src/errors.rs b/compiler/rustc_ast_passes/src/errors.rs index 21467e5765198..4f3b09c587113 100644 --- a/compiler/rustc_ast_passes/src/errors.rs +++ b/compiler/rustc_ast_passes/src/errors.rs @@ -79,17 +79,6 @@ pub enum InvalidVisibilityNote { IndividualForeignItems, } -#[derive(SessionDiagnostic)] -#[diag(ast_passes::trait_fn_async, code = "E0706")] -#[note] -#[note(ast_passes::note2)] -pub struct TraitFnAsync { - #[primary_span] - pub fn_span: Span, - #[label] - pub span: Span, -} - #[derive(SessionDiagnostic)] #[diag(ast_passes::trait_fn_const, code = "E0379")] pub struct TraitFnConst { diff --git a/compiler/rustc_borrowck/src/diagnostics/region_name.rs b/compiler/rustc_borrowck/src/diagnostics/region_name.rs index 75fde53b6cdec..0707ff5ed02a0 100644 --- a/compiler/rustc_borrowck/src/diagnostics/region_name.rs +++ b/compiler/rustc_borrowck/src/diagnostics/region_name.rs @@ -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: {:?}", diff --git a/compiler/rustc_error_messages/locales/en-US/ast_lowering.ftl b/compiler/rustc_error_messages/locales/en-US/ast_lowering.ftl index f2790531aba44..c45e045b4dba0 100644 --- a/compiler/rustc_error_messages/locales/en-US/ast_lowering.ftl +++ b/compiler/rustc_error_messages/locales/en-US/ast_lowering.ftl @@ -131,3 +131,9 @@ ast_lowering_arbitrary_expression_in_pattern = arbitrary expressions aren't allowed in patterns ast_lowering_inclusive_range_with_no_end = inclusive range with no end + +ast_lowering_trait_fn_async = + functions in traits cannot be declared `async` + .label = `async` because of this + .note = `async` trait functions are not currently supported + .note2 = consider using the `async-trait` crate: https://crates.io/crates/async-trait diff --git a/compiler/rustc_error_messages/locales/en-US/ast_passes.ftl b/compiler/rustc_error_messages/locales/en-US/ast_passes.ftl index d7108e1e2de35..e5cd1142b20c8 100644 --- a/compiler/rustc_error_messages/locales/en-US/ast_passes.ftl +++ b/compiler/rustc_error_messages/locales/en-US/ast_passes.ftl @@ -26,12 +26,6 @@ ast_passes_invalid_visibility = .individual_impl_items = place qualifiers on individual impl items instead .individual_foreign_items = place qualifiers on individual foreign items instead -ast_passes_trait_fn_async = - functions in traits cannot be declared `async` - .label = `async` because of this - .note = `async` trait functions are not currently supported - .note2 = consider using the `async-trait` crate: https://crates.io/crates/async-trait - ast_passes_trait_fn_const = functions in traits cannot be declared const .label = functions in traits cannot be const diff --git a/compiler/rustc_feature/src/active.rs b/compiler/rustc_feature/src/active.rs index f71b3d59e2c04..3b8032040e76c 100644 --- a/compiler/rustc_feature/src/active.rs +++ b/compiler/rustc_feature/src/active.rs @@ -487,6 +487,8 @@ declare_features! ( (incomplete, repr128, "1.16.0", Some(56071), None), /// Allows `repr(simd)` and importing the various simd intrinsics. (active, repr_simd, "1.4.0", Some(27731), None), + /// Allows return-position `impl Trait` in traits. + (incomplete, return_position_impl_trait_in_trait, "CURRENT_RUSTC_VERSION", Some(91611), None), /// Allows `extern "rust-cold"`. (active, rust_cold_cc, "1.63.0", Some(97544), None), /// Allows the use of SIMD types in functions declared in `extern` blocks. diff --git a/compiler/rustc_hir/src/def.rs b/compiler/rustc_hir/src/def.rs index b44ee02cfe3bb..e7c26bd726fbf 100644 --- a/compiler/rustc_hir/src/def.rs +++ b/compiler/rustc_hir/src/def.rs @@ -109,6 +109,8 @@ pub enum DefKind { InlineConst, /// Opaque type, aka `impl Trait`. OpaqueTy, + /// A return-position `impl Trait` in a trait definition + ImplTraitPlaceholder, Field, /// Lifetime parameter: the `'a` in `struct Foo<'a> { ... }` LifetimeParam, @@ -138,6 +140,7 @@ impl DefKind { panic!("impossible struct constructor") } DefKind::OpaqueTy => "opaque type", + DefKind::ImplTraitPlaceholder => "opaque type in trait", DefKind::TyAlias => "type alias", DefKind::TraitAlias => "trait alias", DefKind::AssocTy => "associated type", @@ -217,7 +220,8 @@ impl DefKind { | DefKind::Use | DefKind::ForeignMod | DefKind::GlobalAsm - | DefKind::Impl => None, + | DefKind::Impl + | DefKind::ImplTraitPlaceholder => None, } } @@ -254,6 +258,7 @@ impl DefKind { | DefKind::Use | DefKind::ForeignMod | DefKind::OpaqueTy + | DefKind::ImplTraitPlaceholder | DefKind::Impl | DefKind::Field | DefKind::TyParam diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs index cc5aed6cb5482..a57fdc3bfb125 100644 --- a/compiler/rustc_hir/src/hir.rs +++ b/compiler/rustc_hir/src/hir.rs @@ -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. @@ -2544,7 +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>]), + /// + /// 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), diff --git a/compiler/rustc_hir/src/intravisit.rs b/compiler/rustc_hir/src/intravisit.rs index 20ec788463ac0..bf4ab06638bb1 100644 --- a/compiler/rustc_hir/src/intravisit.rs +++ b/compiler/rustc_hir/src/intravisit.rs @@ -670,7 +670,7 @@ 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); } diff --git a/compiler/rustc_hir/src/target.rs b/compiler/rustc_hir/src/target.rs index 78bfd7191dba9..5917d5e346e37 100644 --- a/compiler/rustc_hir/src/target.rs +++ b/compiler/rustc_hir/src/target.rs @@ -36,6 +36,7 @@ pub enum Target { GlobalAsm, TyAlias, OpaqueTy, + ImplTraitPlaceholder, Enum, Variant, Struct, @@ -79,7 +80,13 @@ impl Target { ItemKind::ForeignMod { .. } => Target::ForeignMod, ItemKind::GlobalAsm(..) => Target::GlobalAsm, ItemKind::TyAlias(..) => Target::TyAlias, - ItemKind::OpaqueTy(..) => Target::OpaqueTy, + 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, @@ -103,6 +110,7 @@ impl Target { DefKind::GlobalAsm => Target::GlobalAsm, DefKind::TyAlias => Target::TyAlias, DefKind::OpaqueTy => Target::OpaqueTy, + DefKind::ImplTraitPlaceholder => Target::ImplTraitPlaceholder, DefKind::Enum => Target::Enum, DefKind::Struct => Target::Struct, DefKind::Union => Target::Union, @@ -157,6 +165,7 @@ impl Target { Target::GlobalAsm => "global asm", Target::TyAlias => "type alias", Target::OpaqueTy => "opaque type", + Target::ImplTraitPlaceholder => "opaque type in trait", Target::Enum => "enum", Target::Variant => "enum variant", Target::Struct => "struct", diff --git a/compiler/rustc_infer/src/infer/error_reporting/mod.rs b/compiler/rustc_infer/src/infer/error_reporting/mod.rs index 0196bd262179e..08460463998fd 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/mod.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/mod.rs @@ -61,6 +61,7 @@ use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_errors::{pluralize, struct_span_err, Diagnostic, ErrorGuaranteed, IntoDiagnosticArg}; use rustc_errors::{Applicability, DiagnosticBuilder, DiagnosticStyledString, MultiSpan}; use rustc_hir as hir; +use rustc_hir::def::DefKind; use rustc_hir::def_id::{DefId, LocalDefId}; use rustc_hir::lang_items::LangItem; use rustc_hir::Node; @@ -1682,6 +1683,19 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { pos.col.to_usize() + 1, ) } + (true, ty::Projection(proj)) + if self.tcx.def_kind(proj.item_def_id) + == DefKind::ImplTraitPlaceholder => + { + let sm = self.tcx.sess.source_map(); + let pos = sm.lookup_char_pos(self.tcx.def_span(proj.item_def_id).lo()); + format!( + " (trait associated opaque type at <{}:{}:{}>)", + sm.filename_for_diagnostics(&pos.file.name), + pos.line, + pos.col.to_usize() + 1, + ) + } (true, _) => format!(" ({})", ty.sort_string(self.tcx)), (false, _) => "".to_string(), }; @@ -1758,7 +1772,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { // In some (most?) cases cause.body_id points to actual body, but in some cases // it's an actual definition. According to the comments (e.g. in - // librustc_typeck/check/compare_method.rs:compare_predicate_entailment) the latter + // librustc_typeck/check/compare_method.rs:compare_predicates_and_trait_impl_trait_tys) the latter // is relied upon by some other code. This might (or might not) need cleanup. let body_owner_def_id = self.tcx.hir().opt_local_def_id(cause.body_id).unwrap_or_else(|| { diff --git a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/static_impl_trait.rs b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/static_impl_trait.rs index f804569b0747e..b115ac8b3df95 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/static_impl_trait.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/static_impl_trait.rs @@ -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; diff --git a/compiler/rustc_metadata/src/rmeta/encoder.rs b/compiler/rustc_metadata/src/rmeta/encoder.rs index b807663b10fd0..f967ac9a4dc3e 100644 --- a/compiler/rustc_metadata/src/rmeta/encoder.rs +++ b/compiler/rustc_metadata/src/rmeta/encoder.rs @@ -847,6 +847,7 @@ fn should_encode_visibility(def_kind: DefKind) -> bool { | DefKind::Use | DefKind::ForeignMod | DefKind::OpaqueTy + | DefKind::ImplTraitPlaceholder | DefKind::Impl | DefKind::Field => true, DefKind::TyParam @@ -879,6 +880,7 @@ fn should_encode_stability(def_kind: DefKind) -> bool { | DefKind::ForeignMod | DefKind::TyAlias | DefKind::OpaqueTy + | DefKind::ImplTraitPlaceholder | DefKind::Enum | DefKind::Union | DefKind::Impl @@ -967,6 +969,7 @@ fn should_encode_variances(def_kind: DefKind) -> bool { | DefKind::ForeignMod | DefKind::TyAlias | DefKind::OpaqueTy + | DefKind::ImplTraitPlaceholder | DefKind::Impl | DefKind::Trait | DefKind::TraitAlias @@ -1003,6 +1006,7 @@ fn should_encode_generics(def_kind: DefKind) -> bool { | DefKind::AnonConst | DefKind::InlineConst | DefKind::OpaqueTy + | DefKind::ImplTraitPlaceholder | DefKind::Impl | DefKind::Field | DefKind::TyParam @@ -1032,6 +1036,7 @@ fn should_encode_type(tcx: TyCtxt<'_>, def_id: LocalDefId, def_kind: DefKind) -> | DefKind::Static(..) | DefKind::TyAlias | DefKind::OpaqueTy + | DefKind::ImplTraitPlaceholder | DefKind::ForeignTy | DefKind::Impl | DefKind::AssocFn @@ -1081,6 +1086,7 @@ fn should_encode_const(def_kind: DefKind) -> bool { | DefKind::Static(..) | DefKind::TyAlias | DefKind::OpaqueTy + | DefKind::ImplTraitPlaceholder | DefKind::ForeignTy | DefKind::Impl | DefKind::AssocFn diff --git a/compiler/rustc_metadata/src/rmeta/table.rs b/compiler/rustc_metadata/src/rmeta/table.rs index d5f151f0ed8e5..e7c1abd126e04 100644 --- a/compiler/rustc_metadata/src/rmeta/table.rs +++ b/compiler/rustc_metadata/src/rmeta/table.rs @@ -90,6 +90,7 @@ fixed_size_enum! { ( AnonConst ) ( InlineConst ) ( OpaqueTy ) + ( ImplTraitPlaceholder ) ( Field ) ( LifetimeParam ) ( GlobalAsm ) diff --git a/compiler/rustc_middle/src/arena.rs b/compiler/rustc_middle/src/arena.rs index 65d5f755f7248..9b1fedd0b533c 100644 --- a/compiler/rustc_middle/src/arena.rs +++ b/compiler/rustc_middle/src/arena.rs @@ -101,6 +101,8 @@ macro_rules! arena_types { [decode] impl_source: rustc_middle::traits::ImplSource<'tcx, ()>, [] dep_kind: rustc_middle::dep_graph::DepKindStruct<'tcx>, + + [] trait_impl_trait_tys: rustc_data_structures::fx::FxHashMap>, ]); ) } diff --git a/compiler/rustc_middle/src/hir/map/mod.rs b/compiler/rustc_middle/src/hir/map/mod.rs index 6217bffb8f76c..5a65ec9a4765a 100644 --- a/compiler/rustc_middle/src/hir/map/mod.rs +++ b/compiler/rustc_middle/src/hir/map/mod.rs @@ -212,7 +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::OpaqueTy(ref opaque) => { + if opaque.in_trait { + DefKind::ImplTraitPlaceholder + } else { + DefKind::OpaqueTy + } + } ItemKind::TyAlias(..) => DefKind::TyAlias, ItemKind::Enum(..) => DefKind::Enum, ItemKind::Struct(..) => DefKind::Struct, @@ -1187,7 +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::OpaqueTy(ref opaque) => { + if opaque.in_trait { + "opaque type in trait" + } else { + "opaque type" + } + } ItemKind::Enum(..) => "enum", ItemKind::Struct(..) => "struct", ItemKind::Union(..) => "union", diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs index 4478b45cf1437..adf479c423604 100644 --- a/compiler/rustc_middle/src/query/mod.rs +++ b/compiler/rustc_middle/src/query/mod.rs @@ -161,6 +161,13 @@ rustc_queries! { separate_provide_extern } + query compare_predicates_and_trait_impl_trait_tys(key: DefId) + -> Result<&'tcx FxHashMap>, ErrorGuaranteed> + { + desc { "better description please" } + separate_provide_extern + } + query analysis(key: ()) -> Result<(), ErrorGuaranteed> { eval_always desc { "running analysis passes on this crate" } diff --git a/compiler/rustc_middle/src/ty/diagnostics.rs b/compiler/rustc_middle/src/ty/diagnostics.rs index e4ad96b659b08..648f5f7161fa6 100644 --- a/compiler/rustc_middle/src/ty/diagnostics.rs +++ b/compiler/rustc_middle/src/ty/diagnostics.rs @@ -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); diff --git a/compiler/rustc_middle/src/ty/error.rs b/compiler/rustc_middle/src/ty/error.rs index da564c66a70e1..279c8c8d6d16d 100644 --- a/compiler/rustc_middle/src/ty/error.rs +++ b/compiler/rustc_middle/src/ty/error.rs @@ -2,6 +2,7 @@ use crate::traits::{ObligationCause, ObligationCauseCode}; use crate::ty::diagnostics::suggest_constraining_type_param; use crate::ty::print::{FmtPrinter, Printer}; use crate::ty::{self, BoundRegionKind, Region, Ty, TyCtxt}; +use hir::def::DefKind; use rustc_errors::Applicability::{MachineApplicable, MaybeIncorrect}; use rustc_errors::{pluralize, Diagnostic, MultiSpan}; use rustc_hir as hir; @@ -538,7 +539,7 @@ impl Trait for X { diag.span_label(p_span, "this type parameter"); } } - (ty::Projection(proj_ty), _) => { + (ty::Projection(proj_ty), _) if self.def_kind(proj_ty.item_def_id) != DefKind::ImplTraitPlaceholder => { self.expected_projection( diag, proj_ty, @@ -547,7 +548,7 @@ impl Trait for X { cause.code(), ); } - (_, ty::Projection(proj_ty)) => { + (_, ty::Projection(proj_ty)) if self.def_kind(proj_ty.item_def_id) != DefKind::ImplTraitPlaceholder => { let msg = format!( "consider constraining the associated type `{}` to `{}`", values.found, values.expected, diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs index 4635a9d5575d4..df72260597f9f 100644 --- a/compiler/rustc_middle/src/ty/mod.rs +++ b/compiler/rustc_middle/src/ty/mod.rs @@ -2484,6 +2484,14 @@ impl<'tcx> TyCtxt<'tcx> { pub fn is_const_default_method(self, def_id: DefId) -> bool { matches!(self.trait_of_item(def_id), Some(trait_id) if self.has_attr(trait_id, sym::const_trait)) } + + pub fn impl_trait_in_trait_parent(self, mut def_id: DefId) -> DefId { + while let def_kind = self.def_kind(def_id) && def_kind != DefKind::AssocFn { + debug_assert_eq!(def_kind, DefKind::ImplTraitPlaceholder); + def_id = self.parent(def_id); + } + def_id + } } /// Yields the parent function's `LocalDefId` if `def_id` is an `impl Trait` definition. diff --git a/compiler/rustc_middle/src/ty/print/pretty.rs b/compiler/rustc_middle/src/ty/print/pretty.rs index 1ae3063dae4e7..f134e2cd1bc65 100644 --- a/compiler/rustc_middle/src/ty/print/pretty.rs +++ b/compiler/rustc_middle/src/ty/print/pretty.rs @@ -632,7 +632,13 @@ pub trait PrettyPrinter<'tcx>: ty::Foreign(def_id) => { p!(print_def_path(def_id, &[])); } - ty::Projection(ref data) => p!(print(data)), + ty::Projection(ref data) => { + if self.tcx().def_kind(data.item_def_id) == DefKind::ImplTraitPlaceholder { + return self.pretty_print_opaque_impl_type(data.item_def_id, data.substs); + } else { + p!(print(data)) + } + } ty::Placeholder(placeholder) => p!(write("Placeholder({:?})", placeholder)), ty::Opaque(def_id, substs) => { // FIXME(eddyb) print this with `print_def_path`. diff --git a/compiler/rustc_middle/src/ty/sty.rs b/compiler/rustc_middle/src/ty/sty.rs index 9fb91b5fe8700..c5c5d3473418c 100644 --- a/compiler/rustc_middle/src/ty/sty.rs +++ b/compiler/rustc_middle/src/ty/sty.rs @@ -11,6 +11,7 @@ use crate::ty::{ TypeVisitor, }; use crate::ty::{List, ParamEnv}; +use hir::def::DefKind; use polonius_engine::Atom; use rustc_data_structures::captures::Captures; use rustc_data_structures::intern::Interned; @@ -1196,7 +1197,9 @@ pub struct ProjectionTy<'tcx> { impl<'tcx> ProjectionTy<'tcx> { pub fn trait_def_id(&self, tcx: TyCtxt<'tcx>) -> DefId { - tcx.parent(self.item_def_id) + let parent = tcx.parent(self.item_def_id); + assert_eq!(tcx.def_kind(parent), DefKind::Trait); + parent } /// Extracts the underlying trait reference and own substs from this projection. diff --git a/compiler/rustc_middle/src/ty/util.rs b/compiler/rustc_middle/src/ty/util.rs index a3837512bce26..0c73ae54bc31a 100644 --- a/compiler/rustc_middle/src/ty/util.rs +++ b/compiler/rustc_middle/src/ty/util.rs @@ -651,6 +651,13 @@ impl<'tcx> TyCtxt<'tcx> { ty::EarlyBinder(self.type_of(def_id)) } + pub fn bound_trait_impl_trait_tys( + self, + def_id: DefId, + ) -> ty::EarlyBinder>, ErrorGuaranteed>> { + ty::EarlyBinder(self.compare_predicates_and_trait_impl_trait_tys(def_id)) + } + pub fn bound_fn_sig(self, def_id: DefId) -> ty::EarlyBinder> { ty::EarlyBinder(self.fn_sig(def_id)) } diff --git a/compiler/rustc_monomorphize/src/polymorphize.rs b/compiler/rustc_monomorphize/src/polymorphize.rs index af4b35db3bace..98156a94ec4b4 100644 --- a/compiler/rustc_monomorphize/src/polymorphize.rs +++ b/compiler/rustc_monomorphize/src/polymorphize.rs @@ -170,6 +170,7 @@ fn mark_used_by_default_parameters<'tcx>( | DefKind::AnonConst | DefKind::InlineConst | DefKind::OpaqueTy + | DefKind::ImplTraitPlaceholder | DefKind::Field | DefKind::LifetimeParam | DefKind::GlobalAsm diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs index d0b46aa2c4530..bb684e784c58a 100644 --- a/compiler/rustc_passes/src/check_attr.rs +++ b/compiler/rustc_passes/src/check_attr.rs @@ -661,6 +661,7 @@ impl CheckAttrVisitor<'_> { | Target::GlobalAsm | Target::TyAlias | Target::OpaqueTy + | Target::ImplTraitPlaceholder | Target::Enum | Target::Variant | Target::Struct diff --git a/compiler/rustc_passes/src/dead.rs b/compiler/rustc_passes/src/dead.rs index a7ce0f312af80..f141d7beeb921 100644 --- a/compiler/rustc_passes/src/dead.rs +++ b/compiler/rustc_passes/src/dead.rs @@ -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); } diff --git a/compiler/rustc_privacy/src/lib.rs b/compiler/rustc_privacy/src/lib.rs index b2966f0d21801..afd423dc5fa1a 100644 --- a/compiler/rustc_privacy/src/lib.rs +++ b/compiler/rustc_privacy/src/lib.rs @@ -596,6 +596,7 @@ impl<'tcx> EmbargoVisitor<'tcx> { | DefKind::ForeignTy | DefKind::Fn | DefKind::OpaqueTy + | DefKind::ImplTraitPlaceholder | DefKind::AssocFn | DefKind::Trait | DefKind::TyParam @@ -706,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. @@ -2033,7 +2034,8 @@ fn local_visibility(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Visibility { // Visibility on them should have no effect, but to avoid the 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(..), + kind: hir::ItemKind::Use(_, hir::UseKind::ListStem) + | hir::ItemKind::OpaqueTy(..), .. }) => ty::Visibility::Restricted(tcx.parent_module(hir_id)), // Visibilities of trait impl items are inherited from their traits diff --git a/compiler/rustc_resolve/src/build_reduced_graph.rs b/compiler/rustc_resolve/src/build_reduced_graph.rs index 9cb735b36856c..81b67b758f7e1 100644 --- a/compiler/rustc_resolve/src/build_reduced_graph.rs +++ b/compiler/rustc_resolve/src/build_reduced_graph.rs @@ -972,6 +972,7 @@ impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> { | DefKind::TyAlias | DefKind::ForeignTy | DefKind::OpaqueTy + | DefKind::ImplTraitPlaceholder | DefKind::TraitAlias | DefKind::AssocTy, _, diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs index b37feb15890ba..2d6e76c451bfa 100644 --- a/compiler/rustc_resolve/src/late.rs +++ b/compiler/rustc_resolve/src/late.rs @@ -851,7 +851,7 @@ impl<'a: 'ast, 'ast> Visitor<'ast> for LateResolutionVisitor<'a, '_, 'ast> { // We include all lifetime parameters, either named or "Fresh". // The order of those parameters does not matter, as long as it is // deterministic. - if let Some(async_node_id) = async_node_id { + if let Some((async_node_id, _)) = async_node_id { let mut extra_lifetime_params = this .r .extra_lifetime_params_map diff --git a/compiler/rustc_resolve/src/late/lifetimes.rs b/compiler/rustc_resolve/src/late/lifetimes.rs index 101679aa6dc93..6ff56f9a89114 100644 --- a/compiler/rustc_resolve/src/late/lifetimes.rs +++ b/compiler/rustc_resolve/src/late/lifetimes.rs @@ -715,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>;` diff --git a/compiler/rustc_save_analysis/src/dump_visitor.rs b/compiler/rustc_save_analysis/src/dump_visitor.rs index 6658892881d4b..94f222251d3dc 100644 --- a/compiler/rustc_save_analysis/src/dump_visitor.rs +++ b/compiler/rustc_save_analysis/src/dump_visitor.rs @@ -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)); } diff --git a/compiler/rustc_save_analysis/src/lib.rs b/compiler/rustc_save_analysis/src/lib.rs index 89bca39512f52..ebe44a56449d3 100644 --- a/compiler/rustc_save_analysis/src/lib.rs +++ b/compiler/rustc_save_analysis/src/lib.rs @@ -685,6 +685,7 @@ impl<'tcx> SaveContext<'tcx> { | HirDefKind::AssocTy | HirDefKind::Trait | HirDefKind::OpaqueTy + | HirDefKind::ImplTraitPlaceholder | HirDefKind::TyParam, def_id, ) => Some(Ref { kind: RefKind::Type, span, ref_id: id_from_def_id(def_id) }), diff --git a/compiler/rustc_save_analysis/src/sig.rs b/compiler/rustc_save_analysis/src/sig.rs index d1286c9b8b0df..bae1828cd182d 100644 --- a/compiler/rustc_save_analysis/src/sig.rs +++ b/compiler/rustc_save_analysis/src/sig.rs @@ -316,7 +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, _) => { + hir::TyKind::OpaqueDef(item_id, _, _) => { let item = scx.tcx.hir().item(item_id); item.make(offset, Some(item_id.hir_id()), scx) } @@ -561,7 +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::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"), } diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index 75b1dfc856ac7..4fd9e7407ce14 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -1183,6 +1183,7 @@ symbols! { require, residual, result, + return_position_impl_trait_in_trait, rhs, rintf32, rintf64, diff --git a/compiler/rustc_trait_selection/src/traits/project.rs b/compiler/rustc_trait_selection/src/traits/project.rs index 8a093bf4281cb..8a65262a00723 100644 --- a/compiler/rustc_trait_selection/src/traits/project.rs +++ b/compiler/rustc_trait_selection/src/traits/project.rs @@ -32,6 +32,7 @@ use rustc_middle::traits::select::OverflowError; use rustc_middle::ty::fold::{TypeFoldable, TypeFolder, TypeSuperFoldable}; use rustc_middle::ty::subst::Subst; use rustc_middle::ty::visit::{MaxUniverse, TypeVisitable}; +use rustc_middle::ty::DefIdTree; use rustc_middle::ty::{self, Term, ToPredicate, Ty, TyCtxt}; use rustc_span::symbol::sym; @@ -70,6 +71,8 @@ enum ProjectionCandidate<'tcx> { /// From an "impl" (or a "pseudo-impl" returned by select) Select(Selection<'tcx>), + + ImplTraitInTrait(ImplSourceUserDefinedData<'tcx, PredicateObligation<'tcx>>), } enum ProjectionCandidateSet<'tcx> { @@ -1265,6 +1268,8 @@ fn project<'cx, 'tcx>( let mut candidates = ProjectionCandidateSet::None; + assemble_candidate_for_impl_trait_in_trait(selcx, obligation, &mut candidates); + // Make sure that the following procedures are kept in order. ParamEnv // needs to be first because it has highest priority, and Select checks // the return value of push_candidate which assumes it's ran at last. @@ -1303,6 +1308,48 @@ fn project<'cx, 'tcx>( } } +/// If the predicate's item is an `ImplTraitPlaceholder`, we do a select on the +/// corresponding trait ref. If this yields an `impl`, then we're able to project +/// to a concrete type, since we have an `impl`'s method to provide the RPITIT. +fn assemble_candidate_for_impl_trait_in_trait<'cx, 'tcx>( + selcx: &mut SelectionContext<'cx, 'tcx>, + obligation: &ProjectionTyObligation<'tcx>, + candidate_set: &mut ProjectionCandidateSet<'tcx>, +) { + let tcx = selcx.tcx(); + if tcx.def_kind(obligation.predicate.item_def_id) == DefKind::ImplTraitPlaceholder { + let trait_fn_def_id = tcx.impl_trait_in_trait_parent(obligation.predicate.item_def_id); + let trait_def_id = tcx.parent(trait_fn_def_id); + let trait_substs = + obligation.predicate.substs.truncate_to(tcx, tcx.generics_of(trait_def_id)); + // FIXME(named-returns): Binders + let trait_predicate = + ty::Binder::dummy(ty::TraitRef { def_id: trait_def_id, substs: trait_substs }) + .to_poly_trait_predicate(); + + let _ = + selcx.infcx().commit_if_ok(|_| match selcx.select(&obligation.with(trait_predicate)) { + Ok(Some(super::ImplSource::UserDefined(data))) => { + candidate_set.push_candidate(ProjectionCandidate::ImplTraitInTrait(data)); + Ok(()) + } + Ok(None) => { + candidate_set.mark_ambiguous(); + return Err(()); + } + Ok(Some(_)) => { + // Don't know enough about the impl to provide a useful signature + return Err(()); + } + Err(e) => { + debug!(error = ?e, "selection error"); + candidate_set.mark_error(e); + return Err(()); + } + }); + } +} + /// The first thing we have to do is scan through the parameter /// environment to see whether there are any projection predicates /// there that can answer this question. @@ -1465,6 +1512,11 @@ fn assemble_candidates_from_impls<'cx, 'tcx>( obligation: &ProjectionTyObligation<'tcx>, candidate_set: &mut ProjectionCandidateSet<'tcx>, ) { + // Can't assemble candidate from impl for RPITIT + if selcx.tcx().def_kind(obligation.predicate.item_def_id) == DefKind::ImplTraitPlaceholder { + return; + } + // If we are resolving `>::Item == Type`, // start out by selecting the predicate `T as TraitRef<...>`: let poly_trait_ref = ty::Binder::dummy(obligation.predicate.trait_ref(selcx.tcx())); @@ -1740,6 +1792,9 @@ fn confirm_candidate<'cx, 'tcx>( ProjectionCandidate::Select(impl_source) => { confirm_select_candidate(selcx, obligation, impl_source) } + ProjectionCandidate::ImplTraitInTrait(data) => { + confirm_impl_trait_in_trait_candidate(selcx, obligation, data) + } }; // When checking for cycle during evaluation, we compare predicates with @@ -2102,6 +2157,72 @@ fn confirm_impl_candidate<'cx, 'tcx>( } } +fn confirm_impl_trait_in_trait_candidate<'tcx>( + selcx: &mut SelectionContext<'_, 'tcx>, + obligation: &ProjectionTyObligation<'tcx>, + data: ImplSourceUserDefinedData<'tcx, PredicateObligation<'tcx>>, +) -> Progress<'tcx> { + let tcx = selcx.tcx(); + let mut obligations = data.nested; + + 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 }; + }; + if !leaf_def.item.defaultness(tcx).has_value() { + return Progress { term: tcx.ty_error().into(), obligations }; + } + + let impl_fn_def_id = leaf_def.item.def_id; + let impl_fn_substs = obligation.predicate.substs.rebase_onto(tcx, trait_fn_def_id, data.substs); + + let cause = ObligationCause::new( + obligation.cause.span, + obligation.cause.body_id, + super::ItemObligation(impl_fn_def_id), + ); + let predicates = normalize_with_depth_to( + selcx, + obligation.param_env, + cause.clone(), + obligation.recursion_depth + 1, + tcx.predicates_of(impl_fn_def_id).instantiate(tcx, impl_fn_substs), + &mut obligations, + ); + obligations.extend(std::iter::zip(predicates.predicates, predicates.spans).map( + |(pred, span)| { + Obligation::with_depth( + ObligationCause::new( + obligation.cause.span, + obligation.cause.body_id, + if span.is_dummy() { + super::ItemObligation(impl_fn_def_id) + } else { + super::BindingObligation(impl_fn_def_id, span) + }, + ), + obligation.recursion_depth + 1, + obligation.param_env, + pred, + ) + }, + )); + + let ty = super::normalize_to( + selcx, + obligation.param_env, + cause.clone(), + tcx.bound_trait_impl_trait_tys(impl_fn_def_id) + .map_bound(|tys| { + tys.map_or_else(|_| tcx.ty_error(), |tys| tys[&obligation.predicate.item_def_id]) + }) + .subst(tcx, impl_fn_substs), + &mut obligations, + ); + + Progress { term: ty.into(), obligations } +} + // Get obligations corresponding to the predicates from the where-clause of the // associated type itself. // Note: `feature(generic_associated_types)` is required to write such diff --git a/compiler/rustc_ty_utils/src/implied_bounds.rs b/compiler/rustc_ty_utils/src/implied_bounds.rs index a77ea440aaaea..f0d8c240ea588 100644 --- a/compiler/rustc_ty_utils/src/implied_bounds.rs +++ b/compiler/rustc_ty_utils/src/implied_bounds.rs @@ -51,6 +51,7 @@ fn assumed_wf_types<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId) -> &'tcx ty::List 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,13 +2627,13 @@ 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), } @@ -2703,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(); @@ -2746,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> { diff --git a/compiler/rustc_typeck/src/check/closure.rs b/compiler/rustc_typeck/src/check/closure.rs index bc3fec6e7d66a..55cbaf71e7cfd 100644 --- a/compiler/rustc_typeck/src/check/closure.rs +++ b/compiler/rustc_typeck/src/check/closure.rs @@ -4,6 +4,7 @@ use super::{check_fn, Expectation, FnCtxt, GeneratorTypes}; use crate::astconv::AstConv; use crate::rustc_middle::ty::subst::Subst; +use hir::def::DefKind; use rustc_hir as hir; use rustc_hir::def_id::DefId; use rustc_hir::lang_items::LangItem; @@ -680,9 +681,18 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { .map(|e| e.map_bound(|e| *e).transpose_tuple2()) .find_map(|(p, s)| get_future_output(p.subst(self.tcx, substs), s.0))?, ty::Error(_) => return None, + ty::Projection(proj) + if self.tcx.def_kind(proj.item_def_id) == DefKind::ImplTraitPlaceholder => + { + self.tcx + .bound_explicit_item_bounds(proj.item_def_id) + .transpose_iter() + .map(|e| e.map_bound(|e| *e).transpose_tuple2()) + .find_map(|(p, s)| get_future_output(p.subst(self.tcx, proj.substs), s.0))? + } _ => span_bug!( self.tcx.def_span(expr_def_id), - "async fn generator return type not an inference variable" + "async fn generator return type not an inference variable: {ret_ty}" ), }; diff --git a/compiler/rustc_typeck/src/check/compare_method.rs b/compiler/rustc_typeck/src/check/compare_method.rs index b6bc244d2b144..1152a2477a2a8 100644 --- a/compiler/rustc_typeck/src/check/compare_method.rs +++ b/compiler/rustc_typeck/src/check/compare_method.rs @@ -1,18 +1,22 @@ use super::potentially_plural_count; use crate::errors::LifetimesOrBoundsMismatchOnTrait; -use rustc_data_structures::fx::FxHashSet; +use hir::def_id::DefId; +use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_errors::{pluralize, struct_span_err, Applicability, DiagnosticId, ErrorGuaranteed}; use rustc_hir as hir; use rustc_hir::def::{DefKind, Res}; use rustc_hir::intravisit; use rustc_hir::{GenericParamKind, ImplItemKind, TraitItemKind}; use rustc_infer::infer::outlives::env::OutlivesEnvironment; +use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind}; use rustc_infer::infer::{self, TyCtxtInferExt}; use rustc_infer::traits::util; use rustc_middle::ty::error::{ExpectedFound, TypeError}; use rustc_middle::ty::subst::{InternalSubsts, Subst}; use rustc_middle::ty::util::ExplicitSelf; -use rustc_middle::ty::{self, DefIdTree}; +use rustc_middle::ty::{ + self, DefIdTree, Ty, TypeFoldable, TypeFolder, TypeSuperFoldable, TypeVisitable, +}; use rustc_middle::ty::{GenericParamDefKind, ToPredicate, TyCtxt}; use rustc_span::Span; use rustc_trait_selection::traits::error_reporting::InferCtxtExt; @@ -64,10 +68,7 @@ pub(crate) fn compare_impl_method<'tcx>( return; } - if let Err(_) = compare_predicate_entailment(tcx, impl_m, impl_m_span, trait_m, impl_trait_ref) - { - return; - } + tcx.ensure().compare_predicates_and_trait_impl_trait_tys(impl_m.def_id); } /// This function is best explained by example. Consider a trait: @@ -136,13 +137,15 @@ pub(crate) fn compare_impl_method<'tcx>( /// /// Finally we register each of these predicates as an obligation and check that /// they hold. -fn compare_predicate_entailment<'tcx>( +pub(super) fn compare_predicates_and_trait_impl_trait_tys<'tcx>( tcx: TyCtxt<'tcx>, - impl_m: &ty::AssocItem, - impl_m_span: Span, - trait_m: &ty::AssocItem, - impl_trait_ref: ty::TraitRef<'tcx>, -) -> Result<(), ErrorGuaranteed> { + def_id: DefId, +) -> Result<&'tcx FxHashMap>, ErrorGuaranteed> { + let impl_m = tcx.opt_associated_item(def_id).unwrap(); + let impl_m_span = tcx.def_span(def_id); + let trait_m = tcx.opt_associated_item(impl_m.trait_item_def_id.unwrap()).unwrap(); + let impl_trait_ref = tcx.impl_trait_ref(impl_m.impl_container(tcx).unwrap()).unwrap(); + let trait_to_impl_substs = impl_trait_ref.substs; // This node-id should be used for the `body_id` field on each @@ -161,6 +164,7 @@ fn compare_predicate_entailment<'tcx>( kind: impl_m.kind, }, ); + let return_span = tcx.hir().fn_decl_by_hir_id(impl_m_hir_id).unwrap().output.span(); // Create mapping from impl to placeholder. let impl_to_placeholder_substs = InternalSubsts::identity_for_item(tcx, impl_m.def_id); @@ -266,6 +270,13 @@ fn compare_predicate_entailment<'tcx>( let trait_sig = tcx.bound_fn_sig(trait_m.def_id).subst(tcx, trait_to_placeholder_substs); let trait_sig = tcx.liberate_late_bound_regions(impl_m.def_id, trait_sig); + let mut collector = + ImplTraitInTraitCollector::new(&ocx, return_span, param_env, impl_m_hir_id); + // FIXME(RPITIT): This should only be needed on the output type, but + // RPITIT placeholders shouldn't show up anywhere except for there, + // so I think this is fine. + let trait_sig = trait_sig.fold_with(&mut collector); + // Next, add all inputs and output as well-formed tys. Importantly, // we have to do this before normalization, since the normalized ty may // not contain the input parameters. See issue #87748. @@ -411,10 +422,115 @@ fn compare_predicate_entailment<'tcx>( &outlives_environment, ); - Ok(()) + let mut collected_tys = FxHashMap::default(); + 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>> = 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) => { + tcx.sess.delay_span_bug( + return_span, + format!("could not fully resolve: {ty} => {err:?}"), + ); + collected_tys.insert(def_id, tcx.ty_error()); + } + } + } + + Ok(&*tcx.arena.alloc(collected_tys)) }) } +struct ImplTraitInTraitCollector<'a, 'tcx> { + ocx: &'a ObligationCtxt<'a, 'tcx>, + types: FxHashMap, ty::SubstsRef<'tcx>)>, + span: Span, + param_env: ty::ParamEnv<'tcx>, + body_id: hir::HirId, +} + +impl<'a, 'tcx> ImplTraitInTraitCollector<'a, 'tcx> { + fn new( + ocx: &'a ObligationCtxt<'a, 'tcx>, + span: Span, + param_env: ty::ParamEnv<'tcx>, + body_id: hir::HirId, + ) -> Self { + ImplTraitInTraitCollector { ocx, types: FxHashMap::default(), span, param_env, body_id } + } +} + +impl<'tcx> TypeFolder<'tcx> for ImplTraitInTraitCollector<'_, 'tcx> { + fn tcx<'a>(&'a self) -> TyCtxt<'tcx> { + self.ocx.infcx.tcx + } + + fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'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) { + return *ty; + } + //FIXME(RPITIT): Deny nested RPITIT in substs too + if proj.substs.has_escaping_bound_vars() { + bug!("FIXME(RPITIT): error here"); + } + // Replace with infer var + let infer_ty = self.ocx.infcx.next_ty_var(TypeVariableOrigin { + span: self.span, + kind: TypeVariableOriginKind::MiscVariable, + }); + 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; + + let pred = pred.map_bound(|(pred, _)| *pred).subst(self.tcx(), proj.substs); + let pred = pred.fold_with(self); + let pred = self.ocx.normalize( + ObligationCause::misc(self.span, self.body_id), + self.param_env, + pred, + ); + + self.ocx.register_obligation(traits::Obligation::new( + ObligationCause::new( + self.span, + self.body_id, + ObligationCauseCode::BindingObligation(proj.item_def_id, pred_span), + ), + self.param_env, + pred, + )); + } + infer_ty + } else { + ty.super_fold_with(self) + } + } +} + fn check_region_bounds_on_impl_item<'tcx>( tcx: TyCtxt<'tcx>, impl_m: &ty::AssocItem, @@ -1191,7 +1307,7 @@ pub(crate) fn compare_ty_impl<'tcx>( })(); } -/// The equivalent of [compare_predicate_entailment], but for associated types +/// The equivalent of [compare_predicates_and_trait_impl_trait_tys], but for associated types /// instead of associated functions. fn compare_type_predicate_entailment<'tcx>( tcx: TyCtxt<'tcx>, diff --git a/compiler/rustc_typeck/src/check/mod.rs b/compiler/rustc_typeck/src/check/mod.rs index 69eb34b5f802d..8811b38fc555a 100644 --- a/compiler/rustc_typeck/src/check/mod.rs +++ b/compiler/rustc_typeck/src/check/mod.rs @@ -132,6 +132,7 @@ use crate::require_c_abi_if_c_variadic; use crate::util::common::indenter; use self::coercion::DynamicCoerceMany; +use self::compare_method::compare_predicates_and_trait_impl_trait_tys; use self::region::region_scope_tree; pub use self::Expectation::*; @@ -249,6 +250,7 @@ pub fn provide(providers: &mut Providers) { used_trait_imports, check_mod_item_types, region_scope_tree, + compare_predicates_and_trait_impl_trait_tys, ..*providers }; } diff --git a/compiler/rustc_typeck/src/collect.rs b/compiler/rustc_typeck/src/collect.rs index e70f728d7dcce..ceb5684fdf0a8 100644 --- a/compiler/rustc_typeck/src/collect.rs +++ b/compiler/rustc_typeck/src/collect.rs @@ -1585,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); @@ -1787,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) } diff --git a/compiler/rustc_typeck/src/collect/item_bounds.rs b/compiler/rustc_typeck/src/collect/item_bounds.rs index 318e8f581f7c8..0d34a8bfee333 100644 --- a/compiler/rustc_typeck/src/collect/item_bounds.rs +++ b/compiler/rustc_typeck/src/collect/item_bounds.rs @@ -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 = >::compute_bounds(&icx, item_ty, ast_bounds); @@ -86,10 +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), + }) => opaque_type_bounds(tcx, def_id, bounds, *span, *in_trait), _ => bug!("item_bounds called on {:?}", def_id), } } diff --git a/compiler/rustc_typeck/src/collect/type_of.rs b/compiler/rustc_typeck/src/collect/type_of.rs index a0280ddca4bd8..a26e26cb38996 100644 --- a/compiler/rustc_typeck/src/collect/type_of.rs +++ b/compiler/rustc_typeck/src/collect/type_of.rs @@ -333,8 +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::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(..) diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index 66f766bfbe8d2..08b696e65eb3b 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -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()) diff --git a/src/librustdoc/clean/utils.rs b/src/librustdoc/clean/utils.rs index a9d511ae11e8b..395f213ca87c3 100644 --- a/src/librustdoc/clean/utils.rs +++ b/src/librustdoc/clean/utils.rs @@ -511,8 +511,8 @@ pub(crate) fn register_res(cx: &mut DocContext<'_>, res: Res) -> DefId { | Res::Err => return res.def_id(), Res::Def( TyParam | ConstParam | Ctor(..) | ExternCrate | Use | ForeignMod | AnonConst - | InlineConst | OpaqueTy | Field | LifetimeParam | GlobalAsm | Impl | Closure - | Generator, + | InlineConst | OpaqueTy | ImplTraitPlaceholder | Field | LifetimeParam | GlobalAsm + | Impl | Closure | Generator, id, ) => return id, }; diff --git a/src/librustdoc/formats/item_type.rs b/src/librustdoc/formats/item_type.rs index 0a7ee2005915b..f21e60a64e005 100644 --- a/src/librustdoc/formats/item_type.rs +++ b/src/librustdoc/formats/item_type.rs @@ -135,6 +135,7 @@ impl From for ItemType { | DefKind::AnonConst | DefKind::InlineConst | DefKind::OpaqueTy + | DefKind::ImplTraitPlaceholder | DefKind::Field | DefKind::LifetimeParam | DefKind::GlobalAsm diff --git a/src/librustdoc/passes/collect_intra_doc_links.rs b/src/librustdoc/passes/collect_intra_doc_links.rs index c27f0ce18c141..cfd6ce402c28a 100644 --- a/src/librustdoc/passes/collect_intra_doc_links.rs +++ b/src/librustdoc/passes/collect_intra_doc_links.rs @@ -1805,8 +1805,8 @@ fn resolution_failure( } return; } - Trait | TyAlias | ForeignTy | OpaqueTy | TraitAlias | TyParam - | Static(_) => "associated item", + Trait | TyAlias | ForeignTy | OpaqueTy | ImplTraitPlaceholder + | TraitAlias | TyParam | Static(_) => "associated item", Impl | GlobalAsm => unreachable!("not a path"), } } else { diff --git a/src/test/ui/async-await/async-trait-fn.rs b/src/test/ui/async-await/async-trait-fn.rs index e2062e82725c0..0ea685986db40 100644 --- a/src/test/ui/async-await/async-trait-fn.rs +++ b/src/test/ui/async-await/async-trait-fn.rs @@ -1,8 +1,11 @@ // edition:2018 trait T { async fn foo() {} //~ ERROR functions in traits cannot be declared `async` + //~^ ERROR mismatched types async fn bar(&self) {} //~ ERROR functions in traits cannot be declared `async` + //~^ ERROR mismatched types async fn baz() { //~ ERROR functions in traits cannot be declared `async` + //~^ ERROR mismatched types // Nested item must not ICE. fn a() {} } diff --git a/src/test/ui/async-await/async-trait-fn.stderr b/src/test/ui/async-await/async-trait-fn.stderr index 1eb8969a80d20..e5c584e31e815 100644 --- a/src/test/ui/async-await/async-trait-fn.stderr +++ b/src/test/ui/async-await/async-trait-fn.stderr @@ -2,40 +2,89 @@ error[E0706]: functions in traits cannot be declared `async` --> $DIR/async-trait-fn.rs:3:5 | LL | async fn foo() {} - | -----^^^^^^^^^^^^ + | -----^^^^^^^^^ | | | `async` because of this | = note: `async` trait functions are not currently supported = note: consider using the `async-trait` crate: https://crates.io/crates/async-trait + = note: see issue #91611 for more information + = help: add `#![feature(return_position_impl_trait_in_trait)]` to the crate attributes to enable error[E0706]: functions in traits cannot be declared `async` - --> $DIR/async-trait-fn.rs:4:5 + --> $DIR/async-trait-fn.rs:5:5 | LL | async fn bar(&self) {} - | -----^^^^^^^^^^^^^^^^^ + | -----^^^^^^^^^^^^^^ | | | `async` because of this | = note: `async` trait functions are not currently supported = note: consider using the `async-trait` crate: https://crates.io/crates/async-trait + = note: see issue #91611 for more information + = help: add `#![feature(return_position_impl_trait_in_trait)]` to the crate attributes to enable error[E0706]: functions in traits cannot be declared `async` - --> $DIR/async-trait-fn.rs:5:5 + --> $DIR/async-trait-fn.rs:7:5 + | +LL | async fn baz() { + | -----^^^^^^^^^ + | | + | `async` because of this + | + = note: `async` trait functions are not currently supported + = note: consider using the `async-trait` crate: https://crates.io/crates/async-trait + = note: see issue #91611 for more information + = help: add `#![feature(return_position_impl_trait_in_trait)]` to the crate attributes to enable + +error[E0308]: mismatched types + --> $DIR/async-trait-fn.rs:3:20 + | +LL | async fn foo() {} + | ^^ expected associated type, found opaque type + | + ::: $SRC_DIR/core/src/future/mod.rs:LL:COL + | +LL | pub const fn from_generator(gen: T) -> impl Future + | ------------------------------- the found opaque type + | + = note: expected associated type `impl Future` (trait associated opaque type at <$DIR/async-trait-fn.rs:3:20>) + found opaque type `impl Future` (opaque type at <$SRC_DIR/core/src/future/mod.rs:LL:COL>) + +error[E0308]: mismatched types + --> $DIR/async-trait-fn.rs:5:25 + | +LL | async fn bar(&self) {} + | ^^ expected associated type, found opaque type + | + ::: $SRC_DIR/core/src/future/mod.rs:LL:COL + | +LL | pub const fn from_generator(gen: T) -> impl Future + | ------------------------------- the found opaque type + | + = note: expected associated type `impl Future` (trait associated opaque type at <$DIR/async-trait-fn.rs:5:25>) + found opaque type `impl Future` (opaque type at <$SRC_DIR/core/src/future/mod.rs:LL:COL>) + +error[E0308]: mismatched types + --> $DIR/async-trait-fn.rs:7:20 | LL | async fn baz() { - | ^---- - | | - | _____`async` because of this - | | + | ____________________^ +LL | | LL | | // Nested item must not ICE. LL | | fn a() {} LL | | } - | |_____^ + | |_____^ expected associated type, found opaque type | - = note: `async` trait functions are not currently supported - = note: consider using the `async-trait` crate: https://crates.io/crates/async-trait + ::: $SRC_DIR/core/src/future/mod.rs:LL:COL + | +LL | pub const fn from_generator(gen: T) -> impl Future + | ------------------------------- the found opaque type + | + = note: expected associated type `impl Future` (trait associated opaque type at <$DIR/async-trait-fn.rs:7:20>) + found opaque type `impl Future` (opaque type at <$SRC_DIR/core/src/future/mod.rs:LL:COL>) -error: aborting due to 3 previous errors +error: aborting due to 6 previous errors -For more information about this error, try `rustc --explain E0706`. +Some errors have detailed explanations: E0308, E0706. +For more information about an error, try `rustc --explain E0308`. diff --git a/src/test/ui/async-await/edition-deny-async-fns-2015.rs b/src/test/ui/async-await/edition-deny-async-fns-2015.rs index e5dc9c8a5fee8..22a61dcd25f98 100644 --- a/src/test/ui/async-await/edition-deny-async-fns-2015.rs +++ b/src/test/ui/async-await/edition-deny-async-fns-2015.rs @@ -16,7 +16,8 @@ impl Foo { trait Bar { async fn foo() {} //~ ERROR `async fn` is not permitted in Rust 2015 - //~^ ERROR functions in traits cannot be declared `async` + //~^ ERROR functions in traits cannot be declared `async` + //~| ERROR mismatched types } fn main() { diff --git a/src/test/ui/async-await/edition-deny-async-fns-2015.stderr b/src/test/ui/async-await/edition-deny-async-fns-2015.stderr index 35f9c581c7b21..8c2902d9b00d1 100644 --- a/src/test/ui/async-await/edition-deny-async-fns-2015.stderr +++ b/src/test/ui/async-await/edition-deny-async-fns-2015.stderr @@ -53,7 +53,7 @@ LL | async fn foo() {} = note: for more on editions, read https://doc.rust-lang.org/edition-guide error[E0670]: `async fn` is not permitted in Rust 2015 - --> $DIR/edition-deny-async-fns-2015.rs:36:9 + --> $DIR/edition-deny-async-fns-2015.rs:37:9 | LL | async fn bar() {} | ^^^^^ to use `async fn`, switch to Rust 2018 or later @@ -62,7 +62,7 @@ LL | async fn bar() {} = note: for more on editions, read https://doc.rust-lang.org/edition-guide error[E0670]: `async fn` is not permitted in Rust 2015 - --> $DIR/edition-deny-async-fns-2015.rs:26:9 + --> $DIR/edition-deny-async-fns-2015.rs:27:9 | LL | async fn foo() {} | ^^^^^ to use `async fn`, switch to Rust 2018 or later @@ -71,7 +71,7 @@ LL | async fn foo() {} = note: for more on editions, read https://doc.rust-lang.org/edition-guide error[E0670]: `async fn` is not permitted in Rust 2015 - --> $DIR/edition-deny-async-fns-2015.rs:31:13 + --> $DIR/edition-deny-async-fns-2015.rs:32:13 | LL | async fn bar() {} | ^^^^^ to use `async fn`, switch to Rust 2018 or later @@ -83,14 +83,30 @@ error[E0706]: functions in traits cannot be declared `async` --> $DIR/edition-deny-async-fns-2015.rs:18:5 | LL | async fn foo() {} - | -----^^^^^^^^^^^^ + | -----^^^^^^^^^ | | | `async` because of this | = note: `async` trait functions are not currently supported = note: consider using the `async-trait` crate: https://crates.io/crates/async-trait + = note: see issue #91611 for more information + = help: add `#![feature(return_position_impl_trait_in_trait)]` to the crate attributes to enable -error: aborting due to 10 previous errors +error[E0308]: mismatched types + --> $DIR/edition-deny-async-fns-2015.rs:18:20 + | +LL | async fn foo() {} + | ^^ expected associated type, found opaque type + | + ::: $SRC_DIR/core/src/future/mod.rs:LL:COL + | +LL | pub const fn from_generator(gen: T) -> impl Future + | ------------------------------- the found opaque type + | + = note: expected associated type `impl Future` (trait associated opaque type at <$DIR/edition-deny-async-fns-2015.rs:18:20>) + found opaque type `impl Future` (opaque type at <$SRC_DIR/core/src/future/mod.rs:LL:COL>) + +error: aborting due to 11 previous errors -Some errors have detailed explanations: E0670, E0706. -For more information about an error, try `rustc --explain E0670`. +Some errors have detailed explanations: E0308, E0670, E0706. +For more information about an error, try `rustc --explain E0308`. diff --git a/src/test/ui/async-await/issues/issue-95307.stderr b/src/test/ui/async-await/issues/issue-95307.stderr index 29aebb719d66f..1c12f1e4862e8 100644 --- a/src/test/ui/async-await/issues/issue-95307.stderr +++ b/src/test/ui/async-await/issues/issue-95307.stderr @@ -8,6 +8,8 @@ LL | async fn new() -> [u8; _]; | = note: `async` trait functions are not currently supported = note: consider using the `async-trait` crate: https://crates.io/crates/async-trait + = note: see issue #91611 for more information + = help: add `#![feature(return_position_impl_trait_in_trait)]` to the crate attributes to enable error: in expressions, `_` can only be used on the left-hand side of an assignment --> $DIR/issue-95307.rs:7:28 diff --git a/src/test/ui/feature-gates/feature-gate-return_position_impl_trait_in_trait.rs b/src/test/ui/feature-gates/feature-gate-return_position_impl_trait_in_trait.rs new file mode 100644 index 0000000000000..de7966c66b057 --- /dev/null +++ b/src/test/ui/feature-gates/feature-gate-return_position_impl_trait_in_trait.rs @@ -0,0 +1,5 @@ +trait Foo { + fn bar() -> impl Sized; //~ ERROR `impl Trait` only allowed in function and inherent method return types, not in trait method return +} + +fn main() {} diff --git a/src/test/ui/feature-gates/feature-gate-return_position_impl_trait_in_trait.stderr b/src/test/ui/feature-gates/feature-gate-return_position_impl_trait_in_trait.stderr new file mode 100644 index 0000000000000..36177bbe15830 --- /dev/null +++ b/src/test/ui/feature-gates/feature-gate-return_position_impl_trait_in_trait.stderr @@ -0,0 +1,12 @@ +error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in trait method return + --> $DIR/feature-gate-return_position_impl_trait_in_trait.rs:2:17 + | +LL | fn bar() -> impl Sized; + | ^^^^^^^^^^ + | + = note: see issue #91611 for more information + = help: add `#![feature(return_position_impl_trait_in_trait)]` to the crate attributes to enable + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0562`. diff --git a/src/test/ui/impl-trait/in-trait/deep-match-works.rs b/src/test/ui/impl-trait/in-trait/deep-match-works.rs new file mode 100644 index 0000000000000..772da845ee1f7 --- /dev/null +++ b/src/test/ui/impl-trait/in-trait/deep-match-works.rs @@ -0,0 +1,16 @@ +// check-pass + +#![feature(return_position_impl_trait_in_trait)] +#![allow(incomplete_features)] + +struct Wrapper(T); + +trait Foo { + fn bar() -> Wrapper; +} + +impl Foo for () { + fn bar() -> Wrapper { Wrapper(0) } +} + +fn main() {} diff --git a/src/test/ui/impl-trait/in-trait/deep-match.rs b/src/test/ui/impl-trait/in-trait/deep-match.rs new file mode 100644 index 0000000000000..5a220bc3f198a --- /dev/null +++ b/src/test/ui/impl-trait/in-trait/deep-match.rs @@ -0,0 +1,15 @@ +#![feature(return_position_impl_trait_in_trait)] +#![allow(incomplete_features)] + +struct Wrapper(T); + +trait Foo { + fn bar() -> Wrapper; +} + +impl Foo for () { + fn bar() -> i32 { 0 } + //~^ ERROR method `bar` has an incompatible type for trait +} + +fn main() {} diff --git a/src/test/ui/impl-trait/in-trait/deep-match.stderr b/src/test/ui/impl-trait/in-trait/deep-match.stderr new file mode 100644 index 0000000000000..af449869cb356 --- /dev/null +++ b/src/test/ui/impl-trait/in-trait/deep-match.stderr @@ -0,0 +1,20 @@ +error[E0053]: method `bar` has an incompatible type for trait + --> $DIR/deep-match.rs:11:17 + | +LL | fn bar() -> i32 { 0 } + | ^^^ + | | + | expected struct `Wrapper`, found `i32` + | help: change the output type to match the trait: `Wrapper<_>` + | +note: type in trait + --> $DIR/deep-match.rs:7:17 + | +LL | fn bar() -> Wrapper; + | ^^^^^^^^^^^^^^^^^^^ + = note: expected fn pointer `fn() -> Wrapper<_>` + found fn pointer `fn() -> i32` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0053`. diff --git a/src/test/ui/impl-trait/in-trait/doesnt-satisfy.rs b/src/test/ui/impl-trait/in-trait/doesnt-satisfy.rs new file mode 100644 index 0000000000000..bb4e0d44f3eff --- /dev/null +++ b/src/test/ui/impl-trait/in-trait/doesnt-satisfy.rs @@ -0,0 +1,13 @@ +#![feature(return_position_impl_trait_in_trait)] +#![allow(incomplete_features)] + +trait Foo { + fn bar() -> impl std::fmt::Display; +} + +impl Foo for () { + fn bar() -> () {} + //~^ ERROR `()` doesn't implement `std::fmt::Display` +} + +fn main() {} diff --git a/src/test/ui/impl-trait/in-trait/doesnt-satisfy.stderr b/src/test/ui/impl-trait/in-trait/doesnt-satisfy.stderr new file mode 100644 index 0000000000000..aa5492d285ed6 --- /dev/null +++ b/src/test/ui/impl-trait/in-trait/doesnt-satisfy.stderr @@ -0,0 +1,17 @@ +error[E0277]: `()` doesn't implement `std::fmt::Display` + --> $DIR/doesnt-satisfy.rs:9:17 + | +LL | fn bar() -> () {} + | ^^ `()` cannot be formatted with the default formatter + | + = help: the trait `std::fmt::Display` is not implemented for `()` + = note: in format strings you may be able to use `{:?}` (or {:#?} for pretty-print) instead +note: required by a bound in `Foo::bar::{opaque#0}` + --> $DIR/doesnt-satisfy.rs:5:22 + | +LL | fn bar() -> impl std::fmt::Display; + | ^^^^^^^^^^^^^^^^^ required by this bound in `Foo::bar::{opaque#0}` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/impl-trait/in-trait/nested-rpitit.rs b/src/test/ui/impl-trait/in-trait/nested-rpitit.rs new file mode 100644 index 0000000000000..65285e3a3ccaf --- /dev/null +++ b/src/test/ui/impl-trait/in-trait/nested-rpitit.rs @@ -0,0 +1,32 @@ +// check-pass + +#![feature(return_position_impl_trait_in_trait)] +#![allow(incomplete_features)] + +use std::fmt::Display; +use std::ops::Deref; + +trait Foo { + fn bar(self) -> impl Deref; +} + +struct A; + +impl Foo for A { + fn bar(self) -> &'static str { + "Hello, world" + } +} + +struct B; + +impl Foo for B { + fn bar(self) -> Box { + Box::new(42) + } +} + +fn main() { + println!("Message for you: {:?}", &*A.bar()); + println!("Another for you: {:?}", &*B.bar()); +} diff --git a/src/test/ui/impl-trait/in-trait/opaque-in-impl-is-opaque.rs b/src/test/ui/impl-trait/in-trait/opaque-in-impl-is-opaque.rs new file mode 100644 index 0000000000000..3ac264e8ebac5 --- /dev/null +++ b/src/test/ui/impl-trait/in-trait/opaque-in-impl-is-opaque.rs @@ -0,0 +1,19 @@ +#![feature(return_position_impl_trait_in_trait)] +#![allow(incomplete_features)] + +use std::fmt::Display; + +trait Foo { + fn bar(&self) -> impl Display; +} + +impl Foo for () { + fn bar(&self) -> impl Display { + "Hello, world" + } +} + +fn main() { + let x: &str = ().bar(); + //~^ ERROR mismatched types +} diff --git a/src/test/ui/impl-trait/in-trait/opaque-in-impl-is-opaque.stderr b/src/test/ui/impl-trait/in-trait/opaque-in-impl-is-opaque.stderr new file mode 100644 index 0000000000000..15edda4834015 --- /dev/null +++ b/src/test/ui/impl-trait/in-trait/opaque-in-impl-is-opaque.stderr @@ -0,0 +1,17 @@ +error[E0308]: mismatched types + --> $DIR/opaque-in-impl-is-opaque.rs:17:19 + | +LL | fn bar(&self) -> impl Display { + | ------------ the found opaque type +... +LL | let x: &str = ().bar(); + | ---- ^^^^^^^^ expected `&str`, found opaque type + | | + | expected due to this + | + = note: expected reference `&str` + found opaque type `impl std::fmt::Display` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/impl-trait/in-trait/opaque-in-impl.rs b/src/test/ui/impl-trait/in-trait/opaque-in-impl.rs new file mode 100644 index 0000000000000..2e06629699aad --- /dev/null +++ b/src/test/ui/impl-trait/in-trait/opaque-in-impl.rs @@ -0,0 +1,48 @@ +// check-pass + +#![feature(return_position_impl_trait_in_trait)] +#![allow(incomplete_features)] + +use std::fmt::Debug; + +trait Foo { + fn foo(&self) -> impl Debug; +} + +impl Foo for () { + fn foo(&self) -> impl Debug { + "Hello, world" + } +} + +impl Foo for std::marker::PhantomData { + fn foo(&self) -> impl Debug { + T::default() + } +} + +trait Bar { + fn bar(&self) -> impl Debug; +} + +impl Bar for () { + fn bar(&self) -> impl Debug { + format!("Hello with generic {}", std::any::type_name::()) + } +} + +trait Baz { + fn baz(&self) -> impl Debug + '_; +} + +impl Baz for String { + fn baz(&self) -> impl Debug + '_ { + (self,) + } +} + +fn main() { + println!("{:?}", ().foo()); + println!("{:?}", ().bar::()); + println!("{:?}", "hi".to_string().baz()); +} diff --git a/src/test/ui/impl-trait/in-trait/reveal.rs b/src/test/ui/impl-trait/in-trait/reveal.rs new file mode 100644 index 0000000000000..d6ede1cc495c6 --- /dev/null +++ b/src/test/ui/impl-trait/in-trait/reveal.rs @@ -0,0 +1,18 @@ +// check-pass + +#![feature(return_position_impl_trait_in_trait)] +#![allow(incomplete_features)] + +trait Foo { + fn f() -> Box; +} + +impl Foo for () { + fn f() -> Box { + Box::new(String::new()) + } +} + +fn main() { + let x: Box = <() as Foo>::f(); +} diff --git a/src/test/ui/impl-trait/in-trait/success.rs b/src/test/ui/impl-trait/in-trait/success.rs new file mode 100644 index 0000000000000..4cbe682b46f73 --- /dev/null +++ b/src/test/ui/impl-trait/in-trait/success.rs @@ -0,0 +1,40 @@ +// check-pass + +#![feature(return_position_impl_trait_in_trait)] +#![allow(incomplete_features)] + +use std::fmt::Display; + +trait Foo { + fn bar(&self) -> impl Display; +} + +impl Foo for i32 { + fn bar(&self) -> i32 { + *self + } +} + +impl Foo for &'static str { + fn bar(&self) -> &'static str { + *self + } +} + +struct Yay; + +impl Foo for Yay { + fn bar(&self) -> String { + String::from(":^)") + } +} + +fn foo_generically(t: T) { + println!("{}", t.bar()); +} + +fn main() { + println!("{}", "Hello, world.".bar()); + println!("The answer is {}!", 42.bar()); + foo_generically(Yay); +} diff --git a/src/test/ui/impl-trait/where-allowed.stderr b/src/test/ui/impl-trait/where-allowed.stderr index 58a2f79efb4c6..9b346387d6106 100644 --- a/src/test/ui/impl-trait/where-allowed.stderr +++ b/src/test/ui/impl-trait/where-allowed.stderr @@ -162,12 +162,18 @@ error[E0562]: `impl Trait` only allowed in function and inherent method return t | LL | fn in_return() -> impl Debug; | ^^^^^^^^^^ + | + = note: see issue #91611 for more information + = help: add `#![feature(return_position_impl_trait_in_trait)]` to the crate attributes to enable error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in `impl` method return --> $DIR/where-allowed.rs:125:34 | LL | fn in_trait_impl_return() -> impl Debug { () } | ^^^^^^^^^^ + | + = note: see issue #91611 for more information + = help: add `#![feature(return_position_impl_trait_in_trait)]` to the crate attributes to enable error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in `extern fn` param --> $DIR/where-allowed.rs:138:33 diff --git a/src/test/ui/parser/fn-header-semantic-fail.rs b/src/test/ui/parser/fn-header-semantic-fail.rs index 8ff14fb1f304a..cf5d3dab4aada 100644 --- a/src/test/ui/parser/fn-header-semantic-fail.rs +++ b/src/test/ui/parser/fn-header-semantic-fail.rs @@ -27,7 +27,6 @@ fn main() { struct Y; impl X for Y { async fn ft1() {} //~ ERROR functions in traits cannot be declared `async` - //~^ ERROR has an incompatible type for trait unsafe fn ft2() {} // OK. const fn ft3() {} //~ ERROR functions in traits cannot be declared const extern "C" fn ft4() {} @@ -36,7 +35,6 @@ fn main() { //~| ERROR functions in traits cannot be declared const //~| ERROR functions cannot be both `const` and `async` //~| ERROR cycle detected - //~| ERROR has an incompatible type for trait } impl Y { diff --git a/src/test/ui/parser/fn-header-semantic-fail.stderr b/src/test/ui/parser/fn-header-semantic-fail.stderr index bc51ba8b8c5c5..36304779df36f 100644 --- a/src/test/ui/parser/fn-header-semantic-fail.stderr +++ b/src/test/ui/parser/fn-header-semantic-fail.stderr @@ -7,17 +7,6 @@ LL | const async unsafe extern "C" fn ff5() {} | | `async` because of this | `const` because of this -error[E0706]: functions in traits cannot be declared `async` - --> $DIR/fn-header-semantic-fail.rs:17:9 - | -LL | async fn ft1(); - | -----^^^^^^^^^^ - | | - | `async` because of this - | - = note: `async` trait functions are not currently supported - = note: consider using the `async-trait` crate: https://crates.io/crates/async-trait - error[E0379]: functions in traits cannot be declared const --> $DIR/fn-header-semantic-fail.rs:19:9 | @@ -30,17 +19,6 @@ error[E0379]: functions in traits cannot be declared const LL | const async unsafe extern "C" fn ft5(); | ^^^^^ functions in traits cannot be const -error[E0706]: functions in traits cannot be declared `async` - --> $DIR/fn-header-semantic-fail.rs:21:9 - | -LL | const async unsafe extern "C" fn ft5(); - | ^^^^^^-----^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | | - | `async` because of this - | - = note: `async` trait functions are not currently supported - = note: consider using the `async-trait` crate: https://crates.io/crates/async-trait - error: functions cannot be both `const` and `async` --> $DIR/fn-header-semantic-fail.rs:21:9 | @@ -50,42 +28,20 @@ LL | const async unsafe extern "C" fn ft5(); | | `async` because of this | `const` because of this -error[E0706]: functions in traits cannot be declared `async` - --> $DIR/fn-header-semantic-fail.rs:29:9 - | -LL | async fn ft1() {} - | -----^^^^^^^^^^^^ - | | - | `async` because of this - | - = note: `async` trait functions are not currently supported - = note: consider using the `async-trait` crate: https://crates.io/crates/async-trait - error[E0379]: functions in traits cannot be declared const - --> $DIR/fn-header-semantic-fail.rs:32:9 + --> $DIR/fn-header-semantic-fail.rs:31:9 | LL | const fn ft3() {} | ^^^^^ functions in traits cannot be const error[E0379]: functions in traits cannot be declared const - --> $DIR/fn-header-semantic-fail.rs:34:9 + --> $DIR/fn-header-semantic-fail.rs:33:9 | LL | const async unsafe extern "C" fn ft5() {} | ^^^^^ functions in traits cannot be const -error[E0706]: functions in traits cannot be declared `async` - --> $DIR/fn-header-semantic-fail.rs:34:9 - | -LL | const async unsafe extern "C" fn ft5() {} - | ^^^^^^-----^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | | - | `async` because of this - | - = note: `async` trait functions are not currently supported - = note: consider using the `async-trait` crate: https://crates.io/crates/async-trait - error: functions cannot be both `const` and `async` - --> $DIR/fn-header-semantic-fail.rs:34:9 + --> $DIR/fn-header-semantic-fail.rs:33:9 | LL | const async unsafe extern "C" fn ft5() {} | ^^^^^-^^^^^------------------------------ @@ -94,7 +50,7 @@ LL | const async unsafe extern "C" fn ft5() {} | `const` because of this error: functions cannot be both `const` and `async` - --> $DIR/fn-header-semantic-fail.rs:47:9 + --> $DIR/fn-header-semantic-fail.rs:45:9 | LL | const async unsafe extern "C" fn fi5() {} | ^^^^^-^^^^^------------------------------ @@ -103,7 +59,7 @@ LL | const async unsafe extern "C" fn fi5() {} | `const` because of this error: functions in `extern` blocks cannot have qualifiers - --> $DIR/fn-header-semantic-fail.rs:53:18 + --> $DIR/fn-header-semantic-fail.rs:51:18 | LL | extern "C" { | ---------- in this `extern` block @@ -116,7 +72,7 @@ LL | fn fe1(); | ~~ error: functions in `extern` blocks cannot have qualifiers - --> $DIR/fn-header-semantic-fail.rs:54:19 + --> $DIR/fn-header-semantic-fail.rs:52:19 | LL | extern "C" { | ---------- in this `extern` block @@ -130,7 +86,7 @@ LL | fn fe2(); | ~~ error: functions in `extern` blocks cannot have qualifiers - --> $DIR/fn-header-semantic-fail.rs:55:18 + --> $DIR/fn-header-semantic-fail.rs:53:18 | LL | extern "C" { | ---------- in this `extern` block @@ -144,7 +100,7 @@ LL | fn fe3(); | ~~ error: functions in `extern` blocks cannot have qualifiers - --> $DIR/fn-header-semantic-fail.rs:56:23 + --> $DIR/fn-header-semantic-fail.rs:54:23 | LL | extern "C" { | ---------- in this `extern` block @@ -158,7 +114,7 @@ LL | fn fe4(); | ~~ error: functions in `extern` blocks cannot have qualifiers - --> $DIR/fn-header-semantic-fail.rs:57:42 + --> $DIR/fn-header-semantic-fail.rs:55:42 | LL | extern "C" { | ---------- in this `extern` block @@ -172,7 +128,7 @@ LL | fn fe5(); | ~~ error: functions cannot be both `const` and `async` - --> $DIR/fn-header-semantic-fail.rs:57:9 + --> $DIR/fn-header-semantic-fail.rs:55:9 | LL | const async unsafe extern "C" fn fe5(); | ^^^^^-^^^^^---------------------------- @@ -180,6 +136,58 @@ LL | const async unsafe extern "C" fn fe5(); | | `async` because of this | `const` because of this +error[E0706]: functions in traits cannot be declared `async` + --> $DIR/fn-header-semantic-fail.rs:17:9 + | +LL | async fn ft1(); + | -----^^^^^^^^^^ + | | + | `async` because of this + | + = note: `async` trait functions are not currently supported + = note: consider using the `async-trait` crate: https://crates.io/crates/async-trait + = note: see issue #91611 for more information + = help: add `#![feature(return_position_impl_trait_in_trait)]` to the crate attributes to enable + +error[E0706]: functions in traits cannot be declared `async` + --> $DIR/fn-header-semantic-fail.rs:21:9 + | +LL | const async unsafe extern "C" fn ft5(); + | ^^^^^^-----^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | | + | `async` because of this + | + = note: `async` trait functions are not currently supported + = note: consider using the `async-trait` crate: https://crates.io/crates/async-trait + = note: see issue #91611 for more information + = help: add `#![feature(return_position_impl_trait_in_trait)]` to the crate attributes to enable + +error[E0706]: functions in traits cannot be declared `async` + --> $DIR/fn-header-semantic-fail.rs:29:9 + | +LL | async fn ft1() {} + | -----^^^^^^^^^ + | | + | `async` because of this + | + = note: `async` trait functions are not currently supported + = note: consider using the `async-trait` crate: https://crates.io/crates/async-trait + = note: see issue #91611 for more information + = help: add `#![feature(return_position_impl_trait_in_trait)]` to the crate attributes to enable + +error[E0706]: functions in traits cannot be declared `async` + --> $DIR/fn-header-semantic-fail.rs:33:9 + | +LL | const async unsafe extern "C" fn ft5() {} + | ^^^^^^-----^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | | + | `async` because of this + | + = note: `async` trait functions are not currently supported + = note: consider using the `async-trait` crate: https://crates.io/crates/async-trait + = note: see issue #91611 for more information + = help: add `#![feature(return_position_impl_trait_in_trait)]` to the crate attributes to enable + error[E0391]: cycle detected when computing type of `main::ff5::{opaque#0}` --> $DIR/fn-header-semantic-fail.rs:12:44 | @@ -216,60 +224,24 @@ LL | | } LL | | } | |_^ -error[E0053]: method `ft1` has an incompatible type for trait - --> $DIR/fn-header-semantic-fail.rs:29:24 - | -LL | async fn ft1() {} - | ^ - | | - | checked the `Output` of this `async fn`, found opaque type - | expected `()`, found opaque type - | - = note: while checking the return type of the `async fn` -note: type in trait - --> $DIR/fn-header-semantic-fail.rs:17:23 - | -LL | async fn ft1(); - | ^ - = note: expected fn pointer `fn()` - found fn pointer `fn() -> impl Future` - -error[E0053]: method `ft5` has an incompatible type for trait - --> $DIR/fn-header-semantic-fail.rs:34:48 - | -LL | const async unsafe extern "C" fn ft5() {} - | ^ - | | - | checked the `Output` of this `async fn`, found opaque type - | expected `()`, found opaque type - | - = note: while checking the return type of the `async fn` -note: type in trait - --> $DIR/fn-header-semantic-fail.rs:21:47 - | -LL | const async unsafe extern "C" fn ft5(); - | ^ - = note: expected fn pointer `unsafe extern "C" fn()` - found fn pointer `unsafe extern "C" fn() -> impl Future` - error[E0391]: cycle detected when computing type of `main::::ft5::{opaque#0}` - --> $DIR/fn-header-semantic-fail.rs:34:48 + --> $DIR/fn-header-semantic-fail.rs:33:48 | LL | const async unsafe extern "C" fn ft5() {} | ^ | note: ...which requires borrow-checking `main::::ft5`... - --> $DIR/fn-header-semantic-fail.rs:34:9 + --> $DIR/fn-header-semantic-fail.rs:33:9 | LL | const async unsafe extern "C" fn ft5() {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ note: ...which requires processing `main::::ft5`... - --> $DIR/fn-header-semantic-fail.rs:34:9 + --> $DIR/fn-header-semantic-fail.rs:33:9 | LL | const async unsafe extern "C" fn ft5() {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ note: ...which requires const checking `main::::ft5`... - --> $DIR/fn-header-semantic-fail.rs:34:9 + --> $DIR/fn-header-semantic-fail.rs:33:9 | LL | const async unsafe extern "C" fn ft5() {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -288,30 +260,30 @@ LL | | } LL | | } | |_^ -error[E0391]: cycle detected when computing type of `main::::fi5::{opaque#0}` - --> $DIR/fn-header-semantic-fail.rs:47:48 +error[E0391]: cycle detected when computing type of `main::::fi5::{opaque#0}` + --> $DIR/fn-header-semantic-fail.rs:45:48 | LL | const async unsafe extern "C" fn fi5() {} | ^ | -note: ...which requires borrow-checking `main::::fi5`... - --> $DIR/fn-header-semantic-fail.rs:47:9 +note: ...which requires borrow-checking `main::::fi5`... + --> $DIR/fn-header-semantic-fail.rs:45:9 | LL | const async unsafe extern "C" fn fi5() {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -note: ...which requires processing `main::::fi5`... - --> $DIR/fn-header-semantic-fail.rs:47:9 +note: ...which requires processing `main::::fi5`... + --> $DIR/fn-header-semantic-fail.rs:45:9 | LL | const async unsafe extern "C" fn fi5() {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -note: ...which requires const checking `main::::fi5`... - --> $DIR/fn-header-semantic-fail.rs:47:9 +note: ...which requires const checking `main::::fi5`... + --> $DIR/fn-header-semantic-fail.rs:45:9 | LL | const async unsafe extern "C" fn fi5() {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ = note: ...which requires computing whether `impl core::future::future::Future` is freeze... = note: ...which requires evaluating trait selection obligation `impl core::future::future::Future: core::marker::Freeze`... - = note: ...which again requires computing type of `main::::fi5::{opaque#0}`, completing the cycle + = note: ...which again requires computing type of `main::::fi5::{opaque#0}`, completing the cycle note: cycle used when checking item types in top-level module --> $DIR/fn-header-semantic-fail.rs:5:1 | @@ -324,7 +296,7 @@ LL | | } LL | | } | |_^ -error: aborting due to 23 previous errors +error: aborting due to 21 previous errors -Some errors have detailed explanations: E0053, E0379, E0391, E0706. -For more information about an error, try `rustc --explain E0053`. +Some errors have detailed explanations: E0379, E0391, E0706. +For more information about an error, try `rustc --explain E0379`. diff --git a/src/test/ui/resolve/issue-70736-async-fn-no-body-def-collector.rs b/src/test/ui/resolve/issue-70736-async-fn-no-body-def-collector.rs index aaf0f7eaef0dc..49462f52fb4c2 100644 --- a/src/test/ui/resolve/issue-70736-async-fn-no-body-def-collector.rs +++ b/src/test/ui/resolve/issue-70736-async-fn-no-body-def-collector.rs @@ -14,7 +14,6 @@ trait B { impl B for A { async fn associated(); //~ ERROR without body //~^ ERROR cannot be declared `async` - //~| ERROR has an incompatible type for trait } fn main() {} diff --git a/src/test/ui/resolve/issue-70736-async-fn-no-body-def-collector.stderr b/src/test/ui/resolve/issue-70736-async-fn-no-body-def-collector.stderr index d3214458eac13..55c3b66f1363d 100644 --- a/src/test/ui/resolve/issue-70736-async-fn-no-body-def-collector.stderr +++ b/src/test/ui/resolve/issue-70736-async-fn-no-body-def-collector.stderr @@ -14,17 +14,6 @@ LL | async fn inherent(); | | | help: provide a definition for the function: `{ }` -error[E0706]: functions in traits cannot be declared `async` - --> $DIR/issue-70736-async-fn-no-body-def-collector.rs:11:5 - | -LL | async fn associated(); - | -----^^^^^^^^^^^^^^^^^ - | | - | `async` because of this - | - = note: `async` trait functions are not currently supported - = note: consider using the `async-trait` crate: https://crates.io/crates/async-trait - error: associated function in `impl` without body --> $DIR/issue-70736-async-fn-no-body-def-collector.rs:15:5 | @@ -34,7 +23,7 @@ LL | async fn associated(); | help: provide a definition for the function: `{ }` error[E0706]: functions in traits cannot be declared `async` - --> $DIR/issue-70736-async-fn-no-body-def-collector.rs:15:5 + --> $DIR/issue-70736-async-fn-no-body-def-collector.rs:11:5 | LL | async fn associated(); | -----^^^^^^^^^^^^^^^^^ @@ -43,26 +32,22 @@ LL | async fn associated(); | = note: `async` trait functions are not currently supported = note: consider using the `async-trait` crate: https://crates.io/crates/async-trait + = note: see issue #91611 for more information + = help: add `#![feature(return_position_impl_trait_in_trait)]` to the crate attributes to enable -error[E0053]: method `associated` has an incompatible type for trait - --> $DIR/issue-70736-async-fn-no-body-def-collector.rs:15:26 +error[E0706]: functions in traits cannot be declared `async` + --> $DIR/issue-70736-async-fn-no-body-def-collector.rs:15:5 | LL | async fn associated(); - | ^ - | | - | checked the `Output` of this `async fn`, found opaque type - | expected `()`, found opaque type - | - = note: while checking the return type of the `async fn` -note: type in trait - --> $DIR/issue-70736-async-fn-no-body-def-collector.rs:11:26 + | -----^^^^^^^^^^^^^^^^^ + | | + | `async` because of this | -LL | async fn associated(); - | ^ - = note: expected fn pointer `fn()` - found fn pointer `fn() -> impl Future` + = note: `async` trait functions are not currently supported + = note: consider using the `async-trait` crate: https://crates.io/crates/async-trait + = note: see issue #91611 for more information + = help: add `#![feature(return_position_impl_trait_in_trait)]` to the crate attributes to enable -error: aborting due to 6 previous errors +error: aborting due to 5 previous errors -Some errors have detailed explanations: E0053, E0706. -For more information about an error, try `rustc --explain E0053`. +For more information about this error, try `rustc --explain E0706`. diff --git a/src/test/ui/span/drop-location-span-error-rust-2021-incompatible-closure-captures-93117.rs b/src/test/ui/span/drop-location-span-error-rust-2021-incompatible-closure-captures-93117.rs index b280c8ab6e2b2..94f578af209a8 100644 --- a/src/test/ui/span/drop-location-span-error-rust-2021-incompatible-closure-captures-93117.rs +++ b/src/test/ui/span/drop-location-span-error-rust-2021-incompatible-closure-captures-93117.rs @@ -12,7 +12,8 @@ impl A { trait C{async fn new(val: T) {} //~ ERROR `async fn` is not permitted in Rust 2015 //~^ ERROR functions in traits cannot be declared `async` -//~^^ ERROR cannot find type `T` in this scope -//~^^^ WARN changes to closure capture in Rust 2021 will affect drop order [rust_2021_incompatible_closure_captures] +//~| ERROR mismatched types +//~| ERROR cannot find type `T` in this scope +//~| WARN changes to closure capture in Rust 2021 will affect drop order [rust_2021_incompatible_closure_captures] //~ ERROR this file contains an unclosed delimiter diff --git a/src/test/ui/span/drop-location-span-error-rust-2021-incompatible-closure-captures-93117.stderr b/src/test/ui/span/drop-location-span-error-rust-2021-incompatible-closure-captures-93117.stderr index 50de2322907ed..3814c568e72c1 100644 --- a/src/test/ui/span/drop-location-span-error-rust-2021-incompatible-closure-captures-93117.stderr +++ b/src/test/ui/span/drop-location-span-error-rust-2021-incompatible-closure-captures-93117.stderr @@ -1,5 +1,5 @@ error: this file contains an unclosed delimiter - --> $DIR/drop-location-span-error-rust-2021-incompatible-closure-captures-93117.rs:18:53 + --> $DIR/drop-location-span-error-rust-2021-incompatible-closure-captures-93117.rs:19:53 | LL | trait C{async fn new(val: T) {} | - unclosed delimiter @@ -25,17 +25,6 @@ LL | trait C{async fn new(val: T) {} = help: pass `--edition 2021` to `rustc` = note: for more on editions, read https://doc.rust-lang.org/edition-guide -error[E0706]: functions in traits cannot be declared `async` - --> $DIR/drop-location-span-error-rust-2021-incompatible-closure-captures-93117.rs:13:9 - | -LL | trait C{async fn new(val: T) {} - | -----^^^^^^^^^^^^^^^^^^ - | | - | `async` because of this - | - = note: `async` trait functions are not currently supported - = note: consider using the `async-trait` crate: https://crates.io/crates/async-trait - error[E0423]: expected function, found module `crate` --> $DIR/drop-location-span-error-rust-2021-incompatible-closure-captures-93117.rs:9:5 | @@ -51,6 +40,19 @@ LL | pub struct A {} LL | trait C{async fn new(val: T) {} | ^ help: a struct with a similar name exists: `A` +error[E0706]: functions in traits cannot be declared `async` + --> $DIR/drop-location-span-error-rust-2021-incompatible-closure-captures-93117.rs:13:9 + | +LL | trait C{async fn new(val: T) {} + | -----^^^^^^^^^^^^^^^ + | | + | `async` because of this + | + = note: `async` trait functions are not currently supported + = note: consider using the `async-trait` crate: https://crates.io/crates/async-trait + = note: see issue #91611 for more information + = help: add `#![feature(return_position_impl_trait_in_trait)]` to the crate attributes to enable + warning: changes to closure capture in Rust 2021 will affect drop order --> $DIR/drop-location-span-error-rust-2021-incompatible-closure-captures-93117.rs:6:57 | @@ -72,6 +74,20 @@ help: add a dummy let to cause `path` to be fully captured LL | async fn create(path: impl AsRef) { let _ = &path; | ++++++++++++++ +error[E0308]: mismatched types + --> $DIR/drop-location-span-error-rust-2021-incompatible-closure-captures-93117.rs:13:30 + | +LL | trait C{async fn new(val: T) {} + | ^^ expected associated type, found opaque type + | + ::: $SRC_DIR/core/src/future/mod.rs:LL:COL + | +LL | pub const fn from_generator(gen: T) -> impl Future + | ------------------------------- the found opaque type + | + = note: expected associated type `impl Future` (trait associated opaque type at <$DIR/drop-location-span-error-rust-2021-incompatible-closure-captures-93117.rs:13:30>) + found opaque type `impl Future` (opaque type at <$SRC_DIR/core/src/future/mod.rs:LL:COL>) + warning: changes to closure capture in Rust 2021 will affect drop order --> $DIR/drop-location-span-error-rust-2021-incompatible-closure-captures-93117.rs:13:30 | @@ -87,7 +103,7 @@ help: add a dummy let to cause `val` to be fully captured LL | trait C{async fn new(val: T) { let _ = &val;} | +++++++++++++ -error: aborting due to 6 previous errors; 2 warnings emitted +error: aborting due to 7 previous errors; 2 warnings emitted -Some errors have detailed explanations: E0412, E0423, E0670, E0706. -For more information about an error, try `rustc --explain E0412`. +Some errors have detailed explanations: E0308, E0412, E0423, E0670, E0706. +For more information about an error, try `rustc --explain E0308`. diff --git a/src/tools/clippy/clippy_lints/src/lifetimes.rs b/src/tools/clippy/clippy_lints/src/lifetimes.rs index 573a7c016b8e8..5995675bd969c 100644 --- a/src/tools/clippy/clippy_lints/src/lifetimes.rs +++ b/src/tools/clippy/clippy_lints/src/lifetimes.rs @@ -441,7 +441,7 @@ impl<'a, 'tcx> Visitor<'tcx> for RefVisitor<'a, 'tcx> { fn visit_ty(&mut self, ty: &'tcx Ty<'_>) { match ty.kind { - TyKind::OpaqueDef(item, bounds) => { + TyKind::OpaqueDef(item, bounds, _) => { let map = self.cx.tcx.hir(); let item = map.item(item); let len = self.lts.len(); diff --git a/src/tools/clippy/clippy_lints/src/manual_async_fn.rs b/src/tools/clippy/clippy_lints/src/manual_async_fn.rs index 2502c8f880ddc..754b0e78a148c 100644 --- a/src/tools/clippy/clippy_lints/src/manual_async_fn.rs +++ b/src/tools/clippy/clippy_lints/src/manual_async_fn.rs @@ -103,7 +103,7 @@ fn future_trait_ref<'tcx>( ty: &'tcx Ty<'tcx>, ) -> Option<(&'tcx TraitRef<'tcx>, Vec)> { if_chain! { - if let TyKind::OpaqueDef(item_id, bounds) = ty.kind; + if let TyKind::OpaqueDef(item_id, bounds, false) = ty.kind; let item = cx.tcx.hir().item(item_id); if let ItemKind::OpaqueTy(opaque) = &item.kind; if let Some(trait_ref) = opaque.bounds.iter().find_map(|bound| { diff --git a/src/tools/clippy/clippy_utils/src/hir_utils.rs b/src/tools/clippy/clippy_utils/src/hir_utils.rs index ff23ed5fffa3c..f45cec9f0b430 100644 --- a/src/tools/clippy/clippy_utils/src/hir_utils.rs +++ b/src/tools/clippy/clippy_utils/src/hir_utils.rs @@ -987,8 +987,9 @@ impl<'a, 'tcx> SpanlessHash<'a, 'tcx> { } }, TyKind::Path(ref qpath) => self.hash_qpath(qpath), - TyKind::OpaqueDef(_, arg_list) => { + TyKind::OpaqueDef(_, arg_list, in_trait) => { self.hash_generic_args(arg_list); + in_trait.hash(&mut self.s); }, TyKind::TraitObject(_, lifetime, _) => { self.hash_lifetime(*lifetime);