mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-25 08:13:41 +00:00
Rework precise capturing syntax
This commit is contained in:
parent
68bd001c00
commit
b1efe1ab5d
@ -307,6 +307,8 @@ impl TraitBoundModifiers {
|
||||
pub enum GenericBound {
|
||||
Trait(PolyTraitRef, TraitBoundModifiers),
|
||||
Outlives(Lifetime),
|
||||
/// Precise capturing syntax: `impl Sized + use<'a>`
|
||||
Use(ThinVec<PreciseCapturingArg>, 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<P<(ThinVec<PreciseCapturingArg>, Span)>>),
|
||||
ImplTrait(NodeId, GenericBounds),
|
||||
/// No-op; kept solely so that we can pretty-print faithfully.
|
||||
Paren(P<Ty>),
|
||||
/// Unused for now.
|
||||
|
@ -523,14 +523,9 @@ pub fn noop_visit_ty<T: MutVisitor>(ty: &mut P<Ty>, 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<T: MutVisitor>(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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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<FnDeclKind>,
|
||||
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,12 +1530,14 @@ 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 {
|
||||
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.
|
||||
precise_capturing
|
||||
.iter()
|
||||
args.iter()
|
||||
.filter_map(|arg| match arg {
|
||||
PreciseCapturingArg::Lifetime(lt) => Some(*lt),
|
||||
PreciseCapturingArg::Arg(..) => None,
|
||||
@ -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<Lifetime>,
|
||||
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),
|
||||
),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
|
@ -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,19 +1323,24 @@ 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 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: poly.span,
|
||||
path_str: pprust::path_to_string(&poly.trait_ref.path),
|
||||
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: poly.span });
|
||||
self.dcx().emit_err(errors::OptionalTraitObject { span: trait_ref.span });
|
||||
}
|
||||
(BoundKind::TraitObject, BoundConstness::Always(_), BoundPolarity::Positive) => {
|
||||
self.dcx().emit_err(errors::ConstBoundTraitObject { span: poly.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 =>
|
||||
@ -1386,11 +1392,9 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
|
||||
// Negative trait bounds are not allowed to have associated constraints
|
||||
if let GenericBound::Trait(trait_ref, modifiers) = bound
|
||||
&& let BoundPolarity::Negative(_) = modifiers.polarity
|
||||
if let BoundPolarity::Negative(_) = modifiers.polarity
|
||||
&& let Some(segment) = trait_ref.trait_ref.path.segments.last()
|
||||
{
|
||||
match segment.args.as_deref() {
|
||||
@ -1412,6 +1416,18 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
|
||||
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)
|
||||
}
|
||||
|
@ -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,
|
||||
}
|
||||
|
@ -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(">")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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)),
|
||||
|
@ -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)]
|
||||
|
@ -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()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
};
|
||||
|
@ -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.
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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,9 +2100,23 @@ 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() {
|
||||
|
@ -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<TyCtxt<'tcx>> 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<TyCtxt<'tcx>> 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<TyCtxt<'tcx>> 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 {
|
||||
|
@ -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
|
||||
|
@ -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,
|
||||
|
@ -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:
|
||||
|
@ -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() =>
|
||||
{
|
||||
(
|
||||
|
@ -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)
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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())
|
||||
|
@ -73,7 +73,7 @@ fn type_param_bounds<'tcx>(generics: &'tcx Generics<'tcx>) -> impl Iterator<Item
|
||||
predicate_pos,
|
||||
bound_pos,
|
||||
}),
|
||||
GenericBound::Outlives(_) => None,
|
||||
GenericBound::Outlives(_) | GenericBound::Use(..) => None,
|
||||
})
|
||||
.filter(|bound| !bound.trait_bound.span.from_expansion()),
|
||||
)
|
||||
|
@ -1,4 +1,4 @@
|
||||
fn hello() -> impl use<> Sized {}
|
||||
fn hello() -> impl Sized + use<> {}
|
||||
//~^ ERROR precise captures on `impl Trait` are experimental
|
||||
|
||||
fn main() {}
|
||||
|
@ -1,7 +1,7 @@
|
||||
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 <https://github.com/rust-lang/rust/issues/123432> for more information
|
||||
|
@ -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() {}
|
||||
|
@ -8,9 +8,9 @@ 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
|
||||
|
@ -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() {}
|
||||
|
@ -1,19 +1,19 @@
|
||||
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 {}
|
||||
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 {}
|
||||
LL | fn missing_lt() -> impl Sized + use<'missing> {}
|
||||
| - ^^^^^^^^ undeclared lifetime
|
||||
| |
|
||||
| help: consider introducing lifetime `'missing` here: `<'missing>`
|
||||
@ -28,15 +28,15 @@ 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
|
||||
|
@ -1,19 +1,19 @@
|
||||
#![feature(precise_capturing)]
|
||||
//~^ WARN the feature `precise_capturing` is incomplete
|
||||
|
||||
fn missing() -> impl use<T> Sized {}
|
||||
fn missing() -> impl Sized + use<T> {}
|
||||
//~^ ERROR cannot find type `T` in this scope
|
||||
|
||||
fn missing_self() -> impl use<Self> Sized {}
|
||||
fn missing_self() -> impl Sized + use<Self> {}
|
||||
//~^ ERROR cannot find type `Self` in this scope
|
||||
|
||||
struct MyType;
|
||||
impl MyType {
|
||||
fn self_is_not_param() -> impl use<Self> Sized {}
|
||||
fn self_is_not_param() -> impl Sized + use<Self> {}
|
||||
//~^ ERROR `Self` can't be captured in `use<...>` precise captures list, since it is an alias
|
||||
}
|
||||
|
||||
fn hello() -> impl use<hello> Sized {}
|
||||
fn hello() -> impl Sized + use<hello> {}
|
||||
//~^ ERROR expected type or const parameter in `use<...>` precise captures list, found function
|
||||
|
||||
fn main() {}
|
||||
|
@ -1,18 +1,18 @@
|
||||
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<T> Sized {}
|
||||
LL | fn missing() -> impl Sized + use<T> {}
|
||||
| ^ not found in this scope
|
||||
|
|
||||
help: you might be missing a type parameter
|
||||
|
|
||||
LL | fn missing<T>() -> impl use<T> Sized {}
|
||||
LL | fn missing<T>() -> impl Sized + use<T> {}
|
||||
| +++
|
||||
|
||||
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<Self> Sized {}
|
||||
LL | fn missing_self() -> impl Sized + use<Self> {}
|
||||
| ------------ ^^^^ `Self` is only available in impls, traits, and type definitions
|
||||
| |
|
||||
| `Self` not allowed in a function
|
||||
@ -27,17 +27,17 @@ 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<Self> Sized {}
|
||||
LL | fn self_is_not_param() -> impl Sized + use<Self> {}
|
||||
| ^^^^
|
||||
|
||||
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<hello> Sized {}
|
||||
LL | fn hello() -> impl Sized + use<hello> {}
|
||||
| ^^^^^
|
||||
|
||||
error: aborting due to 4 previous errors; 1 warning emitted
|
||||
|
@ -13,25 +13,25 @@ impl Tr for W<'_> {
|
||||
|
||||
// The normal way of capturing `'a`...
|
||||
impl<'a> W<'a> {
|
||||
fn good1() -> impl use<'a> Into<<W<'a> as Tr>::Assoc> {}
|
||||
fn good1() -> impl Into<<W<'a> 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<<Self as Tr>::Assoc> {}
|
||||
fn good2() -> impl Into<<Self as Tr>::Assoc> + use<'a> {}
|
||||
}
|
||||
|
||||
// The normal way of capturing `'a`... but not mentioned in the bounds.
|
||||
impl<'a> W<'a> {
|
||||
fn bad1() -> impl use<> Into<<W<'a> as Tr>::Assoc> {}
|
||||
fn bad1() -> impl Into<<W<'a> 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<<Self as Tr>::Assoc> {}
|
||||
fn bad2() -> impl Into<<Self as Tr>::Assoc> + use<> {}
|
||||
//~^ ERROR `impl Trait` captures lifetime parameter, but it is not mentioned in `use<...>` precise captures list
|
||||
}
|
||||
|
||||
|
@ -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<<W<'a> as Tr>::Assoc> {}
|
||||
| -------------------^^---------------- lifetime captured due to being mentioned in the bounds of the `impl Trait`
|
||||
LL | fn bad1() -> impl Into<<W<'a> 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<<Self as Tr>::Assoc> {}
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ lifetime captured due to being mentioned in the bounds of the `impl Trait`
|
||||
LL | fn bad2() -> impl Into<<Self as Tr>::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
|
||||
|
||||
|
@ -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() {}
|
||||
|
@ -1,7 +1,7 @@
|
||||
#![feature(precise_capturing)]
|
||||
//~^ WARN the feature `precise_capturing` is incomplete
|
||||
|
||||
fn constant<const C: usize>() -> impl use<> Sized {}
|
||||
fn constant<const C: usize>() -> impl Sized + use<> {}
|
||||
//~^ ERROR `impl Trait` must mention all const parameters in scope
|
||||
|
||||
fn main() {}
|
||||
|
@ -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<const C: usize>() -> impl use<> Sized {}
|
||||
| -------------- ^^^^^^^^^^^^^^^^
|
||||
LL | fn constant<const C: usize>() -> impl Sized + use<> {}
|
||||
| -------------- ^^^^^^^^^^^^^^^^^^
|
||||
| |
|
||||
| const parameter is implicitly captured by this `impl Trait`
|
||||
|
|
||||
|
@ -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() {}
|
||||
|
@ -8,26 +8,26 @@ 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
|
||||
|
@ -1,11 +1,11 @@
|
||||
#![feature(precise_capturing)]
|
||||
//~^ WARN the feature `precise_capturing` is incomplete
|
||||
|
||||
fn type_param<T>() -> impl use<> Sized {}
|
||||
fn type_param<T>() -> 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
|
||||
}
|
||||
|
||||
|
@ -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<T>() -> impl use<> Sized {}
|
||||
| - ^^^^^^^^^^^^^^^^
|
||||
LL | fn type_param<T>() -> 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
|
||||
|
||||
|
@ -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() {}
|
||||
|
@ -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<T>() -> impl use<T, T> Sized {}
|
||||
fn ty<T>() -> impl Sized + use<T, T> {}
|
||||
//~^ ERROR cannot capture parameter `T` twice
|
||||
|
||||
fn ct<const N: usize>() -> impl use<N, N> Sized {}
|
||||
fn ct<const N: usize>() -> impl Sized + use<N, N> {}
|
||||
//~^ ERROR cannot capture parameter `N` twice
|
||||
|
||||
fn ordering<'a, T>() -> impl use<T, 'a> Sized {}
|
||||
fn ordering<'a, T>() -> impl Sized + use<T, 'a> {}
|
||||
//~^ ERROR lifetime parameter `'a` must be listed before non-lifetime parameters
|
||||
|
||||
fn main() {}
|
||||
|
@ -8,27 +8,27 @@ 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 {}
|
||||
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<T>() -> impl use<T, T> Sized {}
|
||||
LL | fn ty<T>() -> impl Sized + use<T, T> {}
|
||||
| ^ - parameter captured again here
|
||||
|
||||
error: cannot capture parameter `N` twice
|
||||
--> $DIR/ordering.rs:10:37
|
||||
--> $DIR/ordering.rs:10:45
|
||||
|
|
||||
LL | fn ct<const N: usize>() -> impl use<N, N> Sized {}
|
||||
LL | fn ct<const N: usize>() -> impl Sized + use<N, N> {}
|
||||
| ^ - 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<T, 'a> Sized {}
|
||||
LL | fn ordering<'a, T>() -> impl Sized + use<T, 'a> {}
|
||||
| - ^^
|
||||
| |
|
||||
| move the lifetime before this parameter
|
||||
|
@ -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) {}
|
||||
|
||||
|
@ -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() {}
|
||||
|
@ -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
|
||||
|
||||
|
@ -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
|
||||
}
|
||||
|
||||
|
@ -10,8 +10,8 @@ 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 {}
|
||||
| ^^^^^-------^^^^^^
|
||||
LL | fn hello<'a>() -> impl Sized + use<'a> {}
|
||||
| ^^^^^^^^^^^^^-------
|
||||
| |
|
||||
| help: remove the `use<...>` syntax
|
||||
|
|
||||
@ -20,24 +20,24 @@ LL | fn hello<'a>() -> impl use<'a> Sized {}
|
||||
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 {}
|
||||
| ^^^^^-------^^^^^^
|
||||
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;
|
||||
| ^^^^^-------------^^^^^^
|
||||
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 {}
|
||||
| ^^^^^-------^^^^^^
|
||||
LL | fn in_trait() -> impl Sized + use<'a> {}
|
||||
| ^^^^^^^^^^^^^-------
|
||||
| |
|
||||
| help: remove the `use<...>` syntax
|
||||
|
||||
|
@ -4,7 +4,7 @@
|
||||
//~^ WARN the feature `precise_capturing` is incomplete
|
||||
|
||||
trait Foo {
|
||||
fn bar<'a>() -> impl use<Self> Sized;
|
||||
fn bar<'a>() -> impl Sized + use<Self>;
|
||||
}
|
||||
|
||||
fn main() {}
|
||||
|
@ -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() {}
|
||||
|
@ -1,7 +1,7 @@
|
||||
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 {}
|
||||
LL | fn hello() -> impl Sized + use<'a {}> {}
|
||||
| ^ expected one of `,` or `>`
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
|
@ -8,7 +8,7 @@ fn foo2(_: &dyn (Drop + AsRef<str>)) {} //~ ERROR incorrect parentheses around t
|
||||
fn foo2_no_space(_: &dyn(Drop + AsRef<str>)) {} //~ ERROR incorrect parentheses around trait bounds
|
||||
|
||||
fn foo3(_: &dyn {Drop + AsRef<str>}) {} //~ 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 <Drop + AsRef<str>>) {} //~ ERROR expected identifier, found `<`
|
||||
|
@ -34,11 +34,11 @@ error: expected parameter name, found `{`
|
||||
LL | fn foo3(_: &dyn {Drop + AsRef<str>}) {}
|
||||
| ^ 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<str>}) {}
|
||||
| -^ expected one of 12 possible tokens
|
||||
| -^ expected one of 13 possible tokens
|
||||
| |
|
||||
| help: missing `,`
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user