Auto merge of #65196 - Centril:rollup-q06lcxm, r=Centril
Rollup of 8 pull requests Successful merges: - #64726 (rewrite documentation for unimplemented! to clarify use) - #65040 (syntax: more cleanups in item and function signature parsing) - #65046 (Make `Cell::new` method come first in documentation) - #65098 (Add long error explanation for E0561) - #65150 (Suggest dereferencing boolean reference when used in 'if' or 'while') - #65154 (Fix const generic arguments not displaying in types mismatch diagnostic) - #65181 (fix bug in folding for constants) - #65187 (use 'invalid argument' for vxWorks) Failed merges: - #65179 (Add long error explanation for E0567) r? @ghost
This commit is contained in:
commit
1e1f25e31b
24 changed files with 469 additions and 309 deletions
|
@ -229,52 +229,6 @@ pub struct Cell<T: ?Sized> {
|
||||||
value: UnsafeCell<T>,
|
value: UnsafeCell<T>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T:Copy> Cell<T> {
|
|
||||||
/// Returns a copy of the contained value.
|
|
||||||
///
|
|
||||||
/// # Examples
|
|
||||||
///
|
|
||||||
/// ```
|
|
||||||
/// use std::cell::Cell;
|
|
||||||
///
|
|
||||||
/// let c = Cell::new(5);
|
|
||||||
///
|
|
||||||
/// let five = c.get();
|
|
||||||
/// ```
|
|
||||||
#[inline]
|
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
|
||||||
pub fn get(&self) -> T {
|
|
||||||
unsafe{ *self.value.get() }
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Updates the contained value using a function and returns the new value.
|
|
||||||
///
|
|
||||||
/// # Examples
|
|
||||||
///
|
|
||||||
/// ```
|
|
||||||
/// #![feature(cell_update)]
|
|
||||||
///
|
|
||||||
/// use std::cell::Cell;
|
|
||||||
///
|
|
||||||
/// let c = Cell::new(5);
|
|
||||||
/// let new = c.update(|x| x + 1);
|
|
||||||
///
|
|
||||||
/// assert_eq!(new, 6);
|
|
||||||
/// assert_eq!(c.get(), 6);
|
|
||||||
/// ```
|
|
||||||
#[inline]
|
|
||||||
#[unstable(feature = "cell_update", issue = "50186")]
|
|
||||||
pub fn update<F>(&self, f: F) -> T
|
|
||||||
where
|
|
||||||
F: FnOnce(T) -> T,
|
|
||||||
{
|
|
||||||
let old = self.get();
|
|
||||||
let new = f(old);
|
|
||||||
self.set(new);
|
|
||||||
new
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
unsafe impl<T: ?Sized> Send for Cell<T> where T: Send {}
|
unsafe impl<T: ?Sized> Send for Cell<T> where T: Send {}
|
||||||
|
|
||||||
|
@ -448,6 +402,52 @@ impl<T> Cell<T> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<T:Copy> Cell<T> {
|
||||||
|
/// Returns a copy of the contained value.
|
||||||
|
///
|
||||||
|
/// # Examples
|
||||||
|
///
|
||||||
|
/// ```
|
||||||
|
/// use std::cell::Cell;
|
||||||
|
///
|
||||||
|
/// let c = Cell::new(5);
|
||||||
|
///
|
||||||
|
/// let five = c.get();
|
||||||
|
/// ```
|
||||||
|
#[inline]
|
||||||
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
|
pub fn get(&self) -> T {
|
||||||
|
unsafe{ *self.value.get() }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Updates the contained value using a function and returns the new value.
|
||||||
|
///
|
||||||
|
/// # Examples
|
||||||
|
///
|
||||||
|
/// ```
|
||||||
|
/// #![feature(cell_update)]
|
||||||
|
///
|
||||||
|
/// use std::cell::Cell;
|
||||||
|
///
|
||||||
|
/// let c = Cell::new(5);
|
||||||
|
/// let new = c.update(|x| x + 1);
|
||||||
|
///
|
||||||
|
/// assert_eq!(new, 6);
|
||||||
|
/// assert_eq!(c.get(), 6);
|
||||||
|
/// ```
|
||||||
|
#[inline]
|
||||||
|
#[unstable(feature = "cell_update", issue = "50186")]
|
||||||
|
pub fn update<F>(&self, f: F) -> T
|
||||||
|
where
|
||||||
|
F: FnOnce(T) -> T,
|
||||||
|
{
|
||||||
|
let old = self.get();
|
||||||
|
let new = f(old);
|
||||||
|
self.set(new);
|
||||||
|
new
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl<T: ?Sized> Cell<T> {
|
impl<T: ?Sized> Cell<T> {
|
||||||
/// Returns a raw pointer to the underlying data in this cell.
|
/// Returns a raw pointer to the underlying data in this cell.
|
||||||
///
|
///
|
||||||
|
|
|
@ -520,18 +520,20 @@ macro_rules! unreachable {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Indicates unfinished code.
|
/// Indicates unfinished code by panicking with a message of "not yet implemented".
|
||||||
///
|
///
|
||||||
/// This can be useful if you are prototyping and are just looking to have your
|
/// This allows the your code to type-check, which is useful if you are prototyping or
|
||||||
/// code type-check, or if you're implementing a trait that requires multiple
|
/// implementing a trait that requires multiple methods which you don't plan of using all of.
|
||||||
/// methods, and you're only planning on using one of them.
|
|
||||||
///
|
///
|
||||||
/// There is no difference between `unimplemented!` and `todo!` apart from the
|
/// There is no difference between `unimplemented!` and `todo!` apart from the
|
||||||
/// name.
|
/// name.
|
||||||
///
|
///
|
||||||
/// # Panics
|
/// # Panics
|
||||||
///
|
///
|
||||||
/// This will always [panic!](macro.panic.html)
|
/// This will always [panic!](macro.panic.html) because `unimplemented!` is just a
|
||||||
|
/// shorthand for `panic!` with a fixed, specific message.
|
||||||
|
///
|
||||||
|
/// Like `panic!`, this macro has a second form for displaying custom values.
|
||||||
///
|
///
|
||||||
/// # Examples
|
/// # Examples
|
||||||
///
|
///
|
||||||
|
@ -539,38 +541,53 @@ macro_rules! unreachable {
|
||||||
///
|
///
|
||||||
/// ```
|
/// ```
|
||||||
/// trait Foo {
|
/// trait Foo {
|
||||||
/// fn bar(&self);
|
/// fn bar(&self) -> u8;
|
||||||
/// fn baz(&self);
|
/// fn baz(&self);
|
||||||
|
/// fn qux(&self) -> Result<u64, ()>;
|
||||||
/// }
|
/// }
|
||||||
/// ```
|
/// ```
|
||||||
///
|
///
|
||||||
/// We want to implement `Foo` on one of our types, but we also want to work on
|
/// We want to implement `Foo` for 'MyStruct', but so far we only know how to
|
||||||
/// just `bar()` first. In order for our code to compile, we need to implement
|
/// implement the `bar()` function. `baz()` and `qux()` will still need to be defined
|
||||||
/// `baz()`, so we can use `unimplemented!`:
|
/// in our implementation of `Foo`, but we can use `unimplemented!` in their definitions
|
||||||
|
/// to allow our code to compile.
|
||||||
|
///
|
||||||
|
/// In the meantime, we want to have our program stop running once these
|
||||||
|
/// unimplemented functions are reached.
|
||||||
///
|
///
|
||||||
/// ```
|
/// ```
|
||||||
/// # trait Foo {
|
/// # trait Foo {
|
||||||
/// # fn bar(&self);
|
/// # fn bar(&self) -> u8;
|
||||||
/// # fn baz(&self);
|
/// # fn baz(&self);
|
||||||
|
/// # fn qux(&self) -> Result<u64, ()>;
|
||||||
/// # }
|
/// # }
|
||||||
/// struct MyStruct;
|
/// struct MyStruct;
|
||||||
///
|
///
|
||||||
/// impl Foo for MyStruct {
|
/// impl Foo for MyStruct {
|
||||||
/// fn bar(&self) {
|
/// fn bar(&self) -> u8 {
|
||||||
/// // implementation goes here
|
/// 1 + 1
|
||||||
/// }
|
/// }
|
||||||
///
|
///
|
||||||
/// fn baz(&self) {
|
/// fn baz(&self) {
|
||||||
/// // let's not worry about implementing baz() for now
|
/// // We aren't sure how to even start writing baz yet,
|
||||||
|
/// // so we have no logic here at all.
|
||||||
|
/// // This will display "thread 'main' panicked at 'not yet implemented'".
|
||||||
/// unimplemented!();
|
/// unimplemented!();
|
||||||
/// }
|
/// }
|
||||||
|
///
|
||||||
|
/// fn qux(&self) -> Result<u64, ()> {
|
||||||
|
/// let n = self.bar();
|
||||||
|
/// // We have some logic here,
|
||||||
|
/// // so we can use unimplemented! to display what we have so far.
|
||||||
|
/// // This will display:
|
||||||
|
/// // "thread 'main' panicked at 'not yet implemented: we need to divide by 2'".
|
||||||
|
/// unimplemented!("we need to divide by {}", n);
|
||||||
|
/// }
|
||||||
/// }
|
/// }
|
||||||
///
|
///
|
||||||
/// fn main() {
|
/// fn main() {
|
||||||
/// let s = MyStruct;
|
/// let s = MyStruct;
|
||||||
/// s.bar();
|
/// s.bar();
|
||||||
///
|
|
||||||
/// // we aren't even using baz() yet, so this is fine.
|
|
||||||
/// }
|
/// }
|
||||||
/// ```
|
/// ```
|
||||||
#[macro_export]
|
#[macro_export]
|
||||||
|
|
|
@ -935,6 +935,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
|
||||||
.filter(|(a, b)| a == b)
|
.filter(|(a, b)| a == b)
|
||||||
.count();
|
.count();
|
||||||
let len = sub1.len() - common_default_params;
|
let len = sub1.len() - common_default_params;
|
||||||
|
let consts_offset = len - sub1.consts().count();
|
||||||
|
|
||||||
// Only draw `<...>` if there're lifetime/type arguments.
|
// Only draw `<...>` if there're lifetime/type arguments.
|
||||||
if len > 0 {
|
if len > 0 {
|
||||||
|
@ -981,7 +982,8 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
|
||||||
// ^ elided type as this type argument was the same in both sides
|
// ^ elided type as this type argument was the same in both sides
|
||||||
let type_arguments = sub1.types().zip(sub2.types());
|
let type_arguments = sub1.types().zip(sub2.types());
|
||||||
let regions_len = sub1.regions().count();
|
let regions_len = sub1.regions().count();
|
||||||
for (i, (ta1, ta2)) in type_arguments.take(len).enumerate() {
|
let num_display_types = consts_offset - regions_len;
|
||||||
|
for (i, (ta1, ta2)) in type_arguments.take(num_display_types).enumerate() {
|
||||||
let i = i + regions_len;
|
let i = i + regions_len;
|
||||||
if ta1 == ta2 {
|
if ta1 == ta2 {
|
||||||
values.0.push_normal("_");
|
values.0.push_normal("_");
|
||||||
|
@ -994,6 +996,21 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
|
||||||
self.push_comma(&mut values.0, &mut values.1, len, i);
|
self.push_comma(&mut values.0, &mut values.1, len, i);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Do the same for const arguments, if they are equal, do not highlight and
|
||||||
|
// elide them from the output.
|
||||||
|
let const_arguments = sub1.consts().zip(sub2.consts());
|
||||||
|
for (i, (ca1, ca2)) in const_arguments.enumerate() {
|
||||||
|
let i = i + consts_offset;
|
||||||
|
if ca1 == ca2 {
|
||||||
|
values.0.push_normal("_");
|
||||||
|
values.1.push_normal("_");
|
||||||
|
} else {
|
||||||
|
values.0.push_highlighted(ca1.to_string());
|
||||||
|
values.1.push_highlighted(ca2.to_string());
|
||||||
|
}
|
||||||
|
self.push_comma(&mut values.0, &mut values.1, len, i);
|
||||||
|
}
|
||||||
|
|
||||||
// Close the type argument bracket.
|
// Close the type argument bracket.
|
||||||
// Only draw `<...>` if there're lifetime/type arguments.
|
// Only draw `<...>` if there're lifetime/type arguments.
|
||||||
if len > 0 {
|
if len > 0 {
|
||||||
|
|
|
@ -250,7 +250,9 @@ impl FlagComputation {
|
||||||
ConstValue::Placeholder(_) => {
|
ConstValue::Placeholder(_) => {
|
||||||
self.add_flags(TypeFlags::HAS_FREE_REGIONS | TypeFlags::HAS_CT_PLACEHOLDER);
|
self.add_flags(TypeFlags::HAS_FREE_REGIONS | TypeFlags::HAS_CT_PLACEHOLDER);
|
||||||
}
|
}
|
||||||
_ => {},
|
ConstValue::Scalar(_) => { }
|
||||||
|
ConstValue::Slice { data: _, start: _, end: _ } => { }
|
||||||
|
ConstValue::ByRef { alloc: _, offset: _ } => { }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -911,13 +911,15 @@ impl<'tcx> TypeVisitor<'tcx> for HasEscapingVarsVisitor {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn visit_const(&mut self, ct: &'tcx ty::Const<'tcx>) -> bool {
|
fn visit_const(&mut self, ct: &'tcx ty::Const<'tcx>) -> bool {
|
||||||
if let ty::Const {
|
// we don't have a `visit_infer_const` callback, so we have to
|
||||||
val: ConstValue::Infer(ty::InferConst::Canonical(debruijn, _)),
|
// hook in here to catch this case (annoying...), but
|
||||||
..
|
// otherwise we do want to remember to visit the rest of the
|
||||||
} = *ct {
|
// const, as it has types/regions embedded in a lot of other
|
||||||
debruijn >= self.outer_index
|
// places.
|
||||||
} else {
|
match ct.val {
|
||||||
false
|
ConstValue::Infer(ty::InferConst::Canonical(debruijn, _))
|
||||||
|
if debruijn >= self.outer_index => true,
|
||||||
|
_ => ct.super_visit_with(self),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -689,7 +689,7 @@ pub trait PrettyPrinter<'tcx>:
|
||||||
if self.tcx().sess.verbose() {
|
if self.tcx().sess.verbose() {
|
||||||
p!(write(
|
p!(write(
|
||||||
" closure_kind_ty={:?} closure_sig_ty={:?}",
|
" closure_kind_ty={:?} closure_sig_ty={:?}",
|
||||||
substs.as_closure().kind(did, self.tcx()),
|
substs.as_closure().kind_ty(did, self.tcx()),
|
||||||
substs.as_closure().sig_ty(did, self.tcx())
|
substs.as_closure().sig_ty(did, self.tcx())
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
@ -698,7 +698,9 @@ pub trait PrettyPrinter<'tcx>:
|
||||||
},
|
},
|
||||||
ty::Array(ty, sz) => {
|
ty::Array(ty, sz) => {
|
||||||
p!(write("["), print(ty), write("; "));
|
p!(write("["), print(ty), write("; "));
|
||||||
if let ConstValue::Unevaluated(..) = sz.val {
|
if self.tcx().sess.verbose() {
|
||||||
|
p!(write("{:?}", sz));
|
||||||
|
} else if let ConstValue::Unevaluated(..) = sz.val {
|
||||||
// do not try to evalute unevaluated constants. If we are const evaluating an
|
// do not try to evalute unevaluated constants. If we are const evaluating an
|
||||||
// array length anon const, rustc will (with debug assertions) print the
|
// array length anon const, rustc will (with debug assertions) print the
|
||||||
// constant's path. Which will end up here again.
|
// constant's path. Which will end up here again.
|
||||||
|
@ -855,6 +857,11 @@ pub trait PrettyPrinter<'tcx>:
|
||||||
) -> Result<Self::Const, Self::Error> {
|
) -> Result<Self::Const, Self::Error> {
|
||||||
define_scoped_cx!(self);
|
define_scoped_cx!(self);
|
||||||
|
|
||||||
|
if self.tcx().sess.verbose() {
|
||||||
|
p!(write("Const({:?}: {:?})", ct.val, ct.ty));
|
||||||
|
return Ok(self);
|
||||||
|
}
|
||||||
|
|
||||||
let u8 = self.tcx().types.u8;
|
let u8 = self.tcx().types.u8;
|
||||||
if let ty::FnDef(did, substs) = ct.ty.kind {
|
if let ty::FnDef(did, substs) = ct.ty.kind {
|
||||||
p!(print_value_path(did, substs));
|
p!(print_value_path(did, substs));
|
||||||
|
|
|
@ -2203,7 +2203,9 @@ impl<'tcx> TyS<'tcx> {
|
||||||
_ => bug!("cannot convert type `{:?}` to a closure kind", self),
|
_ => bug!("cannot convert type `{:?}` to a closure kind", self),
|
||||||
},
|
},
|
||||||
|
|
||||||
Infer(_) => None,
|
// "Bound" types appear in canonical queries when the
|
||||||
|
// closure type is not yet known
|
||||||
|
Bound(..) | Infer(_) => None,
|
||||||
|
|
||||||
Error => Some(ty::ClosureKind::Fn),
|
Error => Some(ty::ClosureKind::Fn),
|
||||||
|
|
||||||
|
|
|
@ -286,6 +286,34 @@ fn main() {
|
||||||
```
|
```
|
||||||
"##,
|
"##,
|
||||||
|
|
||||||
|
E0561: r##"
|
||||||
|
A non-ident or non-wildcard pattern has been used as a parameter of a function
|
||||||
|
pointer type.
|
||||||
|
|
||||||
|
Erroneous code example:
|
||||||
|
|
||||||
|
```compile_fail,E0561
|
||||||
|
type A1 = fn(mut param: u8); // error!
|
||||||
|
type A2 = fn(¶m: u32); // error!
|
||||||
|
```
|
||||||
|
|
||||||
|
When using an alias over a function type, you cannot e.g. denote a parameter as
|
||||||
|
being mutable.
|
||||||
|
|
||||||
|
To fix the issue, remove patterns (`_` is allowed though). Example:
|
||||||
|
|
||||||
|
```
|
||||||
|
type A1 = fn(param: u8); // ok!
|
||||||
|
type A2 = fn(_: u32); // ok!
|
||||||
|
```
|
||||||
|
|
||||||
|
You can also omit the parameter name:
|
||||||
|
|
||||||
|
```
|
||||||
|
type A3 = fn(i16); // ok!
|
||||||
|
```
|
||||||
|
"##,
|
||||||
|
|
||||||
E0571: r##"
|
E0571: r##"
|
||||||
A `break` statement with an argument appeared in a non-`loop` loop.
|
A `break` statement with an argument appeared in a non-`loop` loop.
|
||||||
|
|
||||||
|
@ -503,7 +531,6 @@ Switch to the Rust 2018 edition to use `async fn`.
|
||||||
;
|
;
|
||||||
E0226, // only a single explicit lifetime bound is permitted
|
E0226, // only a single explicit lifetime bound is permitted
|
||||||
E0472, // asm! is unsupported on this target
|
E0472, // asm! is unsupported on this target
|
||||||
E0561, // patterns aren't allowed in function pointer types
|
|
||||||
E0567, // auto traits can not have generic parameters
|
E0567, // auto traits can not have generic parameters
|
||||||
E0568, // auto traits can not have super traits
|
E0568, // auto traits can not have super traits
|
||||||
E0666, // nested `impl Trait` is illegal
|
E0666, // nested `impl Trait` is illegal
|
||||||
|
|
|
@ -17,10 +17,12 @@ fn evaluate_obligation<'tcx>(
|
||||||
tcx: TyCtxt<'tcx>,
|
tcx: TyCtxt<'tcx>,
|
||||||
canonical_goal: CanonicalPredicateGoal<'tcx>,
|
canonical_goal: CanonicalPredicateGoal<'tcx>,
|
||||||
) -> Result<EvaluationResult, OverflowError> {
|
) -> Result<EvaluationResult, OverflowError> {
|
||||||
|
debug!("evaluate_obligation(canonical_goal={:#?})", canonical_goal);
|
||||||
tcx.infer_ctxt().enter_with_canonical(
|
tcx.infer_ctxt().enter_with_canonical(
|
||||||
DUMMY_SP,
|
DUMMY_SP,
|
||||||
&canonical_goal,
|
&canonical_goal,
|
||||||
|ref infcx, goal, _canonical_inference_vars| {
|
|ref infcx, goal, _canonical_inference_vars| {
|
||||||
|
debug!("evaluate_obligation: goal={:#?}", goal);
|
||||||
let ParamEnvAnd {
|
let ParamEnvAnd {
|
||||||
param_env,
|
param_env,
|
||||||
value: predicate,
|
value: predicate,
|
||||||
|
|
|
@ -349,7 +349,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||||
|
|
||||||
// If the span is from a macro, then it's hard to extract the text
|
// If the span is from a macro, then it's hard to extract the text
|
||||||
// and make a good suggestion, so don't bother.
|
// and make a good suggestion, so don't bother.
|
||||||
let is_macro = sp.from_expansion();
|
let is_desugaring = match sp.desugaring_kind() {
|
||||||
|
Some(k) => sp.is_desugaring(k),
|
||||||
|
None => false
|
||||||
|
};
|
||||||
|
let is_macro = sp.from_expansion() && !is_desugaring;
|
||||||
|
|
||||||
match (&expr.kind, &expected.kind, &checked_ty.kind) {
|
match (&expr.kind, &expected.kind, &checked_ty.kind) {
|
||||||
(_, &ty::Ref(_, exp, _), &ty::Ref(_, check, _)) => match (&exp.kind, &check.kind) {
|
(_, &ty::Ref(_, exp, _), &ty::Ref(_, check, _)) => match (&exp.kind, &check.kind) {
|
||||||
|
|
|
@ -87,6 +87,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(mut err) = self.demand_suptype_diag(expr.span, expected_ty, ty) {
|
if let Some(mut err) = self.demand_suptype_diag(expr.span, expected_ty, ty) {
|
||||||
|
self.suggest_ref_or_into(&mut err, expr, expected_ty, ty);
|
||||||
|
|
||||||
let expr = match &expr.kind {
|
let expr = match &expr.kind {
|
||||||
ExprKind::DropTemps(expr) => expr,
|
ExprKind::DropTemps(expr) => expr,
|
||||||
_ => expr,
|
_ => expr,
|
||||||
|
|
|
@ -3112,8 +3112,10 @@ mod tests {
|
||||||
|
|
||||||
#[cfg(windows)]
|
#[cfg(windows)]
|
||||||
let invalid_options = 87; // ERROR_INVALID_PARAMETER
|
let invalid_options = 87; // ERROR_INVALID_PARAMETER
|
||||||
#[cfg(unix)]
|
#[cfg(all(unix, not(target_os = "vxworks")))]
|
||||||
let invalid_options = "Invalid argument";
|
let invalid_options = "Invalid argument";
|
||||||
|
#[cfg(target_os = "vxworks")]
|
||||||
|
let invalid_options = "invalid argument";
|
||||||
|
|
||||||
// Test various combinations of creation modes and access modes.
|
// Test various combinations of creation modes and access modes.
|
||||||
//
|
//
|
||||||
|
|
|
@ -11,7 +11,7 @@ mod stmt;
|
||||||
mod generics;
|
mod generics;
|
||||||
|
|
||||||
use crate::ast::{
|
use crate::ast::{
|
||||||
self, DUMMY_NODE_ID, AttrStyle, Attribute, BindingMode, CrateSugar, FnDecl, Ident,
|
self, DUMMY_NODE_ID, AttrStyle, Attribute, BindingMode, CrateSugar, Ident,
|
||||||
IsAsync, MacDelimiter, Mutability, Param, StrStyle, SelfKind, TyKind, Visibility,
|
IsAsync, MacDelimiter, Mutability, Param, StrStyle, SelfKind, TyKind, Visibility,
|
||||||
VisibilityKind, Unsafety,
|
VisibilityKind, Unsafety,
|
||||||
};
|
};
|
||||||
|
@ -56,6 +56,17 @@ crate enum BlockMode {
|
||||||
Ignore,
|
Ignore,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// The parsing configuration used to parse a parameter list (see `parse_fn_params`).
|
||||||
|
struct ParamCfg {
|
||||||
|
/// Is `self` is allowed as the first parameter?
|
||||||
|
is_self_allowed: bool,
|
||||||
|
/// Is `...` allowed as the tail of the parameter list?
|
||||||
|
allow_c_variadic: bool,
|
||||||
|
/// `is_name_required` decides if, per-parameter,
|
||||||
|
/// the parameter must have a pattern or just a type.
|
||||||
|
is_name_required: fn(&token::Token) -> bool,
|
||||||
|
}
|
||||||
|
|
||||||
/// Like `maybe_whole_expr`, but for things other than expressions.
|
/// Like `maybe_whole_expr`, but for things other than expressions.
|
||||||
#[macro_export]
|
#[macro_export]
|
||||||
macro_rules! maybe_whole {
|
macro_rules! maybe_whole {
|
||||||
|
@ -1094,26 +1105,18 @@ impl<'a> Parser<'a> {
|
||||||
res
|
res
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parse_fn_params(
|
/// Parses the parameter list of a function, including the `(` and `)` delimiters.
|
||||||
&mut self,
|
fn parse_fn_params(&mut self, mut cfg: ParamCfg) -> PResult<'a, Vec<Param>> {
|
||||||
named_params: bool,
|
|
||||||
allow_c_variadic: bool,
|
|
||||||
) -> PResult<'a, Vec<Param>> {
|
|
||||||
let sp = self.token.span;
|
let sp = self.token.span;
|
||||||
let do_not_enforce_named_params_for_c_variadic = |token: &token::Token| {
|
let is_trait_item = cfg.is_self_allowed;
|
||||||
match token.kind {
|
|
||||||
token::DotDotDot => false,
|
|
||||||
_ => named_params,
|
|
||||||
}
|
|
||||||
};
|
|
||||||
let mut c_variadic = false;
|
let mut c_variadic = false;
|
||||||
|
// Parse the arguments, starting out with `self` being possibly allowed...
|
||||||
let (params, _) = self.parse_paren_comma_seq(|p| {
|
let (params, _) = self.parse_paren_comma_seq(|p| {
|
||||||
match p.parse_param_general(
|
let param = p.parse_param_general(&cfg, is_trait_item);
|
||||||
false,
|
// ...now that we've parsed the first argument, `self` is no longer allowed.
|
||||||
false,
|
cfg.is_self_allowed = false;
|
||||||
allow_c_variadic,
|
|
||||||
do_not_enforce_named_params_for_c_variadic,
|
match param {
|
||||||
) {
|
|
||||||
Ok(param) => Ok(
|
Ok(param) => Ok(
|
||||||
if let TyKind::CVarArgs = param.ty.kind {
|
if let TyKind::CVarArgs = param.ty.kind {
|
||||||
c_variadic = true;
|
c_variadic = true;
|
||||||
|
@ -1144,7 +1147,10 @@ impl<'a> Parser<'a> {
|
||||||
}
|
}
|
||||||
})?;
|
})?;
|
||||||
|
|
||||||
let params: Vec<_> = params.into_iter().filter_map(|x| x).collect();
|
let mut params: Vec<_> = params.into_iter().filter_map(|x| x).collect();
|
||||||
|
|
||||||
|
// Replace duplicated recovered params with `_` pattern to avoid unecessary errors.
|
||||||
|
self.deduplicate_recovered_params_names(&mut params);
|
||||||
|
|
||||||
if c_variadic && params.len() <= 1 {
|
if c_variadic && params.len() <= 1 {
|
||||||
self.span_err(
|
self.span_err(
|
||||||
|
@ -1156,79 +1162,53 @@ impl<'a> Parser<'a> {
|
||||||
Ok(params)
|
Ok(params)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Parses the parameter list and result type of a function that may have a `self` parameter.
|
|
||||||
fn parse_fn_decl_with_self(
|
|
||||||
&mut self,
|
|
||||||
is_name_required: impl Copy + Fn(&token::Token) -> bool,
|
|
||||||
) -> PResult<'a, P<FnDecl>> {
|
|
||||||
// Parse the arguments, starting out with `self` being allowed...
|
|
||||||
let mut is_self_allowed = true;
|
|
||||||
let (mut inputs, _): (Vec<_>, _) = self.parse_paren_comma_seq(|p| {
|
|
||||||
let res = p.parse_param_general(is_self_allowed, true, false, is_name_required);
|
|
||||||
// ...but now that we've parsed the first argument, `self` is no longer allowed.
|
|
||||||
is_self_allowed = false;
|
|
||||||
res
|
|
||||||
})?;
|
|
||||||
|
|
||||||
// Replace duplicated recovered params with `_` pattern to avoid unecessary errors.
|
|
||||||
self.deduplicate_recovered_params_names(&mut inputs);
|
|
||||||
|
|
||||||
Ok(P(FnDecl {
|
|
||||||
inputs,
|
|
||||||
output: self.parse_ret_ty(true)?,
|
|
||||||
}))
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Skips unexpected attributes and doc comments in this position and emits an appropriate
|
/// Skips unexpected attributes and doc comments in this position and emits an appropriate
|
||||||
/// error.
|
/// error.
|
||||||
/// This version of parse param doesn't necessarily require identifier names.
|
/// This version of parse param doesn't necessarily require identifier names.
|
||||||
fn parse_param_general(
|
fn parse_param_general(&mut self, cfg: &ParamCfg, is_trait_item: bool) -> PResult<'a, Param> {
|
||||||
&mut self,
|
|
||||||
is_self_allowed: bool,
|
|
||||||
is_trait_item: bool,
|
|
||||||
allow_c_variadic: bool,
|
|
||||||
is_name_required: impl Fn(&token::Token) -> bool,
|
|
||||||
) -> PResult<'a, Param> {
|
|
||||||
let lo = self.token.span;
|
let lo = self.token.span;
|
||||||
let attrs = self.parse_outer_attributes()?;
|
let attrs = self.parse_outer_attributes()?;
|
||||||
|
|
||||||
// Possibly parse `self`. Recover if we parsed it and it wasn't allowed here.
|
// Possibly parse `self`. Recover if we parsed it and it wasn't allowed here.
|
||||||
if let Some(mut param) = self.parse_self_param()? {
|
if let Some(mut param) = self.parse_self_param()? {
|
||||||
param.attrs = attrs.into();
|
param.attrs = attrs.into();
|
||||||
return if is_self_allowed {
|
return if cfg.is_self_allowed {
|
||||||
Ok(param)
|
Ok(param)
|
||||||
} else {
|
} else {
|
||||||
self.recover_bad_self_param(param, is_trait_item)
|
self.recover_bad_self_param(param, is_trait_item)
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
let is_name_required = is_name_required(&self.token);
|
let is_name_required = match self.token.kind {
|
||||||
|
token::DotDotDot => false,
|
||||||
|
_ => (cfg.is_name_required)(&self.token),
|
||||||
|
};
|
||||||
let (pat, ty) = if is_name_required || self.is_named_param() {
|
let (pat, ty) = if is_name_required || self.is_named_param() {
|
||||||
debug!("parse_param_general parse_pat (is_name_required:{})", is_name_required);
|
debug!("parse_param_general parse_pat (is_name_required:{})", is_name_required);
|
||||||
|
|
||||||
let pat = self.parse_fn_param_pat()?;
|
let pat = self.parse_fn_param_pat()?;
|
||||||
if let Err(mut err) = self.expect(&token::Colon) {
|
if let Err(mut err) = self.expect(&token::Colon) {
|
||||||
if let Some(ident) = self.parameter_without_type(
|
return if let Some(ident) = self.parameter_without_type(
|
||||||
&mut err,
|
&mut err,
|
||||||
pat,
|
pat,
|
||||||
is_name_required,
|
is_name_required,
|
||||||
is_self_allowed,
|
cfg.is_self_allowed,
|
||||||
is_trait_item,
|
is_trait_item,
|
||||||
) {
|
) {
|
||||||
err.emit();
|
err.emit();
|
||||||
return Ok(dummy_arg(ident));
|
Ok(dummy_arg(ident))
|
||||||
} else {
|
} else {
|
||||||
return Err(err);
|
Err(err)
|
||||||
}
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
self.eat_incorrect_doc_comment_for_param_type();
|
self.eat_incorrect_doc_comment_for_param_type();
|
||||||
(pat, self.parse_ty_common(true, true, allow_c_variadic)?)
|
(pat, self.parse_ty_common(true, true, cfg.allow_c_variadic)?)
|
||||||
} else {
|
} else {
|
||||||
debug!("parse_param_general ident_to_pat");
|
debug!("parse_param_general ident_to_pat");
|
||||||
let parser_snapshot_before_ty = self.clone();
|
let parser_snapshot_before_ty = self.clone();
|
||||||
self.eat_incorrect_doc_comment_for_param_type();
|
self.eat_incorrect_doc_comment_for_param_type();
|
||||||
let mut ty = self.parse_ty_common(true, true, allow_c_variadic);
|
let mut ty = self.parse_ty_common(true, true, cfg.allow_c_variadic);
|
||||||
if ty.is_ok() && self.token != token::Comma &&
|
if ty.is_ok() && self.token != token::Comma &&
|
||||||
self.token != token::CloseDelim(token::Paren) {
|
self.token != token::CloseDelim(token::Paren) {
|
||||||
// This wasn't actually a type, but a pattern looking like a type,
|
// This wasn't actually a type, but a pattern looking like a type,
|
||||||
|
|
|
@ -1,10 +1,10 @@
|
||||||
use super::{Parser, PResult, PathStyle, SemiColonMode, BlockMode};
|
use super::{Parser, PResult, PathStyle, SemiColonMode, BlockMode, ParamCfg};
|
||||||
|
|
||||||
use crate::maybe_whole;
|
use crate::maybe_whole;
|
||||||
use crate::ptr::P;
|
use crate::ptr::P;
|
||||||
use crate::ast::{
|
use crate::ast::{
|
||||||
self, DUMMY_NODE_ID, Ident, Attribute, AttrStyle,
|
self, DUMMY_NODE_ID, Ident, Attribute, AttrStyle,
|
||||||
Item, ItemKind, ImplItem, TraitItem, TraitItemKind,
|
Item, ItemKind, ImplItem, ImplItemKind, TraitItem, TraitItemKind,
|
||||||
UseTree, UseTreeKind, PathSegment,
|
UseTree, UseTreeKind, PathSegment,
|
||||||
IsAuto, Constness, IsAsync, Unsafety, Defaultness,
|
IsAuto, Constness, IsAsync, Unsafety, Defaultness,
|
||||||
Visibility, VisibilityKind, Mutability, FnDecl, FnHeader, MethodSig, Block,
|
Visibility, VisibilityKind, Mutability, FnDecl, FnHeader, MethodSig, Block,
|
||||||
|
@ -98,7 +98,7 @@ impl<'a> Parser<'a> {
|
||||||
|
|
||||||
let lo = self.token.span;
|
let lo = self.token.span;
|
||||||
|
|
||||||
let visibility = self.parse_visibility(false)?;
|
let vis = self.parse_visibility(false)?;
|
||||||
|
|
||||||
if self.eat_keyword(kw::Use) {
|
if self.eat_keyword(kw::Use) {
|
||||||
// USE ITEM
|
// USE ITEM
|
||||||
|
@ -106,15 +106,14 @@ impl<'a> Parser<'a> {
|
||||||
self.expect(&token::Semi)?;
|
self.expect(&token::Semi)?;
|
||||||
|
|
||||||
let span = lo.to(self.prev_span);
|
let span = lo.to(self.prev_span);
|
||||||
let item =
|
let item = self.mk_item(span, Ident::invalid(), item_, vis, attrs);
|
||||||
self.mk_item(span, Ident::invalid(), item_, visibility, attrs);
|
|
||||||
return Ok(Some(item));
|
return Ok(Some(item));
|
||||||
}
|
}
|
||||||
|
|
||||||
if self.eat_keyword(kw::Extern) {
|
if self.eat_keyword(kw::Extern) {
|
||||||
let extern_sp = self.prev_span;
|
let extern_sp = self.prev_span;
|
||||||
if self.eat_keyword(kw::Crate) {
|
if self.eat_keyword(kw::Crate) {
|
||||||
return Ok(Some(self.parse_item_extern_crate(lo, visibility, attrs)?));
|
return Ok(Some(self.parse_item_extern_crate(lo, vis, attrs)?));
|
||||||
}
|
}
|
||||||
|
|
||||||
let opt_abi = self.parse_opt_abi()?;
|
let opt_abi = self.parse_opt_abi()?;
|
||||||
|
@ -128,10 +127,10 @@ impl<'a> Parser<'a> {
|
||||||
constness: respan(fn_span, Constness::NotConst),
|
constness: respan(fn_span, Constness::NotConst),
|
||||||
abi: opt_abi.unwrap_or(Abi::C),
|
abi: opt_abi.unwrap_or(Abi::C),
|
||||||
};
|
};
|
||||||
return self.parse_item_fn(lo, visibility, attrs, header);
|
return self.parse_item_fn(lo, vis, attrs, header);
|
||||||
} else if self.check(&token::OpenDelim(token::Brace)) {
|
} else if self.check(&token::OpenDelim(token::Brace)) {
|
||||||
return Ok(Some(
|
return Ok(Some(
|
||||||
self.parse_item_foreign_mod(lo, opt_abi, visibility, attrs, extern_sp)?,
|
self.parse_item_foreign_mod(lo, opt_abi, vis, attrs, extern_sp)?,
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -142,16 +141,14 @@ impl<'a> Parser<'a> {
|
||||||
self.bump();
|
self.bump();
|
||||||
// STATIC ITEM
|
// STATIC ITEM
|
||||||
let m = self.parse_mutability();
|
let m = self.parse_mutability();
|
||||||
let (ident, item_, extra_attrs) = self.parse_item_const(Some(m))?;
|
let info = self.parse_item_const(Some(m))?;
|
||||||
let span = lo.to(self.prev_span);
|
return self.mk_item_with_info(attrs, lo, vis, info);
|
||||||
let attrs = maybe_append(attrs, extra_attrs);
|
|
||||||
return Ok(Some(self.mk_item(span, ident, item_, visibility, attrs)));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if self.eat_keyword(kw::Const) {
|
if self.eat_keyword(kw::Const) {
|
||||||
let const_span = self.prev_span;
|
let const_span = self.prev_span;
|
||||||
if [kw::Fn, kw::Unsafe, kw::Extern].iter().any(|k| self.check_keyword(*k)) {
|
if [kw::Fn, kw::Unsafe, kw::Extern].iter().any(|k| self.check_keyword(*k)) {
|
||||||
// CONST FUNCTION ITEM
|
// CONST FUNCTION ITEM
|
||||||
|
|
||||||
let unsafety = self.parse_unsafety();
|
let unsafety = self.parse_unsafety();
|
||||||
|
|
||||||
if self.check_keyword(kw::Extern) {
|
if self.check_keyword(kw::Extern) {
|
||||||
|
@ -160,7 +157,7 @@ impl<'a> Parser<'a> {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
let abi = self.parse_extern_abi()?;
|
let abi = self.parse_extern_abi()?;
|
||||||
self.bump(); // 'fn'
|
self.bump(); // `fn`
|
||||||
|
|
||||||
let header = FnHeader {
|
let header = FnHeader {
|
||||||
unsafety,
|
unsafety,
|
||||||
|
@ -168,7 +165,7 @@ impl<'a> Parser<'a> {
|
||||||
constness: respan(const_span, Constness::Const),
|
constness: respan(const_span, Constness::Const),
|
||||||
abi,
|
abi,
|
||||||
};
|
};
|
||||||
return self.parse_item_fn(lo, visibility, attrs, header);
|
return self.parse_item_fn(lo, vis, attrs, header);
|
||||||
}
|
}
|
||||||
|
|
||||||
// CONST ITEM
|
// CONST ITEM
|
||||||
|
@ -184,10 +181,9 @@ impl<'a> Parser<'a> {
|
||||||
)
|
)
|
||||||
.emit();
|
.emit();
|
||||||
}
|
}
|
||||||
let (ident, item_, extra_attrs) = self.parse_item_const(None)?;
|
|
||||||
let span = lo.to(self.prev_span);
|
let info = self.parse_item_const(None)?;
|
||||||
let attrs = maybe_append(attrs, extra_attrs);
|
return self.mk_item_with_info(attrs, lo, vis, info);
|
||||||
return Ok(Some(self.mk_item(span, ident, item_, visibility, attrs)));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Parses `async unsafe? fn`.
|
// Parses `async unsafe? fn`.
|
||||||
|
@ -212,40 +208,33 @@ impl<'a> Parser<'a> {
|
||||||
constness: respan(fn_span, Constness::NotConst),
|
constness: respan(fn_span, Constness::NotConst),
|
||||||
abi: Abi::Rust,
|
abi: Abi::Rust,
|
||||||
};
|
};
|
||||||
return self.parse_item_fn(lo, visibility, attrs, header);
|
return self.parse_item_fn(lo, vis, attrs, header);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if self.check_keyword(kw::Unsafe) &&
|
if self.check_keyword(kw::Unsafe) &&
|
||||||
self.is_keyword_ahead(1, &[kw::Trait, kw::Auto])
|
self.is_keyword_ahead(1, &[kw::Trait, kw::Auto])
|
||||||
{
|
{
|
||||||
// UNSAFE TRAIT ITEM
|
// UNSAFE TRAIT ITEM
|
||||||
self.bump(); // `unsafe`
|
self.bump(); // `unsafe`
|
||||||
let is_auto = if self.eat_keyword(kw::Trait) {
|
let info = self.parse_item_trait(Unsafety::Unsafe)?;
|
||||||
IsAuto::No
|
return self.mk_item_with_info(attrs, lo, vis, info);
|
||||||
} else {
|
|
||||||
self.expect_keyword(kw::Auto)?;
|
|
||||||
self.expect_keyword(kw::Trait)?;
|
|
||||||
IsAuto::Yes
|
|
||||||
};
|
|
||||||
let (ident, item_, extra_attrs) = self.parse_item_trait(is_auto, Unsafety::Unsafe)?;
|
|
||||||
let span = lo.to(self.prev_span);
|
|
||||||
let attrs = maybe_append(attrs, extra_attrs);
|
|
||||||
return Ok(Some(self.mk_item(span, ident, item_, visibility, attrs)));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if self.check_keyword(kw::Impl) ||
|
if self.check_keyword(kw::Impl) ||
|
||||||
self.check_keyword(kw::Unsafe) &&
|
self.check_keyword(kw::Unsafe) &&
|
||||||
self.is_keyword_ahead(1, &[kw::Impl]) ||
|
self.is_keyword_ahead(1, &[kw::Impl]) ||
|
||||||
self.check_keyword(kw::Default) &&
|
self.check_keyword(kw::Default) &&
|
||||||
self.is_keyword_ahead(1, &[kw::Impl, kw::Unsafe]) {
|
self.is_keyword_ahead(1, &[kw::Impl, kw::Unsafe])
|
||||||
|
{
|
||||||
// IMPL ITEM
|
// IMPL ITEM
|
||||||
let defaultness = self.parse_defaultness();
|
let defaultness = self.parse_defaultness();
|
||||||
let unsafety = self.parse_unsafety();
|
let unsafety = self.parse_unsafety();
|
||||||
self.expect_keyword(kw::Impl)?;
|
self.expect_keyword(kw::Impl)?;
|
||||||
let (ident, item_, extra_attrs) = self.parse_item_impl(unsafety, defaultness)?;
|
let info = self.parse_item_impl(unsafety, defaultness)?;
|
||||||
let span = lo.to(self.prev_span);
|
return self.mk_item_with_info(attrs, lo, vis, info);
|
||||||
let attrs = maybe_append(attrs, extra_attrs);
|
|
||||||
return Ok(Some(self.mk_item(span, ident, item_, visibility, attrs)));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if self.check_keyword(kw::Fn) {
|
if self.check_keyword(kw::Fn) {
|
||||||
// FUNCTION ITEM
|
// FUNCTION ITEM
|
||||||
self.bump();
|
self.bump();
|
||||||
|
@ -256,10 +245,12 @@ impl<'a> Parser<'a> {
|
||||||
constness: respan(fn_span, Constness::NotConst),
|
constness: respan(fn_span, Constness::NotConst),
|
||||||
abi: Abi::Rust,
|
abi: Abi::Rust,
|
||||||
};
|
};
|
||||||
return self.parse_item_fn(lo, visibility, attrs, header);
|
return self.parse_item_fn(lo, vis, attrs, header);
|
||||||
}
|
}
|
||||||
|
|
||||||
if self.check_keyword(kw::Unsafe)
|
if self.check_keyword(kw::Unsafe)
|
||||||
&& self.look_ahead(1, |t| *t != token::OpenDelim(token::Brace)) {
|
&& self.look_ahead(1, |t| *t != token::OpenDelim(token::Brace))
|
||||||
|
{
|
||||||
// UNSAFE FUNCTION ITEM
|
// UNSAFE FUNCTION ITEM
|
||||||
self.bump(); // `unsafe`
|
self.bump(); // `unsafe`
|
||||||
// `{` is also expected after `unsafe`; in case of error, include it in the diagnostic.
|
// `{` is also expected after `unsafe`; in case of error, include it in the diagnostic.
|
||||||
|
@ -273,15 +264,15 @@ impl<'a> Parser<'a> {
|
||||||
constness: respan(fn_span, Constness::NotConst),
|
constness: respan(fn_span, Constness::NotConst),
|
||||||
abi,
|
abi,
|
||||||
};
|
};
|
||||||
return self.parse_item_fn(lo, visibility, attrs, header);
|
return self.parse_item_fn(lo, vis, attrs, header);
|
||||||
}
|
}
|
||||||
|
|
||||||
if self.eat_keyword(kw::Mod) {
|
if self.eat_keyword(kw::Mod) {
|
||||||
// MODULE ITEM
|
// MODULE ITEM
|
||||||
let (ident, item_, extra_attrs) = self.parse_item_mod(&attrs[..])?;
|
let info = self.parse_item_mod(&attrs[..])?;
|
||||||
let span = lo.to(self.prev_span);
|
return self.mk_item_with_info(attrs, lo, vis, info);
|
||||||
let attrs = maybe_append(attrs, extra_attrs);
|
|
||||||
return Ok(Some(self.mk_item(span, ident, item_, visibility, attrs)));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(type_) = self.eat_type() {
|
if let Some(type_) = self.eat_type() {
|
||||||
let (ident, alias, generics) = type_?;
|
let (ident, alias, generics) = type_?;
|
||||||
// TYPE ITEM
|
// TYPE ITEM
|
||||||
|
@ -290,54 +281,44 @@ impl<'a> Parser<'a> {
|
||||||
AliasKind::OpaqueTy(bounds) => ItemKind::OpaqueTy(bounds, generics),
|
AliasKind::OpaqueTy(bounds) => ItemKind::OpaqueTy(bounds, generics),
|
||||||
};
|
};
|
||||||
let span = lo.to(self.prev_span);
|
let span = lo.to(self.prev_span);
|
||||||
return Ok(Some(self.mk_item(span, ident, item_, visibility, attrs)));
|
return Ok(Some(self.mk_item(span, ident, item_, vis, attrs)));
|
||||||
}
|
}
|
||||||
|
|
||||||
if self.eat_keyword(kw::Enum) {
|
if self.eat_keyword(kw::Enum) {
|
||||||
// ENUM ITEM
|
// ENUM ITEM
|
||||||
let (ident, item_, extra_attrs) = self.parse_item_enum()?;
|
let info = self.parse_item_enum()?;
|
||||||
let span = lo.to(self.prev_span);
|
return self.mk_item_with_info(attrs, lo, vis, info);
|
||||||
let attrs = maybe_append(attrs, extra_attrs);
|
|
||||||
return Ok(Some(self.mk_item(span, ident, item_, visibility, attrs)));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if self.check_keyword(kw::Trait)
|
if self.check_keyword(kw::Trait)
|
||||||
|| (self.check_keyword(kw::Auto)
|
|| (self.check_keyword(kw::Auto)
|
||||||
&& self.is_keyword_ahead(1, &[kw::Trait]))
|
&& self.is_keyword_ahead(1, &[kw::Trait]))
|
||||||
{
|
{
|
||||||
let is_auto = if self.eat_keyword(kw::Trait) {
|
|
||||||
IsAuto::No
|
|
||||||
} else {
|
|
||||||
self.expect_keyword(kw::Auto)?;
|
|
||||||
self.expect_keyword(kw::Trait)?;
|
|
||||||
IsAuto::Yes
|
|
||||||
};
|
|
||||||
// TRAIT ITEM
|
// TRAIT ITEM
|
||||||
let (ident, item_, extra_attrs) = self.parse_item_trait(is_auto, Unsafety::Normal)?;
|
let info = self.parse_item_trait(Unsafety::Normal)?;
|
||||||
let span = lo.to(self.prev_span);
|
return self.mk_item_with_info(attrs, lo, vis, info);
|
||||||
let attrs = maybe_append(attrs, extra_attrs);
|
|
||||||
return Ok(Some(self.mk_item(span, ident, item_, visibility, attrs)));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if self.eat_keyword(kw::Struct) {
|
if self.eat_keyword(kw::Struct) {
|
||||||
// STRUCT ITEM
|
// STRUCT ITEM
|
||||||
let (ident, item_, extra_attrs) = self.parse_item_struct()?;
|
let info = self.parse_item_struct()?;
|
||||||
let span = lo.to(self.prev_span);
|
return self.mk_item_with_info(attrs, lo, vis, info);
|
||||||
let attrs = maybe_append(attrs, extra_attrs);
|
|
||||||
return Ok(Some(self.mk_item(span, ident, item_, visibility, attrs)));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if self.is_union_item() {
|
if self.is_union_item() {
|
||||||
// UNION ITEM
|
// UNION ITEM
|
||||||
self.bump();
|
self.bump();
|
||||||
let (ident, item_, extra_attrs) = self.parse_item_union()?;
|
let info = self.parse_item_union()?;
|
||||||
let span = lo.to(self.prev_span);
|
return self.mk_item_with_info(attrs, lo, vis, info);
|
||||||
let attrs = maybe_append(attrs, extra_attrs);
|
|
||||||
return Ok(Some(self.mk_item(span, ident, item_, visibility, attrs)));
|
|
||||||
}
|
}
|
||||||
if let Some(macro_def) = self.eat_macro_def(&attrs, &visibility, lo)? {
|
|
||||||
|
if let Some(macro_def) = self.eat_macro_def(&attrs, &vis, lo)? {
|
||||||
return Ok(Some(macro_def));
|
return Ok(Some(macro_def));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Verify whether we have encountered a struct or method definition where the user forgot to
|
// Verify whether we have encountered a struct or method definition where the user forgot to
|
||||||
// add the `struct` or `fn` keyword after writing `pub`: `pub S {}`
|
// add the `struct` or `fn` keyword after writing `pub`: `pub S {}`
|
||||||
if visibility.node.is_pub() &&
|
if vis.node.is_pub() &&
|
||||||
self.check_ident() &&
|
self.check_ident() &&
|
||||||
self.look_ahead(1, |t| *t != token::Not)
|
self.look_ahead(1, |t| *t != token::Not)
|
||||||
{
|
{
|
||||||
|
@ -428,7 +409,20 @@ impl<'a> Parser<'a> {
|
||||||
return Err(err);
|
return Err(err);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
self.parse_macro_use_or_failure(attrs, macros_allowed, attributes_allowed, lo, visibility)
|
self.parse_macro_use_or_failure(attrs, macros_allowed, attributes_allowed, lo, vis)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn mk_item_with_info(
|
||||||
|
&self,
|
||||||
|
attrs: Vec<Attribute>,
|
||||||
|
lo: Span,
|
||||||
|
vis: Visibility,
|
||||||
|
info: ItemInfo,
|
||||||
|
) -> PResult<'a, Option<P<Item>>> {
|
||||||
|
let (ident, item, extra_attrs) = info;
|
||||||
|
let span = lo.to(self.prev_span);
|
||||||
|
let attrs = maybe_append(attrs, extra_attrs);
|
||||||
|
Ok(Some(self.mk_item(span, ident, item, vis, attrs)))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn recover_first_param(&mut self) -> &'static str {
|
fn recover_first_param(&mut self) -> &'static str {
|
||||||
|
@ -727,16 +721,7 @@ impl<'a> Parser<'a> {
|
||||||
};
|
};
|
||||||
(name, kind, generics)
|
(name, kind, generics)
|
||||||
} else if self.is_const_item() {
|
} else if self.is_const_item() {
|
||||||
// This parses the grammar:
|
self.parse_impl_const()?
|
||||||
// ImplItemConst = "const" Ident ":" Ty "=" Expr ";"
|
|
||||||
self.expect_keyword(kw::Const)?;
|
|
||||||
let name = self.parse_ident()?;
|
|
||||||
self.expect(&token::Colon)?;
|
|
||||||
let typ = self.parse_ty()?;
|
|
||||||
self.expect(&token::Eq)?;
|
|
||||||
let expr = self.parse_expr()?;
|
|
||||||
self.expect(&token::Semi)?;
|
|
||||||
(name, ast::ImplItemKind::Const(typ, expr), Generics::default())
|
|
||||||
} else {
|
} else {
|
||||||
let (name, inner_attrs, generics, kind) = self.parse_impl_method(&vis, at_end)?;
|
let (name, inner_attrs, generics, kind) = self.parse_impl_method(&vis, at_end)?;
|
||||||
attrs.extend(inner_attrs);
|
attrs.extend(inner_attrs);
|
||||||
|
@ -785,12 +770,25 @@ impl<'a> Parser<'a> {
|
||||||
!self.is_keyword_ahead(1, &[kw::Fn, kw::Unsafe])
|
!self.is_keyword_ahead(1, &[kw::Fn, kw::Unsafe])
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// This parses the grammar:
|
||||||
|
/// ImplItemConst = "const" Ident ":" Ty "=" Expr ";"
|
||||||
|
fn parse_impl_const(&mut self) -> PResult<'a, (Ident, ImplItemKind, Generics)> {
|
||||||
|
self.expect_keyword(kw::Const)?;
|
||||||
|
let name = self.parse_ident()?;
|
||||||
|
self.expect(&token::Colon)?;
|
||||||
|
let typ = self.parse_ty()?;
|
||||||
|
self.expect(&token::Eq)?;
|
||||||
|
let expr = self.parse_expr()?;
|
||||||
|
self.expect(&token::Semi)?;
|
||||||
|
Ok((name, ImplItemKind::Const(typ, expr), Generics::default()))
|
||||||
|
}
|
||||||
|
|
||||||
/// Parses a method or a macro invocation in a trait impl.
|
/// Parses a method or a macro invocation in a trait impl.
|
||||||
fn parse_impl_method(
|
fn parse_impl_method(
|
||||||
&mut self,
|
&mut self,
|
||||||
vis: &Visibility,
|
vis: &Visibility,
|
||||||
at_end: &mut bool
|
at_end: &mut bool
|
||||||
) -> PResult<'a, (Ident, Vec<Attribute>, Generics, ast::ImplItemKind)> {
|
) -> PResult<'a, (Ident, Vec<Attribute>, Generics, ImplItemKind)> {
|
||||||
// FIXME: code copied from `parse_macro_use_or_failure` -- use abstraction!
|
// FIXME: code copied from `parse_macro_use_or_failure` -- use abstraction!
|
||||||
if let Some(mac) = self.parse_assoc_macro_invoc("impl", Some(vis), at_end)? {
|
if let Some(mac) = self.parse_assoc_macro_invoc("impl", Some(vis), at_end)? {
|
||||||
// method macro
|
// method macro
|
||||||
|
@ -807,14 +805,15 @@ impl<'a> Parser<'a> {
|
||||||
/// of a method. The body is not parsed as that differs between `trait`s and `impl`s.
|
/// of a method. The body is not parsed as that differs between `trait`s and `impl`s.
|
||||||
fn parse_method_sig(
|
fn parse_method_sig(
|
||||||
&mut self,
|
&mut self,
|
||||||
is_name_required: impl Copy + Fn(&token::Token) -> bool,
|
is_name_required: fn(&token::Token) -> bool,
|
||||||
) -> PResult<'a, (Ident, MethodSig, Generics)> {
|
) -> PResult<'a, (Ident, MethodSig, Generics)> {
|
||||||
let header = self.parse_fn_front_matter()?;
|
let header = self.parse_fn_front_matter()?;
|
||||||
let (ident, mut generics) = self.parse_fn_header()?;
|
let (ident, decl, generics) = self.parse_fn_sig(ParamCfg {
|
||||||
let decl = self.parse_fn_decl_with_self(is_name_required)?;
|
is_self_allowed: true,
|
||||||
let sig = MethodSig { header, decl };
|
allow_c_variadic: false,
|
||||||
generics.where_clause = self.parse_where_clause()?;
|
is_name_required,
|
||||||
Ok((ident, sig, generics))
|
})?;
|
||||||
|
Ok((ident, MethodSig { header, decl }, generics))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Parses all the "front matter" for a `fn` declaration, up to
|
/// Parses all the "front matter" for a `fn` declaration, up to
|
||||||
|
@ -849,8 +848,16 @@ impl<'a> Parser<'a> {
|
||||||
Ok(FnHeader { constness, unsafety, asyncness, abi })
|
Ok(FnHeader { constness, unsafety, asyncness, abi })
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Parses `trait Foo { ... }` or `trait Foo = Bar;`.
|
/// Parses `auto? trait Foo { ... }` or `trait Foo = Bar;`.
|
||||||
fn parse_item_trait(&mut self, is_auto: IsAuto, unsafety: Unsafety) -> PResult<'a, ItemInfo> {
|
fn parse_item_trait(&mut self, unsafety: Unsafety) -> PResult<'a, ItemInfo> {
|
||||||
|
// Parse optional `auto` prefix.
|
||||||
|
let is_auto = if self.eat_keyword(kw::Auto) {
|
||||||
|
IsAuto::Yes
|
||||||
|
} else {
|
||||||
|
IsAuto::No
|
||||||
|
};
|
||||||
|
|
||||||
|
self.expect_keyword(kw::Trait)?;
|
||||||
let ident = self.parse_ident()?;
|
let ident = self.parse_ident()?;
|
||||||
let mut tps = self.parse_generics()?;
|
let mut tps = self.parse_generics()?;
|
||||||
|
|
||||||
|
@ -935,30 +942,20 @@ impl<'a> Parser<'a> {
|
||||||
Ok(item)
|
Ok(item)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parse_trait_item_(&mut self,
|
fn parse_trait_item_(
|
||||||
at_end: &mut bool,
|
&mut self,
|
||||||
mut attrs: Vec<Attribute>) -> PResult<'a, TraitItem> {
|
at_end: &mut bool,
|
||||||
|
mut attrs: Vec<Attribute>,
|
||||||
|
) -> PResult<'a, TraitItem> {
|
||||||
let lo = self.token.span;
|
let lo = self.token.span;
|
||||||
self.eat_bad_pub();
|
self.eat_bad_pub();
|
||||||
let (name, kind, generics) = if self.eat_keyword(kw::Type) {
|
let (name, kind, generics) = if self.eat_keyword(kw::Type) {
|
||||||
self.parse_trait_item_assoc_ty()?
|
self.parse_trait_item_assoc_ty()?
|
||||||
} else if self.is_const_item() {
|
} else if self.is_const_item() {
|
||||||
self.expect_keyword(kw::Const)?;
|
self.parse_trait_item_const()?
|
||||||
let ident = self.parse_ident()?;
|
|
||||||
self.expect(&token::Colon)?;
|
|
||||||
let ty = self.parse_ty()?;
|
|
||||||
let default = if self.eat(&token::Eq) {
|
|
||||||
let expr = self.parse_expr()?;
|
|
||||||
self.expect(&token::Semi)?;
|
|
||||||
Some(expr)
|
|
||||||
} else {
|
|
||||||
self.expect(&token::Semi)?;
|
|
||||||
None
|
|
||||||
};
|
|
||||||
(ident, TraitItemKind::Const(ty, default), Generics::default())
|
|
||||||
} else if let Some(mac) = self.parse_assoc_macro_invoc("trait", None, &mut false)? {
|
} else if let Some(mac) = self.parse_assoc_macro_invoc("trait", None, &mut false)? {
|
||||||
// trait item macro.
|
// trait item macro.
|
||||||
(Ident::invalid(), ast::TraitItemKind::Macro(mac), Generics::default())
|
(Ident::invalid(), TraitItemKind::Macro(mac), Generics::default())
|
||||||
} else {
|
} else {
|
||||||
// This is somewhat dubious; We don't want to allow
|
// This is somewhat dubious; We don't want to allow
|
||||||
// argument names to be left off if there is a definition...
|
// argument names to be left off if there is a definition...
|
||||||
|
@ -966,7 +963,7 @@ impl<'a> Parser<'a> {
|
||||||
// We don't allow argument names to be left off in edition 2018.
|
// We don't allow argument names to be left off in edition 2018.
|
||||||
let (ident, sig, generics) = self.parse_method_sig(|t| t.span.rust_2018())?;
|
let (ident, sig, generics) = self.parse_method_sig(|t| t.span.rust_2018())?;
|
||||||
let body = self.parse_trait_method_body(at_end, &mut attrs)?;
|
let body = self.parse_trait_method_body(at_end, &mut attrs)?;
|
||||||
(ident, ast::TraitItemKind::Method(sig, body), generics)
|
(ident, TraitItemKind::Method(sig, body), generics)
|
||||||
};
|
};
|
||||||
|
|
||||||
Ok(TraitItem {
|
Ok(TraitItem {
|
||||||
|
@ -980,6 +977,20 @@ impl<'a> Parser<'a> {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn parse_trait_item_const(&mut self) -> PResult<'a, (Ident, TraitItemKind, Generics)> {
|
||||||
|
self.expect_keyword(kw::Const)?;
|
||||||
|
let ident = self.parse_ident()?;
|
||||||
|
self.expect(&token::Colon)?;
|
||||||
|
let ty = self.parse_ty()?;
|
||||||
|
let default = if self.eat(&token::Eq) {
|
||||||
|
Some(self.parse_expr()?)
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
};
|
||||||
|
self.expect(&token::Semi)?;
|
||||||
|
Ok((ident, TraitItemKind::Const(ty, default), Generics::default()))
|
||||||
|
}
|
||||||
|
|
||||||
/// Parse the "body" of a method in a trait item definition.
|
/// Parse the "body" of a method in a trait item definition.
|
||||||
/// This can either be `;` when there's no body,
|
/// This can either be `;` when there's no body,
|
||||||
/// or e.g. a block when the method is a provided one.
|
/// or e.g. a block when the method is a provided one.
|
||||||
|
@ -1020,8 +1031,7 @@ impl<'a> Parser<'a> {
|
||||||
/// Parses the following grammar:
|
/// Parses the following grammar:
|
||||||
///
|
///
|
||||||
/// TraitItemAssocTy = Ident ["<"...">"] [":" [GenericBounds]] ["where" ...] ["=" Ty]
|
/// TraitItemAssocTy = Ident ["<"...">"] [":" [GenericBounds]] ["where" ...] ["=" Ty]
|
||||||
fn parse_trait_item_assoc_ty(&mut self)
|
fn parse_trait_item_assoc_ty(&mut self) -> PResult<'a, (Ident, TraitItemKind, Generics)> {
|
||||||
-> PResult<'a, (Ident, TraitItemKind, Generics)> {
|
|
||||||
let ident = self.parse_ident()?;
|
let ident = self.parse_ident()?;
|
||||||
let mut generics = self.parse_generics()?;
|
let mut generics = self.parse_generics()?;
|
||||||
|
|
||||||
|
@ -1067,21 +1077,13 @@ impl<'a> Parser<'a> {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
if self.eat(&token::BinOp(token::Star)) {
|
self.parse_use_tree_glob_or_nested()?
|
||||||
UseTreeKind::Glob
|
|
||||||
} else {
|
|
||||||
UseTreeKind::Nested(self.parse_use_tree_list()?)
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
// `use path::*;` or `use path::{...};` or `use path;` or `use path as bar;`
|
// `use path::*;` or `use path::{...};` or `use path;` or `use path as bar;`
|
||||||
prefix = self.parse_path(PathStyle::Mod)?;
|
prefix = self.parse_path(PathStyle::Mod)?;
|
||||||
|
|
||||||
if self.eat(&token::ModSep) {
|
if self.eat(&token::ModSep) {
|
||||||
if self.eat(&token::BinOp(token::Star)) {
|
self.parse_use_tree_glob_or_nested()?
|
||||||
UseTreeKind::Glob
|
|
||||||
} else {
|
|
||||||
UseTreeKind::Nested(self.parse_use_tree_list()?)
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
UseTreeKind::Simple(self.parse_rename()?, DUMMY_NODE_ID, DUMMY_NODE_ID)
|
UseTreeKind::Simple(self.parse_rename()?, DUMMY_NODE_ID, DUMMY_NODE_ID)
|
||||||
}
|
}
|
||||||
|
@ -1090,6 +1092,15 @@ impl<'a> Parser<'a> {
|
||||||
Ok(UseTree { prefix, kind, span: lo.to(self.prev_span) })
|
Ok(UseTree { prefix, kind, span: lo.to(self.prev_span) })
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Parses `*` or `{...}`.
|
||||||
|
fn parse_use_tree_glob_or_nested(&mut self) -> PResult<'a, UseTreeKind> {
|
||||||
|
Ok(if self.eat(&token::BinOp(token::Star)) {
|
||||||
|
UseTreeKind::Glob
|
||||||
|
} else {
|
||||||
|
UseTreeKind::Nested(self.parse_use_tree_list()?)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
/// Parses a `UseTreeKind::Nested(list)`.
|
/// Parses a `UseTreeKind::Nested(list)`.
|
||||||
///
|
///
|
||||||
/// ```
|
/// ```
|
||||||
|
@ -1191,38 +1202,34 @@ impl<'a> Parser<'a> {
|
||||||
attrs: Vec<Attribute>,
|
attrs: Vec<Attribute>,
|
||||||
header: FnHeader,
|
header: FnHeader,
|
||||||
) -> PResult<'a, Option<P<Item>>> {
|
) -> PResult<'a, Option<P<Item>>> {
|
||||||
let allow_c_variadic = header.abi == Abi::C && header.unsafety == Unsafety::Unsafe;
|
let (ident, decl, generics) = self.parse_fn_sig(ParamCfg {
|
||||||
let (ident, decl, generics) = self.parse_fn_sig(allow_c_variadic)?;
|
is_self_allowed: false,
|
||||||
|
allow_c_variadic: header.abi == Abi::C && header.unsafety == Unsafety::Unsafe,
|
||||||
|
is_name_required: |_| true,
|
||||||
|
})?;
|
||||||
let (inner_attrs, body) = self.parse_inner_attrs_and_block()?;
|
let (inner_attrs, body) = self.parse_inner_attrs_and_block()?;
|
||||||
let span = lo.to(self.prev_span);
|
|
||||||
let kind = ItemKind::Fn(decl, header, generics, body);
|
let kind = ItemKind::Fn(decl, header, generics, body);
|
||||||
let attrs = maybe_append(attrs, Some(inner_attrs));
|
self.mk_item_with_info(attrs, lo, vis, (ident, kind, Some(inner_attrs)))
|
||||||
Ok(Some(self.mk_item(span, ident, kind, vis, attrs)))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Parse the "signature", including the identifier, parameters, and generics of a function.
|
/// Parse the "signature", including the identifier, parameters, and generics of a function.
|
||||||
fn parse_fn_sig(
|
fn parse_fn_sig(&mut self, cfg: ParamCfg) -> PResult<'a, (Ident, P<FnDecl>, Generics)> {
|
||||||
&mut self,
|
let ident = self.parse_ident()?;
|
||||||
allow_c_variadic: bool,
|
let mut generics = self.parse_generics()?;
|
||||||
) -> PResult<'a, (Ident, P<FnDecl>, Generics)> {
|
let decl = self.parse_fn_decl(cfg, true)?;
|
||||||
let (ident, mut generics) = self.parse_fn_header()?;
|
|
||||||
let decl = self.parse_fn_decl(allow_c_variadic)?;
|
|
||||||
generics.where_clause = self.parse_where_clause()?;
|
generics.where_clause = self.parse_where_clause()?;
|
||||||
Ok((ident, decl, generics))
|
Ok((ident, decl, generics))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Parses the name and optional generic types of a function header.
|
|
||||||
fn parse_fn_header(&mut self) -> PResult<'a, (Ident, Generics)> {
|
|
||||||
let id = self.parse_ident()?;
|
|
||||||
let generics = self.parse_generics()?;
|
|
||||||
Ok((id, generics))
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Parses the parameter list and result type of a function declaration.
|
/// Parses the parameter list and result type of a function declaration.
|
||||||
fn parse_fn_decl(&mut self, allow_c_variadic: bool) -> PResult<'a, P<FnDecl>> {
|
pub(super) fn parse_fn_decl(
|
||||||
|
&mut self,
|
||||||
|
cfg: ParamCfg,
|
||||||
|
ret_allow_plus: bool,
|
||||||
|
) -> PResult<'a, P<FnDecl>> {
|
||||||
Ok(P(FnDecl {
|
Ok(P(FnDecl {
|
||||||
inputs: self.parse_fn_params(true, allow_c_variadic)?,
|
inputs: self.parse_fn_params(cfg)?,
|
||||||
output: self.parse_ret_ty(true)?,
|
output: self.parse_ret_ty(ret_allow_plus)?,
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1346,7 +1353,11 @@ impl<'a> Parser<'a> {
|
||||||
extern_sp: Span,
|
extern_sp: Span,
|
||||||
) -> PResult<'a, ForeignItem> {
|
) -> PResult<'a, ForeignItem> {
|
||||||
self.expect_keyword(kw::Fn)?;
|
self.expect_keyword(kw::Fn)?;
|
||||||
let (ident, decl, generics) = self.parse_fn_sig(true)?;
|
let (ident, decl, generics) = self.parse_fn_sig(super::ParamCfg {
|
||||||
|
is_self_allowed: false,
|
||||||
|
allow_c_variadic: true,
|
||||||
|
is_name_required: |_| true,
|
||||||
|
})?;
|
||||||
let span = lo.to(self.token.span);
|
let span = lo.to(self.token.span);
|
||||||
self.parse_semi_or_incorrect_foreign_fn_body(&ident, extern_sp)?;
|
self.parse_semi_or_incorrect_foreign_fn_body(&ident, extern_sp)?;
|
||||||
Ok(ast::ForeignItem {
|
Ok(ast::ForeignItem {
|
||||||
|
|
|
@ -4,13 +4,11 @@ use crate::{maybe_whole, maybe_recover_from_interpolated_ty_qpath};
|
||||||
use crate::ptr::P;
|
use crate::ptr::P;
|
||||||
use crate::ast::{self, Ty, TyKind, MutTy, BareFnTy, FunctionRetTy, GenericParam, Lifetime, Ident};
|
use crate::ast::{self, Ty, TyKind, MutTy, BareFnTy, FunctionRetTy, GenericParam, Lifetime, Ident};
|
||||||
use crate::ast::{TraitBoundModifier, TraitObjectSyntax, GenericBound, GenericBounds, PolyTraitRef};
|
use crate::ast::{TraitBoundModifier, TraitObjectSyntax, GenericBound, GenericBounds, PolyTraitRef};
|
||||||
use crate::ast::{Mutability, AnonConst, FnDecl, Mac};
|
use crate::ast::{Mutability, AnonConst, Mac};
|
||||||
use crate::parse::token::{self, Token};
|
use crate::parse::token::{self, Token};
|
||||||
use crate::source_map::Span;
|
use crate::source_map::Span;
|
||||||
use crate::symbol::{kw};
|
use crate::symbol::{kw};
|
||||||
|
|
||||||
use rustc_target::spec::abi::Abi;
|
|
||||||
|
|
||||||
use errors::{Applicability, pluralise};
|
use errors::{Applicability, pluralise};
|
||||||
|
|
||||||
/// Returns `true` if `IDENT t` can start a type -- `IDENT::a::b`, `IDENT<u8, u8>`,
|
/// Returns `true` if `IDENT t` can start a type -- `IDENT::a::b`, `IDENT<u8, u8>`,
|
||||||
|
@ -281,19 +279,14 @@ impl<'a> Parser<'a> {
|
||||||
*/
|
*/
|
||||||
|
|
||||||
let unsafety = self.parse_unsafety();
|
let unsafety = self.parse_unsafety();
|
||||||
let abi = if self.eat_keyword(kw::Extern) {
|
let abi = self.parse_extern_abi()?;
|
||||||
self.parse_opt_abi()?.unwrap_or(Abi::C)
|
|
||||||
} else {
|
|
||||||
Abi::Rust
|
|
||||||
};
|
|
||||||
|
|
||||||
self.expect_keyword(kw::Fn)?;
|
self.expect_keyword(kw::Fn)?;
|
||||||
let inputs = self.parse_fn_params(false, true)?;
|
let cfg = super::ParamCfg {
|
||||||
let ret_ty = self.parse_ret_ty(false)?;
|
is_self_allowed: false,
|
||||||
let decl = P(FnDecl {
|
allow_c_variadic: true,
|
||||||
inputs,
|
is_name_required: |_| false,
|
||||||
output: ret_ty,
|
};
|
||||||
});
|
let decl = self.parse_fn_decl(cfg, false)?;
|
||||||
Ok(TyKind::BareFn(P(BareFnTy {
|
Ok(TyKind::BareFn(P(BareFnTy {
|
||||||
abi,
|
abi,
|
||||||
unsafety,
|
unsafety,
|
||||||
|
|
|
@ -12,8 +12,8 @@ error[E0308]: mismatched types
|
||||||
LL | let _: ConstString<"Hello"> = ConstString::<"World">;
|
LL | let _: ConstString<"Hello"> = ConstString::<"World">;
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^ expected `"Hello"`, found `"World"`
|
| ^^^^^^^^^^^^^^^^^^^^^^ expected `"Hello"`, found `"World"`
|
||||||
|
|
|
|
||||||
= note: expected type `ConstString<>`
|
= note: expected type `ConstString<"Hello">`
|
||||||
found type `ConstString<>`
|
found type `ConstString<"World">`
|
||||||
|
|
||||||
error[E0308]: mismatched types
|
error[E0308]: mismatched types
|
||||||
--> $DIR/slice-const-param-mismatch.rs:11:33
|
--> $DIR/slice-const-param-mismatch.rs:11:33
|
||||||
|
@ -21,8 +21,8 @@ error[E0308]: mismatched types
|
||||||
LL | let _: ConstString<"ℇ㇈↦"> = ConstString::<"ℇ㇈↥">;
|
LL | let _: ConstString<"ℇ㇈↦"> = ConstString::<"ℇ㇈↥">;
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^ expected `"ℇ㇈↦"`, found `"ℇ㇈↥"`
|
| ^^^^^^^^^^^^^^^^^^^^^ expected `"ℇ㇈↦"`, found `"ℇ㇈↥"`
|
||||||
|
|
|
|
||||||
= note: expected type `ConstString<>`
|
= note: expected type `ConstString<"ℇ㇈↦">`
|
||||||
found type `ConstString<>`
|
found type `ConstString<"ℇ㇈↥">`
|
||||||
|
|
||||||
error[E0308]: mismatched types
|
error[E0308]: mismatched types
|
||||||
--> $DIR/slice-const-param-mismatch.rs:13:33
|
--> $DIR/slice-const-param-mismatch.rs:13:33
|
||||||
|
@ -30,8 +30,8 @@ error[E0308]: mismatched types
|
||||||
LL | let _: ConstBytes<b"AAA"> = ConstBytes::<b"BBB">;
|
LL | let _: ConstBytes<b"AAA"> = ConstBytes::<b"BBB">;
|
||||||
| ^^^^^^^^^^^^^^^^^^^^ expected `b"AAA"`, found `b"BBB"`
|
| ^^^^^^^^^^^^^^^^^^^^ expected `b"AAA"`, found `b"BBB"`
|
||||||
|
|
|
|
||||||
= note: expected type `ConstBytes<>`
|
= note: expected type `ConstBytes<b"AAA">`
|
||||||
found type `ConstBytes<>`
|
found type `ConstBytes<b"BBB">`
|
||||||
|
|
||||||
error: aborting due to 3 previous errors
|
error: aborting due to 3 previous errors
|
||||||
|
|
||||||
|
|
19
src/test/ui/const-generics/types-mismatch-const-args.rs
Normal file
19
src/test/ui/const-generics/types-mismatch-const-args.rs
Normal file
|
@ -0,0 +1,19 @@
|
||||||
|
#![feature(const_generics)]
|
||||||
|
//~^ WARN the feature `const_generics` is incomplete and may cause the compiler to crash
|
||||||
|
|
||||||
|
// tests the diagnostic output of type mismatches for types that have const generics arguments.
|
||||||
|
|
||||||
|
use std::marker::PhantomData;
|
||||||
|
|
||||||
|
struct A<'a, T, const X: u32, const Y: u32> {
|
||||||
|
data: PhantomData<&'a T>
|
||||||
|
}
|
||||||
|
|
||||||
|
fn a<'a, 'b>() {
|
||||||
|
let _: A<'a, u32, {2u32}, {3u32}> = A::<'a, u32, {4u32}, {3u32}> { data: PhantomData };
|
||||||
|
//~^ ERROR mismatched types
|
||||||
|
let _: A<'a, u16, {2u32}, {3u32}> = A::<'b, u32, {2u32}, {3u32}> { data: PhantomData };
|
||||||
|
//~^ ERROR mismatched types
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn main() {}
|
29
src/test/ui/const-generics/types-mismatch-const-args.stderr
Normal file
29
src/test/ui/const-generics/types-mismatch-const-args.stderr
Normal file
|
@ -0,0 +1,29 @@
|
||||||
|
warning: the feature `const_generics` is incomplete and may cause the compiler to crash
|
||||||
|
--> $DIR/types-mismatch-const-args.rs:1:12
|
||||||
|
|
|
||||||
|
LL | #![feature(const_generics)]
|
||||||
|
| ^^^^^^^^^^^^^^
|
||||||
|
|
|
||||||
|
= note: `#[warn(incomplete_features)]` on by default
|
||||||
|
|
||||||
|
error[E0308]: mismatched types
|
||||||
|
--> $DIR/types-mismatch-const-args.rs:13:41
|
||||||
|
|
|
||||||
|
LL | let _: A<'a, u32, {2u32}, {3u32}> = A::<'a, u32, {4u32}, {3u32}> { data: PhantomData };
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `2u32`, found `4u32`
|
||||||
|
|
|
||||||
|
= note: expected type `A<'_, _, 2u32, _>`
|
||||||
|
found type `A<'_, _, 4u32, _>`
|
||||||
|
|
||||||
|
error[E0308]: mismatched types
|
||||||
|
--> $DIR/types-mismatch-const-args.rs:15:41
|
||||||
|
|
|
||||||
|
LL | let _: A<'a, u16, {2u32}, {3u32}> = A::<'b, u32, {2u32}, {3u32}> { data: PhantomData };
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected u16, found u32
|
||||||
|
|
|
||||||
|
= note: expected type `A<'a, u16, _, _>`
|
||||||
|
found type `A<'b, u32, _, _>`
|
||||||
|
|
||||||
|
error: aborting due to 2 previous errors
|
||||||
|
|
||||||
|
For more information about this error, try `rustc --explain E0308`.
|
|
@ -2,7 +2,10 @@ error[E0308]: mismatched types
|
||||||
--> $DIR/if-no-match-bindings.rs:18:8
|
--> $DIR/if-no-match-bindings.rs:18:8
|
||||||
|
|
|
|
||||||
LL | if b_ref() {}
|
LL | if b_ref() {}
|
||||||
| ^^^^^^^ expected bool, found &bool
|
| ^^^^^^^
|
||||||
|
| |
|
||||||
|
| expected bool, found &bool
|
||||||
|
| help: consider dereferencing the borrow: `*b_ref()`
|
||||||
|
|
|
|
||||||
= note: expected type `bool`
|
= note: expected type `bool`
|
||||||
found type `&bool`
|
found type `&bool`
|
||||||
|
@ -11,7 +14,10 @@ error[E0308]: mismatched types
|
||||||
--> $DIR/if-no-match-bindings.rs:19:8
|
--> $DIR/if-no-match-bindings.rs:19:8
|
||||||
|
|
|
|
||||||
LL | if b_mut_ref() {}
|
LL | if b_mut_ref() {}
|
||||||
| ^^^^^^^^^^^ expected bool, found &mut bool
|
| ^^^^^^^^^^^
|
||||||
|
| |
|
||||||
|
| expected bool, found &mut bool
|
||||||
|
| help: consider dereferencing the borrow: `*b_mut_ref()`
|
||||||
|
|
|
|
||||||
= note: expected type `bool`
|
= note: expected type `bool`
|
||||||
found type `&mut bool`
|
found type `&mut bool`
|
||||||
|
@ -20,7 +26,10 @@ error[E0308]: mismatched types
|
||||||
--> $DIR/if-no-match-bindings.rs:20:8
|
--> $DIR/if-no-match-bindings.rs:20:8
|
||||||
|
|
|
|
||||||
LL | if &true {}
|
LL | if &true {}
|
||||||
| ^^^^^ expected bool, found &bool
|
| ^^^^^
|
||||||
|
| |
|
||||||
|
| expected bool, found &bool
|
||||||
|
| help: consider dereferencing the borrow: `*&true`
|
||||||
|
|
|
|
||||||
= note: expected type `bool`
|
= note: expected type `bool`
|
||||||
found type `&bool`
|
found type `&bool`
|
||||||
|
@ -29,7 +38,10 @@ error[E0308]: mismatched types
|
||||||
--> $DIR/if-no-match-bindings.rs:21:8
|
--> $DIR/if-no-match-bindings.rs:21:8
|
||||||
|
|
|
|
||||||
LL | if &mut true {}
|
LL | if &mut true {}
|
||||||
| ^^^^^^^^^ expected bool, found &mut bool
|
| ^^^^^^^^^
|
||||||
|
| |
|
||||||
|
| expected bool, found &mut bool
|
||||||
|
| help: consider dereferencing the borrow: `*&mut true`
|
||||||
|
|
|
|
||||||
= note: expected type `bool`
|
= note: expected type `bool`
|
||||||
found type `&mut bool`
|
found type `&mut bool`
|
||||||
|
@ -38,7 +50,10 @@ error[E0308]: mismatched types
|
||||||
--> $DIR/if-no-match-bindings.rs:24:11
|
--> $DIR/if-no-match-bindings.rs:24:11
|
||||||
|
|
|
|
||||||
LL | while b_ref() {}
|
LL | while b_ref() {}
|
||||||
| ^^^^^^^ expected bool, found &bool
|
| ^^^^^^^
|
||||||
|
| |
|
||||||
|
| expected bool, found &bool
|
||||||
|
| help: consider dereferencing the borrow: `*b_ref()`
|
||||||
|
|
|
|
||||||
= note: expected type `bool`
|
= note: expected type `bool`
|
||||||
found type `&bool`
|
found type `&bool`
|
||||||
|
@ -47,7 +62,10 @@ error[E0308]: mismatched types
|
||||||
--> $DIR/if-no-match-bindings.rs:25:11
|
--> $DIR/if-no-match-bindings.rs:25:11
|
||||||
|
|
|
|
||||||
LL | while b_mut_ref() {}
|
LL | while b_mut_ref() {}
|
||||||
| ^^^^^^^^^^^ expected bool, found &mut bool
|
| ^^^^^^^^^^^
|
||||||
|
| |
|
||||||
|
| expected bool, found &mut bool
|
||||||
|
| help: consider dereferencing the borrow: `*b_mut_ref()`
|
||||||
|
|
|
|
||||||
= note: expected type `bool`
|
= note: expected type `bool`
|
||||||
found type `&mut bool`
|
found type `&mut bool`
|
||||||
|
@ -56,7 +74,10 @@ error[E0308]: mismatched types
|
||||||
--> $DIR/if-no-match-bindings.rs:26:11
|
--> $DIR/if-no-match-bindings.rs:26:11
|
||||||
|
|
|
|
||||||
LL | while &true {}
|
LL | while &true {}
|
||||||
| ^^^^^ expected bool, found &bool
|
| ^^^^^
|
||||||
|
| |
|
||||||
|
| expected bool, found &bool
|
||||||
|
| help: consider dereferencing the borrow: `*&true`
|
||||||
|
|
|
|
||||||
= note: expected type `bool`
|
= note: expected type `bool`
|
||||||
found type `&bool`
|
found type `&bool`
|
||||||
|
@ -65,7 +86,10 @@ error[E0308]: mismatched types
|
||||||
--> $DIR/if-no-match-bindings.rs:27:11
|
--> $DIR/if-no-match-bindings.rs:27:11
|
||||||
|
|
|
|
||||||
LL | while &mut true {}
|
LL | while &mut true {}
|
||||||
| ^^^^^^^^^ expected bool, found &mut bool
|
| ^^^^^^^^^
|
||||||
|
| |
|
||||||
|
| expected bool, found &mut bool
|
||||||
|
| help: consider dereferencing the borrow: `*&mut true`
|
||||||
|
|
|
|
||||||
= note: expected type `bool`
|
= note: expected type `bool`
|
||||||
found type `&mut bool`
|
found type `&mut bool`
|
||||||
|
|
|
@ -18,5 +18,5 @@ LL | m!((bad, pat));
|
||||||
|
|
||||||
error: aborting due to 3 previous errors
|
error: aborting due to 3 previous errors
|
||||||
|
|
||||||
Some errors have detailed explanations: E0130, E0642.
|
Some errors have detailed explanations: E0130, E0561, E0642.
|
||||||
For more information about an error, try `rustc --explain E0130`.
|
For more information about an error, try `rustc --explain E0130`.
|
||||||
|
|
|
@ -30,4 +30,5 @@ LL | type A2 = fn(&arg: u8);
|
||||||
|
|
||||||
error: aborting due to 5 previous errors
|
error: aborting due to 5 previous errors
|
||||||
|
|
||||||
For more information about this error, try `rustc --explain E0130`.
|
Some errors have detailed explanations: E0130, E0561.
|
||||||
|
For more information about an error, try `rustc --explain E0130`.
|
||||||
|
|
|
@ -3,6 +3,7 @@ struct S;
|
||||||
impl S {
|
impl S {
|
||||||
fn f(*, a: u8) -> u8 {}
|
fn f(*, a: u8) -> u8 {}
|
||||||
//~^ ERROR expected parameter name, found `*`
|
//~^ ERROR expected parameter name, found `*`
|
||||||
|
//~| ERROR mismatched types
|
||||||
}
|
}
|
||||||
|
|
||||||
fn main() {}
|
fn main() {}
|
||||||
|
|
|
@ -4,5 +4,17 @@ error: expected parameter name, found `*`
|
||||||
LL | fn f(*, a: u8) -> u8 {}
|
LL | fn f(*, a: u8) -> u8 {}
|
||||||
| ^ expected parameter name
|
| ^ expected parameter name
|
||||||
|
|
||||||
error: aborting due to previous error
|
error[E0308]: mismatched types
|
||||||
|
--> $DIR/issue-33413.rs:4:23
|
||||||
|
|
|
||||||
|
LL | fn f(*, a: u8) -> u8 {}
|
||||||
|
| - ^^ expected u8, found ()
|
||||||
|
| |
|
||||||
|
| implicitly returns `()` as its body has no tail or `return` expression
|
||||||
|
|
|
||||||
|
= note: expected type `u8`
|
||||||
|
found type `()`
|
||||||
|
|
||||||
|
error: aborting due to 2 previous errors
|
||||||
|
|
||||||
|
For more information about this error, try `rustc --explain E0308`.
|
||||||
|
|
|
@ -517,7 +517,10 @@ error[E0308]: mismatched types
|
||||||
--> $DIR/disallowed-positions.rs:32:8
|
--> $DIR/disallowed-positions.rs:32:8
|
||||||
|
|
|
|
||||||
LL | if &let 0 = 0 {}
|
LL | if &let 0 = 0 {}
|
||||||
| ^^^^^^^^^^ expected bool, found &bool
|
| ^^^^^^^^^^
|
||||||
|
| |
|
||||||
|
| expected bool, found &bool
|
||||||
|
| help: consider dereferencing the borrow: `*&let 0 = 0`
|
||||||
|
|
|
|
||||||
= note: expected type `bool`
|
= note: expected type `bool`
|
||||||
found type `&bool`
|
found type `&bool`
|
||||||
|
@ -702,7 +705,10 @@ error[E0308]: mismatched types
|
||||||
--> $DIR/disallowed-positions.rs:96:11
|
--> $DIR/disallowed-positions.rs:96:11
|
||||||
|
|
|
|
||||||
LL | while &let 0 = 0 {}
|
LL | while &let 0 = 0 {}
|
||||||
| ^^^^^^^^^^ expected bool, found &bool
|
| ^^^^^^^^^^
|
||||||
|
| |
|
||||||
|
| expected bool, found &bool
|
||||||
|
| help: consider dereferencing the borrow: `*&let 0 = 0`
|
||||||
|
|
|
|
||||||
= note: expected type `bool`
|
= note: expected type `bool`
|
||||||
found type `&bool`
|
found type `&bool`
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue