1
Fork 0

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:
bors 2019-10-08 04:35:03 +00:00
commit 1e1f25e31b
24 changed files with 469 additions and 309 deletions

View file

@ -229,52 +229,6 @@ pub struct Cell<T: ?Sized> {
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")]
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> {
/// Returns a raw pointer to the underlying data in this cell.
///

View file

@ -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
/// code type-check, or if you're implementing a trait that requires multiple
/// methods, and you're only planning on using one of them.
/// This allows the your code to type-check, which is useful if you are prototyping or
/// implementing a trait that requires multiple methods which you don't plan of using all of.
///
/// There is no difference between `unimplemented!` and `todo!` apart from the
/// name.
///
/// # 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
///
@ -539,38 +541,53 @@ macro_rules! unreachable {
///
/// ```
/// trait Foo {
/// fn bar(&self);
/// fn bar(&self) -> u8;
/// 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
/// just `bar()` first. In order for our code to compile, we need to implement
/// `baz()`, so we can use `unimplemented!`:
/// We want to implement `Foo` for 'MyStruct', but so far we only know how to
/// implement the `bar()` function. `baz()` and `qux()` will still need to be defined
/// 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 {
/// # fn bar(&self);
/// # fn bar(&self) -> u8;
/// # fn baz(&self);
/// # fn qux(&self) -> Result<u64, ()>;
/// # }
/// struct MyStruct;
///
/// impl Foo for MyStruct {
/// fn bar(&self) {
/// // implementation goes here
/// fn bar(&self) -> u8 {
/// 1 + 1
/// }
///
/// 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!();
/// }
///
/// 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() {
/// let s = MyStruct;
/// s.bar();
///
/// // we aren't even using baz() yet, so this is fine.
/// }
/// ```
#[macro_export]

View file

@ -935,6 +935,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
.filter(|(a, b)| a == b)
.count();
let len = sub1.len() - common_default_params;
let consts_offset = len - sub1.consts().count();
// Only draw `<...>` if there're lifetime/type arguments.
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
let type_arguments = sub1.types().zip(sub2.types());
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;
if ta1 == ta2 {
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);
}
// 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.
// Only draw `<...>` if there're lifetime/type arguments.
if len > 0 {

View file

@ -250,7 +250,9 @@ impl FlagComputation {
ConstValue::Placeholder(_) => {
self.add_flags(TypeFlags::HAS_FREE_REGIONS | TypeFlags::HAS_CT_PLACEHOLDER);
}
_ => {},
ConstValue::Scalar(_) => { }
ConstValue::Slice { data: _, start: _, end: _ } => { }
ConstValue::ByRef { alloc: _, offset: _ } => { }
}
}

View file

@ -911,13 +911,15 @@ impl<'tcx> TypeVisitor<'tcx> for HasEscapingVarsVisitor {
}
fn visit_const(&mut self, ct: &'tcx ty::Const<'tcx>) -> bool {
if let ty::Const {
val: ConstValue::Infer(ty::InferConst::Canonical(debruijn, _)),
..
} = *ct {
debruijn >= self.outer_index
} else {
false
// we don't have a `visit_infer_const` callback, so we have to
// hook in here to catch this case (annoying...), but
// otherwise we do want to remember to visit the rest of the
// const, as it has types/regions embedded in a lot of other
// places.
match ct.val {
ConstValue::Infer(ty::InferConst::Canonical(debruijn, _))
if debruijn >= self.outer_index => true,
_ => ct.super_visit_with(self),
}
}
}

View file

@ -689,7 +689,7 @@ pub trait PrettyPrinter<'tcx>:
if self.tcx().sess.verbose() {
p!(write(
" 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())
));
}
@ -698,7 +698,9 @@ pub trait PrettyPrinter<'tcx>:
},
ty::Array(ty, sz) => {
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
// array length anon const, rustc will (with debug assertions) print the
// constant's path. Which will end up here again.
@ -855,6 +857,11 @@ pub trait PrettyPrinter<'tcx>:
) -> Result<Self::Const, Self::Error> {
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;
if let ty::FnDef(did, substs) = ct.ty.kind {
p!(print_value_path(did, substs));

View file

@ -2203,7 +2203,9 @@ impl<'tcx> TyS<'tcx> {
_ => 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),

View file

@ -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(&param: 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##"
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
E0472, // asm! is unsupported on this target
E0561, // patterns aren't allowed in function pointer types
E0567, // auto traits can not have generic parameters
E0568, // auto traits can not have super traits
E0666, // nested `impl Trait` is illegal

View file

@ -17,10 +17,12 @@ fn evaluate_obligation<'tcx>(
tcx: TyCtxt<'tcx>,
canonical_goal: CanonicalPredicateGoal<'tcx>,
) -> Result<EvaluationResult, OverflowError> {
debug!("evaluate_obligation(canonical_goal={:#?})", canonical_goal);
tcx.infer_ctxt().enter_with_canonical(
DUMMY_SP,
&canonical_goal,
|ref infcx, goal, _canonical_inference_vars| {
debug!("evaluate_obligation: goal={:#?}", goal);
let ParamEnvAnd {
param_env,
value: predicate,

View file

@ -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
// 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) {
(_, &ty::Ref(_, exp, _), &ty::Ref(_, check, _)) => match (&exp.kind, &check.kind) {

View file

@ -87,6 +87,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
}
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 {
ExprKind::DropTemps(expr) => expr,
_ => expr,

View file

@ -3112,8 +3112,10 @@ mod tests {
#[cfg(windows)]
let invalid_options = 87; // ERROR_INVALID_PARAMETER
#[cfg(unix)]
#[cfg(all(unix, not(target_os = "vxworks")))]
let invalid_options = "Invalid argument";
#[cfg(target_os = "vxworks")]
let invalid_options = "invalid argument";
// Test various combinations of creation modes and access modes.
//

View file

@ -11,7 +11,7 @@ mod stmt;
mod generics;
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,
VisibilityKind, Unsafety,
};
@ -56,6 +56,17 @@ crate enum BlockMode {
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.
#[macro_export]
macro_rules! maybe_whole {
@ -1094,26 +1105,18 @@ impl<'a> Parser<'a> {
res
}
fn parse_fn_params(
&mut self,
named_params: bool,
allow_c_variadic: bool,
) -> PResult<'a, Vec<Param>> {
/// Parses the parameter list of a function, including the `(` and `)` delimiters.
fn parse_fn_params(&mut self, mut cfg: ParamCfg) -> PResult<'a, Vec<Param>> {
let sp = self.token.span;
let do_not_enforce_named_params_for_c_variadic = |token: &token::Token| {
match token.kind {
token::DotDotDot => false,
_ => named_params,
}
};
let is_trait_item = cfg.is_self_allowed;
let mut c_variadic = false;
// Parse the arguments, starting out with `self` being possibly allowed...
let (params, _) = self.parse_paren_comma_seq(|p| {
match p.parse_param_general(
false,
false,
allow_c_variadic,
do_not_enforce_named_params_for_c_variadic,
) {
let param = p.parse_param_general(&cfg, is_trait_item);
// ...now that we've parsed the first argument, `self` is no longer allowed.
cfg.is_self_allowed = false;
match param {
Ok(param) => Ok(
if let TyKind::CVarArgs = param.ty.kind {
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 {
self.span_err(
@ -1156,79 +1162,53 @@ impl<'a> Parser<'a> {
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
/// error.
/// This version of parse param doesn't necessarily require identifier names.
fn parse_param_general(
&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> {
fn parse_param_general(&mut self, cfg: &ParamCfg, is_trait_item: bool) -> PResult<'a, Param> {
let lo = self.token.span;
let attrs = self.parse_outer_attributes()?;
// Possibly parse `self`. Recover if we parsed it and it wasn't allowed here.
if let Some(mut param) = self.parse_self_param()? {
param.attrs = attrs.into();
return if is_self_allowed {
return if cfg.is_self_allowed {
Ok(param)
} else {
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() {
debug!("parse_param_general parse_pat (is_name_required:{})", is_name_required);
let pat = self.parse_fn_param_pat()?;
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,
pat,
is_name_required,
is_self_allowed,
cfg.is_self_allowed,
is_trait_item,
) {
err.emit();
return Ok(dummy_arg(ident));
Ok(dummy_arg(ident))
} else {
return Err(err);
}
Err(err)
};
}
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 {
debug!("parse_param_general ident_to_pat");
let parser_snapshot_before_ty = self.clone();
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 &&
self.token != token::CloseDelim(token::Paren) {
// This wasn't actually a type, but a pattern looking like a type,

View file

@ -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::ptr::P;
use crate::ast::{
self, DUMMY_NODE_ID, Ident, Attribute, AttrStyle,
Item, ItemKind, ImplItem, TraitItem, TraitItemKind,
Item, ItemKind, ImplItem, ImplItemKind, TraitItem, TraitItemKind,
UseTree, UseTreeKind, PathSegment,
IsAuto, Constness, IsAsync, Unsafety, Defaultness,
Visibility, VisibilityKind, Mutability, FnDecl, FnHeader, MethodSig, Block,
@ -98,7 +98,7 @@ impl<'a> Parser<'a> {
let lo = self.token.span;
let visibility = self.parse_visibility(false)?;
let vis = self.parse_visibility(false)?;
if self.eat_keyword(kw::Use) {
// USE ITEM
@ -106,15 +106,14 @@ impl<'a> Parser<'a> {
self.expect(&token::Semi)?;
let span = lo.to(self.prev_span);
let item =
self.mk_item(span, Ident::invalid(), item_, visibility, attrs);
let item = self.mk_item(span, Ident::invalid(), item_, vis, attrs);
return Ok(Some(item));
}
if self.eat_keyword(kw::Extern) {
let extern_sp = self.prev_span;
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()?;
@ -128,10 +127,10 @@ impl<'a> Parser<'a> {
constness: respan(fn_span, Constness::NotConst),
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)) {
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();
// STATIC ITEM
let m = self.parse_mutability();
let (ident, item_, extra_attrs) = self.parse_item_const(Some(m))?;
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)));
let info = self.parse_item_const(Some(m))?;
return self.mk_item_with_info(attrs, lo, vis, info);
}
if self.eat_keyword(kw::Const) {
let const_span = self.prev_span;
if [kw::Fn, kw::Unsafe, kw::Extern].iter().any(|k| self.check_keyword(*k)) {
// CONST FUNCTION ITEM
let unsafety = self.parse_unsafety();
if self.check_keyword(kw::Extern) {
@ -160,7 +157,7 @@ impl<'a> Parser<'a> {
);
}
let abi = self.parse_extern_abi()?;
self.bump(); // 'fn'
self.bump(); // `fn`
let header = FnHeader {
unsafety,
@ -168,7 +165,7 @@ impl<'a> Parser<'a> {
constness: respan(const_span, Constness::Const),
abi,
};
return self.parse_item_fn(lo, visibility, attrs, header);
return self.parse_item_fn(lo, vis, attrs, header);
}
// CONST ITEM
@ -184,10 +181,9 @@ impl<'a> Parser<'a> {
)
.emit();
}
let (ident, item_, extra_attrs) = self.parse_item_const(None)?;
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)));
let info = self.parse_item_const(None)?;
return self.mk_item_with_info(attrs, lo, vis, info);
}
// Parses `async unsafe? fn`.
@ -212,40 +208,33 @@ impl<'a> Parser<'a> {
constness: respan(fn_span, Constness::NotConst),
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) &&
self.is_keyword_ahead(1, &[kw::Trait, kw::Auto])
{
// UNSAFE TRAIT ITEM
self.bump(); // `unsafe`
let is_auto = if self.eat_keyword(kw::Trait) {
IsAuto::No
} 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)));
let info = self.parse_item_trait(Unsafety::Unsafe)?;
return self.mk_item_with_info(attrs, lo, vis, info);
}
if self.check_keyword(kw::Impl) ||
self.check_keyword(kw::Unsafe) &&
self.is_keyword_ahead(1, &[kw::Impl]) ||
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
let defaultness = self.parse_defaultness();
let unsafety = self.parse_unsafety();
self.expect_keyword(kw::Impl)?;
let (ident, item_, extra_attrs) = self.parse_item_impl(unsafety, defaultness)?;
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)));
let info = self.parse_item_impl(unsafety, defaultness)?;
return self.mk_item_with_info(attrs, lo, vis, info);
}
if self.check_keyword(kw::Fn) {
// FUNCTION ITEM
self.bump();
@ -256,10 +245,12 @@ impl<'a> Parser<'a> {
constness: respan(fn_span, Constness::NotConst),
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)
&& self.look_ahead(1, |t| *t != token::OpenDelim(token::Brace)) {
&& self.look_ahead(1, |t| *t != token::OpenDelim(token::Brace))
{
// UNSAFE FUNCTION ITEM
self.bump(); // `unsafe`
// `{` 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),
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) {
// MODULE ITEM
let (ident, item_, extra_attrs) = self.parse_item_mod(&attrs[..])?;
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)));
let info = self.parse_item_mod(&attrs[..])?;
return self.mk_item_with_info(attrs, lo, vis, info);
}
if let Some(type_) = self.eat_type() {
let (ident, alias, generics) = type_?;
// TYPE ITEM
@ -290,54 +281,44 @@ impl<'a> Parser<'a> {
AliasKind::OpaqueTy(bounds) => ItemKind::OpaqueTy(bounds, generics),
};
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) {
// ENUM ITEM
let (ident, item_, extra_attrs) = self.parse_item_enum()?;
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)));
let info = self.parse_item_enum()?;
return self.mk_item_with_info(attrs, lo, vis, info);
}
if self.check_keyword(kw::Trait)
|| (self.check_keyword(kw::Auto)
&& 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
let (ident, item_, extra_attrs) = self.parse_item_trait(is_auto, Unsafety::Normal)?;
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)));
let info = self.parse_item_trait(Unsafety::Normal)?;
return self.mk_item_with_info(attrs, lo, vis, info);
}
if self.eat_keyword(kw::Struct) {
// STRUCT ITEM
let (ident, item_, extra_attrs) = self.parse_item_struct()?;
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)));
let info = self.parse_item_struct()?;
return self.mk_item_with_info(attrs, lo, vis, info);
}
if self.is_union_item() {
// UNION ITEM
self.bump();
let (ident, item_, extra_attrs) = self.parse_item_union()?;
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)));
let info = self.parse_item_union()?;
return self.mk_item_with_info(attrs, lo, vis, info);
}
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));
}
// 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 {}`
if visibility.node.is_pub() &&
if vis.node.is_pub() &&
self.check_ident() &&
self.look_ahead(1, |t| *t != token::Not)
{
@ -428,7 +409,20 @@ impl<'a> Parser<'a> {
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 {
@ -727,16 +721,7 @@ impl<'a> Parser<'a> {
};
(name, kind, generics)
} else if self.is_const_item() {
// This parses the grammar:
// 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())
self.parse_impl_const()?
} else {
let (name, inner_attrs, generics, kind) = self.parse_impl_method(&vis, at_end)?;
attrs.extend(inner_attrs);
@ -785,12 +770,25 @@ impl<'a> Parser<'a> {
!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.
fn parse_impl_method(
&mut self,
vis: &Visibility,
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!
if let Some(mac) = self.parse_assoc_macro_invoc("impl", Some(vis), at_end)? {
// 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.
fn parse_method_sig(
&mut self,
is_name_required: impl Copy + Fn(&token::Token) -> bool,
is_name_required: fn(&token::Token) -> bool,
) -> PResult<'a, (Ident, MethodSig, Generics)> {
let header = self.parse_fn_front_matter()?;
let (ident, mut generics) = self.parse_fn_header()?;
let decl = self.parse_fn_decl_with_self(is_name_required)?;
let sig = MethodSig { header, decl };
generics.where_clause = self.parse_where_clause()?;
Ok((ident, sig, generics))
let (ident, decl, generics) = self.parse_fn_sig(ParamCfg {
is_self_allowed: true,
allow_c_variadic: false,
is_name_required,
})?;
Ok((ident, MethodSig { header, decl }, generics))
}
/// 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 })
}
/// Parses `trait Foo { ... }` or `trait Foo = Bar;`.
fn parse_item_trait(&mut self, is_auto: IsAuto, unsafety: Unsafety) -> PResult<'a, ItemInfo> {
/// Parses `auto? trait Foo { ... }` or `trait Foo = Bar;`.
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 mut tps = self.parse_generics()?;
@ -935,30 +942,20 @@ impl<'a> Parser<'a> {
Ok(item)
}
fn parse_trait_item_(&mut self,
at_end: &mut bool,
mut attrs: Vec<Attribute>) -> PResult<'a, TraitItem> {
fn parse_trait_item_(
&mut self,
at_end: &mut bool,
mut attrs: Vec<Attribute>,
) -> PResult<'a, TraitItem> {
let lo = self.token.span;
self.eat_bad_pub();
let (name, kind, generics) = if self.eat_keyword(kw::Type) {
self.parse_trait_item_assoc_ty()?
} else if self.is_const_item() {
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) {
let expr = self.parse_expr()?;
self.expect(&token::Semi)?;
Some(expr)
} else {
self.expect(&token::Semi)?;
None
};
(ident, TraitItemKind::Const(ty, default), Generics::default())
self.parse_trait_item_const()?
} else if let Some(mac) = self.parse_assoc_macro_invoc("trait", None, &mut false)? {
// trait item macro.
(Ident::invalid(), ast::TraitItemKind::Macro(mac), Generics::default())
(Ident::invalid(), TraitItemKind::Macro(mac), Generics::default())
} else {
// This is somewhat dubious; We don't want to allow
// 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.
let (ident, sig, generics) = self.parse_method_sig(|t| t.span.rust_2018())?;
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 {
@ -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.
/// This can either be `;` when there's no body,
/// or e.g. a block when the method is a provided one.
@ -1020,8 +1031,7 @@ impl<'a> Parser<'a> {
/// Parses the following grammar:
///
/// TraitItemAssocTy = Ident ["<"...">"] [":" [GenericBounds]] ["where" ...] ["=" Ty]
fn parse_trait_item_assoc_ty(&mut self)
-> PResult<'a, (Ident, TraitItemKind, Generics)> {
fn parse_trait_item_assoc_ty(&mut self) -> PResult<'a, (Ident, TraitItemKind, Generics)> {
let ident = self.parse_ident()?;
let mut generics = self.parse_generics()?;
@ -1067,21 +1077,13 @@ impl<'a> Parser<'a> {
);
}
if self.eat(&token::BinOp(token::Star)) {
UseTreeKind::Glob
} else {
UseTreeKind::Nested(self.parse_use_tree_list()?)
}
self.parse_use_tree_glob_or_nested()?
} else {
// `use path::*;` or `use path::{...};` or `use path;` or `use path as bar;`
prefix = self.parse_path(PathStyle::Mod)?;
if self.eat(&token::ModSep) {
if self.eat(&token::BinOp(token::Star)) {
UseTreeKind::Glob
} else {
UseTreeKind::Nested(self.parse_use_tree_list()?)
}
self.parse_use_tree_glob_or_nested()?
} else {
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) })
}
/// 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)`.
///
/// ```
@ -1191,38 +1202,34 @@ impl<'a> Parser<'a> {
attrs: Vec<Attribute>,
header: FnHeader,
) -> 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(allow_c_variadic)?;
let (ident, decl, generics) = self.parse_fn_sig(ParamCfg {
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 span = lo.to(self.prev_span);
let kind = ItemKind::Fn(decl, header, generics, body);
let attrs = maybe_append(attrs, Some(inner_attrs));
Ok(Some(self.mk_item(span, ident, kind, vis, attrs)))
self.mk_item_with_info(attrs, lo, vis, (ident, kind, Some(inner_attrs)))
}
/// Parse the "signature", including the identifier, parameters, and generics of a function.
fn parse_fn_sig(
&mut self,
allow_c_variadic: bool,
) -> PResult<'a, (Ident, P<FnDecl>, Generics)> {
let (ident, mut generics) = self.parse_fn_header()?;
let decl = self.parse_fn_decl(allow_c_variadic)?;
fn parse_fn_sig(&mut self, cfg: ParamCfg) -> PResult<'a, (Ident, P<FnDecl>, Generics)> {
let ident = self.parse_ident()?;
let mut generics = self.parse_generics()?;
let decl = self.parse_fn_decl(cfg, true)?;
generics.where_clause = self.parse_where_clause()?;
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.
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 {
inputs: self.parse_fn_params(true, allow_c_variadic)?,
output: self.parse_ret_ty(true)?,
inputs: self.parse_fn_params(cfg)?,
output: self.parse_ret_ty(ret_allow_plus)?,
}))
}
@ -1346,7 +1353,11 @@ impl<'a> Parser<'a> {
extern_sp: Span,
) -> PResult<'a, ForeignItem> {
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);
self.parse_semi_or_incorrect_foreign_fn_body(&ident, extern_sp)?;
Ok(ast::ForeignItem {

View file

@ -4,13 +4,11 @@ use crate::{maybe_whole, maybe_recover_from_interpolated_ty_qpath};
use crate::ptr::P;
use crate::ast::{self, Ty, TyKind, MutTy, BareFnTy, FunctionRetTy, GenericParam, Lifetime, Ident};
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::source_map::Span;
use crate::symbol::{kw};
use rustc_target::spec::abi::Abi;
use errors::{Applicability, pluralise};
/// 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 abi = if self.eat_keyword(kw::Extern) {
self.parse_opt_abi()?.unwrap_or(Abi::C)
} else {
Abi::Rust
};
let abi = self.parse_extern_abi()?;
self.expect_keyword(kw::Fn)?;
let inputs = self.parse_fn_params(false, true)?;
let ret_ty = self.parse_ret_ty(false)?;
let decl = P(FnDecl {
inputs,
output: ret_ty,
});
let cfg = super::ParamCfg {
is_self_allowed: false,
allow_c_variadic: true,
is_name_required: |_| false,
};
let decl = self.parse_fn_decl(cfg, false)?;
Ok(TyKind::BareFn(P(BareFnTy {
abi,
unsafety,

View file

@ -12,8 +12,8 @@ error[E0308]: mismatched types
LL | let _: ConstString<"Hello"> = ConstString::<"World">;
| ^^^^^^^^^^^^^^^^^^^^^^ expected `"Hello"`, found `"World"`
|
= note: expected type `ConstString<>`
found type `ConstString<>`
= note: expected type `ConstString<"Hello">`
found type `ConstString<"World">`
error[E0308]: mismatched types
--> $DIR/slice-const-param-mismatch.rs:11:33
@ -21,8 +21,8 @@ error[E0308]: mismatched types
LL | let _: ConstString<"ℇ㇈↦"> = ConstString::<"ℇ㇈↥">;
| ^^^^^^^^^^^^^^^^^^^^^ expected `"ℇ㇈↦"`, found `"ℇ㇈↥"`
|
= note: expected type `ConstString<>`
found type `ConstString<>`
= note: expected type `ConstString<"ℇ㇈↦">`
found type `ConstString<"ℇ㇈↥">`
error[E0308]: mismatched types
--> $DIR/slice-const-param-mismatch.rs:13:33
@ -30,8 +30,8 @@ error[E0308]: mismatched types
LL | let _: ConstBytes<b"AAA"> = ConstBytes::<b"BBB">;
| ^^^^^^^^^^^^^^^^^^^^ expected `b"AAA"`, found `b"BBB"`
|
= note: expected type `ConstBytes<>`
found type `ConstBytes<>`
= note: expected type `ConstBytes<b"AAA">`
found type `ConstBytes<b"BBB">`
error: aborting due to 3 previous errors

View 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() {}

View 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`.

View file

@ -2,7 +2,10 @@ error[E0308]: mismatched types
--> $DIR/if-no-match-bindings.rs:18:8
|
LL | if b_ref() {}
| ^^^^^^^ expected bool, found &bool
| ^^^^^^^
| |
| expected bool, found &bool
| help: consider dereferencing the borrow: `*b_ref()`
|
= note: expected type `bool`
found type `&bool`
@ -11,7 +14,10 @@ error[E0308]: mismatched types
--> $DIR/if-no-match-bindings.rs:19:8
|
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`
found type `&mut bool`
@ -20,7 +26,10 @@ error[E0308]: mismatched types
--> $DIR/if-no-match-bindings.rs:20:8
|
LL | if &true {}
| ^^^^^ expected bool, found &bool
| ^^^^^
| |
| expected bool, found &bool
| help: consider dereferencing the borrow: `*&true`
|
= note: expected type `bool`
found type `&bool`
@ -29,7 +38,10 @@ error[E0308]: mismatched types
--> $DIR/if-no-match-bindings.rs:21:8
|
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`
found type `&mut bool`
@ -38,7 +50,10 @@ error[E0308]: mismatched types
--> $DIR/if-no-match-bindings.rs:24:11
|
LL | while b_ref() {}
| ^^^^^^^ expected bool, found &bool
| ^^^^^^^
| |
| expected bool, found &bool
| help: consider dereferencing the borrow: `*b_ref()`
|
= note: expected type `bool`
found type `&bool`
@ -47,7 +62,10 @@ error[E0308]: mismatched types
--> $DIR/if-no-match-bindings.rs:25:11
|
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`
found type `&mut bool`
@ -56,7 +74,10 @@ error[E0308]: mismatched types
--> $DIR/if-no-match-bindings.rs:26:11
|
LL | while &true {}
| ^^^^^ expected bool, found &bool
| ^^^^^
| |
| expected bool, found &bool
| help: consider dereferencing the borrow: `*&true`
|
= note: expected type `bool`
found type `&bool`
@ -65,7 +86,10 @@ error[E0308]: mismatched types
--> $DIR/if-no-match-bindings.rs:27:11
|
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`
found type `&mut bool`

View file

@ -18,5 +18,5 @@ LL | m!((bad, pat));
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`.

View file

@ -30,4 +30,5 @@ LL | type A2 = fn(&arg: u8);
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`.

View file

@ -3,6 +3,7 @@ struct S;
impl S {
fn f(*, a: u8) -> u8 {}
//~^ ERROR expected parameter name, found `*`
//~| ERROR mismatched types
}
fn main() {}

View file

@ -4,5 +4,17 @@ error: expected parameter name, found `*`
LL | fn f(*, a: u8) -> u8 {}
| ^ 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`.

View file

@ -517,7 +517,10 @@ error[E0308]: mismatched types
--> $DIR/disallowed-positions.rs:32:8
|
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`
found type `&bool`
@ -702,7 +705,10 @@ error[E0308]: mismatched types
--> $DIR/disallowed-positions.rs:96:11
|
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`
found type `&bool`