mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-01 06:51:58 +00:00
Auto merge of #85346 - estebank:issue-84946, r=nagisa,varkor
Account for incorrect `impl Foo<const N: ty> {}` syntax Fix #84946
This commit is contained in:
commit
c6eda7d8a7
@ -405,6 +405,21 @@ pub struct GenericParam {
|
|||||||
pub kind: GenericParamKind,
|
pub kind: GenericParamKind,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl GenericParam {
|
||||||
|
pub fn span(&self) -> Span {
|
||||||
|
match &self.kind {
|
||||||
|
GenericParamKind::Lifetime | GenericParamKind::Type { default: None } => {
|
||||||
|
self.ident.span
|
||||||
|
}
|
||||||
|
GenericParamKind::Type { default: Some(ty) } => self.ident.span.to(ty.span),
|
||||||
|
GenericParamKind::Const { kw_span, default: Some(default), .. } => {
|
||||||
|
kw_span.to(default.value.span)
|
||||||
|
}
|
||||||
|
GenericParamKind::Const { kw_span, default: None, ty } => kw_span.to(ty.span),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Represents lifetime, type and const parameters attached to a declaration of
|
/// Represents lifetime, type and const parameters attached to a declaration of
|
||||||
/// a function, enum, trait, etc.
|
/// a function, enum, trait, etc.
|
||||||
#[derive(Clone, Encodable, Decodable, Debug)]
|
#[derive(Clone, Encodable, Decodable, Debug)]
|
||||||
|
@ -6,9 +6,11 @@ use rustc_ast as ast;
|
|||||||
use rustc_ast::ptr::P;
|
use rustc_ast::ptr::P;
|
||||||
use rustc_ast::token::{self, Lit, LitKind, TokenKind};
|
use rustc_ast::token::{self, Lit, LitKind, TokenKind};
|
||||||
use rustc_ast::util::parser::AssocOp;
|
use rustc_ast::util::parser::AssocOp;
|
||||||
use rustc_ast::{AngleBracketedArg, AngleBracketedArgs, AnonConst, AttrVec};
|
use rustc_ast::{
|
||||||
use rustc_ast::{BinOpKind, BindingMode, Block, BlockCheckMode, Expr, ExprKind, GenericArg, Item};
|
AngleBracketedArg, AngleBracketedArgs, AnonConst, AttrVec, BinOpKind, BindingMode, Block,
|
||||||
use rustc_ast::{ItemKind, Mutability, Param, Pat, PatKind, Path, PathSegment, QSelf, Ty, TyKind};
|
BlockCheckMode, Expr, ExprKind, GenericArg, Generics, Item, ItemKind, Mutability, Param, Pat,
|
||||||
|
PatKind, Path, PathSegment, QSelf, Ty, TyKind,
|
||||||
|
};
|
||||||
use rustc_ast_pretty::pprust;
|
use rustc_ast_pretty::pprust;
|
||||||
use rustc_data_structures::fx::FxHashSet;
|
use rustc_data_structures::fx::FxHashSet;
|
||||||
use rustc_errors::{pluralize, struct_span_err};
|
use rustc_errors::{pluralize, struct_span_err};
|
||||||
@ -662,7 +664,7 @@ impl<'a> Parser<'a> {
|
|||||||
let snapshot = self.clone();
|
let snapshot = self.clone();
|
||||||
self.bump();
|
self.bump();
|
||||||
let lo = self.token.span;
|
let lo = self.token.span;
|
||||||
match self.parse_angle_args() {
|
match self.parse_angle_args(None) {
|
||||||
Ok(args) => {
|
Ok(args) => {
|
||||||
let span = lo.to(self.prev_token.span);
|
let span = lo.to(self.prev_token.span);
|
||||||
// Detect trailing `>` like in `x.collect::Vec<_>>()`.
|
// Detect trailing `>` like in `x.collect::Vec<_>>()`.
|
||||||
@ -719,7 +721,7 @@ impl<'a> Parser<'a> {
|
|||||||
let x = self.parse_seq_to_before_end(
|
let x = self.parse_seq_to_before_end(
|
||||||
&token::Gt,
|
&token::Gt,
|
||||||
SeqSep::trailing_allowed(token::Comma),
|
SeqSep::trailing_allowed(token::Comma),
|
||||||
|p| p.parse_generic_arg(),
|
|p| p.parse_generic_arg(None),
|
||||||
);
|
);
|
||||||
match x {
|
match x {
|
||||||
Ok((_, _, false)) => {
|
Ok((_, _, false)) => {
|
||||||
@ -1103,7 +1105,7 @@ impl<'a> Parser<'a> {
|
|||||||
self.expect(&token::ModSep)?;
|
self.expect(&token::ModSep)?;
|
||||||
|
|
||||||
let mut path = ast::Path { segments: Vec::new(), span: DUMMY_SP, tokens: None };
|
let mut path = ast::Path { segments: Vec::new(), span: DUMMY_SP, tokens: None };
|
||||||
self.parse_path_segments(&mut path.segments, T::PATH_STYLE)?;
|
self.parse_path_segments(&mut path.segments, T::PATH_STYLE, None)?;
|
||||||
path.span = ty_span.to(self.prev_token.span);
|
path.span = ty_span.to(self.prev_token.span);
|
||||||
|
|
||||||
let ty_str = self.span_to_snippet(ty_span).unwrap_or_else(|_| pprust::ty_to_string(&ty));
|
let ty_str = self.span_to_snippet(ty_span).unwrap_or_else(|_| pprust::ty_to_string(&ty));
|
||||||
@ -1909,6 +1911,71 @@ impl<'a> Parser<'a> {
|
|||||||
Ok(expr)
|
Ok(expr)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn recover_const_param_decl(
|
||||||
|
&mut self,
|
||||||
|
ty_generics: Option<&Generics>,
|
||||||
|
) -> PResult<'a, Option<GenericArg>> {
|
||||||
|
let snapshot = self.clone();
|
||||||
|
let param = match self.parse_const_param(vec![]) {
|
||||||
|
Ok(param) => param,
|
||||||
|
Err(mut err) => {
|
||||||
|
err.cancel();
|
||||||
|
*self = snapshot;
|
||||||
|
return Err(err);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
let mut err =
|
||||||
|
self.struct_span_err(param.span(), "unexpected `const` parameter declaration");
|
||||||
|
err.span_label(param.span(), "expected a `const` expression, not a parameter declaration");
|
||||||
|
if let (Some(generics), Ok(snippet)) =
|
||||||
|
(ty_generics, self.sess.source_map().span_to_snippet(param.span()))
|
||||||
|
{
|
||||||
|
let (span, sugg) = match &generics.params[..] {
|
||||||
|
[] => (generics.span, format!("<{}>", snippet)),
|
||||||
|
[.., generic] => (generic.span().shrink_to_hi(), format!(", {}", snippet)),
|
||||||
|
};
|
||||||
|
err.multipart_suggestion(
|
||||||
|
"`const` parameters must be declared for the `impl`",
|
||||||
|
vec![(span, sugg), (param.span(), param.ident.to_string())],
|
||||||
|
Applicability::MachineApplicable,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
let value = self.mk_expr_err(param.span());
|
||||||
|
err.emit();
|
||||||
|
return Ok(Some(GenericArg::Const(AnonConst { id: ast::DUMMY_NODE_ID, value })));
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn recover_const_param_declaration(
|
||||||
|
&mut self,
|
||||||
|
ty_generics: Option<&Generics>,
|
||||||
|
) -> PResult<'a, Option<GenericArg>> {
|
||||||
|
// We have to check for a few different cases.
|
||||||
|
if let Ok(arg) = self.recover_const_param_decl(ty_generics) {
|
||||||
|
return Ok(arg);
|
||||||
|
}
|
||||||
|
|
||||||
|
// We haven't consumed `const` yet.
|
||||||
|
let start = self.token.span;
|
||||||
|
self.bump(); // `const`
|
||||||
|
|
||||||
|
// Detect and recover from the old, pre-RFC2000 syntax for const generics.
|
||||||
|
let mut err = self
|
||||||
|
.struct_span_err(start, "expected lifetime, type, or constant, found keyword `const`");
|
||||||
|
if self.check_const_arg() {
|
||||||
|
err.span_suggestion_verbose(
|
||||||
|
start.until(self.token.span),
|
||||||
|
"the `const` keyword is only needed in the definition of the type",
|
||||||
|
String::new(),
|
||||||
|
Applicability::MaybeIncorrect,
|
||||||
|
);
|
||||||
|
err.emit();
|
||||||
|
Ok(Some(GenericArg::Const(self.parse_const_arg()?)))
|
||||||
|
} else {
|
||||||
|
let after_kw_const = self.token.span;
|
||||||
|
self.recover_const_arg(after_kw_const, err).map(Some)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Try to recover from possible generic const argument without `{` and `}`.
|
/// Try to recover from possible generic const argument without `{` and `}`.
|
||||||
///
|
///
|
||||||
/// When encountering code like `foo::< bar + 3 >` or `foo::< bar - baz >` we suggest
|
/// When encountering code like `foo::< bar + 3 >` or `foo::< bar - baz >` we suggest
|
||||||
|
@ -1150,7 +1150,7 @@ impl<'a> Parser<'a> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
let fn_span_lo = self.token.span;
|
let fn_span_lo = self.token.span;
|
||||||
let mut segment = self.parse_path_segment(PathStyle::Expr)?;
|
let mut segment = self.parse_path_segment(PathStyle::Expr, None)?;
|
||||||
self.check_trailing_angle_brackets(&segment, &[&token::OpenDelim(token::Paren)]);
|
self.check_trailing_angle_brackets(&segment, &[&token::OpenDelim(token::Paren)]);
|
||||||
self.check_turbofish_missing_angle_brackets(&mut segment);
|
self.check_turbofish_missing_angle_brackets(&mut segment);
|
||||||
|
|
||||||
|
@ -48,7 +48,10 @@ impl<'a> Parser<'a> {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parse_const_param(&mut self, preceding_attrs: Vec<Attribute>) -> PResult<'a, GenericParam> {
|
crate fn parse_const_param(
|
||||||
|
&mut self,
|
||||||
|
preceding_attrs: Vec<Attribute>,
|
||||||
|
) -> PResult<'a, GenericParam> {
|
||||||
let const_span = self.token.span;
|
let const_span = self.token.span;
|
||||||
|
|
||||||
self.expect_keyword(kw::Const)?;
|
self.expect_keyword(kw::Const)?;
|
||||||
|
@ -514,7 +514,7 @@ impl<'a> Parser<'a> {
|
|||||||
tokens: None,
|
tokens: None,
|
||||||
})
|
})
|
||||||
} else {
|
} else {
|
||||||
self.parse_ty()?
|
self.parse_ty_with_generics_recovery(&generics)?
|
||||||
};
|
};
|
||||||
|
|
||||||
// If `for` is missing we try to recover.
|
// If `for` is missing we try to recover.
|
||||||
|
@ -3,10 +3,11 @@ use super::{Parser, TokenType};
|
|||||||
use crate::maybe_whole;
|
use crate::maybe_whole;
|
||||||
use rustc_ast::ptr::P;
|
use rustc_ast::ptr::P;
|
||||||
use rustc_ast::token::{self, Token};
|
use rustc_ast::token::{self, Token};
|
||||||
use rustc_ast::{self as ast, AngleBracketedArg, AngleBracketedArgs, ParenthesizedArgs};
|
use rustc_ast::{
|
||||||
use rustc_ast::{AnonConst, AssocTyConstraint, AssocTyConstraintKind, BlockCheckMode};
|
self as ast, AngleBracketedArg, AngleBracketedArgs, AnonConst, AssocTyConstraint,
|
||||||
use rustc_ast::{GenericArg, GenericArgs};
|
AssocTyConstraintKind, BlockCheckMode, GenericArg, GenericArgs, Generics, ParenthesizedArgs,
|
||||||
use rustc_ast::{Path, PathSegment, QSelf};
|
Path, PathSegment, QSelf,
|
||||||
|
};
|
||||||
use rustc_errors::{pluralize, Applicability, PResult};
|
use rustc_errors::{pluralize, Applicability, PResult};
|
||||||
use rustc_span::source_map::{BytePos, Span};
|
use rustc_span::source_map::{BytePos, Span};
|
||||||
use rustc_span::symbol::{kw, sym, Ident};
|
use rustc_span::symbol::{kw, sym, Ident};
|
||||||
@ -78,7 +79,7 @@ impl<'a> Parser<'a> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
let qself = QSelf { ty, path_span, position: path.segments.len() };
|
let qself = QSelf { ty, path_span, position: path.segments.len() };
|
||||||
self.parse_path_segments(&mut path.segments, style)?;
|
self.parse_path_segments(&mut path.segments, style, None)?;
|
||||||
|
|
||||||
Ok((
|
Ok((
|
||||||
qself,
|
qself,
|
||||||
@ -119,6 +120,10 @@ impl<'a> Parser<'a> {
|
|||||||
true
|
true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub(super) fn parse_path(&mut self, style: PathStyle) -> PResult<'a, Path> {
|
||||||
|
self.parse_path_inner(style, None)
|
||||||
|
}
|
||||||
|
|
||||||
/// Parses simple paths.
|
/// Parses simple paths.
|
||||||
///
|
///
|
||||||
/// `path = [::] segment+`
|
/// `path = [::] segment+`
|
||||||
@ -129,7 +134,11 @@ impl<'a> Parser<'a> {
|
|||||||
/// `a::b::C::<D>` (with disambiguator)
|
/// `a::b::C::<D>` (with disambiguator)
|
||||||
/// `Fn(Args)` (without disambiguator)
|
/// `Fn(Args)` (without disambiguator)
|
||||||
/// `Fn::(Args)` (with disambiguator)
|
/// `Fn::(Args)` (with disambiguator)
|
||||||
pub(super) fn parse_path(&mut self, style: PathStyle) -> PResult<'a, Path> {
|
pub(super) fn parse_path_inner(
|
||||||
|
&mut self,
|
||||||
|
style: PathStyle,
|
||||||
|
ty_generics: Option<&Generics>,
|
||||||
|
) -> PResult<'a, Path> {
|
||||||
maybe_whole!(self, NtPath, |path| {
|
maybe_whole!(self, NtPath, |path| {
|
||||||
if style == PathStyle::Mod && path.segments.iter().any(|segment| segment.args.is_some())
|
if style == PathStyle::Mod && path.segments.iter().any(|segment| segment.args.is_some())
|
||||||
{
|
{
|
||||||
@ -152,7 +161,7 @@ impl<'a> Parser<'a> {
|
|||||||
if self.eat(&token::ModSep) {
|
if self.eat(&token::ModSep) {
|
||||||
segments.push(PathSegment::path_root(lo.shrink_to_lo().with_ctxt(mod_sep_ctxt)));
|
segments.push(PathSegment::path_root(lo.shrink_to_lo().with_ctxt(mod_sep_ctxt)));
|
||||||
}
|
}
|
||||||
self.parse_path_segments(&mut segments, style)?;
|
self.parse_path_segments(&mut segments, style, ty_generics)?;
|
||||||
|
|
||||||
Ok(Path { segments, span: lo.to(self.prev_token.span), tokens: None })
|
Ok(Path { segments, span: lo.to(self.prev_token.span), tokens: None })
|
||||||
}
|
}
|
||||||
@ -161,9 +170,10 @@ impl<'a> Parser<'a> {
|
|||||||
&mut self,
|
&mut self,
|
||||||
segments: &mut Vec<PathSegment>,
|
segments: &mut Vec<PathSegment>,
|
||||||
style: PathStyle,
|
style: PathStyle,
|
||||||
|
ty_generics: Option<&Generics>,
|
||||||
) -> PResult<'a, ()> {
|
) -> PResult<'a, ()> {
|
||||||
loop {
|
loop {
|
||||||
let segment = self.parse_path_segment(style)?;
|
let segment = self.parse_path_segment(style, ty_generics)?;
|
||||||
if style == PathStyle::Expr {
|
if style == PathStyle::Expr {
|
||||||
// In order to check for trailing angle brackets, we must have finished
|
// In order to check for trailing angle brackets, we must have finished
|
||||||
// recursing (`parse_path_segment` can indirectly call this function),
|
// recursing (`parse_path_segment` can indirectly call this function),
|
||||||
@ -191,7 +201,11 @@ impl<'a> Parser<'a> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(super) fn parse_path_segment(&mut self, style: PathStyle) -> PResult<'a, PathSegment> {
|
pub(super) fn parse_path_segment(
|
||||||
|
&mut self,
|
||||||
|
style: PathStyle,
|
||||||
|
ty_generics: Option<&Generics>,
|
||||||
|
) -> PResult<'a, PathSegment> {
|
||||||
let ident = self.parse_path_segment_ident()?;
|
let ident = self.parse_path_segment_ident()?;
|
||||||
let is_args_start = |token: &Token| {
|
let is_args_start = |token: &Token| {
|
||||||
matches!(
|
matches!(
|
||||||
@ -229,8 +243,11 @@ impl<'a> Parser<'a> {
|
|||||||
let lo = self.token.span;
|
let lo = self.token.span;
|
||||||
let args = if self.eat_lt() {
|
let args = if self.eat_lt() {
|
||||||
// `<'a, T, A = U>`
|
// `<'a, T, A = U>`
|
||||||
let args =
|
let args = self.parse_angle_args_with_leading_angle_bracket_recovery(
|
||||||
self.parse_angle_args_with_leading_angle_bracket_recovery(style, lo)?;
|
style,
|
||||||
|
lo,
|
||||||
|
ty_generics,
|
||||||
|
)?;
|
||||||
self.expect_gt()?;
|
self.expect_gt()?;
|
||||||
let span = lo.to(self.prev_token.span);
|
let span = lo.to(self.prev_token.span);
|
||||||
AngleBracketedArgs { args, span }.into()
|
AngleBracketedArgs { args, span }.into()
|
||||||
@ -238,9 +255,9 @@ impl<'a> Parser<'a> {
|
|||||||
// `(T, U) -> R`
|
// `(T, U) -> R`
|
||||||
let (inputs, _) = self.parse_paren_comma_seq(|p| p.parse_ty())?;
|
let (inputs, _) = self.parse_paren_comma_seq(|p| p.parse_ty())?;
|
||||||
let inputs_span = lo.to(self.prev_token.span);
|
let inputs_span = lo.to(self.prev_token.span);
|
||||||
let span = ident.span.to(self.prev_token.span);
|
|
||||||
let output =
|
let output =
|
||||||
self.parse_ret_ty(AllowPlus::No, RecoverQPath::No, RecoverReturnSign::No)?;
|
self.parse_ret_ty(AllowPlus::No, RecoverQPath::No, RecoverReturnSign::No)?;
|
||||||
|
let span = ident.span.to(self.prev_token.span);
|
||||||
ParenthesizedArgs { span, inputs, inputs_span, output }.into()
|
ParenthesizedArgs { span, inputs, inputs_span, output }.into()
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -275,6 +292,7 @@ impl<'a> Parser<'a> {
|
|||||||
&mut self,
|
&mut self,
|
||||||
style: PathStyle,
|
style: PathStyle,
|
||||||
lo: Span,
|
lo: Span,
|
||||||
|
ty_generics: Option<&Generics>,
|
||||||
) -> PResult<'a, Vec<AngleBracketedArg>> {
|
) -> PResult<'a, Vec<AngleBracketedArg>> {
|
||||||
// We need to detect whether there are extra leading left angle brackets and produce an
|
// We need to detect whether there are extra leading left angle brackets and produce an
|
||||||
// appropriate error and suggestion. This cannot be implemented by looking ahead at
|
// appropriate error and suggestion. This cannot be implemented by looking ahead at
|
||||||
@ -350,7 +368,7 @@ impl<'a> Parser<'a> {
|
|||||||
let snapshot = if is_first_invocation { Some(self.clone()) } else { None };
|
let snapshot = if is_first_invocation { Some(self.clone()) } else { None };
|
||||||
|
|
||||||
debug!("parse_generic_args_with_leading_angle_bracket_recovery: (snapshotting)");
|
debug!("parse_generic_args_with_leading_angle_bracket_recovery: (snapshotting)");
|
||||||
match self.parse_angle_args() {
|
match self.parse_angle_args(ty_generics) {
|
||||||
Ok(args) => Ok(args),
|
Ok(args) => Ok(args),
|
||||||
Err(mut e) if is_first_invocation && self.unmatched_angle_bracket_count > 0 => {
|
Err(mut e) if is_first_invocation && self.unmatched_angle_bracket_count > 0 => {
|
||||||
// Swap `self` with our backup of the parser state before attempting to parse
|
// Swap `self` with our backup of the parser state before attempting to parse
|
||||||
@ -403,7 +421,7 @@ impl<'a> Parser<'a> {
|
|||||||
.emit();
|
.emit();
|
||||||
|
|
||||||
// Try again without unmatched angle bracket characters.
|
// Try again without unmatched angle bracket characters.
|
||||||
self.parse_angle_args()
|
self.parse_angle_args(ty_generics)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Err(e) => Err(e),
|
Err(e) => Err(e),
|
||||||
@ -412,9 +430,12 @@ impl<'a> Parser<'a> {
|
|||||||
|
|
||||||
/// Parses (possibly empty) list of generic arguments / associated item constraints,
|
/// Parses (possibly empty) list of generic arguments / associated item constraints,
|
||||||
/// possibly including trailing comma.
|
/// possibly including trailing comma.
|
||||||
pub(super) fn parse_angle_args(&mut self) -> PResult<'a, Vec<AngleBracketedArg>> {
|
pub(super) fn parse_angle_args(
|
||||||
|
&mut self,
|
||||||
|
ty_generics: Option<&Generics>,
|
||||||
|
) -> PResult<'a, Vec<AngleBracketedArg>> {
|
||||||
let mut args = Vec::new();
|
let mut args = Vec::new();
|
||||||
while let Some(arg) = self.parse_angle_arg()? {
|
while let Some(arg) = self.parse_angle_arg(ty_generics)? {
|
||||||
args.push(arg);
|
args.push(arg);
|
||||||
if !self.eat(&token::Comma) {
|
if !self.eat(&token::Comma) {
|
||||||
if !self.token.kind.should_end_const_arg() {
|
if !self.token.kind.should_end_const_arg() {
|
||||||
@ -431,9 +452,12 @@ impl<'a> Parser<'a> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Parses a single argument in the angle arguments `<...>` of a path segment.
|
/// Parses a single argument in the angle arguments `<...>` of a path segment.
|
||||||
fn parse_angle_arg(&mut self) -> PResult<'a, Option<AngleBracketedArg>> {
|
fn parse_angle_arg(
|
||||||
|
&mut self,
|
||||||
|
ty_generics: Option<&Generics>,
|
||||||
|
) -> PResult<'a, Option<AngleBracketedArg>> {
|
||||||
let lo = self.token.span;
|
let lo = self.token.span;
|
||||||
let arg = self.parse_generic_arg()?;
|
let arg = self.parse_generic_arg(ty_generics)?;
|
||||||
match arg {
|
match arg {
|
||||||
Some(arg) => {
|
Some(arg) => {
|
||||||
if self.check(&token::Colon) | self.check(&token::Eq) {
|
if self.check(&token::Colon) | self.check(&token::Eq) {
|
||||||
@ -476,7 +500,7 @@ impl<'a> Parser<'a> {
|
|||||||
/// That is, parse `<term>` in `Item = <term>`.
|
/// That is, parse `<term>` in `Item = <term>`.
|
||||||
/// Right now, this only admits types in `<term>`.
|
/// Right now, this only admits types in `<term>`.
|
||||||
fn parse_assoc_equality_term(&mut self, ident: Ident, eq: Span) -> PResult<'a, P<ast::Ty>> {
|
fn parse_assoc_equality_term(&mut self, ident: Ident, eq: Span) -> PResult<'a, P<ast::Ty>> {
|
||||||
let arg = self.parse_generic_arg()?;
|
let arg = self.parse_generic_arg(None)?;
|
||||||
let span = ident.span.to(self.prev_token.span);
|
let span = ident.span.to(self.prev_token.span);
|
||||||
match arg {
|
match arg {
|
||||||
Some(GenericArg::Type(ty)) => return Ok(ty),
|
Some(GenericArg::Type(ty)) => return Ok(ty),
|
||||||
@ -563,7 +587,10 @@ impl<'a> Parser<'a> {
|
|||||||
|
|
||||||
/// Parse a generic argument in a path segment.
|
/// Parse a generic argument in a path segment.
|
||||||
/// This does not include constraints, e.g., `Item = u8`, which is handled in `parse_angle_arg`.
|
/// This does not include constraints, e.g., `Item = u8`, which is handled in `parse_angle_arg`.
|
||||||
pub(super) fn parse_generic_arg(&mut self) -> PResult<'a, Option<GenericArg>> {
|
pub(super) fn parse_generic_arg(
|
||||||
|
&mut self,
|
||||||
|
ty_generics: Option<&Generics>,
|
||||||
|
) -> PResult<'a, Option<GenericArg>> {
|
||||||
let start = self.token.span;
|
let start = self.token.span;
|
||||||
let arg = if self.check_lifetime() && self.look_ahead(1, |t| !t.is_like_plus()) {
|
let arg = if self.check_lifetime() && self.look_ahead(1, |t| !t.is_like_plus()) {
|
||||||
// Parse lifetime argument.
|
// Parse lifetime argument.
|
||||||
@ -580,25 +607,8 @@ impl<'a> Parser<'a> {
|
|||||||
return self.recover_const_arg(start, err).map(Some);
|
return self.recover_const_arg(start, err).map(Some);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if self.eat_keyword_noexpect(kw::Const) {
|
} else if self.token.is_keyword(kw::Const) {
|
||||||
// Detect and recover from the old, pre-RFC2000 syntax for const generics.
|
return self.recover_const_param_declaration(ty_generics);
|
||||||
let mut err = self.struct_span_err(
|
|
||||||
start,
|
|
||||||
"expected lifetime, type, or constant, found keyword `const`",
|
|
||||||
);
|
|
||||||
if self.check_const_arg() {
|
|
||||||
err.span_suggestion_verbose(
|
|
||||||
start.until(self.token.span),
|
|
||||||
"the `const` keyword is only needed in the definition of the type",
|
|
||||||
String::new(),
|
|
||||||
Applicability::MaybeIncorrect,
|
|
||||||
);
|
|
||||||
err.emit();
|
|
||||||
GenericArg::Const(self.parse_const_arg()?)
|
|
||||||
} else {
|
|
||||||
let after_kw_const = self.token.span;
|
|
||||||
return self.recover_const_arg(after_kw_const, err).map(Some);
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
return Ok(None);
|
return Ok(None);
|
||||||
};
|
};
|
||||||
|
@ -4,9 +4,10 @@ use crate::{maybe_recover_from_interpolated_ty_qpath, maybe_whole};
|
|||||||
|
|
||||||
use rustc_ast::ptr::P;
|
use rustc_ast::ptr::P;
|
||||||
use rustc_ast::token::{self, Token, TokenKind};
|
use rustc_ast::token::{self, Token, TokenKind};
|
||||||
use rustc_ast::{self as ast, BareFnTy, FnRetTy, GenericParam, Lifetime, MutTy, Ty, TyKind};
|
use rustc_ast::{
|
||||||
use rustc_ast::{GenericBound, GenericBounds, MacCall, Mutability};
|
self as ast, BareFnTy, FnRetTy, GenericBound, GenericBounds, GenericParam, Generics, Lifetime,
|
||||||
use rustc_ast::{PolyTraitRef, TraitBoundModifier, TraitObjectSyntax};
|
MacCall, MutTy, Mutability, PolyTraitRef, TraitBoundModifier, TraitObjectSyntax, Ty, TyKind,
|
||||||
|
};
|
||||||
use rustc_errors::{pluralize, struct_span_err, Applicability, PResult};
|
use rustc_errors::{pluralize, struct_span_err, Applicability, PResult};
|
||||||
use rustc_span::source_map::Span;
|
use rustc_span::source_map::Span;
|
||||||
use rustc_span::symbol::{kw, sym};
|
use rustc_span::symbol::{kw, sym};
|
||||||
@ -98,6 +99,20 @@ impl<'a> Parser<'a> {
|
|||||||
AllowCVariadic::No,
|
AllowCVariadic::No,
|
||||||
RecoverQPath::Yes,
|
RecoverQPath::Yes,
|
||||||
RecoverReturnSign::Yes,
|
RecoverReturnSign::Yes,
|
||||||
|
None,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(super) fn parse_ty_with_generics_recovery(
|
||||||
|
&mut self,
|
||||||
|
ty_params: &Generics,
|
||||||
|
) -> PResult<'a, P<Ty>> {
|
||||||
|
self.parse_ty_common(
|
||||||
|
AllowPlus::Yes,
|
||||||
|
AllowCVariadic::No,
|
||||||
|
RecoverQPath::Yes,
|
||||||
|
RecoverReturnSign::Yes,
|
||||||
|
Some(ty_params),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -110,6 +125,7 @@ impl<'a> Parser<'a> {
|
|||||||
AllowCVariadic::Yes,
|
AllowCVariadic::Yes,
|
||||||
RecoverQPath::Yes,
|
RecoverQPath::Yes,
|
||||||
RecoverReturnSign::Yes,
|
RecoverReturnSign::Yes,
|
||||||
|
None,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -125,6 +141,7 @@ impl<'a> Parser<'a> {
|
|||||||
AllowCVariadic::No,
|
AllowCVariadic::No,
|
||||||
RecoverQPath::Yes,
|
RecoverQPath::Yes,
|
||||||
RecoverReturnSign::Yes,
|
RecoverReturnSign::Yes,
|
||||||
|
None,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -135,6 +152,7 @@ impl<'a> Parser<'a> {
|
|||||||
AllowCVariadic::Yes,
|
AllowCVariadic::Yes,
|
||||||
RecoverQPath::Yes,
|
RecoverQPath::Yes,
|
||||||
RecoverReturnSign::OnlyFatArrow,
|
RecoverReturnSign::OnlyFatArrow,
|
||||||
|
None,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -152,6 +170,7 @@ impl<'a> Parser<'a> {
|
|||||||
AllowCVariadic::No,
|
AllowCVariadic::No,
|
||||||
recover_qpath,
|
recover_qpath,
|
||||||
recover_return_sign,
|
recover_return_sign,
|
||||||
|
None,
|
||||||
)?;
|
)?;
|
||||||
FnRetTy::Ty(ty)
|
FnRetTy::Ty(ty)
|
||||||
} else if recover_return_sign.can_recover(&self.token.kind) {
|
} else if recover_return_sign.can_recover(&self.token.kind) {
|
||||||
@ -171,6 +190,7 @@ impl<'a> Parser<'a> {
|
|||||||
AllowCVariadic::No,
|
AllowCVariadic::No,
|
||||||
recover_qpath,
|
recover_qpath,
|
||||||
recover_return_sign,
|
recover_return_sign,
|
||||||
|
None,
|
||||||
)?;
|
)?;
|
||||||
FnRetTy::Ty(ty)
|
FnRetTy::Ty(ty)
|
||||||
} else {
|
} else {
|
||||||
@ -184,6 +204,7 @@ impl<'a> Parser<'a> {
|
|||||||
allow_c_variadic: AllowCVariadic,
|
allow_c_variadic: AllowCVariadic,
|
||||||
recover_qpath: RecoverQPath,
|
recover_qpath: RecoverQPath,
|
||||||
recover_return_sign: RecoverReturnSign,
|
recover_return_sign: RecoverReturnSign,
|
||||||
|
ty_generics: Option<&Generics>,
|
||||||
) -> PResult<'a, P<Ty>> {
|
) -> PResult<'a, P<Ty>> {
|
||||||
let allow_qpath_recovery = recover_qpath == RecoverQPath::Yes;
|
let allow_qpath_recovery = recover_qpath == RecoverQPath::Yes;
|
||||||
maybe_recover_from_interpolated_ty_qpath!(self, allow_qpath_recovery);
|
maybe_recover_from_interpolated_ty_qpath!(self, allow_qpath_recovery);
|
||||||
@ -233,7 +254,7 @@ impl<'a> Parser<'a> {
|
|||||||
let (qself, path) = self.parse_qpath(PathStyle::Type)?;
|
let (qself, path) = self.parse_qpath(PathStyle::Type)?;
|
||||||
TyKind::Path(Some(qself), path)
|
TyKind::Path(Some(qself), path)
|
||||||
} else if self.check_path() {
|
} else if self.check_path() {
|
||||||
self.parse_path_start_ty(lo, allow_plus)?
|
self.parse_path_start_ty(lo, allow_plus, ty_generics)?
|
||||||
} else if self.can_begin_bound() {
|
} else if self.can_begin_bound() {
|
||||||
self.parse_bare_trait_object(lo, allow_plus)?
|
self.parse_bare_trait_object(lo, allow_plus)?
|
||||||
} else if self.eat(&token::DotDotDot) {
|
} else if self.eat(&token::DotDotDot) {
|
||||||
@ -512,9 +533,14 @@ impl<'a> Parser<'a> {
|
|||||||
/// 1. a type macro, `mac!(...)`,
|
/// 1. a type macro, `mac!(...)`,
|
||||||
/// 2. a bare trait object, `B0 + ... + Bn`,
|
/// 2. a bare trait object, `B0 + ... + Bn`,
|
||||||
/// 3. or a path, `path::to::MyType`.
|
/// 3. or a path, `path::to::MyType`.
|
||||||
fn parse_path_start_ty(&mut self, lo: Span, allow_plus: AllowPlus) -> PResult<'a, TyKind> {
|
fn parse_path_start_ty(
|
||||||
|
&mut self,
|
||||||
|
lo: Span,
|
||||||
|
allow_plus: AllowPlus,
|
||||||
|
ty_generics: Option<&Generics>,
|
||||||
|
) -> PResult<'a, TyKind> {
|
||||||
// Simple path
|
// Simple path
|
||||||
let path = self.parse_path(PathStyle::Type)?;
|
let path = self.parse_path_inner(PathStyle::Type, ty_generics)?;
|
||||||
if self.eat(&token::Not) {
|
if self.eat(&token::Not) {
|
||||||
// Macro invocation in type position
|
// Macro invocation in type position
|
||||||
Ok(TyKind::MacCall(MacCall {
|
Ok(TyKind::MacCall(MacCall {
|
||||||
|
@ -0,0 +1,15 @@
|
|||||||
|
struct NInts<const N: usize>([u8; N]);
|
||||||
|
impl NInts<const N: usize> {} //~ ERROR unexpected `const` parameter declaration
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
let _: () = 42; //~ ERROR mismatched types
|
||||||
|
}
|
||||||
|
|
||||||
|
fn banana(a: <T<const N: usize>>::BAR) {}
|
||||||
|
//~^ ERROR unexpected `const` parameter declaration
|
||||||
|
//~| ERROR cannot find type `T` in this scope
|
||||||
|
fn chaenomeles() {
|
||||||
|
path::path::Struct::<const N: usize>()
|
||||||
|
//~^ ERROR unexpected `const` parameter declaration
|
||||||
|
//~| ERROR failed to resolve: use of undeclared crate or module `path`
|
||||||
|
}
|
@ -0,0 +1,47 @@
|
|||||||
|
error: unexpected `const` parameter declaration
|
||||||
|
--> $DIR/const-param-decl-on-type-instead-of-impl.rs:2:12
|
||||||
|
|
|
||||||
|
LL | impl NInts<const N: usize> {}
|
||||||
|
| ^^^^^^^^^^^^^^ expected a `const` expression, not a parameter declaration
|
||||||
|
|
|
||||||
|
help: `const` parameters must be declared for the `impl`
|
||||||
|
|
|
||||||
|
LL | impl<const N: usize> NInts<N> {}
|
||||||
|
| ++++++++++++++++ ~
|
||||||
|
|
||||||
|
error: unexpected `const` parameter declaration
|
||||||
|
--> $DIR/const-param-decl-on-type-instead-of-impl.rs:8:17
|
||||||
|
|
|
||||||
|
LL | fn banana(a: <T<const N: usize>>::BAR) {}
|
||||||
|
| ^^^^^^^^^^^^^^ expected a `const` expression, not a parameter declaration
|
||||||
|
|
||||||
|
error: unexpected `const` parameter declaration
|
||||||
|
--> $DIR/const-param-decl-on-type-instead-of-impl.rs:12:26
|
||||||
|
|
|
||||||
|
LL | path::path::Struct::<const N: usize>()
|
||||||
|
| ^^^^^^^^^^^^^^ expected a `const` expression, not a parameter declaration
|
||||||
|
|
||||||
|
error[E0433]: failed to resolve: use of undeclared crate or module `path`
|
||||||
|
--> $DIR/const-param-decl-on-type-instead-of-impl.rs:12:5
|
||||||
|
|
|
||||||
|
LL | path::path::Struct::<const N: usize>()
|
||||||
|
| ^^^^ use of undeclared crate or module `path`
|
||||||
|
|
||||||
|
error[E0412]: cannot find type `T` in this scope
|
||||||
|
--> $DIR/const-param-decl-on-type-instead-of-impl.rs:8:15
|
||||||
|
|
|
||||||
|
LL | fn banana(a: <T<const N: usize>>::BAR) {}
|
||||||
|
| ^ not found in this scope
|
||||||
|
|
||||||
|
error[E0308]: mismatched types
|
||||||
|
--> $DIR/const-param-decl-on-type-instead-of-impl.rs:5:17
|
||||||
|
|
|
||||||
|
LL | let _: () = 42;
|
||||||
|
| -- ^^ expected `()`, found integer
|
||||||
|
| |
|
||||||
|
| expected due to this
|
||||||
|
|
||||||
|
error: aborting due to 6 previous errors
|
||||||
|
|
||||||
|
Some errors have detailed explanations: E0308, E0412, E0433.
|
||||||
|
For more information about an error, try `rustc --explain E0308`.
|
@ -2236,18 +2236,10 @@ fn rewrite_fn_base(
|
|||||||
result.push_str(¶m_indent.to_string_with_newline(context.config));
|
result.push_str(¶m_indent.to_string_with_newline(context.config));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Skip `pub(crate)`.
|
|
||||||
let lo_after_visibility = get_bytepos_after_visibility(fn_sig.visibility, span);
|
|
||||||
// A conservative estimation, the goal is to be over all parens in generics
|
|
||||||
let params_start = fn_sig
|
|
||||||
.generics
|
|
||||||
.params
|
|
||||||
.last()
|
|
||||||
.map_or(lo_after_visibility, |param| param.span().hi());
|
|
||||||
let params_end = if fd.inputs.is_empty() {
|
let params_end = if fd.inputs.is_empty() {
|
||||||
context
|
context
|
||||||
.snippet_provider
|
.snippet_provider
|
||||||
.span_after(mk_sp(params_start, span.hi()), ")")
|
.span_after(mk_sp(fn_sig.generics.span.hi(), span.hi()), ")")
|
||||||
} else {
|
} else {
|
||||||
let last_span = mk_sp(fd.inputs[fd.inputs.len() - 1].span().hi(), span.hi());
|
let last_span = mk_sp(fd.inputs[fd.inputs.len() - 1].span().hi(), span.hi());
|
||||||
context.snippet_provider.span_after(last_span, ")")
|
context.snippet_provider.span_after(last_span, ")")
|
||||||
@ -2255,7 +2247,7 @@ fn rewrite_fn_base(
|
|||||||
let params_span = mk_sp(
|
let params_span = mk_sp(
|
||||||
context
|
context
|
||||||
.snippet_provider
|
.snippet_provider
|
||||||
.span_after(mk_sp(params_start, span.hi()), "("),
|
.span_after(mk_sp(fn_sig.generics.span.hi(), span.hi()), "("),
|
||||||
params_end,
|
params_end,
|
||||||
);
|
);
|
||||||
let param_str = rewrite_params(
|
let param_str = rewrite_params(
|
||||||
|
Loading…
Reference in New Issue
Block a user