Skip to main content

PatNonVarErased

Struct PatNonVarErased 

Source
pub struct PatNonVarErased(pub Box<Pattern>);
Expand description

An ast::Pattern that is not a bare variable — the target of a destructuring let, and the left factor that keeps the two let forms from backtracking over each other.

§Why this type exists

let ‹target› = ‹value› in ‹body› is written twice in this grammar, as ast::Expr::LetIn (target a BindName, plus curried params) and ast::Expr::LetPatternIn (target a full pattern) — and at the top level again as TopBinding::Let/TopBinding::LetPattern. Upstream writes each of those ONCE: 0.0.6’s nxnonrecdec is the single production patbot nonrecdecargpart DEFEQ nxlet (parser.mly:652-656), and 0.1 spells the second target pattern_non_var (parser_v1.mly:796) — a nonterminal that, as its name says, cannot derive a bare variable.

Splitting one production into two whose common prefix is not factored is what made this port’s worst backtracking blow-up. LetIn is tried first and subsumes every bare-variable target, so LetPatternIn could never succeed on one — but it was still tried, and trying it re-parses value and body in full. With body being the rest of the file, each enclosing let doubled the cost of every failure below it: measured over a chain of let vN = N in ending in a broken let, 1,115 serves at 3, 9,459 at 6, 76,211 at 9, 610,227 at 12, 4,882,355 at 15 — ×2.000 per let, in both grammars. A 129-line document with a missing in sixteen lets deep cost 17.9M serves and was reported as crate::ParseFailureKind::GaveUp rather than as the one-word syntax error it is.

Requiring a non-variable target here restores upstream’s disjointness: the two alternatives now differ at the token after let, so the choice is made on the target alone and no tail is ever parsed twice. The same chain costs 374, 677, 980, 1,283, 1,586 — linear, ~17 serves per atom.

§Why it loses nothing

LetPatternIn on a bare-variable target is unreachable-on-success today, and provably so rather than by inspection: if it matched, the token after the name is =, so LetIn’s greedy params is empty (no ast::Param begins with =), its optional ascription/leading_bar are absent, and its value/in_kw/body are the identical grammar — so LetIn, tried first, has already succeeded and this variant is never reached. Only PatBot::Var is excluded: _, Ctor, (a, b), […], x :: xs and x as y all still take this route, because BindName accepts none of them.

Tuple Fields§

§0: Box<Pattern>

Trait Implementations§

Source§

impl Clone for PatNonVarErased

Source§

fn clone(&self) -> PatNonVarErased

Returns a duplicate of the value. Read more
1.0.0 (const: unstable) · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
Source§

impl Debug for PatNonVarErased

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

impl Deref for PatNonVarErased
where Box<Pattern>: Deref,

Source§

type Target = <Box<Pattern> as Deref>::Target

The resulting type after dereferencing.
Source§

fn deref(&self) -> &Self::Target

Dereferences the value.
Source§

impl Deref for PatNonVarErased
where Box<Pattern>: Deref,

Source§

impl Parse<WithSpan<Token, Span>> for PatNonVarErased

Source§

type Error = ParseError<Span>

Every error must be convertible to the universal one, so a field’s failure can become the enclosing type’s failure with no per-field where-predicate. Stating it HERE rather than at each derived impl is what keeps it out of the obligation graph: a per-field <FieldTy as Parse<Atom>>::Error: Into<…> predicate re-creates a projection cycle on a recursive field (E0275), which decycle’s bound-peeling does not break.
Source§

fn parse_stream<S: ParseStream<Atom = Atom>>( stream: &mut S, ) -> Result<Self, Self::Error>

Parse from a reborrowable stream. Read more
Source§

fn parse(stream: impl IntoParseStream<Atom = Atom>) -> Result<Self, Self::Error>

Parse from anything that can become a stream — String, TokenStream, an existing stream. Read more
Source§

fn attempt(self) -> Attempt<Self>

Wrap this value in Attempt, the atomic-parse marker: parsing an Attempt<Self> parses Self but rewinds the stream on failure (it requires Atom: Clone). This is the value constructor; value.attempt() is sugar for Attempt(value).
Source§

impl PartialEq for PatNonVarErased

Source§

fn eq(&self, other: &PatNonVarErased) -> bool

Equality operator ==. Read more
1.0.0 (const: unstable) · Source§

fn ne(&self, other: &Rhs) -> bool

Inequality operator !=. Read more
Source§

impl StructuralPartialEq for PatNonVarErased

Source§

impl Unparse<WithSpan<Token, Span>> for PatNonVarErased

Source§

fn unparse<S: Emitter<Atom>>(&self, sink: &mut S) -> Result<(), S::Error>

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> Clone for T
where T: Clone,

Source§

fn clone(&self) -> T

Source§

impl<T> CloneToUninit for T
where T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dest: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dest. Read more
Source§

impl<T> Debug for T
where T: Debug,

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), Error>

Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<P, T> Receiver for P
where P: Deref<Target = T> + ?Sized, T: ?Sized,

Source§

type Target = T

🔬This is a nightly-only experimental API. (arbitrary_self_types)
The target type on which the method may be called.
Source§

impl<T> ToOwned for T
where T: Clone,

Source§

type Owned = T

The resulting type after obtaining ownership.
Source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
Source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.