diff --git a/compiler/rustc_ast/src/ast.rs b/compiler/rustc_ast/src/ast.rs index 9cb193b4a6781..fe888d2004f83 100644 --- a/compiler/rustc_ast/src/ast.rs +++ b/compiler/rustc_ast/src/ast.rs @@ -307,6 +307,8 @@ impl TraitBoundModifiers { pub enum GenericBound { Trait(PolyTraitRef, TraitBoundModifiers), Outlives(Lifetime), + /// Precise capturing syntax: `impl Sized + use<'a>` + Use(ThinVec, Span), } impl GenericBound { @@ -314,6 +316,7 @@ impl GenericBound { match self { GenericBound::Trait(t, ..) => t.span, GenericBound::Outlives(l) => l.ident.span, + GenericBound::Use(_, span) => *span, } } } @@ -2162,7 +2165,7 @@ pub enum TyKind { /// The `NodeId` exists to prevent lowering from having to /// generate `NodeId`s on the fly, which would complicate /// the generation of opaque `type Foo = impl Trait` items significantly. - ImplTrait(NodeId, GenericBounds, Option, Span)>>), + ImplTrait(NodeId, GenericBounds), /// No-op; kept solely so that we can pretty-print faithfully. Paren(P), /// Unused for now. diff --git a/compiler/rustc_ast/src/mut_visit.rs b/compiler/rustc_ast/src/mut_visit.rs index cc33ce2cb5629..182ad7359af8a 100644 --- a/compiler/rustc_ast/src/mut_visit.rs +++ b/compiler/rustc_ast/src/mut_visit.rs @@ -523,14 +523,9 @@ pub fn noop_visit_ty(ty: &mut P, vis: &mut T) { TyKind::TraitObject(bounds, _syntax) => { visit_vec(bounds, |bound| vis.visit_param_bound(bound)) } - TyKind::ImplTrait(id, bounds, precise_capturing) => { + TyKind::ImplTrait(id, bounds) => { vis.visit_id(id); visit_vec(bounds, |bound| vis.visit_param_bound(bound)); - if let Some((precise_capturing, _span)) = precise_capturing.as_deref_mut() { - for arg in precise_capturing { - vis.visit_precise_capturing_arg(arg); - } - } } TyKind::MacCall(mac) => vis.visit_mac_call(mac), TyKind::AnonStruct(id, fields) | TyKind::AnonUnion(id, fields) => { @@ -923,6 +918,11 @@ fn noop_visit_param_bound(pb: &mut GenericBound, vis: &mut T) { match pb { GenericBound::Trait(ty, _modifier) => vis.visit_poly_trait_ref(ty), GenericBound::Outlives(lifetime) => noop_visit_lifetime(lifetime, vis), + GenericBound::Use(args, _) => { + for arg in args { + vis.visit_precise_capturing_arg(arg); + } + } } } diff --git a/compiler/rustc_ast/src/util/classify.rs b/compiler/rustc_ast/src/util/classify.rs index 382c903625fbd..4b2544ac47ed8 100644 --- a/compiler/rustc_ast/src/util/classify.rs +++ b/compiler/rustc_ast/src/util/classify.rs @@ -184,7 +184,7 @@ fn type_trailing_braced_mac_call(mut ty: &ast::Ty) -> Option<&ast::MacCall> { None => break None, }, - ast::TyKind::TraitObject(bounds, _) | ast::TyKind::ImplTrait(_, bounds, _) => { + ast::TyKind::TraitObject(bounds, _) | ast::TyKind::ImplTrait(_, bounds) => { match bounds.last() { Some(ast::GenericBound::Trait(bound, _)) => { match path_return_type(&bound.trait_ref.path) { @@ -192,7 +192,9 @@ fn type_trailing_braced_mac_call(mut ty: &ast::Ty) -> Option<&ast::MacCall> { None => break None, } } - Some(ast::GenericBound::Outlives(_)) | None => break None, + Some(ast::GenericBound::Outlives(_) | ast::GenericBound::Use(..)) | None => { + break None; + } } } diff --git a/compiler/rustc_ast/src/visit.rs b/compiler/rustc_ast/src/visit.rs index fa97c8db3267b..104a401cd531c 100644 --- a/compiler/rustc_ast/src/visit.rs +++ b/compiler/rustc_ast/src/visit.rs @@ -52,6 +52,16 @@ pub enum BoundKind { /// E.g., `trait A: B` SuperTraits, } +impl BoundKind { + pub fn descr(self) -> &'static str { + match self { + BoundKind::Bound => "bounds", + BoundKind::Impl => "`impl Trait`", + BoundKind::TraitObject => "`dyn` trait object bounds", + BoundKind::SuperTraits => "supertrait bounds", + } + } +} #[derive(Copy, Clone, Debug)] pub enum FnKind<'a> { @@ -497,13 +507,8 @@ pub fn walk_ty<'a, V: Visitor<'a>>(visitor: &mut V, typ: &'a Ty) -> V::Result { TyKind::TraitObject(bounds, ..) => { walk_list!(visitor, visit_param_bound, bounds, BoundKind::TraitObject); } - TyKind::ImplTrait(_, bounds, precise_capturing) => { + TyKind::ImplTrait(_, bounds) => { walk_list!(visitor, visit_param_bound, bounds, BoundKind::Impl); - if let Some((precise_capturing, _span)) = precise_capturing.as_deref() { - for arg in precise_capturing { - try_visit!(visitor.visit_precise_capturing_arg(arg)); - } - } } TyKind::Typeof(expression) => try_visit!(visitor.visit_anon_const(expression)), TyKind::Infer | TyKind::ImplicitSelf | TyKind::Dummy | TyKind::Err(_) => {} @@ -688,6 +693,10 @@ pub fn walk_param_bound<'a, V: Visitor<'a>>(visitor: &mut V, bound: &'a GenericB match bound { GenericBound::Trait(typ, _modifier) => visitor.visit_poly_trait_ref(typ), GenericBound::Outlives(lifetime) => visitor.visit_lifetime(lifetime, LifetimeCtxt::Bound), + GenericBound::Use(args, _) => { + walk_list!(visitor, visit_precise_capturing_arg, args); + V::Result::output() + } } } diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs index 88f6e6c3b780c..1fc6a96991573 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs @@ -51,9 +51,9 @@ use rustc_data_structures::sorted_map::SortedMap; use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; use rustc_data_structures::sync::Lrc; use rustc_errors::{DiagArgFromDisplay, DiagCtxt, StashKey}; -use rustc_hir as hir; use rustc_hir::def::{DefKind, LifetimeRes, Namespace, PartialRes, PerNS, Res}; use rustc_hir::def_id::{LocalDefId, LocalDefIdMap, CRATE_DEF_ID, LOCAL_CRATE}; +use rustc_hir::{self as hir}; use rustc_hir::{ ConstArg, GenericArg, HirId, ItemLocalMap, MissingLifetimeKind, ParamName, TraitCandidate, }; @@ -1384,6 +1384,8 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { } None } + // Ignore `use` syntax since that is not valid in objects. + GenericBound::Use(..) => None, })); let lifetime_bound = lifetime_bound.unwrap_or_else(|| this.elided_dyn_bound(t.span)); @@ -1391,7 +1393,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { }); hir::TyKind::TraitObject(bounds, lifetime_bound, *kind) } - TyKind::ImplTrait(def_node_id, bounds, precise_capturing) => { + TyKind::ImplTrait(def_node_id, bounds) => { let span = t.span; match itctx { ImplTraitContext::OpaqueTy { origin, fn_kind } => self.lower_opaque_impl_trait( @@ -1401,12 +1403,15 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { bounds, fn_kind, itctx, - precise_capturing.as_deref().map(|(args, span)| (args.as_slice(), *span)), ), ImplTraitContext::Universal => { - if let Some(&(_, span)) = precise_capturing.as_deref() { + if let Some(span) = bounds.iter().find_map(|bound| match *bound { + ast::GenericBound::Use(_, span) => Some(span), + _ => None, + }) { self.tcx.dcx().emit_err(errors::NoPreciseCapturesOnApit { span }); - }; + } + let span = t.span; // HACK: pprust breaks strings with newlines when the type @@ -1517,7 +1522,6 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { bounds: &GenericBounds, fn_kind: Option, itctx: ImplTraitContext, - precise_capturing_args: Option<(&[PreciseCapturingArg], Span)>, ) -> hir::TyKind<'hir> { // Make sure we know that some funky desugaring has been going on here. // This is a first: there is code in other places like for loop @@ -1526,59 +1530,61 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { // frequently opened issues show. let opaque_ty_span = self.mark_span_with_reason(DesugaringKind::OpaqueTy, span, None); - let captured_lifetimes_to_duplicate = - if let Some((precise_capturing, _)) = precise_capturing_args { - // We'll actually validate these later on; all we need is the list of - // lifetimes to duplicate during this portion of lowering. - precise_capturing - .iter() - .filter_map(|arg| match arg { - PreciseCapturingArg::Lifetime(lt) => Some(*lt), - PreciseCapturingArg::Arg(..) => None, - }) - // Add in all the lifetimes mentioned in the bounds. We will error - // them out later, but capturing them here is important to make sure - // they actually get resolved in resolve_bound_vars. - .chain(lifetime_collector::lifetimes_in_bounds(self.resolver, bounds)) - .collect() - } else { - match origin { - hir::OpaqueTyOrigin::TyAlias { .. } => { - // type alias impl trait and associated type position impl trait were - // decided to capture all in-scope lifetimes, which we collect for - // all opaques during resolution. + let captured_lifetimes_to_duplicate = if let Some(args) = + bounds.iter().find_map(|bound| match bound { + ast::GenericBound::Use(a, _) => Some(a), + _ => None, + }) { + // We'll actually validate these later on; all we need is the list of + // lifetimes to duplicate during this portion of lowering. + args.iter() + .filter_map(|arg| match arg { + PreciseCapturingArg::Lifetime(lt) => Some(*lt), + PreciseCapturingArg::Arg(..) => None, + }) + // Add in all the lifetimes mentioned in the bounds. We will error + // them out later, but capturing them here is important to make sure + // they actually get resolved in resolve_bound_vars. + .chain(lifetime_collector::lifetimes_in_bounds(self.resolver, bounds)) + .collect() + } else { + match origin { + hir::OpaqueTyOrigin::TyAlias { .. } => { + // type alias impl trait and associated type position impl trait were + // decided to capture all in-scope lifetimes, which we collect for + // all opaques during resolution. + self.resolver + .take_extra_lifetime_params(opaque_ty_node_id) + .into_iter() + .map(|(ident, id, _)| Lifetime { id, ident }) + .collect() + } + hir::OpaqueTyOrigin::FnReturn(..) => { + if matches!( + fn_kind.expect("expected RPITs to be lowered with a FnKind"), + FnDeclKind::Impl | FnDeclKind::Trait + ) || self.tcx.features().lifetime_capture_rules_2024 + || span.at_least_rust_2024() + { + // return-position impl trait in trait was decided to capture all + // in-scope lifetimes, which we collect for all opaques during resolution. self.resolver .take_extra_lifetime_params(opaque_ty_node_id) .into_iter() .map(|(ident, id, _)| Lifetime { id, ident }) .collect() - } - hir::OpaqueTyOrigin::FnReturn(..) => { - if matches!( - fn_kind.expect("expected RPITs to be lowered with a FnKind"), - FnDeclKind::Impl | FnDeclKind::Trait - ) || self.tcx.features().lifetime_capture_rules_2024 - || span.at_least_rust_2024() - { - // return-position impl trait in trait was decided to capture all - // in-scope lifetimes, which we collect for all opaques during resolution. - self.resolver - .take_extra_lifetime_params(opaque_ty_node_id) - .into_iter() - .map(|(ident, id, _)| Lifetime { id, ident }) - .collect() - } else { - // in fn return position, like the `fn test<'a>() -> impl Debug + 'a` - // example, we only need to duplicate lifetimes that appear in the - // bounds, since those are the only ones that are captured by the opaque. - lifetime_collector::lifetimes_in_bounds(self.resolver, bounds) - } - } - hir::OpaqueTyOrigin::AsyncFn(..) => { - unreachable!("should be using `lower_async_fn_ret_ty`") + } else { + // in fn return position, like the `fn test<'a>() -> impl Debug + 'a` + // example, we only need to duplicate lifetimes that appear in the + // bounds, since those are the only ones that are captured by the opaque. + lifetime_collector::lifetimes_in_bounds(self.resolver, bounds) } } - }; + hir::OpaqueTyOrigin::AsyncFn(..) => { + unreachable!("should be using `lower_async_fn_ret_ty`") + } + } + }; debug!(?captured_lifetimes_to_duplicate); self.lower_opaque_inner( @@ -1588,7 +1594,6 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { captured_lifetimes_to_duplicate, span, opaque_ty_span, - precise_capturing_args, |this| this.lower_param_bounds(bounds, itctx), ) } @@ -1601,7 +1606,6 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { captured_lifetimes_to_duplicate: FxIndexSet, span: Span, opaque_ty_span: Span, - precise_capturing_args: Option<(&[PreciseCapturingArg], Span)>, lower_item_bounds: impl FnOnce(&mut Self) -> &'hir [hir::GenericBound<'hir>], ) -> hir::TyKind<'hir> { let opaque_ty_def_id = self.create_def( @@ -1688,18 +1692,8 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { // Install the remapping from old to new (if any). This makes sure that // any lifetimes that would have resolved to the def-id of captured // lifetimes are remapped to the new *synthetic* lifetimes of the opaque. - let (bounds, precise_capturing_args) = - this.with_remapping(captured_to_synthesized_mapping, |this| { - ( - lower_item_bounds(this), - precise_capturing_args.map(|(precise_capturing, span)| { - ( - this.lower_precise_capturing_args(precise_capturing), - this.lower_span(span), - ) - }), - ) - }); + let bounds = this + .with_remapping(captured_to_synthesized_mapping, |this| lower_item_bounds(this)); let generic_params = this.arena.alloc_from_iter(synthesized_lifetime_definitions.iter().map( @@ -1744,7 +1738,6 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { origin, lifetime_mapping, in_trait, - precise_capturing_args, }; // Generate an `type Foo = impl Trait;` declaration. @@ -1955,7 +1948,6 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { captured_lifetimes, span, opaque_ty_span, - None, |this| { let bound = this.lower_coroutine_fn_output_type_to_bound( output, @@ -2038,6 +2030,10 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { GenericBound::Outlives(lifetime) => { hir::GenericBound::Outlives(self.lower_lifetime(lifetime)) } + GenericBound::Use(args, span) => hir::GenericBound::Use( + self.lower_precise_capturing_args(args), + self.lower_span(*span), + ), } } diff --git a/compiler/rustc_ast_passes/messages.ftl b/compiler/rustc_ast_passes/messages.ftl index 9a8689e27c068..af27429b5083b 100644 --- a/compiler/rustc_ast_passes/messages.ftl +++ b/compiler/rustc_ast_passes/messages.ftl @@ -14,6 +14,8 @@ ast_passes_assoc_type_without_body = associated type in `impl` without body .suggestion = provide a definition for the type +ast_passes_precise_capturing_not_allowed_here = `use<...>` precise capturing syntax is not allowed in {$loc} + ast_passes_at_least_one_trait = at least one trait must be specified ast_passes_auto_generic = auto traits cannot have generic parameters diff --git a/compiler/rustc_ast_passes/src/ast_validation.rs b/compiler/rustc_ast_passes/src/ast_validation.rs index 0fbb288cc968c..04c06e76e9c2a 100644 --- a/compiler/rustc_ast_passes/src/ast_validation.rs +++ b/compiler/rustc_ast_passes/src/ast_validation.rs @@ -751,7 +751,7 @@ impl<'a> AstValidator<'a> { } } } - TyKind::ImplTrait(_, bounds, _) => { + TyKind::ImplTrait(_, bounds) => { if self.is_impl_trait_banned { self.dcx().emit_err(errors::ImplTraitPath { span: ty.span }); } @@ -1304,6 +1304,7 @@ impl<'a> Visitor<'a> for AstValidator<'a> { } } GenericBound::Outlives(_) => {} + GenericBound::Use(..) => {} } } } @@ -1322,95 +1323,110 @@ impl<'a> Visitor<'a> for AstValidator<'a> { } fn visit_param_bound(&mut self, bound: &'a GenericBound, ctxt: BoundKind) { - if let GenericBound::Trait(poly, modifiers) = bound { - match (ctxt, modifiers.constness, modifiers.polarity) { - (BoundKind::SuperTraits, BoundConstness::Never, BoundPolarity::Maybe(_)) => { - self.dcx().emit_err(errors::OptionalTraitSupertrait { - span: poly.span, - path_str: pprust::path_to_string(&poly.trait_ref.path), - }); - } - (BoundKind::TraitObject, BoundConstness::Never, BoundPolarity::Maybe(_)) => { - self.dcx().emit_err(errors::OptionalTraitObject { span: poly.span }); - } - (BoundKind::TraitObject, BoundConstness::Always(_), BoundPolarity::Positive) => { - self.dcx().emit_err(errors::ConstBoundTraitObject { span: poly.span }); + match bound { + GenericBound::Trait(trait_ref, modifiers) => { + match (ctxt, modifiers.constness, modifiers.polarity) { + (BoundKind::SuperTraits, BoundConstness::Never, BoundPolarity::Maybe(_)) => { + self.dcx().emit_err(errors::OptionalTraitSupertrait { + span: trait_ref.span, + path_str: pprust::path_to_string(&trait_ref.trait_ref.path), + }); + } + (BoundKind::TraitObject, BoundConstness::Never, BoundPolarity::Maybe(_)) => { + self.dcx().emit_err(errors::OptionalTraitObject { span: trait_ref.span }); + } + ( + BoundKind::TraitObject, + BoundConstness::Always(_), + BoundPolarity::Positive, + ) => { + self.dcx().emit_err(errors::ConstBoundTraitObject { span: trait_ref.span }); + } + (_, BoundConstness::Maybe(span), BoundPolarity::Positive) + if let Some(reason) = &self.disallow_tilde_const => + { + let reason = match reason { + DisallowTildeConstContext::Fn(FnKind::Closure(..)) => { + errors::TildeConstReason::Closure + } + DisallowTildeConstContext::Fn(FnKind::Fn(_, ident, ..)) => { + errors::TildeConstReason::Function { ident: ident.span } + } + &DisallowTildeConstContext::Trait(span) => { + errors::TildeConstReason::Trait { span } + } + &DisallowTildeConstContext::TraitImpl(span) => { + errors::TildeConstReason::TraitImpl { span } + } + &DisallowTildeConstContext::Impl(span) => { + // FIXME(effects): Consider providing a help message or even a structured + // suggestion for moving such bounds to the assoc const fns if available. + errors::TildeConstReason::Impl { span } + } + &DisallowTildeConstContext::TraitAssocTy(span) => { + errors::TildeConstReason::TraitAssocTy { span } + } + &DisallowTildeConstContext::TraitImplAssocTy(span) => { + errors::TildeConstReason::TraitImplAssocTy { span } + } + &DisallowTildeConstContext::InherentAssocTy(span) => { + errors::TildeConstReason::InherentAssocTy { span } + } + DisallowTildeConstContext::TraitObject => { + errors::TildeConstReason::TraitObject + } + DisallowTildeConstContext::Item => errors::TildeConstReason::Item, + }; + self.dcx().emit_err(errors::TildeConstDisallowed { span, reason }); + } + ( + _, + BoundConstness::Always(_) | BoundConstness::Maybe(_), + BoundPolarity::Negative(_) | BoundPolarity::Maybe(_), + ) => { + self.dcx().emit_err(errors::IncompatibleTraitBoundModifiers { + span: bound.span(), + left: modifiers.constness.as_str(), + right: modifiers.polarity.as_str(), + }); + } + _ => {} } - (_, BoundConstness::Maybe(span), BoundPolarity::Positive) - if let Some(reason) = &self.disallow_tilde_const => + + // Negative trait bounds are not allowed to have associated constraints + if let BoundPolarity::Negative(_) = modifiers.polarity + && let Some(segment) = trait_ref.trait_ref.path.segments.last() { - let reason = match reason { - DisallowTildeConstContext::Fn(FnKind::Closure(..)) => { - errors::TildeConstReason::Closure - } - DisallowTildeConstContext::Fn(FnKind::Fn(_, ident, ..)) => { - errors::TildeConstReason::Function { ident: ident.span } - } - &DisallowTildeConstContext::Trait(span) => { - errors::TildeConstReason::Trait { span } - } - &DisallowTildeConstContext::TraitImpl(span) => { - errors::TildeConstReason::TraitImpl { span } - } - &DisallowTildeConstContext::Impl(span) => { - // FIXME(effects): Consider providing a help message or even a structured - // suggestion for moving such bounds to the assoc const fns if available. - errors::TildeConstReason::Impl { span } - } - &DisallowTildeConstContext::TraitAssocTy(span) => { - errors::TildeConstReason::TraitAssocTy { span } - } - &DisallowTildeConstContext::TraitImplAssocTy(span) => { - errors::TildeConstReason::TraitImplAssocTy { span } - } - &DisallowTildeConstContext::InherentAssocTy(span) => { - errors::TildeConstReason::InherentAssocTy { span } - } - DisallowTildeConstContext::TraitObject => { - errors::TildeConstReason::TraitObject + match segment.args.as_deref() { + Some(ast::GenericArgs::AngleBracketed(args)) => { + for arg in &args.args { + if let ast::AngleBracketedArg::Constraint(constraint) = arg { + self.dcx().emit_err(errors::ConstraintOnNegativeBound { + span: constraint.span, + }); + } + } } - DisallowTildeConstContext::Item => errors::TildeConstReason::Item, - }; - self.dcx().emit_err(errors::TildeConstDisallowed { span, reason }); - } - ( - _, - BoundConstness::Always(_) | BoundConstness::Maybe(_), - BoundPolarity::Negative(_) | BoundPolarity::Maybe(_), - ) => { - self.dcx().emit_err(errors::IncompatibleTraitBoundModifiers { - span: bound.span(), - left: modifiers.constness.as_str(), - right: modifiers.polarity.as_str(), - }); - } - _ => {} - } - } - - // Negative trait bounds are not allowed to have associated constraints - if let GenericBound::Trait(trait_ref, modifiers) = bound - && let BoundPolarity::Negative(_) = modifiers.polarity - && let Some(segment) = trait_ref.trait_ref.path.segments.last() - { - match segment.args.as_deref() { - Some(ast::GenericArgs::AngleBracketed(args)) => { - for arg in &args.args { - if let ast::AngleBracketedArg::Constraint(constraint) = arg { - self.dcx().emit_err(errors::ConstraintOnNegativeBound { - span: constraint.span, + // The lowered form of parenthesized generic args contains an associated type binding. + Some(ast::GenericArgs::Parenthesized(args)) => { + self.dcx().emit_err(errors::NegativeBoundWithParentheticalNotation { + span: args.span, }); } + None => {} } } - // The lowered form of parenthesized generic args contains an associated type binding. - Some(ast::GenericArgs::Parenthesized(args)) => { - self.dcx().emit_err(errors::NegativeBoundWithParentheticalNotation { - span: args.span, - }); - } - None => {} } + GenericBound::Outlives(_) => {} + GenericBound::Use(_, span) => match ctxt { + BoundKind::Impl => {} + BoundKind::Bound | BoundKind::TraitObject | BoundKind::SuperTraits => { + self.dcx().emit_err(errors::PreciseCapturingNotAllowedHere { + loc: ctxt.descr(), + span: *span, + }) + } + }, } visit::walk_param_bound(self, bound) diff --git a/compiler/rustc_ast_passes/src/errors.rs b/compiler/rustc_ast_passes/src/errors.rs index 260c182bd9e49..cb95b7bce919c 100644 --- a/compiler/rustc_ast_passes/src/errors.rs +++ b/compiler/rustc_ast_passes/src/errors.rs @@ -844,3 +844,11 @@ pub struct MatchArmWithNoBody { #[suggestion(code = " => todo!(),", applicability = "has-placeholders")] pub suggestion: Span, } + +#[derive(Diagnostic)] +#[diag(ast_passes_precise_capturing_not_allowed_here)] +pub struct PreciseCapturingNotAllowedHere { + #[primary_span] + pub span: Span, + pub loc: &'static str, +} diff --git a/compiler/rustc_ast_pretty/src/pprust/state.rs b/compiler/rustc_ast_pretty/src/pprust/state.rs index 4eb2a103fd8f5..0225c95dca8e3 100644 --- a/compiler/rustc_ast_pretty/src/pprust/state.rs +++ b/compiler/rustc_ast_pretty/src/pprust/state.rs @@ -1187,17 +1187,8 @@ impl<'a> State<'a> { } self.print_type_bounds(bounds); } - ast::TyKind::ImplTrait(_, bounds, precise_capturing_args) => { + ast::TyKind::ImplTrait(_, bounds) => { self.word_nbsp("impl"); - if let Some((precise_capturing_args, ..)) = precise_capturing_args.as_deref() { - self.word("use"); - self.word("<"); - self.commasep(Inconsistent, precise_capturing_args, |s, arg| match arg { - ast::PreciseCapturingArg::Arg(p, _) => s.print_path(p, false, 0), - ast::PreciseCapturingArg::Lifetime(lt) => s.print_lifetime(*lt), - }); - self.word(">") - } self.print_type_bounds(bounds); } ast::TyKind::Array(ty, length) => { @@ -1800,6 +1791,15 @@ impl<'a> State<'a> { self.print_poly_trait_ref(tref); } GenericBound::Outlives(lt) => self.print_lifetime(*lt), + GenericBound::Use(args, _) => { + self.word("use"); + self.word("<"); + self.commasep(Inconsistent, args, |s, arg| match arg { + ast::PreciseCapturingArg::Arg(p, _) => s.print_path(p, false, 0), + ast::PreciseCapturingArg::Lifetime(lt) => s.print_lifetime(*lt), + }); + self.word(">") + } } } } diff --git a/compiler/rustc_feature/src/unstable.rs b/compiler/rustc_feature/src/unstable.rs index 58832cb108750..5cb72a2ba385a 100644 --- a/compiler/rustc_feature/src/unstable.rs +++ b/compiler/rustc_feature/src/unstable.rs @@ -567,7 +567,7 @@ declare_features! ( (unstable, optimize_attribute, "1.34.0", Some(54882)), /// Allows postfix match `expr.match { ... }` (unstable, postfix_match, "1.79.0", Some(121618)), - /// Allows `use<'a, 'b, A, B>` in `impl use<...> Trait` for precise capture of generic args. + /// Allows `use<'a, 'b, A, B>` in `impl Trait + use<...>` for precise capture of generic args. (incomplete, precise_capturing, "1.79.0", Some(123432)), /// Allows macro attributes on expressions, statements and non-inline modules. (unstable, proc_macro_hygiene, "1.30.0", Some(54727)), diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs index d4a22c4c31f6a..22a6c06bba323 100644 --- a/compiler/rustc_hir/src/hir.rs +++ b/compiler/rustc_hir/src/hir.rs @@ -463,6 +463,7 @@ pub enum TraitBoundModifier { pub enum GenericBound<'hir> { Trait(PolyTraitRef<'hir>, TraitBoundModifier), Outlives(&'hir Lifetime), + Use(&'hir [PreciseCapturingArg<'hir>], Span), } impl GenericBound<'_> { @@ -477,6 +478,7 @@ impl GenericBound<'_> { match self { GenericBound::Trait(t, ..) => t.span, GenericBound::Outlives(l) => l.ident.span, + GenericBound::Use(_, span) => *span, } } } @@ -2689,8 +2691,6 @@ pub struct OpaqueTy<'hir> { /// originating from a trait method. This makes it so that the opaque is /// lowered as an associated type. pub in_trait: bool, - /// List of arguments captured via `impl use<'a, P, ...> Trait` syntax. - pub precise_capturing_args: Option<(&'hir [PreciseCapturingArg<'hir>], Span)>, } #[derive(Debug, Clone, Copy, HashStable_Generic)] diff --git a/compiler/rustc_hir/src/intravisit.rs b/compiler/rustc_hir/src/intravisit.rs index 5a16f266dab3e..065ecc5d7b7ba 100644 --- a/compiler/rustc_hir/src/intravisit.rs +++ b/compiler/rustc_hir/src/intravisit.rs @@ -532,15 +532,10 @@ pub fn walk_item<'v, V: Visitor<'v>>(visitor: &mut V, item: &'v Item<'v>) -> V:: try_visit!(visitor.visit_ty(ty)); try_visit!(visitor.visit_generics(generics)); } - ItemKind::OpaqueTy(&OpaqueTy { generics, bounds, precise_capturing_args, .. }) => { + ItemKind::OpaqueTy(&OpaqueTy { generics, bounds, .. }) => { try_visit!(visitor.visit_id(item.hir_id())); try_visit!(walk_generics(visitor, generics)); walk_list!(visitor, visit_param_bound, bounds); - if let Some((precise_capturing_args, _)) = precise_capturing_args { - for arg in precise_capturing_args { - try_visit!(visitor.visit_precise_capturing_arg(arg)); - } - } } ItemKind::Enum(ref enum_definition, ref generics) => { try_visit!(visitor.visit_generics(generics)); @@ -1147,6 +1142,10 @@ pub fn walk_param_bound<'v, V: Visitor<'v>>( match *bound { GenericBound::Trait(ref typ, _modifier) => visitor.visit_poly_trait_ref(typ), GenericBound::Outlives(ref lifetime) => visitor.visit_lifetime(lifetime), + GenericBound::Use(args, _) => { + walk_list!(visitor, visit_precise_capturing_arg, args); + V::Result::output() + } } } diff --git a/compiler/rustc_hir_analysis/src/check/check.rs b/compiler/rustc_hir_analysis/src/check/check.rs index 72e5995e892ec..3b53c253195fa 100644 --- a/compiler/rustc_hir_analysis/src/check/check.rs +++ b/compiler/rustc_hir_analysis/src/check/check.rs @@ -481,9 +481,12 @@ fn sanity_check_found_hidden_type<'tcx>( /// 2. Checking that all lifetimes that are implicitly captured are mentioned. /// 3. Asserting that all parameters mentioned in the captures list are invariant. fn check_opaque_precise_captures<'tcx>(tcx: TyCtxt<'tcx>, opaque_def_id: LocalDefId) { - let hir::OpaqueTy { precise_capturing_args, .. } = + let hir::OpaqueTy { bounds, .. } = *tcx.hir_node_by_def_id(opaque_def_id).expect_item().expect_opaque_ty(); - let Some((precise_capturing_args, _)) = precise_capturing_args else { + let Some(precise_capturing_args) = bounds.iter().find_map(|bound| match *bound { + hir::GenericBound::Use(bounds, ..) => Some(bounds), + _ => None, + }) else { // No precise capturing args; nothing to validate return; }; diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs index 9a6bc8a7b7212..c7699b0b310fb 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs @@ -178,6 +178,9 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { lifetime.ident.span, ); } + hir::GenericBound::Use(..) => { + // We don't actually lower `use` into the type layer. + } } } } diff --git a/compiler/rustc_hir_pretty/src/lib.rs b/compiler/rustc_hir_pretty/src/lib.rs index d32d0183c4e47..b21f1eadfb7a3 100644 --- a/compiler/rustc_hir_pretty/src/lib.rs +++ b/compiler/rustc_hir_pretty/src/lib.rs @@ -13,7 +13,7 @@ use rustc_ast_pretty::pprust::{Comments, PrintState}; use rustc_hir as hir; use rustc_hir::{ BindingMode, ByRef, GenericArg, GenericBound, GenericParam, GenericParamKind, HirId, - LifetimeParamKind, Node, PatKind, RangeEnd, Term, TraitBoundModifier, + LifetimeParamKind, Node, PatKind, PreciseCapturingArg, RangeEnd, Term, TraitBoundModifier, }; use rustc_span::source_map::SourceMap; use rustc_span::symbol::{kw, Ident, Symbol}; @@ -2100,10 +2100,24 @@ impl<'a> State<'a> { GenericBound::Outlives(lt) => { self.print_lifetime(lt); } + GenericBound::Use(args, _) => { + self.word("use <"); + + self.commasep(Inconsistent, args, |s, arg| s.print_precise_capturing_arg(*arg)); + + self.word(">"); + } } } } + fn print_precise_capturing_arg(&mut self, arg: PreciseCapturingArg<'_>) { + match arg { + PreciseCapturingArg::Lifetime(lt) => self.print_lifetime(lt), + PreciseCapturingArg::Param(arg) => self.print_ident(arg.ident), + } + } + fn print_generic_params(&mut self, generic_params: &[GenericParam<'_>]) { if !generic_params.is_empty() { self.word("<"); diff --git a/compiler/rustc_lint/src/impl_trait_overcaptures.rs b/compiler/rustc_lint/src/impl_trait_overcaptures.rs index a311c274a6bae..d4f6d388d9fe3 100644 --- a/compiler/rustc_lint/src/impl_trait_overcaptures.rs +++ b/compiler/rustc_lint/src/impl_trait_overcaptures.rs @@ -11,7 +11,7 @@ use rustc_middle::ty::{ self, Ty, TyCtxt, TypeSuperVisitable, TypeVisitable, TypeVisitableExt, TypeVisitor, }; use rustc_session::{declare_lint, declare_lint_pass}; -use rustc_span::{sym, BytePos, Span}; +use rustc_span::{sym, Span}; use crate::fluent_generated as fluent; use crate::{LateContext, LateLintPass}; @@ -53,7 +53,7 @@ declare_lint! { /// while the `impl Display` is live. /// /// To fix this, we can explicitly state that the `impl Display` doesn't - /// capture any lifetimes, using `impl use<> Display`. + /// capture any lifetimes, using `impl Display + use<>`. pub IMPL_TRAIT_OVERCAPTURES, Allow, "`impl Trait` will capture more lifetimes than possibly intended in edition 2024", @@ -79,7 +79,7 @@ declare_lint! { /// # #![feature(precise_capturing, lifetime_capture_rules_2024)] /// # #![allow(incomplete_features)] /// # #![deny(impl_trait_redundant_captures)] - /// fn test<'a>(x: &'a i32) -> impl use<'a> Sized { x } + /// fn test<'a>(x: &'a i32) -> impl Sized + use<'a> { x } /// ``` /// /// {{produces}} @@ -249,7 +249,7 @@ impl<'tcx> TypeVisitor> for VisitOpaqueTypes<'tcx> { // If we have uncaptured args, and if the opaque doesn't already have // `use<>` syntax on it, and we're < edition 2024, then warn the user. if !new_capture_rules - && opaque.precise_capturing_args.is_none() + && !opaque.bounds.iter().any(|bound| matches!(bound, hir::GenericBound::Use(..))) && !uncaptured_spans.is_empty() { let suggestion = if let Ok(snippet) = @@ -268,8 +268,8 @@ impl<'tcx> TypeVisitor> for VisitOpaqueTypes<'tcx> { // Make sure that we're not trying to name any APITs if generics.iter().all(|name| !name.starts_with("impl ")) { Some(( - format!(" use<{}>", generics.join(", ")), - opaque_span.with_lo(opaque_span.lo() + BytePos(4)).shrink_to_lo(), + format!(" + use<{}>", generics.join(", ")), + opaque_span.shrink_to_hi(), )) } else { None @@ -294,7 +294,11 @@ impl<'tcx> TypeVisitor> for VisitOpaqueTypes<'tcx> { // have no uncaptured args, then we should warn to the user that // it's redundant to capture all args explicitly. else if new_capture_rules - && let Some((captured_args, capturing_span)) = opaque.precise_capturing_args + && let Some((captured_args, capturing_span)) = + opaque.bounds.iter().find_map(|bound| match *bound { + hir::GenericBound::Use(a, s) => Some((a, s)), + _ => None, + }) { let mut explicitly_captured = UnordSet::default(); for arg in captured_args { diff --git a/compiler/rustc_lint/src/unused.rs b/compiler/rustc_lint/src/unused.rs index 7a1aa4043be02..195a0f72475f0 100644 --- a/compiler/rustc_lint/src/unused.rs +++ b/compiler/rustc_lint/src/unused.rs @@ -1268,7 +1268,7 @@ impl EarlyLintPass for UnusedParens { ast::TyKind::TraitObject(..) => {} ast::TyKind::BareFn(b) if self.with_self_ty_parens && b.generic_params.len() > 0 => {} - ast::TyKind::ImplTrait(_, bounds, _) if bounds.len() > 1 => {} + ast::TyKind::ImplTrait(_, bounds) if bounds.len() > 1 => {} _ => { let spans = if !ty.span.from_expansion() { r.span diff --git a/compiler/rustc_parse/src/parser/generics.rs b/compiler/rustc_parse/src/parser/generics.rs index 93a15c938ecf1..fde16ac957dfe 100644 --- a/compiler/rustc_parse/src/parser/generics.rs +++ b/compiler/rustc_parse/src/parser/generics.rs @@ -62,7 +62,7 @@ impl<'a> Parser<'a> { let snapshot = self.create_snapshot_for_diagnostic(); match self.parse_ty() { Ok(p) => { - if let TyKind::ImplTrait(_, bounds, None) = &p.kind { + if let TyKind::ImplTrait(_, bounds) = &p.kind { let span = impl_span.to(self.token.span.shrink_to_lo()); let mut err = self.dcx().struct_span_err( span, diff --git a/compiler/rustc_parse/src/parser/item.rs b/compiler/rustc_parse/src/parser/item.rs index 3f5a4afdad8ab..3d2eee247b879 100644 --- a/compiler/rustc_parse/src/parser/item.rs +++ b/compiler/rustc_parse/src/parser/item.rs @@ -633,7 +633,7 @@ impl<'a> Parser<'a> { // This notably includes paths passed through `ty` macro fragments (#46438). TyKind::Path(None, path) => path, other => { - if let TyKind::ImplTrait(_, bounds, None) = other + if let TyKind::ImplTrait(_, bounds) = other && let [bound] = bounds.as_slice() { // Suggest removing extra `impl` keyword: diff --git a/compiler/rustc_parse/src/parser/ty.rs b/compiler/rustc_parse/src/parser/ty.rs index bdb08709f2762..fcd623b477f5d 100644 --- a/compiler/rustc_parse/src/parser/ty.rs +++ b/compiler/rustc_parse/src/parser/ty.rs @@ -316,7 +316,7 @@ impl<'a> Parser<'a> { TyKind::TraitObject(bounds, TraitObjectSyntax::Dyn) } (TyKind::TraitObject(bounds, _), kw::Impl) => { - TyKind::ImplTrait(ast::DUMMY_NODE_ID, bounds, None) + TyKind::ImplTrait(ast::DUMMY_NODE_ID, bounds) } _ => return Err(err), }; @@ -670,24 +670,12 @@ impl<'a> Parser<'a> { }) } - // parse precise captures, if any. This is `use<'lt, 'lt, P, P>`; a list of - // lifetimes and ident params (including SelfUpper). These are validated later - // for order, duplication, and whether they actually reference params. - let precise_capturing = if self.eat_keyword(kw::Use) { - let use_span = self.prev_token.span; - self.psess.gated_spans.gate(sym::precise_capturing, use_span); - let (args, args_span) = self.parse_precise_capturing_args()?; - Some(P((args, use_span.to(args_span)))) - } else { - None - }; - // Always parse bounds greedily for better error recovery. let bounds = self.parse_generic_bounds()?; *impl_dyn_multi = bounds.len() > 1 || self.prev_token.kind == TokenKind::BinOp(token::Plus); - Ok(TyKind::ImplTrait(ast::DUMMY_NODE_ID, bounds, precise_capturing)) + Ok(TyKind::ImplTrait(ast::DUMMY_NODE_ID, bounds)) } fn parse_precise_capturing_args( @@ -834,6 +822,7 @@ impl<'a> Parser<'a> { || self.check(&token::OpenDelim(Delimiter::Parenthesis)) || self.check_keyword(kw::Const) || self.check_keyword(kw::Async) + || self.check_keyword(kw::Use) } /// Parses a bound according to the grammar: @@ -850,6 +839,14 @@ impl<'a> Parser<'a> { let bound = if self.token.is_lifetime() { self.error_lt_bound_with_modifiers(modifiers); self.parse_generic_lt_bound(lo, inner_lo, has_parens)? + } else if self.eat_keyword(kw::Use) { + // parse precise captures, if any. This is `use<'lt, 'lt, P, P>`; a list of + // lifetimes and ident params (including SelfUpper). These are validated later + // for order, duplication, and whether they actually reference params. + let use_span = self.prev_token.span; + self.psess.gated_spans.gate(sym::precise_capturing, use_span); + let (args, args_span) = self.parse_precise_capturing_args()?; + GenericBound::Use(args, use_span.to(args_span)) } else { self.parse_generic_ty_bound(lo, has_parens, modifiers, &leading_token)? }; @@ -1009,7 +1006,7 @@ impl<'a> Parser<'a> { Applicability::MaybeIncorrect, ) } - TyKind::ImplTrait(_, bounds, None) + TyKind::ImplTrait(_, bounds) if let [GenericBound::Trait(tr, ..), ..] = bounds.as_slice() => { ( diff --git a/compiler/rustc_passes/src/hir_stats.rs b/compiler/rustc_passes/src/hir_stats.rs index d49298781a23d..0ba61f8e8b40f 100644 --- a/compiler/rustc_passes/src/hir_stats.rs +++ b/compiler/rustc_passes/src/hir_stats.rs @@ -429,7 +429,7 @@ impl<'v> hir_visit::Visitor<'v> for StatCollector<'v> { fn visit_param_bound(&mut self, b: &'v hir::GenericBound<'v>) { record_variants!( (self, b, b, Id::None, hir, GenericBound, GenericBound), - [Trait, Outlives] + [Trait, Outlives, Use] ); hir_visit::walk_param_bound(self, b) } @@ -659,7 +659,7 @@ impl<'v> ast_visit::Visitor<'v> for StatCollector<'v> { fn visit_param_bound(&mut self, b: &'v ast::GenericBound, _ctxt: BoundKind) { record_variants!( (self, b, b, Id::None, ast, GenericBound, GenericBound), - [Trait, Outlives] + [Trait, Outlives, Use] ); ast_visit::walk_param_bound(self, b) } diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs index c1e83c59f98ce..5ab6ba23a7da6 100644 --- a/compiler/rustc_resolve/src/late.rs +++ b/compiler/rustc_resolve/src/late.rs @@ -799,7 +799,7 @@ impl<'a: 'ast, 'ast, 'tcx> Visitor<'ast> for LateResolutionVisitor<'a, '_, 'ast, self.r.record_partial_res(ty.id, PartialRes::new(res)); visit::walk_ty(self, ty) } - TyKind::ImplTrait(node_id, _, _) => { + TyKind::ImplTrait(node_id, _) => { let candidates = self.lifetime_elision_candidates.take(); visit::walk_ty(self, ty); self.record_lifetime_params_for_impl_trait(*node_id); diff --git a/compiler/rustc_resolve/src/late/diagnostics.rs b/compiler/rustc_resolve/src/late/diagnostics.rs index be24755d4c5a0..75a1aff4fc519 100644 --- a/compiler/rustc_resolve/src/late/diagnostics.rs +++ b/compiler/rustc_resolve/src/late/diagnostics.rs @@ -829,7 +829,7 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> { auto-traits; structs and enums can't be bound in that way", ); if bounds.iter().all(|bound| match bound { - ast::GenericBound::Outlives(_) => true, + ast::GenericBound::Outlives(_) | ast::GenericBound::Use(..) => true, ast::GenericBound::Trait(tr, _) => tr.span == base_error.span, }) { let mut sugg = vec![]; @@ -3210,7 +3210,7 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> { .inputs .iter() .filter_map(|param| match ¶m.ty.kind { - TyKind::ImplTrait(_, bounds, _) => Some(bounds), + TyKind::ImplTrait(_, bounds) => Some(bounds), _ => None, }) .flat_map(|bounds| bounds.into_iter()) diff --git a/src/tools/clippy/clippy_lints/src/needless_maybe_sized.rs b/src/tools/clippy/clippy_lints/src/needless_maybe_sized.rs index 06ae1723a03d4..4922c87b206c0 100644 --- a/src/tools/clippy/clippy_lints/src/needless_maybe_sized.rs +++ b/src/tools/clippy/clippy_lints/src/needless_maybe_sized.rs @@ -73,7 +73,7 @@ fn type_param_bounds<'tcx>(generics: &'tcx Generics<'tcx>) -> impl Iterator None, + GenericBound::Outlives(_) | GenericBound::Use(..) => None, }) .filter(|bound| !bound.trait_bound.span.from_expansion()), ) diff --git a/tests/ui/feature-gates/feature-gate-precise-capturing.rs b/tests/ui/feature-gates/feature-gate-precise-capturing.rs index 0c3b49776230c..47a21539d3779 100644 --- a/tests/ui/feature-gates/feature-gate-precise-capturing.rs +++ b/tests/ui/feature-gates/feature-gate-precise-capturing.rs @@ -1,4 +1,4 @@ -fn hello() -> impl use<> Sized {} +fn hello() -> impl Sized + use<> {} //~^ ERROR precise captures on `impl Trait` are experimental fn main() {} diff --git a/tests/ui/feature-gates/feature-gate-precise-capturing.stderr b/tests/ui/feature-gates/feature-gate-precise-capturing.stderr index 102b39148f9f0..04365408880d7 100644 --- a/tests/ui/feature-gates/feature-gate-precise-capturing.stderr +++ b/tests/ui/feature-gates/feature-gate-precise-capturing.stderr @@ -1,8 +1,8 @@ error[E0658]: precise captures on `impl Trait` are experimental - --> $DIR/feature-gate-precise-capturing.rs:1:20 + --> $DIR/feature-gate-precise-capturing.rs:1:28 | -LL | fn hello() -> impl use<> Sized {} - | ^^^ +LL | fn hello() -> impl Sized + use<> {} + | ^^^ | = note: see issue #123432 for more information = help: add `#![feature(precise_capturing)]` to the crate attributes to enable diff --git a/tests/ui/impl-trait/precise-capturing/apit.rs b/tests/ui/impl-trait/precise-capturing/apit.rs index efcac9ebb0b84..98e7da4e34a55 100644 --- a/tests/ui/impl-trait/precise-capturing/apit.rs +++ b/tests/ui/impl-trait/precise-capturing/apit.rs @@ -1,7 +1,7 @@ #![feature(precise_capturing)] //~^ WARN the feature `precise_capturing` is incomplete -fn hello(_: impl use<> Sized) {} +fn hello(_: impl Sized + use<>) {} //~^ ERROR `use<...>` precise capturing syntax not allowed on argument-position `impl Trait` fn main() {} diff --git a/tests/ui/impl-trait/precise-capturing/apit.stderr b/tests/ui/impl-trait/precise-capturing/apit.stderr index 96548f5732f57..b676ed260cb7f 100644 --- a/tests/ui/impl-trait/precise-capturing/apit.stderr +++ b/tests/ui/impl-trait/precise-capturing/apit.stderr @@ -8,10 +8,10 @@ LL | #![feature(precise_capturing)] = note: `#[warn(incomplete_features)]` on by default error: `use<...>` precise capturing syntax not allowed on argument-position `impl Trait` - --> $DIR/apit.rs:4:18 + --> $DIR/apit.rs:4:26 | -LL | fn hello(_: impl use<> Sized) {} - | ^^^^^ +LL | fn hello(_: impl Sized + use<>) {} + | ^^^^^ error: aborting due to 1 previous error; 1 warning emitted diff --git a/tests/ui/impl-trait/precise-capturing/bad-lifetimes.rs b/tests/ui/impl-trait/precise-capturing/bad-lifetimes.rs index 623063a8f5028..d9ea20b1e30a1 100644 --- a/tests/ui/impl-trait/precise-capturing/bad-lifetimes.rs +++ b/tests/ui/impl-trait/precise-capturing/bad-lifetimes.rs @@ -1,14 +1,14 @@ #![feature(precise_capturing)] //~^ WARN the feature `precise_capturing` is incomplete -fn no_elided_lt() -> impl use<'_> Sized {} +fn no_elided_lt() -> impl Sized + use<'_> {} //~^ ERROR missing lifetime specifier //~| ERROR expected lifetime parameter in `use<...>` precise captures list, found `'_` -fn static_lt() -> impl use<'static> Sized {} +fn static_lt() -> impl Sized + use<'static> {} //~^ ERROR expected lifetime parameter in `use<...>` precise captures list, found `'static` -fn missing_lt() -> impl use<'missing> Sized {} +fn missing_lt() -> impl Sized + use<'missing> {} //~^ ERROR use of undeclared lifetime name `'missing` fn main() {} diff --git a/tests/ui/impl-trait/precise-capturing/bad-lifetimes.stderr b/tests/ui/impl-trait/precise-capturing/bad-lifetimes.stderr index a926362c50c83..ac8ec34e341e3 100644 --- a/tests/ui/impl-trait/precise-capturing/bad-lifetimes.stderr +++ b/tests/ui/impl-trait/precise-capturing/bad-lifetimes.stderr @@ -1,20 +1,20 @@ error[E0106]: missing lifetime specifier - --> $DIR/bad-lifetimes.rs:4:31 + --> $DIR/bad-lifetimes.rs:4:39 | -LL | fn no_elided_lt() -> impl use<'_> Sized {} - | ^^ expected named lifetime parameter +LL | fn no_elided_lt() -> impl Sized + use<'_> {} + | ^^ expected named lifetime parameter | = help: this function's return type contains a borrowed value, but there is no value for it to be borrowed from help: consider using the `'static` lifetime, but this is uncommon unless you're returning a borrowed value from a `const` or a `static`, or if you will only have owned values | -LL | fn no_elided_lt() -> impl use<'static> Sized {} - | ~~~~~~~ +LL | fn no_elided_lt() -> impl Sized + use<'static> {} + | ~~~~~~~ error[E0261]: use of undeclared lifetime name `'missing` - --> $DIR/bad-lifetimes.rs:11:29 + --> $DIR/bad-lifetimes.rs:11:37 | -LL | fn missing_lt() -> impl use<'missing> Sized {} - | - ^^^^^^^^ undeclared lifetime +LL | fn missing_lt() -> impl Sized + use<'missing> {} + | - ^^^^^^^^ undeclared lifetime | | | help: consider introducing lifetime `'missing` here: `<'missing>` @@ -28,16 +28,16 @@ LL | #![feature(precise_capturing)] = note: `#[warn(incomplete_features)]` on by default error: expected lifetime parameter in `use<...>` precise captures list, found `'_` - --> $DIR/bad-lifetimes.rs:4:31 + --> $DIR/bad-lifetimes.rs:4:39 | -LL | fn no_elided_lt() -> impl use<'_> Sized {} - | ^^ +LL | fn no_elided_lt() -> impl Sized + use<'_> {} + | ^^ error: expected lifetime parameter in `use<...>` precise captures list, found `'static` - --> $DIR/bad-lifetimes.rs:8:28 + --> $DIR/bad-lifetimes.rs:8:36 | -LL | fn static_lt() -> impl use<'static> Sized {} - | ^^^^^^^ +LL | fn static_lt() -> impl Sized + use<'static> {} + | ^^^^^^^ error: aborting due to 4 previous errors; 1 warning emitted diff --git a/tests/ui/impl-trait/precise-capturing/bad-params.rs b/tests/ui/impl-trait/precise-capturing/bad-params.rs index 7970d49bf7c07..4d9392f76f24d 100644 --- a/tests/ui/impl-trait/precise-capturing/bad-params.rs +++ b/tests/ui/impl-trait/precise-capturing/bad-params.rs @@ -1,19 +1,19 @@ #![feature(precise_capturing)] //~^ WARN the feature `precise_capturing` is incomplete -fn missing() -> impl use Sized {} +fn missing() -> impl Sized + use {} //~^ ERROR cannot find type `T` in this scope -fn missing_self() -> impl use Sized {} +fn missing_self() -> impl Sized + use {} //~^ ERROR cannot find type `Self` in this scope struct MyType; impl MyType { - fn self_is_not_param() -> impl use Sized {} + fn self_is_not_param() -> impl Sized + use {} //~^ ERROR `Self` can't be captured in `use<...>` precise captures list, since it is an alias } -fn hello() -> impl use Sized {} +fn hello() -> impl Sized + use {} //~^ ERROR expected type or const parameter in `use<...>` precise captures list, found function fn main() {} diff --git a/tests/ui/impl-trait/precise-capturing/bad-params.stderr b/tests/ui/impl-trait/precise-capturing/bad-params.stderr index 27bf05302f9b1..309a8128fe4ed 100644 --- a/tests/ui/impl-trait/precise-capturing/bad-params.stderr +++ b/tests/ui/impl-trait/precise-capturing/bad-params.stderr @@ -1,19 +1,19 @@ error[E0412]: cannot find type `T` in this scope - --> $DIR/bad-params.rs:4:26 + --> $DIR/bad-params.rs:4:34 | -LL | fn missing() -> impl use Sized {} - | ^ not found in this scope +LL | fn missing() -> impl Sized + use {} + | ^ not found in this scope | help: you might be missing a type parameter | -LL | fn missing() -> impl use Sized {} +LL | fn missing() -> impl Sized + use {} | +++ error[E0411]: cannot find type `Self` in this scope - --> $DIR/bad-params.rs:7:31 + --> $DIR/bad-params.rs:7:39 | -LL | fn missing_self() -> impl use Sized {} - | ------------ ^^^^ `Self` is only available in impls, traits, and type definitions +LL | fn missing_self() -> impl Sized + use {} + | ------------ ^^^^ `Self` is only available in impls, traits, and type definitions | | | `Self` not allowed in a function @@ -27,18 +27,18 @@ LL | #![feature(precise_capturing)] = note: `#[warn(incomplete_features)]` on by default error: `Self` can't be captured in `use<...>` precise captures list, since it is an alias - --> $DIR/bad-params.rs:12:40 + --> $DIR/bad-params.rs:12:48 | LL | impl MyType { | ----------- `Self` is not a generic argument, but an alias to the type of the implementation -LL | fn self_is_not_param() -> impl use Sized {} - | ^^^^ +LL | fn self_is_not_param() -> impl Sized + use {} + | ^^^^ error: expected type or const parameter in `use<...>` precise captures list, found function - --> $DIR/bad-params.rs:16:24 + --> $DIR/bad-params.rs:16:32 | -LL | fn hello() -> impl use Sized {} - | ^^^^^ +LL | fn hello() -> impl Sized + use {} + | ^^^^^ error: aborting due to 4 previous errors; 1 warning emitted diff --git a/tests/ui/impl-trait/precise-capturing/capture-parent-arg.rs b/tests/ui/impl-trait/precise-capturing/capture-parent-arg.rs index 35b28d0e6fb56..f4acc4db269de 100644 --- a/tests/ui/impl-trait/precise-capturing/capture-parent-arg.rs +++ b/tests/ui/impl-trait/precise-capturing/capture-parent-arg.rs @@ -13,25 +13,25 @@ impl Tr for W<'_> { // The normal way of capturing `'a`... impl<'a> W<'a> { - fn good1() -> impl use<'a> Into< as Tr>::Assoc> {} + fn good1() -> impl Into< as Tr>::Assoc> + use<'a> {} } // This ensures that we don't error when we capture the *parent* copy of `'a`, // since the opaque captures that rather than the duplicated `'a` lifetime // synthesized from mentioning `'a` directly in the bounds. impl<'a> W<'a> { - fn good2() -> impl use<'a> Into<::Assoc> {} + fn good2() -> impl Into<::Assoc> + use<'a> {} } // The normal way of capturing `'a`... but not mentioned in the bounds. impl<'a> W<'a> { - fn bad1() -> impl use<> Into< as Tr>::Assoc> {} + fn bad1() -> impl Into< as Tr>::Assoc> + use<> {} //~^ ERROR `impl Trait` captures lifetime parameter, but it is not mentioned in `use<...>` precise captures list } // But also make sure that we error here... impl<'a> W<'a> { - fn bad2() -> impl use<> Into<::Assoc> {} + fn bad2() -> impl Into<::Assoc> + use<> {} //~^ ERROR `impl Trait` captures lifetime parameter, but it is not mentioned in `use<...>` precise captures list } diff --git a/tests/ui/impl-trait/precise-capturing/capture-parent-arg.stderr b/tests/ui/impl-trait/precise-capturing/capture-parent-arg.stderr index 13aaa9997073d..447f74dca2bb0 100644 --- a/tests/ui/impl-trait/precise-capturing/capture-parent-arg.stderr +++ b/tests/ui/impl-trait/precise-capturing/capture-parent-arg.stderr @@ -8,20 +8,20 @@ LL | #![feature(precise_capturing)] = note: `#[warn(incomplete_features)]` on by default error: `impl Trait` captures lifetime parameter, but it is not mentioned in `use<...>` precise captures list - --> $DIR/capture-parent-arg.rs:28:37 + --> $DIR/capture-parent-arg.rs:28:31 | LL | impl<'a> W<'a> { | -- this lifetime parameter is captured -LL | fn bad1() -> impl use<> Into< as Tr>::Assoc> {} - | -------------------^^---------------- lifetime captured due to being mentioned in the bounds of the `impl Trait` +LL | fn bad1() -> impl Into< as Tr>::Assoc> + use<> {} + | -------------^^------------------------ lifetime captured due to being mentioned in the bounds of the `impl Trait` error: `impl Trait` captures lifetime parameter, but it is not mentioned in `use<...>` precise captures list --> $DIR/capture-parent-arg.rs:34:18 | LL | impl<'a> W<'a> { | -- this lifetime parameter is captured -LL | fn bad2() -> impl use<> Into<::Assoc> {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ lifetime captured due to being mentioned in the bounds of the `impl Trait` +LL | fn bad2() -> impl Into<::Assoc> + use<> {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ lifetime captured due to being mentioned in the bounds of the `impl Trait` error: aborting due to 2 previous errors; 1 warning emitted diff --git a/tests/ui/impl-trait/precise-capturing/elided.rs b/tests/ui/impl-trait/precise-capturing/elided.rs index de80e8a5d581b..71e269e03a3bd 100644 --- a/tests/ui/impl-trait/precise-capturing/elided.rs +++ b/tests/ui/impl-trait/precise-capturing/elided.rs @@ -3,6 +3,6 @@ #![feature(precise_capturing)] //~^ WARN the feature `precise_capturing` is incomplete -fn elided(x: &()) -> impl use<'_> Sized { x } +fn elided(x: &()) -> impl Sized + use<'_> { x } fn main() {} diff --git a/tests/ui/impl-trait/precise-capturing/forgot-to-capture-const.rs b/tests/ui/impl-trait/precise-capturing/forgot-to-capture-const.rs index 1b604e6c358ba..49466585c52d0 100644 --- a/tests/ui/impl-trait/precise-capturing/forgot-to-capture-const.rs +++ b/tests/ui/impl-trait/precise-capturing/forgot-to-capture-const.rs @@ -1,7 +1,7 @@ #![feature(precise_capturing)] //~^ WARN the feature `precise_capturing` is incomplete -fn constant() -> impl use<> Sized {} +fn constant() -> impl Sized + use<> {} //~^ ERROR `impl Trait` must mention all const parameters in scope fn main() {} diff --git a/tests/ui/impl-trait/precise-capturing/forgot-to-capture-const.stderr b/tests/ui/impl-trait/precise-capturing/forgot-to-capture-const.stderr index 3f78e7c56b6eb..ce27f79a9d680 100644 --- a/tests/ui/impl-trait/precise-capturing/forgot-to-capture-const.stderr +++ b/tests/ui/impl-trait/precise-capturing/forgot-to-capture-const.stderr @@ -10,8 +10,8 @@ LL | #![feature(precise_capturing)] error: `impl Trait` must mention all const parameters in scope in `use<...>` --> $DIR/forgot-to-capture-const.rs:4:34 | -LL | fn constant() -> impl use<> Sized {} - | -------------- ^^^^^^^^^^^^^^^^ +LL | fn constant() -> impl Sized + use<> {} + | -------------- ^^^^^^^^^^^^^^^^^^ | | | const parameter is implicitly captured by this `impl Trait` | diff --git a/tests/ui/impl-trait/precise-capturing/forgot-to-capture-lifetime.rs b/tests/ui/impl-trait/precise-capturing/forgot-to-capture-lifetime.rs index cc86bf83107e1..9af36817847c3 100644 --- a/tests/ui/impl-trait/precise-capturing/forgot-to-capture-lifetime.rs +++ b/tests/ui/impl-trait/precise-capturing/forgot-to-capture-lifetime.rs @@ -1,10 +1,10 @@ #![feature(precise_capturing)] //~^ WARN the feature `precise_capturing` is incomplete -fn lifetime_in_bounds<'a>(x: &'a ()) -> impl use<> Into<&'a ()> { x } +fn lifetime_in_bounds<'a>(x: &'a ()) -> impl Into<&'a ()> + use<> { x } //~^ ERROR `impl Trait` captures lifetime parameter, but it is not mentioned in `use<...>` precise captures list -fn lifetime_in_hidden<'a>(x: &'a ()) -> impl use<> Sized { x } +fn lifetime_in_hidden<'a>(x: &'a ()) -> impl Sized + use<> { x } //~^ ERROR hidden type for `impl Sized` captures lifetime that does not appear in bounds fn main() {} diff --git a/tests/ui/impl-trait/precise-capturing/forgot-to-capture-lifetime.stderr b/tests/ui/impl-trait/precise-capturing/forgot-to-capture-lifetime.stderr index e472c898050a3..c884b6b0d91f4 100644 --- a/tests/ui/impl-trait/precise-capturing/forgot-to-capture-lifetime.stderr +++ b/tests/ui/impl-trait/precise-capturing/forgot-to-capture-lifetime.stderr @@ -8,27 +8,27 @@ LL | #![feature(precise_capturing)] = note: `#[warn(incomplete_features)]` on by default error: `impl Trait` captures lifetime parameter, but it is not mentioned in `use<...>` precise captures list - --> $DIR/forgot-to-capture-lifetime.rs:4:58 + --> $DIR/forgot-to-capture-lifetime.rs:4:52 | -LL | fn lifetime_in_bounds<'a>(x: &'a ()) -> impl use<> Into<&'a ()> { x } - | -- -----------------^^---- +LL | fn lifetime_in_bounds<'a>(x: &'a ()) -> impl Into<&'a ()> + use<> { x } + | -- -----------^^------------ | | | | | lifetime captured due to being mentioned in the bounds of the `impl Trait` | this lifetime parameter is captured error[E0700]: hidden type for `impl Sized` captures lifetime that does not appear in bounds - --> $DIR/forgot-to-capture-lifetime.rs:7:60 + --> $DIR/forgot-to-capture-lifetime.rs:7:62 | -LL | fn lifetime_in_hidden<'a>(x: &'a ()) -> impl use<> Sized { x } - | -- ---------------- ^ +LL | fn lifetime_in_hidden<'a>(x: &'a ()) -> impl Sized + use<> { x } + | -- ------------------ ^ | | | | | opaque type defined here | hidden type `&'a ()` captures the lifetime `'a` as defined here | help: to declare that `impl Sized` captures `'a`, you can add an explicit `'a` lifetime bound | -LL | fn lifetime_in_hidden<'a>(x: &'a ()) -> impl use<> Sized + 'a { x } - | ++++ +LL | fn lifetime_in_hidden<'a>(x: &'a ()) -> impl Sized + use<> + 'a { x } + | ++++ error: aborting due to 2 previous errors; 1 warning emitted diff --git a/tests/ui/impl-trait/precise-capturing/forgot-to-capture-type.rs b/tests/ui/impl-trait/precise-capturing/forgot-to-capture-type.rs index d359ea5e26df6..bfb0745805a5a 100644 --- a/tests/ui/impl-trait/precise-capturing/forgot-to-capture-type.rs +++ b/tests/ui/impl-trait/precise-capturing/forgot-to-capture-type.rs @@ -1,11 +1,11 @@ #![feature(precise_capturing)] //~^ WARN the feature `precise_capturing` is incomplete -fn type_param() -> impl use<> Sized {} +fn type_param() -> impl Sized + use<> {} //~^ ERROR `impl Trait` must mention all type parameters in scope trait Foo { - fn bar() -> impl use<> Sized; + fn bar() -> impl Sized + use<>; //~^ ERROR `impl Trait` must mention the `Self` type of the trait } diff --git a/tests/ui/impl-trait/precise-capturing/forgot-to-capture-type.stderr b/tests/ui/impl-trait/precise-capturing/forgot-to-capture-type.stderr index 26994d0bdbf19..91e7e79564d84 100644 --- a/tests/ui/impl-trait/precise-capturing/forgot-to-capture-type.stderr +++ b/tests/ui/impl-trait/precise-capturing/forgot-to-capture-type.stderr @@ -10,8 +10,8 @@ LL | #![feature(precise_capturing)] error: `impl Trait` must mention all type parameters in scope in `use<...>` --> $DIR/forgot-to-capture-type.rs:4:23 | -LL | fn type_param() -> impl use<> Sized {} - | - ^^^^^^^^^^^^^^^^ +LL | fn type_param() -> impl Sized + use<> {} + | - ^^^^^^^^^^^^^^^^^^ | | | type parameter is implicitly captured by this `impl Trait` | @@ -22,8 +22,8 @@ error: `impl Trait` must mention the `Self` type of the trait in `use<...>` | LL | trait Foo { | --------- `Self` type parameter is implicitly captured by this `impl Trait` -LL | fn bar() -> impl use<> Sized; - | ^^^^^^^^^^^^^^^^ +LL | fn bar() -> impl Sized + use<>; + | ^^^^^^^^^^^^^^^^^^ | = note: currently, all type parameters are required to be mentioned in the precise captures list diff --git a/tests/ui/impl-trait/precise-capturing/higher-ranked.rs b/tests/ui/impl-trait/precise-capturing/higher-ranked.rs index 28fb1fa4b9ec6..7c8038600d132 100644 --- a/tests/ui/impl-trait/precise-capturing/higher-ranked.rs +++ b/tests/ui/impl-trait/precise-capturing/higher-ranked.rs @@ -13,6 +13,6 @@ impl Trait<'_> for () { type Item = Vec<()>; } -fn hello() -> impl for<'a> Trait<'a, Item = impl use<> IntoIterator> {} +fn hello() -> impl for<'a> Trait<'a, Item = impl IntoIterator + use<>> {} fn main() {} diff --git a/tests/ui/impl-trait/precise-capturing/ordering.rs b/tests/ui/impl-trait/precise-capturing/ordering.rs index 2bace798c5702..ff326ae6d023e 100644 --- a/tests/ui/impl-trait/precise-capturing/ordering.rs +++ b/tests/ui/impl-trait/precise-capturing/ordering.rs @@ -1,16 +1,16 @@ #![feature(precise_capturing)] //~^ WARN the feature `precise_capturing` is incomplete -fn lt<'a>() -> impl use<'a, 'a> Sized {} +fn lt<'a>() -> impl Sized + use<'a, 'a> {} //~^ ERROR cannot capture parameter `'a` twice -fn ty() -> impl use Sized {} +fn ty() -> impl Sized + use {} //~^ ERROR cannot capture parameter `T` twice -fn ct() -> impl use Sized {} +fn ct() -> impl Sized + use {} //~^ ERROR cannot capture parameter `N` twice -fn ordering<'a, T>() -> impl use Sized {} +fn ordering<'a, T>() -> impl Sized + use {} //~^ ERROR lifetime parameter `'a` must be listed before non-lifetime parameters fn main() {} diff --git a/tests/ui/impl-trait/precise-capturing/ordering.stderr b/tests/ui/impl-trait/precise-capturing/ordering.stderr index 3f545108df563..65059b854b376 100644 --- a/tests/ui/impl-trait/precise-capturing/ordering.stderr +++ b/tests/ui/impl-trait/precise-capturing/ordering.stderr @@ -8,30 +8,30 @@ LL | #![feature(precise_capturing)] = note: `#[warn(incomplete_features)]` on by default error: cannot capture parameter `'a` twice - --> $DIR/ordering.rs:4:25 + --> $DIR/ordering.rs:4:33 | -LL | fn lt<'a>() -> impl use<'a, 'a> Sized {} - | ^^ -- parameter captured again here +LL | fn lt<'a>() -> impl Sized + use<'a, 'a> {} + | ^^ -- parameter captured again here error: cannot capture parameter `T` twice - --> $DIR/ordering.rs:7:24 + --> $DIR/ordering.rs:7:32 | -LL | fn ty() -> impl use Sized {} - | ^ - parameter captured again here +LL | fn ty() -> impl Sized + use {} + | ^ - parameter captured again here error: cannot capture parameter `N` twice - --> $DIR/ordering.rs:10:37 + --> $DIR/ordering.rs:10:45 | -LL | fn ct() -> impl use Sized {} - | ^ - parameter captured again here +LL | fn ct() -> impl Sized + use {} + | ^ - parameter captured again here error: lifetime parameter `'a` must be listed before non-lifetime parameters - --> $DIR/ordering.rs:13:37 + --> $DIR/ordering.rs:13:45 | -LL | fn ordering<'a, T>() -> impl use Sized {} - | - ^^ - | | - | move the lifetime before this parameter +LL | fn ordering<'a, T>() -> impl Sized + use {} + | - ^^ + | | + | move the lifetime before this parameter error: aborting due to 4 previous errors; 1 warning emitted diff --git a/tests/ui/impl-trait/precise-capturing/outlives.rs b/tests/ui/impl-trait/precise-capturing/outlives.rs index 71e6333934e7d..c316a869ec5ba 100644 --- a/tests/ui/impl-trait/precise-capturing/outlives.rs +++ b/tests/ui/impl-trait/precise-capturing/outlives.rs @@ -5,7 +5,7 @@ #![feature(lifetime_capture_rules_2024, precise_capturing)] //~^ WARN the feature `precise_capturing` is incomplete -fn hello<'a: 'a, 'b: 'b>() -> impl use<'a> Sized { } +fn hello<'a: 'a, 'b: 'b>() -> impl Sized + use<'a> { } fn outlives<'a, T: 'a>(_: T) {} diff --git a/tests/ui/impl-trait/precise-capturing/overcaptures-2024.fixed b/tests/ui/impl-trait/precise-capturing/overcaptures-2024.fixed index 014ab23e4ebc2..5ac296a9cbdf0 100644 --- a/tests/ui/impl-trait/precise-capturing/overcaptures-2024.fixed +++ b/tests/ui/impl-trait/precise-capturing/overcaptures-2024.fixed @@ -4,15 +4,15 @@ #![allow(unused, incomplete_features)] #![deny(impl_trait_overcaptures)] -fn named<'a>(x: &'a i32) -> impl use<> Sized { *x } +fn named<'a>(x: &'a i32) -> impl Sized + use<> { *x } //~^ ERROR `impl Sized` will capture more lifetimes than possibly intended in edition 2024 -fn implicit(x: &i32) -> impl use<> Sized { *x } +fn implicit(x: &i32) -> impl Sized + use<> { *x } //~^ ERROR `impl Sized` will capture more lifetimes than possibly intended in edition 2024 struct W; impl W { - fn hello(&self, x: &i32) -> impl use<'_> Sized + '_ { self } + fn hello(&self, x: &i32) -> impl Sized + '_ + use<'_> { self } //~^ ERROR `impl Sized + '_` will capture more lifetimes than possibly intended in edition 2024 } @@ -23,7 +23,7 @@ impl Higher<'_> for () { type Output = (); } -fn hrtb() -> impl for<'a> Higher<'a, Output = impl use<> Sized> {} +fn hrtb() -> impl for<'a> Higher<'a, Output = impl Sized + use<>> {} //~^ ERROR `impl Sized` will capture more lifetimes than possibly intended in edition 2024 fn main() {} diff --git a/tests/ui/impl-trait/precise-capturing/overcaptures-2024.stderr b/tests/ui/impl-trait/precise-capturing/overcaptures-2024.stderr index 16cb8b7e94b11..f8bb7f099af9e 100644 --- a/tests/ui/impl-trait/precise-capturing/overcaptures-2024.stderr +++ b/tests/ui/impl-trait/precise-capturing/overcaptures-2024.stderr @@ -17,8 +17,8 @@ LL | #![deny(impl_trait_overcaptures)] | ^^^^^^^^^^^^^^^^^^^^^^^ help: use the precise capturing `use<...>` syntax to make the captures explicit | -LL | fn named<'a>(x: &'a i32) -> impl use<> Sized { *x } - | +++++ +LL | fn named<'a>(x: &'a i32) -> impl Sized + use<> { *x } + | +++++++ error: `impl Sized` will capture more lifetimes than possibly intended in edition 2024 --> $DIR/overcaptures-2024.rs:10:25 @@ -34,8 +34,8 @@ LL | fn implicit(x: &i32) -> impl Sized { *x } = note: all lifetimes in scope will be captured by `impl Trait`s in edition 2024 help: use the precise capturing `use<...>` syntax to make the captures explicit | -LL | fn implicit(x: &i32) -> impl use<> Sized { *x } - | +++++ +LL | fn implicit(x: &i32) -> impl Sized + use<> { *x } + | +++++++ error: `impl Sized + '_` will capture more lifetimes than possibly intended in edition 2024 --> $DIR/overcaptures-2024.rs:15:33 @@ -51,8 +51,8 @@ LL | fn hello(&self, x: &i32) -> impl Sized + '_ { self } = note: all lifetimes in scope will be captured by `impl Trait`s in edition 2024 help: use the precise capturing `use<...>` syntax to make the captures explicit | -LL | fn hello(&self, x: &i32) -> impl use<'_> Sized + '_ { self } - | +++++++ +LL | fn hello(&self, x: &i32) -> impl Sized + '_ + use<'_> { self } + | +++++++++ error: `impl Sized` will capture more lifetimes than possibly intended in edition 2024 --> $DIR/overcaptures-2024.rs:26:47 @@ -68,8 +68,8 @@ LL | fn hrtb() -> impl for<'a> Higher<'a, Output = impl Sized> {} = note: all lifetimes in scope will be captured by `impl Trait`s in edition 2024 help: use the precise capturing `use<...>` syntax to make the captures explicit | -LL | fn hrtb() -> impl for<'a> Higher<'a, Output = impl use<> Sized> {} - | +++++ +LL | fn hrtb() -> impl for<'a> Higher<'a, Output = impl Sized + use<>> {} + | +++++++ error: aborting due to 4 previous errors diff --git a/tests/ui/impl-trait/precise-capturing/redundant.rs b/tests/ui/impl-trait/precise-capturing/redundant.rs index 108a4cb64aa8d..30acfe77e2e31 100644 --- a/tests/ui/impl-trait/precise-capturing/redundant.rs +++ b/tests/ui/impl-trait/precise-capturing/redundant.rs @@ -4,21 +4,21 @@ #![feature(precise_capturing)] //~^ WARN the feature `precise_capturing` is incomplete -fn hello<'a>() -> impl use<'a> Sized {} +fn hello<'a>() -> impl Sized + use<'a> {} //~^ WARN all possible in-scope parameters are already captured struct Inherent; impl Inherent { - fn inherent(&self) -> impl use<'_> Sized {} + fn inherent(&self) -> impl Sized + use<'_> {} //~^ WARN all possible in-scope parameters are already captured } trait Test<'a> { - fn in_trait() -> impl use<'a, Self> Sized; + fn in_trait() -> impl Sized + use<'a, Self>; //~^ WARN all possible in-scope parameters are already captured } impl<'a> Test<'a> for () { - fn in_trait() -> impl use<'a> Sized {} + fn in_trait() -> impl Sized + use<'a> {} //~^ WARN all possible in-scope parameters are already captured } diff --git a/tests/ui/impl-trait/precise-capturing/redundant.stderr b/tests/ui/impl-trait/precise-capturing/redundant.stderr index 325f04d3536a2..d100fd02053ec 100644 --- a/tests/ui/impl-trait/precise-capturing/redundant.stderr +++ b/tests/ui/impl-trait/precise-capturing/redundant.stderr @@ -10,36 +10,36 @@ LL | #![feature(precise_capturing)] warning: all possible in-scope parameters are already captured, so `use<...>` syntax is redundant --> $DIR/redundant.rs:7:19 | -LL | fn hello<'a>() -> impl use<'a> Sized {} - | ^^^^^-------^^^^^^ - | | - | help: remove the `use<...>` syntax +LL | fn hello<'a>() -> impl Sized + use<'a> {} + | ^^^^^^^^^^^^^------- + | | + | help: remove the `use<...>` syntax | = note: `#[warn(impl_trait_redundant_captures)]` on by default warning: all possible in-scope parameters are already captured, so `use<...>` syntax is redundant --> $DIR/redundant.rs:12:27 | -LL | fn inherent(&self) -> impl use<'_> Sized {} - | ^^^^^-------^^^^^^ - | | - | help: remove the `use<...>` syntax +LL | fn inherent(&self) -> impl Sized + use<'_> {} + | ^^^^^^^^^^^^^------- + | | + | help: remove the `use<...>` syntax warning: all possible in-scope parameters are already captured, so `use<...>` syntax is redundant --> $DIR/redundant.rs:17:22 | -LL | fn in_trait() -> impl use<'a, Self> Sized; - | ^^^^^-------------^^^^^^ - | | - | help: remove the `use<...>` syntax +LL | fn in_trait() -> impl Sized + use<'a, Self>; + | ^^^^^^^^^^^^^------------- + | | + | help: remove the `use<...>` syntax warning: all possible in-scope parameters are already captured, so `use<...>` syntax is redundant --> $DIR/redundant.rs:21:22 | -LL | fn in_trait() -> impl use<'a> Sized {} - | ^^^^^-------^^^^^^ - | | - | help: remove the `use<...>` syntax +LL | fn in_trait() -> impl Sized + use<'a> {} + | ^^^^^^^^^^^^^------- + | | + | help: remove the `use<...>` syntax warning: 5 warnings emitted diff --git a/tests/ui/impl-trait/precise-capturing/self-capture.rs b/tests/ui/impl-trait/precise-capturing/self-capture.rs index ecbc388e27be6..1dbbcadff6d6e 100644 --- a/tests/ui/impl-trait/precise-capturing/self-capture.rs +++ b/tests/ui/impl-trait/precise-capturing/self-capture.rs @@ -4,7 +4,7 @@ //~^ WARN the feature `precise_capturing` is incomplete trait Foo { - fn bar<'a>() -> impl use Sized; + fn bar<'a>() -> impl Sized + use; } fn main() {} diff --git a/tests/ui/impl-trait/precise-capturing/unexpected-token.rs b/tests/ui/impl-trait/precise-capturing/unexpected-token.rs index 2a7ccbe1e609e..a1089fd7bfc53 100644 --- a/tests/ui/impl-trait/precise-capturing/unexpected-token.rs +++ b/tests/ui/impl-trait/precise-capturing/unexpected-token.rs @@ -2,7 +2,7 @@ // token due to a strange interaction between the sequence parsing code and the // param/lifetime parsing code. -fn hello() -> impl use<'a {}> Sized {} +fn hello() -> impl Sized + use<'a {}> {} //~^ ERROR expected one of `,` or `>`, found `{` fn main() {} diff --git a/tests/ui/impl-trait/precise-capturing/unexpected-token.stderr b/tests/ui/impl-trait/precise-capturing/unexpected-token.stderr index 1f8e1d0ec323f..51e4f0f67754a 100644 --- a/tests/ui/impl-trait/precise-capturing/unexpected-token.stderr +++ b/tests/ui/impl-trait/precise-capturing/unexpected-token.stderr @@ -1,8 +1,8 @@ error: expected one of `,` or `>`, found `{` - --> $DIR/unexpected-token.rs:5:27 + --> $DIR/unexpected-token.rs:5:35 | -LL | fn hello() -> impl use<'a {}> Sized {} - | ^ expected one of `,` or `>` +LL | fn hello() -> impl Sized + use<'a {}> {} + | ^ expected one of `,` or `>` error: aborting due to 1 previous error diff --git a/tests/ui/parser/trait-object-delimiters.rs b/tests/ui/parser/trait-object-delimiters.rs index d6bc629aa114b..8f6221c1b9434 100644 --- a/tests/ui/parser/trait-object-delimiters.rs +++ b/tests/ui/parser/trait-object-delimiters.rs @@ -8,7 +8,7 @@ fn foo2(_: &dyn (Drop + AsRef)) {} //~ ERROR incorrect parentheses around t fn foo2_no_space(_: &dyn(Drop + AsRef)) {} //~ ERROR incorrect parentheses around trait bounds fn foo3(_: &dyn {Drop + AsRef}) {} //~ ERROR expected parameter name, found `{` -//~^ ERROR expected one of `!`, `(`, `)`, `*`, `,`, `?`, `async`, `const`, `for`, `~`, lifetime, or path, found `{` +//~^ ERROR expected one of `!`, `(`, `)`, `*`, `,`, `?`, `async`, `const`, `for`, `use`, `~`, lifetime, or path, found `{` //~| ERROR at least one trait is required for an object type fn foo4(_: &dyn >) {} //~ ERROR expected identifier, found `<` diff --git a/tests/ui/parser/trait-object-delimiters.stderr b/tests/ui/parser/trait-object-delimiters.stderr index 2b1f8df991f4b..5f175e86545a8 100644 --- a/tests/ui/parser/trait-object-delimiters.stderr +++ b/tests/ui/parser/trait-object-delimiters.stderr @@ -34,11 +34,11 @@ error: expected parameter name, found `{` LL | fn foo3(_: &dyn {Drop + AsRef}) {} | ^ expected parameter name -error: expected one of `!`, `(`, `)`, `*`, `,`, `?`, `async`, `const`, `for`, `~`, lifetime, or path, found `{` +error: expected one of `!`, `(`, `)`, `*`, `,`, `?`, `async`, `const`, `for`, `use`, `~`, lifetime, or path, found `{` --> $DIR/trait-object-delimiters.rs:10:17 | LL | fn foo3(_: &dyn {Drop + AsRef}) {} - | -^ expected one of 12 possible tokens + | -^ expected one of 13 possible tokens | | | help: missing `,`